From ca2c173dd8b9d13cbd04a91638aff843b84522c8 Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Wed, 25 Nov 2015 17:05:57 -0500 Subject: [PATCH 01/12] Implement dynamic handler registration. --- eventhandler.py | 30 ++++++++++++++++++++++++++++++ newpr.py | 9 +++++++++ 2 files changed, 39 insertions(+) create mode 100644 eventhandler.py diff --git a/eventhandler.py b/eventhandler.py new file mode 100644 index 0000000..d422e99 --- /dev/null +++ b/eventhandler.py @@ -0,0 +1,30 @@ +import imp +import os + +class EventHandler: + def on_pr_opened(self, api, payload): + pass + + def on_pr_updated(self, api, payload): + pass + + def on_new_comment(self, api, payload): + pass + +def get_handlers(): + modules = [] + handlers = [] + possiblehandlers = os.listdir('handlers') + for i in possiblehandlers: + location = os.path.join('handlers', i) + module = '__init__' + if not os.path.isdir(location) or not module + ".py" in os.listdir(location): + continue + try: + (file, pathname, description) = imp.find_module(module, [location]) + module = imp.load_module(module, file, pathname, description) + handlers.append(module.handler_interface()) + modules.append(module) + finally: + file.close() + return (modules, handlers) diff --git a/newpr.py b/newpr.py index 929cb6e..9f80320 100755 --- a/newpr.py +++ b/newpr.py @@ -1,6 +1,7 @@ #!/usr/bin/env python import base64 +import eventhandler import urllib, urllib2 import cgi import cgitb @@ -296,12 +297,20 @@ def update_pr(api, payload): def handle_payload(api, payload): + (modules, handlers) = eventhandler.get_handlers() + if payload["action"] == "opened": new_pr(api, payload) + for handler in handlers: + handler.on_pr_opened(api, payload) elif payload["action"] == "synchronize": update_pr(api, payload) + for handler in handlers: + handler.on_pr_updated(api, payload) elif payload["action"] == "created": new_comment(api, payload) + for handler in handlers: + handler.on_new_comment(api, payload) else: pass From f991b7c25d9975d4a39a9de567ed4a8eac70c494 Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Wed, 25 Nov 2015 17:07:36 -0500 Subject: [PATCH 02/12] Convert welcome message. --- handlers/welcome/__init__.py | 21 +++++++++++++++++++++ newpr.py | 9 --------- 2 files changed, 21 insertions(+), 9 deletions(-) create mode 100644 handlers/welcome/__init__.py diff --git a/handlers/welcome/__init__.py b/handlers/welcome/__init__.py new file mode 100644 index 0000000..0bf8f3e --- /dev/null +++ b/handlers/welcome/__init__.py @@ -0,0 +1,21 @@ +from eventhandler import EventHandler +import random + +welcome_msg = "Thanks for the pull request, and welcome! The Servo team is excited to review your changes, and you should hear from @%s (or someone else) soon." + +class WelcomeHandler(EventHandler): + def on_pr_opened(self, api, payload): + author = payload["pull_request"]['user']['login'] + if api.is_new_contributor(author): + collaborators = ['jdm', 'larsbergstrom', 'metajack', 'mbrubeck', + 'Ms2ger', 'Manishearth', 'glennw', 'pcwalton', + 'SimonSapin'] \ + if api.repo == 'servo' and api.owner == 'servo' \ + else ['test_user_selection_ignore_this'] + random.seed() + to_notify = random.choice(collaborators) + api.post_comment(welcome_msg % to_notify) + + +handler_interface = WelcomeHandler + diff --git a/newpr.py b/newpr.py index 9f80320..b7160ee 100755 --- a/newpr.py +++ b/newpr.py @@ -184,7 +184,6 @@ def find_reviewer(commit_msg): return match.group(1) -welcome_msg = "Thanks for the pull request, and welcome! The Servo team is excited to review your changes, and you should hear from @%s (or someone else) soon." warning_summary = 'warning **Warning** warning\n\n%s' unsafe_warning_msg = 'These commits modify **unsafe code**. Please review it carefully!' reftest_required_msg = 'These commits modify layout code, but no reftests are modified. Please consider adding a reftest!' @@ -258,14 +257,6 @@ def new_comment(api, payload): def new_pr(api, payload): manage_pr_state(api, payload) - author = payload["pull_request"]['user']['login'] - if api.is_new_contributor(author): - #collaborators = json.load(urllib2.urlopen(collaborators_url)) - collaborators = ['jdm', 'larsbergstrom', 'metajack', 'mbrubeck', 'Ms2ger', 'Manishearth', 'glennw', 'pcwalton', 'SimonSapin'] if api.repo == 'servo' and api.owner == 'servo' else ['test_user_selection_ignore_this'] - random.seed() - to_notify = random.choice(collaborators) - api.post_comment(welcome_msg % to_notify) - warn_unsafe = False layout_changed = False saw_reftest = False From edd76e9f10c1d71ecde2a9fde1ba734ea1f91a83 Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Thu, 26 Nov 2015 14:50:59 -0500 Subject: [PATCH 03/12] Allow handlers to automatically register tests in a tests subdirectory. Create a new test format that includes initial and expected values, causing only the listed expected values to be checked. --- eventhandler.py | 14 +- handlers/welcome/tests/new_pr.json | 432 +++++++++++++++++++++++++++++ test.py | 95 ++++--- 3 files changed, 501 insertions(+), 40 deletions(-) create mode 100644 handlers/welcome/tests/new_pr.json diff --git a/eventhandler.py b/eventhandler.py index d422e99..64d676e 100644 --- a/eventhandler.py +++ b/eventhandler.py @@ -1,4 +1,5 @@ import imp +import json import os class EventHandler: @@ -11,6 +12,17 @@ def on_pr_updated(self, api, payload): def on_new_comment(self, api, payload): pass + def register_tests(self, path): + from test import create_test + tests_location = os.path.join(path, 'tests') + if not os.path.isdir(tests_location): + return + tests = [os.path.join(tests_location, f) for f in os.listdir(tests_location) if f.endswith('.json')] + for testfile in tests: + with open(testfile) as f: + contents = json.load(f) + yield create_test(testfile, contents['initial'], contents['expected'], True) + def get_handlers(): modules = [] handlers = [] @@ -24,7 +36,7 @@ def get_handlers(): (file, pathname, description) = imp.find_module(module, [location]) module = imp.load_module(module, file, pathname, description) handlers.append(module.handler_interface()) - modules.append(module) + modules.append((module, location)) finally: file.close() return (modules, handlers) diff --git a/handlers/welcome/tests/new_pr.json b/handlers/welcome/tests/new_pr.json new file mode 100644 index 0000000..cfcc1cb --- /dev/null +++ b/handlers/welcome/tests/new_pr.json @@ -0,0 +1,432 @@ +{ + "initial": { + "new_contributor": true + }, + "expected": { + "comments": 1 + }, + "payload": +{ + "action": "opened", + "number": 7076, + "pull_request": { + "url": "https://api.github.com/repos/servo/servo/pulls/7076", + "id": 41896942, + "html_url": "https://github.com/servo/servo/pull/7076", + "diff_url": "https://github.com/servo/servo/pull/7076.diff", + "patch_url": "https://github.com/servo/servo/pull/7076.patch", + "issue_url": "https://api.github.com/repos/servo/servo/issues/7076", + "number": 7076, + "state": "open", + "locked": false, + "title": "Remove invalid file path in ignored_files for tidying", + "user": { + "login": "frewsxcv", + "id": 416575, + "avatar_url": "https://avatars.githubusercontent.com/u/416575?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/frewsxcv", + "html_url": "https://github.com/frewsxcv", + "followers_url": "https://api.github.com/users/frewsxcv/followers", + "following_url": "https://api.github.com/users/frewsxcv/following{/other_user}", + "gists_url": "https://api.github.com/users/frewsxcv/gists{/gist_id}", + "starred_url": "https://api.github.com/users/frewsxcv/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/frewsxcv/subscriptions", + "organizations_url": "https://api.github.com/users/frewsxcv/orgs", + "repos_url": "https://api.github.com/users/frewsxcv/repos", + "events_url": "https://api.github.com/users/frewsxcv/events{/privacy}", + "received_events_url": "https://api.github.com/users/frewsxcv/received_events", + "type": "User", + "site_admin": false + }, + "body": null, + "created_at": "2015-08-07T14:24:50Z", + "updated_at": "2015-08-07T14:24:50Z", + "closed_at": null, + "merged_at": null, + "merge_commit_sha": null, + "assignee": null, + "milestone": null, + "commits_url": "https://api.github.com/repos/servo/servo/pulls/7076/commits", + "review_comments_url": "https://api.github.com/repos/servo/servo/pulls/7076/comments", + "review_comment_url": "https://api.github.com/repos/servo/servo/pulls/comments{/number}", + "comments_url": "https://api.github.com/repos/servo/servo/issues/7076/comments", + "statuses_url": "https://api.github.com/repos/servo/servo/statuses/da44f31cb1debe2c8161ee280121d79d3dd5ec18", + "head": { + "label": "frewsxcv:tidy-rm-invalid-file", + "ref": "tidy-rm-invalid-file", + "sha": "da44f31cb1debe2c8161ee280121d79d3dd5ec18", + "user": { + "login": "frewsxcv", + "id": 416575, + "avatar_url": "https://avatars.githubusercontent.com/u/416575?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/frewsxcv", + "html_url": "https://github.com/frewsxcv", + "followers_url": "https://api.github.com/users/frewsxcv/followers", + "following_url": "https://api.github.com/users/frewsxcv/following{/other_user}", + "gists_url": "https://api.github.com/users/frewsxcv/gists{/gist_id}", + "starred_url": "https://api.github.com/users/frewsxcv/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/frewsxcv/subscriptions", + "organizations_url": "https://api.github.com/users/frewsxcv/orgs", + "repos_url": "https://api.github.com/users/frewsxcv/repos", + "events_url": "https://api.github.com/users/frewsxcv/events{/privacy}", + "received_events_url": "https://api.github.com/users/frewsxcv/received_events", + "type": "User", + "site_admin": false + }, + "repo": { + "id": 27014207, + "name": "servo", + "full_name": "frewsxcv/servo", + "owner": { + "login": "frewsxcv", + "id": 416575, + "avatar_url": "https://avatars.githubusercontent.com/u/416575?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/frewsxcv", + "html_url": "https://github.com/frewsxcv", + "followers_url": "https://api.github.com/users/frewsxcv/followers", + "following_url": "https://api.github.com/users/frewsxcv/following{/other_user}", + "gists_url": "https://api.github.com/users/frewsxcv/gists{/gist_id}", + "starred_url": "https://api.github.com/users/frewsxcv/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/frewsxcv/subscriptions", + "organizations_url": "https://api.github.com/users/frewsxcv/orgs", + "repos_url": "https://api.github.com/users/frewsxcv/repos", + "events_url": "https://api.github.com/users/frewsxcv/events{/privacy}", + "received_events_url": "https://api.github.com/users/frewsxcv/received_events", + "type": "User", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/frewsxcv/servo", + "description": "The Servo Browser Engine", + "fork": true, + "url": "https://api.github.com/repos/frewsxcv/servo", + "forks_url": "https://api.github.com/repos/frewsxcv/servo/forks", + "keys_url": "https://api.github.com/repos/frewsxcv/servo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/frewsxcv/servo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/frewsxcv/servo/teams", + "hooks_url": "https://api.github.com/repos/frewsxcv/servo/hooks", + "issue_events_url": "https://api.github.com/repos/frewsxcv/servo/issues/events{/number}", + "events_url": "https://api.github.com/repos/frewsxcv/servo/events", + "assignees_url": "https://api.github.com/repos/frewsxcv/servo/assignees{/user}", + "branches_url": "https://api.github.com/repos/frewsxcv/servo/branches{/branch}", + "tags_url": "https://api.github.com/repos/frewsxcv/servo/tags", + "blobs_url": "https://api.github.com/repos/frewsxcv/servo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/frewsxcv/servo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/frewsxcv/servo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/frewsxcv/servo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/frewsxcv/servo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/frewsxcv/servo/languages", + "stargazers_url": "https://api.github.com/repos/frewsxcv/servo/stargazers", + "contributors_url": "https://api.github.com/repos/frewsxcv/servo/contributors", + "subscribers_url": "https://api.github.com/repos/frewsxcv/servo/subscribers", + "subscription_url": "https://api.github.com/repos/frewsxcv/servo/subscription", + "commits_url": "https://api.github.com/repos/frewsxcv/servo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/frewsxcv/servo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/frewsxcv/servo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/frewsxcv/servo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/frewsxcv/servo/contents/{+path}", + "compare_url": "https://api.github.com/repos/frewsxcv/servo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/frewsxcv/servo/merges", + "archive_url": "https://api.github.com/repos/frewsxcv/servo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/frewsxcv/servo/downloads", + "issues_url": "https://api.github.com/repos/frewsxcv/servo/issues{/number}", + "pulls_url": "https://api.github.com/repos/frewsxcv/servo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/frewsxcv/servo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/frewsxcv/servo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/frewsxcv/servo/labels{/name}", + "releases_url": "https://api.github.com/repos/frewsxcv/servo/releases{/id}", + "created_at": "2014-11-22T22:10:35Z", + "updated_at": "2014-11-22T22:10:38Z", + "pushed_at": "2015-08-07T14:24:45Z", + "git_url": "git://github.com/frewsxcv/servo.git", + "ssh_url": "git@github.com:frewsxcv/servo.git", + "clone_url": "https://github.com/frewsxcv/servo.git", + "svn_url": "https://github.com/frewsxcv/servo", + "homepage": "", + "size": 119557, + "stargazers_count": 0, + "watchers_count": 0, + "language": "Rust", + "has_issues": false, + "has_downloads": true, + "has_wiki": true, + "has_pages": true, + "forks_count": 0, + "mirror_url": null, + "open_issues_count": 0, + "forks": 0, + "open_issues": 0, + "watchers": 0, + "default_branch": "master" + } + }, + "base": { + "label": "servo:master", + "ref": "master", + "sha": "b4e30da3dbf58c16703864f4bec4b0b0132084fa", + "user": { + "login": "servo", + "id": 2566135, + "avatar_url": "https://avatars.githubusercontent.com/u/2566135?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/servo", + "html_url": "https://github.com/servo", + "followers_url": "https://api.github.com/users/servo/followers", + "following_url": "https://api.github.com/users/servo/following{/other_user}", + "gists_url": "https://api.github.com/users/servo/gists{/gist_id}", + "starred_url": "https://api.github.com/users/servo/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/servo/subscriptions", + "organizations_url": "https://api.github.com/users/servo/orgs", + "repos_url": "https://api.github.com/users/servo/repos", + "events_url": "https://api.github.com/users/servo/events{/privacy}", + "received_events_url": "https://api.github.com/users/servo/received_events", + "type": "Organization", + "site_admin": false + }, + "repo": { + "id": 3390243, + "name": "servo", + "full_name": "servo/servo", + "owner": { + "login": "servo", + "id": 2566135, + "avatar_url": "https://avatars.githubusercontent.com/u/2566135?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/servo", + "html_url": "https://github.com/servo", + "followers_url": "https://api.github.com/users/servo/followers", + "following_url": "https://api.github.com/users/servo/following{/other_user}", + "gists_url": "https://api.github.com/users/servo/gists{/gist_id}", + "starred_url": "https://api.github.com/users/servo/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/servo/subscriptions", + "organizations_url": "https://api.github.com/users/servo/orgs", + "repos_url": "https://api.github.com/users/servo/repos", + "events_url": "https://api.github.com/users/servo/events{/privacy}", + "received_events_url": "https://api.github.com/users/servo/received_events", + "type": "Organization", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/servo/servo", + "description": "The Servo Browser Engine", + "fork": false, + "url": "https://api.github.com/repos/servo/servo", + "forks_url": "https://api.github.com/repos/servo/servo/forks", + "keys_url": "https://api.github.com/repos/servo/servo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/servo/servo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/servo/servo/teams", + "hooks_url": "https://api.github.com/repos/servo/servo/hooks", + "issue_events_url": "https://api.github.com/repos/servo/servo/issues/events{/number}", + "events_url": "https://api.github.com/repos/servo/servo/events", + "assignees_url": "https://api.github.com/repos/servo/servo/assignees{/user}", + "branches_url": "https://api.github.com/repos/servo/servo/branches{/branch}", + "tags_url": "https://api.github.com/repos/servo/servo/tags", + "blobs_url": "https://api.github.com/repos/servo/servo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/servo/servo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/servo/servo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/servo/servo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/servo/servo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/servo/servo/languages", + "stargazers_url": "https://api.github.com/repos/servo/servo/stargazers", + "contributors_url": "https://api.github.com/repos/servo/servo/contributors", + "subscribers_url": "https://api.github.com/repos/servo/servo/subscribers", + "subscription_url": "https://api.github.com/repos/servo/servo/subscription", + "commits_url": "https://api.github.com/repos/servo/servo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/servo/servo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/servo/servo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/servo/servo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/servo/servo/contents/{+path}", + "compare_url": "https://api.github.com/repos/servo/servo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/servo/servo/merges", + "archive_url": "https://api.github.com/repos/servo/servo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/servo/servo/downloads", + "issues_url": "https://api.github.com/repos/servo/servo/issues{/number}", + "pulls_url": "https://api.github.com/repos/servo/servo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/servo/servo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/servo/servo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/servo/servo/labels{/name}", + "releases_url": "https://api.github.com/repos/servo/servo/releases{/id}", + "created_at": "2012-02-08T19:07:25Z", + "updated_at": "2015-08-07T09:37:49Z", + "pushed_at": "2015-08-07T14:10:08Z", + "git_url": "git://github.com/servo/servo.git", + "ssh_url": "git@github.com:servo/servo.git", + "clone_url": "https://github.com/servo/servo.git", + "svn_url": "https://github.com/servo/servo", + "homepage": "", + "size": 1904176, + "stargazers_count": 4571, + "watchers_count": 4571, + "language": "Rust", + "has_issues": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "forks_count": 717, + "mirror_url": null, + "open_issues_count": 1060, + "forks": 717, + "open_issues": 1060, + "watchers": 4571, + "default_branch": "master" + } + }, + "_links": { + "self": { + "href": "https://api.github.com/repos/servo/servo/pulls/7076" + }, + "html": { + "href": "https://github.com/servo/servo/pull/7076" + }, + "issue": { + "href": "https://api.github.com/repos/servo/servo/issues/7076" + }, + "comments": { + "href": "https://api.github.com/repos/servo/servo/issues/7076/comments" + }, + "review_comments": { + "href": "https://api.github.com/repos/servo/servo/pulls/7076/comments" + }, + "review_comment": { + "href": "https://api.github.com/repos/servo/servo/pulls/comments{/number}" + }, + "commits": { + "href": "https://api.github.com/repos/servo/servo/pulls/7076/commits" + }, + "statuses": { + "href": "https://api.github.com/repos/servo/servo/statuses/da44f31cb1debe2c8161ee280121d79d3dd5ec18" + } + }, + "merged": false, + "mergeable": null, + "mergeable_state": "unknown", + "merged_by": null, + "comments": 0, + "review_comments": 0, + "commits": 1, + "additions": 0, + "deletions": 1, + "changed_files": 1 + }, + "repository": { + "id": 3390243, + "name": "servo", + "full_name": "servo/servo", + "owner": { + "login": "servo", + "id": 2566135, + "avatar_url": "https://avatars.githubusercontent.com/u/2566135?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/servo", + "html_url": "https://github.com/servo", + "followers_url": "https://api.github.com/users/servo/followers", + "following_url": "https://api.github.com/users/servo/following{/other_user}", + "gists_url": "https://api.github.com/users/servo/gists{/gist_id}", + "starred_url": "https://api.github.com/users/servo/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/servo/subscriptions", + "organizations_url": "https://api.github.com/users/servo/orgs", + "repos_url": "https://api.github.com/users/servo/repos", + "events_url": "https://api.github.com/users/servo/events{/privacy}", + "received_events_url": "https://api.github.com/users/servo/received_events", + "type": "Organization", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/servo/servo", + "description": "The Servo Browser Engine", + "fork": false, + "url": "https://api.github.com/repos/servo/servo", + "forks_url": "https://api.github.com/repos/servo/servo/forks", + "keys_url": "https://api.github.com/repos/servo/servo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/servo/servo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/servo/servo/teams", + "hooks_url": "https://api.github.com/repos/servo/servo/hooks", + "issue_events_url": "https://api.github.com/repos/servo/servo/issues/events{/number}", + "events_url": "https://api.github.com/repos/servo/servo/events", + "assignees_url": "https://api.github.com/repos/servo/servo/assignees{/user}", + "branches_url": "https://api.github.com/repos/servo/servo/branches{/branch}", + "tags_url": "https://api.github.com/repos/servo/servo/tags", + "blobs_url": "https://api.github.com/repos/servo/servo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/servo/servo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/servo/servo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/servo/servo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/servo/servo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/servo/servo/languages", + "stargazers_url": "https://api.github.com/repos/servo/servo/stargazers", + "contributors_url": "https://api.github.com/repos/servo/servo/contributors", + "subscribers_url": "https://api.github.com/repos/servo/servo/subscribers", + "subscription_url": "https://api.github.com/repos/servo/servo/subscription", + "commits_url": "https://api.github.com/repos/servo/servo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/servo/servo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/servo/servo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/servo/servo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/servo/servo/contents/{+path}", + "compare_url": "https://api.github.com/repos/servo/servo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/servo/servo/merges", + "archive_url": "https://api.github.com/repos/servo/servo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/servo/servo/downloads", + "issues_url": "https://api.github.com/repos/servo/servo/issues{/number}", + "pulls_url": "https://api.github.com/repos/servo/servo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/servo/servo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/servo/servo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/servo/servo/labels{/name}", + "releases_url": "https://api.github.com/repos/servo/servo/releases{/id}", + "created_at": "2012-02-08T19:07:25Z", + "updated_at": "2015-08-07T09:37:49Z", + "pushed_at": "2015-08-07T14:10:08Z", + "git_url": "git://github.com/servo/servo.git", + "ssh_url": "git@github.com:servo/servo.git", + "clone_url": "https://github.com/servo/servo.git", + "svn_url": "https://github.com/servo/servo", + "homepage": "", + "size": 1904176, + "stargazers_count": 4571, + "watchers_count": 4571, + "language": "Rust", + "has_issues": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "forks_count": 717, + "mirror_url": null, + "open_issues_count": 1060, + "forks": 717, + "open_issues": 1060, + "watchers": 4571, + "default_branch": "master" + }, + "organization": { + "login": "servo", + "id": 2566135, + "url": "https://api.github.com/orgs/servo", + "repos_url": "https://api.github.com/orgs/servo/repos", + "events_url": "https://api.github.com/orgs/servo/events", + "members_url": "https://api.github.com/orgs/servo/members{/member}", + "public_members_url": "https://api.github.com/orgs/servo/public_members{/member}", + "avatar_url": "https://avatars.githubusercontent.com/u/2566135?v=3", + "description": null + }, + "sender": { + "login": "frewsxcv", + "id": 416575, + "avatar_url": "https://avatars.githubusercontent.com/u/416575?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/frewsxcv", + "html_url": "https://github.com/frewsxcv", + "followers_url": "https://api.github.com/users/frewsxcv/followers", + "following_url": "https://api.github.com/users/frewsxcv/following{/other_user}", + "gists_url": "https://api.github.com/users/frewsxcv/gists{/gist_id}", + "starred_url": "https://api.github.com/users/frewsxcv/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/frewsxcv/subscriptions", + "organizations_url": "https://api.github.com/users/frewsxcv/orgs", + "repos_url": "https://api.github.com/users/frewsxcv/repos", + "events_url": "https://api.github.com/users/frewsxcv/events{/privacy}", + "received_events_url": "https://api.github.com/users/frewsxcv/received_events", + "type": "User", + "site_admin": false + } +} +} diff --git a/test.py b/test.py index 8917538..88bc3fa 100644 --- a/test.py +++ b/test.py @@ -38,33 +38,41 @@ def get_payload(filename): with open(filename) as f: return json.load(f) -tests = [] -def add_test(filename, initial, expected): +def create_test(filename, initial, expected, new_style=False): global tests initial_values = {'new_contributor': initial.get('new_contributor', False), 'labels': initial.get('labels', []), 'diff': initial.get('diff', ''), 'assignee': initial.get('assignee', None)} - expected_values = {'labels': expected.get('labels', []), - 'assignee': expected.get('assignee', None), - 'comments': expected.get('comments', 0)} - tests += [{'filename': filename, - 'initial': initial_values, - 'expected': expected_values}] + if new_style: + expected_values = expected + else: + expected_values = {'labels': expected.get('labels', []), + 'assignee': expected.get('assignee', None), + 'comments': expected.get('comments', 0)} + return {'filename': filename, + 'initial': initial_values, + 'expected': expected_values, + 'ignore_missing_expected': new_style} def run_tests(tests): failed = 0 for test in tests: try: - payload = get_payload(test['filename']) + test_contents = get_payload(test['filename']) + payload = test_contents['payload'] if 'payload' in test_contents else test_contents initial = test['initial'] api = TestAPIProvider(payload, 'highfive', initial['new_contributor'], initial['labels'], initial['assignee'], initial['diff']) handle_payload(api, payload) expected = test['expected'] - assert len(api.comments_posted) == expected['comments'] - assert api.labels == expected['labels'] - assert api.assignee == expected['assignee'] + ignore_missing = test['ignore_missing_expected'] + if not ignore_missing or 'comments' in expected: + assert len(api.comments_posted) == expected['comments'] + if not ignore_missing or 'labels' in expected: + assert api.labels == expected['labels'] + if not ignore_missing or 'assignee' in expected: + assert api.assignee == expected['assignee'] except AssertionError: _, _, tb = sys.exc_info() traceback.print_tb(tb) # Fixed format @@ -75,7 +83,7 @@ def run_tests(tests): possible_tests = [f for f in os.listdir('.') if f.endswith('.json')] test_files = set([test['filename'] for test in tests]) - if len(possible_tests) != len(test_files): + if len(possible_tests) > len(test_files): print 'Found unused JSON test data: %s' % ', '.join(filter(lambda x: x not in test_files, possible_tests)) sys.exit(1) print 'Ran %d tests, %d failed' % (len(tests), failed) @@ -83,42 +91,51 @@ def run_tests(tests): if failed: sys.exit(1) -add_test('test_new_pr.json', {'new_contributor': True}, - {'labels': ['S-awaiting-review'], 'comments': 1}) +def setup_tests(): + import eventhandler + (modules, handlers) = eventhandler.get_handlers() + tests = [] + for module, handler in zip(modules, handlers): + tests.extend(handler.register_tests(module[1])) -add_test('test_new_pr.json', {'diff': "+ unsafe fn foo()"}, - {'labels': ['S-awaiting-review'], 'comments': 1}) + tests += [ + create_test('test_new_pr.json', {'diff': "+ unsafe fn foo()"}, + {'labels': ['S-awaiting-review'], 'comments': 1}), -add_test('test_new_pr.json', {'diff': "diff --git components/layout/"}, - {'labels': ['S-awaiting-review'], 'comments': 1}) + create_test('test_new_pr.json', {'diff': "diff --git components/layout/"}, + {'labels': ['S-awaiting-review'], 'comments': 1}), -add_test('test_new_pr.json', {'diff': "diff --git components/layout/\ndiff --git tests/wpt"}, - {'labels': ['S-awaiting-review'], 'comments': 0}) + create_test('test_new_pr.json', {'diff': "diff --git components/layout/\ndiff --git tests/wpt"}, + {'labels': ['S-awaiting-review'], 'comments': 0}), -add_test('test_new_pr.json', {'new_contributor': True}, - {'labels': ['S-awaiting-review'], 'comments': 1}) + create_test('test_new_pr.json', {'new_contributor': True}, + {'labels': ['S-awaiting-review'], 'comments': 1}), -add_test('test_ignored_action.json', {}, {}) + create_test('test_ignored_action.json', {}, {}), -add_test('test_synchronize.json', {'labels': ['S-needs-code-changes', 'S-tests-failed', 'S-awaiting-merge']}, - {'labels': ['S-awaiting-review']}) + create_test('test_synchronize.json', {'labels': ['S-needs-code-changes', 'S-tests-failed', 'S-awaiting-merge']}, + {'labels': ['S-awaiting-review']}), -add_test('test_comment.json', {}, {'assignee': 'jdm'}) + create_test('test_comment.json', {}, {'assignee': 'jdm'}), -add_test('test_merge_approved.json', {'labels': ['S-needs-code-changes', 'S-needs-rebase', - 'S-tests-failed', 'S-needs-squash', - 'S-awaiting-review']}, {'labels': ['S-awaiting-merge']}) + create_test('test_merge_approved.json', {'labels': ['S-needs-code-changes', 'S-needs-rebase', + 'S-tests-failed', 'S-needs-squash', + 'S-awaiting-review']}, {'labels': ['S-awaiting-merge']}), -add_test('test_merge_conflict.json', {'labels': ['S-awaiting-merge']}, - {'labels': ['S-needs-rebase']}) + create_test('test_merge_conflict.json', {'labels': ['S-awaiting-merge']}, + {'labels': ['S-needs-rebase']}), -add_test('test_tests_failed.json', {'labels': ['S-awaiting-merge']}, - {'labels': ['S-tests-failed']}) + create_test('test_tests_failed.json', {'labels': ['S-awaiting-merge']}, + {'labels': ['S-tests-failed']}), -add_test('test_post_retry.json', {'labels': ['S-tests-failed']}, - {'labels': ['S-awaiting-merge']}) + create_test('test_post_retry.json', {'labels': ['S-tests-failed']}, + {'labels': ['S-awaiting-merge']}), -add_test('test_post_retry.json', {'labels': ['S-awaiting-merge']}, - {'labels': ['S-awaiting-merge']}) + create_test('test_post_retry.json', {'labels': ['S-awaiting-merge']}, + {'labels': ['S-awaiting-merge']}) + ] + return tests -run_tests(tests) +if __name__ == "__main__": + tests = setup_tests() + run_tests(tests) From 04c3de6a5cb66490cdb3e097f43edb72707a2aa2 Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Thu, 26 Nov 2015 14:51:35 -0500 Subject: [PATCH 04/12] .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0d20b64 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.pyc From 7c7357dffae750fffc9b8a3ce03cae9fa44d60a2 Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Thu, 26 Nov 2015 15:35:52 -0500 Subject: [PATCH 05/12] Convert missing tests and unsafe checks to handlers. --- eventhandler.py | 21 +- handlers/missing_test/__init__.py | 21 ++ handlers/missing_test/tests/new_pr.json | 438 ++++++++++++++++++++++++ handlers/unsafe/__init__.py | 15 + handlers/unsafe/tests/new_pr.json | 432 +++++++++++++++++++++++ newpr.py | 32 +- test.py | 13 +- 7 files changed, 935 insertions(+), 37 deletions(-) create mode 100644 handlers/missing_test/__init__.py create mode 100644 handlers/missing_test/tests/new_pr.json create mode 100644 handlers/unsafe/__init__.py create mode 100644 handlers/unsafe/tests/new_pr.json diff --git a/eventhandler.py b/eventhandler.py index 64d676e..34dc651 100644 --- a/eventhandler.py +++ b/eventhandler.py @@ -2,6 +2,8 @@ import json import os +_warnings = [] + class EventHandler: def on_pr_opened(self, api, payload): pass @@ -12,6 +14,10 @@ def on_pr_updated(self, api, payload): def on_new_comment(self, api, payload): pass + def warn(self, msg): + global _warnings + _warnings += [msg] + def register_tests(self, path): from test import create_test tests_location = os.path.join(path, 'tests') @@ -21,7 +27,20 @@ def register_tests(self, path): for testfile in tests: with open(testfile) as f: contents = json.load(f) - yield create_test(testfile, contents['initial'], contents['expected'], True) + if not isinstance(contents['initial'], list): + assert not isinstance(contents['expected'], list) + contents['initial'] = [contents['initial']] + contents['expected'] = [contents['expected']] + for initial, expected in zip(contents['initial'], contents['expected']): + yield create_test(testfile, initial, expected, True) + +def reset_test_state(): + global _warnings + _warnings = [] + +def get_warnings(): + global _warnings + return _warnings def get_handlers(): modules = [] diff --git a/handlers/missing_test/__init__.py b/handlers/missing_test/__init__.py new file mode 100644 index 0000000..618b8c5 --- /dev/null +++ b/handlers/missing_test/__init__.py @@ -0,0 +1,21 @@ +from eventhandler import EventHandler +import random + +reftest_required_msg = 'These commits modify layout code, but no reftests are modified. Please consider adding a reftest!' + +class MissingTestHandler(EventHandler): + def on_pr_opened(self, api, payload): + diff = api.get_diff() + layout_changed = False + for line in diff.split('\n'): + if line.startswith('diff --git') and line.find('components/layout/') > -1: + layout_changed = True + if line.startswith('diff --git') and \ + (line.find('tests/ref') > -1 or line.find('tests/wpt') > -1): + return + + if layout_changed: + self.warn(reftest_required_msg) + + +handler_interface = MissingTestHandler diff --git a/handlers/missing_test/tests/new_pr.json b/handlers/missing_test/tests/new_pr.json new file mode 100644 index 0000000..89bbc74 --- /dev/null +++ b/handlers/missing_test/tests/new_pr.json @@ -0,0 +1,438 @@ +{ + "initial": [{ + "diff": "diff --git components/layout/" + }, + { + "diff": "diff --git components/layout/\ndiff --git tests/wpt" + }], + "expected": [{ + "comments": 1 + }, + { + "comments": 0 + }], + "payload": +{ + "action": "opened", + "number": 7076, + "pull_request": { + "url": "https://api.github.com/repos/servo/servo/pulls/7076", + "id": 41896942, + "html_url": "https://github.com/servo/servo/pull/7076", + "diff_url": "https://github.com/servo/servo/pull/7076.diff", + "patch_url": "https://github.com/servo/servo/pull/7076.patch", + "issue_url": "https://api.github.com/repos/servo/servo/issues/7076", + "number": 7076, + "state": "open", + "locked": false, + "title": "Remove invalid file path in ignored_files for tidying", + "user": { + "login": "frewsxcv", + "id": 416575, + "avatar_url": "https://avatars.githubusercontent.com/u/416575?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/frewsxcv", + "html_url": "https://github.com/frewsxcv", + "followers_url": "https://api.github.com/users/frewsxcv/followers", + "following_url": "https://api.github.com/users/frewsxcv/following{/other_user}", + "gists_url": "https://api.github.com/users/frewsxcv/gists{/gist_id}", + "starred_url": "https://api.github.com/users/frewsxcv/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/frewsxcv/subscriptions", + "organizations_url": "https://api.github.com/users/frewsxcv/orgs", + "repos_url": "https://api.github.com/users/frewsxcv/repos", + "events_url": "https://api.github.com/users/frewsxcv/events{/privacy}", + "received_events_url": "https://api.github.com/users/frewsxcv/received_events", + "type": "User", + "site_admin": false + }, + "body": null, + "created_at": "2015-08-07T14:24:50Z", + "updated_at": "2015-08-07T14:24:50Z", + "closed_at": null, + "merged_at": null, + "merge_commit_sha": null, + "assignee": null, + "milestone": null, + "commits_url": "https://api.github.com/repos/servo/servo/pulls/7076/commits", + "review_comments_url": "https://api.github.com/repos/servo/servo/pulls/7076/comments", + "review_comment_url": "https://api.github.com/repos/servo/servo/pulls/comments{/number}", + "comments_url": "https://api.github.com/repos/servo/servo/issues/7076/comments", + "statuses_url": "https://api.github.com/repos/servo/servo/statuses/da44f31cb1debe2c8161ee280121d79d3dd5ec18", + "head": { + "label": "frewsxcv:tidy-rm-invalid-file", + "ref": "tidy-rm-invalid-file", + "sha": "da44f31cb1debe2c8161ee280121d79d3dd5ec18", + "user": { + "login": "frewsxcv", + "id": 416575, + "avatar_url": "https://avatars.githubusercontent.com/u/416575?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/frewsxcv", + "html_url": "https://github.com/frewsxcv", + "followers_url": "https://api.github.com/users/frewsxcv/followers", + "following_url": "https://api.github.com/users/frewsxcv/following{/other_user}", + "gists_url": "https://api.github.com/users/frewsxcv/gists{/gist_id}", + "starred_url": "https://api.github.com/users/frewsxcv/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/frewsxcv/subscriptions", + "organizations_url": "https://api.github.com/users/frewsxcv/orgs", + "repos_url": "https://api.github.com/users/frewsxcv/repos", + "events_url": "https://api.github.com/users/frewsxcv/events{/privacy}", + "received_events_url": "https://api.github.com/users/frewsxcv/received_events", + "type": "User", + "site_admin": false + }, + "repo": { + "id": 27014207, + "name": "servo", + "full_name": "frewsxcv/servo", + "owner": { + "login": "frewsxcv", + "id": 416575, + "avatar_url": "https://avatars.githubusercontent.com/u/416575?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/frewsxcv", + "html_url": "https://github.com/frewsxcv", + "followers_url": "https://api.github.com/users/frewsxcv/followers", + "following_url": "https://api.github.com/users/frewsxcv/following{/other_user}", + "gists_url": "https://api.github.com/users/frewsxcv/gists{/gist_id}", + "starred_url": "https://api.github.com/users/frewsxcv/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/frewsxcv/subscriptions", + "organizations_url": "https://api.github.com/users/frewsxcv/orgs", + "repos_url": "https://api.github.com/users/frewsxcv/repos", + "events_url": "https://api.github.com/users/frewsxcv/events{/privacy}", + "received_events_url": "https://api.github.com/users/frewsxcv/received_events", + "type": "User", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/frewsxcv/servo", + "description": "The Servo Browser Engine", + "fork": true, + "url": "https://api.github.com/repos/frewsxcv/servo", + "forks_url": "https://api.github.com/repos/frewsxcv/servo/forks", + "keys_url": "https://api.github.com/repos/frewsxcv/servo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/frewsxcv/servo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/frewsxcv/servo/teams", + "hooks_url": "https://api.github.com/repos/frewsxcv/servo/hooks", + "issue_events_url": "https://api.github.com/repos/frewsxcv/servo/issues/events{/number}", + "events_url": "https://api.github.com/repos/frewsxcv/servo/events", + "assignees_url": "https://api.github.com/repos/frewsxcv/servo/assignees{/user}", + "branches_url": "https://api.github.com/repos/frewsxcv/servo/branches{/branch}", + "tags_url": "https://api.github.com/repos/frewsxcv/servo/tags", + "blobs_url": "https://api.github.com/repos/frewsxcv/servo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/frewsxcv/servo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/frewsxcv/servo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/frewsxcv/servo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/frewsxcv/servo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/frewsxcv/servo/languages", + "stargazers_url": "https://api.github.com/repos/frewsxcv/servo/stargazers", + "contributors_url": "https://api.github.com/repos/frewsxcv/servo/contributors", + "subscribers_url": "https://api.github.com/repos/frewsxcv/servo/subscribers", + "subscription_url": "https://api.github.com/repos/frewsxcv/servo/subscription", + "commits_url": "https://api.github.com/repos/frewsxcv/servo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/frewsxcv/servo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/frewsxcv/servo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/frewsxcv/servo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/frewsxcv/servo/contents/{+path}", + "compare_url": "https://api.github.com/repos/frewsxcv/servo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/frewsxcv/servo/merges", + "archive_url": "https://api.github.com/repos/frewsxcv/servo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/frewsxcv/servo/downloads", + "issues_url": "https://api.github.com/repos/frewsxcv/servo/issues{/number}", + "pulls_url": "https://api.github.com/repos/frewsxcv/servo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/frewsxcv/servo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/frewsxcv/servo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/frewsxcv/servo/labels{/name}", + "releases_url": "https://api.github.com/repos/frewsxcv/servo/releases{/id}", + "created_at": "2014-11-22T22:10:35Z", + "updated_at": "2014-11-22T22:10:38Z", + "pushed_at": "2015-08-07T14:24:45Z", + "git_url": "git://github.com/frewsxcv/servo.git", + "ssh_url": "git@github.com:frewsxcv/servo.git", + "clone_url": "https://github.com/frewsxcv/servo.git", + "svn_url": "https://github.com/frewsxcv/servo", + "homepage": "", + "size": 119557, + "stargazers_count": 0, + "watchers_count": 0, + "language": "Rust", + "has_issues": false, + "has_downloads": true, + "has_wiki": true, + "has_pages": true, + "forks_count": 0, + "mirror_url": null, + "open_issues_count": 0, + "forks": 0, + "open_issues": 0, + "watchers": 0, + "default_branch": "master" + } + }, + "base": { + "label": "servo:master", + "ref": "master", + "sha": "b4e30da3dbf58c16703864f4bec4b0b0132084fa", + "user": { + "login": "servo", + "id": 2566135, + "avatar_url": "https://avatars.githubusercontent.com/u/2566135?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/servo", + "html_url": "https://github.com/servo", + "followers_url": "https://api.github.com/users/servo/followers", + "following_url": "https://api.github.com/users/servo/following{/other_user}", + "gists_url": "https://api.github.com/users/servo/gists{/gist_id}", + "starred_url": "https://api.github.com/users/servo/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/servo/subscriptions", + "organizations_url": "https://api.github.com/users/servo/orgs", + "repos_url": "https://api.github.com/users/servo/repos", + "events_url": "https://api.github.com/users/servo/events{/privacy}", + "received_events_url": "https://api.github.com/users/servo/received_events", + "type": "Organization", + "site_admin": false + }, + "repo": { + "id": 3390243, + "name": "servo", + "full_name": "servo/servo", + "owner": { + "login": "servo", + "id": 2566135, + "avatar_url": "https://avatars.githubusercontent.com/u/2566135?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/servo", + "html_url": "https://github.com/servo", + "followers_url": "https://api.github.com/users/servo/followers", + "following_url": "https://api.github.com/users/servo/following{/other_user}", + "gists_url": "https://api.github.com/users/servo/gists{/gist_id}", + "starred_url": "https://api.github.com/users/servo/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/servo/subscriptions", + "organizations_url": "https://api.github.com/users/servo/orgs", + "repos_url": "https://api.github.com/users/servo/repos", + "events_url": "https://api.github.com/users/servo/events{/privacy}", + "received_events_url": "https://api.github.com/users/servo/received_events", + "type": "Organization", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/servo/servo", + "description": "The Servo Browser Engine", + "fork": false, + "url": "https://api.github.com/repos/servo/servo", + "forks_url": "https://api.github.com/repos/servo/servo/forks", + "keys_url": "https://api.github.com/repos/servo/servo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/servo/servo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/servo/servo/teams", + "hooks_url": "https://api.github.com/repos/servo/servo/hooks", + "issue_events_url": "https://api.github.com/repos/servo/servo/issues/events{/number}", + "events_url": "https://api.github.com/repos/servo/servo/events", + "assignees_url": "https://api.github.com/repos/servo/servo/assignees{/user}", + "branches_url": "https://api.github.com/repos/servo/servo/branches{/branch}", + "tags_url": "https://api.github.com/repos/servo/servo/tags", + "blobs_url": "https://api.github.com/repos/servo/servo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/servo/servo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/servo/servo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/servo/servo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/servo/servo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/servo/servo/languages", + "stargazers_url": "https://api.github.com/repos/servo/servo/stargazers", + "contributors_url": "https://api.github.com/repos/servo/servo/contributors", + "subscribers_url": "https://api.github.com/repos/servo/servo/subscribers", + "subscription_url": "https://api.github.com/repos/servo/servo/subscription", + "commits_url": "https://api.github.com/repos/servo/servo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/servo/servo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/servo/servo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/servo/servo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/servo/servo/contents/{+path}", + "compare_url": "https://api.github.com/repos/servo/servo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/servo/servo/merges", + "archive_url": "https://api.github.com/repos/servo/servo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/servo/servo/downloads", + "issues_url": "https://api.github.com/repos/servo/servo/issues{/number}", + "pulls_url": "https://api.github.com/repos/servo/servo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/servo/servo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/servo/servo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/servo/servo/labels{/name}", + "releases_url": "https://api.github.com/repos/servo/servo/releases{/id}", + "created_at": "2012-02-08T19:07:25Z", + "updated_at": "2015-08-07T09:37:49Z", + "pushed_at": "2015-08-07T14:10:08Z", + "git_url": "git://github.com/servo/servo.git", + "ssh_url": "git@github.com:servo/servo.git", + "clone_url": "https://github.com/servo/servo.git", + "svn_url": "https://github.com/servo/servo", + "homepage": "", + "size": 1904176, + "stargazers_count": 4571, + "watchers_count": 4571, + "language": "Rust", + "has_issues": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "forks_count": 717, + "mirror_url": null, + "open_issues_count": 1060, + "forks": 717, + "open_issues": 1060, + "watchers": 4571, + "default_branch": "master" + } + }, + "_links": { + "self": { + "href": "https://api.github.com/repos/servo/servo/pulls/7076" + }, + "html": { + "href": "https://github.com/servo/servo/pull/7076" + }, + "issue": { + "href": "https://api.github.com/repos/servo/servo/issues/7076" + }, + "comments": { + "href": "https://api.github.com/repos/servo/servo/issues/7076/comments" + }, + "review_comments": { + "href": "https://api.github.com/repos/servo/servo/pulls/7076/comments" + }, + "review_comment": { + "href": "https://api.github.com/repos/servo/servo/pulls/comments{/number}" + }, + "commits": { + "href": "https://api.github.com/repos/servo/servo/pulls/7076/commits" + }, + "statuses": { + "href": "https://api.github.com/repos/servo/servo/statuses/da44f31cb1debe2c8161ee280121d79d3dd5ec18" + } + }, + "merged": false, + "mergeable": null, + "mergeable_state": "unknown", + "merged_by": null, + "comments": 0, + "review_comments": 0, + "commits": 1, + "additions": 0, + "deletions": 1, + "changed_files": 1 + }, + "repository": { + "id": 3390243, + "name": "servo", + "full_name": "servo/servo", + "owner": { + "login": "servo", + "id": 2566135, + "avatar_url": "https://avatars.githubusercontent.com/u/2566135?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/servo", + "html_url": "https://github.com/servo", + "followers_url": "https://api.github.com/users/servo/followers", + "following_url": "https://api.github.com/users/servo/following{/other_user}", + "gists_url": "https://api.github.com/users/servo/gists{/gist_id}", + "starred_url": "https://api.github.com/users/servo/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/servo/subscriptions", + "organizations_url": "https://api.github.com/users/servo/orgs", + "repos_url": "https://api.github.com/users/servo/repos", + "events_url": "https://api.github.com/users/servo/events{/privacy}", + "received_events_url": "https://api.github.com/users/servo/received_events", + "type": "Organization", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/servo/servo", + "description": "The Servo Browser Engine", + "fork": false, + "url": "https://api.github.com/repos/servo/servo", + "forks_url": "https://api.github.com/repos/servo/servo/forks", + "keys_url": "https://api.github.com/repos/servo/servo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/servo/servo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/servo/servo/teams", + "hooks_url": "https://api.github.com/repos/servo/servo/hooks", + "issue_events_url": "https://api.github.com/repos/servo/servo/issues/events{/number}", + "events_url": "https://api.github.com/repos/servo/servo/events", + "assignees_url": "https://api.github.com/repos/servo/servo/assignees{/user}", + "branches_url": "https://api.github.com/repos/servo/servo/branches{/branch}", + "tags_url": "https://api.github.com/repos/servo/servo/tags", + "blobs_url": "https://api.github.com/repos/servo/servo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/servo/servo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/servo/servo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/servo/servo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/servo/servo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/servo/servo/languages", + "stargazers_url": "https://api.github.com/repos/servo/servo/stargazers", + "contributors_url": "https://api.github.com/repos/servo/servo/contributors", + "subscribers_url": "https://api.github.com/repos/servo/servo/subscribers", + "subscription_url": "https://api.github.com/repos/servo/servo/subscription", + "commits_url": "https://api.github.com/repos/servo/servo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/servo/servo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/servo/servo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/servo/servo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/servo/servo/contents/{+path}", + "compare_url": "https://api.github.com/repos/servo/servo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/servo/servo/merges", + "archive_url": "https://api.github.com/repos/servo/servo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/servo/servo/downloads", + "issues_url": "https://api.github.com/repos/servo/servo/issues{/number}", + "pulls_url": "https://api.github.com/repos/servo/servo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/servo/servo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/servo/servo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/servo/servo/labels{/name}", + "releases_url": "https://api.github.com/repos/servo/servo/releases{/id}", + "created_at": "2012-02-08T19:07:25Z", + "updated_at": "2015-08-07T09:37:49Z", + "pushed_at": "2015-08-07T14:10:08Z", + "git_url": "git://github.com/servo/servo.git", + "ssh_url": "git@github.com:servo/servo.git", + "clone_url": "https://github.com/servo/servo.git", + "svn_url": "https://github.com/servo/servo", + "homepage": "", + "size": 1904176, + "stargazers_count": 4571, + "watchers_count": 4571, + "language": "Rust", + "has_issues": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "forks_count": 717, + "mirror_url": null, + "open_issues_count": 1060, + "forks": 717, + "open_issues": 1060, + "watchers": 4571, + "default_branch": "master" + }, + "organization": { + "login": "servo", + "id": 2566135, + "url": "https://api.github.com/orgs/servo", + "repos_url": "https://api.github.com/orgs/servo/repos", + "events_url": "https://api.github.com/orgs/servo/events", + "members_url": "https://api.github.com/orgs/servo/members{/member}", + "public_members_url": "https://api.github.com/orgs/servo/public_members{/member}", + "avatar_url": "https://avatars.githubusercontent.com/u/2566135?v=3", + "description": null + }, + "sender": { + "login": "frewsxcv", + "id": 416575, + "avatar_url": "https://avatars.githubusercontent.com/u/416575?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/frewsxcv", + "html_url": "https://github.com/frewsxcv", + "followers_url": "https://api.github.com/users/frewsxcv/followers", + "following_url": "https://api.github.com/users/frewsxcv/following{/other_user}", + "gists_url": "https://api.github.com/users/frewsxcv/gists{/gist_id}", + "starred_url": "https://api.github.com/users/frewsxcv/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/frewsxcv/subscriptions", + "organizations_url": "https://api.github.com/users/frewsxcv/orgs", + "repos_url": "https://api.github.com/users/frewsxcv/repos", + "events_url": "https://api.github.com/users/frewsxcv/events{/privacy}", + "received_events_url": "https://api.github.com/users/frewsxcv/received_events", + "type": "User", + "site_admin": false + } +} +} diff --git a/handlers/unsafe/__init__.py b/handlers/unsafe/__init__.py new file mode 100644 index 0000000..001b0cc --- /dev/null +++ b/handlers/unsafe/__init__.py @@ -0,0 +1,15 @@ +from eventhandler import EventHandler +import random + +unsafe_warning_msg = 'These commits modify **unsafe code**. Please review it carefully!' + +class UnsafeHandler(EventHandler): + def on_pr_opened(self, api, payload): + diff = api.get_diff() + for line in diff.split('\n'): + if line.startswith('+') and not line.startswith('+++') and line.find('unsafe ') > -1: + self.warn(unsafe_warning_msg) + return + + +handler_interface = UnsafeHandler diff --git a/handlers/unsafe/tests/new_pr.json b/handlers/unsafe/tests/new_pr.json new file mode 100644 index 0000000..d9b98d6 --- /dev/null +++ b/handlers/unsafe/tests/new_pr.json @@ -0,0 +1,432 @@ +{ + "initial": { + "diff": "+ unsafe fn foo()" + }, + "expected": { + "comments": 1 + }, + "payload": +{ + "action": "opened", + "number": 7076, + "pull_request": { + "url": "https://api.github.com/repos/servo/servo/pulls/7076", + "id": 41896942, + "html_url": "https://github.com/servo/servo/pull/7076", + "diff_url": "https://github.com/servo/servo/pull/7076.diff", + "patch_url": "https://github.com/servo/servo/pull/7076.patch", + "issue_url": "https://api.github.com/repos/servo/servo/issues/7076", + "number": 7076, + "state": "open", + "locked": false, + "title": "Remove invalid file path in ignored_files for tidying", + "user": { + "login": "frewsxcv", + "id": 416575, + "avatar_url": "https://avatars.githubusercontent.com/u/416575?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/frewsxcv", + "html_url": "https://github.com/frewsxcv", + "followers_url": "https://api.github.com/users/frewsxcv/followers", + "following_url": "https://api.github.com/users/frewsxcv/following{/other_user}", + "gists_url": "https://api.github.com/users/frewsxcv/gists{/gist_id}", + "starred_url": "https://api.github.com/users/frewsxcv/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/frewsxcv/subscriptions", + "organizations_url": "https://api.github.com/users/frewsxcv/orgs", + "repos_url": "https://api.github.com/users/frewsxcv/repos", + "events_url": "https://api.github.com/users/frewsxcv/events{/privacy}", + "received_events_url": "https://api.github.com/users/frewsxcv/received_events", + "type": "User", + "site_admin": false + }, + "body": null, + "created_at": "2015-08-07T14:24:50Z", + "updated_at": "2015-08-07T14:24:50Z", + "closed_at": null, + "merged_at": null, + "merge_commit_sha": null, + "assignee": null, + "milestone": null, + "commits_url": "https://api.github.com/repos/servo/servo/pulls/7076/commits", + "review_comments_url": "https://api.github.com/repos/servo/servo/pulls/7076/comments", + "review_comment_url": "https://api.github.com/repos/servo/servo/pulls/comments{/number}", + "comments_url": "https://api.github.com/repos/servo/servo/issues/7076/comments", + "statuses_url": "https://api.github.com/repos/servo/servo/statuses/da44f31cb1debe2c8161ee280121d79d3dd5ec18", + "head": { + "label": "frewsxcv:tidy-rm-invalid-file", + "ref": "tidy-rm-invalid-file", + "sha": "da44f31cb1debe2c8161ee280121d79d3dd5ec18", + "user": { + "login": "frewsxcv", + "id": 416575, + "avatar_url": "https://avatars.githubusercontent.com/u/416575?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/frewsxcv", + "html_url": "https://github.com/frewsxcv", + "followers_url": "https://api.github.com/users/frewsxcv/followers", + "following_url": "https://api.github.com/users/frewsxcv/following{/other_user}", + "gists_url": "https://api.github.com/users/frewsxcv/gists{/gist_id}", + "starred_url": "https://api.github.com/users/frewsxcv/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/frewsxcv/subscriptions", + "organizations_url": "https://api.github.com/users/frewsxcv/orgs", + "repos_url": "https://api.github.com/users/frewsxcv/repos", + "events_url": "https://api.github.com/users/frewsxcv/events{/privacy}", + "received_events_url": "https://api.github.com/users/frewsxcv/received_events", + "type": "User", + "site_admin": false + }, + "repo": { + "id": 27014207, + "name": "servo", + "full_name": "frewsxcv/servo", + "owner": { + "login": "frewsxcv", + "id": 416575, + "avatar_url": "https://avatars.githubusercontent.com/u/416575?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/frewsxcv", + "html_url": "https://github.com/frewsxcv", + "followers_url": "https://api.github.com/users/frewsxcv/followers", + "following_url": "https://api.github.com/users/frewsxcv/following{/other_user}", + "gists_url": "https://api.github.com/users/frewsxcv/gists{/gist_id}", + "starred_url": "https://api.github.com/users/frewsxcv/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/frewsxcv/subscriptions", + "organizations_url": "https://api.github.com/users/frewsxcv/orgs", + "repos_url": "https://api.github.com/users/frewsxcv/repos", + "events_url": "https://api.github.com/users/frewsxcv/events{/privacy}", + "received_events_url": "https://api.github.com/users/frewsxcv/received_events", + "type": "User", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/frewsxcv/servo", + "description": "The Servo Browser Engine", + "fork": true, + "url": "https://api.github.com/repos/frewsxcv/servo", + "forks_url": "https://api.github.com/repos/frewsxcv/servo/forks", + "keys_url": "https://api.github.com/repos/frewsxcv/servo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/frewsxcv/servo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/frewsxcv/servo/teams", + "hooks_url": "https://api.github.com/repos/frewsxcv/servo/hooks", + "issue_events_url": "https://api.github.com/repos/frewsxcv/servo/issues/events{/number}", + "events_url": "https://api.github.com/repos/frewsxcv/servo/events", + "assignees_url": "https://api.github.com/repos/frewsxcv/servo/assignees{/user}", + "branches_url": "https://api.github.com/repos/frewsxcv/servo/branches{/branch}", + "tags_url": "https://api.github.com/repos/frewsxcv/servo/tags", + "blobs_url": "https://api.github.com/repos/frewsxcv/servo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/frewsxcv/servo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/frewsxcv/servo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/frewsxcv/servo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/frewsxcv/servo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/frewsxcv/servo/languages", + "stargazers_url": "https://api.github.com/repos/frewsxcv/servo/stargazers", + "contributors_url": "https://api.github.com/repos/frewsxcv/servo/contributors", + "subscribers_url": "https://api.github.com/repos/frewsxcv/servo/subscribers", + "subscription_url": "https://api.github.com/repos/frewsxcv/servo/subscription", + "commits_url": "https://api.github.com/repos/frewsxcv/servo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/frewsxcv/servo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/frewsxcv/servo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/frewsxcv/servo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/frewsxcv/servo/contents/{+path}", + "compare_url": "https://api.github.com/repos/frewsxcv/servo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/frewsxcv/servo/merges", + "archive_url": "https://api.github.com/repos/frewsxcv/servo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/frewsxcv/servo/downloads", + "issues_url": "https://api.github.com/repos/frewsxcv/servo/issues{/number}", + "pulls_url": "https://api.github.com/repos/frewsxcv/servo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/frewsxcv/servo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/frewsxcv/servo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/frewsxcv/servo/labels{/name}", + "releases_url": "https://api.github.com/repos/frewsxcv/servo/releases{/id}", + "created_at": "2014-11-22T22:10:35Z", + "updated_at": "2014-11-22T22:10:38Z", + "pushed_at": "2015-08-07T14:24:45Z", + "git_url": "git://github.com/frewsxcv/servo.git", + "ssh_url": "git@github.com:frewsxcv/servo.git", + "clone_url": "https://github.com/frewsxcv/servo.git", + "svn_url": "https://github.com/frewsxcv/servo", + "homepage": "", + "size": 119557, + "stargazers_count": 0, + "watchers_count": 0, + "language": "Rust", + "has_issues": false, + "has_downloads": true, + "has_wiki": true, + "has_pages": true, + "forks_count": 0, + "mirror_url": null, + "open_issues_count": 0, + "forks": 0, + "open_issues": 0, + "watchers": 0, + "default_branch": "master" + } + }, + "base": { + "label": "servo:master", + "ref": "master", + "sha": "b4e30da3dbf58c16703864f4bec4b0b0132084fa", + "user": { + "login": "servo", + "id": 2566135, + "avatar_url": "https://avatars.githubusercontent.com/u/2566135?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/servo", + "html_url": "https://github.com/servo", + "followers_url": "https://api.github.com/users/servo/followers", + "following_url": "https://api.github.com/users/servo/following{/other_user}", + "gists_url": "https://api.github.com/users/servo/gists{/gist_id}", + "starred_url": "https://api.github.com/users/servo/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/servo/subscriptions", + "organizations_url": "https://api.github.com/users/servo/orgs", + "repos_url": "https://api.github.com/users/servo/repos", + "events_url": "https://api.github.com/users/servo/events{/privacy}", + "received_events_url": "https://api.github.com/users/servo/received_events", + "type": "Organization", + "site_admin": false + }, + "repo": { + "id": 3390243, + "name": "servo", + "full_name": "servo/servo", + "owner": { + "login": "servo", + "id": 2566135, + "avatar_url": "https://avatars.githubusercontent.com/u/2566135?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/servo", + "html_url": "https://github.com/servo", + "followers_url": "https://api.github.com/users/servo/followers", + "following_url": "https://api.github.com/users/servo/following{/other_user}", + "gists_url": "https://api.github.com/users/servo/gists{/gist_id}", + "starred_url": "https://api.github.com/users/servo/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/servo/subscriptions", + "organizations_url": "https://api.github.com/users/servo/orgs", + "repos_url": "https://api.github.com/users/servo/repos", + "events_url": "https://api.github.com/users/servo/events{/privacy}", + "received_events_url": "https://api.github.com/users/servo/received_events", + "type": "Organization", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/servo/servo", + "description": "The Servo Browser Engine", + "fork": false, + "url": "https://api.github.com/repos/servo/servo", + "forks_url": "https://api.github.com/repos/servo/servo/forks", + "keys_url": "https://api.github.com/repos/servo/servo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/servo/servo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/servo/servo/teams", + "hooks_url": "https://api.github.com/repos/servo/servo/hooks", + "issue_events_url": "https://api.github.com/repos/servo/servo/issues/events{/number}", + "events_url": "https://api.github.com/repos/servo/servo/events", + "assignees_url": "https://api.github.com/repos/servo/servo/assignees{/user}", + "branches_url": "https://api.github.com/repos/servo/servo/branches{/branch}", + "tags_url": "https://api.github.com/repos/servo/servo/tags", + "blobs_url": "https://api.github.com/repos/servo/servo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/servo/servo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/servo/servo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/servo/servo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/servo/servo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/servo/servo/languages", + "stargazers_url": "https://api.github.com/repos/servo/servo/stargazers", + "contributors_url": "https://api.github.com/repos/servo/servo/contributors", + "subscribers_url": "https://api.github.com/repos/servo/servo/subscribers", + "subscription_url": "https://api.github.com/repos/servo/servo/subscription", + "commits_url": "https://api.github.com/repos/servo/servo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/servo/servo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/servo/servo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/servo/servo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/servo/servo/contents/{+path}", + "compare_url": "https://api.github.com/repos/servo/servo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/servo/servo/merges", + "archive_url": "https://api.github.com/repos/servo/servo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/servo/servo/downloads", + "issues_url": "https://api.github.com/repos/servo/servo/issues{/number}", + "pulls_url": "https://api.github.com/repos/servo/servo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/servo/servo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/servo/servo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/servo/servo/labels{/name}", + "releases_url": "https://api.github.com/repos/servo/servo/releases{/id}", + "created_at": "2012-02-08T19:07:25Z", + "updated_at": "2015-08-07T09:37:49Z", + "pushed_at": "2015-08-07T14:10:08Z", + "git_url": "git://github.com/servo/servo.git", + "ssh_url": "git@github.com:servo/servo.git", + "clone_url": "https://github.com/servo/servo.git", + "svn_url": "https://github.com/servo/servo", + "homepage": "", + "size": 1904176, + "stargazers_count": 4571, + "watchers_count": 4571, + "language": "Rust", + "has_issues": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "forks_count": 717, + "mirror_url": null, + "open_issues_count": 1060, + "forks": 717, + "open_issues": 1060, + "watchers": 4571, + "default_branch": "master" + } + }, + "_links": { + "self": { + "href": "https://api.github.com/repos/servo/servo/pulls/7076" + }, + "html": { + "href": "https://github.com/servo/servo/pull/7076" + }, + "issue": { + "href": "https://api.github.com/repos/servo/servo/issues/7076" + }, + "comments": { + "href": "https://api.github.com/repos/servo/servo/issues/7076/comments" + }, + "review_comments": { + "href": "https://api.github.com/repos/servo/servo/pulls/7076/comments" + }, + "review_comment": { + "href": "https://api.github.com/repos/servo/servo/pulls/comments{/number}" + }, + "commits": { + "href": "https://api.github.com/repos/servo/servo/pulls/7076/commits" + }, + "statuses": { + "href": "https://api.github.com/repos/servo/servo/statuses/da44f31cb1debe2c8161ee280121d79d3dd5ec18" + } + }, + "merged": false, + "mergeable": null, + "mergeable_state": "unknown", + "merged_by": null, + "comments": 0, + "review_comments": 0, + "commits": 1, + "additions": 0, + "deletions": 1, + "changed_files": 1 + }, + "repository": { + "id": 3390243, + "name": "servo", + "full_name": "servo/servo", + "owner": { + "login": "servo", + "id": 2566135, + "avatar_url": "https://avatars.githubusercontent.com/u/2566135?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/servo", + "html_url": "https://github.com/servo", + "followers_url": "https://api.github.com/users/servo/followers", + "following_url": "https://api.github.com/users/servo/following{/other_user}", + "gists_url": "https://api.github.com/users/servo/gists{/gist_id}", + "starred_url": "https://api.github.com/users/servo/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/servo/subscriptions", + "organizations_url": "https://api.github.com/users/servo/orgs", + "repos_url": "https://api.github.com/users/servo/repos", + "events_url": "https://api.github.com/users/servo/events{/privacy}", + "received_events_url": "https://api.github.com/users/servo/received_events", + "type": "Organization", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/servo/servo", + "description": "The Servo Browser Engine", + "fork": false, + "url": "https://api.github.com/repos/servo/servo", + "forks_url": "https://api.github.com/repos/servo/servo/forks", + "keys_url": "https://api.github.com/repos/servo/servo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/servo/servo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/servo/servo/teams", + "hooks_url": "https://api.github.com/repos/servo/servo/hooks", + "issue_events_url": "https://api.github.com/repos/servo/servo/issues/events{/number}", + "events_url": "https://api.github.com/repos/servo/servo/events", + "assignees_url": "https://api.github.com/repos/servo/servo/assignees{/user}", + "branches_url": "https://api.github.com/repos/servo/servo/branches{/branch}", + "tags_url": "https://api.github.com/repos/servo/servo/tags", + "blobs_url": "https://api.github.com/repos/servo/servo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/servo/servo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/servo/servo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/servo/servo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/servo/servo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/servo/servo/languages", + "stargazers_url": "https://api.github.com/repos/servo/servo/stargazers", + "contributors_url": "https://api.github.com/repos/servo/servo/contributors", + "subscribers_url": "https://api.github.com/repos/servo/servo/subscribers", + "subscription_url": "https://api.github.com/repos/servo/servo/subscription", + "commits_url": "https://api.github.com/repos/servo/servo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/servo/servo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/servo/servo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/servo/servo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/servo/servo/contents/{+path}", + "compare_url": "https://api.github.com/repos/servo/servo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/servo/servo/merges", + "archive_url": "https://api.github.com/repos/servo/servo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/servo/servo/downloads", + "issues_url": "https://api.github.com/repos/servo/servo/issues{/number}", + "pulls_url": "https://api.github.com/repos/servo/servo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/servo/servo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/servo/servo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/servo/servo/labels{/name}", + "releases_url": "https://api.github.com/repos/servo/servo/releases{/id}", + "created_at": "2012-02-08T19:07:25Z", + "updated_at": "2015-08-07T09:37:49Z", + "pushed_at": "2015-08-07T14:10:08Z", + "git_url": "git://github.com/servo/servo.git", + "ssh_url": "git@github.com:servo/servo.git", + "clone_url": "https://github.com/servo/servo.git", + "svn_url": "https://github.com/servo/servo", + "homepage": "", + "size": 1904176, + "stargazers_count": 4571, + "watchers_count": 4571, + "language": "Rust", + "has_issues": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "forks_count": 717, + "mirror_url": null, + "open_issues_count": 1060, + "forks": 717, + "open_issues": 1060, + "watchers": 4571, + "default_branch": "master" + }, + "organization": { + "login": "servo", + "id": 2566135, + "url": "https://api.github.com/orgs/servo", + "repos_url": "https://api.github.com/orgs/servo/repos", + "events_url": "https://api.github.com/orgs/servo/events", + "members_url": "https://api.github.com/orgs/servo/members{/member}", + "public_members_url": "https://api.github.com/orgs/servo/public_members{/member}", + "avatar_url": "https://avatars.githubusercontent.com/u/2566135?v=3", + "description": null + }, + "sender": { + "login": "frewsxcv", + "id": 416575, + "avatar_url": "https://avatars.githubusercontent.com/u/416575?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/frewsxcv", + "html_url": "https://github.com/frewsxcv", + "followers_url": "https://api.github.com/users/frewsxcv/followers", + "following_url": "https://api.github.com/users/frewsxcv/following{/other_user}", + "gists_url": "https://api.github.com/users/frewsxcv/gists{/gist_id}", + "starred_url": "https://api.github.com/users/frewsxcv/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/frewsxcv/subscriptions", + "organizations_url": "https://api.github.com/users/frewsxcv/orgs", + "repos_url": "https://api.github.com/users/frewsxcv/repos", + "events_url": "https://api.github.com/users/frewsxcv/events{/privacy}", + "received_events_url": "https://api.github.com/users/frewsxcv/received_events", + "type": "User", + "site_admin": false + } +} +} diff --git a/newpr.py b/newpr.py index b7160ee..a122784 100755 --- a/newpr.py +++ b/newpr.py @@ -185,8 +185,6 @@ def find_reviewer(commit_msg): warning_summary = 'warning **Warning** warning\n\n%s' -unsafe_warning_msg = 'These commits modify **unsafe code**. Please review it carefully!' -reftest_required_msg = 'These commits modify layout code, but no reftests are modified. Please consider adding a reftest!' reviewer_re = re.compile("\\b[rR]\?[:\- ]*@([a-zA-Z0-9\-]+)") @@ -257,31 +255,6 @@ def new_comment(api, payload): def new_pr(api, payload): manage_pr_state(api, payload) - warn_unsafe = False - layout_changed = False - saw_reftest = False - diff = api.get_diff() - for line in diff.split('\n'): - if line.startswith('+') and not line.startswith('+++') and line.find('unsafe') > -1: - warn_unsafe = True - if line.startswith('diff --git') and line.find('components/layout/') > -1: - layout_changed = True - if line.startswith('diff --git') and line.find('tests/ref') > -1: - saw_reftest = True - if line.startswith('diff --git') and line.find('tests/wpt') > -1: - saw_reftest = True - - warnings = [] - if warn_unsafe: - warnings += [unsafe_warning_msg] - - if layout_changed: - if not saw_reftest: - warnings += [reftest_required_msg] - - if warnings: - api.post_comment(warning_summary % '\n'.join(map(lambda x: '* ' + x, warnings))) - def update_pr(api, payload): manage_pr_state(api, payload) @@ -305,6 +278,11 @@ def handle_payload(api, payload): else: pass + warnings = eventhandler.get_warnings() + if warnings: + api.post_comment(warning_summary % '\n'.join(map(lambda x: '* ' + x, warnings))) + + if __name__ == "__main__": print "Content-Type: text/html;charset=utf-8" print diff --git a/test.py b/test.py index 88bc3fa..3fd2a11 100644 --- a/test.py +++ b/test.py @@ -56,8 +56,12 @@ def create_test(filename, initial, expected, new_style=False): 'ignore_missing_expected': new_style} def run_tests(tests): + import eventhandler + failed = 0 for test in tests: + eventhandler.reset_test_state() + try: test_contents = get_payload(test['filename']) payload = test_contents['payload'] if 'payload' in test_contents else test_contents @@ -99,15 +103,6 @@ def setup_tests(): tests.extend(handler.register_tests(module[1])) tests += [ - create_test('test_new_pr.json', {'diff': "+ unsafe fn foo()"}, - {'labels': ['S-awaiting-review'], 'comments': 1}), - - create_test('test_new_pr.json', {'diff': "diff --git components/layout/"}, - {'labels': ['S-awaiting-review'], 'comments': 1}), - - create_test('test_new_pr.json', {'diff': "diff --git components/layout/\ndiff --git tests/wpt"}, - {'labels': ['S-awaiting-review'], 'comments': 0}), - create_test('test_new_pr.json', {'new_contributor': True}, {'labels': ['S-awaiting-review'], 'comments': 1}), From ecda42e84cf8b8504625c5b2a369c474f6611856 Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Thu, 26 Nov 2015 16:06:37 -0500 Subject: [PATCH 06/12] Convert homu status updates and review assignment to handlers. --- eventhandler.py | 3 ++ handlers/assign_reviewer/__init__.py | 22 +++++++++ .../assign_reviewer/tests/comment.json | 8 ++++ handlers/homu_status/__init__.py | 34 ++++++++++++++ .../homu_status/tests/merge_approved.json | 10 ++++ .../homu_status/tests/merge_conflict.json | 9 ++++ .../homu_status/tests/post_retry.json | 15 ++++++ .../homu_status/tests/tests_failed.json | 9 ++++ handlers/missing_test/__init__.py | 1 - handlers/unsafe/__init__.py | 1 - newpr.py | 46 ------------------- test.py | 20 +------- 12 files changed, 111 insertions(+), 67 deletions(-) create mode 100644 handlers/assign_reviewer/__init__.py rename test_comment.json => handlers/assign_reviewer/tests/comment.json (99%) create mode 100644 handlers/homu_status/__init__.py rename test_merge_approved.json => handlers/homu_status/tests/merge_approved.json (97%) rename test_merge_conflict.json => handlers/homu_status/tests/merge_conflict.json (98%) rename test_post_retry.json => handlers/homu_status/tests/post_retry.json (97%) rename test_tests_failed.json => handlers/homu_status/tests/tests_failed.json (98%) diff --git a/eventhandler.py b/eventhandler.py index 34dc651..0c58807 100644 --- a/eventhandler.py +++ b/eventhandler.py @@ -18,6 +18,9 @@ def warn(self, msg): global _warnings _warnings += [msg] + def is_open_pr(self, payload): + return payload['issue']['state'] == 'open' and 'pull_request' in payload['issue'] + def register_tests(self, path): from test import create_test tests_location = os.path.join(path, 'tests') diff --git a/handlers/assign_reviewer/__init__.py b/handlers/assign_reviewer/__init__.py new file mode 100644 index 0000000..fd55624 --- /dev/null +++ b/handlers/assign_reviewer/__init__.py @@ -0,0 +1,22 @@ +from eventhandler import EventHandler +import re + +# If the user specified a reviewer, return the username, otherwise returns None. +def find_reviewer(commit_msg): + reviewer_re = re.compile("\\b[rR]\?[:\- ]*@([a-zA-Z0-9\-]+)") + match = reviewer_re.search(commit_msg) + if not match: + return None + return match.group(1) + +class AssignReviewerHandler(EventHandler): + def on_new_comment(self, api, payload): + if not self.is_open_pr(payload): + return + + reviewer = find_reviewer(payload["comment"]["body"]) + if reviewer: + api.set_assignee(reviewer) + + +handler_interface = AssignReviewerHandler diff --git a/test_comment.json b/handlers/assign_reviewer/tests/comment.json similarity index 99% rename from test_comment.json rename to handlers/assign_reviewer/tests/comment.json index 9459c33..2192279 100644 --- a/test_comment.json +++ b/handlers/assign_reviewer/tests/comment.json @@ -1,3 +1,10 @@ +{ + "initial": { + }, + "expected": { + "assignee": "jdm" + }, + "payload": { "action": "created", "issue": { @@ -197,3 +204,4 @@ "site_admin": false } } +} diff --git a/handlers/homu_status/__init__.py b/handlers/homu_status/__init__.py new file mode 100644 index 0000000..5878f07 --- /dev/null +++ b/handlers/homu_status/__init__.py @@ -0,0 +1,34 @@ +from eventhandler import EventHandler + +class HomuStatusHandler(EventHandler): + def on_new_comment(self, api, payload): + if not self.is_open_pr(payload): + return + + if payload['comment']['user']['login'] != 'bors-servo': + return + + labels = api.get_labels(); + msg = payload["comment"]["body"] + + def remove_if_exists(label): + if label in labels: + api.remove_label(label) + + if 'has been approved by' in msg or 'Testing commit' in msg: + for label in ["S-awaiting-review", "S-needs-rebase", "S-tests-failed", + "S-needs-code-changes", "S-needs-squash", "S-awaiting-answer"]: + remove_if_exists(label) + if not "S-awaiting-merge" in labels: + api.add_label("S-awaiting-merge") + + elif 'Test failed' in msg: + remove_if_exists("S-awaiting-merge") + api.add_label("S-tests-failed") + + elif 'Please resolve the merge conflicts' in msg: + remove_if_exists("S-awaiting-merge") + api.add_label("S-needs-rebase") + + +handler_interface = HomuStatusHandler diff --git a/test_merge_approved.json b/handlers/homu_status/tests/merge_approved.json similarity index 97% rename from test_merge_approved.json rename to handlers/homu_status/tests/merge_approved.json index 8864e7d..e29469d 100644 --- a/test_merge_approved.json +++ b/handlers/homu_status/tests/merge_approved.json @@ -1,3 +1,12 @@ +{ + "initial": { + "labels": ["S-needs-code-changes", "S-needs-rebase", "S-tests-failed", + "S-needs-squash", "S-awaiting-review"] + }, + "expected": { + "labels": ["S-awaiting-merge"] + }, + "payload": { "action": "created", "issue": { @@ -197,3 +206,4 @@ "site_admin": false } } +} diff --git a/test_merge_conflict.json b/handlers/homu_status/tests/merge_conflict.json similarity index 98% rename from test_merge_conflict.json rename to handlers/homu_status/tests/merge_conflict.json index aacf788..1211e18 100644 --- a/test_merge_conflict.json +++ b/handlers/homu_status/tests/merge_conflict.json @@ -1,3 +1,11 @@ +{ + "initial": { + "labels": ["S-awaiting-merge"] + }, + "expected": { + "labels": ["S-needs-rebase"] + }, + "payload": { "action": "created", "issue": { @@ -197,3 +205,4 @@ "site_admin": false } } +} diff --git a/test_post_retry.json b/handlers/homu_status/tests/post_retry.json similarity index 97% rename from test_post_retry.json rename to handlers/homu_status/tests/post_retry.json index 9b8c521..4556ac8 100644 --- a/test_post_retry.json +++ b/handlers/homu_status/tests/post_retry.json @@ -1,3 +1,17 @@ +{ + "initial": [{ + "labels": ["S-tests-failed"] + }, + { + "labels": ["S-awaiting-merge"] + }], + "expected": [{ + "labels": ["S-awaiting-merge"] + }, + { + "labels": ["S-awaiting-merge"] + }], + "payload": { "action": "created", "issue": { @@ -197,3 +211,4 @@ "site_admin": false } } +} diff --git a/test_tests_failed.json b/handlers/homu_status/tests/tests_failed.json similarity index 98% rename from test_tests_failed.json rename to handlers/homu_status/tests/tests_failed.json index f98940d..1c37ee7 100644 --- a/test_tests_failed.json +++ b/handlers/homu_status/tests/tests_failed.json @@ -1,3 +1,11 @@ +{ + "initial": { + "labels": ["S-awaiting-merge"] + }, + "expected": { + "labels": ["S-tests-failed"] + }, + "payload": { "action": "created", "issue": { @@ -197,3 +205,4 @@ "site_admin": false } } +} diff --git a/handlers/missing_test/__init__.py b/handlers/missing_test/__init__.py index 618b8c5..4815a5a 100644 --- a/handlers/missing_test/__init__.py +++ b/handlers/missing_test/__init__.py @@ -1,5 +1,4 @@ from eventhandler import EventHandler -import random reftest_required_msg = 'These commits modify layout code, but no reftests are modified. Please consider adding a reftest!' diff --git a/handlers/unsafe/__init__.py b/handlers/unsafe/__init__.py index 001b0cc..a64656c 100644 --- a/handlers/unsafe/__init__.py +++ b/handlers/unsafe/__init__.py @@ -1,5 +1,4 @@ from eventhandler import EventHandler -import random unsafe_warning_msg = 'These commits modify **unsafe code**. Please review it carefully!' diff --git a/newpr.py b/newpr.py index a122784..8cb9f9c 100755 --- a/newpr.py +++ b/newpr.py @@ -176,18 +176,8 @@ def set_assignee(self, assignee): raise e -# If the user specified a reviewer, return the username, otherwise returns None. -def find_reviewer(commit_msg): - match = reviewer_re.search(commit_msg) - if not match: - return None - return match.group(1) - - warning_summary = 'warning **Warning** warning\n\n%s' -reviewer_re = re.compile("\\b[rR]\?[:\- ]*@([a-zA-Z0-9\-]+)") - def extract_globals_from_payload(payload): if payload["action"] == "created": owner = payload['repository']['owner']['login'] @@ -217,41 +207,6 @@ def manage_pr_state(api, payload): api.remove_label("S-needs-rebase") -def new_comment(api, payload): - # We only care about comments in open PRs - if payload['issue']['state'] != 'open' or 'pull_request' not in payload['issue']: - return - - commenter = payload['comment']['user']['login'] - # Ignore our own comments. - if commenter == api.user: - return - - msg = payload["comment"]["body"] - reviewer = find_reviewer(msg) - if reviewer: - api.set_assignee(reviewer) - - if commenter == 'bors-servo': - labels = api.get_labels(); - - if 'has been approved by' in msg or 'Testing commit' in msg: - for label in ["S-awaiting-review", "S-needs-rebase", "S-tests-failed", - "S-needs-code-changes", "S-needs-squash", "S-awaiting-answer"]: - if label in labels: - api.remove_label(label) - if not "S-awaiting-merge" in labels: - api.add_label("S-awaiting-merge") - - elif 'Test failed' in msg: - api.remove_label("S-awaiting-merge") - api.add_label("S-tests-failed") - - elif 'Please resolve the merge conflicts' in msg: - api.remove_label("S-awaiting-merge") - api.add_label("S-needs-rebase") - - def new_pr(api, payload): manage_pr_state(api, payload) @@ -272,7 +227,6 @@ def handle_payload(api, payload): for handler in handlers: handler.on_pr_updated(api, payload) elif payload["action"] == "created": - new_comment(api, payload) for handler in handlers: handler.on_new_comment(api, payload) else: diff --git a/test.py b/test.py index 3fd2a11..5eaaa5d 100644 --- a/test.py +++ b/test.py @@ -109,25 +109,7 @@ def setup_tests(): create_test('test_ignored_action.json', {}, {}), create_test('test_synchronize.json', {'labels': ['S-needs-code-changes', 'S-tests-failed', 'S-awaiting-merge']}, - {'labels': ['S-awaiting-review']}), - - create_test('test_comment.json', {}, {'assignee': 'jdm'}), - - create_test('test_merge_approved.json', {'labels': ['S-needs-code-changes', 'S-needs-rebase', - 'S-tests-failed', 'S-needs-squash', - 'S-awaiting-review']}, {'labels': ['S-awaiting-merge']}), - - create_test('test_merge_conflict.json', {'labels': ['S-awaiting-merge']}, - {'labels': ['S-needs-rebase']}), - - create_test('test_tests_failed.json', {'labels': ['S-awaiting-merge']}, - {'labels': ['S-tests-failed']}), - - create_test('test_post_retry.json', {'labels': ['S-tests-failed']}, - {'labels': ['S-awaiting-merge']}), - - create_test('test_post_retry.json', {'labels': ['S-awaiting-merge']}, - {'labels': ['S-awaiting-merge']}) + {'labels': ['S-awaiting-review']}) ] return tests From 9363d93ec65868d1afa33a16d3ceae85623f734d Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Thu, 26 Nov 2015 16:22:35 -0500 Subject: [PATCH 07/12] Convert label updates to a handler and remove all traces of pre-handler test setup. --- eventhandler.py | 2 +- handlers/status_update/__init__.py | 26 ++ .../status_update/tests/new_pr.json | 327 +++++++++--------- .../status_update/tests/synchronize.json | 9 + newpr.py | 27 -- test.py | 29 +- 6 files changed, 198 insertions(+), 222 deletions(-) create mode 100644 handlers/status_update/__init__.py rename test_ignored_action.json => handlers/status_update/tests/new_pr.json (58%) rename test_synchronize.json => handlers/status_update/tests/synchronize.json (99%) diff --git a/eventhandler.py b/eventhandler.py index 0c58807..3e28e0d 100644 --- a/eventhandler.py +++ b/eventhandler.py @@ -35,7 +35,7 @@ def register_tests(self, path): contents['initial'] = [contents['initial']] contents['expected'] = [contents['expected']] for initial, expected in zip(contents['initial'], contents['expected']): - yield create_test(testfile, initial, expected, True) + yield create_test(testfile, initial, expected) def reset_test_state(): global _warnings diff --git a/handlers/status_update/__init__.py b/handlers/status_update/__init__.py new file mode 100644 index 0000000..749f06d --- /dev/null +++ b/handlers/status_update/__init__.py @@ -0,0 +1,26 @@ +from eventhandler import EventHandler + +def manage_pr_state(api, payload): + labels = api.get_labels(); + + for label in ["S-awaiting-merge", "S-tests-failed", "S-needs-code-changes"]: + if label in labels: + api.remove_label(label) + if not "S-awaiting-review" in labels: + api.add_label("S-awaiting-review") + + # If mergeable is null, the data wasn't available yet. It would be nice to try to fetch that + # information again. + if payload["action"] == "synchronize" and payload['pull_request']['mergeable']: + if "S-needs-rebase" in labels: + api.remove_label("S-needs-rebase") + +class StatusUpdateHandler(EventHandler): + def on_pr_opened(self, api, payload): + manage_pr_state(api, payload) + + def on_pr_updated(self, api, payload): + manage_pr_state(api, payload) + + +handler_interface = StatusUpdateHandler diff --git a/test_ignored_action.json b/handlers/status_update/tests/new_pr.json similarity index 58% rename from test_ignored_action.json rename to handlers/status_update/tests/new_pr.json index 2850291..ab1cf33 100644 --- a/test_ignored_action.json +++ b/handlers/status_update/tests/new_pr.json @@ -1,169 +1,158 @@ { - "action": "labeled", - "number": 7066, + "initial": { + }, + "expected": { + "labels": ["S-awaiting-review"] + }, + "payload": +{ + "action": "opened", + "number": 7076, "pull_request": { - "url": "https://api.github.com/repos/servo/servo/pulls/7066", - "id": 41874546, - "html_url": "https://github.com/servo/servo/pull/7066", - "diff_url": "https://github.com/servo/servo/pull/7066.diff", - "patch_url": "https://github.com/servo/servo/pull/7066.patch", - "issue_url": "https://api.github.com/repos/servo/servo/issues/7066", - "number": 7066, + "url": "https://api.github.com/repos/servo/servo/pulls/7076", + "id": 41896942, + "html_url": "https://github.com/servo/servo/pull/7076", + "diff_url": "https://github.com/servo/servo/pull/7076.diff", + "patch_url": "https://github.com/servo/servo/pull/7076.patch", + "issue_url": "https://api.github.com/repos/servo/servo/issues/7076", + "number": 7076, "state": "open", "locked": false, - "title": "Dispatch message events for WebSocket.", + "title": "Remove invalid file path in ignored_files for tidying", "user": { - "login": "Ms2ger", - "id": 111161, - "avatar_url": "https://avatars.githubusercontent.com/u/111161?v=3", + "login": "frewsxcv", + "id": 416575, + "avatar_url": "https://avatars.githubusercontent.com/u/416575?v=3", "gravatar_id": "", - "url": "https://api.github.com/users/Ms2ger", - "html_url": "https://github.com/Ms2ger", - "followers_url": "https://api.github.com/users/Ms2ger/followers", - "following_url": "https://api.github.com/users/Ms2ger/following{/other_user}", - "gists_url": "https://api.github.com/users/Ms2ger/gists{/gist_id}", - "starred_url": "https://api.github.com/users/Ms2ger/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/Ms2ger/subscriptions", - "organizations_url": "https://api.github.com/users/Ms2ger/orgs", - "repos_url": "https://api.github.com/users/Ms2ger/repos", - "events_url": "https://api.github.com/users/Ms2ger/events{/privacy}", - "received_events_url": "https://api.github.com/users/Ms2ger/received_events", + "url": "https://api.github.com/users/frewsxcv", + "html_url": "https://github.com/frewsxcv", + "followers_url": "https://api.github.com/users/frewsxcv/followers", + "following_url": "https://api.github.com/users/frewsxcv/following{/other_user}", + "gists_url": "https://api.github.com/users/frewsxcv/gists{/gist_id}", + "starred_url": "https://api.github.com/users/frewsxcv/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/frewsxcv/subscriptions", + "organizations_url": "https://api.github.com/users/frewsxcv/orgs", + "repos_url": "https://api.github.com/users/frewsxcv/repos", + "events_url": "https://api.github.com/users/frewsxcv/events{/privacy}", + "received_events_url": "https://api.github.com/users/frewsxcv/received_events", "type": "User", "site_admin": false }, - "body": "\n\n\n[\"Review](https://reviewable.io/reviews/servo/servo/7066)\n\n", - "created_at": "2015-08-07T09:32:45Z", - "updated_at": "2015-08-07T16:13:17Z", + "body": null, + "created_at": "2015-08-07T14:24:50Z", + "updated_at": "2015-08-07T14:24:50Z", "closed_at": null, "merged_at": null, - "merge_commit_sha": "155eb5fd6e65dbcc70613c2f614f6eb0fc791baa", - "assignee": { - "login": "metajack", - "id": 28357, - "avatar_url": "https://avatars.githubusercontent.com/u/28357?v=3", - "gravatar_id": "", - "url": "https://api.github.com/users/metajack", - "html_url": "https://github.com/metajack", - "followers_url": "https://api.github.com/users/metajack/followers", - "following_url": "https://api.github.com/users/metajack/following{/other_user}", - "gists_url": "https://api.github.com/users/metajack/gists{/gist_id}", - "starred_url": "https://api.github.com/users/metajack/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/metajack/subscriptions", - "organizations_url": "https://api.github.com/users/metajack/orgs", - "repos_url": "https://api.github.com/users/metajack/repos", - "events_url": "https://api.github.com/users/metajack/events{/privacy}", - "received_events_url": "https://api.github.com/users/metajack/received_events", - "type": "User", - "site_admin": false - }, + "merge_commit_sha": null, + "assignee": null, "milestone": null, - "commits_url": "https://api.github.com/repos/servo/servo/pulls/7066/commits", - "review_comments_url": "https://api.github.com/repos/servo/servo/pulls/7066/comments", + "commits_url": "https://api.github.com/repos/servo/servo/pulls/7076/commits", + "review_comments_url": "https://api.github.com/repos/servo/servo/pulls/7076/comments", "review_comment_url": "https://api.github.com/repos/servo/servo/pulls/comments{/number}", - "comments_url": "https://api.github.com/repos/servo/servo/issues/7066/comments", - "statuses_url": "https://api.github.com/repos/servo/servo/statuses/749743f424cddd137c5d78d0bf6b49016a640c29", + "comments_url": "https://api.github.com/repos/servo/servo/issues/7076/comments", + "statuses_url": "https://api.github.com/repos/servo/servo/statuses/da44f31cb1debe2c8161ee280121d79d3dd5ec18", "head": { - "label": "Ms2ger:ws-event", - "ref": "ws-event", - "sha": "749743f424cddd137c5d78d0bf6b49016a640c29", + "label": "frewsxcv:tidy-rm-invalid-file", + "ref": "tidy-rm-invalid-file", + "sha": "da44f31cb1debe2c8161ee280121d79d3dd5ec18", "user": { - "login": "Ms2ger", - "id": 111161, - "avatar_url": "https://avatars.githubusercontent.com/u/111161?v=3", + "login": "frewsxcv", + "id": 416575, + "avatar_url": "https://avatars.githubusercontent.com/u/416575?v=3", "gravatar_id": "", - "url": "https://api.github.com/users/Ms2ger", - "html_url": "https://github.com/Ms2ger", - "followers_url": "https://api.github.com/users/Ms2ger/followers", - "following_url": "https://api.github.com/users/Ms2ger/following{/other_user}", - "gists_url": "https://api.github.com/users/Ms2ger/gists{/gist_id}", - "starred_url": "https://api.github.com/users/Ms2ger/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/Ms2ger/subscriptions", - "organizations_url": "https://api.github.com/users/Ms2ger/orgs", - "repos_url": "https://api.github.com/users/Ms2ger/repos", - "events_url": "https://api.github.com/users/Ms2ger/events{/privacy}", - "received_events_url": "https://api.github.com/users/Ms2ger/received_events", + "url": "https://api.github.com/users/frewsxcv", + "html_url": "https://github.com/frewsxcv", + "followers_url": "https://api.github.com/users/frewsxcv/followers", + "following_url": "https://api.github.com/users/frewsxcv/following{/other_user}", + "gists_url": "https://api.github.com/users/frewsxcv/gists{/gist_id}", + "starred_url": "https://api.github.com/users/frewsxcv/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/frewsxcv/subscriptions", + "organizations_url": "https://api.github.com/users/frewsxcv/orgs", + "repos_url": "https://api.github.com/users/frewsxcv/repos", + "events_url": "https://api.github.com/users/frewsxcv/events{/privacy}", + "received_events_url": "https://api.github.com/users/frewsxcv/received_events", "type": "User", "site_admin": false }, "repo": { - "id": 12599239, + "id": 27014207, "name": "servo", - "full_name": "Ms2ger/servo", + "full_name": "frewsxcv/servo", "owner": { - "login": "Ms2ger", - "id": 111161, - "avatar_url": "https://avatars.githubusercontent.com/u/111161?v=3", + "login": "frewsxcv", + "id": 416575, + "avatar_url": "https://avatars.githubusercontent.com/u/416575?v=3", "gravatar_id": "", - "url": "https://api.github.com/users/Ms2ger", - "html_url": "https://github.com/Ms2ger", - "followers_url": "https://api.github.com/users/Ms2ger/followers", - "following_url": "https://api.github.com/users/Ms2ger/following{/other_user}", - "gists_url": "https://api.github.com/users/Ms2ger/gists{/gist_id}", - "starred_url": "https://api.github.com/users/Ms2ger/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/Ms2ger/subscriptions", - "organizations_url": "https://api.github.com/users/Ms2ger/orgs", - "repos_url": "https://api.github.com/users/Ms2ger/repos", - "events_url": "https://api.github.com/users/Ms2ger/events{/privacy}", - "received_events_url": "https://api.github.com/users/Ms2ger/received_events", + "url": "https://api.github.com/users/frewsxcv", + "html_url": "https://github.com/frewsxcv", + "followers_url": "https://api.github.com/users/frewsxcv/followers", + "following_url": "https://api.github.com/users/frewsxcv/following{/other_user}", + "gists_url": "https://api.github.com/users/frewsxcv/gists{/gist_id}", + "starred_url": "https://api.github.com/users/frewsxcv/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/frewsxcv/subscriptions", + "organizations_url": "https://api.github.com/users/frewsxcv/orgs", + "repos_url": "https://api.github.com/users/frewsxcv/repos", + "events_url": "https://api.github.com/users/frewsxcv/events{/privacy}", + "received_events_url": "https://api.github.com/users/frewsxcv/received_events", "type": "User", "site_admin": false }, "private": false, - "html_url": "https://github.com/Ms2ger/servo", + "html_url": "https://github.com/frewsxcv/servo", "description": "The Servo Browser Engine", "fork": true, - "url": "https://api.github.com/repos/Ms2ger/servo", - "forks_url": "https://api.github.com/repos/Ms2ger/servo/forks", - "keys_url": "https://api.github.com/repos/Ms2ger/servo/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/Ms2ger/servo/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/Ms2ger/servo/teams", - "hooks_url": "https://api.github.com/repos/Ms2ger/servo/hooks", - "issue_events_url": "https://api.github.com/repos/Ms2ger/servo/issues/events{/number}", - "events_url": "https://api.github.com/repos/Ms2ger/servo/events", - "assignees_url": "https://api.github.com/repos/Ms2ger/servo/assignees{/user}", - "branches_url": "https://api.github.com/repos/Ms2ger/servo/branches{/branch}", - "tags_url": "https://api.github.com/repos/Ms2ger/servo/tags", - "blobs_url": "https://api.github.com/repos/Ms2ger/servo/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/Ms2ger/servo/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/Ms2ger/servo/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/Ms2ger/servo/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/Ms2ger/servo/statuses/{sha}", - "languages_url": "https://api.github.com/repos/Ms2ger/servo/languages", - "stargazers_url": "https://api.github.com/repos/Ms2ger/servo/stargazers", - "contributors_url": "https://api.github.com/repos/Ms2ger/servo/contributors", - "subscribers_url": "https://api.github.com/repos/Ms2ger/servo/subscribers", - "subscription_url": "https://api.github.com/repos/Ms2ger/servo/subscription", - "commits_url": "https://api.github.com/repos/Ms2ger/servo/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/Ms2ger/servo/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/Ms2ger/servo/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/Ms2ger/servo/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/Ms2ger/servo/contents/{+path}", - "compare_url": "https://api.github.com/repos/Ms2ger/servo/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/Ms2ger/servo/merges", - "archive_url": "https://api.github.com/repos/Ms2ger/servo/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/Ms2ger/servo/downloads", - "issues_url": "https://api.github.com/repos/Ms2ger/servo/issues{/number}", - "pulls_url": "https://api.github.com/repos/Ms2ger/servo/pulls{/number}", - "milestones_url": "https://api.github.com/repos/Ms2ger/servo/milestones{/number}", - "notifications_url": "https://api.github.com/repos/Ms2ger/servo/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/Ms2ger/servo/labels{/name}", - "releases_url": "https://api.github.com/repos/Ms2ger/servo/releases{/id}", - "created_at": "2013-09-04T18:49:05Z", - "updated_at": "2015-06-21T07:02:55Z", - "pushed_at": "2015-08-07T14:34:22Z", - "git_url": "git://github.com/Ms2ger/servo.git", - "ssh_url": "git@github.com:Ms2ger/servo.git", - "clone_url": "https://github.com/Ms2ger/servo.git", - "svn_url": "https://github.com/Ms2ger/servo", + "url": "https://api.github.com/repos/frewsxcv/servo", + "forks_url": "https://api.github.com/repos/frewsxcv/servo/forks", + "keys_url": "https://api.github.com/repos/frewsxcv/servo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/frewsxcv/servo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/frewsxcv/servo/teams", + "hooks_url": "https://api.github.com/repos/frewsxcv/servo/hooks", + "issue_events_url": "https://api.github.com/repos/frewsxcv/servo/issues/events{/number}", + "events_url": "https://api.github.com/repos/frewsxcv/servo/events", + "assignees_url": "https://api.github.com/repos/frewsxcv/servo/assignees{/user}", + "branches_url": "https://api.github.com/repos/frewsxcv/servo/branches{/branch}", + "tags_url": "https://api.github.com/repos/frewsxcv/servo/tags", + "blobs_url": "https://api.github.com/repos/frewsxcv/servo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/frewsxcv/servo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/frewsxcv/servo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/frewsxcv/servo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/frewsxcv/servo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/frewsxcv/servo/languages", + "stargazers_url": "https://api.github.com/repos/frewsxcv/servo/stargazers", + "contributors_url": "https://api.github.com/repos/frewsxcv/servo/contributors", + "subscribers_url": "https://api.github.com/repos/frewsxcv/servo/subscribers", + "subscription_url": "https://api.github.com/repos/frewsxcv/servo/subscription", + "commits_url": "https://api.github.com/repos/frewsxcv/servo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/frewsxcv/servo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/frewsxcv/servo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/frewsxcv/servo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/frewsxcv/servo/contents/{+path}", + "compare_url": "https://api.github.com/repos/frewsxcv/servo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/frewsxcv/servo/merges", + "archive_url": "https://api.github.com/repos/frewsxcv/servo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/frewsxcv/servo/downloads", + "issues_url": "https://api.github.com/repos/frewsxcv/servo/issues{/number}", + "pulls_url": "https://api.github.com/repos/frewsxcv/servo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/frewsxcv/servo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/frewsxcv/servo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/frewsxcv/servo/labels{/name}", + "releases_url": "https://api.github.com/repos/frewsxcv/servo/releases{/id}", + "created_at": "2014-11-22T22:10:35Z", + "updated_at": "2014-11-22T22:10:38Z", + "pushed_at": "2015-08-07T14:24:45Z", + "git_url": "git://github.com/frewsxcv/servo.git", + "ssh_url": "git@github.com:frewsxcv/servo.git", + "clone_url": "https://github.com/frewsxcv/servo.git", + "svn_url": "https://github.com/frewsxcv/servo", "homepage": "", - "size": 124200, + "size": 119557, "stargazers_count": 0, "watchers_count": 0, "language": "Rust", "has_issues": false, "has_downloads": true, "has_wiki": true, - "has_pages": false, + "has_pages": true, "forks_count": 0, "mirror_url": null, "open_issues_count": 0, @@ -176,7 +165,7 @@ "base": { "label": "servo:master", "ref": "master", - "sha": "44c4bb00c1cb8645ee2fc303848a5136108e594f", + "sha": "b4e30da3dbf58c16703864f4bec4b0b0132084fa", "user": { "login": "servo", "id": 2566135, @@ -261,13 +250,13 @@ "releases_url": "https://api.github.com/repos/servo/servo/releases{/id}", "created_at": "2012-02-08T19:07:25Z", "updated_at": "2015-08-07T09:37:49Z", - "pushed_at": "2015-08-07T16:09:30Z", + "pushed_at": "2015-08-07T14:10:08Z", "git_url": "git://github.com/servo/servo.git", "ssh_url": "git@github.com:servo/servo.git", "clone_url": "https://github.com/servo/servo.git", "svn_url": "https://github.com/servo/servo", "homepage": "", - "size": 1903023, + "size": 1904176, "stargazers_count": 4571, "watchers_count": 4571, "language": "Rust", @@ -277,54 +266,49 @@ "has_pages": false, "forks_count": 717, "mirror_url": null, - "open_issues_count": 1057, + "open_issues_count": 1060, "forks": 717, - "open_issues": 1057, + "open_issues": 1060, "watchers": 4571, "default_branch": "master" } }, "_links": { "self": { - "href": "https://api.github.com/repos/servo/servo/pulls/7066" + "href": "https://api.github.com/repos/servo/servo/pulls/7076" }, "html": { - "href": "https://github.com/servo/servo/pull/7066" + "href": "https://github.com/servo/servo/pull/7076" }, "issue": { - "href": "https://api.github.com/repos/servo/servo/issues/7066" + "href": "https://api.github.com/repos/servo/servo/issues/7076" }, "comments": { - "href": "https://api.github.com/repos/servo/servo/issues/7066/comments" + "href": "https://api.github.com/repos/servo/servo/issues/7076/comments" }, "review_comments": { - "href": "https://api.github.com/repos/servo/servo/pulls/7066/comments" + "href": "https://api.github.com/repos/servo/servo/pulls/7076/comments" }, "review_comment": { "href": "https://api.github.com/repos/servo/servo/pulls/comments{/number}" }, "commits": { - "href": "https://api.github.com/repos/servo/servo/pulls/7066/commits" + "href": "https://api.github.com/repos/servo/servo/pulls/7076/commits" }, "statuses": { - "href": "https://api.github.com/repos/servo/servo/statuses/749743f424cddd137c5d78d0bf6b49016a640c29" + "href": "https://api.github.com/repos/servo/servo/statuses/da44f31cb1debe2c8161ee280121d79d3dd5ec18" } }, "merged": false, - "mergeable": true, - "mergeable_state": "clean", + "mergeable": null, + "mergeable_state": "unknown", "merged_by": null, "comments": 0, "review_comments": 0, - "commits": 2, - "additions": 127, - "deletions": 421, - "changed_files": 86 - }, - "label": { - "url": "https://api.github.com/repos/servo/servo/labels/S-awaiting-merge", - "name": "S-awaiting-merge", - "color": "d4c5f9" + "commits": 1, + "additions": 0, + "deletions": 1, + "changed_files": 1 }, "repository": { "id": 3390243, @@ -391,13 +375,13 @@ "releases_url": "https://api.github.com/repos/servo/servo/releases{/id}", "created_at": "2012-02-08T19:07:25Z", "updated_at": "2015-08-07T09:37:49Z", - "pushed_at": "2015-08-07T16:09:30Z", + "pushed_at": "2015-08-07T14:10:08Z", "git_url": "git://github.com/servo/servo.git", "ssh_url": "git@github.com:servo/servo.git", "clone_url": "https://github.com/servo/servo.git", "svn_url": "https://github.com/servo/servo", "homepage": "", - "size": 1903023, + "size": 1904176, "stargazers_count": 4571, "watchers_count": 4571, "language": "Rust", @@ -407,9 +391,9 @@ "has_pages": false, "forks_count": 717, "mirror_url": null, - "open_issues_count": 1057, + "open_issues_count": 1060, "forks": 717, - "open_issues": 1057, + "open_issues": 1060, "watchers": 4571, "default_branch": "master" }, @@ -425,22 +409,23 @@ "description": null }, "sender": { - "login": "metajack", - "id": 28357, - "avatar_url": "https://avatars.githubusercontent.com/u/28357?v=3", + "login": "frewsxcv", + "id": 416575, + "avatar_url": "https://avatars.githubusercontent.com/u/416575?v=3", "gravatar_id": "", - "url": "https://api.github.com/users/metajack", - "html_url": "https://github.com/metajack", - "followers_url": "https://api.github.com/users/metajack/followers", - "following_url": "https://api.github.com/users/metajack/following{/other_user}", - "gists_url": "https://api.github.com/users/metajack/gists{/gist_id}", - "starred_url": "https://api.github.com/users/metajack/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/metajack/subscriptions", - "organizations_url": "https://api.github.com/users/metajack/orgs", - "repos_url": "https://api.github.com/users/metajack/repos", - "events_url": "https://api.github.com/users/metajack/events{/privacy}", - "received_events_url": "https://api.github.com/users/metajack/received_events", + "url": "https://api.github.com/users/frewsxcv", + "html_url": "https://github.com/frewsxcv", + "followers_url": "https://api.github.com/users/frewsxcv/followers", + "following_url": "https://api.github.com/users/frewsxcv/following{/other_user}", + "gists_url": "https://api.github.com/users/frewsxcv/gists{/gist_id}", + "starred_url": "https://api.github.com/users/frewsxcv/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/frewsxcv/subscriptions", + "organizations_url": "https://api.github.com/users/frewsxcv/orgs", + "repos_url": "https://api.github.com/users/frewsxcv/repos", + "events_url": "https://api.github.com/users/frewsxcv/events{/privacy}", + "received_events_url": "https://api.github.com/users/frewsxcv/received_events", "type": "User", "site_admin": false } } +} diff --git a/test_synchronize.json b/handlers/status_update/tests/synchronize.json similarity index 99% rename from test_synchronize.json rename to handlers/status_update/tests/synchronize.json index 1b26d31..3b724f5 100644 --- a/test_synchronize.json +++ b/handlers/status_update/tests/synchronize.json @@ -1,3 +1,11 @@ +{ + "initial": { + "labels": ["S-needs-code-changes", "S-tests-failed", "S-awaiting-merge"] + }, + "expected": { + "labels": ["S-awaiting-review"] + }, + "payload": { "action": "synchronize", "number": 7062, @@ -421,3 +429,4 @@ "site_admin": false } } +} diff --git a/newpr.py b/newpr.py index 8cb9f9c..2857bbd 100755 --- a/newpr.py +++ b/newpr.py @@ -190,40 +190,13 @@ def extract_globals_from_payload(payload): return (owner, repo, issue) -def manage_pr_state(api, payload): - labels = api.get_labels(); - - if payload["action"] in ["synchronize", "opened"]: - for label in ["S-awaiting-merge", "S-tests-failed", "S-needs-code-changes"]: - if label in labels: - api.remove_label(label) - if not "S-awaiting-review" in labels: - api.add_label("S-awaiting-review") - - # If mergeable is null, the data wasn't available yet. It would be nice to try to fetch that - # information again. - if payload["action"] == "synchronize" and payload['pull_request']['mergeable']: - if "S-needs-rebase" in labels: - api.remove_label("S-needs-rebase") - - -def new_pr(api, payload): - manage_pr_state(api, payload) - - -def update_pr(api, payload): - manage_pr_state(api, payload) - - def handle_payload(api, payload): (modules, handlers) = eventhandler.get_handlers() if payload["action"] == "opened": - new_pr(api, payload) for handler in handlers: handler.on_pr_opened(api, payload) elif payload["action"] == "synchronize": - update_pr(api, payload) for handler in handlers: handler.on_pr_updated(api, payload) elif payload["action"] == "created": diff --git a/test.py b/test.py index 5eaaa5d..88d6fc2 100644 --- a/test.py +++ b/test.py @@ -38,22 +38,16 @@ def get_payload(filename): with open(filename) as f: return json.load(f) -def create_test(filename, initial, expected, new_style=False): +def create_test(filename, initial, expected): global tests initial_values = {'new_contributor': initial.get('new_contributor', False), 'labels': initial.get('labels', []), 'diff': initial.get('diff', ''), 'assignee': initial.get('assignee', None)} - if new_style: - expected_values = expected - else: - expected_values = {'labels': expected.get('labels', []), - 'assignee': expected.get('assignee', None), - 'comments': expected.get('comments', 0)} + expected_values = expected return {'filename': filename, 'initial': initial_values, - 'expected': expected_values, - 'ignore_missing_expected': new_style} + 'expected': expected} def run_tests(tests): import eventhandler @@ -70,12 +64,11 @@ def run_tests(tests): initial['assignee'], initial['diff']) handle_payload(api, payload) expected = test['expected'] - ignore_missing = test['ignore_missing_expected'] - if not ignore_missing or 'comments' in expected: + if 'comments' in expected: assert len(api.comments_posted) == expected['comments'] - if not ignore_missing or 'labels' in expected: + if 'labels' in expected: assert api.labels == expected['labels'] - if not ignore_missing or 'assignee' in expected: + if 'assignee' in expected: assert api.assignee == expected['assignee'] except AssertionError: _, _, tb = sys.exc_info() @@ -101,16 +94,6 @@ def setup_tests(): tests = [] for module, handler in zip(modules, handlers): tests.extend(handler.register_tests(module[1])) - - tests += [ - create_test('test_new_pr.json', {'new_contributor': True}, - {'labels': ['S-awaiting-review'], 'comments': 1}), - - create_test('test_ignored_action.json', {}, {}), - - create_test('test_synchronize.json', {'labels': ['S-needs-code-changes', 'S-tests-failed', 'S-awaiting-merge']}, - {'labels': ['S-awaiting-review']}) - ] return tests if __name__ == "__main__": From 6c670a0bd38eba07b77c0d2dcfe9d18e842786ea Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Thu, 26 Nov 2015 16:28:37 -0500 Subject: [PATCH 08/12] Cache API-dependent values that could be requested by multiple handlers. --- newpr.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/newpr.py b/newpr.py index 2857bbd..4cbbd1c 100755 --- a/newpr.py +++ b/newpr.py @@ -58,6 +58,8 @@ class GithubAPIProvider(APIProvider): def __init__(self, payload, user, token): APIProvider.__init__(self, payload, user) self.token = token + self._labels = None + self._diff = None if "pull_request" in payload: self.diff_url = payload["pull_request"]["diff_url"] @@ -133,6 +135,8 @@ def post_comment(self, body): raise e def add_label(self, label): + if self._labels: + self._labels += [label] try: result = self.api_req("POST", self.add_label_url % (self.owner, self.repo, self.issue), [label]) @@ -143,6 +147,8 @@ def add_label(self, label): raise e def remove_label(self, label): + if self._labels and label in self._labels: + self._labels.remove(label) try: result = self.api_req("DELETE", self.remove_label_url % (self.owner, self.repo, self.issue, label), {}) except urllib2.HTTPError, e: @@ -153,6 +159,8 @@ def remove_label(self, label): pass def get_labels(self): + if self._labels is not None: + return self._labels try: result = self.api_req("GET", self.get_label_url % (self.owner, self.repo, self.issue)) except urllib2.HTTPError, e: @@ -160,10 +168,14 @@ def get_labels(self): pass else: raise e - return map(lambda x: x["name"], json.loads(result['body'])) + self._labels = map(lambda x: x["name"], json.loads(result['body'])) + return self._labels def get_diff(self): - return self.api_req("GET", self.diff_url)['body'] + if self._diff: + return self._diff; + self._diff = self.api_req("GET", self.diff_url)['body'] + return self._diff def set_assignee(self, assignee): try: From c9b9d072ba620791bf9b11253bb5214c36f0ca15 Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Thu, 26 Nov 2015 16:46:41 -0500 Subject: [PATCH 09/12] Improve documentation. --- README.md | 43 ++++++++++++++++++++++++++++++++++++++++--- test.py | 1 - 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 7968217..07c8808 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,44 @@ Highfive ======== -GitHub hooks to provide an encouraging atmosphere for new contributors +GitHub hooks to provide an encouraging atmosphere for new contributors. -Docs for this highfive live [on the Servo -wiki](https://github.com/servo/servo/wiki/Highfive) +Docs for the highfive instance for servo/servo repository live [on the Servo +wiki](https://github.com/servo/servo/wiki/Highfive). + +## Design + +Highfive is built as a modular, loosely-coupled set of handlers for Github +API events. Each time an API event is processed, each handler is given the +opportunity to respond to it, either by making direct API calls (such as +manipulating PR labels) or using cross-handler features such as logging a +warning (which are aggregated at the end and posted as a single comment). + +## Testing + +Per-handler tests can be run using `python test.py`. These consist of +a set of JSON documents collected from the `tests/` subdirectory of +each handler, using the following format: +```json +{ + "initial": { + // Initial state of the PR before any handlers process the payload. + // Defaults: + "labels": [], + "diff": "", + "new_contributor": False, + "assignee": None, + }, + "expected": { + // Expected state of the PR after all the handlers process + // the following payload. + // Only fields present in this object will be checked. + // comments: 5, + // labels: ["S-awaiting-review"], + // assignee: "jdm" + }, + "payload": { + // Github API event payload in JSON format + } +} +``` diff --git a/test.py b/test.py index 88d6fc2..176739d 100644 --- a/test.py +++ b/test.py @@ -44,7 +44,6 @@ def create_test(filename, initial, expected): 'labels': initial.get('labels', []), 'diff': initial.get('diff', ''), 'assignee': initial.get('assignee', None)} - expected_values = expected return {'filename': filename, 'initial': initial_values, 'expected': expected} From f1a1d0a26dcae5413eebb2adf9f5640290f56eae Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Thu, 26 Nov 2015 16:46:58 -0500 Subject: [PATCH 10/12] Remove unused test file. --- test_new_pr.json | 423 ----------------------------------------------- 1 file changed, 423 deletions(-) delete mode 100644 test_new_pr.json diff --git a/test_new_pr.json b/test_new_pr.json deleted file mode 100644 index 91bd48d..0000000 --- a/test_new_pr.json +++ /dev/null @@ -1,423 +0,0 @@ -{ - "action": "opened", - "number": 7076, - "pull_request": { - "url": "https://api.github.com/repos/servo/servo/pulls/7076", - "id": 41896942, - "html_url": "https://github.com/servo/servo/pull/7076", - "diff_url": "https://github.com/servo/servo/pull/7076.diff", - "patch_url": "https://github.com/servo/servo/pull/7076.patch", - "issue_url": "https://api.github.com/repos/servo/servo/issues/7076", - "number": 7076, - "state": "open", - "locked": false, - "title": "Remove invalid file path in ignored_files for tidying", - "user": { - "login": "frewsxcv", - "id": 416575, - "avatar_url": "https://avatars.githubusercontent.com/u/416575?v=3", - "gravatar_id": "", - "url": "https://api.github.com/users/frewsxcv", - "html_url": "https://github.com/frewsxcv", - "followers_url": "https://api.github.com/users/frewsxcv/followers", - "following_url": "https://api.github.com/users/frewsxcv/following{/other_user}", - "gists_url": "https://api.github.com/users/frewsxcv/gists{/gist_id}", - "starred_url": "https://api.github.com/users/frewsxcv/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/frewsxcv/subscriptions", - "organizations_url": "https://api.github.com/users/frewsxcv/orgs", - "repos_url": "https://api.github.com/users/frewsxcv/repos", - "events_url": "https://api.github.com/users/frewsxcv/events{/privacy}", - "received_events_url": "https://api.github.com/users/frewsxcv/received_events", - "type": "User", - "site_admin": false - }, - "body": null, - "created_at": "2015-08-07T14:24:50Z", - "updated_at": "2015-08-07T14:24:50Z", - "closed_at": null, - "merged_at": null, - "merge_commit_sha": null, - "assignee": null, - "milestone": null, - "commits_url": "https://api.github.com/repos/servo/servo/pulls/7076/commits", - "review_comments_url": "https://api.github.com/repos/servo/servo/pulls/7076/comments", - "review_comment_url": "https://api.github.com/repos/servo/servo/pulls/comments{/number}", - "comments_url": "https://api.github.com/repos/servo/servo/issues/7076/comments", - "statuses_url": "https://api.github.com/repos/servo/servo/statuses/da44f31cb1debe2c8161ee280121d79d3dd5ec18", - "head": { - "label": "frewsxcv:tidy-rm-invalid-file", - "ref": "tidy-rm-invalid-file", - "sha": "da44f31cb1debe2c8161ee280121d79d3dd5ec18", - "user": { - "login": "frewsxcv", - "id": 416575, - "avatar_url": "https://avatars.githubusercontent.com/u/416575?v=3", - "gravatar_id": "", - "url": "https://api.github.com/users/frewsxcv", - "html_url": "https://github.com/frewsxcv", - "followers_url": "https://api.github.com/users/frewsxcv/followers", - "following_url": "https://api.github.com/users/frewsxcv/following{/other_user}", - "gists_url": "https://api.github.com/users/frewsxcv/gists{/gist_id}", - "starred_url": "https://api.github.com/users/frewsxcv/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/frewsxcv/subscriptions", - "organizations_url": "https://api.github.com/users/frewsxcv/orgs", - "repos_url": "https://api.github.com/users/frewsxcv/repos", - "events_url": "https://api.github.com/users/frewsxcv/events{/privacy}", - "received_events_url": "https://api.github.com/users/frewsxcv/received_events", - "type": "User", - "site_admin": false - }, - "repo": { - "id": 27014207, - "name": "servo", - "full_name": "frewsxcv/servo", - "owner": { - "login": "frewsxcv", - "id": 416575, - "avatar_url": "https://avatars.githubusercontent.com/u/416575?v=3", - "gravatar_id": "", - "url": "https://api.github.com/users/frewsxcv", - "html_url": "https://github.com/frewsxcv", - "followers_url": "https://api.github.com/users/frewsxcv/followers", - "following_url": "https://api.github.com/users/frewsxcv/following{/other_user}", - "gists_url": "https://api.github.com/users/frewsxcv/gists{/gist_id}", - "starred_url": "https://api.github.com/users/frewsxcv/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/frewsxcv/subscriptions", - "organizations_url": "https://api.github.com/users/frewsxcv/orgs", - "repos_url": "https://api.github.com/users/frewsxcv/repos", - "events_url": "https://api.github.com/users/frewsxcv/events{/privacy}", - "received_events_url": "https://api.github.com/users/frewsxcv/received_events", - "type": "User", - "site_admin": false - }, - "private": false, - "html_url": "https://github.com/frewsxcv/servo", - "description": "The Servo Browser Engine", - "fork": true, - "url": "https://api.github.com/repos/frewsxcv/servo", - "forks_url": "https://api.github.com/repos/frewsxcv/servo/forks", - "keys_url": "https://api.github.com/repos/frewsxcv/servo/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/frewsxcv/servo/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/frewsxcv/servo/teams", - "hooks_url": "https://api.github.com/repos/frewsxcv/servo/hooks", - "issue_events_url": "https://api.github.com/repos/frewsxcv/servo/issues/events{/number}", - "events_url": "https://api.github.com/repos/frewsxcv/servo/events", - "assignees_url": "https://api.github.com/repos/frewsxcv/servo/assignees{/user}", - "branches_url": "https://api.github.com/repos/frewsxcv/servo/branches{/branch}", - "tags_url": "https://api.github.com/repos/frewsxcv/servo/tags", - "blobs_url": "https://api.github.com/repos/frewsxcv/servo/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/frewsxcv/servo/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/frewsxcv/servo/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/frewsxcv/servo/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/frewsxcv/servo/statuses/{sha}", - "languages_url": "https://api.github.com/repos/frewsxcv/servo/languages", - "stargazers_url": "https://api.github.com/repos/frewsxcv/servo/stargazers", - "contributors_url": "https://api.github.com/repos/frewsxcv/servo/contributors", - "subscribers_url": "https://api.github.com/repos/frewsxcv/servo/subscribers", - "subscription_url": "https://api.github.com/repos/frewsxcv/servo/subscription", - "commits_url": "https://api.github.com/repos/frewsxcv/servo/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/frewsxcv/servo/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/frewsxcv/servo/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/frewsxcv/servo/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/frewsxcv/servo/contents/{+path}", - "compare_url": "https://api.github.com/repos/frewsxcv/servo/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/frewsxcv/servo/merges", - "archive_url": "https://api.github.com/repos/frewsxcv/servo/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/frewsxcv/servo/downloads", - "issues_url": "https://api.github.com/repos/frewsxcv/servo/issues{/number}", - "pulls_url": "https://api.github.com/repos/frewsxcv/servo/pulls{/number}", - "milestones_url": "https://api.github.com/repos/frewsxcv/servo/milestones{/number}", - "notifications_url": "https://api.github.com/repos/frewsxcv/servo/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/frewsxcv/servo/labels{/name}", - "releases_url": "https://api.github.com/repos/frewsxcv/servo/releases{/id}", - "created_at": "2014-11-22T22:10:35Z", - "updated_at": "2014-11-22T22:10:38Z", - "pushed_at": "2015-08-07T14:24:45Z", - "git_url": "git://github.com/frewsxcv/servo.git", - "ssh_url": "git@github.com:frewsxcv/servo.git", - "clone_url": "https://github.com/frewsxcv/servo.git", - "svn_url": "https://github.com/frewsxcv/servo", - "homepage": "", - "size": 119557, - "stargazers_count": 0, - "watchers_count": 0, - "language": "Rust", - "has_issues": false, - "has_downloads": true, - "has_wiki": true, - "has_pages": true, - "forks_count": 0, - "mirror_url": null, - "open_issues_count": 0, - "forks": 0, - "open_issues": 0, - "watchers": 0, - "default_branch": "master" - } - }, - "base": { - "label": "servo:master", - "ref": "master", - "sha": "b4e30da3dbf58c16703864f4bec4b0b0132084fa", - "user": { - "login": "servo", - "id": 2566135, - "avatar_url": "https://avatars.githubusercontent.com/u/2566135?v=3", - "gravatar_id": "", - "url": "https://api.github.com/users/servo", - "html_url": "https://github.com/servo", - "followers_url": "https://api.github.com/users/servo/followers", - "following_url": "https://api.github.com/users/servo/following{/other_user}", - "gists_url": "https://api.github.com/users/servo/gists{/gist_id}", - "starred_url": "https://api.github.com/users/servo/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/servo/subscriptions", - "organizations_url": "https://api.github.com/users/servo/orgs", - "repos_url": "https://api.github.com/users/servo/repos", - "events_url": "https://api.github.com/users/servo/events{/privacy}", - "received_events_url": "https://api.github.com/users/servo/received_events", - "type": "Organization", - "site_admin": false - }, - "repo": { - "id": 3390243, - "name": "servo", - "full_name": "servo/servo", - "owner": { - "login": "servo", - "id": 2566135, - "avatar_url": "https://avatars.githubusercontent.com/u/2566135?v=3", - "gravatar_id": "", - "url": "https://api.github.com/users/servo", - "html_url": "https://github.com/servo", - "followers_url": "https://api.github.com/users/servo/followers", - "following_url": "https://api.github.com/users/servo/following{/other_user}", - "gists_url": "https://api.github.com/users/servo/gists{/gist_id}", - "starred_url": "https://api.github.com/users/servo/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/servo/subscriptions", - "organizations_url": "https://api.github.com/users/servo/orgs", - "repos_url": "https://api.github.com/users/servo/repos", - "events_url": "https://api.github.com/users/servo/events{/privacy}", - "received_events_url": "https://api.github.com/users/servo/received_events", - "type": "Organization", - "site_admin": false - }, - "private": false, - "html_url": "https://github.com/servo/servo", - "description": "The Servo Browser Engine", - "fork": false, - "url": "https://api.github.com/repos/servo/servo", - "forks_url": "https://api.github.com/repos/servo/servo/forks", - "keys_url": "https://api.github.com/repos/servo/servo/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/servo/servo/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/servo/servo/teams", - "hooks_url": "https://api.github.com/repos/servo/servo/hooks", - "issue_events_url": "https://api.github.com/repos/servo/servo/issues/events{/number}", - "events_url": "https://api.github.com/repos/servo/servo/events", - "assignees_url": "https://api.github.com/repos/servo/servo/assignees{/user}", - "branches_url": "https://api.github.com/repos/servo/servo/branches{/branch}", - "tags_url": "https://api.github.com/repos/servo/servo/tags", - "blobs_url": "https://api.github.com/repos/servo/servo/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/servo/servo/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/servo/servo/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/servo/servo/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/servo/servo/statuses/{sha}", - "languages_url": "https://api.github.com/repos/servo/servo/languages", - "stargazers_url": "https://api.github.com/repos/servo/servo/stargazers", - "contributors_url": "https://api.github.com/repos/servo/servo/contributors", - "subscribers_url": "https://api.github.com/repos/servo/servo/subscribers", - "subscription_url": "https://api.github.com/repos/servo/servo/subscription", - "commits_url": "https://api.github.com/repos/servo/servo/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/servo/servo/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/servo/servo/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/servo/servo/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/servo/servo/contents/{+path}", - "compare_url": "https://api.github.com/repos/servo/servo/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/servo/servo/merges", - "archive_url": "https://api.github.com/repos/servo/servo/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/servo/servo/downloads", - "issues_url": "https://api.github.com/repos/servo/servo/issues{/number}", - "pulls_url": "https://api.github.com/repos/servo/servo/pulls{/number}", - "milestones_url": "https://api.github.com/repos/servo/servo/milestones{/number}", - "notifications_url": "https://api.github.com/repos/servo/servo/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/servo/servo/labels{/name}", - "releases_url": "https://api.github.com/repos/servo/servo/releases{/id}", - "created_at": "2012-02-08T19:07:25Z", - "updated_at": "2015-08-07T09:37:49Z", - "pushed_at": "2015-08-07T14:10:08Z", - "git_url": "git://github.com/servo/servo.git", - "ssh_url": "git@github.com:servo/servo.git", - "clone_url": "https://github.com/servo/servo.git", - "svn_url": "https://github.com/servo/servo", - "homepage": "", - "size": 1904176, - "stargazers_count": 4571, - "watchers_count": 4571, - "language": "Rust", - "has_issues": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "forks_count": 717, - "mirror_url": null, - "open_issues_count": 1060, - "forks": 717, - "open_issues": 1060, - "watchers": 4571, - "default_branch": "master" - } - }, - "_links": { - "self": { - "href": "https://api.github.com/repos/servo/servo/pulls/7076" - }, - "html": { - "href": "https://github.com/servo/servo/pull/7076" - }, - "issue": { - "href": "https://api.github.com/repos/servo/servo/issues/7076" - }, - "comments": { - "href": "https://api.github.com/repos/servo/servo/issues/7076/comments" - }, - "review_comments": { - "href": "https://api.github.com/repos/servo/servo/pulls/7076/comments" - }, - "review_comment": { - "href": "https://api.github.com/repos/servo/servo/pulls/comments{/number}" - }, - "commits": { - "href": "https://api.github.com/repos/servo/servo/pulls/7076/commits" - }, - "statuses": { - "href": "https://api.github.com/repos/servo/servo/statuses/da44f31cb1debe2c8161ee280121d79d3dd5ec18" - } - }, - "merged": false, - "mergeable": null, - "mergeable_state": "unknown", - "merged_by": null, - "comments": 0, - "review_comments": 0, - "commits": 1, - "additions": 0, - "deletions": 1, - "changed_files": 1 - }, - "repository": { - "id": 3390243, - "name": "servo", - "full_name": "servo/servo", - "owner": { - "login": "servo", - "id": 2566135, - "avatar_url": "https://avatars.githubusercontent.com/u/2566135?v=3", - "gravatar_id": "", - "url": "https://api.github.com/users/servo", - "html_url": "https://github.com/servo", - "followers_url": "https://api.github.com/users/servo/followers", - "following_url": "https://api.github.com/users/servo/following{/other_user}", - "gists_url": "https://api.github.com/users/servo/gists{/gist_id}", - "starred_url": "https://api.github.com/users/servo/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/servo/subscriptions", - "organizations_url": "https://api.github.com/users/servo/orgs", - "repos_url": "https://api.github.com/users/servo/repos", - "events_url": "https://api.github.com/users/servo/events{/privacy}", - "received_events_url": "https://api.github.com/users/servo/received_events", - "type": "Organization", - "site_admin": false - }, - "private": false, - "html_url": "https://github.com/servo/servo", - "description": "The Servo Browser Engine", - "fork": false, - "url": "https://api.github.com/repos/servo/servo", - "forks_url": "https://api.github.com/repos/servo/servo/forks", - "keys_url": "https://api.github.com/repos/servo/servo/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/servo/servo/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/servo/servo/teams", - "hooks_url": "https://api.github.com/repos/servo/servo/hooks", - "issue_events_url": "https://api.github.com/repos/servo/servo/issues/events{/number}", - "events_url": "https://api.github.com/repos/servo/servo/events", - "assignees_url": "https://api.github.com/repos/servo/servo/assignees{/user}", - "branches_url": "https://api.github.com/repos/servo/servo/branches{/branch}", - "tags_url": "https://api.github.com/repos/servo/servo/tags", - "blobs_url": "https://api.github.com/repos/servo/servo/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/servo/servo/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/servo/servo/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/servo/servo/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/servo/servo/statuses/{sha}", - "languages_url": "https://api.github.com/repos/servo/servo/languages", - "stargazers_url": "https://api.github.com/repos/servo/servo/stargazers", - "contributors_url": "https://api.github.com/repos/servo/servo/contributors", - "subscribers_url": "https://api.github.com/repos/servo/servo/subscribers", - "subscription_url": "https://api.github.com/repos/servo/servo/subscription", - "commits_url": "https://api.github.com/repos/servo/servo/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/servo/servo/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/servo/servo/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/servo/servo/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/servo/servo/contents/{+path}", - "compare_url": "https://api.github.com/repos/servo/servo/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/servo/servo/merges", - "archive_url": "https://api.github.com/repos/servo/servo/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/servo/servo/downloads", - "issues_url": "https://api.github.com/repos/servo/servo/issues{/number}", - "pulls_url": "https://api.github.com/repos/servo/servo/pulls{/number}", - "milestones_url": "https://api.github.com/repos/servo/servo/milestones{/number}", - "notifications_url": "https://api.github.com/repos/servo/servo/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/servo/servo/labels{/name}", - "releases_url": "https://api.github.com/repos/servo/servo/releases{/id}", - "created_at": "2012-02-08T19:07:25Z", - "updated_at": "2015-08-07T09:37:49Z", - "pushed_at": "2015-08-07T14:10:08Z", - "git_url": "git://github.com/servo/servo.git", - "ssh_url": "git@github.com:servo/servo.git", - "clone_url": "https://github.com/servo/servo.git", - "svn_url": "https://github.com/servo/servo", - "homepage": "", - "size": 1904176, - "stargazers_count": 4571, - "watchers_count": 4571, - "language": "Rust", - "has_issues": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "forks_count": 717, - "mirror_url": null, - "open_issues_count": 1060, - "forks": 717, - "open_issues": 1060, - "watchers": 4571, - "default_branch": "master" - }, - "organization": { - "login": "servo", - "id": 2566135, - "url": "https://api.github.com/orgs/servo", - "repos_url": "https://api.github.com/orgs/servo/repos", - "events_url": "https://api.github.com/orgs/servo/events", - "members_url": "https://api.github.com/orgs/servo/members{/member}", - "public_members_url": "https://api.github.com/orgs/servo/public_members{/member}", - "avatar_url": "https://avatars.githubusercontent.com/u/2566135?v=3", - "description": null - }, - "sender": { - "login": "frewsxcv", - "id": 416575, - "avatar_url": "https://avatars.githubusercontent.com/u/416575?v=3", - "gravatar_id": "", - "url": "https://api.github.com/users/frewsxcv", - "html_url": "https://github.com/frewsxcv", - "followers_url": "https://api.github.com/users/frewsxcv/followers", - "following_url": "https://api.github.com/users/frewsxcv/following{/other_user}", - "gists_url": "https://api.github.com/users/frewsxcv/gists{/gist_id}", - "starred_url": "https://api.github.com/users/frewsxcv/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/frewsxcv/subscriptions", - "organizations_url": "https://api.github.com/users/frewsxcv/orgs", - "repos_url": "https://api.github.com/users/frewsxcv/repos", - "events_url": "https://api.github.com/users/frewsxcv/events{/privacy}", - "received_events_url": "https://api.github.com/users/frewsxcv/received_events", - "type": "User", - "site_admin": false - } -} From 3e85bcdbd39a682b3fea1bfb11a1fe224ba441a0 Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Thu, 26 Nov 2015 16:48:52 -0500 Subject: [PATCH 11/12] Remove further traces of old declarative test format. --- test.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/test.py b/test.py index 176739d..f050e5f 100644 --- a/test.py +++ b/test.py @@ -56,8 +56,7 @@ def run_tests(tests): eventhandler.reset_test_state() try: - test_contents = get_payload(test['filename']) - payload = test_contents['payload'] if 'payload' in test_contents else test_contents + payload = get_payload(test['filename'])['payload'] initial = test['initial'] api = TestAPIProvider(payload, 'highfive', initial['new_contributor'], initial['labels'], initial['assignee'], initial['diff']) @@ -77,11 +76,6 @@ def run_tests(tests): print('{}: An error occurred on line {} in statement {}'.format(test['filename'], line, text)) failed += 1 - possible_tests = [f for f in os.listdir('.') if f.endswith('.json')] - test_files = set([test['filename'] for test in tests]) - if len(possible_tests) > len(test_files): - print 'Found unused JSON test data: %s' % ', '.join(filter(lambda x: x not in test_files, possible_tests)) - sys.exit(1) print 'Ran %d tests, %d failed' % (len(tests), failed) if failed: From 8cb122ac5ae0599b8505bacdc7654998a8482b88 Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Thu, 26 Nov 2015 16:54:39 -0500 Subject: [PATCH 12/12] Clean up JSON. --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 07c8808..fcfe4d3 100644 --- a/README.md +++ b/README.md @@ -26,8 +26,8 @@ each handler, using the following format: // Defaults: "labels": [], "diff": "", - "new_contributor": False, - "assignee": None, + "new_contributor": false, + "assignee": null, }, "expected": { // Expected state of the PR after all the handlers process @@ -42,3 +42,5 @@ each handler, using the following format: } } ``` +Each test runs with a mock Github API provider, so no account information +or network connection is required to run the test suite.