@@ -4,6 +4,10 @@ name: Release
44
55on :
66 workflow_dispatch :
7+ inputs :
8+ release-pr :
9+ description : a release PR number to rerun release jobs on
10+ type : string
711 push :
812 branches :
913 - main
1923 release :
2024 outputs :
2125 pr : ${{ steps.release.outputs.pr }}
26+ release : ${{ steps.release.outputs.release }}
2227 releases : ${{ steps.release.outputs.releases }}
23- release-flags : ${{ steps.release.outputs.release-flags }}
2428 branch : ${{ steps.release.outputs.pr-branch }}
2529 pr-number : ${{ steps.release.outputs.pr-number }}
2630 comment-id : ${{ steps.pr-comment.outputs.result }}
5054 env :
5155 GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
5256 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 }}"
5458 - name : Post Pull Request Comment
5559 if : steps.release.outputs.pr-number
5660 uses : actions/github-script@v6
@@ -60,26 +64,25 @@ jobs:
6064 REF_NAME : ${{ github.ref_name }}
6165 with :
6266 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
6669
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 })
6871
6972 let body = '## Release Manager\n\n'
7073
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
7376
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\`\`\``
7881
7982 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 })
8184 } 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 })
8386 commentId = comment?.id
8487 }
8588
@@ -162,7 +165,7 @@ jobs:
162165 RELEASE_COMMENT_ID : ${{ needs.release.outputs.comment-id }}
163166 GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
164167 run : |
165- node . exec --offline -- template-oss-release-manager
168+ node . exec --offline -- template-oss-release-manager --lockfile=true
166169 node . run rp-pull-request --ignore-scripts -ws -iwr --if-present
167170 - name : Commit
168171 id : commit
@@ -270,21 +273,132 @@ jobs:
270273 run :
271274 shell : bash
272275 steps :
273- - name : Checkout
274- uses : actions/checkout@v3
275- - name : Setup Git User
276- run : |
277- git config --global user.email "npm-cli+bot@github.com"
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 :
279318 - name : Setup Node
280319 uses : actions/setup-node@v3
281320 with :
282321 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
289360 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