diff --git a/environment.sample b/environment.sample index ff75553a..93f1a9f2 100644 --- a/environment.sample +++ b/environment.sample @@ -34,6 +34,9 @@ ODOO_PASSWORD= # Number of days before the proposal can be marked as "Approved" #MIN_PR_AGE=5 +# Color of the github label that contains the name of the module +#MODULE_LABEL_COLOR=#ffc + # Coma separated list of task to run # By default all configured tasks are run. # Available tasks: diff --git a/src/oca_github_bot/config.py b/src/oca_github_bot/config.py index d445452a..869208ab 100644 --- a/src/oca_github_bot/config.py +++ b/src/oca_github_bot/config.py @@ -59,7 +59,7 @@ def func_wrapper(*args, **kwargs): # Available tasks: # delete_branch,tag_approved,tag_ready_to_merge,gen_addons_table, # gen_addons_readme,gen_addons_icon,setuptools_odoo,merge_bot,tag_needs_review, -# migration_issue_bot,whool_init,gen_metapackage +# migration_issue_bot,whool_init,gen_metapackage,label_modified_addons BOT_TASKS = os.environ.get("BOT_TASKS", "all").split(",") BOT_TASKS_DISABLED = os.environ.get("BOT_TASKS_DISABLED", "").split(",") @@ -101,6 +101,8 @@ def func_wrapper(*args, **kwargs): APPROVALS_REQUIRED = int(os.environ.get("APPROVALS_REQUIRED", "2")) MIN_PR_AGE = int(os.environ.get("MIN_PR_AGE", "5")) +MODULE_LABEL_COLOR = os.environ.get("MODULE_LABEL_COLOR", "#ffc") + dist_publisher = MultiDistPublisher() SIMPLE_INDEX_ROOT = os.environ.get("SIMPLE_INDEX_ROOT") if SIMPLE_INDEX_ROOT: diff --git a/src/oca_github_bot/tasks/__init__.py b/src/oca_github_bot/tasks/__init__.py index b9d6be7c..29b5a562 100644 --- a/src/oca_github_bot/tasks/__init__.py +++ b/src/oca_github_bot/tasks/__init__.py @@ -3,6 +3,7 @@ from . import ( heartbeat, + label_modified_addons, main_branch_bot, mention_maintainer, migration_issue_bot, diff --git a/src/oca_github_bot/tasks/label_modified_addons.py b/src/oca_github_bot/tasks/label_modified_addons.py new file mode 100644 index 00000000..d9b44760 --- /dev/null +++ b/src/oca_github_bot/tasks/label_modified_addons.py @@ -0,0 +1,56 @@ +# Copyright (c) ACSONE SA/NV 2024 +# Distributed under the MIT License (http://opensource.org/licenses/MIT). + +from .. import github +from ..config import MODULE_LABEL_COLOR, switchable +from ..manifest import git_modified_addons +from ..process import check_call +from ..queue import task +from ..utils import compute_module_label_name +from ..version_branch import is_main_branch_bot_branch + + +def _label_modified_addons(gh, org, repo, pr, dry_run): + gh_repo = gh.repository(org, repo) + gh_pr = gh.pull_request(org, repo, pr) + target_branch = gh_pr.base.ref + pr_branch = f"tmp-pr-{pr}" + with github.temporary_clone(org, repo, target_branch) as clone_dir: + check_call( + ["git", "fetch", "origin", f"pull/{pr}/head:{pr_branch}"], + cwd=clone_dir, + ) + check_call(["git", "checkout", pr_branch], cwd=clone_dir) + modified_addons, _ = git_modified_addons(clone_dir, target_branch) + if not modified_addons: + return + gh_issue = github.gh_call(gh_pr.issue) + + new_labels = set() + for modified_addon in modified_addons: + label_name = compute_module_label_name(modified_addon) + # We create label at repo level, because it is possible to + # to set description in create_label() function + # (and not in issue.add_labels()) + if label_name not in [x.name for x in gh_repo.labels()] and not dry_run: + github.gh_call( + gh_repo.create_label, + name=label_name, + description=f"Module {modified_addon}", + color=MODULE_LABEL_COLOR.replace("#", ""), + ) + new_labels.add(label_name) + + if is_main_branch_bot_branch(target_branch): + new_labels.add(f"series:{target_branch}") + new_labels = new_labels - {label.name for label in gh_issue.labels()} + if new_labels and not dry_run: + for new_label in new_labels: + github.gh_call(gh_issue.add_labels, new_label) + + +@task() +@switchable("label_modified_addons") +def label_modified_addons(org, repo, pr, dry_run=False): + with github.login() as gh: + _label_modified_addons(gh, org, repo, pr, dry_run) diff --git a/src/oca_github_bot/utils.py b/src/oca_github_bot/utils.py index bd76d6d8..fdeaf61e 100644 --- a/src/oca_github_bot/utils.py +++ b/src/oca_github_bot/utils.py @@ -1,6 +1,7 @@ # Copyright (c) ACSONE SA/NV 2021 # Distributed under the MIT License (http://opensource.org/licenses/MIT). +import hashlib import re import shlex import time @@ -8,6 +9,12 @@ from . import config +# Max size allowed by github for label name +_MAX_LABEL_SIZE = 50 +# Size of the hash, added at the end of the label name +# if module name is too long +_HASH_SIZE = 5 + def hide_secrets(s: str) -> str: # TODO do we want to hide other secrets ? @@ -33,3 +40,24 @@ def retry_on_exception( def cmd_to_str(cmd: Sequence[str]) -> str: return shlex.join(str(c) for c in cmd) + + +def compute_module_label_name(module_name: str) -> str: + """To avoid error if label name is too long + we cut big label, and finish by a hash of the module name. + (The full module name will be present in the description). + Short module name exemple : + - module : 'web_responsive' + - label : 'mod:web_responsive' + Long module name exemple : + - module : 'account_invoice_supplierinfo_update_triple_discount' + - label : 'mod:account_invoice_supplierinfo_update_trip bf3f3' + """ + label_name = f"mod:{module_name}" + if len(label_name) > _MAX_LABEL_SIZE: + module_hash = hashlib.sha256(bytes(module_name, "utf-8")).hexdigest() + label_name = ( + f"{label_name[:(_MAX_LABEL_SIZE - (_HASH_SIZE + 1))]}" + f" {module_hash[:_HASH_SIZE]}" + ) + return label_name diff --git a/src/oca_github_bot/version_branch.py b/src/oca_github_bot/version_branch.py index 41f43330..be1da6de 100644 --- a/src/oca_github_bot/version_branch.py +++ b/src/oca_github_bot/version_branch.py @@ -33,7 +33,7 @@ def is_main_branch_bot_branch(branch_name): def is_protected_branch(branch_name): - if branch_name == "master": + if branch_name in ("master", "main"): return True return bool(ODOO_VERSION_RE.match(branch_name)) diff --git a/src/oca_github_bot/webhooks/__init__.py b/src/oca_github_bot/webhooks/__init__.py index 55e90e44..8a2d6e1f 100644 --- a/src/oca_github_bot/webhooks/__init__.py +++ b/src/oca_github_bot/webhooks/__init__.py @@ -5,6 +5,7 @@ on_command, on_pr_close_delete_branch, on_pr_green_label_needs_review, + on_pr_label_modified_addons, on_pr_open_label_new_contributor, on_pr_open_mention_maintainer, on_pr_review, diff --git a/src/oca_github_bot/webhooks/on_pr_label_modified_addons.py b/src/oca_github_bot/webhooks/on_pr_label_modified_addons.py new file mode 100644 index 00000000..59b74ed7 --- /dev/null +++ b/src/oca_github_bot/webhooks/on_pr_label_modified_addons.py @@ -0,0 +1,21 @@ +# Copyright (c) ACSONE SA/NV 2024 +# Distributed under the MIT License (http://opensource.org/licenses/MIT). + +import logging + +from ..router import router +from ..tasks.label_modified_addons import label_modified_addons + +_logger = logging.getLogger(__name__) + + +@router.register("pull_request", action="opened") +@router.register("pull_request", action="reopened") +@router.register("pull_request", action="synchronize") +async def on_pr_label_modified_addons(event, *args, **kwargs): + """ + Whenever a PR is opened, add labels based on modified addons. + """ + org, repo = event.data["repository"]["full_name"].split("/") + pr = event.data["pull_request"]["number"] + label_modified_addons.delay(org, repo, pr) diff --git a/tests/cassettes/test_label_modified_addons.yaml b/tests/cassettes/test_label_modified_addons.yaml new file mode 100644 index 00000000..e864c486 --- /dev/null +++ b/tests/cassettes/test_label_modified_addons.yaml @@ -0,0 +1,190 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/vnd.github.v3.full+json + Accept-Charset: + - utf-8 + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Type: + - application/json + User-Agent: + - github3.py/4.0.1 + authorization: + - DUMMY + method: GET + uri: https://api.github.com/repos/OCA/mis-builder + response: + body: + string: '{"id":105316242,"node_id":"MDEwOlJlcG9zaXRvcnkxMDUzMTYyNDI=","name":"mis-builder","full_name":"OCA/mis-builder","private":false,"owner":{"login":"OCA","id":7600578,"node_id":"MDEyOk9yZ2FuaXphdGlvbjc2MDA1Nzg=","avatar_url":"https://avatars.githubusercontent.com/u/7600578?v=4","gravatar_id":"","url":"https://api.github.com/users/OCA","html_url":"https://github.com/OCA","followers_url":"https://api.github.com/users/OCA/followers","following_url":"https://api.github.com/users/OCA/following{/other_user}","gists_url":"https://api.github.com/users/OCA/gists{/gist_id}","starred_url":"https://api.github.com/users/OCA/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/OCA/subscriptions","organizations_url":"https://api.github.com/users/OCA/orgs","repos_url":"https://api.github.com/users/OCA/repos","events_url":"https://api.github.com/users/OCA/events{/privacy}","received_events_url":"https://api.github.com/users/OCA/received_events","type":"Organization","user_view_type":"public","site_admin":false},"html_url":"https://github.com/OCA/mis-builder","description":"Management + Information System reports for Odoo: easily build super fast, beautiful, custom + reports such as P&L, Balance Sheets and more.","fork":false,"url":"https://api.github.com/repos/OCA/mis-builder","forks_url":"https://api.github.com/repos/OCA/mis-builder/forks","keys_url":"https://api.github.com/repos/OCA/mis-builder/keys{/key_id}","collaborators_url":"https://api.github.com/repos/OCA/mis-builder/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/OCA/mis-builder/teams","hooks_url":"https://api.github.com/repos/OCA/mis-builder/hooks","issue_events_url":"https://api.github.com/repos/OCA/mis-builder/issues/events{/number}","events_url":"https://api.github.com/repos/OCA/mis-builder/events","assignees_url":"https://api.github.com/repos/OCA/mis-builder/assignees{/user}","branches_url":"https://api.github.com/repos/OCA/mis-builder/branches{/branch}","tags_url":"https://api.github.com/repos/OCA/mis-builder/tags","blobs_url":"https://api.github.com/repos/OCA/mis-builder/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/OCA/mis-builder/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/OCA/mis-builder/git/refs{/sha}","trees_url":"https://api.github.com/repos/OCA/mis-builder/git/trees{/sha}","statuses_url":"https://api.github.com/repos/OCA/mis-builder/statuses/{sha}","languages_url":"https://api.github.com/repos/OCA/mis-builder/languages","stargazers_url":"https://api.github.com/repos/OCA/mis-builder/stargazers","contributors_url":"https://api.github.com/repos/OCA/mis-builder/contributors","subscribers_url":"https://api.github.com/repos/OCA/mis-builder/subscribers","subscription_url":"https://api.github.com/repos/OCA/mis-builder/subscription","commits_url":"https://api.github.com/repos/OCA/mis-builder/commits{/sha}","git_commits_url":"https://api.github.com/repos/OCA/mis-builder/git/commits{/sha}","comments_url":"https://api.github.com/repos/OCA/mis-builder/comments{/number}","issue_comment_url":"https://api.github.com/repos/OCA/mis-builder/issues/comments{/number}","contents_url":"https://api.github.com/repos/OCA/mis-builder/contents/{+path}","compare_url":"https://api.github.com/repos/OCA/mis-builder/compare/{base}...{head}","merges_url":"https://api.github.com/repos/OCA/mis-builder/merges","archive_url":"https://api.github.com/repos/OCA/mis-builder/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/OCA/mis-builder/downloads","issues_url":"https://api.github.com/repos/OCA/mis-builder/issues{/number}","pulls_url":"https://api.github.com/repos/OCA/mis-builder/pulls{/number}","milestones_url":"https://api.github.com/repos/OCA/mis-builder/milestones{/number}","notifications_url":"https://api.github.com/repos/OCA/mis-builder/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/OCA/mis-builder/labels{/name}","releases_url":"https://api.github.com/repos/OCA/mis-builder/releases{/id}","deployments_url":"https://api.github.com/repos/OCA/mis-builder/deployments","created_at":"2017-09-29T20:53:23Z","updated_at":"2026-03-30T22:36:43Z","pushed_at":"2026-03-17T11:45:29Z","git_url":"git://github.com/OCA/mis-builder.git","ssh_url":"git@github.com:OCA/mis-builder.git","clone_url":"https://github.com/OCA/mis-builder.git","svn_url":"https://github.com/OCA/mis-builder","homepage":"","size":10363,"stargazers_count":175,"watchers_count":175,"language":"Python","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"has_discussions":true,"forks_count":364,"mirror_url":null,"archived":false,"disabled":false,"open_issues_count":68,"license":{"key":"agpl-3.0","name":"GNU + Affero General Public License v3.0","spdx_id":"AGPL-3.0","url":"https://api.github.com/licenses/agpl-3.0","node_id":"MDc6TGljZW5zZTE="},"allow_forking":true,"is_template":false,"web_commit_signoff_required":false,"has_pull_requests":true,"pull_request_creation_policy":"all","topics":["erp","hacktoberfest","odoo"],"visibility":"public","forks":364,"open_issues":68,"watchers":175,"default_branch":"18.0","permissions":{"admin":true,"maintain":true,"push":true,"triage":true,"pull":true},"temp_clone_token":"","allow_squash_merge":true,"allow_merge_commit":true,"allow_rebase_merge":true,"allow_auto_merge":true,"delete_branch_on_merge":false,"allow_update_branch":false,"use_squash_pr_title_as_default":false,"squash_merge_commit_message":"COMMIT_MESSAGES","squash_merge_commit_title":"COMMIT_OR_PR_TITLE","merge_commit_message":"PR_TITLE","merge_commit_title":"MERGE_MESSAGE","custom_properties":{},"organization":{"login":"OCA","id":7600578,"node_id":"MDEyOk9yZ2FuaXphdGlvbjc2MDA1Nzg=","avatar_url":"https://avatars.githubusercontent.com/u/7600578?v=4","gravatar_id":"","url":"https://api.github.com/users/OCA","html_url":"https://github.com/OCA","followers_url":"https://api.github.com/users/OCA/followers","following_url":"https://api.github.com/users/OCA/following{/other_user}","gists_url":"https://api.github.com/users/OCA/gists{/gist_id}","starred_url":"https://api.github.com/users/OCA/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/OCA/subscriptions","organizations_url":"https://api.github.com/users/OCA/orgs","repos_url":"https://api.github.com/users/OCA/repos","events_url":"https://api.github.com/users/OCA/events{/privacy}","received_events_url":"https://api.github.com/users/OCA/received_events","type":"Organization","user_view_type":"public","site_admin":false},"security_and_analysis":{"secret_scanning":{"status":"disabled"},"secret_scanning_push_protection":{"status":"disabled"},"dependabot_security_updates":{"status":"enabled"},"secret_scanning_non_provider_patterns":{"status":"disabled"},"secret_scanning_validity_checks":{"status":"disabled"}},"network_count":364,"subscribers_count":42}' + headers: + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, + X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, + X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, + X-GitHub-Request-Id, Deprecation, Sunset + Cache-Control: + - private, max-age=60, s-maxage=60 + Content-Encoding: + - gzip + Content-Security-Policy: + - default-src 'none' + Content-Type: + - application/json; charset=utf-8 + Date: + - Thu, 02 Apr 2026 12:10:40 GMT + ETag: + - W/"43d0a3537052654c1b85c9d96dfcc39c2e2caf8fdb26159254c230c32c4788d9" + Last-Modified: + - Mon, 30 Mar 2026 22:36:43 GMT + Referrer-Policy: + - origin-when-cross-origin, strict-origin-when-cross-origin + Server: + - github.com + Strict-Transport-Security: + - max-age=31536000; includeSubdomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With + X-Accepted-OAuth-Scopes: + - repo + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - deny + X-GitHub-Media-Type: + - github.v3; param=full; format=json + X-GitHub-Request-Id: + - BCC6:5C9C2:46AC3C3:3E8E2AE:69CE5CC0 + X-OAuth-Scopes: + - gist, read:org, repo + X-RateLimit-Limit: + - '5000' + X-RateLimit-Remaining: + - '4989' + X-RateLimit-Reset: + - '1775131848' + X-RateLimit-Resource: + - core + X-RateLimit-Used: + - '11' + X-XSS-Protection: + - '0' + x-github-api-version-selected: + - '2022-11-28' + x-oauth-client-id: + - 178c6fc778ccc68e1d6a + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/vnd.github.v3.full+json + Accept-Charset: + - utf-8 + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Type: + - application/json + User-Agent: + - github3.py/4.0.1 + authorization: + - DUMMY + method: GET + uri: https://api.github.com/repos/OCA/mis-builder/pulls/610 + response: + body: + string: "{\"url\":\"https://api.github.com/repos/OCA/mis-builder/pulls/610\",\"id\":1892283352,\"node_id\":\"PR_kwDOBkb_ks5wyfPY\",\"html_url\":\"https://github.com/OCA/mis-builder/pull/610\",\"diff_url\":\"https://github.com/OCA/mis-builder/pull/610.diff\",\"patch_url\":\"https://github.com/OCA/mis-builder/pull/610.patch\",\"issue_url\":\"https://api.github.com/repos/OCA/mis-builder/issues/610\",\"number\":610,\"state\":\"closed\",\"locked\":false,\"title\":\"[15.0][IMP] + add: css sticky table header added for mis-builder-widget\",\"user\":{\"login\":\"hitrosol\",\"id\":5949936,\"node_id\":\"MDQ6VXNlcjU5NDk5MzY=\",\"avatar_url\":\"https://avatars.githubusercontent.com/u/5949936?v=4\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/hitrosol\",\"html_url\":\"https://github.com/hitrosol\",\"followers_url\":\"https://api.github.com/users/hitrosol/followers\",\"following_url\":\"https://api.github.com/users/hitrosol/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/hitrosol/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/hitrosol/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/hitrosol/subscriptions\",\"organizations_url\":\"https://api.github.com/users/hitrosol/orgs\",\"repos_url\":\"https://api.github.com/users/hitrosol/repos\",\"events_url\":\"https://api.github.com/users/hitrosol/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/hitrosol/received_events\",\"type\":\"User\",\"user_view_type\":\"public\",\"site_admin\":false},\"body\":\"i + forward the improvement in v14 from https://github.com/OCA/mis-builder/pull/588\\r\\n\",\"created_at\":\"2024-05-28T16:40:39Z\",\"updated_at\":\"2025-02-28T14:15:38Z\",\"closed_at\":\"2024-11-10T17:19:56Z\",\"merged_at\":\"2024-11-10T17:19:56Z\",\"merge_commit_sha\":\"7bf91bb8abbc1452e841a017dedd39c68499a12b\",\"assignees\":[],\"requested_reviewers\":[],\"requested_teams\":[],\"labels\":[{\"id\":1407506376,\"node_id\":\"MDU6TGFiZWwxNDA3NTA2Mzc2\",\"url\":\"https://api.github.com/repos/OCA/mis-builder/labels/merged%20%F0%9F%8E%89\",\"name\":\"merged + \U0001F389\",\"color\":\"ededed\",\"default\":false,\"description\":\"\"},{\"id\":7236411066,\"node_id\":\"LA_kwDOBkb_ks8AAAABr1Leug\",\"url\":\"https://api.github.com/repos/OCA/mis-builder/labels/mod:mis_builder\",\"name\":\"mod:mis_builder\",\"color\":\"ededed\",\"default\":false,\"description\":\"\"},{\"id\":7236411148,\"node_id\":\"LA_kwDOBkb_ks8AAAABr1LfDA\",\"url\":\"https://api.github.com/repos/OCA/mis-builder/labels/series:15.0\",\"name\":\"series:15.0\",\"color\":\"ededed\",\"default\":false,\"description\":null}],\"milestone\":null,\"draft\":false,\"commits_url\":\"https://api.github.com/repos/OCA/mis-builder/pulls/610/commits\",\"review_comments_url\":\"https://api.github.com/repos/OCA/mis-builder/pulls/610/comments\",\"review_comment_url\":\"https://api.github.com/repos/OCA/mis-builder/pulls/comments{/number}\",\"comments_url\":\"https://api.github.com/repos/OCA/mis-builder/issues/610/comments\",\"statuses_url\":\"https://api.github.com/repos/OCA/mis-builder/statuses/d18c5d4d7e64a22c777cfe9a63cd00dae730c522\",\"head\":{\"label\":\"hitrosol:15.0-imp-mis_builder\",\"ref\":\"15.0-imp-mis_builder\",\"sha\":\"d18c5d4d7e64a22c777cfe9a63cd00dae730c522\",\"user\":{\"login\":\"hitrosol\",\"id\":5949936,\"node_id\":\"MDQ6VXNlcjU5NDk5MzY=\",\"avatar_url\":\"https://avatars.githubusercontent.com/u/5949936?v=4\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/hitrosol\",\"html_url\":\"https://github.com/hitrosol\",\"followers_url\":\"https://api.github.com/users/hitrosol/followers\",\"following_url\":\"https://api.github.com/users/hitrosol/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/hitrosol/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/hitrosol/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/hitrosol/subscriptions\",\"organizations_url\":\"https://api.github.com/users/hitrosol/orgs\",\"repos_url\":\"https://api.github.com/users/hitrosol/repos\",\"events_url\":\"https://api.github.com/users/hitrosol/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/hitrosol/received_events\",\"type\":\"User\",\"user_view_type\":\"public\",\"site_admin\":false},\"repo\":{\"id\":807198047,\"node_id\":\"R_kgDOMBzdXw\",\"name\":\"mis-builder\",\"full_name\":\"hitrosol/mis-builder\",\"private\":false,\"owner\":{\"login\":\"hitrosol\",\"id\":5949936,\"node_id\":\"MDQ6VXNlcjU5NDk5MzY=\",\"avatar_url\":\"https://avatars.githubusercontent.com/u/5949936?v=4\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/hitrosol\",\"html_url\":\"https://github.com/hitrosol\",\"followers_url\":\"https://api.github.com/users/hitrosol/followers\",\"following_url\":\"https://api.github.com/users/hitrosol/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/hitrosol/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/hitrosol/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/hitrosol/subscriptions\",\"organizations_url\":\"https://api.github.com/users/hitrosol/orgs\",\"repos_url\":\"https://api.github.com/users/hitrosol/repos\",\"events_url\":\"https://api.github.com/users/hitrosol/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/hitrosol/received_events\",\"type\":\"User\",\"user_view_type\":\"public\",\"site_admin\":false},\"html_url\":\"https://github.com/hitrosol/mis-builder\",\"description\":\"Management + Information System reports for Odoo: easily build super fast, beautiful, custom + reports such as P&L, Balance Sheets and more.\",\"fork\":true,\"url\":\"https://api.github.com/repos/hitrosol/mis-builder\",\"forks_url\":\"https://api.github.com/repos/hitrosol/mis-builder/forks\",\"keys_url\":\"https://api.github.com/repos/hitrosol/mis-builder/keys{/key_id}\",\"collaborators_url\":\"https://api.github.com/repos/hitrosol/mis-builder/collaborators{/collaborator}\",\"teams_url\":\"https://api.github.com/repos/hitrosol/mis-builder/teams\",\"hooks_url\":\"https://api.github.com/repos/hitrosol/mis-builder/hooks\",\"issue_events_url\":\"https://api.github.com/repos/hitrosol/mis-builder/issues/events{/number}\",\"events_url\":\"https://api.github.com/repos/hitrosol/mis-builder/events\",\"assignees_url\":\"https://api.github.com/repos/hitrosol/mis-builder/assignees{/user}\",\"branches_url\":\"https://api.github.com/repos/hitrosol/mis-builder/branches{/branch}\",\"tags_url\":\"https://api.github.com/repos/hitrosol/mis-builder/tags\",\"blobs_url\":\"https://api.github.com/repos/hitrosol/mis-builder/git/blobs{/sha}\",\"git_tags_url\":\"https://api.github.com/repos/hitrosol/mis-builder/git/tags{/sha}\",\"git_refs_url\":\"https://api.github.com/repos/hitrosol/mis-builder/git/refs{/sha}\",\"trees_url\":\"https://api.github.com/repos/hitrosol/mis-builder/git/trees{/sha}\",\"statuses_url\":\"https://api.github.com/repos/hitrosol/mis-builder/statuses/{sha}\",\"languages_url\":\"https://api.github.com/repos/hitrosol/mis-builder/languages\",\"stargazers_url\":\"https://api.github.com/repos/hitrosol/mis-builder/stargazers\",\"contributors_url\":\"https://api.github.com/repos/hitrosol/mis-builder/contributors\",\"subscribers_url\":\"https://api.github.com/repos/hitrosol/mis-builder/subscribers\",\"subscription_url\":\"https://api.github.com/repos/hitrosol/mis-builder/subscription\",\"commits_url\":\"https://api.github.com/repos/hitrosol/mis-builder/commits{/sha}\",\"git_commits_url\":\"https://api.github.com/repos/hitrosol/mis-builder/git/commits{/sha}\",\"comments_url\":\"https://api.github.com/repos/hitrosol/mis-builder/comments{/number}\",\"issue_comment_url\":\"https://api.github.com/repos/hitrosol/mis-builder/issues/comments{/number}\",\"contents_url\":\"https://api.github.com/repos/hitrosol/mis-builder/contents/{+path}\",\"compare_url\":\"https://api.github.com/repos/hitrosol/mis-builder/compare/{base}...{head}\",\"merges_url\":\"https://api.github.com/repos/hitrosol/mis-builder/merges\",\"archive_url\":\"https://api.github.com/repos/hitrosol/mis-builder/{archive_format}{/ref}\",\"downloads_url\":\"https://api.github.com/repos/hitrosol/mis-builder/downloads\",\"issues_url\":\"https://api.github.com/repos/hitrosol/mis-builder/issues{/number}\",\"pulls_url\":\"https://api.github.com/repos/hitrosol/mis-builder/pulls{/number}\",\"milestones_url\":\"https://api.github.com/repos/hitrosol/mis-builder/milestones{/number}\",\"notifications_url\":\"https://api.github.com/repos/hitrosol/mis-builder/notifications{?since,all,participating}\",\"labels_url\":\"https://api.github.com/repos/hitrosol/mis-builder/labels{/name}\",\"releases_url\":\"https://api.github.com/repos/hitrosol/mis-builder/releases{/id}\",\"deployments_url\":\"https://api.github.com/repos/hitrosol/mis-builder/deployments\",\"created_at\":\"2024-05-28T16:37:08Z\",\"updated_at\":\"2024-05-28T16:37:08Z\",\"pushed_at\":\"2024-05-28T16:38:09Z\",\"git_url\":\"git://github.com/hitrosol/mis-builder.git\",\"ssh_url\":\"git@github.com:hitrosol/mis-builder.git\",\"clone_url\":\"https://github.com/hitrosol/mis-builder.git\",\"svn_url\":\"https://github.com/hitrosol/mis-builder\",\"homepage\":\"\",\"size\":8072,\"stargazers_count\":0,\"watchers_count\":0,\"language\":null,\"has_issues\":false,\"has_projects\":true,\"has_downloads\":true,\"has_wiki\":true,\"has_pages\":false,\"has_discussions\":false,\"forks_count\":0,\"mirror_url\":null,\"archived\":false,\"disabled\":false,\"open_issues_count\":0,\"license\":{\"key\":\"agpl-3.0\",\"name\":\"GNU + Affero General Public License v3.0\",\"spdx_id\":\"AGPL-3.0\",\"url\":\"https://api.github.com/licenses/agpl-3.0\",\"node_id\":\"MDc6TGljZW5zZTE=\"},\"allow_forking\":true,\"is_template\":false,\"web_commit_signoff_required\":false,\"has_pull_requests\":true,\"pull_request_creation_policy\":\"all\",\"topics\":[],\"visibility\":\"public\",\"forks\":0,\"open_issues\":0,\"watchers\":0,\"default_branch\":\"16.0\"}},\"base\":{\"label\":\"OCA:15.0\",\"ref\":\"15.0\",\"sha\":\"964efcd53ecc5709f3f7478ccc7f96037db7abf4\",\"user\":{\"login\":\"OCA\",\"id\":7600578,\"node_id\":\"MDEyOk9yZ2FuaXphdGlvbjc2MDA1Nzg=\",\"avatar_url\":\"https://avatars.githubusercontent.com/u/7600578?v=4\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/OCA\",\"html_url\":\"https://github.com/OCA\",\"followers_url\":\"https://api.github.com/users/OCA/followers\",\"following_url\":\"https://api.github.com/users/OCA/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/OCA/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/OCA/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/OCA/subscriptions\",\"organizations_url\":\"https://api.github.com/users/OCA/orgs\",\"repos_url\":\"https://api.github.com/users/OCA/repos\",\"events_url\":\"https://api.github.com/users/OCA/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/OCA/received_events\",\"type\":\"Organization\",\"user_view_type\":\"public\",\"site_admin\":false},\"repo\":{\"id\":105316242,\"node_id\":\"MDEwOlJlcG9zaXRvcnkxMDUzMTYyNDI=\",\"name\":\"mis-builder\",\"full_name\":\"OCA/mis-builder\",\"private\":false,\"owner\":{\"login\":\"OCA\",\"id\":7600578,\"node_id\":\"MDEyOk9yZ2FuaXphdGlvbjc2MDA1Nzg=\",\"avatar_url\":\"https://avatars.githubusercontent.com/u/7600578?v=4\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/OCA\",\"html_url\":\"https://github.com/OCA\",\"followers_url\":\"https://api.github.com/users/OCA/followers\",\"following_url\":\"https://api.github.com/users/OCA/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/OCA/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/OCA/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/OCA/subscriptions\",\"organizations_url\":\"https://api.github.com/users/OCA/orgs\",\"repos_url\":\"https://api.github.com/users/OCA/repos\",\"events_url\":\"https://api.github.com/users/OCA/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/OCA/received_events\",\"type\":\"Organization\",\"user_view_type\":\"public\",\"site_admin\":false},\"html_url\":\"https://github.com/OCA/mis-builder\",\"description\":\"Management + Information System reports for Odoo: easily build super fast, beautiful, custom + reports such as P&L, Balance Sheets and more.\",\"fork\":false,\"url\":\"https://api.github.com/repos/OCA/mis-builder\",\"forks_url\":\"https://api.github.com/repos/OCA/mis-builder/forks\",\"keys_url\":\"https://api.github.com/repos/OCA/mis-builder/keys{/key_id}\",\"collaborators_url\":\"https://api.github.com/repos/OCA/mis-builder/collaborators{/collaborator}\",\"teams_url\":\"https://api.github.com/repos/OCA/mis-builder/teams\",\"hooks_url\":\"https://api.github.com/repos/OCA/mis-builder/hooks\",\"issue_events_url\":\"https://api.github.com/repos/OCA/mis-builder/issues/events{/number}\",\"events_url\":\"https://api.github.com/repos/OCA/mis-builder/events\",\"assignees_url\":\"https://api.github.com/repos/OCA/mis-builder/assignees{/user}\",\"branches_url\":\"https://api.github.com/repos/OCA/mis-builder/branches{/branch}\",\"tags_url\":\"https://api.github.com/repos/OCA/mis-builder/tags\",\"blobs_url\":\"https://api.github.com/repos/OCA/mis-builder/git/blobs{/sha}\",\"git_tags_url\":\"https://api.github.com/repos/OCA/mis-builder/git/tags{/sha}\",\"git_refs_url\":\"https://api.github.com/repos/OCA/mis-builder/git/refs{/sha}\",\"trees_url\":\"https://api.github.com/repos/OCA/mis-builder/git/trees{/sha}\",\"statuses_url\":\"https://api.github.com/repos/OCA/mis-builder/statuses/{sha}\",\"languages_url\":\"https://api.github.com/repos/OCA/mis-builder/languages\",\"stargazers_url\":\"https://api.github.com/repos/OCA/mis-builder/stargazers\",\"contributors_url\":\"https://api.github.com/repos/OCA/mis-builder/contributors\",\"subscribers_url\":\"https://api.github.com/repos/OCA/mis-builder/subscribers\",\"subscription_url\":\"https://api.github.com/repos/OCA/mis-builder/subscription\",\"commits_url\":\"https://api.github.com/repos/OCA/mis-builder/commits{/sha}\",\"git_commits_url\":\"https://api.github.com/repos/OCA/mis-builder/git/commits{/sha}\",\"comments_url\":\"https://api.github.com/repos/OCA/mis-builder/comments{/number}\",\"issue_comment_url\":\"https://api.github.com/repos/OCA/mis-builder/issues/comments{/number}\",\"contents_url\":\"https://api.github.com/repos/OCA/mis-builder/contents/{+path}\",\"compare_url\":\"https://api.github.com/repos/OCA/mis-builder/compare/{base}...{head}\",\"merges_url\":\"https://api.github.com/repos/OCA/mis-builder/merges\",\"archive_url\":\"https://api.github.com/repos/OCA/mis-builder/{archive_format}{/ref}\",\"downloads_url\":\"https://api.github.com/repos/OCA/mis-builder/downloads\",\"issues_url\":\"https://api.github.com/repos/OCA/mis-builder/issues{/number}\",\"pulls_url\":\"https://api.github.com/repos/OCA/mis-builder/pulls{/number}\",\"milestones_url\":\"https://api.github.com/repos/OCA/mis-builder/milestones{/number}\",\"notifications_url\":\"https://api.github.com/repos/OCA/mis-builder/notifications{?since,all,participating}\",\"labels_url\":\"https://api.github.com/repos/OCA/mis-builder/labels{/name}\",\"releases_url\":\"https://api.github.com/repos/OCA/mis-builder/releases{/id}\",\"deployments_url\":\"https://api.github.com/repos/OCA/mis-builder/deployments\",\"created_at\":\"2017-09-29T20:53:23Z\",\"updated_at\":\"2026-03-30T22:36:43Z\",\"pushed_at\":\"2026-03-17T11:45:29Z\",\"git_url\":\"git://github.com/OCA/mis-builder.git\",\"ssh_url\":\"git@github.com:OCA/mis-builder.git\",\"clone_url\":\"https://github.com/OCA/mis-builder.git\",\"svn_url\":\"https://github.com/OCA/mis-builder\",\"homepage\":\"\",\"size\":10363,\"stargazers_count\":175,\"watchers_count\":175,\"language\":\"Python\",\"has_issues\":true,\"has_projects\":true,\"has_downloads\":true,\"has_wiki\":true,\"has_pages\":false,\"has_discussions\":true,\"forks_count\":364,\"mirror_url\":null,\"archived\":false,\"disabled\":false,\"open_issues_count\":68,\"license\":{\"key\":\"agpl-3.0\",\"name\":\"GNU + Affero General Public License v3.0\",\"spdx_id\":\"AGPL-3.0\",\"url\":\"https://api.github.com/licenses/agpl-3.0\",\"node_id\":\"MDc6TGljZW5zZTE=\"},\"allow_forking\":true,\"is_template\":false,\"web_commit_signoff_required\":false,\"has_pull_requests\":true,\"pull_request_creation_policy\":\"all\",\"topics\":[\"erp\",\"hacktoberfest\",\"odoo\"],\"visibility\":\"public\",\"forks\":364,\"open_issues\":68,\"watchers\":175,\"default_branch\":\"18.0\"}},\"_links\":{\"self\":{\"href\":\"https://api.github.com/repos/OCA/mis-builder/pulls/610\"},\"html\":{\"href\":\"https://github.com/OCA/mis-builder/pull/610\"},\"issue\":{\"href\":\"https://api.github.com/repos/OCA/mis-builder/issues/610\"},\"comments\":{\"href\":\"https://api.github.com/repos/OCA/mis-builder/issues/610/comments\"},\"review_comments\":{\"href\":\"https://api.github.com/repos/OCA/mis-builder/pulls/610/comments\"},\"review_comment\":{\"href\":\"https://api.github.com/repos/OCA/mis-builder/pulls/comments{/number}\"},\"commits\":{\"href\":\"https://api.github.com/repos/OCA/mis-builder/pulls/610/commits\"},\"statuses\":{\"href\":\"https://api.github.com/repos/OCA/mis-builder/statuses/d18c5d4d7e64a22c777cfe9a63cd00dae730c522\"}},\"author_association\":\"FIRST_TIME_CONTRIBUTOR\",\"auto_merge\":null,\"body_html\":\"
i forward the improvement in v14 from #588
\",\"body_text\":\"i + forward the improvement in v14 from #588\",\"assignee\":null,\"active_lock_reason\":null,\"merged\":true,\"mergeable\":null,\"rebaseable\":null,\"mergeable_state\":\"unknown\",\"merged_by\":{\"login\":\"OCA-git-bot\",\"id\":8723280,\"node_id\":\"MDQ6VXNlcjg3MjMyODA=\",\"avatar_url\":\"https://avatars.githubusercontent.com/u/8723280?v=4\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/OCA-git-bot\",\"html_url\":\"https://github.com/OCA-git-bot\",\"followers_url\":\"https://api.github.com/users/OCA-git-bot/followers\",\"following_url\":\"https://api.github.com/users/OCA-git-bot/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/OCA-git-bot/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/OCA-git-bot/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/OCA-git-bot/subscriptions\",\"organizations_url\":\"https://api.github.com/users/OCA-git-bot/orgs\",\"repos_url\":\"https://api.github.com/users/OCA-git-bot/repos\",\"events_url\":\"https://api.github.com/users/OCA-git-bot/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/OCA-git-bot/received_events\",\"type\":\"User\",\"user_view_type\":\"public\",\"site_admin\":false},\"comments\":4,\"review_comments\":0,\"maintainer_can_modify\":false,\"commits\":1,\"additions\":5,\"deletions\":0,\"changed_files\":1}" + headers: + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, + X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, + X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, + X-GitHub-Request-Id, Deprecation, Sunset + Cache-Control: + - private, max-age=60, s-maxage=60 + Content-Encoding: + - gzip + Content-Security-Policy: + - default-src 'none' + Content-Type: + - application/json; charset=utf-8 + Date: + - Thu, 02 Apr 2026 12:10:41 GMT + ETag: + - W/"4041e6059278ad3ce669dfc3941b849c60be73c43a1cd4b1e3e1328d66180ddc" + Last-Modified: + - Mon, 16 Mar 2026 02:09:21 GMT + Referrer-Policy: + - origin-when-cross-origin, strict-origin-when-cross-origin + Server: + - github.com + Strict-Transport-Security: + - max-age=31536000; includeSubdomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With + X-Accepted-OAuth-Scopes: + - repo + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - deny + X-GitHub-Media-Type: + - github.v3; param=full; format=json + X-GitHub-Request-Id: + - BCD0:26F600:48134F9:3FEA826:69CE5CC1 + X-OAuth-Scopes: + - gist, read:org, repo + X-RateLimit-Limit: + - '5000' + X-RateLimit-Remaining: + - '4988' + X-RateLimit-Reset: + - '1775131848' + X-RateLimit-Resource: + - core + X-RateLimit-Used: + - '12' + X-XSS-Protection: + - '0' + x-github-api-version-selected: + - '2022-11-28' + x-oauth-client-id: + - 178c6fc778ccc68e1d6a + status: + code: 200 + message: OK +version: 1 diff --git a/tests/test_label_modified_addons.py b/tests/test_label_modified_addons.py new file mode 100644 index 00000000..d5763c7b --- /dev/null +++ b/tests/test_label_modified_addons.py @@ -0,0 +1,10 @@ +# Copyright ACSONE SA/NV 2024 +# Distributed under the MIT License (http://opensource.org/licenses/MIT). +import pytest + +from oca_github_bot.tasks.label_modified_addons import _label_modified_addons + + +@pytest.mark.vcr() +def test_label_modified_addons(gh): + _label_modified_addons(gh, "OCA", "mis-builder", "610", dry_run=False) diff --git a/tests/test_utils.py b/tests/test_utils.py index b3baf49b..6b28b236 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -5,7 +5,12 @@ import pytest -from oca_github_bot.utils import cmd_to_str, hide_secrets, retry_on_exception +from oca_github_bot.utils import ( + cmd_to_str, + compute_module_label_name, + hide_secrets, + retry_on_exception, +) from .common import set_config @@ -98,3 +103,11 @@ def func_that_raises(): ) def test_cmd_to_str(cmd, expected): assert cmd_to_str(cmd) == expected + + +def test_compute_module_label_name(): + assert compute_module_label_name("web_responsive") == "mod:web_responsive" + assert ( + compute_module_label_name("account_invoice_supplierinfo_update_triple_discount") + == "mod:account_invoice_supplierinfo_update_trip bf3f3" + )