• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

release-engineering / Sync2Jira / 18378802996

09 Oct 2025 01:59PM UTC coverage: 73.221% (-5.0%) from 78.204%
18378802996

Pull #378

github

web-flow
Merge 2ce53e22f into e93012104
Pull Request #378: Add gitlab support

362 of 553 branches covered (65.46%)

Branch coverage included in aggregate %.

72 of 182 new or added lines in 7 files covered. (39.56%)

1 existing line in 1 file now uncovered.

945 of 1232 relevant lines covered (76.7%)

0.77 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

15.38
/sync2jira/handler/gitlab.py
1
import logging
1✔
2

3
from sync2jira.api.gitlab_client import GitlabClient
1✔
4
import sync2jira.downstream_issue as d_issue
1✔
5
import sync2jira.downstream_pr as d_pr
1✔
6

7
# Local Modules
8
import sync2jira.intermediary as i
1✔
9

10
log = logging.getLogger("sync2jira")
1✔
11

12

13
def should_sync(upstream, labels, config, event_type):
1✔
NEW
14
    mapped_repos = config["sync2jira"]["map"]["gitlab"]
×
NEW
15
    if upstream not in mapped_repos:
×
NEW
16
        log.debug("%r not in Gitlab map: %r", upstream, mapped_repos.keys())
×
NEW
17
        return None
×
NEW
18
    if event_type not in mapped_repos[upstream].get("sync", []):
×
NEW
19
        log.debug(
×
20
            "%r not in Gitlab sync map: %r",
21
            event_type,
22
            mapped_repos[upstream].get("sync", []),
23
        )
NEW
24
        return None
×
25

NEW
26
    _filter = config["sync2jira"].get("filters", {}).get("gitlab", {}).get(upstream, {})
×
NEW
27
    for key, expected in _filter.items():
×
NEW
28
        if key == "labels":
×
NEW
29
            if labels.isdisjoint(expected):
×
NEW
30
                log.debug("Labels %s not found on issue: %s", expected, upstream)
×
NEW
31
                return None
×
32

33

34
def handle_gitlab_issue(body, headers, config, suffix):
1✔
35
    """
36
    Handle GitLab issue from FedMsg.
37

38
    :param Dict body: FedMsg Message body
39
    :param Dict body: FedMsg Message headers
40
    :param Dict config: Config File
41
    :param Bool is_pr: msg refers to a pull request
42
    """
NEW
43
    upstream = body["project"]["path_with_namespace"]
×
NEW
44
    url = headers["x-gitlab-instance"]
×
NEW
45
    token = config["sync2jira"].get("github_token")
×
NEW
46
    labels = {label["title"] for label in body.get("labels", [])}
×
NEW
47
    iid = body.get("object_attributes").get("iid")
×
48

NEW
49
    if should_sync(upstream, labels, config, "issue"):
×
NEW
50
        sync_gitlab_issue(GitlabClient(url, token, upstream), iid, upstream, config)
×
51

52

53
def handle_gitlab_note(body, headers, config, suffix):
1✔
54
    """
55
    Handle Gitlab note from FedMsg.
56

57
    :param Dict body: FedMsg Message body
58
    :param Dict body: FedMsg Message headers
59
    :param Dict config: Config File
60
    :param String suffix: FedMsg suffix
61
    """
NEW
62
    upstream = body["project"]["path_with_namespace"]
×
NEW
63
    url = headers["x-gitlab-instance"]
×
NEW
64
    token = config["sync2jira"].get("github_token")
×
65

NEW
66
    if "merge_request" in body:
×
NEW
67
        labels = {
×
68
            label["title"] for label in body.get("merge_request").get("labels", [])
69
        }
NEW
70
        iid = body.get("merge_request").get("iid")
×
71

NEW
72
        if should_sync(upstream, labels, config, "issue"):
×
NEW
73
            sync_gitlab_mr(GitlabClient(url, token, upstream), iid, upstream)
×
NEW
74
    if "issue" in body:
×
NEW
75
        labels = {label["title"] for label in body.get("issue").get("labels", [])}
×
NEW
76
        iid = body.get("issue").get("iid")
×
77

NEW
78
        if should_sync(upstream, labels, config, "pullrequest"):
×
NEW
79
            sync_gitlab_issue(GitlabClient(url, token, upstream), iid, upstream)
×
NEW
80
    log.info("Note was not added to an issue or merge request. Skipping note event.")
×
81

82

83
def handle_gitlab_mr(body, headers, config, suffix):
1✔
84
    """
85
    Handle Gitlab merge request from FedMsg.
86

87
    :param Dict body: FedMsg Message body
88
    :param Dict body: FedMsg Message headers
89
    :param Dict config: Config File
90
    :param String suffix: FedMsg suffix
91
    """
NEW
92
    upstream = body["project"]["path_with_namespace"]
×
NEW
93
    url = headers["x-gitlab-instance"]
×
NEW
94
    token = config["sync2jira"].get("github_token")
×
NEW
95
    labels = {label["title"] for label in body.get("labels", [])}
×
NEW
96
    iid = body.get("object_attributes").get("iid")
×
97

NEW
98
    if should_sync(upstream, labels, config, "pullrequest"):
×
NEW
99
        sync_gitlab_mr(GitlabClient(url, token, upstream), iid, upstream, config)
×
100

101

102
def sync_gitlab_issue(client, iid, upstream, config):
1✔
NEW
103
    gitlab_issue = client.fetch_issue(iid)
×
NEW
104
    comments = gitlab_issue.notes.list(all=True)
×
105

NEW
106
    issue = i.Issue.from_gitlab(gitlab_issue, comments, upstream, config)
×
NEW
107
    d_issue.sync_with_jira(issue, config)
×
108

109

110
def sync_gitlab_mr(client, iid, upstream, config):
1✔
NEW
111
    gitlab_mr = client.fetch_mr(iid)
×
NEW
112
    comments = gitlab_mr.notes.list(all=True)
×
113

NEW
114
    mr = i.PR.from_gitlab(gitlab_mr, comments, upstream, config)
×
NEW
115
    d_pr.sync_with_jira(mr, config)
×
116

117

118
handlers = {
1✔
119
    "gitlab.issues": handle_gitlab_issue,
120
    "gitlab.issue_comment": handle_gitlab_mr,
121
    "gitlab.note": handle_gitlab_note,
122
}
123

124

125
def get_handler_for(suffix, topic, idx):
1✔
126
    """
127
    Function to check if a handler for given suffix is configured
128
    :param String suffix: Incoming suffix
129
    :param String topic: Topic of incoming message
130
    :param String idx: Id of incoming message
131
    :returns: Handler function if configured for suffix. Otherwise None.
132
    """
NEW
133
    if suffix in handlers:
×
NEW
134
        return handlers.get(suffix)
×
NEW
135
    log.info("No gitlab handler for %r %r %r", suffix, topic, idx)
×
NEW
136
    return None
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc