@smoothbricks/cli 0.2.0 → 0.3.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/README.md +29 -24
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +19 -3
- package/dist/generate/index.d.ts +20 -0
- package/dist/generate/index.d.ts.map +1 -0
- package/dist/generate/index.js +47 -0
- package/dist/lib/run.d.ts +1 -0
- package/dist/lib/run.d.ts.map +1 -1
- package/dist/lib/run.js +19 -0
- package/dist/lib/workspace.d.ts +10 -0
- package/dist/lib/workspace.d.ts.map +1 -1
- package/dist/lib/workspace.js +55 -16
- package/dist/monorepo/lockfile.d.ts.map +1 -1
- package/dist/monorepo/lockfile.js +9 -0
- package/dist/monorepo/package-policy.d.ts +6 -17
- package/dist/monorepo/package-policy.d.ts.map +1 -1
- package/dist/monorepo/package-policy.js +63 -1127
- package/dist/monorepo/publish-workflow.js +2 -3
- package/dist/nx/index.d.ts +1 -0
- package/dist/nx/index.d.ts.map +1 -1
- package/dist/nx/index.js +23 -5
- package/dist/release/candidates.d.ts +1 -0
- package/dist/release/candidates.d.ts.map +1 -1
- package/dist/release/candidates.js +12 -0
- package/dist/release/core.d.ts +3 -1
- package/dist/release/core.d.ts.map +1 -1
- package/dist/release/core.js +76 -9
- package/dist/release/github-release.d.ts +1 -0
- package/dist/release/github-release.d.ts.map +1 -1
- package/dist/release/github-release.js +1 -1
- package/dist/release/index.d.ts +9 -3
- package/dist/release/index.d.ts.map +1 -1
- package/dist/release/index.js +287 -39
- package/dist/release/orchestration.d.ts +10 -2
- package/dist/release/orchestration.d.ts.map +1 -1
- package/dist/release/orchestration.js +33 -3
- package/managed/raw/tooling/git-hooks/commit-msg.sh +7 -1
- package/managed/raw/tooling/git-hooks/pre-commit.sh +7 -1
- package/managed/templates/github/workflows/ci.yml +3 -2
- package/package.json +7 -12
- package/src/cli.ts +21 -4
- package/src/generate/index.ts +92 -0
- package/src/lib/run.ts +25 -0
- package/src/lib/workspace.ts +72 -16
- package/src/monorepo/lockfile.ts +9 -0
- package/src/monorepo/package-policy.test.ts +254 -26
- package/src/monorepo/package-policy.ts +88 -1351
- package/src/monorepo/publish-workflow.ts +2 -3
- package/src/nx/index.test.ts +9 -0
- package/src/nx/index.ts +25 -5
- package/src/release/__tests__/candidates.test.ts +109 -8
- package/src/release/__tests__/core-properties.test.ts +2 -2
- package/src/release/__tests__/core-scenarios.test.ts +12 -15
- package/src/release/__tests__/core.test.ts +50 -3
- package/src/release/__tests__/fixture-repo.test.ts +68 -18
- package/src/release/__tests__/github-release.test.ts +9 -16
- package/src/release/__tests__/orchestration.test.ts +91 -5
- package/src/release/__tests__/retag-unpublished.test.ts +9 -9
- package/src/release/__tests__/trust-publisher.test.ts +65 -33
- package/src/release/candidates.ts +13 -0
- package/src/release/core.ts +95 -10
- package/src/release/github-release.ts +1 -1
- package/src/release/index.ts +366 -49
- package/src/release/orchestration.ts +50 -5
- package/dist/nx-version-actions.cjs +0 -25
- package/dist/nx-version-actions.d.cts +0 -6
- package/dist/nx-version-actions.d.cts.map +0 -1
- package/src/nx-version-actions.cts +0 -36
package/dist/release/index.js
CHANGED
|
@@ -6,15 +6,15 @@ import { Writable } from 'node:stream';
|
|
|
6
6
|
import { $ } from 'bun';
|
|
7
7
|
import { withDevenvEnv } from '../lib/devenv.js';
|
|
8
8
|
import { isRecord, readJsonObject, stringProperty } from '../lib/json.js';
|
|
9
|
-
import { decode, run, runResult, runStatus } from '../lib/run.js';
|
|
9
|
+
import { decode, run, runInteractiveStatus, runResult, runStatus } from '../lib/run.js';
|
|
10
10
|
import { listReleasePackages, readPackageJson, repositoryInfo } from '../lib/workspace.js';
|
|
11
11
|
import { readPackedPackageJson, validatePackedWorkspaceDependencies } from '../monorepo/packed-manifest.js';
|
|
12
12
|
import { bootstrapNpmPackages, NPM_BOOTSTRAP_DIST_TAG, NPM_BOOTSTRAP_VERSION, } from './bootstrap-npm-packages.js';
|
|
13
13
|
import { autoReleaseCandidatePackages } from './candidates.js';
|
|
14
|
-
import { collectOwnedReleaseTagRecords, pendingReleaseTargets, releaseTag, } from './core.js';
|
|
15
|
-
import { createOrUpdateGithubRelease, renderNxProjectChangelogContents } from './github-release.js';
|
|
14
|
+
import { collectOwnedReleaseTagRecords, pendingReleaseTargets, releaseTag, releaseTagAliases, } from './core.js';
|
|
15
|
+
import { createOrUpdateGithubRelease, renderNxProjectChangelogContents, withNxWorkspaceRoot, } from './github-release.js';
|
|
16
16
|
import { publishWithAuthDiagnostics } from './npm-auth.js';
|
|
17
|
-
import { completeReleaseAtHead as completeReleaseAtHeadWithShell, repairPendingTargets, runReleaseVersion, } from './orchestration.js';
|
|
17
|
+
import { bumpStableReleaseToNext, completeReleaseAtHead as completeReleaseAtHeadWithShell, repairPendingTargets, runReleaseVersion, } from './orchestration.js';
|
|
18
18
|
import { retagUnpublished } from './retag-unpublished.js';
|
|
19
19
|
export async function releaseVersion(root, options) {
|
|
20
20
|
const bump = releaseBumpArg(options.bump);
|
|
@@ -33,6 +33,9 @@ export async function releaseVersion(root, options) {
|
|
|
33
33
|
else if (result.status === 'no-release-needed') {
|
|
34
34
|
console.log('Nx did not create a release commit; no release needed.');
|
|
35
35
|
}
|
|
36
|
+
if (result.status === 'dry-run') {
|
|
37
|
+
await writeReleasePreviewSummary(root, packages, result.packages);
|
|
38
|
+
}
|
|
36
39
|
await writeReleaseGithubOutput(options.githubOutput, result.packages, result.mode);
|
|
37
40
|
}
|
|
38
41
|
export async function releasePublish(root, options) {
|
|
@@ -40,15 +43,20 @@ export async function releasePublish(root, options) {
|
|
|
40
43
|
const packages = await releasePackagesAtHead(root, releasePackages(root));
|
|
41
44
|
if (packages.length === 0) {
|
|
42
45
|
if (bump === 'auto') {
|
|
46
|
+
if (options.dryRun === true) {
|
|
47
|
+
console.log('No release tags found at HEAD because dry-run versioning does not create release commits or tags.');
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
43
50
|
console.log('No release tags found at HEAD; no release to publish.');
|
|
44
51
|
const summary = {
|
|
45
52
|
sha: await gitHead(root),
|
|
46
|
-
dryRun:
|
|
53
|
+
dryRun: false,
|
|
47
54
|
packages,
|
|
48
55
|
pushed: false,
|
|
49
56
|
published: [],
|
|
50
57
|
alreadyPublished: [],
|
|
51
58
|
githubReleases: [],
|
|
59
|
+
githubReleaseLinks: [],
|
|
52
60
|
rerunRequired: false,
|
|
53
61
|
noRelease: true,
|
|
54
62
|
};
|
|
@@ -59,6 +67,10 @@ export async function releasePublish(root, options) {
|
|
|
59
67
|
}
|
|
60
68
|
const summary = await completeReleaseAtHeadWithShell(releaseCompletionShell(root), packages, options.dryRun === true, await newerCommitsRemain(root));
|
|
61
69
|
await writeReleaseSummary(summary);
|
|
70
|
+
const bumpedPackages = await bumpStableReleaseToNext(releaseNextShell(root), packages, options.dryRun === true, summary.rerunRequired);
|
|
71
|
+
if (bumpedPackages.length > 0) {
|
|
72
|
+
console.log(`Prepared next prerelease for ${packageSummary(bumpedPackages)}.`);
|
|
73
|
+
}
|
|
62
74
|
}
|
|
63
75
|
export async function releaseRepairPending(root, options) {
|
|
64
76
|
const branch = await releaseBranch(root);
|
|
@@ -72,6 +84,9 @@ export async function releaseRepairPending(root, options) {
|
|
|
72
84
|
console.log(targets.length === 0
|
|
73
85
|
? 'Repair pending releases: no pending durable state repairs found.'
|
|
74
86
|
: `Repair pending releases: ${targets.length} release target${targets.length === 1 ? '' : 's'} need repair.`);
|
|
87
|
+
for (const target of targets) {
|
|
88
|
+
console.log(`Repair pending releases: target ${target.sha.slice(0, 12)} needs ${repairTargetSummary(target)}.`);
|
|
89
|
+
}
|
|
75
90
|
const summaries = await repairPendingTargets(releaseRepairShell(root), targets, restoreRef, options.dryRun === true);
|
|
76
91
|
await writeRepairSummary(summaries, options.dryRun === true);
|
|
77
92
|
}
|
|
@@ -91,7 +106,6 @@ export async function releaseTrustPublisher(root, options) {
|
|
|
91
106
|
promptOtp: (packageName) => promptForNpmOtp(packageName),
|
|
92
107
|
log: (message) => console.log(message),
|
|
93
108
|
}, bootstrapOptions),
|
|
94
|
-
login: () => runLatestNpm(root, ['login', '--auth-type=web']),
|
|
95
109
|
trustPublisher: (pkg, dryRun, env) => {
|
|
96
110
|
const args = ['trust', 'github', pkg.name, '--file', workflow, '--repo', repository, '--yes'];
|
|
97
111
|
if (dryRun) {
|
|
@@ -99,28 +113,27 @@ export async function releaseTrustPublisher(root, options) {
|
|
|
99
113
|
}
|
|
100
114
|
return runLatestNpmTrust(root, args, env);
|
|
101
115
|
},
|
|
102
|
-
|
|
116
|
+
trustedPublishers: (pkg) => listTrustedPublishers(root, pkg),
|
|
103
117
|
log: (message) => console.log(message),
|
|
104
118
|
error: (message) => console.error(message),
|
|
105
119
|
}, options);
|
|
106
120
|
}
|
|
107
121
|
export async function configureTrustedPublishers(shell, options) {
|
|
108
122
|
const packages = shell.listReleasePackages();
|
|
109
|
-
|
|
123
|
+
const selectedPackages = selectedTrustPublisherPackages(packages, options.packages ?? []);
|
|
124
|
+
if (selectedPackages.length === 0) {
|
|
110
125
|
throw new Error('No owned release packages found.');
|
|
111
126
|
}
|
|
112
|
-
let bootstrapLoggedIn = false;
|
|
113
127
|
if (options.bootstrap) {
|
|
114
|
-
|
|
128
|
+
await shell.bootstrapNpmPackages({
|
|
115
129
|
dryRun: options.dryRun === true,
|
|
116
130
|
skipLogin: options.skipLogin === true,
|
|
117
131
|
otp: options.bootstrapOtp,
|
|
118
|
-
packages: [],
|
|
132
|
+
packages: options.packages ?? [],
|
|
119
133
|
});
|
|
120
|
-
bootstrapLoggedIn = bootstrapped.length > 0 && !options.dryRun && !options.skipLogin;
|
|
121
134
|
}
|
|
122
135
|
if (!options.dryRun) {
|
|
123
|
-
const packageStates = await Promise.all(
|
|
136
|
+
const packageStates = await Promise.all(selectedPackages.map(async (pkg) => ((await shell.packageExists(pkg.name)) ? null : pkg.name)));
|
|
124
137
|
const missingPackages = packageStates.filter((name) => name !== null);
|
|
125
138
|
if (missingPackages.length > 0) {
|
|
126
139
|
throw new Error('npm trusted publishing can only be configured after packages exist on the registry. ' +
|
|
@@ -128,16 +141,23 @@ export async function configureTrustedPublishers(shell, options) {
|
|
|
128
141
|
`Missing packages: ${missingPackages.join(', ')}`);
|
|
129
142
|
}
|
|
130
143
|
}
|
|
131
|
-
if (!options.dryRun && !options.skipLogin && !bootstrapLoggedIn) {
|
|
132
|
-
await shell.login();
|
|
133
|
-
}
|
|
134
144
|
const failedPackages = [];
|
|
135
|
-
for (const pkg of
|
|
145
|
+
for (const pkg of selectedPackages) {
|
|
146
|
+
if (!options.dryRun) {
|
|
147
|
+
const trustedPublishers = await shell.trustedPublishers(pkg);
|
|
148
|
+
if (hasMatchingGithubTrustedPublisher(trustedPublishers, shell.repository, shell.workflow)) {
|
|
149
|
+
shell.log(`${pkg.name}: npm trusted publisher is already configured; skipping.`);
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
if (trustedPublishers.length > 0) {
|
|
153
|
+
throw new Error(`${pkg.name}: npm trusted publisher exists but does not match GitHub Actions ${shell.repository}/${shell.workflow}. ` +
|
|
154
|
+
'Use npm trust list to inspect it and npm trust revoke --id <trust-id> before reconfiguring.');
|
|
155
|
+
}
|
|
156
|
+
}
|
|
136
157
|
shell.log(`${pkg.name}: trusting GitHub Actions ${shell.repository}/${shell.workflow}`);
|
|
137
158
|
while (true) {
|
|
138
|
-
const otp = options.dryRun ? undefined : (options.otp ?? (await shell.promptOtp(pkg.name)));
|
|
139
159
|
try {
|
|
140
|
-
const result = await shell.trustPublisher(pkg, options.dryRun === true
|
|
160
|
+
const result = await shell.trustPublisher(pkg, options.dryRun === true);
|
|
141
161
|
if (result === 'already-configured') {
|
|
142
162
|
shell.log(`${pkg.name}: npm trusted publisher is already configured; skipping.`);
|
|
143
163
|
}
|
|
@@ -147,9 +167,9 @@ export async function configureTrustedPublishers(shell, options) {
|
|
|
147
167
|
shell.error(`${pkg.name}: npm trusted publisher setup failed.`);
|
|
148
168
|
shell.error(error instanceof Error ? error.message : String(error));
|
|
149
169
|
if (!options.dryRun) {
|
|
150
|
-
shell.error('npm
|
|
170
|
+
shell.error('npm owns trusted publishing authentication. Complete the npm browser challenge, then retry.');
|
|
151
171
|
}
|
|
152
|
-
if (options.
|
|
172
|
+
if (options.dryRun) {
|
|
153
173
|
failedPackages.push(pkg.name);
|
|
154
174
|
break;
|
|
155
175
|
}
|
|
@@ -159,10 +179,33 @@ export async function configureTrustedPublishers(shell, options) {
|
|
|
159
179
|
}
|
|
160
180
|
if (failedPackages.length > 0) {
|
|
161
181
|
shell.error(`Trusted publishing was not configured for: ${failedPackages.join(', ')}`);
|
|
162
|
-
|
|
163
|
-
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
function selectedTrustPublisherPackages(packages, selections) {
|
|
185
|
+
if (selections.length === 0) {
|
|
186
|
+
return packages;
|
|
187
|
+
}
|
|
188
|
+
const byName = new Map(packages.map((pkg) => [pkg.name, pkg]));
|
|
189
|
+
const selected = [];
|
|
190
|
+
const unknown = [];
|
|
191
|
+
for (const name of selections) {
|
|
192
|
+
const pkg = byName.get(name);
|
|
193
|
+
if (pkg) {
|
|
194
|
+
selected.push(pkg);
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
unknown.push(name);
|
|
164
198
|
}
|
|
165
199
|
}
|
|
200
|
+
if (unknown.length > 0) {
|
|
201
|
+
throw new Error(`Unknown owned release package selection: ${unknown.join(', ')}`);
|
|
202
|
+
}
|
|
203
|
+
return selected;
|
|
204
|
+
}
|
|
205
|
+
function hasMatchingGithubTrustedPublisher(trustedPublishers, repository, workflow) {
|
|
206
|
+
return trustedPublishers.some((trustedPublisher) => trustedPublisher.type === 'github' &&
|
|
207
|
+
trustedPublisher.repository === repository &&
|
|
208
|
+
trustedPublisher.file === workflow);
|
|
166
209
|
}
|
|
167
210
|
export async function releaseBootstrapNpmPackages(root, options) {
|
|
168
211
|
await bootstrapNpmPackages({
|
|
@@ -198,6 +241,7 @@ export async function releaseRetagUnpublished(root, options) {
|
|
|
198
241
|
export async function printReleaseState(root) {
|
|
199
242
|
console.log(JSON.stringify(await getReleaseState(root), null, 2));
|
|
200
243
|
}
|
|
244
|
+
const releasePreviewChangelogs = new Map();
|
|
201
245
|
async function getReleaseState(root) {
|
|
202
246
|
return getReleaseStateForPackages(root, listReleasePackages(root));
|
|
203
247
|
}
|
|
@@ -293,6 +337,7 @@ async function releaseVersionPackages(root, packages, bump) {
|
|
|
293
337
|
}
|
|
294
338
|
return autoReleaseCandidatePackages({
|
|
295
339
|
gitRefExists: (ref) => gitRefExists(root, ref),
|
|
340
|
+
latestStableReleaseRef: (projectName) => latestStableReleaseRef(root, projectName),
|
|
296
341
|
packageChangedFilesSince: (ref, packagePath) => packageChangedFilesSince(root, ref, packagePath),
|
|
297
342
|
packageJsonAtRef: (ref, packagePath) => packageJsonAtRef(root, ref, packagePath),
|
|
298
343
|
currentPackageJson: (packagePath) => currentPackageJson(root, packagePath),
|
|
@@ -301,6 +346,9 @@ async function releaseVersionPackages(root, packages, bump) {
|
|
|
301
346
|
}, packages);
|
|
302
347
|
}
|
|
303
348
|
async function runNxReleaseVersion(root, projects, bump, dryRun) {
|
|
349
|
+
if (dryRun) {
|
|
350
|
+
return runNxReleaseVersionPreview(root, projects, bump);
|
|
351
|
+
}
|
|
304
352
|
// Nx owns local release mutation: package versions, bun.lock updates, the
|
|
305
353
|
// release commit, and annotated tags. smoo owns remote publication after the
|
|
306
354
|
// workflow validates the exact release commit Nx produced.
|
|
@@ -309,10 +357,66 @@ async function runNxReleaseVersion(root, projects, bump, dryRun) {
|
|
|
309
357
|
nxArgs.push(bump);
|
|
310
358
|
}
|
|
311
359
|
nxArgs.push(`--projects=${projects}`, '--git-commit=true', '--git-tag=true', '--git-push=false');
|
|
312
|
-
if (dryRun) {
|
|
313
|
-
nxArgs.push('--dry-run');
|
|
314
|
-
}
|
|
315
360
|
await run('nx', nxArgs, root);
|
|
361
|
+
return [];
|
|
362
|
+
}
|
|
363
|
+
async function runNxReleaseVersionPreview(root, projects, bump) {
|
|
364
|
+
return withNxWorkspaceRoot(root, async () => {
|
|
365
|
+
const { createAPI } = await import('nx/src/command-line/release/version.js');
|
|
366
|
+
const { createAPI: createChangelogAPI } = await import('nx/src/command-line/release/changelog.js');
|
|
367
|
+
const projectNames = projects.split(',').filter(Boolean);
|
|
368
|
+
const result = await createAPI({}, false)({
|
|
369
|
+
specifier: bump === 'auto' ? undefined : bump,
|
|
370
|
+
projects: projectNames,
|
|
371
|
+
gitCommit: true,
|
|
372
|
+
gitTag: true,
|
|
373
|
+
gitPush: false,
|
|
374
|
+
dryRun: true,
|
|
375
|
+
});
|
|
376
|
+
const changelogResult = await createChangelogAPI({
|
|
377
|
+
changelog: {
|
|
378
|
+
workspaceChangelog: false,
|
|
379
|
+
projectChangelogs: { createRelease: false, file: false },
|
|
380
|
+
},
|
|
381
|
+
}, false)({
|
|
382
|
+
projects: projectNames,
|
|
383
|
+
versionData: result.projectsVersionData,
|
|
384
|
+
releaseGraph: result.releaseGraph,
|
|
385
|
+
gitCommit: false,
|
|
386
|
+
gitTag: false,
|
|
387
|
+
gitPush: false,
|
|
388
|
+
stageChanges: false,
|
|
389
|
+
createRelease: false,
|
|
390
|
+
dryRun: true,
|
|
391
|
+
});
|
|
392
|
+
releasePreviewChangelogs.clear();
|
|
393
|
+
for (const [projectName, changelog] of Object.entries(changelogResult.projectChangelogs ?? {})) {
|
|
394
|
+
releasePreviewChangelogs.set(projectName, changelog.contents);
|
|
395
|
+
}
|
|
396
|
+
const packagesByProject = new Map(releasePackages(root).map((pkg) => [pkg.projectName, pkg]));
|
|
397
|
+
return Object.entries(result.projectsVersionData)
|
|
398
|
+
.map(([projectName, data]) => {
|
|
399
|
+
const pkg = packagesByProject.get(projectName);
|
|
400
|
+
if (!pkg || !data.newVersion) {
|
|
401
|
+
return null;
|
|
402
|
+
}
|
|
403
|
+
return { ...pkg, version: data.newVersion };
|
|
404
|
+
})
|
|
405
|
+
.filter((pkg) => pkg !== null);
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
async function runNxNextPrereleaseVersion(root, projects) {
|
|
409
|
+
await run('nx', [
|
|
410
|
+
'release',
|
|
411
|
+
'version',
|
|
412
|
+
'prerelease',
|
|
413
|
+
`--projects=${projects}`,
|
|
414
|
+
'--preid=next',
|
|
415
|
+
'--git-commit=true',
|
|
416
|
+
'--git-tag=false',
|
|
417
|
+
'--git-push=false',
|
|
418
|
+
'--git-commit-message=chore(release): prepare next prerelease',
|
|
419
|
+
], root);
|
|
316
420
|
}
|
|
317
421
|
async function releasePackagesAtHead(root, packages) {
|
|
318
422
|
return releasePackagesAtRef(root, packages, 'HEAD');
|
|
@@ -381,7 +485,7 @@ async function gitTagsAtRef(root, ref) {
|
|
|
381
485
|
.filter(Boolean);
|
|
382
486
|
}
|
|
383
487
|
async function previousReleaseTag(root, pkg, currentTag) {
|
|
384
|
-
const result = await $ `git tag --list ${`${pkg.
|
|
488
|
+
const result = await $ `git tag --list ${`${pkg.projectName}@*`} --sort=-v:refname --merged ${currentTag}`
|
|
385
489
|
.cwd(root)
|
|
386
490
|
.quiet()
|
|
387
491
|
.nothrow();
|
|
@@ -429,6 +533,11 @@ async function pushReleaseRefs(root, packages) {
|
|
|
429
533
|
await run('git', ['push', '--atomic', remote, ...refspecs], root);
|
|
430
534
|
return true;
|
|
431
535
|
}
|
|
536
|
+
async function pushCurrentBranch(root) {
|
|
537
|
+
const branch = await releaseBranch(root);
|
|
538
|
+
const remote = await releaseRemote(root, branch);
|
|
539
|
+
await run('git', ['push', remote, `HEAD:refs/heads/${branch}`], root);
|
|
540
|
+
}
|
|
432
541
|
function releaseCompletionShell(root) {
|
|
433
542
|
return {
|
|
434
543
|
gitHead: () => gitHead(root),
|
|
@@ -446,6 +555,14 @@ function releaseCompletionShell(root) {
|
|
|
446
555
|
createGithubRelease: (pkg, dryRun) => createGithubRelease(root, pkg, dryRun),
|
|
447
556
|
};
|
|
448
557
|
}
|
|
558
|
+
function releaseNextShell(root) {
|
|
559
|
+
return {
|
|
560
|
+
bumpStablePackagesToNext: async (packages) => {
|
|
561
|
+
await runNxNextPrereleaseVersion(root, releasePackageProjects(packages));
|
|
562
|
+
await pushCurrentBranch(root);
|
|
563
|
+
},
|
|
564
|
+
};
|
|
565
|
+
}
|
|
449
566
|
function releaseRepairShell(root) {
|
|
450
567
|
return {
|
|
451
568
|
...releaseCompletionShell(root),
|
|
@@ -490,15 +607,23 @@ async function listOwnedReleaseTagRecords(root, ref) {
|
|
|
490
607
|
}
|
|
491
608
|
async function durableReleaseTagState(root, pkg, tag) {
|
|
492
609
|
const packageVersion = `${pkg.name}@${pkg.version}`;
|
|
610
|
+
const githubReleaseTags = releaseTagAliases({ ...pkg, projectName: projectNameFromReleaseTag(tag) });
|
|
493
611
|
const start = Date.now();
|
|
494
|
-
console.log(`${packageVersion}: checking durable state (npm + GitHub Release ${
|
|
612
|
+
console.log(`${packageVersion}: checking durable state (npm + GitHub Release ${githubReleaseTags.join(' or ')}).`);
|
|
495
613
|
const [npmPublished, githubReleasePresent] = await Promise.all([
|
|
496
614
|
npmVersionExists(root, pkg.name, pkg.version),
|
|
497
|
-
|
|
615
|
+
anyGithubReleaseExists(root, githubReleaseTags),
|
|
498
616
|
]);
|
|
499
617
|
console.log(`${packageVersion}: durable state npm=${yesNo(npmPublished)} github=${yesNo(githubReleasePresent)} (${Date.now() - start}ms).`);
|
|
500
618
|
return { npmPublished, githubReleaseExists: githubReleasePresent };
|
|
501
619
|
}
|
|
620
|
+
function projectNameFromReleaseTag(tag) {
|
|
621
|
+
const versionSeparator = tag.lastIndexOf('@');
|
|
622
|
+
if (versionSeparator <= 0) {
|
|
623
|
+
return tag;
|
|
624
|
+
}
|
|
625
|
+
return tag.slice(0, versionSeparator);
|
|
626
|
+
}
|
|
502
627
|
async function gitReleaseTagsByCreatorDate(root) {
|
|
503
628
|
const result = await $ `git for-each-ref --sort=-creatordate --format=${'%(refname:short)%09%(creatordate:unix)%09%(*objectname)%09%(objectname)'} refs/tags`
|
|
504
629
|
.cwd(root)
|
|
@@ -537,7 +662,7 @@ async function createGithubRelease(root, pkg, dryRun) {
|
|
|
537
662
|
const previousTag = await previousReleaseTag(root, pkg, currentTag);
|
|
538
663
|
if (dryRun) {
|
|
539
664
|
await renderNxProjectChangelogContents({ root, pkg, previousTag, dryRun });
|
|
540
|
-
return;
|
|
665
|
+
return null;
|
|
541
666
|
}
|
|
542
667
|
const contents = await renderNxProjectChangelogContents({ root, pkg, previousTag, dryRun });
|
|
543
668
|
await createOrUpdateGithubRelease(pkg, contents, {
|
|
@@ -545,6 +670,7 @@ async function createGithubRelease(root, pkg, dryRun) {
|
|
|
545
670
|
runGhRelease: (args) => run('gh', args, root),
|
|
546
671
|
log: (message) => console.log(message),
|
|
547
672
|
});
|
|
673
|
+
return githubReleaseUrl(root, currentTag);
|
|
548
674
|
}
|
|
549
675
|
function envPresence(name) {
|
|
550
676
|
return `${name}=${process.env[name] ? 'present' : 'missing'}`;
|
|
@@ -579,7 +705,7 @@ async function writeReleaseSummary(summary) {
|
|
|
579
705
|
lines.push(`- Git refs pushed: ${summary.pushed ? 'yes' : 'already current'}`);
|
|
580
706
|
lines.push(`- npm published: ${packageSummary(summary.published)}`);
|
|
581
707
|
lines.push(`- npm already published: ${packageSummary(summary.alreadyPublished)}`);
|
|
582
|
-
lines.push(`- GitHub Releases created/updated: ${
|
|
708
|
+
lines.push(`- GitHub Releases created/updated: ${githubReleaseSummary(summary)}`);
|
|
583
709
|
}
|
|
584
710
|
if (summary.rerunRequired) {
|
|
585
711
|
const message = 'A previous incomplete release was repaired; newer commits remain. Run Publish again.';
|
|
@@ -593,6 +719,32 @@ async function writeReleaseSummary(summary) {
|
|
|
593
719
|
await appendFile(summaryPath, `${text}\n`);
|
|
594
720
|
}
|
|
595
721
|
}
|
|
722
|
+
async function writeReleasePreviewSummary(root, currentPackages, previewPackages) {
|
|
723
|
+
const lines = ['## Release Preview', '', `- Commit: \`${(await gitHead(root)).slice(0, 12)}\``, '- Mode: dry run'];
|
|
724
|
+
if (previewPackages.length === 0) {
|
|
725
|
+
lines.push('- Result: no release needed');
|
|
726
|
+
}
|
|
727
|
+
else {
|
|
728
|
+
lines.push('- Packages:');
|
|
729
|
+
const currentByName = new Map(currentPackages.map((pkg) => [pkg.name, pkg]));
|
|
730
|
+
for (const pkg of previewPackages) {
|
|
731
|
+
lines.push(` - \`${pkg.name}\`: \`${currentByName.get(pkg.name)?.version ?? 'unknown'}\` -> \`${pkg.version}\``);
|
|
732
|
+
}
|
|
733
|
+
for (const pkg of previewPackages) {
|
|
734
|
+
const contents = releasePreviewChangelogs.get(pkg.projectName);
|
|
735
|
+
if (!contents) {
|
|
736
|
+
throw new Error(`Nx did not generate a project changelog for ${pkg.projectName}.`);
|
|
737
|
+
}
|
|
738
|
+
lines.push('', `### ${pkg.name} ${pkg.version}`, '', contents.trim());
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
const text = `${lines.join('\n')}\n`;
|
|
742
|
+
console.log(text.trimEnd());
|
|
743
|
+
const summaryPath = process.env.GITHUB_STEP_SUMMARY;
|
|
744
|
+
if (summaryPath) {
|
|
745
|
+
await appendFile(summaryPath, `${text}\n`);
|
|
746
|
+
}
|
|
747
|
+
}
|
|
596
748
|
async function writeRepairSummary(summaries, dryRun) {
|
|
597
749
|
const lines = ['## Pending Release Repair', '', `- Mode: ${dryRun ? 'dry run' : 'release'}`];
|
|
598
750
|
if (summaries.length === 0) {
|
|
@@ -600,7 +752,7 @@ async function writeRepairSummary(summaries, dryRun) {
|
|
|
600
752
|
}
|
|
601
753
|
else {
|
|
602
754
|
for (const summary of summaries) {
|
|
603
|
-
lines.push(`- Repaired \`${summary.sha.slice(0, 12)}\`: ${packageSummary(summary.packages)}`);
|
|
755
|
+
lines.push(`- ${dryRun ? 'Would repair' : 'Repaired'} \`${summary.sha.slice(0, 12)}\`: ${packageSummary(summary.packages)}`);
|
|
604
756
|
}
|
|
605
757
|
}
|
|
606
758
|
const text = `${lines.join('\n')}\n`;
|
|
@@ -616,6 +768,27 @@ function packageSummary(packages) {
|
|
|
616
768
|
}
|
|
617
769
|
return packages.map((pkg) => `${pkg.name}@${pkg.version}`).join(', ');
|
|
618
770
|
}
|
|
771
|
+
function githubReleaseSummary(summary) {
|
|
772
|
+
if (summary.githubReleaseLinks.length > 0) {
|
|
773
|
+
return summary.githubReleaseLinks.map(({ pkg, url }) => `[${pkg.name}@${pkg.version}](${url})`).join(', ');
|
|
774
|
+
}
|
|
775
|
+
return packageSummary(summary.githubReleases);
|
|
776
|
+
}
|
|
777
|
+
function repairTargetSummary(target) {
|
|
778
|
+
return target.packages
|
|
779
|
+
.map((pkg) => `${pkg.name}@${pkg.version} (${repairReasons(target, pkg).join(' + ')})`)
|
|
780
|
+
.join(', ');
|
|
781
|
+
}
|
|
782
|
+
function repairReasons(target, pkg) {
|
|
783
|
+
const reasons = [];
|
|
784
|
+
if (target.npmPackages.includes(pkg)) {
|
|
785
|
+
reasons.push('npm missing');
|
|
786
|
+
}
|
|
787
|
+
if (target.githubPackages.includes(pkg)) {
|
|
788
|
+
reasons.push('GitHub Release missing');
|
|
789
|
+
}
|
|
790
|
+
return reasons;
|
|
791
|
+
}
|
|
619
792
|
async function fetchReleaseRefs(root, remote, branch) {
|
|
620
793
|
await run('git', ['fetch', '--tags', remote, branch], root);
|
|
621
794
|
}
|
|
@@ -623,6 +796,27 @@ async function gitRefExists(root, ref) {
|
|
|
623
796
|
const result = await $ `git rev-parse --verify ${ref}`.cwd(root).quiet().nothrow();
|
|
624
797
|
return result.exitCode === 0;
|
|
625
798
|
}
|
|
799
|
+
async function latestStableReleaseRef(root, projectName) {
|
|
800
|
+
// List tags matching <projectName>@* sorted newest-first by version, then
|
|
801
|
+
// return the first non-prerelease tag as a full ref.
|
|
802
|
+
const pattern = `${projectName}@*`;
|
|
803
|
+
const result = await $ `git tag --list ${pattern} --sort=-v:refname`.cwd(root).quiet().nothrow();
|
|
804
|
+
if (result.exitCode !== 0) {
|
|
805
|
+
return null;
|
|
806
|
+
}
|
|
807
|
+
const tags = decode(result.stdout)
|
|
808
|
+
.split('\n')
|
|
809
|
+
.map((t) => t.trim())
|
|
810
|
+
.filter(Boolean);
|
|
811
|
+
const prefix = `${projectName}@`;
|
|
812
|
+
for (const tagName of tags) {
|
|
813
|
+
const version = tagName.slice(prefix.length);
|
|
814
|
+
if (version && !version.includes('-')) {
|
|
815
|
+
return `refs/tags/${tagName}`;
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
return null;
|
|
819
|
+
}
|
|
626
820
|
async function packageChangedFilesSince(root, ref, packagePath) {
|
|
627
821
|
const result = await $ `git diff --name-only ${`${ref}..HEAD`} -- ${packagePath}`.cwd(root).quiet().nothrow();
|
|
628
822
|
if (result.exitCode !== 0) {
|
|
@@ -806,6 +1000,17 @@ async function pushRetaggedReleaseTags(root, remote, updates) {
|
|
|
806
1000
|
async function githubReleaseExists(root, tag) {
|
|
807
1001
|
return (await runStatus('gh', ['release', 'view', tag, '--json', 'tagName'], root, true)) === 0;
|
|
808
1002
|
}
|
|
1003
|
+
function githubReleaseUrl(root, tag) {
|
|
1004
|
+
return `https://github.com/${githubRepositoryFromRootPackage(root)}/releases/tag/${encodeURIComponent(tag)}`;
|
|
1005
|
+
}
|
|
1006
|
+
async function anyGithubReleaseExists(root, tags) {
|
|
1007
|
+
for (const tag of tags) {
|
|
1008
|
+
if (await githubReleaseExists(root, tag)) {
|
|
1009
|
+
return true;
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
1012
|
+
return false;
|
|
1013
|
+
}
|
|
809
1014
|
async function assertRemoteTagExists(root, tag) {
|
|
810
1015
|
const branch = await releaseBranch(root);
|
|
811
1016
|
const remote = await releaseRemote(root, branch);
|
|
@@ -917,15 +1122,58 @@ async function runLatestNpm(root, npmArgs, env) {
|
|
|
917
1122
|
await run('nix', ['shell', 'nixpkgs#nodejs_latest', '-c', 'npm', ...npmArgs], root, env);
|
|
918
1123
|
}
|
|
919
1124
|
async function runLatestNpmTrust(root, npmArgs, env) {
|
|
920
|
-
const
|
|
921
|
-
if (
|
|
1125
|
+
const status = await runInteractiveStatus('nix', ['shell', 'nixpkgs#nodejs_latest', '-c', 'npm', ...npmArgs], root, env);
|
|
1126
|
+
if (status === 0) {
|
|
922
1127
|
return 'configured';
|
|
923
1128
|
}
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
1129
|
+
throw new Error(`nix shell nixpkgs#nodejs_latest -c npm ${npmArgs.join(' ')} failed with exit code ${status}`);
|
|
1130
|
+
}
|
|
1131
|
+
async function listTrustedPublishers(root, pkg) {
|
|
1132
|
+
const args = ['trust', 'list', pkg.name, '--json'];
|
|
1133
|
+
let result = await runResult('nix', ['shell', 'nixpkgs#nodejs_latest', '-c', 'npm', ...args], root);
|
|
1134
|
+
if (result.exitCode !== 0 && /\bEOTP\b/.test(`${result.stdout}\n${result.stderr}`)) {
|
|
1135
|
+
const status = await runInteractiveStatus('nix', ['shell', 'nixpkgs#nodejs_latest', '-c', 'npm', ...args], root);
|
|
1136
|
+
if (status !== 0) {
|
|
1137
|
+
throw new Error(`nix shell nixpkgs#nodejs_latest -c npm ${args.join(' ')} failed with exit code ${status}`);
|
|
1138
|
+
}
|
|
1139
|
+
result = await runResult('nix', ['shell', 'nixpkgs#nodejs_latest', '-c', 'npm', ...args], root);
|
|
1140
|
+
}
|
|
1141
|
+
if (result.exitCode !== 0) {
|
|
1142
|
+
throw new Error(`nix shell nixpkgs#nodejs_latest -c npm ${args.join(' ')} failed with exit code ${result.exitCode}`);
|
|
1143
|
+
}
|
|
1144
|
+
return parseTrustedPublishers(result.stdout, pkg.name);
|
|
1145
|
+
}
|
|
1146
|
+
export function parseTrustedPublishers(stdout, packageName) {
|
|
1147
|
+
if (stdout.trim().length === 0) {
|
|
1148
|
+
return [];
|
|
1149
|
+
}
|
|
1150
|
+
const parsed = JSON.parse(stdout);
|
|
1151
|
+
if (parsed === null) {
|
|
1152
|
+
return [];
|
|
1153
|
+
}
|
|
1154
|
+
if (Array.isArray(parsed)) {
|
|
1155
|
+
return parsed.map((value) => parseTrustedPublisher(value, packageName));
|
|
1156
|
+
}
|
|
1157
|
+
if (isRecord(parsed)) {
|
|
1158
|
+
return [parseTrustedPublisher(parsed, packageName)];
|
|
927
1159
|
}
|
|
928
|
-
throw new Error(
|
|
1160
|
+
throw new Error(`${packageName}: npm trust list returned invalid JSON.`);
|
|
1161
|
+
}
|
|
1162
|
+
function parseTrustedPublisher(value, packageName) {
|
|
1163
|
+
if (!isRecord(value)) {
|
|
1164
|
+
throw new Error(`${packageName}: npm trust list returned invalid trusted publisher entry.`);
|
|
1165
|
+
}
|
|
1166
|
+
const id = stringProperty(value, 'id');
|
|
1167
|
+
const type = stringProperty(value, 'type');
|
|
1168
|
+
if (!id || !type) {
|
|
1169
|
+
throw new Error(`${packageName}: npm trust list returned a trusted publisher without id or type.`);
|
|
1170
|
+
}
|
|
1171
|
+
return {
|
|
1172
|
+
id,
|
|
1173
|
+
type,
|
|
1174
|
+
file: stringProperty(value, 'file') ?? undefined,
|
|
1175
|
+
repository: stringProperty(value, 'repository') ?? undefined,
|
|
1176
|
+
};
|
|
929
1177
|
}
|
|
930
1178
|
async function runLatestNpmPublish(root, npmArgs) {
|
|
931
1179
|
await runLatestNpm(root, npmArgs, { NODE_AUTH_TOKEN: '', NPM_TOKEN: '' });
|
|
@@ -935,7 +1183,7 @@ function missingNpmPackagePublishGuidance(pkg) {
|
|
|
935
1183
|
}
|
|
936
1184
|
async function promptForNpmOtp(packageName) {
|
|
937
1185
|
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
938
|
-
throw new Error(`npm
|
|
1186
|
+
throw new Error(`npm requires a one-time password for ${packageName}. Pass --otp <code> in non-interactive shells.`);
|
|
939
1187
|
}
|
|
940
1188
|
const mutedOutput = new Writable({
|
|
941
1189
|
write(_chunk, _encoding, callback) {
|
|
@@ -8,6 +8,10 @@ export interface ReleaseSummary<Package extends ReleasePackageInfo = ReleasePack
|
|
|
8
8
|
published: Package[];
|
|
9
9
|
alreadyPublished: Package[];
|
|
10
10
|
githubReleases: Package[];
|
|
11
|
+
githubReleaseLinks: Array<{
|
|
12
|
+
pkg: Package;
|
|
13
|
+
url: string;
|
|
14
|
+
}>;
|
|
11
15
|
rerunRequired: boolean;
|
|
12
16
|
noRelease: boolean;
|
|
13
17
|
}
|
|
@@ -18,7 +22,10 @@ export interface ReleaseCompletionShell<Package extends ReleasePackageInfo = Rel
|
|
|
18
22
|
buildReleaseCandidate(packages: Package[]): Promise<void>;
|
|
19
23
|
publishPackage(pkg: Package, distTag: string, dryRun: boolean): Promise<void>;
|
|
20
24
|
listGithubMissingPackages(packages: Package[]): Promise<Package[]>;
|
|
21
|
-
createGithubRelease(pkg: Package, dryRun: boolean): Promise<
|
|
25
|
+
createGithubRelease(pkg: Package, dryRun: boolean): Promise<string | null>;
|
|
26
|
+
}
|
|
27
|
+
export interface ReleaseNextShell<Package extends ReleasePackageInfo = ReleasePackageInfo> {
|
|
28
|
+
bumpStablePackagesToNext(packages: Package[]): Promise<void>;
|
|
22
29
|
}
|
|
23
30
|
export interface ReleaseRepairShell<Package extends ReleasePackageInfo = ReleasePackageInfo> extends ReleaseCompletionShell<Package> {
|
|
24
31
|
checkout(ref: string): Promise<void>;
|
|
@@ -31,7 +38,7 @@ export interface ReleaseVersionShell<Package extends ReleasePackageInfo = Releas
|
|
|
31
38
|
releaseVersionPackages(bump: string): Promise<Package[]>;
|
|
32
39
|
ensureLocalReleaseTags(packages: Package[]): Promise<void>;
|
|
33
40
|
gitHead(): Promise<string>;
|
|
34
|
-
runNxReleaseVersion(packages: Package[], bump: string, dryRun: boolean): Promise<
|
|
41
|
+
runNxReleaseVersion(packages: Package[], bump: string, dryRun: boolean): Promise<Package[]>;
|
|
35
42
|
assertCleanGitTree(): Promise<void>;
|
|
36
43
|
}
|
|
37
44
|
export interface ReleaseVersionResult<Package extends ReleasePackageInfo = ReleasePackageInfo> {
|
|
@@ -44,6 +51,7 @@ export declare function runReleaseVersion<Package extends ReleasePackageInfo>(sh
|
|
|
44
51
|
dryRun: boolean;
|
|
45
52
|
}): Promise<ReleaseVersionResult<Package>>;
|
|
46
53
|
export declare function completeReleaseAtHead<Package extends ReleasePackageInfo>(shell: ReleaseCompletionShell<Package>, packages: Package[], dryRun: boolean, rerunRequired: boolean): Promise<ReleaseSummary<Package>>;
|
|
54
|
+
export declare function bumpStableReleaseToNext<Package extends ReleasePackageInfo>(shell: ReleaseNextShell<Package>, packages: Package[], dryRun: boolean, rerunRequired: boolean): Promise<Package[]>;
|
|
47
55
|
export declare function repairPendingTargets<Package extends ReleasePackageInfo>(shell: ReleaseRepairShell<Package>, targets: Array<ReleaseTarget<Package>>, restoreRef: string, dryRun: boolean): Promise<Array<ReleaseSummary<Package>>>;
|
|
48
56
|
export declare function completeRepairTargetAtHead<Package extends ReleasePackageInfo>(shell: ReleaseCompletionShell<Package>, target: ReleaseTarget<Package>, dryRun: boolean): Promise<ReleaseSummary<Package>>;
|
|
49
57
|
//# sourceMappingURL=orchestration.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"orchestration.d.ts","sourceRoot":"","sources":["../../src/release/orchestration.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAGnE,MAAM,MAAM,kBAAkB,GAAG,KAAK,GAAG,MAAM,CAAC;AAEhD,MAAM,WAAW,cAAc,CAAC,OAAO,SAAS,kBAAkB,GAAG,kBAAkB;IACrF,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,MAAM,EAAE,OAAO,CAAC;IAChB,SAAS,EAAE,OAAO,EAAE,CAAC;IACrB,gBAAgB,EAAE,OAAO,EAAE,CAAC;IAC5B,cAAc,EAAE,OAAO,EAAE,CAAC;IAC1B,aAAa,EAAE,OAAO,CAAC;IACvB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,sBAAsB,CAAC,OAAO,SAAS,kBAAkB,GAAG,kBAAkB;IAC7F,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAC3B,eAAe,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACvD,sBAAsB,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IAChE,qBAAqB,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1D,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9E,yBAAyB,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IACnE,mBAAmB,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"orchestration.d.ts","sourceRoot":"","sources":["../../src/release/orchestration.ts"],"names":[],"mappings":"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"}
|