From 07bba7582d32f83183b4dc59af0fd69411ab749a Mon Sep 17 00:00:00 2001 From: Sylvain LE GAL Date: Thu, 14 Apr 2022 01:49:21 +0200 Subject: [PATCH] [IMP] Search addons maintainers in other branches. Fix : #122 --- environment.sample | 4 ++ src/oca_github_bot/config.py | 6 +++ src/oca_github_bot/manifest.py | 53 +++++++++++++++++-- .../tasks/mention_maintainer.py | 2 +- src/oca_github_bot/tasks/merge_bot.py | 2 +- tests/test_manifest.py | 1 + 6 files changed, 63 insertions(+), 5 deletions(-) diff --git a/environment.sample b/environment.sample index bfeb8b32..949e5410 100644 --- a/environment.sample +++ b/environment.sample @@ -80,3 +80,7 @@ OCABOT_TWINE_REPOSITORIES="[('https://pypi.org/simple','https://upload.pypi.org/ # Markdown text to be used to call for maintainers when a PR is made to an # addon that has no declared maintainers. #ADOPT_AN_ADDON_MENTION= + +# List of branches the bot will check to verify if user is the maintainer +# of module(s) +MAINTAINER_CHECK_ODOO_RELEASES=8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0 \ No newline at end of file diff --git a/src/oca_github_bot/config.py b/src/oca_github_bot/config.py index 0dbd8728..121afa3d 100644 --- a/src/oca_github_bot/config.py +++ b/src/oca_github_bot/config.py @@ -130,3 +130,9 @@ def func_wrapper(*args, **kwargs): ) ADOPT_AN_ADDON_MENTION = os.environ.get("ADOPT_AN_ADDON_MENTION") + +MAINTAINER_CHECK_ODOO_RELEASES = ( + os.environ.get("MAINTAINER_CHECK_ODOO_RELEASES") + and os.environ.get("MAINTAINER_CHECK_ODOO_RELEASES").split(",") + or [] +) \ No newline at end of file diff --git a/src/oca_github_bot/manifest.py b/src/oca_github_bot/manifest.py index 859be80c..ef209ad3 100644 --- a/src/oca_github_bot/manifest.py +++ b/src/oca_github_bot/manifest.py @@ -2,9 +2,12 @@ # Distributed under the MIT License (http://opensource.org/licenses/MIT). import ast +import logging import os import re +import requests +from . import config from .github import git_get_current_branch, github_user_can_push from .process import check_call, check_output @@ -17,6 +20,8 @@ r"(?P
[\"']version[\"']\s*:\s*[\"'])(?P[\d\.]+)(?P[\"'])"
 )
 
+_logger = logging.getLogger(__name__)
+
 
 class NoManifestFound(Exception):
     pass
@@ -189,7 +194,7 @@ def git_modified_addons(addons_dir, ref):
 
 def git_modified_addon_dirs(addons_dir, ref):
     modified_addons, other_changes = git_modified_addons(addons_dir, ref)
-    return [os.path.join(addons_dir, addon) for addon in modified_addons], other_changes
+    return [os.path.join(addons_dir, addon) for addon in modified_addons], other_changes, modified_addons
 
 
 def get_odoo_series_from_version(version):
@@ -220,11 +225,13 @@ def user_can_push(gh, org, repo, username, addons_dir, target_branch):
     return true if username is declared in the maintainers key
     on the target branch, for all addons modified in the current branch
     compared to the target_branch.
