@@ -4,6 +4,10 @@ name: Release
4
4
5
5
on :
6
6
workflow_dispatch :
7
+ inputs :
8
+ release-pr :
9
+ description : a release PR number to rerun release jobs on
10
+ type : string
7
11
push :
8
12
branches :
9
13
- main
19
23
release :
20
24
outputs :
21
25
pr : ${{ steps.release.outputs.pr }}
26
+ release : ${{ steps.release.outputs.release }}
22
27
releases : ${{ steps.release.outputs.releases }}
23
- release-flags : ${{ steps.release.outputs.release-flags }}
24
28
branch : ${{ steps.release.outputs.pr-branch }}
25
29
pr-number : ${{ steps.release.outputs.pr-number }}
26
30
comment-id : ${{ steps.pr-comment.outputs.result }}
50
54
env :
51
55
GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
52
56
run : |
53
- npx --offline template-oss-release-please ${{ github.ref_name }} ${{ github.event_name }}
57
+ npx --offline template-oss-release-please " ${{ github.ref_name }}" " ${{ inputs.release-pr }}"
54
58
- name : Post Pull Request Comment
55
59
if : steps.release.outputs.pr-number
56
60
uses : actions/github-script@v6
@@ -60,26 +64,25 @@ jobs:
60
64
REF_NAME : ${{ github.ref_name }}
61
65
with :
62
66
script : |
63
- const { REF_NAME, PR_NUMBER } = process.env
64
- const repo = { owner: context.repo.owner, repo: context.repo.repo }
65
- const issue = { ...repo, issue_number: PR_NUMBER }
67
+ const { REF_NAME, PR_NUMBER: issue_number } = process.env
68
+ const { runId, repo: { owner, repo } } = context
66
69
67
- const { data: workflow } = await github.rest.actions.getWorkflowRun({ ... repo, run_id: context. runId })
70
+ const { data: workflow } = await github.rest.actions.getWorkflowRun({ owner, repo, run_id: runId })
68
71
69
72
let body = '## Release Manager\n\n'
70
73
71
- const comments = await github.paginate(github.rest.issues.listComments, issue )
72
- let commentId = comments? .find(c => c.user.login === 'github-actions[bot]' && c.body.startsWith(body))?.id
74
+ const comments = await github.paginate(github.rest.issues.listComments, { owner, repo, issue_number } )
75
+ let commentId = comments.find(c => c.user.login === 'github-actions[bot]' && c.body.startsWith(body))?.id
73
76
74
- body += `Release workflow run: ${workflow.html_url}\n\n#### Force CI to Rerun for This Release\n\n`
75
- body += `This PR will be updated and CI will run for every non-\`chore:\` commit that is pushed to \`main \`. `
76
- body += `To force CI to rerun , run this command:\n\n`
77
- body += `\`\`\`\ngh workflow run release.yml -r ${REF_NAME}\n\`\`\``
77
+ body += `Release workflow run: ${workflow.html_url}\n\n#### Force CI to Update This Release\n\n`
78
+ body += `This PR will be updated and CI will run for every non-\`chore:\` commit that is pushed to \`latest \`. `
79
+ body += `To force CI to update this PR , run this command:\n\n`
80
+ body += `\`\`\`\ngh workflow run release.yml -r ${REF_NAME} -R ${owner}/${repo} -f release-pr=${issue_number} \n\`\`\``
78
81
79
82
if (commentId) {
80
- await github.rest.issues.updateComment({ ... repo, comment_id: commentId, body })
83
+ await github.rest.issues.updateComment({ owner, repo, comment_id: commentId, body })
81
84
} else {
82
- const { data: comment } = await github.rest.issues.createComment({ ...issue , body })
85
+ const { data: comment } = await github.rest.issues.createComment({ owner, repo, issue_number , body })
83
86
commentId = comment?.id
84
87
}
85
88
@@ -162,7 +165,7 @@ jobs:
162
165
RELEASE_COMMENT_ID : ${{ needs.release.outputs.comment-id }}
163
166
GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
164
167
run : |
165
- node . exec --offline -- template-oss-release-manager
168
+ node . exec --offline -- template-oss-release-manager --lockfile=true
166
169
node . run rp-pull-request --ignore-scripts -ws -iwr --if-present
167
170
- name : Commit
168
171
id : commit
@@ -270,21 +273,132 @@ jobs:
270
273
run :
271
274
shell : bash
272
275
steps :
273
- - name : Checkout
274
- uses : actions/checkout@v3
275
- - name : Setup Git User
276
- run : |
277
- git config --global user.email "[email protected] "
278
- git config --global user.name "npm CLI robot"
276
+ - name : Create Release PR Comment
277
+ uses : actions/github-script@v6
278
+ env :
279
+ RELEASES : ${{ needs.release.outputs.releases }}
280
+ with :
281
+ script : |
282
+ const releases = JSON.parse(process.env.RELEASES)
283
+ const { runId, repo: { owner, repo } } = context
284
+ const issue_number = releases[0].prNumber
285
+
286
+ let body = '## Release Workflow\n\n'
287
+ for (const { pkgName, version, url } of releases) {
288
+ body += `- \`${pkgName}@${version}\` ${url}\n`
289
+ }
290
+
291
+ const comments = await github.paginate(github.rest.issues.listComments, { owner, repo, issue_number })
292
+ .then(cs => cs.map(c => ({ id: c.id, login: c.user.login, body: c.body })))
293
+ console.log(`Found comments: ${JSON.stringify(comments, null, 2)}`)
294
+ const releaseComments = comments.filter(c => c.login === 'github-actions[bot]' && c.body.includes('Release is at'))
295
+
296
+ for (const comment of releaseComments) {
297
+ console.log(`Release comment: ${JSON.stringify(comment, null, 2)}`)
298
+ await github.rest.issues.deleteComment({ owner, repo, comment_id: comment.id })
299
+ }
300
+
301
+ const runUrl = `https://github.com/${owner}/${repo}/actions/runs/${runId}`
302
+ await github.rest.issues.createComment({
303
+ owner,
304
+ repo,
305
+ issue_number,
306
+ body: `${body}- Workflow run: :arrows_counterclockwise: ${runUrl}`,
307
+ })
308
+
309
+ release-integration :
310
+ needs : release
311
+ name : Release Integration
312
+ if : needs.release.outputs.release
313
+ runs-on : ubuntu-latest
314
+ defaults :
315
+ run :
316
+ shell : bash
317
+ steps :
279
318
- name : Setup Node
280
319
uses : actions/setup-node@v3
281
320
with :
282
321
node-version : 16.x
283
- cache : npm
284
- - name : Reset Deps
285
- run : node . run resetdeps
286
- - name : Run Post Release Actions
287
- env :
288
- RELEASES : ${{ needs.release.outputs.releases }}
322
+ - name : View in Registry
323
+ run : |
324
+ EXIT_CODE=0
325
+
326
+ function is_published {
327
+ if npm view "$@" --loglevel=error > /dev/null; then
328
+ echo 0
329
+ else
330
+ echo 1
331
+ fi
332
+ }
333
+
334
+ for release in $(echo '${{ needs.release.outputs.releases }}' | jq -r '.[] | @base64'); do
335
+ name=$(echo "$release" | base64 --decode | jq -r .pkgName)
336
+ version=$(echo "$release" | base64 --decode | jq -r .version)
337
+ spec="$name@$version"
338
+ status=$(is_published "$spec")
339
+ if [[ "$status" -eq 1 ]]; then
340
+ echo "$spec ERROR"
341
+ EXIT_CODE=$status
342
+ else
343
+ echo "$spec OK"
344
+ fi
345
+ done
346
+
347
+ exit $EXIT_CODE
348
+
349
+ post-release-integration :
350
+ needs : [ release, release-integration ]
351
+ name : Post Release Integration - Release
352
+ if : github.repository_owner == 'npm' && needs.release.outputs.release && always()
353
+ runs-on : ubuntu-latest
354
+ defaults :
355
+ run :
356
+ shell : bash
357
+ steps :
358
+ - name : Get Needs Result
359
+ id : needs-result
289
360
run : |
290
- node . run rp-release --ignore-scripts --if-present ${{ join(fromJSON(needs.release.outputs.release-flags), ' ') }}
361
+ result=""
362
+ if [[ "${{ contains(needs.*.result, 'failure') }}" == "true" ]]; then
363
+ result="x"
364
+ elif [[ "${{ contains(needs.*.result, 'cancelled') }}" == "true" ]]; then
365
+ result="heavy_multiplication_x"
366
+ else
367
+ result="white_check_mark"
368
+ fi
369
+ echo "::set-output name=result::$result"
370
+ - name : Update Release PR Comment
371
+ uses : actions/github-script@v6
372
+ env :
373
+ PR_NUMBER : ${{ fromJSON(needs.release.outputs.release).prNumber }}
374
+ RESULT : ${{ steps.needs-result.outputs.result }}
375
+ with :
376
+ script : |
377
+ const { PR_NUMBER: issue_number, RESULT } = process.env
378
+ const { runId, repo: { owner, repo } } = context
379
+
380
+ const comments = await github.paginate(github.rest.issues.listComments, { owner, repo, issue_number })
381
+ const updateComment = comments.find(c =>
382
+ c.user.login === 'github-actions[bot]' &&
383
+ c.body.startsWith('## Release Workflow\n\n') &&
384
+ c.body.includes(runId)
385
+ )
386
+
387
+ if (updateComment) {
388
+ console.log('Found comment to update:', JSON.stringify(updateComment, null, 2))
389
+ let body = updateComment.body.replace(/Workflow run: :[a-z_]+:/, `Workflow run: :${RESULT}:`)
390
+ if (RESULT === 'x') {
391
+ body += `\n\n:rotating_light:`
392
+ body += ` @npm/cli-team: The post-release workflow failed for this release.`
393
+ body += ` Manual steps may need to be taken after examining the workflow output`
394
+ body += ` from the above workflow run. :rotating_light:`
395
+ }
396
+ await github.rest.issues.updateComment({
397
+ owner,
398
+ repo,
399
+ body,
400
+ comment_id: updateComment.id,
401
+ })
402
+ } else {
403
+ console.log('No matching comments found:', JSON.stringify(comments, null, 2))
404
+ }
0 commit comments