Merge lp:~3v1n0/ubuntu-bots/gitlab-support into lp:ubuntu-bots

Proposed by Marco Trevisan (Treviño)
Status: Needs review
Proposed branch: lp:~3v1n0/ubuntu-bots/gitlab-support
Merge into: lp:ubuntu-bots
Prerequisite: lp:~3v1n0/ubuntu-bots/github-support
Diff against target: 199 lines (+122/-11)
2 files modified
Bugtracker/README.txt (+1/-0)
Bugtracker/plugin.py (+121/-11)
To merge this branch: bzr merge lp:~3v1n0/ubuntu-bots/gitlab-support
Reviewer Review Type Date Requested Status
Ubuntu IRC Bots Pending
Review via email: mp+342164@code.launchpad.net

Commit message

Bugtracker: add support for Gitlab issues and merge requests

To post a comment you must log in.
lp:~3v1n0/ubuntu-bots/gitlab-support updated
324. By Marco Trevisan (Treviño)

Bugtracker: add support for Gitlab issues and merge requests

325. By Marco Trevisan (Treviño)

Bugtracker: use cleaner code in generating bug status text

326. By Marco Trevisan (Treviño)

Bugtracker, gitlab: allow to user longer paths for projects

Unmerged revisions

326. By Marco Trevisan (Treviño)

Bugtracker, gitlab: allow to user longer paths for projects

325. By Marco Trevisan (Treviño)

Bugtracker: use cleaner code in generating bug status text

324. By Marco Trevisan (Treviño)

Bugtracker: add support for Gitlab issues and merge requests

323. By Marco Trevisan (Treviño)

Bugtracker: add ext info for Github

322. By Marco Trevisan (Treviño)

Bugtracker: add support for trackers with multiple sub-trackers

Properly log pull requests in Github

321. By Marco Trevisan (Treviño)

