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"