@smoothbricks/cli 0.1.1 → 0.3.0
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 +161 -32
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +110 -10
- package/dist/devenv/index.d.ts +10 -0
- package/dist/devenv/index.d.ts.map +1 -0
- package/dist/devenv/index.js +27 -0
- 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/cli-package.d.ts +4 -0
- package/dist/lib/cli-package.d.ts.map +1 -0
- package/dist/lib/cli-package.js +15 -0
- package/dist/lib/run.d.ts +6 -0
- package/dist/lib/run.d.ts.map +1 -1
- package/dist/lib/run.js +32 -0
- package/dist/lib/workspace.d.ts +25 -1
- package/dist/lib/workspace.d.ts.map +1 -1
- package/dist/lib/workspace.js +79 -17
- package/dist/monorepo/commit-msg.d.ts +8 -1
- package/dist/monorepo/commit-msg.d.ts.map +1 -1
- package/dist/monorepo/commit-msg.js +85 -7
- package/dist/monorepo/index.d.ts +19 -2
- package/dist/monorepo/index.d.ts.map +1 -1
- package/dist/monorepo/index.js +104 -16
- package/dist/monorepo/lockfile.d.ts.map +1 -1
- package/dist/monorepo/lockfile.js +9 -0
- package/dist/monorepo/managed-files.js +1 -1
- package/dist/monorepo/nx-sync.d.ts +2 -1
- package/dist/monorepo/nx-sync.d.ts.map +1 -1
- package/dist/monorepo/nx-sync.js +8 -2
- package/dist/monorepo/package-hygiene.d.ts +6 -2
- package/dist/monorepo/package-hygiene.d.ts.map +1 -1
- package/dist/monorepo/package-hygiene.js +12 -4
- package/dist/monorepo/package-policy.d.ts +13 -4
- package/dist/monorepo/package-policy.d.ts.map +1 -1
- package/dist/monorepo/package-policy.js +208 -113
- package/dist/monorepo/packed-package.d.ts +3 -0
- package/dist/monorepo/packed-package.d.ts.map +1 -1
- package/dist/monorepo/packed-package.js +68 -36
- package/dist/monorepo/packs/index.d.ts +20 -1
- package/dist/monorepo/packs/index.d.ts.map +1 -1
- package/dist/monorepo/packs/index.js +238 -19
- package/dist/monorepo/publish-workflow.d.ts +0 -4
- package/dist/monorepo/publish-workflow.d.ts.map +1 -1
- package/dist/monorepo/publish-workflow.js +7 -15
- package/dist/monorepo/tool-validation.d.ts +22 -0
- package/dist/monorepo/tool-validation.d.ts.map +1 -0
- package/dist/monorepo/tool-validation.js +399 -0
- package/dist/nx/index.d.ts +25 -0
- package/dist/nx/index.d.ts.map +1 -0
- package/dist/nx/index.js +112 -0
- package/dist/release/bootstrap-npm-packages.d.ts +19 -0
- package/dist/release/bootstrap-npm-packages.d.ts.map +1 -0
- package/dist/release/bootstrap-npm-packages.js +58 -0
- package/dist/release/candidates.d.ts +11 -0
- package/dist/release/candidates.d.ts.map +1 -0
- package/dist/release/candidates.js +181 -0
- package/dist/release/core.d.ts +4 -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 +3 -3
- package/dist/release/index.d.ts +32 -1
- package/dist/release/index.d.ts.map +1 -1
- package/dist/release/index.js +488 -64
- package/dist/release/npm-auth.d.ts +0 -1
- package/dist/release/npm-auth.d.ts.map +1 -1
- package/dist/release/npm-auth.js +4 -16
- package/dist/release/orchestration.d.ts +11 -2
- package/dist/release/orchestration.d.ts.map +1 -1
- package/dist/release/orchestration.js +41 -3
- package/dist/release/publish-plan.js +1 -1
- package/managed/raw/git-format-staged.yml +54 -0
- package/managed/raw/tooling/git-hooks/commit-msg.sh +1 -1
- package/managed/templates/github/actions/setup-devenv/action.yml +1 -7
- package/managed/templates/github/workflows/ci.yml +4 -2
- package/package.json +15 -8
- package/src/cli.ts +153 -22
- package/src/devenv/index.test.ts +49 -0
- package/src/devenv/index.ts +38 -0
- package/src/generate/index.ts +92 -0
- package/src/lib/cli-package.ts +18 -0
- package/src/lib/run.ts +44 -0
- package/src/lib/workspace.ts +112 -17
- package/src/monorepo/__tests__/publish-workflow.test.ts +16 -9
- package/src/monorepo/commit-msg.test.ts +45 -0
- package/src/monorepo/commit-msg.ts +107 -7
- package/src/monorepo/index.ts +142 -16
- package/src/monorepo/lockfile.ts +9 -0
- package/src/monorepo/managed-files.ts +1 -1
- package/src/monorepo/nx-sync.ts +9 -2
- package/src/monorepo/package-hygiene.test.ts +34 -0
- package/src/monorepo/package-hygiene.ts +26 -4
- package/src/monorepo/package-policy.test.ts +1130 -0
- package/src/monorepo/package-policy.ts +237 -114
- package/src/monorepo/packed-package.ts +89 -37
- package/src/monorepo/packs/index.test.ts +189 -0
- package/src/monorepo/packs/index.ts +311 -20
- package/src/monorepo/publish-workflow.ts +10 -19
- package/src/monorepo/setup-test-tracing.test.ts +120 -0
- package/src/monorepo/tool-validation.test.ts +261 -0
- package/src/monorepo/tool-validation.ts +462 -0
- package/src/nx/index.test.ts +73 -0
- package/src/nx/index.ts +139 -0
- package/src/release/__tests__/bootstrap-npm-packages.test.ts +127 -0
- package/src/release/__tests__/candidates.test.ts +262 -0
- package/src/release/__tests__/core-properties.test.ts +6 -6
- package/src/release/__tests__/core-scenarios.test.ts +27 -20
- package/src/release/__tests__/core.test.ts +52 -5
- package/src/release/__tests__/fixture-repo.test.ts +90 -31
- package/src/release/__tests__/github-release.test.ts +22 -24
- package/src/release/__tests__/helpers/fixture-repo.ts +1 -0
- package/src/release/__tests__/npm-auth.test.ts +12 -21
- package/src/release/__tests__/orchestration.test.ts +142 -12
- package/src/release/__tests__/publish-plan.test.ts +9 -3
- package/src/release/__tests__/retag-unpublished.test.ts +10 -10
- package/src/release/__tests__/trust-publisher.test.ts +165 -0
- package/src/release/bootstrap-npm-packages.ts +88 -0
- package/src/release/candidates.ts +225 -0
- package/src/release/core.ts +96 -10
- package/src/release/github-release.ts +3 -3
- package/src/release/index.ts +658 -74
- package/src/release/npm-auth.ts +4 -33
- package/src/release/orchestration.ts +60 -5
- package/src/release/publish-plan.ts +1 -1
- 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/managed/raw/.git-format-staged.yml +0 -47
- package/src/nx-version-actions.cts +0 -36
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"npm-auth.d.ts","sourceRoot":"","sources":["../../src/release/npm-auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAEpD,MAAM,WAAW,4BAA4B;IAC3C,
|
|
1
|
+
{"version":3,"file":"npm-auth.d.ts","sourceRoot":"","sources":["../../src/release/npm-auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAEpD,MAAM,WAAW,4BAA4B;IAC3C,YAAY,EAAE,OAAO,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,yBAAyB;IACxC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACzB,aAAa,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAClC,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAChD;AAED,wBAAsB,0BAA0B,CAC9C,GAAG,EAAE,IAAI,CAAC,kBAAkB,EAAE,MAAM,GAAG,SAAS,CAAC,EACjD,KAAK,EAAE,yBAAyB,EAChC,OAAO,EAAE,4BAA4B,GACpC,OAAO,CAAC,IAAI,CAAC,CAgBf;AAED,wBAAgB,4BAA4B,CAC1C,GAAG,EAAE,IAAI,CAAC,kBAAkB,EAAE,MAAM,GAAG,SAAS,CAAC,EACjD,OAAO,EAAE,4BAA4B,GACpC,MAAM,CAwBR;AAED,wBAAgB,6BAA6B,CAC3C,GAAG,EAAE,IAAI,CAAC,kBAAkB,EAAE,MAAM,GAAG,SAAS,CAAC,EACjD,OAAO,EAAE,4BAA4B,GACpC,MAAM,CAmBR"}
|
package/dist/release/npm-auth.js
CHANGED
|
@@ -10,40 +10,28 @@ export async function publishWithAuthDiagnostics(pkg, shell, options) {
|
|
|
10
10
|
}
|
|
11
11
|
shell.error(npmPublishAuthFailureMessage(pkg, options));
|
|
12
12
|
await shell.appendSummary(npmPublishAuthFailureMarkdown(pkg, options));
|
|
13
|
-
throw new Error(`${packageVersion}: npm publish authentication failed. Run smoo release trust-publisher
|
|
13
|
+
throw new Error(`${packageVersion}: npm publish authentication failed. Run smoo release trust-publisher; see the warning banner above for details.`, { cause: error });
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
16
|
export function npmPublishAuthFailureMessage(pkg, options) {
|
|
17
17
|
const packageVersion = `${pkg.name}@${pkg.version}`;
|
|
18
18
|
const lines = [
|
|
19
|
-
`::error title=npm publish authentication failed::${packageVersion} could not be published. This usually means npm trusted publishing is not configured for this package/workflow/repo
|
|
19
|
+
`::error title=npm publish authentication failed::${packageVersion} could not be published. This usually means npm trusted publishing is not configured for this package/workflow/repo.`,
|
|
20
20
|
'',
|
|
21
21
|
`🚨 npm publish authentication failed for ${packageVersion}`,
|
|
22
22
|
'',
|
|
23
23
|
];
|
|
24
|
-
if (options.useBootstrapToken) {
|
|
25
|
-
lines.push('smoo expected a temporary npm automation token because this package does not exist on npm yet.', options.tokenPresent
|
|
26
|
-
? 'NODE_AUTH_TOKEN/NPM_TOKEN is set, but npm still rejected the bootstrap publish. Check that the token is valid, has publish rights for this scope, and is available to this workflow.'
|
|
27
|
-
: 'NODE_AUTH_TOKEN/NPM_TOKEN is not set. Add a temporary NPM_TOKEN repository secret and rerun the Publish workflow.', '', 'After the first successful publish, run:', ' smoo release trust-publisher', '', 'Then remove the temporary bootstrap token path for future releases.');
|
|
28
|
-
return lines.join('\n');
|
|
29
|
-
}
|
|
30
24
|
lines.push('smoo expected npm trusted publishing/OIDC because this package already exists on npm.', options.tokenPresent
|
|
31
25
|
? 'NODE_AUTH_TOKEN/NPM_TOKEN is set but unused: smoo intentionally clears token auth for existing packages; npm must authenticate through trusted publishing instead.'
|
|
32
|
-
: 'NODE_AUTH_TOKEN/NPM_TOKEN is not set, which is expected for trusted publishing; npm did not authenticate the workflow as a trusted publisher.', '', 'Fix:', '1. Run locally: smoo release trust-publisher', '2. Ensure the npm trusted publisher uses:', ` repository: ${trustedPublisherRepository(options)}`, ' workflow: publish.yml', '3. Rerun the Publish workflow.', '', 'For first-ever package publishes,
|
|
26
|
+
: 'NODE_AUTH_TOKEN/NPM_TOKEN is not set, which is expected for trusted publishing; npm did not authenticate the workflow as a trusted publisher.', '', 'Fix:', '1. Run locally: smoo release trust-publisher', '2. Ensure the npm trusted publisher uses:', ` repository: ${trustedPublisherRepository(options)}`, ' workflow: publish.yml', '3. Rerun the Publish workflow.', '', 'For first-ever package publishes, run locally: smoo release trust-publisher --bootstrap.');
|
|
33
27
|
return lines.join('\n');
|
|
34
28
|
}
|
|
35
29
|
export function npmPublishAuthFailureMarkdown(pkg, options) {
|
|
36
30
|
const packageVersion = `${pkg.name}@${pkg.version}`;
|
|
37
31
|
const lines = ['## 🚨 npm Publish Authentication Failed', '', `Package: \`${packageVersion}\``, ''];
|
|
38
|
-
if (options.useBootstrapToken) {
|
|
39
|
-
lines.push('smoo expected a temporary npm automation token because this package does not exist on npm yet.', '', options.tokenPresent
|
|
40
|
-
? '`NODE_AUTH_TOKEN`/`NPM_TOKEN` is set, but npm still rejected the bootstrap publish. Check that the token is valid, has publish rights for this scope, and is available to this workflow.'
|
|
41
|
-
: '`NODE_AUTH_TOKEN`/`NPM_TOKEN` is not set. Add a temporary `NPM_TOKEN` repository secret and rerun the Publish workflow.', '', 'After the first successful publish, run `smoo release trust-publisher`, then remove the temporary bootstrap token path for future releases.');
|
|
42
|
-
return lines.join('\n');
|
|
43
|
-
}
|
|
44
32
|
lines.push('smoo expected npm trusted publishing/OIDC because this package already exists on npm.', '', options.tokenPresent
|
|
45
33
|
? '`NODE_AUTH_TOKEN`/`NPM_TOKEN` is set but unused: smoo intentionally clears token auth for existing packages; npm must authenticate through trusted publishing instead.'
|
|
46
|
-
: '`NODE_AUTH_TOKEN`/`NPM_TOKEN` is not set, which is expected for trusted publishing; npm did not authenticate the workflow as a trusted publisher.', '', 'Fix:', '', '1. Run locally: `smoo release trust-publisher`', `2. Ensure the npm trusted publisher uses repository \`${trustedPublisherRepository(options)}\` and workflow \`publish.yml\``, '3. Rerun the Publish workflow.', '', 'For first-ever package publishes,
|
|
34
|
+
: '`NODE_AUTH_TOKEN`/`NPM_TOKEN` is not set, which is expected for trusted publishing; npm did not authenticate the workflow as a trusted publisher.', '', 'Fix:', '', '1. Run locally: `smoo release trust-publisher`', `2. Ensure the npm trusted publisher uses repository \`${trustedPublisherRepository(options)}\` and workflow \`publish.yml\``, '3. Rerun the Publish workflow.', '', 'For first-ever package publishes, run `smoo release trust-publisher --bootstrap` locally.');
|
|
47
35
|
return lines.join('\n');
|
|
48
36
|
}
|
|
49
37
|
function trustedPublisherRepository(options) {
|
|
@@ -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>;
|
|
@@ -28,9 +35,10 @@ export interface ReleaseRepairShell<Package extends ReleasePackageInfo = Release
|
|
|
28
35
|
}
|
|
29
36
|
export interface ReleaseVersionShell<Package extends ReleasePackageInfo = ReleasePackageInfo> {
|
|
30
37
|
releasePackagesAtHead(): Promise<Package[]>;
|
|
38
|
+
releaseVersionPackages(bump: string): Promise<Package[]>;
|
|
31
39
|
ensureLocalReleaseTags(packages: Package[]): Promise<void>;
|
|
32
40
|
gitHead(): Promise<string>;
|
|
33
|
-
runNxReleaseVersion(bump: string, dryRun: boolean): Promise<
|
|
41
|
+
runNxReleaseVersion(packages: Package[], bump: string, dryRun: boolean): Promise<Package[]>;
|
|
34
42
|
assertCleanGitTree(): Promise<void>;
|
|
35
43
|
}
|
|
36
44
|
export interface ReleaseVersionResult<Package extends ReleasePackageInfo = ReleasePackageInfo> {
|
|
@@ -43,6 +51,7 @@ export declare function runReleaseVersion<Package extends ReleasePackageInfo>(sh
|
|
|
43
51
|
dryRun: boolean;
|
|
44
52
|
}): Promise<ReleaseVersionResult<Package>>;
|
|
45
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[]>;
|
|
46
55
|
export declare function repairPendingTargets<Package extends ReleasePackageInfo>(shell: ReleaseRepairShell<Package>, targets: Array<ReleaseTarget<Package>>, restoreRef: string, dryRun: boolean): Promise<Array<ReleaseSummary<Package>>>;
|
|
47
56
|
export declare function completeRepairTargetAtHead<Package extends ReleasePackageInfo>(shell: ReleaseCompletionShell<Package>, target: ReleaseTarget<Package>, dryRun: boolean): Promise<ReleaseSummary<Package>>;
|
|
48
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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"}
|
|
@@ -7,10 +7,18 @@ export async function runReleaseVersion(shell, options) {
|
|
|
7
7
|
return { mode: 'none', packages: localRelease, status: 'already-release-target' };
|
|
8
8
|
}
|
|
9
9
|
}
|
|
10
|
+
const versionPackages = await shell.releaseVersionPackages(options.bump);
|
|
11
|
+
if (versionPackages.length === 0) {
|
|
12
|
+
if (options.bump !== 'auto') {
|
|
13
|
+
// invariant throw: the CLI resolves forced bumps from the full owned release package set.
|
|
14
|
+
throw new Error(`No release packages were selected for forced --bump ${options.bump}.`);
|
|
15
|
+
}
|
|
16
|
+
return { mode: 'none', packages: [], status: 'no-release-needed' };
|
|
17
|
+
}
|
|
10
18
|
const headBeforeVersioning = await shell.gitHead();
|
|
11
|
-
await shell.runNxReleaseVersion(options.bump, options.dryRun);
|
|
19
|
+
const dryRunPackages = await shell.runNxReleaseVersion(versionPackages, options.bump, options.dryRun);
|
|
12
20
|
if (options.dryRun) {
|
|
13
|
-
return { mode: 'none', packages:
|
|
21
|
+
return { mode: 'none', packages: dryRunPackages, status: 'dry-run' };
|
|
14
22
|
}
|
|
15
23
|
await shell.assertCleanGitTree();
|
|
16
24
|
const headAfterVersioning = await shell.gitHead();
|
|
@@ -43,7 +51,18 @@ export async function completeReleaseAtHead(shell, packages, dryRun, rerunRequir
|
|
|
43
51
|
rerunRequired,
|
|
44
52
|
});
|
|
45
53
|
}
|
|
54
|
+
export async function bumpStableReleaseToNext(shell, packages, dryRun, rerunRequired) {
|
|
55
|
+
const stablePackages = packages.filter((pkg) => !pkg.version.includes('-'));
|
|
56
|
+
if (dryRun || rerunRequired || stablePackages.length === 0) {
|
|
57
|
+
return [];
|
|
58
|
+
}
|
|
59
|
+
await shell.bumpStablePackagesToNext(stablePackages);
|
|
60
|
+
return stablePackages;
|
|
61
|
+
}
|
|
46
62
|
export async function repairPendingTargets(shell, targets, restoreRef, dryRun) {
|
|
63
|
+
if (dryRun) {
|
|
64
|
+
return targets.map((target) => repairDryRunSummary(target));
|
|
65
|
+
}
|
|
47
66
|
const summaries = [];
|
|
48
67
|
try {
|
|
49
68
|
for (const target of targets) {
|
|
@@ -65,6 +84,20 @@ export async function repairPendingTargets(shell, targets, restoreRef, dryRun) {
|
|
|
65
84
|
}
|
|
66
85
|
return summaries;
|
|
67
86
|
}
|
|
87
|
+
function repairDryRunSummary(target) {
|
|
88
|
+
return {
|
|
89
|
+
sha: target.sha,
|
|
90
|
+
dryRun: true,
|
|
91
|
+
packages: target.packages,
|
|
92
|
+
pushed: false,
|
|
93
|
+
published: [],
|
|
94
|
+
alreadyPublished: target.packages.filter((pkg) => !target.npmPackages.includes(pkg)),
|
|
95
|
+
githubReleases: [],
|
|
96
|
+
githubReleaseLinks: [],
|
|
97
|
+
rerunRequired: false,
|
|
98
|
+
noRelease: false,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
68
101
|
export async function completeRepairTargetAtHead(shell, target, dryRun) {
|
|
69
102
|
return completePlannedRelease(shell, {
|
|
70
103
|
sha: await shell.gitHead(),
|
|
@@ -88,8 +121,12 @@ async function completePlannedRelease(shell, input) {
|
|
|
88
121
|
for (const { pkg, distTag } of plan.publishPackages) {
|
|
89
122
|
await shell.publishPackage(pkg, distTag, input.dryRun);
|
|
90
123
|
}
|
|
124
|
+
const githubReleaseLinks = [];
|
|
91
125
|
for (const pkg of plan.githubReleasePackages) {
|
|
92
|
-
await shell.createGithubRelease(pkg, input.dryRun);
|
|
126
|
+
const url = await shell.createGithubRelease(pkg, input.dryRun);
|
|
127
|
+
if (url) {
|
|
128
|
+
githubReleaseLinks.push({ pkg, url });
|
|
129
|
+
}
|
|
93
130
|
}
|
|
94
131
|
return {
|
|
95
132
|
sha: input.sha,
|
|
@@ -99,6 +136,7 @@ async function completePlannedRelease(shell, input) {
|
|
|
99
136
|
published: input.dryRun ? [] : plan.publishPackages.map((action) => action.pkg),
|
|
100
137
|
alreadyPublished: input.packages.filter((pkg) => !input.npmMissingPackages.includes(pkg)),
|
|
101
138
|
githubReleases: input.dryRun ? [] : plan.githubReleasePackages,
|
|
139
|
+
githubReleaseLinks,
|
|
102
140
|
rerunRequired: input.rerunRequired,
|
|
103
141
|
noRelease: false,
|
|
104
142
|
};
|
|
@@ -5,7 +5,7 @@ export function planPublishActions(input) {
|
|
|
5
5
|
const npmPackages = input.releasePackages.filter((pkg) => npmMissingNames.has(pkg.name));
|
|
6
6
|
const githubReleasePackages = input.releasePackages.filter((pkg) => githubMissingNames.has(pkg.name));
|
|
7
7
|
return {
|
|
8
|
-
buildProjects: npmPackages.map((pkg) => pkg.
|
|
8
|
+
buildProjects: npmPackages.map((pkg) => pkg.projectName),
|
|
9
9
|
publishPackages: npmPackages.map((pkg) => ({ pkg, distTag: npmDistTagForVersion(pkg.version) })),
|
|
10
10
|
githubReleasePackages,
|
|
11
11
|
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# git-format-staged configuration for SmoothBricks-style monorepos
|
|
2
|
+
|
|
3
|
+
formatters:
|
|
4
|
+
# ESLint for Astro files (run first as it only handles .astro files)
|
|
5
|
+
eslint:
|
|
6
|
+
command: "eslint-stdout '{}'"
|
|
7
|
+
patterns:
|
|
8
|
+
- '*.astro'
|
|
9
|
+
- '!.*' # Exclude hidden files
|
|
10
|
+
|
|
11
|
+
# Biome for JS/TS/JSX/TSX/JSON/HTML/CSS/GraphQL files
|
|
12
|
+
biome:
|
|
13
|
+
command: "biome check --files-ignore-unknown=true --use-editorconfig=true '--stdin-file-path={}' --fix"
|
|
14
|
+
patterns:
|
|
15
|
+
- '*.js'
|
|
16
|
+
- '*.ts'
|
|
17
|
+
- '*.jsx'
|
|
18
|
+
- '*.tsx'
|
|
19
|
+
- '*.json'
|
|
20
|
+
- '*.jsonc'
|
|
21
|
+
- '*.html'
|
|
22
|
+
- '*.css'
|
|
23
|
+
- '*.graphql'
|
|
24
|
+
|
|
25
|
+
# Prettier for all other files (mainly Markdown)
|
|
26
|
+
prettier:
|
|
27
|
+
command: "prettier --ignore-unknown --stdin-filepath '{}'"
|
|
28
|
+
patterns:
|
|
29
|
+
# Match all files
|
|
30
|
+
- '*'
|
|
31
|
+
# Exclude files handled by Biome
|
|
32
|
+
- '!*.js'
|
|
33
|
+
- '!*.ts'
|
|
34
|
+
- '!*.jsx'
|
|
35
|
+
- '!*.tsx'
|
|
36
|
+
- '!*.json'
|
|
37
|
+
- '!*.jsonc'
|
|
38
|
+
- '!*.html'
|
|
39
|
+
- '!*.css'
|
|
40
|
+
- '!*.graphql'
|
|
41
|
+
# Exclude files handled by Alejandra
|
|
42
|
+
- '!*.nix'
|
|
43
|
+
# Bun lockfiles are generated and should not be rewritten by Prettier
|
|
44
|
+
- '!bun.lock'
|
|
45
|
+
|
|
46
|
+
# Alejandra for Nix files
|
|
47
|
+
alejandra:
|
|
48
|
+
command: 'alejandra'
|
|
49
|
+
patterns:
|
|
50
|
+
- '*.nix'
|
|
51
|
+
|
|
52
|
+
settings:
|
|
53
|
+
update_working_tree: true
|
|
54
|
+
show_commands: true # Verbose output
|
|
@@ -15,13 +15,7 @@ runs:
|
|
|
15
15
|
# This action is intentionally post-checkout only. Repo-local actions do not
|
|
16
16
|
# exist before actions/checkout has populated the working tree.
|
|
17
17
|
- name: ❄️ Install Nix
|
|
18
|
-
uses: DeterminateSystems/nix-
|
|
19
|
-
with:
|
|
20
|
-
extra-conf: |
|
|
21
|
-
keep-outputs = true
|
|
22
|
-
keep-derivations = true
|
|
23
|
-
gc-keep-derivations = true
|
|
24
|
-
gc-keep-outputs = true
|
|
18
|
+
uses: DeterminateSystems/determinate-nix-action@v3
|
|
25
19
|
|
|
26
20
|
- name: 🧊 Cache Nix profiles and store NAR
|
|
27
21
|
id: nix-cache
|
|
@@ -17,7 +17,9 @@ defaults:
|
|
|
17
17
|
|
|
18
18
|
jobs:
|
|
19
19
|
main:
|
|
20
|
+
name: Validate
|
|
20
21
|
runs-on: ubuntu-latest
|
|
22
|
+
timeout-minutes: 45
|
|
21
23
|
env:
|
|
22
24
|
NIX_STORE_NAR: ${{ github.workspace }}/nix-store.nar
|
|
23
25
|
GH_TOKEN: ${{ github.token }}
|
|
@@ -80,8 +82,8 @@ jobs:
|
|
|
80
82
|
|
|
81
83
|
# Step 10
|
|
82
84
|
- name: 📎 Upload trace DBs
|
|
83
|
-
if: ${{
|
|
84
|
-
uses: actions/upload-artifact@
|
|
85
|
+
if: ${{ always() }}
|
|
86
|
+
uses: actions/upload-artifact@v7.0.1
|
|
85
87
|
with:
|
|
86
88
|
name: trace-results-${{ github.run_id }}
|
|
87
89
|
path: packages/*/.trace-results.db
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@smoothbricks/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "SmoothBricks monorepo automation CLI",
|
|
6
6
|
"bin": {
|
|
7
7
|
"smoo": "./bin/smoo"
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
|
-
"test": "
|
|
10
|
+
"test": "nx run cli:test --tui=false --outputStyle=stream"
|
|
11
11
|
},
|
|
12
12
|
"main": "./dist/index.js",
|
|
13
13
|
"module": "./dist/index.js",
|
|
@@ -33,11 +33,6 @@
|
|
|
33
33
|
"development": "./src/monorepo/git-config.ts",
|
|
34
34
|
"import": "./dist/monorepo/git-config.js",
|
|
35
35
|
"default": "./dist/monorepo/git-config.js"
|
|
36
|
-
},
|
|
37
|
-
"./nx-version-actions": {
|
|
38
|
-
"types": "./dist/nx-version-actions.d.cts",
|
|
39
|
-
"require": "./dist/nx-version-actions.cjs",
|
|
40
|
-
"default": "./dist/nx-version-actions.cjs"
|
|
41
36
|
}
|
|
42
37
|
},
|
|
43
38
|
"files": [
|
|
@@ -50,9 +45,11 @@
|
|
|
50
45
|
],
|
|
51
46
|
"dependencies": {
|
|
52
47
|
"@arethetypeswrong/cli": "^0.18.2",
|
|
48
|
+
"@smoothbricks/nx-plugin": "0.2.0",
|
|
53
49
|
"@smoothbricks/validation": "0.1.1",
|
|
54
50
|
"commander": "^14.0.3",
|
|
55
51
|
"publint": "^0.3.18",
|
|
52
|
+
"semver": "^7.7.4",
|
|
56
53
|
"sherif": "^1.11.1",
|
|
57
54
|
"tslib": "^2.8.1"
|
|
58
55
|
},
|
|
@@ -71,11 +68,21 @@
|
|
|
71
68
|
"dependsOn": [
|
|
72
69
|
"build"
|
|
73
70
|
]
|
|
71
|
+
},
|
|
72
|
+
"test": {
|
|
73
|
+
"executor": "@smoothbricks/nx-plugin:bounded-exec",
|
|
74
|
+
"options": {
|
|
75
|
+
"command": "bun test",
|
|
76
|
+
"cwd": "{projectRoot}",
|
|
77
|
+
"timeoutMs": 120000,
|
|
78
|
+
"killAfterMs": 1e4
|
|
79
|
+
}
|
|
74
80
|
}
|
|
75
81
|
},
|
|
76
82
|
"tags": [
|
|
77
83
|
"npm:public"
|
|
78
|
-
]
|
|
84
|
+
],
|
|
85
|
+
"name": "cli"
|
|
79
86
|
},
|
|
80
87
|
"license": "MIT",
|
|
81
88
|
"publishConfig": {
|
package/src/cli.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { Command, CommanderError } from 'commander';
|
|
2
|
+
import { variants } from './generate/index.js';
|
|
3
|
+
import { cliPackageVersion } from './lib/cli-package.js';
|
|
2
4
|
import { findRepoRoot } from './lib/run.js';
|
|
3
5
|
|
|
4
6
|
export async function runCli(argv = process.argv.slice(2)): Promise<void> {
|
|
@@ -20,7 +22,12 @@ export async function runCli(argv = process.argv.slice(2)): Promise<void> {
|
|
|
20
22
|
|
|
21
23
|
function buildProgram(): Command {
|
|
22
24
|
const program = new Command();
|
|
23
|
-
program
|
|
25
|
+
program
|
|
26
|
+
.name('smoo')
|
|
27
|
+
.description('SmoothBricks monorepo tooling')
|
|
28
|
+
.version(cliPackageVersion, '-v, --version', 'print smoo version')
|
|
29
|
+
.exitOverride()
|
|
30
|
+
.showHelpAfterError();
|
|
24
31
|
|
|
25
32
|
const monorepo = program.command('monorepo').description('Manage SmoothBricks-style monorepos');
|
|
26
33
|
monorepo
|
|
@@ -33,12 +40,21 @@ function buildProgram(): Command {
|
|
|
33
40
|
});
|
|
34
41
|
monorepo
|
|
35
42
|
.command('validate')
|
|
43
|
+
.option('--fix', 'apply safe monorepo policy fixes before validation')
|
|
36
44
|
.option('--fail-fast', 'stop after the first failing validation pack')
|
|
37
45
|
.option('--only-if-new-workspace-package', 'skip validation unless a new workspace package manifest is staged')
|
|
38
|
-
.
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
46
|
+
.option('--verbose', 'print validation progress and successful checks')
|
|
47
|
+
.action(
|
|
48
|
+
async (options: {
|
|
49
|
+
fix?: boolean;
|
|
50
|
+
failFast?: boolean;
|
|
51
|
+
onlyIfNewWorkspacePackage?: boolean;
|
|
52
|
+
verbose?: boolean;
|
|
53
|
+
}) => {
|
|
54
|
+
const { validateMonorepo } = await import('./monorepo/index.js');
|
|
55
|
+
await validateMonorepo(await findRepoRoot(), options);
|
|
56
|
+
},
|
|
57
|
+
);
|
|
42
58
|
monorepo.command('update').action(async () => {
|
|
43
59
|
const { updateManagedFiles } = await import('./monorepo/index.js');
|
|
44
60
|
updateManagedFiles(await findRepoRoot());
|
|
@@ -51,10 +67,13 @@ function buildProgram(): Command {
|
|
|
51
67
|
const { diffManagedFiles } = await import('./monorepo/index.js');
|
|
52
68
|
diffManagedFiles(await findRepoRoot());
|
|
53
69
|
});
|
|
54
|
-
monorepo
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
70
|
+
monorepo
|
|
71
|
+
.command('validate-commit-msg <commitMsgFile>')
|
|
72
|
+
.option('--fix', 'format the commit message before validation')
|
|
73
|
+
.action(async (commitMsgFile: string, options: { fix?: boolean }) => {
|
|
74
|
+
const { validateCommitMessageFile } = await import('./monorepo/index.js');
|
|
75
|
+
validateCommitMessageFile(commitMsgFile, options, await findRepoRoot());
|
|
76
|
+
});
|
|
58
77
|
monorepo.command('sync-bun-lockfile-versions').action(async () => {
|
|
59
78
|
const { syncBunLockfileVersions } = await import('./monorepo/index.js');
|
|
60
79
|
syncBunLockfileVersions(await findRepoRoot());
|
|
@@ -62,10 +81,10 @@ function buildProgram(): Command {
|
|
|
62
81
|
monorepo
|
|
63
82
|
.command('list-release-packages')
|
|
64
83
|
.option('--fail-empty', 'fail when no owned release packages are found')
|
|
65
|
-
.option('--github-output <path>', 'append projects=<
|
|
84
|
+
.option('--github-output <path>', 'append projects=<nx-projects> to a GitHub Actions output file')
|
|
66
85
|
.action(async (options: { failEmpty?: boolean; githubOutput?: string }) => {
|
|
67
|
-
const {
|
|
68
|
-
const packages =
|
|
86
|
+
const { listReleaseProjectNamesForNx } = await import('./monorepo/index.js');
|
|
87
|
+
const packages = listReleaseProjectNamesForNx(await findRepoRoot(), options);
|
|
69
88
|
if (!options.githubOutput) {
|
|
70
89
|
console.log(packages);
|
|
71
90
|
}
|
|
@@ -74,6 +93,46 @@ function buildProgram(): Command {
|
|
|
74
93
|
const { validatePublicPackageTags } = await import('./monorepo/index.js');
|
|
75
94
|
validatePublicPackageTags(await findRepoRoot());
|
|
76
95
|
});
|
|
96
|
+
monorepo
|
|
97
|
+
.command('setup-test-tracing')
|
|
98
|
+
.description('Configure LMAO Bun test tracing for workspace packages')
|
|
99
|
+
.option('--all', 'configure every workspace package')
|
|
100
|
+
.option('--projects <projects>', 'comma-separated Nx project names, package names, or package roots')
|
|
101
|
+
.option('--op-context-export <exportName>', 'named op context export imported by test-suite-tracer', 'opContext')
|
|
102
|
+
.option(
|
|
103
|
+
'--tracer-module <module>',
|
|
104
|
+
'module specifier that exports defineTestTracer',
|
|
105
|
+
'@smoothbricks/lmao/testing/bun',
|
|
106
|
+
)
|
|
107
|
+
.option('--dry-run', 'print generator invocations without writing files')
|
|
108
|
+
.action(
|
|
109
|
+
async (options: {
|
|
110
|
+
all?: boolean;
|
|
111
|
+
projects?: string;
|
|
112
|
+
opContextExport?: string;
|
|
113
|
+
tracerModule?: string;
|
|
114
|
+
dryRun?: boolean;
|
|
115
|
+
}) => {
|
|
116
|
+
const { setupTestTracing } = await import('./monorepo/index.js');
|
|
117
|
+
await setupTestTracing(await findRepoRoot(), options);
|
|
118
|
+
},
|
|
119
|
+
);
|
|
120
|
+
// `smoo g` / `smoo generate` — subcommands are driven by the variant
|
|
121
|
+
// registry in src/generate/index.ts. To add a new variant, add an entry
|
|
122
|
+
// there; the CLI wiring below picks it up automatically.
|
|
123
|
+
const g = program.command('g').alias('generate').description('Scaffold workspace packages and components');
|
|
124
|
+
for (const [variantName, variant] of Object.entries(variants)) {
|
|
125
|
+
const sub = g.command(`${variantName} <name>`).description(variant.description);
|
|
126
|
+
for (const opt of variant.options ?? []) {
|
|
127
|
+
sub.option(opt.flag, opt.description);
|
|
128
|
+
}
|
|
129
|
+
sub.option('--dry-run', 'preview changes without writing');
|
|
130
|
+
sub.action(async (name: string, options: Record<string, unknown>) => {
|
|
131
|
+
const { generate } = await import('./generate/index.js');
|
|
132
|
+
await generate(await findRepoRoot(), variantName, name, options);
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
|
|
77
136
|
const release = program.command('release').description('Version, publish, and create GitHub Releases');
|
|
78
137
|
release.command('npm-status').action(async () => {
|
|
79
138
|
const { printReleaseState } = await import('./release/index.js');
|
|
@@ -91,7 +150,7 @@ function buildProgram(): Command {
|
|
|
91
150
|
.command('version')
|
|
92
151
|
.option('--bump <bump>', 'auto, patch, minor, major, or prerelease', 'auto')
|
|
93
152
|
.option('--dry-run [dryRun]', 'run without writing versions or tags')
|
|
94
|
-
.option('--github-output <path>', 'append mode=<mode> and projects=<
|
|
153
|
+
.option('--github-output <path>', 'append mode=<mode> and projects=<nx-projects> to a GitHub Actions output file')
|
|
95
154
|
.action(async (options: { bump: string; dryRun?: string | boolean; githubOutput?: string }) => {
|
|
96
155
|
const { releaseVersion } = await import('./release/index.js');
|
|
97
156
|
await releaseVersion(await findRepoRoot(), {
|
|
@@ -143,19 +202,91 @@ function buildProgram(): Command {
|
|
|
143
202
|
},
|
|
144
203
|
);
|
|
145
204
|
release
|
|
146
|
-
.command('
|
|
147
|
-
.
|
|
148
|
-
.
|
|
149
|
-
.option('--
|
|
150
|
-
.option('--skip-login', 'skip npm browser login before
|
|
151
|
-
.
|
|
152
|
-
|
|
153
|
-
|
|
205
|
+
.command('bootstrap-npm-packages')
|
|
206
|
+
.alias('bootstrap')
|
|
207
|
+
.description('Publish minimal npm placeholder packages so trusted publishing can be configured')
|
|
208
|
+
.option('--dry-run [dryRun]', 'show placeholder publishes without logging in or publishing')
|
|
209
|
+
.option('--skip-login', 'skip npm browser login before publishing placeholders')
|
|
210
|
+
.option('--otp <otp>', 'npm one-time password for placeholder publish operations')
|
|
211
|
+
.option('--package <name...>', 'only bootstrap the selected owned release package names')
|
|
212
|
+
.action(async (options: { dryRun?: string | boolean; skipLogin?: boolean; otp?: string; package?: string[] }) => {
|
|
213
|
+
const { releaseBootstrapNpmPackages } = await import('./release/index.js');
|
|
214
|
+
await releaseBootstrapNpmPackages(await findRepoRoot(), {
|
|
154
215
|
dryRun: booleanOption(options.dryRun),
|
|
155
|
-
otp: options.otp,
|
|
156
216
|
skipLogin: options.skipLogin === true,
|
|
217
|
+
otp: options.otp,
|
|
218
|
+
packages: options.package ?? [],
|
|
157
219
|
});
|
|
158
220
|
});
|
|
221
|
+
release
|
|
222
|
+
.command('trust-publisher')
|
|
223
|
+
.description('Configure npm trusted publishing for owned release packages')
|
|
224
|
+
.option('--dry-run [dryRun]', 'show npm trust changes without saving them')
|
|
225
|
+
.option('--bootstrap', 'publish missing npm placeholder packages before configuring trust')
|
|
226
|
+
.option('--bootstrap-otp <otp>', 'npm one-time password for placeholder publishes during --bootstrap')
|
|
227
|
+
.option('--skip-login', 'skip npm browser login before publishing placeholders during --bootstrap')
|
|
228
|
+
.option('--package <name...>', 'only configure the selected owned release package names')
|
|
229
|
+
.action(
|
|
230
|
+
async (options: {
|
|
231
|
+
dryRun?: string | boolean;
|
|
232
|
+
bootstrap?: boolean;
|
|
233
|
+
bootstrapOtp?: string;
|
|
234
|
+
skipLogin?: boolean;
|
|
235
|
+
package?: string[];
|
|
236
|
+
}) => {
|
|
237
|
+
const { releaseTrustPublisher } = await import('./release/index.js');
|
|
238
|
+
await releaseTrustPublisher(await findRepoRoot(), {
|
|
239
|
+
dryRun: booleanOption(options.dryRun),
|
|
240
|
+
bootstrap: options.bootstrap === true,
|
|
241
|
+
bootstrapOtp: options.bootstrapOtp,
|
|
242
|
+
skipLogin: options.skipLogin === true,
|
|
243
|
+
packages: options.package ?? [],
|
|
244
|
+
});
|
|
245
|
+
},
|
|
246
|
+
);
|
|
247
|
+
|
|
248
|
+
const devenv = program.command('devenv').description('Manage the repository devenv shell');
|
|
249
|
+
devenv.command('update').action(async () => {
|
|
250
|
+
const { updateDevenv } = await import('./devenv/index.js');
|
|
251
|
+
await updateDevenv(await findRepoRoot());
|
|
252
|
+
});
|
|
253
|
+
devenv.command('reload').action(async () => {
|
|
254
|
+
const { reloadDevenv } = await import('./devenv/index.js');
|
|
255
|
+
await reloadDevenv(await findRepoRoot());
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
const nixpkgsOverlay = program.command('nixpkgs-overlay').description('Manage the repository nixpkgs overlay');
|
|
259
|
+
nixpkgsOverlay.command('update').action(async () => {
|
|
260
|
+
const { updateNixpkgsOverlay } = await import('./devenv/index.js');
|
|
261
|
+
await updateNixpkgsOverlay(await findRepoRoot());
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
const nx = program.command('nx').description('Nx workspace helpers');
|
|
265
|
+
nx.command('list-targets')
|
|
266
|
+
.description('List project:target entries for every Nx project')
|
|
267
|
+
.action(async () => {
|
|
268
|
+
const { listTargets } = await import('./nx/index.js');
|
|
269
|
+
await listTargets(await findRepoRoot());
|
|
270
|
+
});
|
|
271
|
+
nx.command('list-projects')
|
|
272
|
+
.description('List Nx projects matching filters')
|
|
273
|
+
.requiredOption('--with-target <target>', 'only include projects defining this target')
|
|
274
|
+
.action(async (options: { withTarget?: string }) => {
|
|
275
|
+
const { listProjects } = await import('./nx/index.js');
|
|
276
|
+
await listProjects(await findRepoRoot(), options);
|
|
277
|
+
});
|
|
278
|
+
nx.command('reset-cache')
|
|
279
|
+
.description('Run nx reset to clear Nx daemon and cache state')
|
|
280
|
+
.action(async () => {
|
|
281
|
+
const { resetCache } = await import('./nx/index.js');
|
|
282
|
+
await resetCache(await findRepoRoot());
|
|
283
|
+
});
|
|
284
|
+
nx.command('clean-cache')
|
|
285
|
+
.description('Remove local Nx cache directories when present')
|
|
286
|
+
.action(async () => {
|
|
287
|
+
const { cleanCache } = await import('./nx/index.js');
|
|
288
|
+
await cleanCache(await findRepoRoot());
|
|
289
|
+
});
|
|
159
290
|
|
|
160
291
|
const githubCi = program.command('github-ci').description('GitHub Actions helpers');
|
|
161
292
|
githubCi.command('cleanup-cache').action(async () => {
|