+    If the username is not declared as maintainer on the current branch,
+    check if the user is maintainer in other branches.
     """
     gh_repo = gh.repository(org, repo)
     if github_user_can_push(gh_repo, username):
         return True
-    modified_addon_dirs, other_changes = git_modified_addon_dirs(
+    modified_addon_dirs, other_changes, modified_addons = git_modified_addon_dirs(
         addons_dir, target_branch
     )
     if other_changes or not modified_addon_dirs:
@@ -234,6 +241,46 @@ def user_can_push(gh, org, repo, username, addons_dir, target_branch):
     current_branch = git_get_current_branch(cwd=addons_dir)
     try:
         check_call(["git", "checkout", target_branch], cwd=addons_dir)
-        return is_maintainer(username, modified_addon_dirs)
+        result = is_maintainer(username, modified_addon_dirs)
     finally:
         check_call(["git", "checkout", current_branch], cwd=addons_dir)
+
+    if result:
+        return True
+
+    return is_maintainer_other_branch(
+        gh, org, repo, username, modified_addons, target_branch
+    )
+
+
+def is_maintainer_other_branch(gh, org, repo, username, modified_addons, target_branch):
+    releases_to_check = config.MAINTAINER_CHECK_ODOO_RELEASES
+    if target_branch in releases_to_check:
+        releases_to_check.remove(target_branch)
+    for addon in modified_addons:
+        is_maintainer = False
+        for release in releases_to_check:
+            manifest_file = (
+                float(release) < 10.0 and
+                "__openerp__.py"
+                or "__manifest__.py"
+            )
+            url = (
+                f"https://raw.githubusercontent.com/{org}/{repo}/{release}/"
+                f"{addon}/{manifest_file}"
+            )
+            _logger.debug("Looking for maintainers in %s" % url)
+            r = requests.get(
+                url,
+                allow_redirects=True,
+                headers={'Cache-Control': 'no-cache'}
+            )
+            if r.ok:
+                manifest = ast.literal_eval(r.content.decode('utf-8'))
+                if username in manifest.get("maintainers", []):
+                    is_maintainer = True
+                    break
+
+        if not is_maintainer:
+            return False
+    return True
\ No newline at end of file
diff --git a/src/oca_github_bot/tasks/mention_maintainer.py b/src/oca_github_bot/tasks/mention_maintainer.py
index a7186ad6..4b4649e1 100644
--- a/src/oca_github_bot/tasks/mention_maintainer.py
+++ b/src/oca_github_bot/tasks/mention_maintainer.py
@@ -33,7 +33,7 @@ def mention_maintainer(org, repo, pr, dry_run=False):
                 cwd=clonedir,
             )
             check_call(["git", "checkout", pr_branch], cwd=clonedir)
-            modified_addon_dirs, _ = git_modified_addon_dirs(clonedir, target_branch)
+            modified_addon_dirs, _, _ = git_modified_addon_dirs(clonedir, target_branch)
 
             # Remove not installable addons
             # (case where an addon becomes no more installable).
diff --git a/src/oca_github_bot/tasks/merge_bot.py b/src/oca_github_bot/tasks/merge_bot.py
index 0cbb781c..4d1d2f6d 100644
--- a/src/oca_github_bot/tasks/merge_bot.py
+++ b/src/oca_github_bot/tasks/merge_bot.py
@@ -131,7 +131,7 @@ def _merge_bot_merge_pr(org, repo, merge_bot_branch, cwd, dry_run=False):
     # to the PR.
     check_call(["git", "fetch", "origin", f"refs/pull/{pr}/head:tmp-pr-{pr}"], cwd=cwd)
     check_call(["git", "checkout", f"tmp-pr-{pr}"], cwd=cwd)
-    modified_addon_dirs, _ = git_modified_addon_dirs(cwd, target_branch)
+    modified_addon_dirs, _, _ = git_modified_addon_dirs(cwd, target_branch)
     # Run main branch bot actions before bump version.
     # Do not run the main branch bot if there are no modified addons,
     # because it is dedicated to addons repos.
diff --git a/tests/test_manifest.py b/tests/test_manifest.py
index 78996cd6..313a6eec 100644
--- a/tests/test_manifest.py
+++ b/tests/test_manifest.py
@@ -140,6 +140,7 @@ def test_git_modified_addons(git_clone):
     assert git_modified_addon_dirs(git_clone, "origin/master") == (
         [str(git_clone / "addon")],
         False,
+        ["addon"]
     )
     # add a second addon, and change the first one
     addon2_dir = git_clone / "addon2"