aboutsummaryrefslogtreecommitdiff
path: root/labbot/addons/merge-label.py
blob: 2b6dffa8ceb8bc81d6c8d899d07dd21a7b4f62c7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
"""
automatically labels issues referenced in merge requests with
specified labels.
"""

import os
import re
import logging

from labbot.config import Config

log = logging.getLogger(__name__)

config = Config(__name__)
config.set_global_data(
    title_regex = r"^(?:#|)(\d+)\s*",
    word_regex = r"^#(\d+)$",

    relation_keywords = [
        "related"
    ],
    relation_distance = 2,

    state_label = {
        "closed": "In Progress",
        "opened": "Code-Review",
        "merged": "C-R Bestanden",
    },

    act_labels = [
        "Sprint",
        "Testing",
        "TestingFailed",
    ]
)

@config.config_decorator()
async def merge_label_hook(event, gl, *args, **kwargs):
    title = event.object_attributes["title"]
    description = event.object_attributes["description"]
    state = event.object_attributes["state"]
    related_issues = []

    if not description or title.lower().startswith("draft"):
        return

    match = re.search(config["title_regex"], title)
    if match:
        related_issues.append(match.group(1))

    for line in description.split("\\n"):
        line = line.lower()
        line_list = line.split(" ")

        for keyword in config["relation_keywords"]:
            try:
                keyword_index = line_list.index(keyword)

                min_pos = keyword_index - config["relation_distance"]
                if min_pos < 0:
                    min_pos = 0

                max_pos = keyword_index + config["relation_distance"]
                if max_pos >= len(line_list):
                    max_pos = len(line_list)-1

                for word in line_list[min_pos:max_pos+1]:
                    match = re.search(config["word_regex"], word)
                    if match:
                        related_issues.append(match.group(1))

            except ValueError:
                pass

    for issue in related_issues:
        if not issue: continue

        base_url = f"/projects/{event.project_id}/issues/{issue}"

        has_label = False
        issue_data = await gl.getitem(base_url)
        issue_labels = issue_data["labels"]
        for label in issue_labels:
            if label in config["act_labels"] or label in config["state_label"].values():
                has_label = True
                break

        if not has_label:
            label_str = ", ".join(issue_labels)
            log.debug(f"Issue #{issue}({event.project_id}) does not have a relevant label (has: '{label_str}')")
            continue

        delete_labels = config["act_labels"] + list(config["state_label"].values())

        try:
            label = config["state_label"][state]
            if label in delete_labels:
                delete_labels.remove(label)

            remove_labels = ",".join(delete_labels)
            log.debug(f"Applying {label} to {issue}")
            if remove_labels:
                log.debug(f"Removing `{remove_labels} from {issue}")
            await gl.put(base_url, data={
                "add_labels": label,
                "remove_labels": remove_labels,
            })

        except KeyError:
            log.exception("Unknown state")

def setup(bot) -> None:
    config.setup(__name__, bot.name)
    bot.register_merge_hook(merge_label_hook)