From metatracker at psf.upfronthosting.co.za Thu Jan 5 18:31:04 2017 From: metatracker at psf.upfronthosting.co.za (Ezio Melotti) Date: Thu, 05 Jan 2017 23:31:04 +0000 Subject: [Tracker-discuss] [issue589] Add GitHub PR to b.p.o issues using GitHub webhooks (depends on issue586) In-Reply-To: <1464035377.63.0.520552418309.issue589@psf.upfronthosting.co.za> Message-ID: <1483659064.1.0.0447777159402.issue589@psf.upfronthosting.co.za> Ezio Melotti added the comment: Done in https://hg.python.org/tracker/roundup/rev/f44e8ff423a4 Thanks everyone for the patches and the reviews! ---------- assignedto: -> ezio.melotti nosy: +ezio.melotti status: in-progress -> testing _______________________________________________________ PSF Meta Tracker _______________________________________________________ From metatracker at psf.upfronthosting.co.za Thu Jan 12 16:25:46 2017 From: metatracker at psf.upfronthosting.co.za (Maciej Szulik) Date: Thu, 12 Jan 2017 21:25:46 +0000 Subject: [Tracker-discuss] [issue590] Show Pull Request status on b.p.o (depends on issue586, issue589) In-Reply-To: <1468432537.9.0.749472602209.issue590@psf.upfronthosting.co.za> Message-ID: <1484256346.03.0.858902561823.issue590@psf.upfronthosting.co.za> Maciej Szulik added the comment: Done in https://hg.python.org/tracker/roundup/rev/719a007ca12d and https://hg.python.org/tracker/python-dev/rev/74d7030f0eef Thanks everyone for help! ---------- status: in-progress -> testing _______________________________________________________ PSF Meta Tracker _______________________________________________________ From metatracker at psf.upfronthosting.co.za Thu Jan 19 13:05:31 2017 From: metatracker at psf.upfronthosting.co.za (Brett C.) Date: Thu, 19 Jan 2017 18:05:31 +0000 Subject: [Tracker-discuss] [issue589] Add GitHub PR to b.p.o issues using GitHub webhooks (depends on issue586) In-Reply-To: <1464035377.63.0.520552418309.issue589@psf.upfronthosting.co.za> Message-ID: <1484849131.74.0.742438478214.issue589@psf.upfronthosting.co.za> Brett C. added the comment: I've tested this and it seems to be working. _______________________________________________________ PSF Meta Tracker _______________________________________________________ From metatracker at psf.upfronthosting.co.za Thu Jan 19 13:05:41 2017 From: metatracker at psf.upfronthosting.co.za (Brett C.) Date: Thu, 19 Jan 2017 18:05:41 +0000 Subject: [Tracker-discuss] [issue590] Show Pull Request status on b.p.o (depends on issue586, issue589) In-Reply-To: <1468432537.9.0.749472602209.issue590@psf.upfronthosting.co.za> Message-ID: <1484849141.46.0.289445122157.issue590@psf.upfronthosting.co.za> Brett C. added the comment: Just did a quick test of this and it seems to be working! ---------- nosy: +brett.cannon _______________________________________________________ PSF Meta Tracker _______________________________________________________ From metatracker at psf.upfronthosting.co.za Mon Jan 23 21:21:54 2017 From: metatracker at psf.upfronthosting.co.za (Ezio Melotti) Date: Tue, 24 Jan 2017 02:21:54 +0000 Subject: [Tracker-discuss] [issue611] Update issue with a commit information Message-ID: <1485224514.2.0.124865035832.issue611@psf.upfronthosting.co.za> New submission from Ezio Melotti: I haven't tried the patch yet, but in + if len(user_id) > 1: + # pick first matching user, when multiple found + user_id = user_id[0] + elif len(user_id) < 1: + # set bpobot as userid when none is found + user_id = self.db.user.filter(None, {'username': 'python-dev'}) + if len(user_id) != 1: + # python-dev does not exists, anonymous will be used instead + return + username = self.db.user.get(user_id[0], 'username') + self.db.setCurrentUser(username) I think you'll end up with a user_id in the >1 case and a list (assuming filter returns a list) in the <1 case. At the end you take the first element of the list, which is correct only for the <1 case (unless filters returns a single id, but in that case I'm not sure what the [0] at the end is for). I would also suggest to user user_ids and user_id to distinguish the list from the single id. I would rename set_current_user() to something more explicit, or, if the only purpose of this method is to affect the author=self.db.getuid(), perhaps remove the method and use a module/class-level constant. The same constant could also be used in the snippet I pasted above to avoid duplication. Does + newmsg = self.db.msg.create(content=msg, author=self.db.getuid()) + issue_msgs.append(newmsg) + self.db.issue.set(issue_id, messages=issue_msgs) produces the correct output in the history at the bottom of the issue? (i.e. does it show "set messages: +msgXXX" with only the new message, rather than the whole list of messages?) I would move the .encode('utf-8') from dispatch() to handle_action() (add it to the line "'branch': branch.encode('utf-8'),"). The commit_id variable in handle_action() is unused. Any reason why you used Template() instead of a simply using format() (or %)? You might also be able to get rid of all those encode if you use format(). github/roundup should be capitalized properly in the docstrings. The docstring for handle_action() could be a bit more explicit :) _______________________________________________________ PSF Meta Tracker _______________________________________________________ From metatracker at psf.upfronthosting.co.za Wed Jan 25 01:42:31 2017 From: metatracker at psf.upfronthosting.co.za (INADA Naoki) Date: Wed, 25 Jan 2017 06:42:31 +0000 Subject: [Tracker-discuss] [issue463] HTTPS only version for login for this tracker In-Reply-To: <1337666026.16.0.0159243982051.issue463@psf.upfronthosting.co.za> Message-ID: <1485326551.29.0.0888026653441.issue463@psf.upfronthosting.co.za> INADA Naoki added the comment: https://www.mozilla.org/en-US/firefox/51.0/releasenotes/ > A warning is displayed when a login page does not have a secure connection I think we should follow "always use HTTPS" trends. ---------- nosy: +inada.naoki _______________________________________________________ PSF Meta Tracker _______________________________________________________ From metatracker at psf.upfronthosting.co.za Fri Jan 27 18:27:41 2017 From: metatracker at psf.upfronthosting.co.za (Brett C.) Date: Fri, 27 Jan 2017 23:27:41 +0000 Subject: [Tracker-discuss] [issue611] Update issue with a commit information In-Reply-To: <1485224514.2.0.124865035832.issue611@psf.upfronthosting.co.za> Message-ID: <1485559661.73.0.667700985982.issue611@psf.upfronthosting.co.za> Brett C. added the comment: Ezio seems to be right about user_id and getting a list or a name depending on which branch is taken based on the line that sets user_id initially. It also might be clearer if you check for `not len(user_id)` or `len(user_id) == 0` instead of `len(user_id) < 1`. And thanks for handling the case when there's no match. I wouldn't be surprised if people don't sign the CLA but still get a PR merged that e.g. fixes a single line of the documentation. _______________________________________________________ PSF Meta Tracker _______________________________________________________ From metatracker at psf.upfronthosting.co.za Sat Jan 28 06:04:04 2017 From: metatracker at psf.upfronthosting.co.za (Maciej Szulik) Date: Sat, 28 Jan 2017 11:04:04 +0000 Subject: [Tracker-discuss] [issue611] Update issue with a commit information In-Reply-To: <1485224514.2.0.124865035832.issue611@psf.upfronthosting.co.za> Message-ID: <1485601444.48.0.740452650805.issue611@psf.upfronthosting.co.za> Maciej Szulik added the comment: Patch updated and most importantly tested with github. Comments inline below: > I think you'll end up with a user_id in the >1 case and a list (assuming filter returns a list) in the <1 case. At the end you take the first element of the list, which is > correct only for the <1 case (unless filters returns a single id, but in that case I'm not sure what the [0] at the end is for). I would also suggest to user user_ids and > user_id to distinguish the list from the single id. > Ezio seems to be right about user_id and getting a list or a name depending on which branch is taken based on the line that sets user_id initially. It also might be clearer if > you check for `not len(user_id)` or `len(user_id) == 0` instead of `len(user_id) < 1`. Yeah, filter returns list always, I've updated the patch accordingly. > I would rename set_current_user() to something more explicit, or, if the only purpose of this method is to affect the author=self.db.getuid(), perhaps remove the method and use > a module/class-level constant. The same constant could also be used in the snippet I pasted above to avoid duplication. I've changed it to set_roundup_user, not sure what kind of constant you were talking about. > Does produces the correct output in the history at the bottom of the issue? (i.e. does it show "set messages: +msgXXX" with only the new message, rather than the whole list > of messages?) Yes, it's 'messages +msgX', as expected. > I would move the .encode('utf-8') from dispatch() to handle_action() (add it to the line "'branch': branch.encode('utf-8'),"). Done > The commit_id variable in handle_action() is unused. Removed > Any reason why you used Template() instead of a simply using format() (or %)? You might also be able to get rid of all those encode if you use format(). Laziness, I just copy&pasted what I got from hglookup.py ;) Changed to format. > github/roundup should be capitalized properly in the docstrings. The docstring for handle_action() could be a bit more explicit :) Done > And thanks for handling the case when there's no match. I wouldn't be surprised if people don't sign the CLA but still get a PR merged that e.g. fixes a single line of the > documentation. N/p :) _______________________________________________________ PSF Meta Tracker _______________________________________________________ -------------- next part -------------- diff --git a/roundup/github.py b/roundup/github.py --- a/roundup/github.py +++ b/roundup/github.py @@ -1,5 +1,3 @@ -from roundup.exceptions import * - import hashlib import hmac import json @@ -7,6 +5,8 @@ import os import logging +from roundup.exceptions import Unauthorised, MethodNotAllowed, \ + UnsupportedMediaType, Reject if hasattr(hmac, 'compare_digest'): compare_digest = hmac.compare_digest @@ -14,8 +14,15 @@ def compare_digest(a, b): return a == b -url_re = re.compile(r'https://github.com/python/cpython/pull/(?P\d+)') -issue_id_re = re.compile(r'bpo\s*(\d+)', re.I) +URL_RE = re.compile(r'https://github.com/python/cpython/pull/(?P\d+)') +ISSUE_GH_RE = re.compile(r'bpo\s*(\d+)', re.I) +ISSUE_BPO_RE = re.compile(r'(#|issue|bug)\s*(?P\d+)', re.I) + +COMMENT_TEMPLATE = """\ +New changeset {changeset_id} by {author} in branch '{branch}': +{commit_msg} +{changeset_url} +""" class GitHubHandler: """ @@ -59,6 +66,10 @@ data = json.loads(self.form.value) handler = IssueComment(self.db, data) handler.dispatch() + elif event == 'push': + data = json.loads(self.form.value) + handler = Push(self.db, data) + handler.dispatch() def validate_webhook_secret(self): """ @@ -93,7 +104,7 @@ def get_event(self): """ - Extracts github event from header field. + Extracts GitHub event from header field. """ return self.request.headers.get('X-GitHub-Event', None) @@ -107,24 +118,27 @@ self.db = db self.data = data - def set_current_user(self): + def set_roundup_user(self): """ - Helper method used for setting current user for roundup, based - on the information from github about event author. + Helper method used for setting the current user for Roundup, based + on the information from GitHub about event author. """ github_username = self.get_github_username() - user_id = self.db.user.filter(None, {'github': github_username}) - # TODO set bpobot as userid when none is found - if len(user_id) == 1: - # TODO what if multiple bpo users have the same github username? - username = self.db.user.get(user_id[0], 'username') - self.db.setCurrentUser(username) + user_ids = self.db.user.filter(None, {'github': github_username}) + if not user_ids: + # set bpobot as userid when none is found + user_ids = self.db.user.filter(None, {'username': 'python-dev'}) + if not user_ids: + # python-dev does not exists, anonymous will be used instead + return + username = self.db.user.get(user_ids[0], 'username') + self.db.setCurrentUser(username) def dispatch(self): """ - Main method responsible for responding to incoming github event. + Main method responsible for responding to incoming GitHub event. """ - self.set_current_user() + self.set_roundup_user() action = self.data.get('action', '').encode('utf-8') issue_ids = self.get_issue_ids() if not issue_ids: @@ -220,7 +234,7 @@ raise Reject() title = pull_request.get('title', '').encode('utf-8') body = pull_request.get('body', '').encode('utf-8') - return list(set(issue_id_re.findall(title) + issue_id_re.findall(body))) + return list(set(ISSUE_GH_RE.findall(title) + ISSUE_GH_RE.findall(body))) def get_pr_details(self): """ @@ -234,7 +248,7 @@ raise Reject() title = pull_request.get('title', '').encode('utf-8') status = pull_request.get('state', '').encode('utf-8') - # github has two states open and closed, information about pull request + # GitHub has two states open and closed, information about pull request # being merged in kept in separate field if pull_request.get('merged', False): status = "merged" @@ -242,13 +256,14 @@ def get_github_username(self): """ - Extract github username from a pull request. + Extract GitHub username from a pull request. """ pull_request = self.data.get('pull_request') if pull_request is None: raise Reject() return pull_request.get('user', {}).get('login', '').encode('utf-8') + class IssueComment(Event): """ Class responsible for handling issue comment events, but only within the @@ -274,7 +289,7 @@ raise Reject() title = issue.get('title', '').encode('utf-8') body = comment.get('body', '').encode('utf-8') - return list(set(issue_id_re.findall(title) + issue_id_re.findall(body))) + return list(set(ISSUE_GH_RE.findall(title) + ISSUE_GH_RE.findall(body))) def get_pr_details(self): """ @@ -284,16 +299,74 @@ if issue is None: raise Reject() url = issue.get('pull_request', {}).get('html_url') - number_match = url_re.search(url) + number_match = URL_RE.search(url) if not number_match: return (None, None, None) return number_match.group('number'), None, None def get_github_username(self): """ - Extract github username from a comment. + Extract GitHub username from a comment. """ issue = self.data.get('issue') if issue is None: raise Reject() return issue.get('user', {}).get('login', '').encode('utf-8') + + +class Push(Event): + """ + Class responsible for handling push events. + """ + + def dispatch(self): + """ + Main method responsible for responding to incoming GitHub event. + """ + self.set_roundup_user() + commits = self.data.get('commits', []) + ref = self.data.get('ref', 'refs/heads/master') + messages = {} + # extract commit messages + for commit in commits: + messages.update(self.handle_action(commit, ref)) + if not messages: + return + # add comments to appropriate issues + for issue_id, msg in messages.iteritems(): + issue_msgs = self.db.issue.get(issue_id, 'messages') + newmsg = self.db.msg.create(content=msg, author=self.db.getuid()) + issue_msgs.append(newmsg) + self.db.issue.set(issue_id, messages=issue_msgs) + self.db.commit() + + def get_github_username(self): + """ + Extract GitHub username from a push event. + """ + return self.data.get('pusher', []).get('name', '').encode('utf-8') + + def handle_action(self, commit, ref): + """ + This is implementing the same logic as the mercurial hook from here: + https://hg.python.org/hooks/file/tip/hgroundup.py + """ + branch = ref.encode('utf-8').split('/')[-1] + description = commit.get('message', '').encode('utf-8') + matches = ISSUE_BPO_RE.finditer(description) + messages = {} + for match in matches: + # TODO: close issue when close(s|d) is seen + data = match.groupdict() + # check for duplicated issue numbers in the same commit msg + if data['issue_id'] in messages: + continue + messages[data['issue_id']] = COMMENT_TEMPLATE.format( + author=commit.get('committer', {}).get('name', '').encode('utf-8'), + branch=branch, + changeset_id=commit.get('id', '').encode('utf-8'), + changeset_url=commit.get('url', '').encode('utf-8'), + commit_msg=description.splitlines()[0], + ) + return messages + diff --git a/test/data/pushevent.txt b/test/data/pushevent.txt new file mode 100644 --- /dev/null +++ b/test/data/pushevent.txt @@ -0,0 +1,11 @@ +POST /python-dev/pull_request HTTP/1.1 +Host: 3ab1787e.ngrok.io +Accept: */* +User-Agent: GitHub-Hookshot/98ea3cc +X-GitHub-Event: push +X-GitHub-Delivery: 3d4b5180-5c89-11e6-88fd-1aa99d941991 +content-type: application/json +X-Hub-Signature: sha1=c760213ddccd47bf3bbd1735b70c787bb8d07724 +Content-Length: 5852 + +{"ref":"refs/heads/test1","before":"6c5d08240c73014f282bc7336c08fe9ec0b557b0","after":"65c3a074262662a2c55109ff9a2456ee7647fcc9","created":false,"deleted":false,"forced":false,"base_ref":null,"compare":"https://github.com/python/cpython/compare/6c5d08240c73...65c3a0742626","commits":[{"id":"65c3a074262662a2c55109ff9a2456ee7647fcc9","tree_id":"2a35adbb6fce03b51dce23b4ed48526a5a74255a","distinct":true,"message":"#1: fix tests.","timestamp":"2017-01-19T22:19:07+01:00","url":"https://github.com/python/cpython/commit/65c3a074262662a2c55109ff9a2456ee7647fcc9","author":{"name":"Maciej Szulik","email":"soltysh at gmail.com","username":"soltysh"},"committer":{"name":"Maciej Szulik","email":"soltysh at gmail.com","username":"soltysh"},"added":[],"removed":[],"modified":["README"]}],"head_commit":{"id":"65c3a074262662a2c55109ff9a2456ee7647fcc9","tree_id":"2a35adbb6fce03b51dce23b4ed48526a5a74255a","distinct":true,"message":"Fixes#1","timestamp":"2017-01-19T22:19:07+01:00","url":"https://githu b.com/python/cpython/commit/65c3a074262662a2c55109ff9a2456ee7647fcc9","author":{"name":"Maciej Szulik","email":"soltysh at gmail.com","username":"soltysh"},"committer":{"name":"Maciej Szulik","email":"soltysh at gmail.com","username":"soltysh"},"added":[],"removed":[],"modified":["README"]},"repository":{"id":76687672,"name":"cpython","full_name":"python/cpython","owner":{"name":"python"},"private":false,"html_url":"https://github.com/python/cpython","description":"Semi-officialread-onlymirroroftheCPythonMercurialrepository","fork":true,"url":"https://github.com/python/cpython","forks_url":"https://api.github.com/repos/python/cpython/forks","keys_url":"https://api.github.com/repos/python/cpython/keys{/key_id}","collaborators_url":"https://api.github.com/repos/python/cpython/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/python/cpython/teams","hooks_url":"https://api.github.com/repos/python/cpython/hooks","issue_events_url":"https://api.github.com/repos/pyt hon/cpython/issues/events{/number}","events_url":"https://api.github.com/repos/python/cpython/events","assignees_url":"https://api.github.com/repos/python/cpython/assignees{/user}","branches_url":"https://api.github.com/repos/python/cpython/branches{/branch}","tags_url":"https://api.github.com/repos/python/cpython/tags","blobs_url":"https://api.github.com/repos/python/cpython/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/python/cpython/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/python/cpython/git/refs{/sha}","trees_url":"https://api.github.com/repos/python/cpython/git/trees{/sha}","statuses_url":"https://api.github.com/repos/python/cpython/statuses/{sha}","languages_url":"https://api.github.com/repos/python/cpython/languages","stargazers_url":"https://api.github.com/repos/python/cpython/stargazers","contributors_url":"https://api.github.com/repos/python/cpython/contributors","subscribers_url":"https://api.github.com/repos/python/cpython/subs cribers","subscription_url":"https://api.github.com/repos/python/cpython/subscription","commits_url":"https://api.github.com/repos/python/cpython/commits{/sha}","git_commits_url":"https://api.github.com/repos/python/cpython/git/commits{/sha}","comments_url":"https://api.github.com/repos/python/cpython/comments{/number}","issue_comment_url":"https://api.github.com/repos/python/cpython/issues/comments{/number}","contents_url":"https://api.github.com/repos/python/cpython/contents/{+path}","compare_url":"https://api.github.com/repos/python/cpython/compare/{base}...{head}","merges_url":"https://api.github.com/repos/python/cpython/merges","archive_url":"https://api.github.com/repos/python/cpython/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/python/cpython/downloads","issues_url":"https://api.github.com/repos/python/cpython/issues{/number}","pulls_url":"https://api.github.com/repos/python/cpython/pulls{/number}","milestones_url":"https://api.github.com/repo s/python/cpython/milestones{/number}","notifications_url":"https://api.github.com/repos/python/cpython/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/python/cpython/labels{/name}","releases_url":"https://api.github.com/repos/python/cpython/releases{/id}","deployments_url":"https://api.github.com/repos/python/cpython/deployments","created_at":1481924711,"updated_at":"2016-12-16T21:45:35Z","pushed_at":1484860759,"git_url":"git://github.com/python/cpython.git","ssh_url":"git at github.com:python/cpython.git","clone_url":"https://github.com/python/cpython.git","svn_url":"https://github.com/python/cpython","homepage":"","size":269743,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master","stargazers":0,"master_branch":"master"},"pusher":{"name":"sol tysh","email":"soltysh at gmail.com"},"sender":{"login":"soltysh","id":576341,"avatar_url":"https://avatars.githubusercontent.com/u/576341?v=3","gravatar_id":"","url":"https://api.github.com/users/soltysh","html_url":"https://github.com/soltysh","followers_url":"https://api.github.com/users/soltysh/followers","following_url":"https://api.github.com/users/soltysh/following{/other_user}","gists_url":"https://api.github.com/users/soltysh/gists{/gist_id}","starred_url":"https://api.github.com/users/soltysh/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/soltysh/subscriptions","organizations_url":"https://api.github.com/users/soltysh/orgs","repos_url":"https://api.github.com/users/soltysh/repos","events_url":"https://api.github.com/users/soltysh/events{/privacy}","received_events_url":"https://api.github.com/users/soltysh/received_events","type":"User","site_admin":false}} diff --git a/test/test_github.py b/test/test_github.py --- a/test/test_github.py +++ b/test/test_github.py @@ -296,6 +296,18 @@ status = self.db.pull_request.get(prs[0], 'status') self.assertEqual(status, 'closed') + def testPushEventAddsComment(self): + dummy_client = self._make_client('pushevent.txt') + handler = GitHubHandler(dummy_client) + handler.dispatch() + msgs = self.db.issue.get('1', 'messages') + self.assertEqual(len(msgs), 1) + content = self.db.msg.get(msgs[0], 'content') + self.assertIn("""New changeset 65c3a074262662a2c55109ff9a2456ee7647fcc9 by Maciej Szulik in branch 'test1': +#1: fix tests. +https://github.com/python/cpython/commit/65c3a074262662a2c55109ff9a2456ee7647fcc9 +""", + content) def test_suite(): suite = unittest.TestSuite() From metatracker at psf.upfronthosting.co.za Sun Jan 29 21:43:22 2017 From: metatracker at psf.upfronthosting.co.za (Ezio Melotti) Date: Mon, 30 Jan 2017 02:43:22 +0000 Subject: [Tracker-discuss] [issue611] Update issue with a commit information In-Reply-To: <1485224514.2.0.124865035832.issue611@psf.upfronthosting.co.za> Message-ID: <1485744202.37.0.944973706447.issue611@psf.upfronthosting.co.za> Ezio Melotti added the comment: > I've changed it to set_roundup_user, not sure what kind of constant you were talking about. I meant a constant for the python-dev user you find with: user_ids = self.db.user.filter(None, {'username': 'python-dev'}) Since the python-dev user is not going to change at run-time, there should be no reason to look it up every time, however it might be difficult to get access to the db, so if it's too much trouble don't worry about it. I think the COMMENT_TEMPLATE.format(...) in handle_action() can be further improved. If you use unicode for the template string, and pass unicode to format, you should be able to just encode the result once at end (either after the format or in self.db.msg.create(), assuming create() doesn't accept unicode). The rest of the patch LGTM. _______________________________________________________ PSF Meta Tracker _______________________________________________________ From metatracker at psf.upfronthosting.co.za Mon Jan 30 15:44:03 2017 From: metatracker at psf.upfronthosting.co.za (Maciej Szulik) Date: Mon, 30 Jan 2017 20:44:03 +0000 Subject: [Tracker-discuss] [issue611] Update issue with a commit information In-Reply-To: <1485224514.2.0.124865035832.issue611@psf.upfronthosting.co.za> Message-ID: <1485809043.52.0.13686581042.issue611@psf.upfronthosting.co.za> Maciej Szulik added the comment: Patch with comments from Ezio addressed and additionally supporting closing issues. _______________________________________________________ PSF Meta Tracker _______________________________________________________ -------------- next part -------------- diff --git a/roundup/github.py b/roundup/github.py --- a/roundup/github.py +++ b/roundup/github.py @@ -1,5 +1,3 @@ -from roundup.exceptions import * - import hashlib import hmac import json @@ -7,6 +5,8 @@ import os import logging +from roundup.exceptions import Unauthorised, MethodNotAllowed, \ + UnsupportedMediaType, Reject if hasattr(hmac, 'compare_digest'): compare_digest = hmac.compare_digest @@ -14,8 +14,17 @@ def compare_digest(a, b): return a == b -url_re = re.compile(r'https://github.com/python/cpython/pull/(?P\d+)') -issue_id_re = re.compile(r'bpo\s*(\d+)', re.I) +URL_RE = re.compile(r'https://github.com/python/cpython/pull/(?P\d+)') +ISSUE_GH_RE = re.compile(r'bpo\s*(\d+)', re.I) +VERBS = r'(?:\b(?Pclose[sd]?|closing|)\s+)?' +ISSUE_BPO_RE = re.compile(r'%s(?:#|\bissue|\bbug)\s*(?P\d+)' + % VERBS, re.I|re.U) + +COMMENT_TEMPLATE = u"""\ +New changeset {changeset_id} by {author} in branch '{branch}': +{commit_msg} +{changeset_url} +""" class GitHubHandler: """ @@ -59,6 +68,10 @@ data = json.loads(self.form.value) handler = IssueComment(self.db, data) handler.dispatch() + elif event == 'push': + data = json.loads(self.form.value) + handler = Push(self.db, data) + handler.dispatch() def validate_webhook_secret(self): """ @@ -93,7 +106,7 @@ def get_event(self): """ - Extracts github event from header field. + Extracts GitHub event from header field. """ return self.request.headers.get('X-GitHub-Event', None) @@ -107,24 +120,27 @@ self.db = db self.data = data - def set_current_user(self): + def set_roundup_user(self): """ - Helper method used for setting current user for roundup, based - on the information from github about event author. + Helper method used for setting the current user for Roundup, based + on the information from GitHub about event author. """ github_username = self.get_github_username() - user_id = self.db.user.filter(None, {'github': github_username}) - # TODO set bpobot as userid when none is found - if len(user_id) == 1: - # TODO what if multiple bpo users have the same github username? - username = self.db.user.get(user_id[0], 'username') - self.db.setCurrentUser(username) + user_ids = self.db.user.filter(None, {'github': github_username}) + if not user_ids: + # set bpobot as userid when none is found + user_ids = self.db.user.filter(None, {'username': 'python-dev'}) + if not user_ids: + # python-dev does not exists, anonymous will be used instead + return + username = self.db.user.get(user_ids[0], 'username') + self.db.setCurrentUser(username) def dispatch(self): """ - Main method responsible for responding to incoming github event. + Main method responsible for responding to incoming GitHub event. """ - self.set_current_user() + self.set_roundup_user() action = self.data.get('action', '').encode('utf-8') issue_ids = self.get_issue_ids() if not issue_ids: @@ -220,7 +236,7 @@ raise Reject() title = pull_request.get('title', '').encode('utf-8') body = pull_request.get('body', '').encode('utf-8') - return list(set(issue_id_re.findall(title) + issue_id_re.findall(body))) + return list(set(ISSUE_GH_RE.findall(title) + ISSUE_GH_RE.findall(body))) def get_pr_details(self): """ @@ -234,7 +250,7 @@ raise Reject() title = pull_request.get('title', '').encode('utf-8') status = pull_request.get('state', '').encode('utf-8') - # github has two states open and closed, information about pull request + # GitHub has two states open and closed, information about pull request # being merged in kept in separate field if pull_request.get('merged', False): status = "merged" @@ -242,13 +258,14 @@ def get_github_username(self): """ - Extract github username from a pull request. + Extract GitHub username from a pull request. """ pull_request = self.data.get('pull_request') if pull_request is None: raise Reject() return pull_request.get('user', {}).get('login', '').encode('utf-8') + class IssueComment(Event): """ Class responsible for handling issue comment events, but only within the @@ -274,7 +291,7 @@ raise Reject() title = issue.get('title', '').encode('utf-8') body = comment.get('body', '').encode('utf-8') - return list(set(issue_id_re.findall(title) + issue_id_re.findall(body))) + return list(set(ISSUE_GH_RE.findall(title) + ISSUE_GH_RE.findall(body))) def get_pr_details(self): """ @@ -284,16 +301,93 @@ if issue is None: raise Reject() url = issue.get('pull_request', {}).get('html_url') - number_match = url_re.search(url) + number_match = URL_RE.search(url) if not number_match: return (None, None, None) return number_match.group('number'), None, None def get_github_username(self): """ - Extract github username from a comment. + Extract GitHub username from a comment. """ issue = self.data.get('issue') if issue is None: raise Reject() return issue.get('user', {}).get('login', '').encode('utf-8') + + +class Push(Event): + """ + Class responsible for handling push events. + """ + + def get_github_username(self): + """ + Extract GitHub username from a push event. + """ + return self.data.get('pusher', []).get('name', '').encode('utf-8') + + def dispatch(self): + """ + Main method responsible for responding to incoming GitHub event. + """ + self.set_roundup_user() + commits = self.data.get('commits', []) + ref = self.data.get('ref', 'refs/heads/master') + # messages dictionary maps issue number to a tuple containing + # the message to be posted as a comment an boolean flag informing + # if the issue should be 'closed' + messages = {} + # extract commit messages + for commit in commits: + msgs = self.handle_action(commit, ref) + for issue_id, (msg, close) in msgs.iteritems(): + if issue_id not in messages: + messages[issue_id] = (u'', False) + curr_msg, curr_close = messages[issue_id] + # we append the new message to the other and do binary OR + # on close, so that at least one information will actually + # close the issue + messages[issue_id] = (curr_msg + u'\n' + msg, curr_close|close) + if not messages: + return + for issue_id, (msg, close) in messages.iteritems(): + # add comments to appropriate issues... + id = issue_id.encode('utf-8') + issue_msgs = self.db.issue.get(id, 'messages') + newmsg = self.db.msg.create(content=msg.encode('utf-8'), author=self.db.getuid()) + issue_msgs.append(newmsg) + self.db.issue.set(id, messages=issue_msgs) + # ... and close, if needed + if close: + self.db.issue.set(id, + status=self.db.status.lookup('closed')) + self.db.issue.set(id, + resolution=self.db.resolution.lookup('fixed')) + self.db.issue.set(id, + stage=self.db.stage.lookup('resolved')) + self.db.commit() + + def handle_action(self, commit, ref): + """ + This is implementing the same logic as the mercurial hook from here: + https://hg.python.org/hooks/file/tip/hgroundup.py + """ + branch = ref.split('/')[-1] + description = commit.get('message', '') + matches = ISSUE_BPO_RE.finditer(description) + messages = {} + for match in matches: + data = match.groupdict() + # check for duplicated issue numbers in the same commit msg + if data['issue_id'] in messages: + continue + close = data['verb'] is not None + messages[data['issue_id']] = (COMMENT_TEMPLATE.format( + author=commit.get('committer', {}).get('name', ''), + branch=branch, + changeset_id=commit.get('id', ''), + changeset_url=commit.get('url', ''), + commit_msg=description.splitlines()[0], + ), close) + return messages diff --git a/share/roundup/templates/classic/initial_data.py b/share/roundup/templates/classic/initial_data.py --- a/share/roundup/templates/classic/initial_data.py +++ b/share/roundup/templates/classic/initial_data.py @@ -17,6 +17,13 @@ stat.create(name=''"testing", order="6") stat.create(name=''"done-cbb", order="7") stat.create(name=''"resolved", order="8") +stat.create(name=''"closed", order="9") + +resolution = db.getclass('resolution') +resolution.create(name=''"fixed", order="1") + +stage = db.getclass('stage') +stage.create(name=''"resolved", order="1") # create the two default users user = db.getclass('user') diff --git a/share/roundup/templates/classic/schema.py b/share/roundup/templates/classic/schema.py --- a/share/roundup/templates/classic/schema.py +++ b/share/roundup/templates/classic/schema.py @@ -21,6 +21,20 @@ order=Number()) stat.setkey("name") +# Stage +stage = Class(db, 'stage', + name = String(), + description = String(), + order = Number()) +stage.setkey('name') + +# Resolution +resolution = Class(db, "resolution", + name=String(), + description=String(), + order=Number()) +resolution.setkey('name') + # Keywords keyword = Class(db, "keyword", name=String()) @@ -84,6 +98,8 @@ keyword=Multilink("keyword"), priority=Link("priority"), status=Link("status"), + resolution=Link('resolution'), + stage=Link('stage'), pull_requests=Multilink('pull_request')) # diff --git a/test/data/pushevent.txt b/test/data/pushevent.txt new file mode 100644 --- /dev/null +++ b/test/data/pushevent.txt @@ -0,0 +1,11 @@ +POST /python-dev/pull_request HTTP/1.1 +Host: 3ab1787e.ngrok.io +Accept: */* +User-Agent: GitHub-Hookshot/98ea3cc +X-GitHub-Event: push +X-GitHub-Delivery: 3d4b5180-5c89-11e6-88fd-1aa99d941991 +content-type: application/json +X-Hub-Signature: sha1=c760213ddccd47bf3bbd1735b70c787bb8d07724 +Content-Length: 5852 + +{"ref":"refs/heads/test1","before":"6c5d08240c73014f282bc7336c08fe9ec0b557b0","after":"65c3a074262662a2c55109ff9a2456ee7647fcc9","created":false,"deleted":false,"forced":false,"base_ref":null,"compare":"https://github.com/python/cpython/compare/6c5d08240c73...65c3a0742626","commits":[{"id":"65c3a074262662a2c55109ff9a2456ee7647fcc9","tree_id":"2a35adbb6fce03b51dce23b4ed48526a5a74255a","distinct":true,"message":"#1: fix tests.","timestamp":"2017-01-19T22:19:07+01:00","url":"https://github.com/python/cpython/commit/65c3a074262662a2c55109ff9a2456ee7647fcc9","author":{"name":"Maciej Szulik","email":"soltysh at gmail.com","username":"soltysh"},"committer":{"name":"Maciej Szulik","email":"soltysh at gmail.com","username":"soltysh"},"added":[],"removed":[],"modified":["README"]}],"head_commit":{"id":"65c3a074262662a2c55109ff9a2456ee7647fcc9","tree_id":"2a35adbb6fce03b51dce23b4ed48526a5a74255a","distinct":true,"message":"Fixes#1","timestamp":"2017-01-19T22:19:07+01:00","url":"https://githu b.com/python/cpython/commit/65c3a074262662a2c55109ff9a2456ee7647fcc9","author":{"name":"Maciej Szulik","email":"soltysh at gmail.com","username":"soltysh"},"committer":{"name":"Maciej Szulik","email":"soltysh at gmail.com","username":"soltysh"},"added":[],"removed":[],"modified":["README"]},"repository":{"id":76687672,"name":"cpython","full_name":"python/cpython","owner":{"name":"python"},"private":false,"html_url":"https://github.com/python/cpython","description":"Semi-officialread-onlymirroroftheCPythonMercurialrepository","fork":true,"url":"https://github.com/python/cpython","forks_url":"https://api.github.com/repos/python/cpython/forks","keys_url":"https://api.github.com/repos/python/cpython/keys{/key_id}","collaborators_url":"https://api.github.com/repos/python/cpython/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/python/cpython/teams","hooks_url":"https://api.github.com/repos/python/cpython/hooks","issue_events_url":"https://api.github.com/repos/pyt hon/cpython/issues/events{/number}","events_url":"https://api.github.com/repos/python/cpython/events","assignees_url":"https://api.github.com/repos/python/cpython/assignees{/user}","branches_url":"https://api.github.com/repos/python/cpython/branches{/branch}","tags_url":"https://api.github.com/repos/python/cpython/tags","blobs_url":"https://api.github.com/repos/python/cpython/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/python/cpython/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/python/cpython/git/refs{/sha}","trees_url":"https://api.github.com/repos/python/cpython/git/trees{/sha}","statuses_url":"https://api.github.com/repos/python/cpython/statuses/{sha}","languages_url":"https://api.github.com/repos/python/cpython/languages","stargazers_url":"https://api.github.com/repos/python/cpython/stargazers","contributors_url":"https://api.github.com/repos/python/cpython/contributors","subscribers_url":"https://api.github.com/repos/python/cpython/subs cribers","subscription_url":"https://api.github.com/repos/python/cpython/subscription","commits_url":"https://api.github.com/repos/python/cpython/commits{/sha}","git_commits_url":"https://api.github.com/repos/python/cpython/git/commits{/sha}","comments_url":"https://api.github.com/repos/python/cpython/comments{/number}","issue_comment_url":"https://api.github.com/repos/python/cpython/issues/comments{/number}","contents_url":"https://api.github.com/repos/python/cpython/contents/{+path}","compare_url":"https://api.github.com/repos/python/cpython/compare/{base}...{head}","merges_url":"https://api.github.com/repos/python/cpython/merges","archive_url":"https://api.github.com/repos/python/cpython/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/python/cpython/downloads","issues_url":"https://api.github.com/repos/python/cpython/issues{/number}","pulls_url":"https://api.github.com/repos/python/cpython/pulls{/number}","milestones_url":"https://api.github.com/repo s/python/cpython/milestones{/number}","notifications_url":"https://api.github.com/repos/python/cpython/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/python/cpython/labels{/name}","releases_url":"https://api.github.com/repos/python/cpython/releases{/id}","deployments_url":"https://api.github.com/repos/python/cpython/deployments","created_at":1481924711,"updated_at":"2016-12-16T21:45:35Z","pushed_at":1484860759,"git_url":"git://github.com/python/cpython.git","ssh_url":"git at github.com:python/cpython.git","clone_url":"https://github.com/python/cpython.git","svn_url":"https://github.com/python/cpython","homepage":"","size":269743,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master","stargazers":0,"master_branch":"master"},"pusher":{"name":"sol tysh","email":"soltysh at gmail.com"},"sender":{"login":"soltysh","id":576341,"avatar_url":"https://avatars.githubusercontent.com/u/576341?v=3","gravatar_id":"","url":"https://api.github.com/users/soltysh","html_url":"https://github.com/soltysh","followers_url":"https://api.github.com/users/soltysh/followers","following_url":"https://api.github.com/users/soltysh/following{/other_user}","gists_url":"https://api.github.com/users/soltysh/gists{/gist_id}","starred_url":"https://api.github.com/users/soltysh/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/soltysh/subscriptions","organizations_url":"https://api.github.com/users/soltysh/orgs","repos_url":"https://api.github.com/users/soltysh/repos","events_url":"https://api.github.com/users/soltysh/events{/privacy}","received_events_url":"https://api.github.com/users/soltysh/received_events","type":"User","site_admin":false}} diff --git a/test/data/pushevent1.txt b/test/data/pushevent1.txt new file mode 100644 --- /dev/null +++ b/test/data/pushevent1.txt @@ -0,0 +1,11 @@ +POST /python-dev/pull_request HTTP/1.1 +Host: 3ab1787e.ngrok.io +Accept: */* +User-Agent: GitHub-Hookshot/98ea3cc +X-GitHub-Event: push +X-GitHub-Delivery: 3d4b5180-5c89-11e6-88fd-1aa99d941991 +content-type: application/json +X-Hub-Signature: sha1=764b12621ca4b8ef3f71ce414394e8bfd88efdce +Content-Length: 5860 + +{"ref":"refs/heads/test1","before":"6c5d08240c73014f282bc7336c08fe9ec0b557b0","after":"65c3a074262662a2c55109ff9a2456ee7647fcc9","created":false,"deleted":false,"forced":false,"base_ref":null,"compare":"https://github.com/python/cpython/compare/6c5d08240c73...65c3a0742626","commits":[{"id":"65c3a074262662a2c55109ff9a2456ee7647fcc9","tree_id":"2a35adbb6fce03b51dce23b4ed48526a5a74255a","distinct":true,"message":"closes issue 1: fix tests.","timestamp":"2017-01-19T22:19:07+01:00","url":"https://github.com/python/cpython/commit/65c3a074262662a2c55109ff9a2456ee7647fcc9","author":{"name":"Maciej Szulik","email":"soltysh at gmail.com","username":"soltysh"},"committer":{"name":"Maciej Szulik","email":"soltysh at gmail.com","username":"soltysh"},"added":[],"removed":[],"modified":["README"]}],"head_commit":{"id":"65c3a074262662a2c55109ff9a2456ee7647fcc9","tree_id":"2a35adbb6fce03b51dce23b4ed48526a5a74255a","distinct":true,"message":"Fixes#1","timestamp":"2017-01-19T22:19:07+01:00","url":"h ttps://github.com/python/cpython/commit/65c3a074262662a2c55109ff9a2456ee7647fcc9","author":{"name":"Maciej Szulik","email":"soltysh at gmail.com","username":"soltysh"},"committer":{"name":"Maciej Szulik","email":"soltysh at gmail.com","username":"soltysh"},"added":[],"removed":[],"modified":["README"]},"repository":{"id":76687672,"name":"cpython","full_name":"python/cpython","owner":{"name":"python"},"private":false,"html_url":"https://github.com/python/cpython","description":"Semi-officialread-onlymirroroftheCPythonMercurialrepository","fork":true,"url":"https://github.com/python/cpython","forks_url":"https://api.github.com/repos/python/cpython/forks","keys_url":"https://api.github.com/repos/python/cpython/keys{/key_id}","collaborators_url":"https://api.github.com/repos/python/cpython/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/python/cpython/teams","hooks_url":"https://api.github.com/repos/python/cpython/hooks","issue_events_url":"https://api.github.c om/repos/python/cpython/issues/events{/number}","events_url":"https://api.github.com/repos/python/cpython/events","assignees_url":"https://api.github.com/repos/python/cpython/assignees{/user}","branches_url":"https://api.github.com/repos/python/cpython/branches{/branch}","tags_url":"https://api.github.com/repos/python/cpython/tags","blobs_url":"https://api.github.com/repos/python/cpython/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/python/cpython/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/python/cpython/git/refs{/sha}","trees_url":"https://api.github.com/repos/python/cpython/git/trees{/sha}","statuses_url":"https://api.github.com/repos/python/cpython/statuses/{sha}","languages_url":"https://api.github.com/repos/python/cpython/languages","stargazers_url":"https://api.github.com/repos/python/cpython/stargazers","contributors_url":"https://api.github.com/repos/python/cpython/contributors","subscribers_url":"https://api.github.com/repos/python/ cpython/subscribers","subscription_url":"https://api.github.com/repos/python/cpython/subscription","commits_url":"https://api.github.com/repos/python/cpython/commits{/sha}","git_commits_url":"https://api.github.com/repos/python/cpython/git/commits{/sha}","comments_url":"https://api.github.com/repos/python/cpython/comments{/number}","issue_comment_url":"https://api.github.com/repos/python/cpython/issues/comments{/number}","contents_url":"https://api.github.com/repos/python/cpython/contents/{+path}","compare_url":"https://api.github.com/repos/python/cpython/compare/{base}...{head}","merges_url":"https://api.github.com/repos/python/cpython/merges","archive_url":"https://api.github.com/repos/python/cpython/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/python/cpython/downloads","issues_url":"https://api.github.com/repos/python/cpython/issues{/number}","pulls_url":"https://api.github.com/repos/python/cpython/pulls{/number}","milestones_url":"https://api.git hub.com/repos/python/cpython/milestones{/number}","notifications_url":"https://api.github.com/repos/python/cpython/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/python/cpython/labels{/name}","releases_url":"https://api.github.com/repos/python/cpython/releases{/id}","deployments_url":"https://api.github.com/repos/python/cpython/deployments","created_at":1481924711,"updated_at":"2016-12-16T21:45:35Z","pushed_at":1484860759,"git_url":"git://github.com/python/cpython.git","ssh_url":"git at github.com:python/cpython.git","clone_url":"https://github.com/python/cpython.git","svn_url":"https://github.com/python/cpython","homepage":"","size":269743,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master","stargazers":0,"master_branch":"master"},"pusher": {"name":"soltysh","email":"soltysh at gmail.com"},"sender":{"login":"soltysh","id":576341,"avatar_url":"https://avatars.githubusercontent.com/u/576341?v=3","gravatar_id":"","url":"https://api.github.com/users/soltysh","html_url":"https://github.com/soltysh","followers_url":"https://api.github.com/users/soltysh/followers","following_url":"https://api.github.com/users/soltysh/following{/other_user}","gists_url":"https://api.github.com/users/soltysh/gists{/gist_id}","starred_url":"https://api.github.com/users/soltysh/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/soltysh/subscriptions","organizations_url":"https://api.github.com/users/soltysh/orgs","repos_url":"https://api.github.com/users/soltysh/repos","events_url":"https://api.github.com/users/soltysh/events{/privacy}","received_events_url":"https://api.github.com/users/soltysh/received_events","type":"User","site_admin":false}} diff --git a/test/data/pushevent2.txt b/test/data/pushevent2.txt new file mode 100644 --- /dev/null +++ b/test/data/pushevent2.txt @@ -0,0 +1,11 @@ +POST /python-dev/pull_request HTTP/1.1 +Host: 3ab1787e.ngrok.io +Accept: */* +User-Agent: GitHub-Hookshot/98ea3cc +X-GitHub-Event: push +X-GitHub-Delivery: 3d4b5180-5c89-11e6-88fd-1aa99d941991 +content-type: application/json +X-Hub-Signature: sha1=7e52815fdd264f934d60d0dab305d4d2b198a47d +Content-Length: 6343 + +{"ref":"refs/heads/test1","before":"6c5d08240c73014f282bc7336c08fe9ec0b557b0","after":"65c3a074262662a2c55109ff9a2456ee7647fcc9","created":false,"deleted":false,"forced":false,"base_ref":null,"compare":"https://github.com/python/cpython/compare/6c5d08240c73...65c3a0742626","commits":[{"id":"65c3a074262662a2c55109ff9a2456ee7647fcc9","tree_id":"2a35adbb6fce03b51dce23b4ed48526a5a74255a","distinct":true,"message":"issue 1: fix tests.","timestamp":"2017-01-19T22:19:07+01:00","url":"https://github.com/python/cpython/commit/65c3a074262662a2c55109ff9a2456ee7647fcc9","author":{"name":"Maciej Szulik","email":"soltysh at gmail.com","username":"soltysh"},"committer":{"name":"Maciej Szulik","email":"soltysh at gmail.com","username":"soltysh"},"added":[],"removed":[],"modified":["README"]},{"id":"4488ebcdf2d16393d1a78c4105e4a18e4d0d77af","tree_id":"2a35adbb6fce03b51dce23b4ed48526a5a74255a","distinct":true,"message":"#1: fix else.","timestamp":"2017-01-19T22:19:07+01:00","url":"https://github.co m/python/cpython/commit/4488ebcdf2d16393d1a78c4105e4a18e4d0d77af","author":{"name":"Maciej Szulik","email":"soltysh at gmail.com","username":"soltysh"},"committer":{"name":"Maciej Szulik","email":"soltysh at gmail.com","username":"soltysh"},"added":[],"removed":[],"modified":["README"]}],"head_commit":{"id":"65c3a074262662a2c55109ff9a2456ee7647fcc9","tree_id":"2a35adbb6fce03b51dce23b4ed48526a5a74255a","distinct":true,"message":"Fixes#1","timestamp":"2017-01-19T22:19:07+01:00","url":"https://github.com/python/cpython/commit/65c3a074262662a2c55109ff9a2456ee7647fcc9","author":{"name":"Maciej Szulik","email":"soltysh at gmail.com","username":"soltysh"},"committer":{"name":"Maciej Szulik","email":"soltysh at gmail.com","username":"soltysh"},"added":[],"removed":[],"modified":["README"]},"repository":{"id":76687672,"name":"cpython","full_name":"python/cpython","owner":{"name":"python"},"private":false,"html_url":"https://github.com/python/cpython","description":"Semi-officialread-onlymirrorof theCPythonMercurialrepository","fork":true,"url":"https://github.com/python/cpython","forks_url":"https://api.github.com/repos/python/cpython/forks","keys_url":"https://api.github.com/repos/python/cpython/keys{/key_id}","collaborators_url":"https://api.github.com/repos/python/cpython/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/python/cpython/teams","hooks_url":"https://api.github.com/repos/python/cpython/hooks","issue_events_url":"https://api.github.com/repos/python/cpython/issues/events{/number}","events_url":"https://api.github.com/repos/python/cpython/events","assignees_url":"https://api.github.com/repos/python/cpython/assignees{/user}","branches_url":"https://api.github.com/repos/python/cpython/branches{/branch}","tags_url":"https://api.github.com/repos/python/cpython/tags","blobs_url":"https://api.github.com/repos/python/cpython/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/python/cpython/git/tags{/sha}","git_refs_url":"https: //api.github.com/repos/python/cpython/git/refs{/sha}","trees_url":"https://api.github.com/repos/python/cpython/git/trees{/sha}","statuses_url":"https://api.github.com/repos/python/cpython/statuses/{sha}","languages_url":"https://api.github.com/repos/python/cpython/languages","stargazers_url":"https://api.github.com/repos/python/cpython/stargazers","contributors_url":"https://api.github.com/repos/python/cpython/contributors","subscribers_url":"https://api.github.com/repos/python/cpython/subscribers","subscription_url":"https://api.github.com/repos/python/cpython/subscription","commits_url":"https://api.github.com/repos/python/cpython/commits{/sha}","git_commits_url":"https://api.github.com/repos/python/cpython/git/commits{/sha}","comments_url":"https://api.github.com/repos/python/cpython/comments{/number}","issue_comment_url":"https://api.github.com/repos/python/cpython/issues/comments{/number}","contents_url":"https://api.github.com/repos/python/cpython/contents/{+path}","co mpare_url":"https://api.github.com/repos/python/cpython/compare/{base}...{head}","merges_url":"https://api.github.com/repos/python/cpython/merges","archive_url":"https://api.github.com/repos/python/cpython/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/python/cpython/downloads","issues_url":"https://api.github.com/repos/python/cpython/issues{/number}","pulls_url":"https://api.github.com/repos/python/cpython/pulls{/number}","milestones_url":"https://api.github.com/repos/python/cpython/milestones{/number}","notifications_url":"https://api.github.com/repos/python/cpython/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/python/cpython/labels{/name}","releases_url":"https://api.github.com/repos/python/cpython/releases{/id}","deployments_url":"https://api.github.com/repos/python/cpython/deployments","created_at":1481924711,"updated_at":"2016-12-16T21:45:35Z","pushed_at":1484860759,"git_url":"git://github.com/python/cpython. git","ssh_url":"git at github.com:python/cpython.git","clone_url":"https://github.com/python/cpython.git","svn_url":"https://github.com/python/cpython","homepage":"","size":269743,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master","stargazers":0,"master_branch":"master"},"pusher":{"name":"soltysh","email":"soltysh at gmail.com"},"sender":{"login":"soltysh","id":576341,"avatar_url":"https://avatars.githubusercontent.com/u/576341?v=3","gravatar_id":"","url":"https://api.github.com/users/soltysh","html_url":"https://github.com/soltysh","followers_url":"https://api.github.com/users/soltysh/followers","following_url":"https://api.github.com/users/soltysh/following{/other_user}","gists_url":"https://api.github.com/users/soltysh/gists{/gist_id}","starred_url":"https://api.github.com/use rs/soltysh/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/soltysh/subscriptions","organizations_url":"https://api.github.com/users/soltysh/orgs","repos_url":"https://api.github.com/users/soltysh/repos","events_url":"https://api.github.com/users/soltysh/events{/privacy}","received_events_url":"https://api.github.com/users/soltysh/received_events","type":"User","site_admin":false}} diff --git a/test/data/pushevent3.txt b/test/data/pushevent3.txt new file mode 100644 --- /dev/null +++ b/test/data/pushevent3.txt @@ -0,0 +1,11 @@ +POST /python-dev/pull_request HTTP/1.1 +Host: 3ab1787e.ngrok.io +Accept: */* +User-Agent: GitHub-Hookshot/98ea3cc +X-GitHub-Event: push +X-GitHub-Delivery: 3d4b5180-5c89-11e6-88fd-1aa99d941991 +content-type: application/json +X-Hub-Signature: sha1=c521799f81bd30df0a672bfdfb5959ad55ccbb63 +Content-Length: 6351 + +{"ref":"refs/heads/test1","before":"6c5d08240c73014f282bc7336c08fe9ec0b557b0","after":"65c3a074262662a2c55109ff9a2456ee7647fcc9","created":false,"deleted":false,"forced":false,"base_ref":null,"compare":"https://github.com/python/cpython/compare/6c5d08240c73...65c3a0742626","commits":[{"id":"65c3a074262662a2c55109ff9a2456ee7647fcc9","tree_id":"2a35adbb6fce03b51dce23b4ed48526a5a74255a","distinct":true,"message":"closing issue 1: fix tests.","timestamp":"2017-01-19T22:19:07+01:00","url":"https://github.com/python/cpython/commit/65c3a074262662a2c55109ff9a2456ee7647fcc9","author":{"name":"Maciej Szulik","email":"soltysh at gmail.com","username":"soltysh"},"committer":{"name":"Maciej Szulik","email":"soltysh at gmail.com","username":"soltysh"},"added":[],"removed":[],"modified":["README"]},{"id":"4488ebcdf2d16393d1a78c4105e4a18e4d0d77af","tree_id":"2a35adbb6fce03b51dce23b4ed48526a5a74255a","distinct":true,"message":"#1: fix else.","timestamp":"2017-01-19T22:19:07+01:00","url":"https://g ithub.com/python/cpython/commit/4488ebcdf2d16393d1a78c4105e4a18e4d0d77af","author":{"name":"Maciej Szulik","email":"soltysh at gmail.com","username":"soltysh"},"committer":{"name":"Maciej Szulik","email":"soltysh at gmail.com","username":"soltysh"},"added":[],"removed":[],"modified":["README"]}],"head_commit":{"id":"65c3a074262662a2c55109ff9a2456ee7647fcc9","tree_id":"2a35adbb6fce03b51dce23b4ed48526a5a74255a","distinct":true,"message":"Fixes#1","timestamp":"2017-01-19T22:19:07+01:00","url":"https://github.com/python/cpython/commit/65c3a074262662a2c55109ff9a2456ee7647fcc9","author":{"name":"Maciej Szulik","email":"soltysh at gmail.com","username":"soltysh"},"committer":{"name":"Maciej Szulik","email":"soltysh at gmail.com","username":"soltysh"},"added":[],"removed":[],"modified":["README"]},"repository":{"id":76687672,"name":"cpython","full_name":"python/cpython","owner":{"name":"python"},"private":false,"html_url":"https://github.com/python/cpython","description":"Semi-officialread-only mirroroftheCPythonMercurialrepository","fork":true,"url":"https://github.com/python/cpython","forks_url":"https://api.github.com/repos/python/cpython/forks","keys_url":"https://api.github.com/repos/python/cpython/keys{/key_id}","collaborators_url":"https://api.github.com/repos/python/cpython/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/python/cpython/teams","hooks_url":"https://api.github.com/repos/python/cpython/hooks","issue_events_url":"https://api.github.com/repos/python/cpython/issues/events{/number}","events_url":"https://api.github.com/repos/python/cpython/events","assignees_url":"https://api.github.com/repos/python/cpython/assignees{/user}","branches_url":"https://api.github.com/repos/python/cpython/branches{/branch}","tags_url":"https://api.github.com/repos/python/cpython/tags","blobs_url":"https://api.github.com/repos/python/cpython/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/python/cpython/git/tags{/sha}","git_refs_url" :"https://api.github.com/repos/python/cpython/git/refs{/sha}","trees_url":"https://api.github.com/repos/python/cpython/git/trees{/sha}","statuses_url":"https://api.github.com/repos/python/cpython/statuses/{sha}","languages_url":"https://api.github.com/repos/python/cpython/languages","stargazers_url":"https://api.github.com/repos/python/cpython/stargazers","contributors_url":"https://api.github.com/repos/python/cpython/contributors","subscribers_url":"https://api.github.com/repos/python/cpython/subscribers","subscription_url":"https://api.github.com/repos/python/cpython/subscription","commits_url":"https://api.github.com/repos/python/cpython/commits{/sha}","git_commits_url":"https://api.github.com/repos/python/cpython/git/commits{/sha}","comments_url":"https://api.github.com/repos/python/cpython/comments{/number}","issue_comment_url":"https://api.github.com/repos/python/cpython/issues/comments{/number}","contents_url":"https://api.github.com/repos/python/cpython/contents/{+pa th}","compare_url":"https://api.github.com/repos/python/cpython/compare/{base}...{head}","merges_url":"https://api.github.com/repos/python/cpython/merges","archive_url":"https://api.github.com/repos/python/cpython/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/python/cpython/downloads","issues_url":"https://api.github.com/repos/python/cpython/issues{/number}","pulls_url":"https://api.github.com/repos/python/cpython/pulls{/number}","milestones_url":"https://api.github.com/repos/python/cpython/milestones{/number}","notifications_url":"https://api.github.com/repos/python/cpython/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/python/cpython/labels{/name}","releases_url":"https://api.github.com/repos/python/cpython/releases{/id}","deployments_url":"https://api.github.com/repos/python/cpython/deployments","created_at":1481924711,"updated_at":"2016-12-16T21:45:35Z","pushed_at":1484860759,"git_url":"git://github.com/python/ cpython.git","ssh_url":"git at github.com:python/cpython.git","clone_url":"https://github.com/python/cpython.git","svn_url":"https://github.com/python/cpython","homepage":"","size":269743,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master","stargazers":0,"master_branch":"master"},"pusher":{"name":"soltysh","email":"soltysh at gmail.com"},"sender":{"login":"soltysh","id":576341,"avatar_url":"https://avatars.githubusercontent.com/u/576341?v=3","gravatar_id":"","url":"https://api.github.com/users/soltysh","html_url":"https://github.com/soltysh","followers_url":"https://api.github.com/users/soltysh/followers","following_url":"https://api.github.com/users/soltysh/following{/other_user}","gists_url":"https://api.github.com/users/soltysh/gists{/gist_id}","starred_url":"https://api.github .com/users/soltysh/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/soltysh/subscriptions","organizations_url":"https://api.github.com/users/soltysh/orgs","repos_url":"https://api.github.com/users/soltysh/repos","events_url":"https://api.github.com/users/soltysh/events{/privacy}","received_events_url":"https://api.github.com/users/soltysh/received_events","type":"User","site_admin":false}} diff --git a/test/data/pushevent4.txt b/test/data/pushevent4.txt new file mode 100644 --- /dev/null +++ b/test/data/pushevent4.txt @@ -0,0 +1,11 @@ +POST /python-dev/pull_request HTTP/1.1 +Host: 3ab1787e.ngrok.io +Accept: */* +User-Agent: GitHub-Hookshot/98ea3cc +X-GitHub-Event: push +X-GitHub-Delivery: 3d4b5180-5c89-11e6-88fd-1aa99d941991 +content-type: application/json +X-Hub-Signature: sha1=9975ce076f3f00558539390b1dc464385b8ae5bb +Content-Length: 6353 + +{"ref":"refs/heads/test1","before":"6c5d08240c73014f282bc7336c08fe9ec0b557b0","after":"65c3a074262662a2c55109ff9a2456ee7647fcc9","created":false,"deleted":false,"forced":false,"base_ref":null,"compare":"https://github.com/python/cpython/compare/6c5d08240c73...65c3a0742626","commits":[{"id":"65c3a074262662a2c55109ff9a2456ee7647fcc9","tree_id":"2a35adbb6fce03b51dce23b4ed48526a5a74255a","distinct":true,"message":"closes issue 1: fix tests.","timestamp":"2017-01-19T22:19:07+01:00","url":"https://github.com/python/cpython/commit/65c3a074262662a2c55109ff9a2456ee7647fcc9","author":{"name":"Maciej Szulik","email":"soltysh at gmail.com","username":"soltysh"},"committer":{"name":"Maciej Szulik","email":"soltysh at gmail.com","username":"soltysh"},"added":[],"removed":[],"modified":["README"]},{"id":"4488ebcdf2d16393d1a78c4105e4a18e4d0d77af","tree_id":"2a35adbb6fce03b51dce23b4ed48526a5a74255a","distinct":true,"message":"bug 2: fix else.","timestamp":"2017-01-19T22:19:07+01:00","url":"https:/ /github.com/python/cpython/commit/4488ebcdf2d16393d1a78c4105e4a18e4d0d77af","author":{"name":"Maciej Szulik","email":"soltysh at gmail.com","username":"soltysh"},"committer":{"name":"Maciej Szulik","email":"soltysh at gmail.com","username":"soltysh"},"added":[],"removed":[],"modified":["README"]}],"head_commit":{"id":"65c3a074262662a2c55109ff9a2456ee7647fcc9","tree_id":"2a35adbb6fce03b51dce23b4ed48526a5a74255a","distinct":true,"message":"Fixes#1","timestamp":"2017-01-19T22:19:07+01:00","url":"https://github.com/python/cpython/commit/65c3a074262662a2c55109ff9a2456ee7647fcc9","author":{"name":"Maciej Szulik","email":"soltysh at gmail.com","username":"soltysh"},"committer":{"name":"Maciej Szulik","email":"soltysh at gmail.com","username":"soltysh"},"added":[],"removed":[],"modified":["README"]},"repository":{"id":76687672,"name":"cpython","full_name":"python/cpython","owner":{"name":"python"},"private":false,"html_url":"https://github.com/python/cpython","description":"Semi-officialread-on lymirroroftheCPythonMercurialrepository","fork":true,"url":"https://github.com/python/cpython","forks_url":"https://api.github.com/repos/python/cpython/forks","keys_url":"https://api.github.com/repos/python/cpython/keys{/key_id}","collaborators_url":"https://api.github.com/repos/python/cpython/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/python/cpython/teams","hooks_url":"https://api.github.com/repos/python/cpython/hooks","issue_events_url":"https://api.github.com/repos/python/cpython/issues/events{/number}","events_url":"https://api.github.com/repos/python/cpython/events","assignees_url":"https://api.github.com/repos/python/cpython/assignees{/user}","branches_url":"https://api.github.com/repos/python/cpython/branches{/branch}","tags_url":"https://api.github.com/repos/python/cpython/tags","blobs_url":"https://api.github.com/repos/python/cpython/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/python/cpython/git/tags{/sha}","git_refs_ur l":"https://api.github.com/repos/python/cpython/git/refs{/sha}","trees_url":"https://api.github.com/repos/python/cpython/git/trees{/sha}","statuses_url":"https://api.github.com/repos/python/cpython/statuses/{sha}","languages_url":"https://api.github.com/repos/python/cpython/languages","stargazers_url":"https://api.github.com/repos/python/cpython/stargazers","contributors_url":"https://api.github.com/repos/python/cpython/contributors","subscribers_url":"https://api.github.com/repos/python/cpython/subscribers","subscription_url":"https://api.github.com/repos/python/cpython/subscription","commits_url":"https://api.github.com/repos/python/cpython/commits{/sha}","git_commits_url":"https://api.github.com/repos/python/cpython/git/commits{/sha}","comments_url":"https://api.github.com/repos/python/cpython/comments{/number}","issue_comment_url":"https://api.github.com/repos/python/cpython/issues/comments{/number}","contents_url":"https://api.github.com/repos/python/cpython/contents/{+ path}","compare_url":"https://api.github.com/repos/python/cpython/compare/{base}...{head}","merges_url":"https://api.github.com/repos/python/cpython/merges","archive_url":"https://api.github.com/repos/python/cpython/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/python/cpython/downloads","issues_url":"https://api.github.com/repos/python/cpython/issues{/number}","pulls_url":"https://api.github.com/repos/python/cpython/pulls{/number}","milestones_url":"https://api.github.com/repos/python/cpython/milestones{/number}","notifications_url":"https://api.github.com/repos/python/cpython/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/python/cpython/labels{/name}","releases_url":"https://api.github.com/repos/python/cpython/releases{/id}","deployments_url":"https://api.github.com/repos/python/cpython/deployments","created_at":1481924711,"updated_at":"2016-12-16T21:45:35Z","pushed_at":1484860759,"git_url":"git://github.com/pytho n/cpython.git","ssh_url":"git at github.com:python/cpython.git","clone_url":"https://github.com/python/cpython.git","svn_url":"https://github.com/python/cpython","homepage":"","size":269743,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master","stargazers":0,"master_branch":"master"},"pusher":{"name":"soltysh","email":"soltysh at gmail.com"},"sender":{"login":"soltysh","id":576341,"avatar_url":"https://avatars.githubusercontent.com/u/576341?v=3","gravatar_id":"","url":"https://api.github.com/users/soltysh","html_url":"https://github.com/soltysh","followers_url":"https://api.github.com/users/soltysh/followers","following_url":"https://api.github.com/users/soltysh/following{/other_user}","gists_url":"https://api.github.com/users/soltysh/gists{/gist_id}","starred_url":"https://api.gith ub.com/users/soltysh/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/soltysh/subscriptions","organizations_url":"https://api.github.com/users/soltysh/orgs","repos_url":"https://api.github.com/users/soltysh/repos","events_url":"https://api.github.com/users/soltysh/events{/privacy}","received_events_url":"https://api.github.com/users/soltysh/received_events","type":"User","site_admin":false}} diff --git a/test/test_github.py b/test/test_github.py --- a/test/test_github.py +++ b/test/test_github.py @@ -296,6 +296,125 @@ status = self.db.pull_request.get(prs[0], 'status') self.assertEqual(status, 'closed') + def testPushEventAddsComment(self): + dummy_client = self._make_client('pushevent.txt') + handler = GitHubHandler(dummy_client) + handler.dispatch() + msgs = self.db.issue.get('1', 'messages') + self.assertEqual(len(msgs), 1) + content = self.db.msg.get(msgs[0], 'content') + self.assertIn("""New changeset 65c3a074262662a2c55109ff9a2456ee7647fcc9 by Maciej Szulik in branch 'test1': +#1: fix tests. +https://github.com/python/cpython/commit/65c3a074262662a2c55109ff9a2456ee7647fcc9 +""", + content) + # issue status + status = self.db.issue.get('1', 'status') + self.assertNotEqual(self.db.status.get(status, 'name'), 'closed') + self.assertIsNone(self.db.issue.get('1', 'resolution')) + self.assertIsNone(self.db.issue.get('1', 'stage')) + + def testPushEventAddsCommentAndClose(self): + dummy_client = self._make_client('pushevent1.txt') + handler = GitHubHandler(dummy_client) + handler.dispatch() + msgs = self.db.issue.get('1', 'messages') + self.assertEqual(len(msgs), 1) + content = self.db.msg.get(msgs[0], 'content') + self.assertIn("""New changeset 65c3a074262662a2c55109ff9a2456ee7647fcc9 by Maciej Szulik in branch 'test1': +closes issue 1: fix tests. +https://github.com/python/cpython/commit/65c3a074262662a2c55109ff9a2456ee7647fcc9 +""", + content) + # issue status + status = self.db.issue.get('1', 'status') + self.assertEqual(self.db.status.get(status, 'name'), 'closed') + resolution = self.db.issue.get('1', 'resolution') + self.assertEqual(self.db.resolution.get(resolution, 'name'), 'fixed') + stage = self.db.issue.get('1', 'stage') + self.assertEqual(self.db.stage.get(stage, 'name'), 'resolved') + + def testPushEventWithMultipleCommitsSingleIssue(self): + dummy_client = self._make_client('pushevent2.txt') + handler = GitHubHandler(dummy_client) + handler.dispatch() + msgs = self.db.issue.get('1', 'messages') + self.assertEqual(len(msgs), 1) + content = self.db.msg.get(msgs[0], 'content') + self.assertIn("""New changeset 65c3a074262662a2c55109ff9a2456ee7647fcc9 by Maciej Szulik in branch 'test1': +issue 1: fix tests. +https://github.com/python/cpython/commit/65c3a074262662a2c55109ff9a2456ee7647fcc9 + +New changeset 4488ebcdf2d16393d1a78c4105e4a18e4d0d77af by Maciej Szulik in branch 'test1': +#1: fix else. +https://github.com/python/cpython/commit/4488ebcdf2d16393d1a78c4105e4a18e4d0d77af +""", + content) + # issue status + status = self.db.issue.get('1', 'status') + self.assertNotEqual(self.db.status.get(status, 'name'), 'closed') + self.assertIsNone(self.db.issue.get('1', 'resolution')) + self.assertIsNone(self.db.issue.get('1', 'stage')) + + def testPushEventWithMultipleCommitsSingleIssueAndClose(self): + dummy_client = self._make_client('pushevent3.txt') + handler = GitHubHandler(dummy_client) + handler.dispatch() + msgs = self.db.issue.get('1', 'messages') + self.assertEqual(len(msgs), 1) + content = self.db.msg.get(msgs[0], 'content') + self.assertIn("""New changeset 65c3a074262662a2c55109ff9a2456ee7647fcc9 by Maciej Szulik in branch 'test1': +closing issue 1: fix tests. +https://github.com/python/cpython/commit/65c3a074262662a2c55109ff9a2456ee7647fcc9 + +New changeset 4488ebcdf2d16393d1a78c4105e4a18e4d0d77af by Maciej Szulik in branch 'test1': +#1: fix else. +https://github.com/python/cpython/commit/4488ebcdf2d16393d1a78c4105e4a18e4d0d77af +""", + content) + # issue status + status = self.db.issue.get('1', 'status') + self.assertEqual(self.db.status.get(status, 'name'), 'closed') + resolution = self.db.issue.get('1', 'resolution') + self.assertEqual(self.db.resolution.get(resolution, 'name'), 'fixed') + stage = self.db.issue.get('1', 'stage') + self.assertEqual(self.db.stage.get(stage, 'name'), 'resolved') + + def testPushEventWithMultipleCommitsMultipleIssues(self): + dummy_client = self._make_client('pushevent4.txt') + self.db.issue.create(title="Issue 2") + handler = GitHubHandler(dummy_client) + handler.dispatch() + # first issue messages + msgs = self.db.issue.get('1', 'messages') + self.assertEqual(len(msgs), 1) + content = self.db.msg.get(msgs[0], 'content') + self.assertIn("""New changeset 65c3a074262662a2c55109ff9a2456ee7647fcc9 by Maciej Szulik in branch 'test1': +closes issue 1: fix tests. +https://github.com/python/cpython/commit/65c3a074262662a2c55109ff9a2456ee7647fcc9 +""", + content) + # first issue status + status = self.db.issue.get('1', 'status') + self.assertEqual(self.db.status.get(status, 'name'), 'closed') + resolution = self.db.issue.get('1', 'resolution') + self.assertEqual(self.db.resolution.get(resolution, 'name'), 'fixed') + stage = self.db.issue.get('1', 'stage') + self.assertEqual(self.db.stage.get(stage, 'name'), 'resolved') + # second issue messages + msgs = self.db.issue.get('2', 'messages') + self.assertEqual(len(msgs), 1) + content = self.db.msg.get(msgs[0], 'content') + self.assertIn("""New changeset 4488ebcdf2d16393d1a78c4105e4a18e4d0d77af by Maciej Szulik in branch 'test1': +bug 2: fix else. +https://github.com/python/cpython/commit/4488ebcdf2d16393d1a78c4105e4a18e4d0d77af +""", + content) + # second issue status + status = self.db.issue.get('2', 'status') + self.assertNotEqual(self.db.status.get(status, 'name'), 'closed') + self.assertIsNone(self.db.issue.get('2', 'resolution')) + self.assertIsNone(self.db.issue.get('2', 'stage')) def test_suite(): suite = unittest.TestSuite() From metatracker at psf.upfronthosting.co.za Mon Jan 30 16:13:01 2017 From: metatracker at psf.upfronthosting.co.za (Maciej Szulik) Date: Mon, 30 Jan 2017 21:13:01 +0000 Subject: [Tracker-discuss] [issue611] Update issue with a commit information In-Reply-To: <1485224514.2.0.124865035832.issue611@psf.upfronthosting.co.za> Message-ID: <1485810781.34.0.928020070094.issue611@psf.upfronthosting.co.za> Maciej Szulik added the comment: Committed in https://hg.python.org/tracker/roundup/rev/bcf18f92716d. ---------- status: in-progress -> testing _______________________________________________________ PSF Meta Tracker _______________________________________________________