Skip to content
This repository was archived by the owner on Mar 19, 2021. It is now read-only.

Commit d071aae

Browse files
committed
Refactor
1 parent 4515947 commit d071aae

File tree

3 files changed

+67
-33
lines changed

3 files changed

+67
-33
lines changed

.github/workflows/detect_pull_request_preview.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: Detect Pull Request Preview
2-
on: deployment
2+
on: deployment_status
33
jobs:
44
detect-deployment:
55
runs-on: ubuntu-18.04
@@ -12,8 +12,8 @@ jobs:
1212
./tools/ci/pr_preview.py
1313
--host http://api.github.com
1414
--github-project web-platform-tests/wpt-actions-test
15-
detect
1615
--target http://s92097608.onlinehome.us/tmp
16+
detect
1717
--timeout 600
1818
env:
1919
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.github/workflows/pull_request_previews.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ jobs:
1414
./tools/ci/pr_preview.py
1515
--host https://api.github.com
1616
--github-project web-platform-tests/wpt-actions-test
17+
--target http://s92097608.onlinehome.us/tmp
1718
synchronize
1819
--remote origin
1920
--window 480

tools/ci/pr_preview.py

Lines changed: 64 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,13 @@
3434
logging.basicConfig(level=logging.INFO)
3535
logger = logging.getLogger(__name__)
3636

37-
def gh_request(method_name, url, body=None):
37+
def gh_request(method_name, url, body=None, media_type=None):
3838
github_token = os.environ.get('GITHUB_TOKEN')
3939

4040
kwargs = {
4141
'headers': {
4242
'Authorization': 'token {}'.format(github_token),
43-
'Accept': 'application/vnd.github.v3+json'
43+
'Accept': media_type or 'application/vnd.github.v3+json'
4444
}
4545
}
4646
method = getattr(requests, method_name.lower())
@@ -145,51 +145,71 @@ def update_ref(self, refspec, revision):
145145
gh_request('PATCH', url, { 'sha': revision })
146146

147147
@guard('core')
148-
def create_deployment(self, pull_request):
148+
def create_deployment(self, pull_request, revision):
149149
url = '{}/repos/{}/deployments'.format(
150150
self._host, self._github_project
151151
)
152-
ref = 'refs/pull/{number}/head'.format(**pull_request)
152+
# The pull request preview system only exposes one deployment for a
153+
# given pull request. Identifying the deployment by the pull request
154+
# number ensures that GitHub.com automatically responds to new
155+
# deployments by designating prior deployments as "inactive"
156+
environment = 'gh-{}'.format(pull_request['number'])
153157

154158
logger.info('Creating deployment for "%s"', ref)
155159

156-
gh_request('POST', url, {
157-
'ref': ref,
158-
# The pull request preview system only exposes one deployment for
159-
# a given pull request. Identifying the deployment by the pull
160-
# request number ensures that GitHub.com automatically responds to
161-
# new deployments by designating prior deployments as "inactive"
162-
'environment': str(pull_request['number']),
160+
return gh_request('POST', url, {
161+
'ref': revision,
162+
'environment': environment,
163+
'auto_merge': False,
163164
# Pull request previews are created regardless of GitHub Commit
164165
# Status Checks, so Status Checks should be ignored when creating
165166
# GitHub Deployments.
166167
'required_contexts': []
167-
})
168+
}, 'application/vnd.github.ant-man-preview+json')
168169

169170
@guard('core')
170-
def get_deployment(self, pull_request):
171-
url = '{}/repos/{}/deployments?environment={}'.format(
172-
self._host, self._github_project, pull_request['number']
171+
def get_deployment(self, revision):
172+
url = '{}/repos/{}/deployments?sha={}'.format(
173+
self._host, self._github_project, revision
173174
)
174175

175176
deployments = gh_request('GET', url)
176177

177178
return deployments.pop() if len(deployments) else None
178179

179180
@guard('core')
180-
def update_deployment(self, deployment, state, description=''):
181+
def deployment_is_pending(self, deployment):
181182
url = '{}/repos/{}/deployments/{}/statuses'.format(
182183
self._host, self._github_project, deployment['id']
183184
)
184-
environment_url = '{}/submissions/{}/'.format(
185-
target, deployment['environment']
185+
186+
statuses = sorted(
187+
gh_request('GET', url),
188+
key=lambda status: status['created_at']
189+
)
190+
191+
if len(statuses) == 0:
192+
return False
193+
194+
return statuses[-1]['state'] == 'pending'
195+
196+
@guard('core')
197+
def update_deployment(self, target, deployment, state, description=''):
198+
if state in ('pending', 'success'):
199+
environment_url = '{}/submissions/{}'.format(
200+
target, deployment['environment']
201+
)
202+
else:
203+
environment_url = None
204+
url = '{}/repos/{}/deployments/{}/statuses'.format(
205+
self._host, self._github_project, deployment['id']
186206
)
187207

188208
gh_request('POST', url, {
189209
'state': state,
190210
'description': description,
191211
'environment_url': environment_url
192-
})
212+
}, 'application/vnd.github.ant-man-preview+json')
193213

