@npmcli/template-oss 4.10.0 → 4.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/release-manager.js +2 -2
- package/bin/release-please.js +14 -7
- package/lib/content/_job-release-integration.yml +12 -0
- package/lib/content/release.yml +82 -13
- package/lib/release-please/github.js +1 -0
- package/lib/release-please/index.js +39 -18
- package/lib/release-please/node-workspace.js +2 -3
- package/package.json +2 -3
package/bin/release-manager.js
CHANGED
|
@@ -53,7 +53,7 @@ const DEFAULT_RELEASE_PROCESS = `
|
|
|
53
53
|
Release Please will run on the just pushed release commit and create GitHub releases and tags for each package.
|
|
54
54
|
|
|
55
55
|
\`\`\`
|
|
56
|
-
gh run watch \`gh run list -w release -b <BASE-BRANCH> -L 1 --json databaseId -q ".[0].databaseId"\`
|
|
56
|
+
gh run watch \`gh run list -R {NWO} -w release -b <BASE-BRANCH> -L 1 --json databaseId -q ".[0].databaseId"\`
|
|
57
57
|
\`\`\`
|
|
58
58
|
` /* eslint-enable max-len */
|
|
59
59
|
|
|
@@ -82,7 +82,7 @@ const getReleaseProcess = async ({ owner, repo }) => {
|
|
|
82
82
|
} catch (e) {
|
|
83
83
|
log('Release wiki not found', e.message)
|
|
84
84
|
log('Using default release process')
|
|
85
|
-
releaseProcess = DEFAULT_RELEASE_PROCESS.trim() + '\n'
|
|
85
|
+
releaseProcess = DEFAULT_RELEASE_PROCESS.replace(/\{NWO\}/g, `${owner}/${repo}`).trim() + '\n'
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
// XXX: the release steps need to always be the last thing in the doc for this to work
|
package/bin/release-please.js
CHANGED
|
@@ -28,6 +28,18 @@ const debugPr = (val) => {
|
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
const debugRelease = (val) => {
|
|
32
|
+
if (dryRun) {
|
|
33
|
+
console.log('ROOT RELEASE:', JSON.stringify(val, null, 2))
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const debugReleases = (val) => {
|
|
38
|
+
if (dryRun) {
|
|
39
|
+
console.log('ALL RELEASES:', JSON.stringify(val, null, 2))
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
31
43
|
main({
|
|
32
44
|
token: process.env.GITHUB_TOKEN,
|
|
33
45
|
repo: process.env.GITHUB_REPOSITORY,
|
|
@@ -44,18 +56,13 @@ main({
|
|
|
44
56
|
}
|
|
45
57
|
|
|
46
58
|
if (release) {
|
|
59
|
+
debugRelease(release)
|
|
47
60
|
core.setOutput('release', JSON.stringify(release))
|
|
48
|
-
core.setOutput('release-path', release.path)
|
|
49
|
-
core.setOutput('release-version', release.version)
|
|
50
|
-
core.setOutput('release-tag', release.tagName)
|
|
51
|
-
core.setOutput('release-url', release.url)
|
|
52
61
|
}
|
|
53
62
|
|
|
54
63
|
if (releases) {
|
|
64
|
+
debugReleases(releases)
|
|
55
65
|
core.setOutput('releases', JSON.stringify(releases))
|
|
56
|
-
core.setOutput('release-flags', JSON.stringify(releases.map((r) => {
|
|
57
|
-
return r.path === '.' ? '-iwr' : `-w ${r.path}`
|
|
58
|
-
})))
|
|
59
66
|
}
|
|
60
67
|
|
|
61
68
|
return null
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
runs-on: ubuntu-latest
|
|
2
|
+
defaults:
|
|
3
|
+
run:
|
|
4
|
+
shell: bash
|
|
5
|
+
steps:
|
|
6
|
+
{{> stepGit }}
|
|
7
|
+
{{> stepNode }}
|
|
8
|
+
- name: View in Registry
|
|
9
|
+
run: |
|
|
10
|
+
name=$(cat package.json | jq -r .name)
|
|
11
|
+
version="$\{{ fromJSON(needs.release.output.release).version }}"
|
|
12
|
+
npm view ${name}@${version}
|
package/lib/content/release.yml
CHANGED
|
@@ -18,8 +18,8 @@ jobs:
|
|
|
18
18
|
release:
|
|
19
19
|
outputs:
|
|
20
20
|
pr: $\{{ steps.release.outputs.pr }}
|
|
21
|
+
release: $\{{ steps.release.outputs.release }}
|
|
21
22
|
releases: $\{{ steps.release.outputs.releases }}
|
|
22
|
-
release-flags: $\{{ steps.release.outputs.release-flags }}
|
|
23
23
|
branch: $\{{ steps.release.outputs.pr-branch }}
|
|
24
24
|
pr-number: $\{{ steps.release.outputs.pr-number }}
|
|
25
25
|
comment-id: $\{{ steps.pr-comment.outputs.result }}
|
|
@@ -40,26 +40,25 @@ jobs:
|
|
|
40
40
|
REF_NAME: $\{{ github.ref_name }}
|
|
41
41
|
with:
|
|
42
42
|
script: |
|
|
43
|
-
const { REF_NAME, PR_NUMBER } = process.env
|
|
44
|
-
const repo
|
|
45
|
-
const issue = { ...repo, issue_number: PR_NUMBER }
|
|
43
|
+
const { REF_NAME, PR_NUMBER: issue_number } = process.env
|
|
44
|
+
const { runId, repo: { owner, repo } } = context
|
|
46
45
|
|
|
47
|
-
const { data: workflow } = await github.rest.actions.getWorkflowRun({
|
|
46
|
+
const { data: workflow } = await github.rest.actions.getWorkflowRun({ owner, repo, run_id: runId })
|
|
48
47
|
|
|
49
48
|
let body = '## Release Manager\n\n'
|
|
50
49
|
|
|
51
|
-
const comments = await github.paginate(github.rest.issues.listComments,
|
|
52
|
-
let commentId = comments
|
|
50
|
+
const comments = await github.paginate(github.rest.issues.listComments, { owner, repo, issue_number })
|
|
51
|
+
let commentId = comments.find(c => c.user.login === 'github-actions[bot]' && c.body.startsWith(body))?.id
|
|
53
52
|
|
|
54
53
|
body += `Release workflow run: ${workflow.html_url}\n\n#### Force CI to Update This Release\n\n`
|
|
55
54
|
body += `This PR will be updated and CI will run for every non-\`chore:\` commit that is pushed to \`{{ defaultBranch }}\`. `
|
|
56
55
|
body += `To force CI to update this PR, run this command:\n\n`
|
|
57
|
-
body += `\`\`\`\ngh workflow run release.yml -r ${REF_NAME}\n\`\`\``
|
|
56
|
+
body += `\`\`\`\ngh workflow run release.yml -r ${REF_NAME} -R ${owner}/${repo}\n\`\`\``
|
|
58
57
|
|
|
59
58
|
if (commentId) {
|
|
60
|
-
await github.rest.issues.updateComment({
|
|
59
|
+
await github.rest.issues.updateComment({ owner, repo, comment_id: commentId, body })
|
|
61
60
|
} else {
|
|
62
|
-
const { data: comment } = await github.rest.issues.createComment({
|
|
61
|
+
const { data: comment } = await github.rest.issues.createComment({ owner, repo, issue_number, body })
|
|
63
62
|
commentId = comment?.id
|
|
64
63
|
}
|
|
65
64
|
|
|
@@ -123,9 +122,79 @@ jobs:
|
|
|
123
122
|
|
|
124
123
|
post-release:
|
|
125
124
|
needs: release
|
|
126
|
-
{{> job jobName="Post Release - Release" jobIf="needs.release.outputs.releases" }}
|
|
127
|
-
- name:
|
|
125
|
+
{{> job jobName="Post Release - Release" jobIf="needs.release.outputs.releases" jobSkipSetup=true }}
|
|
126
|
+
- name: Create Release PR Comment
|
|
127
|
+
uses: actions/github-script@v6
|
|
128
128
|
env:
|
|
129
129
|
RELEASES: $\{{ needs.release.outputs.releases }}
|
|
130
|
+
with:
|
|
131
|
+
script: |
|
|
132
|
+
const releases = JSON.parse(process.env.RELEASES)
|
|
133
|
+
const { runId, repo: { owner, repo } } = context
|
|
134
|
+
const issue_number = releases[0].prNumber
|
|
135
|
+
|
|
136
|
+
let body = '## Release Workflow\n\n'
|
|
137
|
+
for (const { pkgName, version, url } of releases) {
|
|
138
|
+
body += `- \`${pkgName}@${version}\` ${url}\n`
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const comments = await github.paginate(github.rest.issues.listComments, { owner, repo, issue_number })
|
|
142
|
+
const releaseComments = comments.filter(c => c.user.login === 'github-actions[bot]' && c.body.includes('Release is at'))
|
|
143
|
+
|
|
144
|
+
for (const comment of releaseComments) {
|
|
145
|
+
await github.rest.issues.deleteComment({ owner, repo, comment_id: comment.id })
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const runUrl = `https://github.com/${owner}/${repo}/actions/runs/${runId}`
|
|
149
|
+
await github.rest.issues.createComment({
|
|
150
|
+
owner,
|
|
151
|
+
repo,
|
|
152
|
+
issue_number,
|
|
153
|
+
body: `${body}- Workflow run: :arrows_counterclockwise: ${runUrl}`,
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
release-integration:
|
|
157
|
+
needs: release
|
|
158
|
+
name: Release Integration
|
|
159
|
+
if: needs.release.outputs.release
|
|
160
|
+
{{> jobReleaseIntegration }}
|
|
161
|
+
|
|
162
|
+
post-release-integration:
|
|
163
|
+
needs: [release, release-integration]
|
|
164
|
+
{{> job jobName="Post Release Integration - Release" jobIf="needs.release.outputs.release && always()" jobSkipSetup=true }}
|
|
165
|
+
- name: Get Needs Result
|
|
166
|
+
id: needs-result
|
|
130
167
|
run: |
|
|
131
|
-
|
|
168
|
+
result=""
|
|
169
|
+
if [[ "$\{{ contains(needs.*.result, 'failure') }}" == "true" ]]; then
|
|
170
|
+
result="x"
|
|
171
|
+
elif [[ "$\{{ contains(needs.*.result, 'cancelled') }}" == "true" ]]; then
|
|
172
|
+
result="heavy_multiplication_x"
|
|
173
|
+
else
|
|
174
|
+
result="white_check_mark"
|
|
175
|
+
fi
|
|
176
|
+
echo "::set-output name=result::$result"
|
|
177
|
+
- name: Update Release PR Comment
|
|
178
|
+
uses: actions/github-script@v6
|
|
179
|
+
env:
|
|
180
|
+
PR_NUMBER: $\{{ fromJSON(needs.release.outputs.release).prNumber }}
|
|
181
|
+
RESULT: $\{{ steps.needs-result.outputs.result }}
|
|
182
|
+
with:
|
|
183
|
+
script: |
|
|
184
|
+
const { PR_NUMBER: issue_number, RESULT } = process.env
|
|
185
|
+
const { repo: { owner, repo } } = context
|
|
186
|
+
|
|
187
|
+
const comments = await github.paginate(github.rest.issues.listComments, { owner, repo, issue_number })
|
|
188
|
+
const updateComment = comments.find(c => c.user.login === 'github-actions[bot]' && c.body.startsWith('## Release Workflow\n\n'))
|
|
189
|
+
|
|
190
|
+
if (updateComment) {
|
|
191
|
+
console.log('Found comment to update:', JSON.stringify(updateComment, null, 2))
|
|
192
|
+
await github.rest.issues.updateComment({
|
|
193
|
+
owner,
|
|
194
|
+
repo,
|
|
195
|
+
comment_id: updateComment.id,
|
|
196
|
+
body: updateComment.body.replace(/Workflow run: :[a-z_]+:/, `Workflow run: :${RESULT}:`),
|
|
197
|
+
})
|
|
198
|
+
} else {
|
|
199
|
+
console.log('No matching comments found:', JSON.stringify(comments, null, 2))
|
|
200
|
+
}
|
|
@@ -52,5 +52,6 @@ module.exports = (gh) => {
|
|
|
52
52
|
pull: (number) => url('pull', number),
|
|
53
53
|
commit: (sha) => url('commit', sha),
|
|
54
54
|
compare: (a, b) => a ? url('compare', `${a.toString()}...${b.toString()}`) : null,
|
|
55
|
+
release: (tag) => url('releases', 'tag', tag.toString()),
|
|
55
56
|
}
|
|
56
57
|
}
|
|
@@ -9,17 +9,21 @@ RP.registerChangelogNotes('default', (o) => new ChangelogNotes(o))
|
|
|
9
9
|
RP.registerVersioningStrategy('default', (o) => new Version(o))
|
|
10
10
|
RP.registerPlugin('node-workspace', (o) => new NodeWs(o.github, o.targetBranch, o.repositoryConfig))
|
|
11
11
|
|
|
12
|
-
const main = async ({ repo:
|
|
12
|
+
const main = async ({ repo: _fullRepo, token, dryRun, branch, force }) => {
|
|
13
13
|
if (!token) {
|
|
14
14
|
throw new Error('Token is required')
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
if (!
|
|
17
|
+
if (!_fullRepo) {
|
|
18
18
|
throw new Error('Repo is required')
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
const
|
|
22
|
-
const github = await RP.GitHub.create({ owner, repo, token })
|
|
21
|
+
const fullRepo = _fullRepo.split('/')
|
|
22
|
+
const github = await RP.GitHub.create({ owner: fullRepo[0], repo: fullRepo[1], token })
|
|
23
|
+
const {
|
|
24
|
+
octokit,
|
|
25
|
+
repository: { owner, repo, defaultBranch },
|
|
26
|
+
} = github
|
|
23
27
|
|
|
24
28
|
// This is mostly for testing and debugging. Use environs with the
|
|
25
29
|
// format `RELEASE_PLEASE_<manfiestOverrideConfigName>` (eg
|
|
@@ -29,7 +33,7 @@ const main = async ({ repo: fullRepo, token, dryRun, branch, force }) => {
|
|
|
29
33
|
.filter(([k, v]) => k.startsWith('RELEASE_PLEASE_') && v != null)
|
|
30
34
|
.map(([k, v]) => [k.replace('RELEASE_PLEASE_', ''), v])
|
|
31
35
|
|
|
32
|
-
const baseBranch = branch ??
|
|
36
|
+
const baseBranch = branch ?? defaultBranch
|
|
33
37
|
|
|
34
38
|
const manifest = await RP.Manifest.fromManifest(
|
|
35
39
|
github,
|
|
@@ -40,7 +44,7 @@ const main = async ({ repo: fullRepo, token, dryRun, branch, force }) => {
|
|
|
40
44
|
)
|
|
41
45
|
|
|
42
46
|
if (force) {
|
|
43
|
-
const { data: releasePrs } = await
|
|
47
|
+
const { data: releasePrs } = await octokit.pulls.list({
|
|
44
48
|
owner,
|
|
45
49
|
repo,
|
|
46
50
|
head: `release-please--branches--${baseBranch}`,
|
|
@@ -59,7 +63,7 @@ const main = async ({ repo: fullRepo, token, dryRun, branch, force }) => {
|
|
|
59
63
|
// to have a different body string so we append a message a message that CI
|
|
60
64
|
// is running. This will force release-please to rebase the PR but it
|
|
61
65
|
// wont update the body again, so we only append to it.
|
|
62
|
-
await
|
|
66
|
+
await octokit.pulls.update({
|
|
63
67
|
owner,
|
|
64
68
|
repo,
|
|
65
69
|
pull_number: releasePr.number,
|
|
@@ -73,29 +77,46 @@ const main = async ({ repo: fullRepo, token, dryRun, branch, force }) => {
|
|
|
73
77
|
// We only ever get a single pull request with our current release-please settings
|
|
74
78
|
const rootPr = pullRequests.filter(Boolean)?.[0]
|
|
75
79
|
if (rootPr?.number) {
|
|
76
|
-
const commits = await
|
|
77
|
-
owner
|
|
78
|
-
repo
|
|
80
|
+
const commits = await octokit.paginate(octokit.rest.pulls.listCommits, {
|
|
81
|
+
owner,
|
|
82
|
+
repo,
|
|
79
83
|
pull_number: rootPr.number,
|
|
80
84
|
})
|
|
81
85
|
rootPr.sha = commits?.[commits.length - 1]?.sha
|
|
82
86
|
}
|
|
83
87
|
|
|
84
88
|
const releases = allReleases.filter(Boolean)
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
89
|
+
let rootRelease = releases[0]
|
|
90
|
+
|
|
91
|
+
for (const release of releases) {
|
|
92
|
+
const prefix = release.path === '.' ? '' : release.path
|
|
93
|
+
|
|
94
|
+
if (!prefix) {
|
|
95
|
+
rootRelease = release
|
|
90
96
|
}
|
|
91
|
-
|
|
92
|
-
|
|
97
|
+
|
|
98
|
+
const [releasePr, releasePkg] = await Promise.all([
|
|
99
|
+
octokit.rest.repos.listPullRequestsAssociatedWithCommit({
|
|
100
|
+
owner,
|
|
101
|
+
repo,
|
|
102
|
+
commit_sha: release.sha,
|
|
103
|
+
}).then(r => r.data[0]),
|
|
104
|
+
octokit.rest.repos.getContent({
|
|
105
|
+
owner,
|
|
106
|
+
repo,
|
|
107
|
+
ref: baseBranch,
|
|
108
|
+
path: `${prefix}/package.json`,
|
|
109
|
+
}).then(r => JSON.parse(Buffer.from(r.data.content, r.data.encoding))),
|
|
110
|
+
])
|
|
111
|
+
|
|
112
|
+
release.prNumber = releasePr.number
|
|
113
|
+
release.pkgName = releasePkg.name
|
|
114
|
+
}
|
|
93
115
|
|
|
94
116
|
return {
|
|
95
117
|
pr: rootPr,
|
|
96
118
|
release: rootRelease,
|
|
97
119
|
releases: releases.length ? releases : null,
|
|
98
|
-
workspaceReleases: workspaceReleases.length ? workspaceReleases : null,
|
|
99
120
|
}
|
|
100
121
|
}
|
|
101
122
|
|
|
@@ -99,7 +99,6 @@ module.exports = class extends NodeWorkspace {
|
|
|
99
99
|
this.releasesByPackage.set(packageName, {
|
|
100
100
|
path,
|
|
101
101
|
component,
|
|
102
|
-
currentTag: releasesByPath[path]?.tag,
|
|
103
102
|
})
|
|
104
103
|
}
|
|
105
104
|
|
|
@@ -139,9 +138,9 @@ module.exports = class extends NodeWorkspace {
|
|
|
139
138
|
// Update notes with a link to each workspaces release notes
|
|
140
139
|
// now that we have all of the releases in a single pull request
|
|
141
140
|
release.notes = release.notes.replace(WORKSPACE_DEP, (_, depName, depVersion) => {
|
|
142
|
-
const {
|
|
141
|
+
const { path, component } = this.releasesByPackage.get(depName)
|
|
143
142
|
|
|
144
|
-
const url = this.gh.
|
|
143
|
+
const url = this.gh.release(new TagName(
|
|
145
144
|
depVersion,
|
|
146
145
|
component,
|
|
147
146
|
this.repositoryConfig[path].tagSeparator,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@npmcli/template-oss",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.11.1",
|
|
4
4
|
"description": "templated files used in npm CLI team oss projects",
|
|
5
5
|
"main": "lib/content/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -76,8 +76,7 @@
|
|
|
76
76
|
"test-ignore": "^(workspace/test-workspace)/"
|
|
77
77
|
},
|
|
78
78
|
"templateOSS": {
|
|
79
|
-
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten."
|
|
80
|
-
"npmSpec": "8"
|
|
79
|
+
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten."
|
|
81
80
|
},
|
|
82
81
|
"engines": {
|
|
83
82
|
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
|