Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions environment.sample
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
4 changes: 3 additions & 1 deletion src/oca_github_bot/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(",")
Expand Down Expand Up @@ -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:
Expand Down
1 change: 1 addition & 0 deletions src/oca_github_bot/tasks/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

from . import (
heartbeat,
label_modified_addons,
main_branch_bot,
mention_maintainer,
migration_issue_bot,
Expand Down
56 changes: 56 additions & 0 deletions src/oca_github_bot/tasks/label_modified_addons.py
Original file line number Diff line number Diff line change
@@ -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)
28 changes: 28 additions & 0 deletions src/oca_github_bot/utils.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
# Copyright (c) ACSONE SA/NV 2021
# Distributed under the MIT License (http://opensource.org/licenses/MIT).

import hashlib
import re
import shlex
import time
from typing import Sequence

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 ?
Expand All @@ -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
2 changes: 1 addition & 1 deletion src/oca_github_bot/version_branch.py
Original file line number Diff line number Diff line change
Expand Up @@ -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))

Expand Down
1 change: 1 addition & 0 deletions src/oca_github_bot/webhooks/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
21 changes: 21 additions & 0 deletions src/oca_github_bot/webhooks/on_pr_label_modified_addons.py
Original file line number Diff line number Diff line change
@@ -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)
Loading
Loading