194214
class Remote(object):
195215
def __init__(self, name):
@@ -243,21 +263,24 @@ def is_deployed(host, deployment):
243263

244264
return response.text.strip() == deployment['sha']
245265

246-
def synchronize(host, github_project, remote_name, window):
266+
def synchronize(host, github_project, target, remote_name, window):
247267
'''Inspect all pull requests which have been modified in a given window of
248268
time. Add or remove the "preview" label and update or delete the relevant
249269
git refs according to the status of each pull request.'''
250270

251271
project = Project(host, github_project)
252272
remote = Remote(remote_name)
273+
253274
pull_requests = project.get_pull_requests(
254275
time.gmtime(time.time() - window)
255276
)
256277

257278
for pull_request in pull_requests:
258279
logger.info('Processing pull request #%(number)d', pull_request)
259280

260-
refspec_labeled = 'prs-labeled-for-preview/{number}'.format(**pull_request)
281+
refspec_labeled = 'prs-labeled-for-preview/{number}'.format(
282+
**pull_request
283+
)
261284
refspec_open = 'prs-open/{number}'.format(**pull_request)
262285
revision_latest = remote.get_revision(
263286
'pull/{number}/head'.format(**pull_request)
@@ -281,8 +304,14 @@ def synchronize(host, github_project, remote_name, window):
281304
elif revision_open != revision_latest:
282305
project.update_ref(refspec_open, revision_latest)
283306

284-
if project.get_deployment(pull_request) is None:
285-
project.create_deployment(pull_request)
307+
deployment = project.get_deployment(revision_latest)
308+
if deployment is None:
309+
deployment = project.create_deployment(
310+
pull_request, revision_latest
311+
)
312+
313+
if not project.deployment_is_pending(deployment):
314+
project.update_deployment(target, deployment, 'pending')
286315
else:
287316
logger.info('Pull request should not be mirrored')
288317

@@ -304,16 +333,20 @@ def detect(host, github_project, target, timeout):
304333

305334
logger.info('Event data: %s', json.dumps(data, indent=2))
306335

307-
deployment = data['deployment']
336+
if data['deployment_status']['state'] != 'pending':
337+
logger.info('Deployment is not pending. Exiting.')
338+
return
308339

309-
pr_number = int(deployment['environment'])
340+
deployment = data['deployment']
310341

311-
project.update_deployment(deployment, 'in_progress')
342+
if not deployment['environment'].startswith('gh-'):
343+
logger.info('Deployment environment is unrecognized. Exiting.')
344+
return
312345

313346
logger.info(
314-
'Waiting up to %d seconds for pull request #%d to be deployed to %s',
347+
'Waiting up to %d seconds for deployment %s to be available on %s',
315348
timeout,
316-
pr_number,
349+
deployment['environment'],
317350
target
318351
)
319352

@@ -322,12 +355,12 @@ def detect(host, github_project, target, timeout):
322355
while not is_deployed(target, deployment):
323356
if time.time() - start > timeout:
324357
message = 'Deployment did not become available after {} seconds'.format(timeout)
325-
project.update_deployment(deployment, 'error', message)
358+
project.update_deployment(target, deployment, 'error', message)
326359
raise Exception(message)
327360

328361
time.sleep(POLLING_PERIOD)
329362

330-
project.update_deployment(deployment, 'success')
363+
project.update_deployment(target, deployment, 'success')
331364

332365
if __name__ == '__main__':
333366
parser = argparse.ArgumentParser()
@@ -339,6 +372,7 @@ def detect(host, github_project, target, timeout):
339372
help='''the GitHub organization and GitHub project name, separated by
340373
a forward slash (e.g. "web-platform-tests/wpt")'''
341374
)
375+
parser.add_argument('--target', required=True)
342376
subparsers = parser.add_subparsers(title='subcommands')
343377

344378
parser_sync = subparsers.add_parser(
@@ -349,7 +383,6 @@ def detect(host, github_project, target, timeout):
349383
parser_sync.set_defaults(func=synchronize)
350384

351385
parser_detect = subparsers.add_parser('detect', help=detect.__doc__)
352-
parser_detect.add_argument('--target', required=True)
353386
parser_detect.add_argument('--timeout', type=int, required=True)
354387
parser_detect.set_defaults(func=detect)
355388

0 commit comments

Comments
 (0)