From fca5c9d7b070530f6ab2888ea0900d84eebcbb02 Mon Sep 17 00:00:00 2001 From: Sylvain LE GAL Date: Thu, 2 Apr 2026 01:34:22 +0200 Subject: [PATCH] [FIX] handle max size label limitation (50 char) if label name is too long, it is cut, and ended by an hash of the module name. the module name is present in the description of the label MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - factor out function that computes the shortened label - use 'mod:' instead of 'addon:' - add MODULE_LABEL_COLOR as new configuration Co-authored-by: Stéphane Bidoul --- environment.sample | 3 ++ src/oca_github_bot/config.py | 2 ++ .../tasks/label_modified_addons.py | 21 ++++++++++++-- src/oca_github_bot/utils.py | 28 +++++++++++++++++++ tests/test_utils.py | 15 +++++++++- 5 files changed, 66 insertions(+), 3 deletions(-) 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 b1b886c8..869208ab 100644 --- a/src/oca_github_bot/config.py +++ b/src/oca_github_bot/config.py @@ -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/label_modified_addons.py b/src/oca_github_bot/tasks/label_modified_addons.py index d89c9a16..d9b44760 100644 --- a/src/oca_github_bot/tasks/label_modified_addons.py +++ b/src/oca_github_bot/tasks/label_modified_addons.py @@ -2,14 +2,16 @@ # Distributed under the MIT License (http://opensource.org/licenses/MIT). from .. import github -from ..config import switchable +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}" @@ -23,7 +25,22 @@ def _label_modified_addons(gh, org, repo, pr, dry_run): if not modified_addons: return gh_issue = github.gh_call(gh_pr.issue) - new_labels = {f"addon:{modified_addon}" for modified_addon in modified_addons} + + 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()} 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/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" + )