@@ -133,12 +133,314 @@ const cascadingRuns = async (context, req) => {
133
133
134
134
return comment
135
135
}
136
+ if ( checkRunOwner === 'git-for-windows'
137
+ && checkRunRepo === 'git'
138
+ && name . startsWith ( 'git-artifacts-' ) ) {
139
+ const output = req . body . check_run . output
140
+ const match = output . summary . match (
141
+ / B u i l d G i t ( \S + ) a r t i f a c t s f r o m c o m m i t ( \S + ) \( t a g - g i t r u n # ( \d + ) \) /
142
+ )
143
+ if ( ! match ) throw new Error (
144
+ `Could not parse 'summary' attribute of check-run ${ req . body . check_run . id } : ${ output . summary } `
145
+ )
146
+ const [ , ver , commit , tagGitWorkflowRunID ] = match
147
+ const snapshotTag = `prerelease-${ ver . replace ( / ^ v / , '' ) } `
148
+
149
+ // First, verify that the snapshot has not been uploaded yet
150
+ const gitSnapshotsToken = await getToken ( context , checkRunOwner , 'git-snapshots' )
151
+ const githubApiRequest = require ( './github-api-request' )
152
+ try {
153
+ const releasePath = `${ checkRunOwner } /git-snapshots/releases/tags/${ snapshotTag } `
154
+ await githubApiRequest (
155
+ context ,
156
+ gitSnapshotsToken ,
157
+ 'GET' ,
158
+ `/repos/${ releasePath } ` ,
159
+ )
160
+ return `Ignoring ${ name } check-run because the snapshot for ${ commit } was already uploaded`
161
+ + ` to https://github.com/${ releasePath } `
162
+ } catch ( e ) {
163
+ if ( e ?. statusCode !== 404 ) throw e
164
+ // The snapshot does not exist yet
165
+ }
166
+
167
+ // Next, check that the commit is on the `main` branch
168
+ const gitToken = await getToken ( context , checkRunOwner , checkRunRepo )
169
+ const { behind_by } = await githubApiRequest (
170
+ context ,
171
+ gitToken ,
172
+ 'GET' ,
173
+ `/repos/${ checkRunOwner } /${ checkRunRepo } /compare/HEAD...${ commit } ` ,
174
+ )
175
+ if ( behind_by > 0 ) {
176
+ return `Ignoring ${ name } check-run because its corresponding commit ${ commit } is not on the main branch`
177
+ }
178
+
179
+ const workFlowRunIDs = { }
180
+ const { listCheckRunsForCommit, queueCheckRun } = require ( './check-runs' )
181
+ for ( const architecture of [ 'x86_64' , 'i686' , 'aarch64' ] ) {
182
+ const workflowName = `git-artifacts-${ architecture } `
183
+ const runs = name === workflowName ? [ req . body . check_run ] : await listCheckRunsForCommit (
184
+ context ,
185
+ gitToken ,
186
+ checkRunOwner ,
187
+ checkRunRepo ,
188
+ commit ,
189
+ workflowName
190
+ )
191
+ const needle =
192
+ `Build Git ${ ver } artifacts from commit ${ commit } (tag-git run #${ tagGitWorkflowRunID } )`
193
+ const latest = runs
194
+ . filter ( run => run . output . summary === needle )
195
+ . sort ( ( a , b ) => a . id - b . id )
196
+ . pop ( )
197
+ if ( latest ) {
198
+ if ( latest . status !== 'completed' ) {
199
+ return `The '${ workflowName } ' run at ${ latest . html_url } did not complete yet.`
200
+ }
201
+ if ( latest . conclusion !== 'success' ) {
202
+ throw new Error ( `The '${ workflowName } ' run at ${ latest . html_url } did not succeed.` )
203
+ }
204
+
205
+ const match = latest . output . text . match (
206
+ / F o r d e t a i l s , s e e \[ t h i s r u n \] \( h t t p s : \/ \/ g i t h u b .c o m \/ ( [ ^ / ] + ) \/ ( [ ^ / ] + ) \/ a c t i o n s \/ r u n s \/ ( \d + ) \) /
207
+ )
208
+ if ( ! match ) throw new Error ( `Unhandled 'text' attribute of git-artifacts run ${ latest . id } : ${ latest . url } ` )
209
+ const owner = match [ 1 ]
210
+ const repo = match [ 2 ]
211
+ workFlowRunIDs [ architecture ] = match [ 3 ]
212
+ if ( owner !== 'git-for-windows' || repo !== 'git-for-windows-automation' ) {
213
+ throw new Error ( `Unexpected repository ${ owner } /${ repo } for git-artifacts run ${ latest . id } : ${ latest . url } ` )
214
+ }
215
+ } else {
216
+ return `Won't trigger 'upload-snapshot' in reaction to ${ name } because the '${ workflowName } ' run does not exist.`
217
+ }
218
+ }
219
+
220
+ const checkRunTitle = `Upload snapshot ${ snapshotTag } `
221
+ await queueCheckRun (
222
+ context ,
223
+ gitToken ,
224
+ 'git-for-windows' ,
225
+ 'git' ,
226
+ commit ,
227
+ 'upload-snapshot' ,
228
+ checkRunTitle ,
229
+ checkRunTitle
230
+ )
231
+
232
+ const gitForWindowsAutomationToken =
233
+ await getToken ( context , checkRunOwner , 'git-for-windows-automation' )
234
+ const triggerWorkflowDispatch = require ( './trigger-workflow-dispatch' )
235
+ const answer = await triggerWorkflowDispatch (
236
+ context ,
237
+ gitForWindowsAutomationToken ,
238
+ 'git-for-windows' ,
239
+ 'git-for-windows-automation' ,
240
+ 'upload-snapshot.yml' ,
241
+ 'main' , {
242
+ git_artifacts_x86_64_workflow_run_id : workFlowRunIDs [ 'x86_64' ] ,
243
+ git_artifacts_i686_workflow_run_id : workFlowRunIDs [ 'i686' ] ,
244
+ git_artifacts_aarch64_workflow_run_id : workFlowRunIDs [ 'aarch64' ] ,
245
+ }
246
+ )
247
+
248
+ return `The 'upload-snapshot' workflow run was started at ${ answer . html_url } `
249
+ }
136
250
return `Not a cascading run: ${ name } ; Doing nothing.`
137
251
}
138
252
return `Unhandled action: ${ action } `
139
253
}
140
254
255
+ const handlePush = async ( context , req ) => {
256
+ const pushOwner = req . body . repository . owner . login
257
+ const pushRepo = req . body . repository . name
258
+ const ref = req . body . ref
259
+ const commit = req . body . after
260
+
261
+ if ( pushOwner !== 'git-for-windows' || pushRepo !== 'git' ) {
262
+ throw new Error ( `Refusing to handle push to ${ pushOwner } /${ pushRepo } ` )
263
+ }
264
+
265
+ if ( ref !== 'refs/heads/main' ) return `Ignoring push to ${ ref } `
266
+
267
+ // See whether there was are already a `tag-git` check-run for this commit
268
+ const { listCheckRunsForCommit, queueCheckRun, updateCheckRun } = require ( './check-runs' )
269
+ const gitToken = await getToken ( context , pushOwner , pushRepo )
270
+ const runs = await listCheckRunsForCommit (
271
+ context ,
272
+ gitToken ,
273
+ pushOwner ,
274
+ pushRepo ,
275
+ commit ,
276
+ 'tag-git'
277
+ )
278
+
279
+ const latest = runs
280
+ . sort ( ( a , b ) => a . id - b . id )
281
+ . pop ( )
282
+
283
+ if ( latest && latest . status !== 'completed' ) throw new Error ( `The 'tag-git' run at ${ latest . html_url } did not complete yet before ${ commit } was pushed to ${ ref } !` )
284
+
285
+ const gitForWindowsAutomationToken =
286
+ await getToken ( context , pushOwner , 'git-for-windows-automation' )
287
+ const triggerWorkflowDispatch = require ( './trigger-workflow-dispatch' )
288
+ if ( ! latest ) {
289
+ // There is no `tag-git` workflow run; Trigger it to build a new snapshot
290
+ const tagGitCheckRunTitle = `Tag snapshot Git @${ commit } `
291
+ const tagGitCheckRunId = await queueCheckRun (
292
+ context ,
293
+ gitForWindowsAutomationToken ,
294
+ pushOwner ,
295
+ pushRepo ,
296
+ commit ,
297
+ 'tag-git' ,
298
+ tagGitCheckRunTitle ,
299
+ tagGitCheckRunTitle
300
+ )
301
+
302
+ try {
303
+ const answer = await triggerWorkflowDispatch (
304
+ context ,
305
+ gitForWindowsAutomationToken ,
306
+ pushOwner ,
307
+ 'git-for-windows-automation' ,
308
+ 'tag-git.yml' ,
309
+ 'main' , {
310
+ rev : commit ,
311
+ owner : pushOwner ,
312
+ repo : pushRepo ,
313
+ snapshot : 'true'
314
+ }
315
+ )
316
+ return `The 'tag-git' workflow run was started at ${ answer . html_url } `
317
+ } catch ( e ) {
318
+ await updateCheckRun (
319
+ context ,
320
+ gitForWindowsAutomationToken ,
321
+ pushOwner ,
322
+ pushRepo ,
323
+ tagGitCheckRunId , {
324
+ status : 'completed' ,
325
+ conclusion : 'failure' ,
326
+ output : {
327
+ title : tagGitCheckRunTitle ,
328
+ summary : tagGitCheckRunTitle ,
329
+ text : e . message || JSON . stringify ( e , null , 2 )
330
+ }
331
+ }
332
+ )
333
+ throw e
334
+ }
335
+ }
336
+
337
+ if ( latest . conclusion !== 'success' ) throw new Error (
338
+ `The 'tag-git' run at ${ latest . html_url } did not succeed (conclusion = ${ latest . conclusion } ).`
339
+ )
340
+
341
+ // There is already a `tag-git` workflow run; Is there already an `upload-snapshot` run?
342
+ const latestUploadSnapshotRun = ( await listCheckRunsForCommit (
343
+ context ,
344
+ gitToken ,
345
+ pushOwner ,
346
+ pushRepo ,
347
+ commit ,
348
+ 'upload-snapshot'
349
+ ) ) . pop ( )
350
+ if ( latestUploadSnapshotRun ) return `The 'upload-snapshot' check-run already exists for ${ commit } : ${ latestUploadSnapshotRun . html_url } `
351
+
352
+ // Trigger the `upload-snapshot` run directly
353
+ const tagGitCheckRunTitle = `Upload snapshot Git @${ commit } `
354
+ const tagGitCheckRunId = await queueCheckRun (
355
+ context ,
356
+ await getToken ( ) ,
357
+ pushOwner ,
358
+ pushRepo ,
359
+ commit ,
360
+ 'tag-git' ,
361
+ tagGitCheckRunTitle ,
362
+ tagGitCheckRunTitle
363
+ )
364
+
365
+ const match = latest . output . summary . match ( / ^ T a g G i t ( \S + ) @ ( [ 0 - 9 a - f ] + ) $ / )
366
+ if ( ! match ) throw new Error ( `Unexpected summary '${ latest . output . summary } ' of tag-git run: ${ latest . html_url } ` )
367
+ if ( ! match [ 2 ] === commit ) throw new Error ( `Unexpected revision ${ match [ 2 ] } '${ latest . output . summary } ' of tag-git run: ${ latest . html_url } ` )
368
+ const ver = match [ 1 ]
369
+
370
+ try {
371
+ const workFlowRunIDs = { }
372
+ for ( const architecture of [ 'x86_64' , 'i686' , 'aarch64' ] ) {
373
+ const workflowName = `git-artifacts-${ architecture } `
374
+ const runs = await listCheckRunsForCommit (
375
+ context ,
376
+ gitToken ,
377
+ pushOwner ,
378
+ pushRepo ,
379
+ commit ,
380
+ workflowName
381
+ )
382
+ const needle =
383
+ `Build Git ${ ver } artifacts from commit ${ commit } (tag-git run #${ latest . id } )`
384
+ const latest2 = runs
385
+ . filter ( run => run . output . summary === needle )
386
+ . sort ( ( a , b ) => a . id - b . id )
387
+ . pop ( )
388
+ if ( latest2 ) {
389
+ if ( latest2 . status !== 'completed' || latest2 . conclusion !== 'success' ) {
390
+ throw new Error ( `The '${ workflowName } ' run at ${ latest2 . html_url } did not succeed.` )
391
+ }
392
+
393
+ const match = latest2 . output . text . match (
394
+ / F o r d e t a i l s , s e e \[ t h i s r u n \] \( h t t p s : \/ \/ g i t h u b .c o m \/ ( [ ^ / ] + ) \/ ( [ ^ / ] + ) \/ a c t i o n s \/ r u n s \/ ( \d + ) \) /
395
+ )
396
+ if ( ! match ) throw new Error ( `Unhandled 'text' attribute of git-artifacts run ${ latest2 . id } : ${ latest2 . url } ` )
397
+ const owner = match [ 1 ]
398
+ const repo = match [ 2 ]
399
+ workFlowRunIDs [ architecture ] = match [ 3 ]
400
+ if ( owner !== 'git-for-windows' || repo !== 'git-for-windows-automation' ) {
401
+ throw new Error ( `Unexpected repository ${ owner } /${ repo } for git-artifacts run ${ latest2 . id } : ${ latest2 . url } ` )
402
+ }
403
+ } else {
404
+ return `Won't trigger 'upload-snapshot' on pushing ${ commit } because the '${ workflowName } ' run does not exist.`
405
+ }
406
+ }
407
+
408
+ const answer = await triggerWorkflowDispatch (
409
+ context ,
410
+ gitForWindowsAutomationToken ,
411
+ pushRepo ,
412
+ 'git-for-windows-automation' ,
413
+ 'upload-snapshot.yml' ,
414
+ 'main' , {
415
+ git_artifacts_x86_64_workflow_run_id : workFlowRunIDs [ 'x86_64' ] ,
416
+ git_artifacts_i686_workflow_run_id : workFlowRunIDs [ 'i686' ] ,
417
+ git_artifacts_aarch64_workflow_run_id : workFlowRunIDs [ 'aarch64' ] ,
418
+ }
419
+ )
420
+
421
+ return `The 'upload-snapshot' workflow run was started at ${ answer . html_url } `
422
+ } catch ( e ) {
423
+ await updateCheckRun (
424
+ context ,
425
+ gitForWindowsAutomationToken ,
426
+ pushOwner ,
427
+ pushRepo ,
428
+ tagGitCheckRunId , {
429
+ status : 'completed' ,
430
+ conclusion : 'failure' ,
431
+ output : {
432
+ title : tagGitCheckRunTitle ,
433
+ summary : tagGitCheckRunTitle ,
434
+ text : e . message || JSON . stringify ( e , null , 2 )
435
+ }
436
+ }
437
+ )
438
+ throw e
439
+ }
440
+ }
441
+
141
442
module . exports = {
142
443
triggerGitArtifactsRuns,
143
- cascadingRuns
444
+ cascadingRuns,
445
+ handlePush
144
446
}
0 commit comments