← Back to team overview

ubuntu-bots team mailing list archive

[Merge] lp:~3v1n0/ubuntu-bots/github-support into lp:ubuntu-bots

 

Marco Trevisan (Treviño) has proposed merging lp:~3v1n0/ubuntu-bots/github-support into lp:ubuntu-bots.

Commit message:
Bugtracker: Add github support

Requested reviews:
  Ubuntu IRC Bots (ubuntu-bots)
Related bugs:
  Bug #1685135 in Ubuntu IRC Bots: "Can't create github bug snarfers"
  https://bugs.launchpad.net/ubuntu-bots/+bug/1685135

For more details, see:
https://code.launchpad.net/~3v1n0/ubuntu-bots/github-support/+merge/342155
-- 
Your team Ubuntu IRC Bots is requested to review the proposed merge of lp:~3v1n0/ubuntu-bots/github-support into lp:ubuntu-bots.
=== modified file 'Bugtracker/README.txt'
--- Bugtracker/README.txt	2011-05-28 06:33:21 +0000
+++ Bugtracker/README.txt	2018-03-26 22:52:07 +0000
@@ -7,6 +7,7 @@
 @bugtracker add openoffice issuezilla http://www.openoffice.org/issues OpenOffice
 @bugtracker add django trac http://code.djangoproject.com/ticket Django
 @bugtracker add gaim sourceforge http://sourceforge.net/tracker/?group_id=235&atid=100235 Gaim
+@bugtracker add snapcore github https://github.com/snapcore Snapcraft
 
 In general: @bugtracker add <name> <type> <baseurl> [description]
 Bugtracker dialects (types) this plugin understands:
@@ -18,6 +19,7 @@
 * WikiForms (see bugs.gnewsense.org for an example)
 * str.php from the CUPS project
 * Mantis (http://www.mantisbt.org)
+* Github
 
 A notable exception is Sourceforge. Unfortunatly, it has no API or data export
 feature to output bug information in a well-formed way.

=== modified file 'Bugtracker/plugin.py'
--- Bugtracker/plugin.py	2014-08-12 16:47:38 +0000
+++ Bugtracker/plugin.py	2018-03-26 22:52:07 +0000
@@ -419,7 +419,7 @@
                         irc.reply(makeClean(r), prefixNick=False)
 
     def turlSnarfer(self, irc, msg, match):
-        r"(?P<tracker>https?://\S*?)/(?:Bugs/0*|str.php\?L|show_bug.cgi\?id=|bugreport.cgi\?bug=|(?:bugs|\+bug)/|ticket/|tracker/|\S*aid=|bug=)?(?P<bug>\d+)(?P<sfurl>&group_id=\d+&at_id=\d+)?"
+        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+)?"
         channel = ircutils.isChannel(msg.args[0]) and msg.args[0] or None
         if not self.registryValue('bugSnarfer', channel):
             return
@@ -515,6 +515,8 @@
             if '/' in url:
                 url = url[:url.index('/')]
             if url in snarfhost:
+                if tracker.has_multiple_trackers():
+                    return tracker.get_tracker(snarfurl)
                 return tracker
 
         if snarfhost == 'pad.lv': # Launchpad URL shortening
@@ -537,11 +539,11 @@
             showext = self.registryValue('extended', channel)
             extinfo = ''
             if len(r) == 8:
-                (bid, product, title, severity, status, assignee, url, extinfo) = r
+                (bid, product, title, severity, status, assignee, url, c) = r
             else:
                 (bid, product, title, severity, status, assignee, url) = r
 
-            severity = severity[0].upper() + severity[1:].lower()
+            severity = severity[0].upper() + severity[1:].lower() if severity else ''
             status = status[0].upper() + status[1:].lower()
             tracker_name = tracker.description + ' '
             if not do_url:
@@ -575,8 +577,12 @@
     def get_bug(self, id):
         raise BugTrackerError("Bugtracker class does not implement get_bug")
 
+    def has_multiple_trackers(self):
+        return False
+
     def get_tracker(self, url):