Bugtracker: Add github support

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'Bugtracker/README.txt'
--- Bugtracker/README.txt 2018-03-27 04:09:52 +0000
+++ Bugtracker/README.txt 2018-03-27 04:09:52 +0000
@@ -20,6 +20,7 @@
20* str.php from the CUPS project20* str.php from the CUPS project
21* Mantis (http://www.mantisbt.org)21* Mantis (http://www.mantisbt.org)
22* Github22* Github
23* Gitlab
2324
24A notable exception is Sourceforge. Unfortunatly, it has no API or data export25A notable exception is Sourceforge. Unfortunatly, it has no API or data export
25feature to output bug information in a well-formed way.26feature to output bug information in a well-formed way.
2627
=== modified file 'Bugtracker/plugin.py'
--- Bugtracker/plugin.py 2018-03-27 04:09:52 +0000
+++ Bugtracker/plugin.py 2018-03-27 04:09:52 +0000
@@ -419,7 +419,7 @@
419 irc.reply(makeClean(r), prefixNick=False)419 irc.reply(makeClean(r), prefixNick=False)
420420
421 def turlSnarfer(self, irc, msg, match):421 def turlSnarfer(self, irc, msg, match):
422 r"(?P<tracker>https?://\S*?)/(?:Bugs/0*|str.php\?L|show_bug.cgi\?id=|bugreport.cgi\?bug=|(?:bugs|\+bug)/|ticket/|tracker/|\S*aid=|bug=|issues/|pull/)?(?P<bug>\d+)(?P<sfurl>&group_id=\d+&at_id=\d+)?"422 r"(?P<tracker>https?://\S*?)/(?:Bugs/0*|str.php\?L|show_bug.cgi\?id=|bugreport.cgi\?bug=|(?:bugs|\+bug)/|ticket/|tracker/|\S*aid=|bug=|issues/|pull/|merge_requests/)?(?P<bug>\d+)(?P<sfurl>&group_id=\d+&at_id=\d+)?"
423 channel = ircutils.isChannel(msg.args[0]) and msg.args[0] or None423 channel = ircutils.isChannel(msg.args[0]) and msg.args[0] or None
424 if not self.registryValue('bugSnarfer', channel):424 if not self.registryValue('bugSnarfer', channel):
425 return425 return
@@ -543,8 +543,7 @@
543 else:543 else:
544 (bid, product, title, severity, status, assignee, url) = r544 (bid, product, title, severity, status, assignee, url) = r
545545
546 severity = severity[0].upper() + severity[1:].lower() if severity else ''546 state_infos = ', '.join(filter(None, [severity.title(), status.title()]))
547 status = status[0].upper() + status[1:].lower()
548 tracker_name = tracker.description + ' '547 tracker_name = tracker.description + ' '
549 if not do_url:548 if not do_url:
550 url = ''549 url = ''
@@ -552,16 +551,16 @@
552 tracker_name = ''551 tracker_name = ''
553 if product:552 if product:
554 if showext:553 if showext:
555 reports.append("%sbug %s in %s \"%s\" %s [%s,%s] %s" % (tracker_name, bid, product, 554 reports.append("%sbug %s in %s \"%s\" %s [%s] %s" % (tracker_name, bid, product,
556 title, extinfo, severity, status, url))555 title, extinfo, state_infos, url))
557 else:556 else:
558 reports.append("%sbug %s in %s \"%s\" [%s,%s] %s" % (tracker_name, bid, product, 557 reports.append("%sbug %s in %s \"%s\" [%s] %s" % (tracker_name, bid, product,
559 title, severity, status, url))558 title, state_infos, url))
560 else:559 else:
561 if showext:560 if showext:
562 reports.append("%sbug %s \"%s\" %s [%s,%s] %s" % (tracker_name, bid, title, extinfo, severity, status, url))561 reports.append("%sbug %s \"%s\" %s [%s] %s" % (tracker_name, bid, title, extinfo, state_infos, url))
563 else:562 else:
564 reports.append("%sbug %s \"%s\" [%s,%s] %s" % (tracker_name, bid, title, severity, status, url))563 reports.append("%sbug %s \"%s\" [%s] %s" % (tracker_name, bid, title, state_infos, url))
565 if do_assignee and assignee:564 if do_assignee and assignee:
566 reports[-1] = reports[-1] + (" - Assigned to %s" % assignee)565 reports[-1] = reports[-1] + (" - Assigned to %s" % assignee)
567 return reports566 return reports
@@ -1128,8 +1127,8 @@
1128 if is_pull_request:1127 if is_pull_request:
1129 id = u'(Pull request) {}'.format(id)1128 id = u'(Pull request) {}'.format(id)
11301129
1131 # extinfo = "(comments: {}, reactions: {})" % (issue.comments, len(issue.get_reactions()))1130 # extinfo = '(comments: {}, reactions: {})'.format(issue.comments, len(issue.get_reactions()))
1132 extinfo = "(comments: {})".format(issue.comments)1131 extinfo = u'(comments: {})'.format(issue.comments)
11331132
1134 return [(id, self.repo.name, issue.title, labels, issue.state, assignee, issue.html_url, extinfo)]1133 return [(id, self.repo.name, issue.title, labels, issue.state, assignee, issue.html_url, extinfo)]
1135 except Exception as e:1134 except Exception as e:
@@ -1139,6 +1138,113 @@
1139 raise BugtrackerError, s1138 raise BugtrackerError, s
11401139
11411140
1141class Gitlab(IBugtracker):
1142 _GL_TOKENS = { 'gitlab.com': None,
1143 'gitlab.gnome.org': None,
1144 'salsa.debian.org': None }
1145 _gl = {}
1146
1147 def __init__(self, *args, **kwargs):
1148 IBugtracker.__init__(self, *args, **kwargs)
1149
1150 self.gl = None
1151 self.project = None
1152 self.merge_requests = False
1153 self.hostname = self.url.split('://', 1)[1].split('/', 1)[0]
1154
1155 if not self.hostname in Gitlab._gl.keys():
1156 if not self.hostname in Gitlab._GL_TOKENS.keys() or not Gitlab._GL_TOKENS[self.hostname]:
1157 self.log.error("No access token for gitlab host {}".format(self.hostname))
1158 return
1159
1160 try: # We need python-gitlab
1161 import gitlab
1162 from distutils.version import LooseVersion
1163
1164 if LooseVersion(gitlab.__version__) < LooseVersion('1.0.0'):
1165 self.log.exception("gitlab version must be 1.0.0 or newer")
1166
1167 Gitlab._gl[self.hostname] = gitlab.Gitlab(self.url, private_token=Gitlab._GL_TOKENS[self.hostname])
1168 except ImportError:
1169 self.log.error("Please install python-gitlab (=> 1.0.0)")
1170
1171 self.gl = Gitlab._gl[self.hostname]
1172
1173 def has_multiple_trackers(self):
1174 return True
1175
1176 def get_tracker(self, url):
1177 if not self.gl:
1178 return
1179 if not url:
1180 self.log.info("Impossible to get tracker for an empty url")
1181 return
1182
1183 try:
1184 url = url.replace('http://', 'https://', 1)
1185 site_prefix = self.url if self.url[-1] != '/' else self.url[:-1]
1186
1187 if not url.startswith(site_prefix+'/'):
1188 return
1189
1190 projectmatch = re.search(re.escape(self.hostname)+"\/(.+)\/(issues|merge_requests)\/\d+", url)
1191
1192 if projectmatch:
1193 project_full_name = projectmatch.group(1)
1194 project = self.gl.projects.get(project_full_name)
1195 merge_request = projectmatch.group(2) == u'merge_requests'
1196
1197 if not merge_request and not project.issues_enabled:
1198 s = u'Project {} has no issues'.format(project_full_name)
1199 self.log.error(s)
1200 return
1201 elif merge_request and not project.merge_requests_enabled:
1202 s = u'Project {} has no merge requests'.format(project_full_name)
1203 self.log.error(s)
1204 return
1205
1206 description = project.name
1207 if project.namespace['kind'] != u'user':
1208 description = project.namespace['name']
1209
1210 gl = Gitlab(project_full_name.replace('/', '-'), project.web_url, description)
1211 gl.project = project
1212 gl.merge_requests = merge_request
1213 return gl
1214
1215 except Exception as e:
1216 s = u'{}: Impossible to get tracker for {}: {}'.format(
1217 self.description, url, e)
1218 self.log.exception(s)
1219
1220 def get_bug(self, id):
1221 if not self.gl or not self.project:
1222 self.log.info("Gitlab or project not initialized")
1223 return []
1224
1225 try:
1226 if self.merge_requests:
1227 issue = self.project.mergerequests.get(id)
1228 id = u'(Merge request) {}'.format(id)
1229 else:
1230 issue = self.project.issues.get(id)
1231
1232 assignee = None
1233 labels = u', '.join([l for l in issue.labels])
1234
1235 if issue.assignee:
1236 assignee = u'{} ({})'.format(issue.assignee.username, issue.assignee['name'])
1237
1238 extinfo = u'(comments: {})'.format(issue.user_notes_count)
1239
1240 return [(id, self.project.path, issue.title, labels, issue.state, assignee, issue.web_url, extinfo)]
1241 except Exception as e:
1242 s = u'{}: Impossible to get infos for {} issue {}: {}'.format(
1243 self.description, self.project.path_with_namespace, id, e)
1244 self.log.exception(s)
1245 raise BugtrackerError, s
1246
1247
1142# Introspection is quite cool1248# Introspection is quite cool
1143defined_bugtrackers = {}1249defined_bugtrackers = {}
1144v = vars()1250v = vars()
@@ -1150,6 +1256,7 @@
1150registerBugtracker('ubuntu', 'https://launchpad.net', 'Ubuntu', 'launchpad')1256registerBugtracker('ubuntu', 'https://launchpad.net', 'Ubuntu', 'launchpad')
1151registerBugtracker('gnome', 'http://bugzilla.gnome.org', 'Gnome', 'bugzilla')1257registerBugtracker('gnome', 'http://bugzilla.gnome.org', 'Gnome', 'bugzilla')
1152registerBugtracker('gnome2', 'http://bugs.gnome.org', 'Gnome', 'bugzilla')1258registerBugtracker('gnome2', 'http://bugs.gnome.org', 'Gnome', 'bugzilla')
1259registerBugtracker('gnome3', 'https://gitlab.gnome.org', 'Gnome', 'gitlab')
1153registerBugtracker('kde', 'http://bugs.kde.org', 'KDE', 'bugzilla')1260registerBugtracker('kde', 'http://bugs.kde.org', 'KDE', 'bugzilla')
1154registerBugtracker('ximian', 'http://bugzilla.ximian.com', 'Ximian', 'bugzilla')1261registerBugtracker('ximian', 'http://bugzilla.ximian.com', 'Ximian', 'bugzilla')
1155registerBugtracker('freedesktop', 'http://bugzilla.freedesktop.org', 'Freedesktop', 'bugzilla')1262registerBugtracker('freedesktop', 'http://bugzilla.freedesktop.org', 'Freedesktop', 'bugzilla')
@@ -1168,5 +1275,8 @@
1168registerBugtracker('ubottu', 'https://launchpad.net', 'Ubottu', 'launchpad')1275registerBugtracker('ubottu', 'https://launchpad.net', 'Ubottu', 'launchpad')
1169registerBugtracker('sourceforge', 'http://sourceforge.net/tracker/', 'Sourceforge', 'sourceforge')1276registerBugtracker('sourceforge', 'http://sourceforge.net/tracker/', 'Sourceforge', 'sourceforge')
1170registerBugtracker('github', 'https://github.com', 'Github', 'github')1277registerBugtracker('github', 'https://github.com', 'Github', 'github')
1278registerBugtracker('gitlab', 'https://gitlab.com', 'Gitlab', 'gitlab')
1279registerBugtracker('salsa', 'https://salsa.debian.org', 'Debian Salsa', 'gitlab')
1280
1171# Don't delete this one1281# Don't delete this one
1172Class = Bugtracker1282Class = Bugtracker

Subscribers

People subscribed via source and target branches