aboutsummaryrefslogtreecommitdiff
path: root/labbot/addons/merge-label.py
blob: a978388ed51d215582fc4b3e85afe8a8cf21d9c6 (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
"""
automatically labels issues referenced in merge requests with
specified labels.
"""

import os
import re
import logging

log = logging.getLogger(__name__)


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",
}

# Extra labels that the bot will check for before acting
act_labels = [
    "Sprint",
    "Testing",
    "TestingFailed",
]

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(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 relation_keywords:
            try:
                keyword_index = line_list.index(keyword)

                min_pos = keyword_index - relation_distance
                if min_pos < 0:
                    min_pos = 0

                max_pos = keyword_index + 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(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)
        for label in issue_data["labels"]:
            if label in act_labels or label in state_label.values():
                has_label = True
                break

        if not has_label:
            log.debug(f"Issue #{issue} does not have a relevant label")
            continue

        delete_labels = act_labels + list(state_label.values())

        try:
            label = 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:
    bot.register_merge_hook(merge_label_hook)