-        raise BugTrackerError("Bugtracker class does not implement get_tracker")
+        if self.has_multiple_trackers():
+            raise BugTrackerError("Bugtracker class does not implement get_tracker")
 
     def __str__(self):
         return '%s(%s)' % (self.__class__.__name__, self.url)
@@ -1057,6 +1063,79 @@
         except:
             raise BugNotFoundError
 
+
+class Github(IBugtracker):
+    _gh = None
+
+    def __init__(self, *args, **kwargs):
+        IBugtracker.__init__(self, *args, **kwargs)
+
+        if not Github._gh:
+            try: # We need python-github
+                from github import Github as GH
+                Github._gh = GH(user_agent='PyGithub/ubuntu-bot')
+            except ImportError:
+                self.log.error("Please install python-github")
+
+        self.gh = Github._gh
+        self.repo = None
+
+    def has_multiple_trackers(self):
+        return True
+
+    def get_tracker(self, url):
+        if not self.gh:
+            return
+        if not url:
+            self.log.info("Impossible to get tracker for an empty url")
+            return
+
+        try:
+            url = url.replace('http://', 'https://', 1)
+            if url.startswith(self.url):
+                projectmatch = re.search("([^/]+/[^/]+)/(issues|pull)/\d+", url)
+
+                if projectmatch:
+                    repo_name = projectmatch.group(1)
+                    repo = self.gh.get_repo(repo_name)
+                    if not repo.has_issues:
+                        s = u'Repository {} has no issues'.format(repo_name)
+                        self.log.exception(s)
+
+                    gh = Github(repo.full_name.replace('/', '-'), repo.html_url, repo.owner.login)
+                    gh.repo = repo
+                    return gh
+
+        except Exception as e:
+            s = u'{}: Impossible to get tracker for {}: {}'.format(
+                self.description, url, e)
+            self.log.exception(s)
+
+    def get_bug(self, id):
+        if not self.gh or not self.repo:
+            self.log.info("Github or repository not initialized")
+            return []
+
+        try:
+            issue = self.repo.get_issue(id)
+
+            assignee = None
+            labels = u', '.join([l.name for l in issue.labels])
+            is_pull_request = issue.html_url.endswith(u'/pull/{}'.format(id))
+
+            if issue.assignee:
+                assignee = u'{} ({})'.format(issue.assignee.login, issue.assignee.name)
+            if is_pull_request:
+                id = u'(Pull request) {}'.format(id)
+
+            return [(id, self.repo.name, issue.title, labels, issue.state, assignee, issue.html_url)]
+        except Exception as e:
+            s = u'{}: Impossible to get infos for {} issue {}: {}'.format(
+                self.description, self.repo.full_name, id, e)
+            self.log.exception(s)
+            raise BugtrackerError, s
+
+
 # Introspection is quite cool
 defined_bugtrackers = {}
 v = vars()
@@ -1084,6 +1163,7 @@
 registerBugtracker('supybot', 'http://sourceforge.net/tracker/?group_id=58965&atid=489447', 'Supybot', 'sourceforge')
 registerBugtracker('mantis', "http://www.mantisbt.org/bugs";, "Mantis", 'mantis')
 registerBugtracker('ubottu', 'https://launchpad.net', 'Ubottu', 'launchpad')
+registerBugtracker('sourceforge', 'http://sourceforge.net/tracker/', 'Sourceforge', 'sourceforge')
+registerBugtracker('github', 'https://github.com', 'Github', 'github')
 # Don't delete this one
-registerBugtracker('sourceforge', 'http://sourceforge.net/tracker/', 'Sourceforge', 'sourceforge')
 Class = Bugtracker

=== modified file 'README.txt'
--- README.txt	2011-05-28 06:33:21 +0000
+++ README.txt	2018-03-26 22:52:07 +0000
@@ -18,6 +18,7 @@
 
 (Optional)
 Launchpadlib    python-launchpadlib         https://launchpad.net/launchpadlib
+PyGithub        python-github               https://github.com/PyGithub/PyGithub
 apt-file        apt-file                    N/A Debian (and derivatives) only
 
 Launchpadlib will become a required module for Bugtracker (and possibly others)