From: Alexander Kanevskiy Date: Tue, 13 Aug 2013 18:44:43 +0000 (+0300) Subject: Alpha version of add_reviewers plugin X-Git-Tag: submit/devel/20190730.075359~8 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=83e27a77bdfeef2252fdd0ebd4d1a3ac20ea4524;p=services%2Fgerrithooks-plugins.git Alpha version of add_reviewers plugin --- diff --git a/plugins/__init__.py b/plugins/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/plugins/add_reviewers.py b/plugins/add_reviewers.py new file mode 100644 index 0000000..0f9a0a6 --- /dev/null +++ b/plugins/add_reviewers.py @@ -0,0 +1,194 @@ +#!/usr/bin/env +# -*- coding: UTF-8 -*- +# vim: sw=4 ts=4 expandtab ai +# +# Copyright (c) 2013 Intel, Inc. +# License: GPLv2 +# Author: Alexander Kanevskiy +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, +# as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. + + +""" +Add reviewers +""" + +import netrc +import urlparse +import types +import re +from gerritrest import GerritREST + +from pprint import pformat + +def to_bool(arg): + """Convert string to bool""" + if isinstance(arg, types.StringTypes): + return bool(arg.lower() in ("true", "yes", "1")) + else: + return bool(arg) + + +def patchset_created(hook = None, config = None, logger = None, params = None, + extra_params = None): + + if not config.has_option("gerrit", "url"): + logger.error("Gerrit URL is not defined in config!") + return 1 + + gerrit_url = config.get("gerrit", "url") + + if not params.change: + logger.warning("Change not defined") + return 1 + if not params.project: + logger.warning("Project not defined") + return 1 + if not params.branch: + logger.warning("Branch not defined") + return 1 + + if config.has_option("gerrit", "username") \ + and config.has_option("gerrit", "password"): + user = config.get("gerrit", "username") + password = config.get("gerrit", "password") + else: + # Fallback to ~/.netrc + try: + user, _, password = \ + netrc.netrc().hosts[urlparse.urlparse(gerrit_url).netloc] + except KeyError, exc: + logger.error("Unable to find credentials in ~/.netrc") + return -1 + + rules = {} + need_project_groups = False + need_files = False + need_owners = False + rules_enabled = False + + for section in config.sections(): + if len(section) < 17 or section[:16] not in \ + ("patchset_created", "patchset-created"): + continue + rule = section[17:] + rules[rule] = dict(config.items(section)) + rules[rule]['enabled'] = to_bool(rules[rule].get('enabled', None)) + if rules[rule]['enabled']: + rules_enabled = True + rule_type = rules[rule].get('type', None) + if rule_type == 'project_group': + need_project_groups = True + elif rule_type == 'change_file': + need_files = True + elif rule_type == 'author': + need_owners = True + else: + logger.warning("Unknown type(%s) in %s", rule_type, section) + + if not rules_enabled: + logger.warning("No rules enabled") + return 0 + + gerrit = GerritREST(gerrit_url, user, password) + + # get change information from gerrit + change_query = "change:%s+project:%s+branch:%s" % \ + (params.change, params.project, params.branch) + + logger.debug("Getting information about change: %s", change_query) + change_info = gerrit.get_changes(query=change_query, all_files=need_files, + all_revisions=True, detailed_accounts=need_owners, detailed_labels=True) + if not change_info: + logger.error("Change not found!") + return 2 + elif len(change_info) > 1: + logger.warning("More than one change like that found! Using first one.") + change_info = change_info[0] + + if need_project_groups: + logger.debug("Getting groups info for project %s", params.project) + project_groups = gerrit.get_groups(project=params.project) + + reviewers = [] + reviewer_groups = [] + for rule in rules: + if not rules[rule]['enabled']: + continue + rule_type = rules[rule].get('type', None) + if rule_type == 'project_group': + if not rules[rule].get('match', None): + logger.warning("No match defined for %s", rule) + continue + group_match = re.compile(rules[rule]['match']) + for group in project_groups: + if group_match.search(group): + logger.debug("[%s] Matched group %s", rule, group) + reviewer_groups.append(group) + elif rule_type == 'change_file': + if not rules[rule].get('match', None): + logger.warning("No match defined for %s", rule) + continue + file_match = re.compile(rules[rule]['match']) + if params.commit and params.commit in change_info['revisions']: + files = change_info['revisions'][params.commit].get('files', {}) + else: + files = change_info['revisions']\ + [change_info['current_revision']].get('files',{}) + matched = False + for change_file in files: + if file_match.search(change_file): + matched = True + logger.debug("[%s] Matched file: %s", rule, change_file) + break + if matched: + for reviewer in re.split('\s*[,;]\s*', + rules[rule].get('reviewer',"")): + reviewers.append(reviewer.strip()) + for group in re.split('\s*[,;]\s*', + rules[rule].get('reviewer_group',"")): + reviewer_groups.append(group.strip()) + elif rule_type == 'author': + if not rules[rule].get('match', None): + logger.warning("No match defined for %s", rule) + continue + owner_match = re.compile(rules[rule]['match'], re.IGNORECASE) + owner_info = [] + owner_email = change_info['owner'].get('email', None) + if owner_email: + owner_info.append(owner_email) + owner_name = change_info['owner'].get('name', None) + if owner_name: + owner_info.append(owner_name) + logger.debug("match: %s Author: %s", rules[rule]['match'], owner_info) + matched = False + for info in owner_info: + if owner_match.search(info): + matched = True + logger.debug("[%s] Matched owner: %s", rule, info) + break + if matched: + for reviewer in re.split('\s*[,;]\s*', + rules[rule].get('reviewer',"")): + reviewers.append(reviewer.strip()) + for group in re.split('\s*[,;]\s*', + rules[rule].get('reviewer_group',"")): + reviewer_groups.append(group.strip()) + + if reviewers: + for reviewer in reviewers: + logger.debug("Adding reviewer %s", reviewer) + if reviewer_groups: + for reviewer_group in reviewer_groups: + logger.debug("Adding reviewer group %s", reviewer_group) + + + +