From ca941ff4321d5b9b356bff14942bbd004bf846f2 Mon Sep 17 00:00:00 2001 From: Mike Pennisi Date: Fri, 5 Jul 2019 13:50:58 -0400 Subject: [PATCH 01/23] Begin --- .github/main.workflow | 44 +++++++++++++++++++++-------------- .taskcluster.yml | 4 ++-- tools/ci/update_pr_preview.py | 40 +++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 19 deletions(-) create mode 100644 tools/ci/update_pr_preview.py diff --git a/.github/main.workflow b/.github/main.workflow index 4f4447fdf0..dd6773f508 100644 --- a/.github/main.workflow +++ b/.github/main.workflow @@ -1,21 +1,31 @@ -workflow "Build & Release Manifest" { - on = "push" - resolves = ["manifest-build-and-tag"] -} +#workflow "Build & Release Manifest" { +# on = "push" +# resolves = ["manifest-build-and-tag"] +#} +# +#action "manifest-build-and-tag" { +# uses = "./tools/docker/github" +# runs = ["python", "tools/ci/manifest_build.py"] +# secrets = ["GITHUB_TOKEN"] +#} +# +#workflow "Build & Publish Documentation Website" { +# on = "push" +# resolves = ["website-build-and-publish"] +#} +# +#action "website-build-and-publish" { +# uses = "./tools/docker/documentation" +# runs = ["/bin/bash", "tools/ci/website_build.sh"] +# secrets = ["DEPLOY_TOKEN"] +#} -action "manifest-build-and-tag" { - uses = "./tools/docker/github" - runs = ["python", "tools/ci/manifest_build.py"] - secrets = ["GITHUB_TOKEN"] +workflow "Synchronize the Pull Request Preview" { + on = "pull_request" + resolves = "update-pr-preview" } -workflow "Build & Publish Documentation Website" { - on = "push" - resolves = ["website-build-and-publish"] -} - -action "website-build-and-publish" { - uses = "./tools/docker/documentation" - runs = ["/bin/bash", "tools/ci/website_build.sh"] - secrets = ["DEPLOY_TOKEN"] +action "update-pr-preview" { + uses = "./tools/docker/github" + runs = ["python", "tools/ci/update_pr_preview.py"] } diff --git a/.taskcluster.yml b/.taskcluster.yml index a8e297242f..e069c1702b 100644 --- a/.taskcluster.yml +++ b/.taskcluster.yml @@ -6,7 +6,7 @@ tasks: event_str: {$json: {$eval: event}} in: $flattenDeep: - - $if: tasks_for == "github-push" + - $if: false then: $map: $flatten: @@ -100,7 +100,7 @@ tasks: --test-type=${chunk[0]} --this-chunk=${chunk[1]} --total-chunks=${chunk[2]}; - - $if: tasks_for == "github-pull-request" + - $if: false # PR tasks that run the tests in various configurations then: # Taskcluster responds to a number of events issued by the GitHub API diff --git a/tools/ci/update_pr_preview.py b/tools/ci/update_pr_preview.py new file mode 100644 index 0000000000..9978be3d2f --- /dev/null +++ b/tools/ci/update_pr_preview.py @@ -0,0 +1,40 @@ +import json +import logging +import os +import subprocess +import sys + +import requests + +here = os.path.abspath(os.path.dirname(__file__)) +wpt_root = os.path.abspath(os.path.join(here, os.pardir, os.pardir)) + +if not(wpt_root in sys.path): + sys.path.append(wpt_root) + +from tools.wpt.testfiles import get_git_cmd + +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) + + +class Status(object): + SUCCESS = 0 + FAIL = 1 + NEUTRAL = 78 + + +def main(): + owner, repo = os.environ['GITHUB_REPOSITORY'].split('/', 1) + + with open(os.environ['GITHUB_EVENT_PATH']) as f: + event = json.load(f) + logger.info(json.dumps(event, indent=2)) + + return Status.SUCCESS + + +if __name__ == '__main__': + code = main() + assert isinstance(code, int) + sys.exit(code) From 7ac7bcc4e3a531da749a0449aaf8b113ddc41662 Mon Sep 17 00:00:00 2001 From: Mike Pennisi Date: Fri, 5 Jul 2019 20:44:01 -0400 Subject: [PATCH 02/23] Complete initial implementation --- .github/main.workflow | 2 +- tools/ci/tests/test_update_pr_preview.py | 277 +++++++++++++++++++++++ tools/ci/update_pr_preview.py | 183 ++++++++++++++- tools/tox.ini | 2 + 4 files changed, 458 insertions(+), 6 deletions(-) create mode 100644 tools/ci/tests/test_update_pr_preview.py diff --git a/.github/main.workflow b/.github/main.workflow index dd6773f508..02949638f7 100644 --- a/.github/main.workflow +++ b/.github/main.workflow @@ -27,5 +27,5 @@ workflow "Synchronize the Pull Request Preview" { action "update-pr-preview" { uses = "./tools/docker/github" - runs = ["python", "tools/ci/update_pr_preview.py"] + runs = ["python", "tools/ci/update_pr_preview.py", "https://api.github.com"] } diff --git a/tools/ci/tests/test_update_pr_preview.py b/tools/ci/tests/test_update_pr_preview.py new file mode 100644 index 0000000000..7c766ed6df --- /dev/null +++ b/tools/ci/tests/test_update_pr_preview.py @@ -0,0 +1,277 @@ +import BaseHTTPServer +import json +import os +import pytest +import subprocess +import tempfile +import threading + +subject = os.path.join( + os.path.dirname(os.path.abspath(__file__)), '..', 'update_pr_preview.py' +) +test_host = 'localhost' + + +class TestHandler(BaseHTTPServer.BaseHTTPRequestHandler, object): + def do_all(self): + request = (self.command, self.path) + self.server.requests.append(request) + self.send_response(self.server.responses.get(request, 200)) + self.end_headers() + self.wfile.write('{}') + def do_DELETE(self): + return self.do_all() + def do_GET(self): + return self.do_all() + def do_PATCH(self): + return self.do_all() + def do_POST(self): + return self.do_all() + + +class TestServer(BaseHTTPServer.HTTPServer, object): + '''This server responds to all HTTP requests with status code 200 unless an + alternative status code is specified for the given method and path in the + `responses` parameter.''' + def __init__(self, address, responses=None): + super(TestServer, self).__init__(address, TestHandler) + self.responses = responses or {} + self.requests = [] + + +def assert_success(returncode): + assert returncode == 0 + + +def assert_neutral(returncode): + assert returncode == 78 + + +def assert_fail(returncode): + assert returncode not in (0, 78) + + +def run(event_data, responses=None): + event_data_file = tempfile.mkstemp()[1] + env = { + 'GITHUB_EVENT_PATH': event_data_file, + 'GITHUB_REPOSITORY': 'test-org/test-repo' + } + env.update(os.environ) + server = TestServer((test_host, 0), responses) + test_port = server.server_address[1] + threading.Thread(target=lambda: server.serve_forever()).start() + + try: + with open(event_data_file, 'w') as handle: + json.dump(event_data, handle) + + child = subprocess.Popen( + ['python', subject, 'http://{}:{}'.format(test_host, test_port)], + env=env + ) + + child.communicate() + finally: + server.shutdown() + os.remove(event_data_file) + + return child.returncode, server.requests + + +def default_data(action): + return { + 'pull_request': { + 'number': 543, + 'closed_at': None, + 'head': { + 'sha': 'deadbeef' + }, + 'user': { + 'login': 'rms' + }, + 'labels': [ + { 'name': 'foo' }, + { 'name': 'bar' } + ] + }, + 'action': action + } + + + +def test_close_active_with_label(): + event_data = default_data('close') + event_data['pull_request']['closed_at'] = '2019-07-05' + event_data['pull_request']['labels'].append( + {'name': 'pull-request-has-preview'} + ) + expected = ( + 'DELETE', + '/repos/test-org/test-repo/issues/543/labels/pull-request-has-preview' + ) + + returncode, requests = run(event_data) + + assert_success(returncode) + assert expected in requests + + +def test_close_active_with_label_error(): + event_data = default_data('close') + event_data['pull_request']['closed_at'] = '2019-07-05' + event_data['pull_request']['labels'].append( + {'name': 'pull-request-has-preview'} + ) + responses = {( + 'DELETE', + '/repos/test-org/test-repo/issues/543/labels/pull-request-has-preview' + ): 500} + + returncode, requests = run(event_data, responses) + + assert_fail(returncode) + + +def test_close_active_without_label(): + event_data = default_data('close') + event_data['pull_request']['closed_at'] = '2019-07-05' + + returncode, requests = run(event_data) + + assert_neutral(returncode) + assert len(requests) == 0 + + +def test_open_with_label(): + event_data = default_data('open') + event_data['pull_request']['labels'].append( + {'name': 'pull-request-has-preview'} + ) + + returncode, requests = run(event_data) + + assert_success(returncode) + expected = ( + 'PATCH', + '/repos/test-org/test-repo/git/refs/pr_preview_543' + ) + assert expected in requests + + +def test_open_without_label_for_collaborator(): + event_data = default_data('open') + + returncode, requests = run(event_data) + + assert_success(returncode) + check_collaborator = ( + 'GET', '/repos/test-org/test-repo/collaborators/rms' + ) + create_label = ( + 'POST', + '/repos/test-org/test-repo/issues/543/labels' + ) + assert len(requests) == 2 + assert check_collaborator in requests + assert create_label in requests + + +def test_open_without_label_for_non_collaborator(): + event_data = default_data('open') + responses = { + ('GET', '/repos/test-org/test-repo/collaborators/rms'): 404 + } + + returncode, requests = run(event_data, responses) + + assert_neutral(returncode) + expected = [( + 'GET', '/repos/test-org/test-repo/collaborators/rms' + )] + assert expected == requests + + +def test_add_unrelated_label(): + event_data = default_data('label') + event_data['label'] = {'name': 'foobar'} + event_data['pull_request']['labels'].append({'name': 'foobar'}) + + returncode, requests = run(event_data) + + assert_neutral(returncode) + assert len(requests) == 0 + + +def test_add_active_label(): + event_data = default_data('label') + event_data['label'] = {'name': 'pull-request-has-preview'} + event_data['pull_request']['labels'].append( + {'name': 'pull-request-has-preview'} + ) + + returncode, requests = run(event_data) + + assert_success(returncode) + expected = ( + 'PATCH', + '/repos/test-org/test-repo/git/refs/pr_preview_543' + ) + assert expected in requests + + +def test_remove_unrelated_label(): + event_data = default_data('unlabel') + event_data['label'] = {'name': 'foobar'} + + returncode, requests = run(event_data) + + assert_neutral(returncode) + assert len(requests) == 0 + + +def test_remove_active_label(): + event_data = default_data('unlabel') + event_data['label'] = {'name': 'pull-request-has-preview'} + expected = ('DELETE', '/repos/test-org/test-repo/git/refs/pr_preview_543') + + returncode, requests = run(event_data) + + assert_success(returncode) + assert expected in requests + + +def test_synchronize_without_label(): + event_data = default_data('synchronize') + + returncode, requests = run(event_data) + + assert_neutral(returncode) + assert len(requests) == 0 + + +def test_synchronize_with_label(): + event_data = default_data('synchronize') + event_data['pull_request']['labels'].append( + {'name': 'pull-request-has-preview'} + ) + + returncode, requests = run(event_data) + + assert_success(returncode) + expected = ( + 'PATCH', + '/repos/test-org/test-repo/git/refs/pr_preview_543' + ) + assert expected in requests + + +def test_unrecognized_action(): + event_data = default_data('assigned') + + returncode, requests = run(event_data) + + assert_neutral(returncode) + assert len(requests) == 0 + + diff --git a/tools/ci/update_pr_preview.py b/tools/ci/update_pr_preview.py index 9978be3d2f..3a7d5a70d4 100644 --- a/tools/ci/update_pr_preview.py +++ b/tools/ci/update_pr_preview.py @@ -8,6 +8,7 @@ here = os.path.abspath(os.path.dirname(__file__)) wpt_root = os.path.abspath(os.path.join(here, os.pardir, os.pardir)) +active_label = 'pull-request-has-preview' if not(wpt_root in sys.path): sys.path.append(wpt_root) @@ -24,17 +25,189 @@ class Status(object): NEUTRAL = 78 -def main(): - owner, repo = os.environ['GITHUB_REPOSITORY'].split('/', 1) +def request(url, method_name, data=None, json_data=None, params=None, + extra_headers=None): + github_token = os.environ.get('GITHUB_TOKEN') + headers = { + 'Authorization': 'token {}'.format(github_token), + 'Accept': 'application/vnd.github.machine-man-preview+json' + } + + if extra_headers is not None: + headers.update(extra_headers) + + kwargs = { + 'params': params, + 'headers': headers + } + method = getattr(requests, method_name) + + logger.info('Loading URL %s' % url) + if json_data is not None or data is not None: + kwargs['json'] = json_data + kwargs['data'] = data + + resp = method(url, **kwargs) + + resp.raise_for_status() + + return resp.json() + + +def resource_exists(url): + try: + request(url, 'get') + except requests.HTTPError as exception: + if exception.response.status_code == 404: + return False + raise + + return True + + +class GitHub(object): + def __init__(self, api_root, owner, repo): + self.api_root = api_root + self.owner = owner + self.repo = repo + + def is_collaborator(self, login): + return resource_exists( + '{}/repos/{}/{}/collaborators/{}'.format( + self.api_root, self.owner, self.repo, login + ) + ) + + def tag_exists(self, tag): + return resource_exists( + '{}/repos/{}/{}/git/refs/{}'.format( + self.api_root, self.owner, self.repo, tag + ) + ) + + def create_tag(self, tag, sha): + data = { + 'ref': 'refs/tags/{}'.format(tag), + 'sha': sha + } + url = '{}/repos/{}/{}/git/refs'.format( + self.api_root, self.owner, self.repo + ) + + request(url, 'post', json_data=data) + + def update_tag(self, tag, sha): + data = { + 'force': True, + 'sha': sha + } + url = '{}/repos/{}/{}/git/refs/{}'.format( + self.api_root, self.owner, self.repo, tag + ) + + request(url, 'patch', json_data=data) - with open(os.environ['GITHUB_EVENT_PATH']) as f: - event = json.load(f) + def delete_tag(self, tag): + url = '{}/repos/{}/{}/git/refs/{}'.format( + self.api_root, self.owner, self.repo, tag + ) + + try: + request(url, 'delete') + except requests.HTTPError as exception: + if exception.response.status_code != 404: + raise + + logger.info( + 'Attempted to delete non-existent tag: {}'.format(tag_name) + ) + + def tag(self, tag, sha): + if self.tag_exists(tag): + self.update_tag(tag, sha) + else: + self.create_tag(tag, sha) + + logger.info('Tagged {} as {}'.format(sha, tag)) + + def add_label(self, pr_number, label_name): + data = { + 'labels': [label_name] + } + url = '{}/repos/{}/{}/issues/{}/labels'.format( + self.api_root, self.owner, self.repo, pr_number + ) + + request(url, 'post', json_data=data) + + def remove_label(self, pr_number, label_name): + url = '{}/repos/{}/{}/issues/{}/labels/{}'.format( + self.api_root, self.owner, self.repo, pr_number, label_name + ) + + try: + request(url, 'delete') + except requests.HTTPError as exception: + if exception.response.status_code != 404: + raise + + logger.info( + 'Attempted to delete non-existent tag: {}'.format(tag_name) + ) + + +def main(api_root): + with open(os.environ['GITHUB_EVENT_PATH']) as handle: + event = json.load(handle) logger.info(json.dumps(event, indent=2)) + if 'pull_request' not in event: + logger.info('Unexpected event data') + return Status.FAIL + + owner, repo = os.environ['GITHUB_REPOSITORY'].split('/', 1) + github = GitHub(api_root, owner, repo) + action = event['action'] + pr_number = event['pull_request']['number'] + tag_name = 'pr_preview_{}'.format(pr_number) + sha = event['pull_request']['head']['sha'] + is_open = event['pull_request']['closed_at'] is None + login = event['pull_request']['user']['login'] + has_label = any( + [label['name'] == active_label + for label in event['pull_request']['labels']] + ) + target_label = event.get('label', {}).get('name') + + + if not is_open: + if action == 'close' and has_label: + # This operation will trigger another GitHub Action which will + # subsequently delete the tag. + github.remove_label(pr_number, active_label) + return Status.SUCCESS + + return Status.NEUTRAL + + if action in ('open', 'reopen') and has_label: + github.tag(tag_name, sha) + elif action in ('open', 'reopen') and github.is_collaborator(login): + # This operation will trigger another GitHub Action which will + # subsequently create the tag. + github.add_label(pr_number, active_label) + elif action == 'label' and target_label == active_label: + github.tag(tag_name, sha) + elif action == 'unlabel' and target_label == active_label: + github.delete_tag(tag_name) + elif action == 'synchronize' and has_label: + github.tag(tag_name, sha) + else: + return Status.NEUTRAL + return Status.SUCCESS if __name__ == '__main__': - code = main() + code = main(sys.argv[1]) assert isinstance(code, int) sys.exit(code) diff --git a/tools/tox.ini b/tools/tox.ini index ba6dc038a1..aba4f3faaa 100644 --- a/tools/tox.ini +++ b/tools/tox.ini @@ -8,6 +8,8 @@ deps = pytest-cov mock hypothesis + # `requests` is required by `update_pr_preview.py` + requests commands = pytest {posargs} From cdbf8338ce50904ea796ea748ed00f7437eed877 Mon Sep 17 00:00:00 2001 From: Mike Pennisi Date: Mon, 8 Jul 2019 10:50:41 -0400 Subject: [PATCH 03/23] Correct linting infractions --- tools/ci/tests/test_update_pr_preview.py | 13 +++++++------ tools/ci/update_pr_preview.py | 12 ++---------- 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/tools/ci/tests/test_update_pr_preview.py b/tools/ci/tests/test_update_pr_preview.py index 7c766ed6df..6a8d59cedc 100644 --- a/tools/ci/tests/test_update_pr_preview.py +++ b/tools/ci/tests/test_update_pr_preview.py @@ -1,7 +1,6 @@ import BaseHTTPServer import json import os -import pytest import subprocess import tempfile import threading @@ -19,18 +18,22 @@ def do_all(self): self.send_response(self.server.responses.get(request, 200)) self.end_headers() self.wfile.write('{}') + def do_DELETE(self): return self.do_all() + def do_GET(self): return self.do_all() + def do_PATCH(self): return self.do_all() + def do_POST(self): return self.do_all() class TestServer(BaseHTTPServer.HTTPServer, object): - '''This server responds to all HTTP requests with status code 200 unless an + '''HTTP server that responds to all requests with status code 200 unless an alternative status code is specified for the given method and path in the `responses` parameter.''' def __init__(self, address, responses=None): @@ -91,8 +94,8 @@ def default_data(action): 'login': 'rms' }, 'labels': [ - { 'name': 'foo' }, - { 'name': 'bar' } + {'name': 'foo'}, + {'name': 'bar'} ] }, 'action': action @@ -273,5 +276,3 @@ def test_unrecognized_action(): assert_neutral(returncode) assert len(requests) == 0 - - diff --git a/tools/ci/update_pr_preview.py b/tools/ci/update_pr_preview.py index 3a7d5a70d4..deac6cd575 100644 --- a/tools/ci/update_pr_preview.py +++ b/tools/ci/update_pr_preview.py @@ -1,20 +1,12 @@ import json import logging import os -import subprocess import sys import requests -here = os.path.abspath(os.path.dirname(__file__)) -wpt_root = os.path.abspath(os.path.join(here, os.pardir, os.pardir)) active_label = 'pull-request-has-preview' -if not(wpt_root in sys.path): - sys.path.append(wpt_root) - -from tools.wpt.testfiles import get_git_cmd - logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) @@ -119,7 +111,7 @@ def delete_tag(self, tag): raise logger.info( - 'Attempted to delete non-existent tag: {}'.format(tag_name) + 'Attempted to delete non-existent tag: {}'.format(tag) ) def tag(self, tag, sha): @@ -152,7 +144,7 @@ def remove_label(self, pr_number, label_name): raise logger.info( - 'Attempted to delete non-existent tag: {}'.format(tag_name) + 'Attempted to remove non-existent label: {}'.format(label_name) ) From 37b2c112f63df447353860efcd7431f693043140 Mon Sep 17 00:00:00 2001 From: Mike Pennisi Date: Mon, 8 Jul 2019 13:44:23 -0400 Subject: [PATCH 04/23] Add some documentation --- docs/writing-tests/submission-process.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/docs/writing-tests/submission-process.md b/docs/writing-tests/submission-process.md index d6ddce5a76..2a0aa0c47b 100644 --- a/docs/writing-tests/submission-process.md +++ b/docs/writing-tests/submission-process.md @@ -38,6 +38,23 @@ Hop on to the [mailing list][public-test-infra] or [IRC][] no need to announce your review request, as soon as you make a Pull Request GitHub will inform interested parties. +## Previews + +The website [wpt-submissions.live](http://wpt-submissions.live) exists to help +contributors demonstrate their proposed changes to others. If your pull request +is open and has the GitHub label `pull-request-has-preview`, then it will be +available at `http://wpt-submissions.live/{{pull request ID}}`, where "pull +request ID" is the numeric identifier for the pull request. + +For example, a pull request at https://github.com/web-platform-tests/wpt/pull/3 +has a pull request ID `3`. Once that has been assigned the +`pull-request-has-preview` label, then its contents can be viewed at +http://wpt-submissions.live/3. + +If you are [a GitHub +collaborator](https://help.github.com/en/articles/permission-levels-for-a-user-account-repository) +on WPT, the label and the preview will be created automatically. + [repo]: https://github.com/web-platform-tests/wpt/ [github flow]: https://guides.github.com/introduction/flow/ [public-test-infra]: https://lists.w3.org/Archives/Public/public-test-infra/ From ee2d3f9fe0966df6910383fb9e827b0ae385bb8b Mon Sep 17 00:00:00 2001 From: Mike Pennisi Date: Mon, 8 Jul 2019 13:51:02 -0400 Subject: [PATCH 05/23] Add logging --- tools/ci/update_pr_preview.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tools/ci/update_pr_preview.py b/tools/ci/update_pr_preview.py index deac6cd575..b9548b8b23 100644 --- a/tools/ci/update_pr_preview.py +++ b/tools/ci/update_pr_preview.py @@ -86,6 +86,8 @@ def create_tag(self, tag, sha): self.api_root, self.owner, self.repo ) + logger.info('Creating tag "{}" as {}'.format(tag, sha)) + request(url, 'post', json_data=data) def update_tag(self, tag, sha): @@ -97,6 +99,8 @@ def update_tag(self, tag, sha): self.api_root, self.owner, self.repo, tag ) + logger.info('Updating tag "{}" as {}'.format(tag, sha)) + request(url, 'patch', json_data=data) def delete_tag(self, tag): @@ -104,6 +108,8 @@ def delete_tag(self, tag): self.api_root, self.owner, self.repo, tag ) + logger.info('Deleting tag "{}" as {}'.format(tag, sha)) + try: request(url, 'delete') except requests.HTTPError as exception: @@ -120,8 +126,6 @@ def tag(self, tag, sha): else: self.create_tag(tag, sha) - logger.info('Tagged {} as {}'.format(sha, tag)) - def add_label(self, pr_number, label_name): data = { 'labels': [label_name] @@ -130,6 +134,8 @@ def add_label(self, pr_number, label_name): self.api_root, self.owner, self.repo, pr_number ) + logger.info('Adding label') + request(url, 'post', json_data=data) def remove_label(self, pr_number, label_name): @@ -137,6 +143,8 @@ def remove_label(self, pr_number, label_name): self.api_root, self.owner, self.repo, pr_number, label_name ) + logger.info('Removing label') + try: request(url, 'delete') except requests.HTTPError as exception: From 314208ec8eb9e2831b8b34daac828e66a88360f8 Mon Sep 17 00:00:00 2001 From: Mike Pennisi Date: Mon, 8 Jul 2019 13:56:38 -0400 Subject: [PATCH 06/23] Authorize action --- .github/main.workflow | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/main.workflow b/.github/main.workflow index 02949638f7..4b076bb4c6 100644 --- a/.github/main.workflow +++ b/.github/main.workflow @@ -28,4 +28,5 @@ workflow "Synchronize the Pull Request Preview" { action "update-pr-preview" { uses = "./tools/docker/github" runs = ["python", "tools/ci/update_pr_preview.py", "https://api.github.com"] + secrets = ["GITHUB_TOKEN"] } From c8fa1c1f35dce91f21b46cab49c290665bdae5ed Mon Sep 17 00:00:00 2001 From: Mike Pennisi Date: Mon, 8 Jul 2019 14:09:11 -0400 Subject: [PATCH 07/23] Removed referenced to undefined variable --- tools/ci/update_pr_preview.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/ci/update_pr_preview.py b/tools/ci/update_pr_preview.py index b9548b8b23..3e97ca4d87 100644 --- a/tools/ci/update_pr_preview.py +++ b/tools/ci/update_pr_preview.py @@ -108,7 +108,7 @@ def delete_tag(self, tag): self.api_root, self.owner, self.repo, tag ) - logger.info('Deleting tag "{}" as {}'.format(tag, sha)) + logger.info('Deleting tag "{}"'.format(tag)) try: request(url, 'delete') From ca74abc4b43b2ae00d7cc5da95c222fcbd9465e2 Mon Sep 17 00:00:00 2001 From: Mike Pennisi Date: Mon, 8 Jul 2019 14:09:28 -0400 Subject: [PATCH 08/23] Correct API references --- tools/ci/tests/test_update_pr_preview.py | 10 ++++++---- tools/ci/update_pr_preview.py | 6 +++--- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/tools/ci/tests/test_update_pr_preview.py b/tools/ci/tests/test_update_pr_preview.py index 6a8d59cedc..e1f1eaa6fb 100644 --- a/tools/ci/tests/test_update_pr_preview.py +++ b/tools/ci/tests/test_update_pr_preview.py @@ -157,7 +157,7 @@ def test_open_with_label(): assert_success(returncode) expected = ( 'PATCH', - '/repos/test-org/test-repo/git/refs/pr_preview_543' + '/repos/test-org/test-repo/git/refs/tags/pr_preview_543' ) assert expected in requests @@ -218,7 +218,7 @@ def test_add_active_label(): assert_success(returncode) expected = ( 'PATCH', - '/repos/test-org/test-repo/git/refs/pr_preview_543' + '/repos/test-org/test-repo/git/refs/tags/pr_preview_543' ) assert expected in requests @@ -236,7 +236,9 @@ def test_remove_unrelated_label(): def test_remove_active_label(): event_data = default_data('unlabel') event_data['label'] = {'name': 'pull-request-has-preview'} - expected = ('DELETE', '/repos/test-org/test-repo/git/refs/pr_preview_543') + expected = ( + 'DELETE', '/repos/test-org/test-repo/git/refs/tags/pr_preview_543' + ) returncode, requests = run(event_data) @@ -264,7 +266,7 @@ def test_synchronize_with_label(): assert_success(returncode) expected = ( 'PATCH', - '/repos/test-org/test-repo/git/refs/pr_preview_543' + '/repos/test-org/test-repo/git/refs/tags/pr_preview_543' ) assert expected in requests diff --git a/tools/ci/update_pr_preview.py b/tools/ci/update_pr_preview.py index 3e97ca4d87..48b429000c 100644 --- a/tools/ci/update_pr_preview.py +++ b/tools/ci/update_pr_preview.py @@ -72,7 +72,7 @@ def is_collaborator(self, login): def tag_exists(self, tag): return resource_exists( - '{}/repos/{}/{}/git/refs/{}'.format( + '{}/repos/{}/{}/git/refs/tags/{}'.format( self.api_root, self.owner, self.repo, tag ) ) @@ -95,7 +95,7 @@ def update_tag(self, tag, sha): 'force': True, 'sha': sha } - url = '{}/repos/{}/{}/git/refs/{}'.format( + url = '{}/repos/{}/{}/git/refs/tags/{}'.format( self.api_root, self.owner, self.repo, tag ) @@ -104,7 +104,7 @@ def update_tag(self, tag, sha): request(url, 'patch', json_data=data) def delete_tag(self, tag): - url = '{}/repos/{}/{}/git/refs/{}'.format( + url = '{}/repos/{}/{}/git/refs/tags/{}'.format( self.api_root, self.owner, self.repo, tag ) From 8bb8bd40d0e475479b7947b90854db53bb9adc1c Mon Sep 17 00:00:00 2001 From: Mike Pennisi Date: Mon, 8 Jul 2019 14:20:21 -0400 Subject: [PATCH 09/23] Correct action names --- tools/ci/tests/test_update_pr_preview.py | 20 ++++++++++---------- tools/ci/update_pr_preview.py | 10 +++++----- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/tools/ci/tests/test_update_pr_preview.py b/tools/ci/tests/test_update_pr_preview.py index e1f1eaa6fb..57813197fa 100644 --- a/tools/ci/tests/test_update_pr_preview.py +++ b/tools/ci/tests/test_update_pr_preview.py @@ -104,7 +104,7 @@ def default_data(action): def test_close_active_with_label(): - event_data = default_data('close') + event_data = default_data('closed') event_data['pull_request']['closed_at'] = '2019-07-05' event_data['pull_request']['labels'].append( {'name': 'pull-request-has-preview'} @@ -121,7 +121,7 @@ def test_close_active_with_label(): def test_close_active_with_label_error(): - event_data = default_data('close') + event_data = default_data('closed') event_data['pull_request']['closed_at'] = '2019-07-05' event_data['pull_request']['labels'].append( {'name': 'pull-request-has-preview'} @@ -137,7 +137,7 @@ def test_close_active_with_label_error(): def test_close_active_without_label(): - event_data = default_data('close') + event_data = default_data('closed') event_data['pull_request']['closed_at'] = '2019-07-05' returncode, requests = run(event_data) @@ -147,7 +147,7 @@ def test_close_active_without_label(): def test_open_with_label(): - event_data = default_data('open') + event_data = default_data('opened') event_data['pull_request']['labels'].append( {'name': 'pull-request-has-preview'} ) @@ -163,7 +163,7 @@ def test_open_with_label(): def test_open_without_label_for_collaborator(): - event_data = default_data('open') + event_data = default_data('opened') returncode, requests = run(event_data) @@ -181,7 +181,7 @@ def test_open_without_label_for_collaborator(): def test_open_without_label_for_non_collaborator(): - event_data = default_data('open') + event_data = default_data('opened') responses = { ('GET', '/repos/test-org/test-repo/collaborators/rms'): 404 } @@ -196,7 +196,7 @@ def test_open_without_label_for_non_collaborator(): def test_add_unrelated_label(): - event_data = default_data('label') + event_data = default_data('labeled') event_data['label'] = {'name': 'foobar'} event_data['pull_request']['labels'].append({'name': 'foobar'}) @@ -207,7 +207,7 @@ def test_add_unrelated_label(): def test_add_active_label(): - event_data = default_data('label') + event_data = default_data('labeled') event_data['label'] = {'name': 'pull-request-has-preview'} event_data['pull_request']['labels'].append( {'name': 'pull-request-has-preview'} @@ -224,7 +224,7 @@ def test_add_active_label(): def test_remove_unrelated_label(): - event_data = default_data('unlabel') + event_data = default_data('unlabeled') event_data['label'] = {'name': 'foobar'} returncode, requests = run(event_data) @@ -234,7 +234,7 @@ def test_remove_unrelated_label(): def test_remove_active_label(): - event_data = default_data('unlabel') + event_data = default_data('unlabeled') event_data['label'] = {'name': 'pull-request-has-preview'} expected = ( 'DELETE', '/repos/test-org/test-repo/git/refs/tags/pr_preview_543' diff --git a/tools/ci/update_pr_preview.py b/tools/ci/update_pr_preview.py index 48b429000c..3548a9eff9 100644 --- a/tools/ci/update_pr_preview.py +++ b/tools/ci/update_pr_preview.py @@ -181,7 +181,7 @@ def main(api_root): if not is_open: - if action == 'close' and has_label: + if action == 'closed' and has_label: # This operation will trigger another GitHub Action which will # subsequently delete the tag. github.remove_label(pr_number, active_label) @@ -189,15 +189,15 @@ def main(api_root): return Status.NEUTRAL - if action in ('open', 'reopen') and has_label: + if action in ('opened', 'reopened') and has_label: github.tag(tag_name, sha) - elif action in ('open', 'reopen') and github.is_collaborator(login): + elif action in ('opened', 'reopened') and github.is_collaborator(login): # This operation will trigger another GitHub Action which will # subsequently create the tag. github.add_label(pr_number, active_label) - elif action == 'label' and target_label == active_label: + elif action == 'labeled' and target_label == active_label: github.tag(tag_name, sha) - elif action == 'unlabel' and target_label == active_label: + elif action == 'unlabeled' and target_label == active_label: github.delete_tag(tag_name) elif action == 'synchronize' and has_label: github.tag(tag_name, sha) From c36351523e1fed6118cbd259bfd22a57ec4621d5 Mon Sep 17 00:00:00 2001 From: Mike Pennisi Date: Mon, 8 Jul 2019 14:41:16 -0400 Subject: [PATCH 10/23] Ignore response body for existence checks --- tools/ci/tests/test_update_pr_preview.py | 20 ++++++++++++-------- tools/ci/update_pr_preview.py | 7 ++++--- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/tools/ci/tests/test_update_pr_preview.py b/tools/ci/tests/test_update_pr_preview.py index 57813197fa..8529e8fdde 100644 --- a/tools/ci/tests/test_update_pr_preview.py +++ b/tools/ci/tests/test_update_pr_preview.py @@ -15,9 +15,10 @@ class TestHandler(BaseHTTPServer.BaseHTTPRequestHandler, object): def do_all(self): request = (self.command, self.path) self.server.requests.append(request) - self.send_response(self.server.responses.get(request, 200)) + status_code, body = self.server.responses.get(request, (200, '{}')) + self.send_response(status_code) self.end_headers() - self.wfile.write('{}') + self.wfile.write(body) def do_DELETE(self): return self.do_all() @@ -33,9 +34,9 @@ def do_POST(self): class TestServer(BaseHTTPServer.HTTPServer, object): - '''HTTP server that responds to all requests with status code 200 unless an - alternative status code is specified for the given method and path in the - `responses` parameter.''' + '''HTTP server that responds to all requests with status code 200 and body + '{}' unless an alternative status code and body are specified for the given + method and path in the `responses` parameter.''' def __init__(self, address, responses=None): super(TestServer, self).__init__(address, TestHandler) self.responses = responses or {} @@ -129,7 +130,7 @@ def test_close_active_with_label_error(): responses = {( 'DELETE', '/repos/test-org/test-repo/issues/543/labels/pull-request-has-preview' - ): 500} + ): (500, '{}')} returncode, requests = run(event_data, responses) @@ -164,8 +165,11 @@ def test_open_with_label(): def test_open_without_label_for_collaborator(): event_data = default_data('opened') + responses = { + ('GET', '/repos/test-org/test-repo/collaborators/rms'): (204, '') + } - returncode, requests = run(event_data) + returncode, requests = run(event_data, responses) assert_success(returncode) check_collaborator = ( @@ -183,7 +187,7 @@ def test_open_without_label_for_collaborator(): def test_open_without_label_for_non_collaborator(): event_data = default_data('opened') responses = { - ('GET', '/repos/test-org/test-repo/collaborators/rms'): 404 + ('GET', '/repos/test-org/test-repo/collaborators/rms'): (404, '{}') } returncode, requests = run(event_data, responses) diff --git a/tools/ci/update_pr_preview.py b/tools/ci/update_pr_preview.py index 3548a9eff9..a97ed7745d 100644 --- a/tools/ci/update_pr_preview.py +++ b/tools/ci/update_pr_preview.py @@ -18,7 +18,7 @@ class Status(object): def request(url, method_name, data=None, json_data=None, params=None, - extra_headers=None): + extra_headers=None, ignore_body=False): github_token = os.environ.get('GITHUB_TOKEN') headers = { 'Authorization': 'token {}'.format(github_token), @@ -43,12 +43,13 @@ def request(url, method_name, data=None, json_data=None, params=None, resp.raise_for_status() - return resp.json() + if not ignore_body: + return resp.json() def resource_exists(url): try: - request(url, 'get') + request(url, 'get', ignore_body=True) except requests.HTTPError as exception: if exception.response.status_code == 404: return False From 20d35430c86063d2f94d57a0b51a9b93ac7464c5 Mon Sep 17 00:00:00 2001 From: Mike Pennisi Date: Mon, 8 Jul 2019 15:39:16 -0400 Subject: [PATCH 11/23] Improve class names --- tools/ci/tests/test_update_pr_preview.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/ci/tests/test_update_pr_preview.py b/tools/ci/tests/test_update_pr_preview.py index 8529e8fdde..e699f029d8 100644 --- a/tools/ci/tests/test_update_pr_preview.py +++ b/tools/ci/tests/test_update_pr_preview.py @@ -11,7 +11,7 @@ test_host = 'localhost' -class TestHandler(BaseHTTPServer.BaseHTTPRequestHandler, object): +class MockHandler(BaseHTTPServer.BaseHTTPRequestHandler, object): def do_all(self): request = (self.command, self.path) self.server.requests.append(request) @@ -33,12 +33,12 @@ def do_POST(self): return self.do_all() -class TestServer(BaseHTTPServer.HTTPServer, object): +class MockServer(BaseHTTPServer.HTTPServer, object): '''HTTP server that responds to all requests with status code 200 and body '{}' unless an alternative status code and body are specified for the given method and path in the `responses` parameter.''' def __init__(self, address, responses=None): - super(TestServer, self).__init__(address, TestHandler) + super(MockServer, self).__init__(address, MockHandler) self.responses = responses or {} self.requests = [] @@ -62,7 +62,7 @@ def run(event_data, responses=None): 'GITHUB_REPOSITORY': 'test-org/test-repo' } env.update(os.environ) - server = TestServer((test_host, 0), responses) + server = MockServer((test_host, 0), responses) test_port = server.server_address[1] threading.Thread(target=lambda: server.serve_forever()).start() From 0a3094c5c658b5c6730d6d0e977a5985ba350542 Mon Sep 17 00:00:00 2001 From: Mike Pennisi Date: Mon, 8 Jul 2019 15:45:59 -0400 Subject: [PATCH 12/23] Omit body in response to DELETE requests --- tools/ci/tests/test_update_pr_preview.py | 11 ++++++----- tools/ci/update_pr_preview.py | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/tools/ci/tests/test_update_pr_preview.py b/tools/ci/tests/test_update_pr_preview.py index e699f029d8..06aa83df0b 100644 --- a/tools/ci/tests/test_update_pr_preview.py +++ b/tools/ci/tests/test_update_pr_preview.py @@ -240,14 +240,15 @@ def test_remove_unrelated_label(): def test_remove_active_label(): event_data = default_data('unlabeled') event_data['label'] = {'name': 'pull-request-has-preview'} - expected = ( - 'DELETE', '/repos/test-org/test-repo/git/refs/tags/pr_preview_543' - ) + responses = { + ('DELETE', '/repos/test-org/test-repo/git/refs/tags/pr_preview_543'): + (204, '') + } - returncode, requests = run(event_data) + returncode, requests = run(event_data, responses) assert_success(returncode) - assert expected in requests + assert responses.keys()[0] in requests def test_synchronize_without_label(): diff --git a/tools/ci/update_pr_preview.py b/tools/ci/update_pr_preview.py index a97ed7745d..1815873cff 100644 --- a/tools/ci/update_pr_preview.py +++ b/tools/ci/update_pr_preview.py @@ -112,7 +112,7 @@ def delete_tag(self, tag): logger.info('Deleting tag "{}"'.format(tag)) try: - request(url, 'delete') + request(url, 'delete', ignore_body=True) except requests.HTTPError as exception: if exception.response.status_code != 404: raise From 107adfd275dbcac1e6b84c9ac7db00139b5c1ec2 Mon Sep 17 00:00:00 2001 From: Mike Pennisi Date: Mon, 8 Jul 2019 15:47:28 -0400 Subject: [PATCH 13/23] Improve logging message --- tools/ci/update_pr_preview.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/ci/update_pr_preview.py b/tools/ci/update_pr_preview.py index 1815873cff..837f470ed5 100644 --- a/tools/ci/update_pr_preview.py +++ b/tools/ci/update_pr_preview.py @@ -34,7 +34,7 @@ def request(url, method_name, data=None, json_data=None, params=None, } method = getattr(requests, method_name) - logger.info('Loading URL %s' % url) + logger.info('Issuing request: {} {}'.format(method_name.upper(), url)) if json_data is not None or data is not None: kwargs['json'] = json_data kwargs['data'] = data From 250aeaaf04999ec14bcbf6b730a9938342167670 Mon Sep 17 00:00:00 2001 From: Mike Pennisi Date: Mon, 8 Jul 2019 15:48:52 -0400 Subject: [PATCH 14/23] Simplify helper function --- tools/ci/update_pr_preview.py | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/tools/ci/update_pr_preview.py b/tools/ci/update_pr_preview.py index 837f470ed5..4bd1a47b01 100644 --- a/tools/ci/update_pr_preview.py +++ b/tools/ci/update_pr_preview.py @@ -17,20 +17,14 @@ class Status(object): NEUTRAL = 78 -def request(url, method_name, data=None, json_data=None, params=None, - extra_headers=None, ignore_body=False): +def request(url, method_name, data=None, json_data=None, ignore_body=False): github_token = os.environ.get('GITHUB_TOKEN') - headers = { - 'Authorization': 'token {}'.format(github_token), - 'Accept': 'application/vnd.github.machine-man-preview+json' - } - - if extra_headers is not None: - headers.update(extra_headers) kwargs = { - 'params': params, - 'headers': headers + 'headers': { + 'Authorization': 'token {}'.format(github_token), + 'Accept': 'application/vnd.github.machine-man-preview+json' + } } method = getattr(requests, method_name) From e92ab0b442a82f26666f65294fcdd5dc4cec2d5c Mon Sep 17 00:00:00 2001 From: Mike Pennisi Date: Mon, 8 Jul 2019 17:07:49 -0400 Subject: [PATCH 15/23] Make test more realistic --- tools/ci/tests/test_update_pr_preview.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tools/ci/tests/test_update_pr_preview.py b/tools/ci/tests/test_update_pr_preview.py index 06aa83df0b..4501b0f86d 100644 --- a/tools/ci/tests/test_update_pr_preview.py +++ b/tools/ci/tests/test_update_pr_preview.py @@ -216,14 +216,15 @@ def test_add_active_label(): event_data['pull_request']['labels'].append( {'name': 'pull-request-has-preview'} ) + responses = {( + 'GET', '/repos/test-org/test-repo/git/refs/tags/pr_preview_543' + ): (404, '{}')} - returncode, requests = run(event_data) + returncode, requests = run(event_data, responses) assert_success(returncode) - expected = ( - 'PATCH', - '/repos/test-org/test-repo/git/refs/tags/pr_preview_543' - ) + expected = ('POST', '/repos/test-org/test-repo/git/refs') + assert responses.keys()[0] in requests assert expected in requests From 3296ddbed70b1705ede15638ea95edff60a168cf Mon Sep 17 00:00:00 2001 From: Mike Pennisi Date: Mon, 8 Jul 2019 17:14:19 -0400 Subject: [PATCH 16/23] Manage tags and labels simultaneously --- tools/ci/tests/test_update_pr_preview.py | 26 +++++++++++++----------- tools/ci/update_pr_preview.py | 21 +++++++++++++++---- 2 files changed, 31 insertions(+), 16 deletions(-) diff --git a/tools/ci/tests/test_update_pr_preview.py b/tools/ci/tests/test_update_pr_preview.py index 4501b0f86d..c760bf2bfc 100644 --- a/tools/ci/tests/test_update_pr_preview.py +++ b/tools/ci/tests/test_update_pr_preview.py @@ -110,15 +110,19 @@ def test_close_active_with_label(): event_data['pull_request']['labels'].append( {'name': 'pull-request-has-preview'} ) - expected = ( + delete_label = ( 'DELETE', '/repos/test-org/test-repo/issues/543/labels/pull-request-has-preview' ) + delete_tag = ( + 'DELETE', '/repos/test-org/test-repo/git/refs/tags/pr_preview_543' + ) returncode, requests = run(event_data) assert_success(returncode) - assert expected in requests + assert delete_label in requests + assert delete_tag in requests def test_close_active_with_label_error(): @@ -166,22 +170,20 @@ def test_open_with_label(): def test_open_without_label_for_collaborator(): event_data = default_data('opened') responses = { - ('GET', '/repos/test-org/test-repo/collaborators/rms'): (204, '') + ('GET', '/repos/test-org/test-repo/collaborators/rms'): (204, ''), + ('GET', '/repos/test-org/test-repo/git/refs/tags/pr_preview_543'): + (404, '{}') } returncode, requests = run(event_data, responses) assert_success(returncode) - check_collaborator = ( - 'GET', '/repos/test-org/test-repo/collaborators/rms' - ) - create_label = ( - 'POST', - '/repos/test-org/test-repo/issues/543/labels' - ) - assert len(requests) == 2 - assert check_collaborator in requests + create_label = ('POST', '/repos/test-org/test-repo/issues/543/labels') + create_tag = ('POST', '/repos/test-org/test-repo/git/refs') + assert responses.keys()[0] in requests + assert responses.keys()[1] in requests assert create_label in requests + assert create_tag in requests def test_open_without_label_for_non_collaborator(): diff --git a/tools/ci/update_pr_preview.py b/tools/ci/update_pr_preview.py index 4bd1a47b01..863da036fe 100644 --- a/tools/ci/update_pr_preview.py +++ b/tools/ci/update_pr_preview.py @@ -177,9 +177,16 @@ def main(api_root): if not is_open: if action == 'closed' and has_label: - # This operation will trigger another GitHub Action which will - # subsequently delete the tag. github.remove_label(pr_number, active_label) + + # > An action can't trigger other workflows. For example, a push, + # > deployment, or any task performed within an action with the + # > provided `GITHUB_TOKEN` will not trigger a workflow listening + # > on push, deploy, or any other supported action triggers. + # + # https://developer.github.com/actions/managing-workflows/workflow-configuration-options/ + github.delete_tag(tag_name) + return Status.SUCCESS return Status.NEUTRAL @@ -187,9 +194,15 @@ def main(api_root): if action in ('opened', 'reopened') and has_label: github.tag(tag_name, sha) elif action in ('opened', 'reopened') and github.is_collaborator(login): - # This operation will trigger another GitHub Action which will - # subsequently create the tag. github.add_label(pr_number, active_label) + + # > An action can't trigger other workflows. For example, a push, + # > deployment, or any task performed within an action with the + # > provided `GITHUB_TOKEN` will not trigger a workflow listening on + # > push, deploy, or any other supported action triggers. + # + # https://developer.github.com/actions/managing-workflows/workflow-configuration-options/ + github.tag(tag_name, sha) elif action == 'labeled' and target_label == active_label: github.tag(tag_name, sha) elif action == 'unlabeled' and target_label == active_label: From b419da74ba778900fb30c409656843886c034b37 Mon Sep 17 00:00:00 2001 From: Mike Pennisi Date: Mon, 8 Jul 2019 17:18:03 -0400 Subject: [PATCH 17/23] Add debugging statement --- tools/ci/update_pr_preview.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/ci/update_pr_preview.py b/tools/ci/update_pr_preview.py index 863da036fe..83e89b4de6 100644 --- a/tools/ci/update_pr_preview.py +++ b/tools/ci/update_pr_preview.py @@ -11,6 +11,12 @@ logger = logging.getLogger(__name__) +import subprocess +logger.info( + subprocess.check_output(['git', 'rev-parse', 'HEAD']) +) + + class Status(object): SUCCESS = 0 FAIL = 1 From 5b3f859794b6d53c9f190f8215ad45a9710ce47f Mon Sep 17 00:00:00 2001 From: Mike Pennisi Date: Mon, 8 Jul 2019 17:48:02 -0400 Subject: [PATCH 18/23] Remove debugging statements --- tools/ci/update_pr_preview.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tools/ci/update_pr_preview.py b/tools/ci/update_pr_preview.py index 83e89b4de6..863da036fe 100644 --- a/tools/ci/update_pr_preview.py +++ b/tools/ci/update_pr_preview.py @@ -11,12 +11,6 @@ logger = logging.getLogger(__name__) -import subprocess -logger.info( - subprocess.check_output(['git', 'rev-parse', 'HEAD']) -) - - class Status(object): SUCCESS = 0 FAIL = 1 From fe9e488c83686846c6591749ded307a159744278 Mon Sep 17 00:00:00 2001 From: Mike Pennisi Date: Mon, 8 Jul 2019 17:50:34 -0400 Subject: [PATCH 19/23] Improve formatting --- tools/ci/update_pr_preview.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/tools/ci/update_pr_preview.py b/tools/ci/update_pr_preview.py index 863da036fe..9c056edfca 100644 --- a/tools/ci/update_pr_preview.py +++ b/tools/ci/update_pr_preview.py @@ -168,13 +168,12 @@ def main(api_root): sha = event['pull_request']['head']['sha'] is_open = event['pull_request']['closed_at'] is None login = event['pull_request']['user']['login'] - has_label = any( - [label['name'] == active_label - for label in event['pull_request']['labels']] - ) + has_label = any([ + label['name'] == active_label + for label in event['pull_request']['labels'] + ]) target_label = event.get('label', {}).get('name') - if not is_open: if action == 'closed' and has_label: github.remove_label(pr_number, active_label) From 852ee214f89dd3d31c4cb2816fabb19d8411a2d9 Mon Sep 17 00:00:00 2001 From: Mike Pennisi Date: Mon, 8 Jul 2019 18:09:08 -0400 Subject: [PATCH 20/23] Add documentation --- tools/ci/update_pr_preview.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tools/ci/update_pr_preview.py b/tools/ci/update_pr_preview.py index 9c056edfca..fe22614963 100644 --- a/tools/ci/update_pr_preview.py +++ b/tools/ci/update_pr_preview.py @@ -1,3 +1,30 @@ +# wpt-submissions.live is a public deployment of WPT, maintained in an external +# repository. It automatically fetches and deploys all tags in the WPT +# repository which match a certain pattern. This behavior is intended to be +# used for pull requests so that reviewers can preview changes without running +# the WPT server locally. +# +# This script facilitates the service by maintaining the git tags. It creates +# and updates tags in response to GitHub events. It does this automatically for +# pull requests from GitHub users who have "collaborator" access permissions to +# the WPT repository. It also does this for any pull requests which bear the +# `pull-request-has-preview` label. Collaborators can add or remove this label +# to enable or disable the preview for submissions from non-collaborators. +# +# Although the script relies on secret access tokens, it is *not* limited to +# use for pull requests from trusted collaborators due to the way GitHub +# Actions are executed: +# +# > # Pull request events for forked repositories +# > +# > [...] +# > +# > ## Pull request with base and head branches in different repositories +# > +# > The base repository receives a pull_request event where the SHA is the +# > latest commit of base branch and ref is the base branch. +# +# https://developer.github.com/actions/managing-workflows/workflow-configuration-options/#pull-request-events-for-forked-repositories import json import logging import os From 13df69cc052f8111ada1383fd3326ae160b6765c Mon Sep 17 00:00:00 2001 From: jugglinmike-bocoup Date: Mon, 8 Jul 2019 18:43:25 -0400 Subject: [PATCH 21/23] Add an empty file --- empty | 1 + 1 file changed, 1 insertion(+) create mode 100644 empty diff --git a/empty b/empty new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/empty @@ -0,0 +1 @@ + From 2575ea5bc0b276957b8962b166755314cdbe9267 Mon Sep 17 00:00:00 2001 From: jugglinmike-bocoup Date: Mon, 8 Jul 2019 18:49:47 -0400 Subject: [PATCH 22/23] Add another empty file --- empty2 | 1 + 1 file changed, 1 insertion(+) create mode 100644 empty2 diff --git a/empty2 b/empty2 new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/empty2 @@ -0,0 +1 @@ + From 091561469fcf5772716d13ba34a9389c8973be95 Mon Sep 17 00:00:00 2001 From: jugglinmike-bocoup Date: Mon, 8 Jul 2019 18:55:52 -0400 Subject: [PATCH 23/23] Add a third empty file --- empty3 | 1 + 1 file changed, 1 insertion(+) create mode 100644 empty3 diff --git a/empty3 b/empty3 new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/empty3 @@ -0,0 +1 @@ +