@smoothbricks/cli 0.10.2 → 0.10.3

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.
Files changed (62) hide show
  1. package/README.md +25 -13
  2. package/dist/cli.js +24 -0
  3. package/dist/github-ci/index.d.ts +17 -2
  4. package/dist/github-ci/index.d.ts.map +1 -1
  5. package/dist/github-ci/index.js +141 -11
  6. package/dist/github-ci/outputs.d.ts +22 -0
  7. package/dist/github-ci/outputs.d.ts.map +1 -0
  8. package/dist/github-ci/outputs.js +649 -0
  9. package/dist/monorepo/ci-workflow.js +1 -1
  10. package/dist/monorepo/managed-files.d.ts +1 -0
  11. package/dist/monorepo/managed-files.d.ts.map +1 -1
  12. package/dist/monorepo/managed-files.js +38 -0
  13. package/dist/monorepo/package-policy.d.ts.map +1 -1
  14. package/dist/monorepo/package-policy.js +26 -0
  15. package/dist/monorepo/packs/index.d.ts +3 -0
  16. package/dist/monorepo/packs/index.d.ts.map +1 -1
  17. package/dist/monorepo/packs/index.js +5 -2
  18. package/dist/monorepo/publish-workflow.d.ts +1 -0
  19. package/dist/monorepo/publish-workflow.d.ts.map +1 -1
  20. package/dist/monorepo/publish-workflow.js +239 -2
  21. package/dist/nx/index.d.ts +6 -0
  22. package/dist/nx/index.d.ts.map +1 -1
  23. package/dist/nx/index.js +55 -5
  24. package/dist/release/github-release.d.ts +3 -0
  25. package/dist/release/github-release.d.ts.map +1 -1
  26. package/dist/release/github-release.js +11 -0
  27. package/dist/release/index.d.ts +19 -1
  28. package/dist/release/index.d.ts.map +1 -1
  29. package/dist/release/index.js +140 -31
  30. package/dist/release/orchestration.d.ts +8 -1
  31. package/dist/release/orchestration.d.ts.map +1 -1
  32. package/dist/release/orchestration.js +38 -1
  33. package/managed/raw/tooling/direnv/github-actions-bootstrap.sh +5 -0
  34. package/managed/raw/tooling/direnv/setup-environment.ts +40 -3
  35. package/managed/templates/github/actions/cache-nix-devenv/action.yml +12 -10
  36. package/managed/templates/github/actions/cache-node-modules/action.yml +3 -2
  37. package/managed/templates/github/actions/cache-nx/action.yml +2 -2
  38. package/managed/templates/github/actions/save-nix-devenv/action.yml +11 -3
  39. package/package.json +7 -4
  40. package/src/cli.ts +30 -4
  41. package/src/github-ci/index.test.ts +486 -0
  42. package/src/github-ci/index.ts +172 -13
  43. package/src/github-ci/outputs.ts +506 -0
  44. package/src/monorepo/__tests__/ci-workflow.test.ts +11 -0
  45. package/src/monorepo/__tests__/publish-workflow.test.ts +222 -1
  46. package/src/monorepo/ci-workflow.ts +1 -1
  47. package/src/monorepo/managed-files.test.ts +62 -0
  48. package/src/monorepo/managed-files.ts +41 -0
  49. package/src/monorepo/package-policy.test.ts +50 -1
  50. package/src/monorepo/package-policy.ts +28 -0
  51. package/src/monorepo/packs/index.test.ts +18 -1
  52. package/src/monorepo/packs/index.ts +7 -3
  53. package/src/monorepo/publish-workflow.ts +479 -2
  54. package/src/nx/index.test.ts +39 -0
  55. package/src/nx/index.ts +65 -5
  56. package/src/release/__tests__/fixture-repo.test.ts +18 -16
  57. package/src/release/__tests__/github-release.test.ts +11 -0
  58. package/src/release/__tests__/orchestration.test.ts +57 -2
  59. package/src/release/__tests__/trust-publisher.test.ts +91 -2
  60. package/src/release/github-release.ts +12 -0
  61. package/src/release/index.ts +218 -40
  62. package/src/release/orchestration.ts +55 -3
@@ -11,6 +11,14 @@ export interface ReleasePublishOptions {
11
11
  }
12
12
  export interface ReleaseRepairPendingOptions {
13
13
  dryRun?: boolean;
14
+ platformOutputs?: string;
15
+ ref?: string;
16
+ }
17
+ export interface ReleasePlatformOutputsOptions {
18
+ bump: string;
19
+ output: string;
20
+ ref?: string;
21
+ targets: string;
14
22
  }
15
23
  export interface ReleaseTrustPublisherOptions {
16
24
  dryRun?: boolean;
@@ -37,7 +45,9 @@ export interface ReleaseRetagUnpublishedOptions {
37
45
  export declare function releaseVersion(root: string, options: ReleaseVersionOptions): Promise<void>;
38
46
  export declare function releasePublish(root: string, options: ReleasePublishOptions): Promise<void>;
39
47
  export declare function releaseRepairPending(root: string, options: ReleaseRepairPendingOptions): Promise<void>;
48
+ export declare function releaseCollectPlatformOutputs(root: string, options: ReleasePlatformOutputsOptions): Promise<void>;
40
49
  export declare function releaseTrustPublisher(root: string, options: ReleaseTrustPublisherOptions): Promise<void>;
50
+ export declare function npmTrustGithubArgs(packageName: string, repository: string, workflow: string, dryRun: boolean): string[];
41
51
  export interface TrustPublisherShell<Package extends ReleasePackageInfo = ReleasePackageInfo> {
42
52
  repository: string;
43
53
  workflow: string;
@@ -45,7 +55,8 @@ export interface TrustPublisherShell<Package extends ReleasePackageInfo = Releas
45
55
  packageExists(name: string): Promise<boolean>;
46
56
  bootstrapNpmPackages(options: BootstrapNpmPackagesOptions): Promise<Package[]>;
47
57
  trustPublisher(pkg: Package, dryRun: boolean, env?: Record<string, string>): Promise<TrustPublisherResult>;
48
- trustedPublishers(pkg: Package): Promise<TrustedPublisher[]>;
58
+ trustedPublishers(pkg: Package): Promise<TrustedPublisherLookup>;
59
+ login(): Promise<void>;
49
60
  log(message: string): void;
50
61
  error(message: string): void;
51
62
  }
@@ -56,9 +67,16 @@ export interface TrustedPublisher {
56
67
  file?: string;
57
68
  repository?: string;
58
69
  }
70
+ export interface NpmTrustAccessDenied {
71
+ readonly status: 'access-denied';
72
+ readonly identity: string;
73
+ readonly owners: string;
74
+ }
75
+ export type TrustedPublisherLookup = TrustedPublisher[] | NpmTrustAccessDenied;
59
76
  export declare function configureTrustedPublishers<Package extends ReleasePackageInfo>(shell: TrustPublisherShell<Package>, options: ReleaseTrustPublisherOptions): Promise<void>;
60
77
  export declare function releaseBootstrapNpmPackages(root: string, options: ReleaseBootstrapNpmPackagesOptions): Promise<void>;
61
78
  export declare function releaseRetagUnpublished(root: string, options: ReleaseRetagUnpublishedOptions): Promise<void>;
62
79
  export declare function printReleaseState(root: string): Promise<void>;
80
+ export declare function npmTrustListAccessDenied(stdout: string, stderr: string): boolean;
63
81
  export declare function parseTrustedPublishers(stdout: string, packageName: string): TrustedPublisher[];
64
82
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/release/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/release/index.ts"],"names":[],"mappings":"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"}
@@ -1,21 +1,22 @@
1
1
  import { appendFile, mkdtemp, rm, writeFile } from 'node:fs/promises';
2
2
  import { tmpdir } from 'node:os';
3
- import { join } from 'node:path';
3
+ import { join, resolve } from 'node:path';
4
4
  import { createInterface } from 'node:readline/promises';
5
5
  import { Writable } from 'node:stream';
6
6
  import { $ } from 'bun';
7
+ import { githubCiApplyOutputs, githubCiNxRunMany } from '../github-ci/index.js';
7
8
  import { assertNoConflictMarkers } from '../lib/conflict-markers.js';
8
9
  import { withDevenvEnv } from '../lib/devenv.js';
9
10
  import { isRecord, readJsonObject, stringProperty } from '../lib/json.js';
10
- import { decode, run, runInteractiveStatus, runResult, runStatus } from '../lib/run.js';
11
+ import { decode, run, runInteractiveStatus, runResult } from '../lib/run.js';
11
12
  import { listReleasePackages, readPackageJson, repositoryInfo } from '../lib/workspace.js';
12
13
  import { readPackedPackageJson, validatePackedWorkspaceDependencies } from '../monorepo/packed-manifest.js';
13
14
  import { bootstrapNpmPackages, NPM_BOOTSTRAP_DIST_TAG, NPM_BOOTSTRAP_VERSION, } from './bootstrap-npm-packages.js';
14
15
  import { autoReleaseCandidatePackages } from './candidates.js';
15
16
  import { collectOwnedReleaseTagRecords, pendingReleaseTargets, releaseTag, releaseTagAliases, } from './core.js';
16
- import { createOrUpdateGithubRelease, renderNxProjectChangelogContents, withNxWorkspaceRoot, } from './github-release.js';
17
+ import { createOrUpdateGithubRelease, githubReleaseLookupExists, renderNxProjectChangelogContents, withNxWorkspaceRoot, } from './github-release.js';
17
18
  import { publishWithAuthDiagnostics } from './npm-auth.js';
18
- import { bumpStableReleaseToNext, completeReleaseAtHead as completeReleaseAtHeadWithShell, repairPendingTargets, runReleaseVersion, } from './orchestration.js';
19
+ import { bumpStableReleaseToNext, collectRepairPlatformOutputs, completeReleaseAtHead as completeReleaseAtHeadWithShell, repairPendingTargets, runReleaseVersion, } from './orchestration.js';
19
20
  import { retagUnpublished } from './retag-unpublished.js';
20
21
  export async function releaseVersion(root, options) {
21
22
  const bump = releaseBumpArg(options.bump);
@@ -78,23 +79,38 @@ export async function releasePublish(root, options) {
78
79
  }
79
80
  }
80
81
  export async function releaseRepairPending(root, options) {
81
- const branch = await releaseBranch(root);
82
- const remote = await releaseRemote(root, branch);
83
- console.log(`Repair pending releases: fetching ${remote}/${branch} and tags.`);
84
- await fetchReleaseRefs(root, remote, branch);
85
- const remoteRef = `${remote}/${branch}`;
86
- const restoreRef = (await gitRefExists(root, remoteRef)) ? remoteRef : await gitHead(root);
87
- console.log(`Repair pending releases: planning from ${restoreRef}.`);
88
- const targets = await listPendingReleaseTargets(root, restoreRef);
89
- console.log(targets.length === 0
90
- ? 'Repair pending releases: no pending durable state repairs found.'
91
- : `Repair pending releases: ${targets.length} release target${targets.length === 1 ? '' : 's'} need repair.`);
92
- for (const target of targets) {
93
- console.log(`Repair pending releases: target ${target.sha.slice(0, 12)} needs ${repairTargetSummary(target)}.`);
94
- }
95
- const summaries = await repairPendingTargets(releaseRepairShell(root), targets, restoreRef, options.dryRun === true);
82
+ const repairRef = await fetchReleaseRepairRef(root, options.ref);
83
+ const restoreRef = options.ref ? await gitHead(root) : repairRef;
84
+ console.log(`Repair pending releases: planning from ${repairRef}.`);
85
+ const targets = await listPendingReleaseTargets(root, repairRef);
86
+ logPendingReleaseTargets(targets);
87
+ const platformOutputs = options.platformOutputs ? resolve(root, options.platformOutputs) : undefined;
88
+ const summaries = await repairPendingTargets(releaseRepairShell(root, platformOutputs), targets, restoreRef, options.dryRun === true);
96
89
  await writeRepairSummary(summaries, options.dryRun === true);
97
90
  }
91
+ export async function releaseCollectPlatformOutputs(root, options) {
92
+ const restoreRef = await gitHead(root);
93
+ const releaseRef = await fetchReleaseRepairRef(root, options.ref);
94
+ const packages = releasePackages(root);
95
+ const packagesAtHead = await releasePackagesAtHead(root, packages);
96
+ const currentPackages = packagesAtHead.length > 0
97
+ ? packagesAtHead
98
+ : await releasePlatformPackages(root, packages, releaseBumpArg(options.bump));
99
+ console.log(currentPackages.length === 0
100
+ ? 'Release platform outputs: no current release packages selected.'
101
+ : `Release platform outputs: building current outputs for ${packageSummary(currentPackages)}.`);
102
+ const outputRoot = resolve(root, options.output);
103
+ await githubCiNxRunMany(root, {
104
+ targets: options.targets,
105
+ projects: releasePackageProjects(currentPackages),
106
+ collectOutputs: join(outputRoot, 'current'),
107
+ allowEmptyProjects: true,
108
+ });
109
+ console.log(`Repair platform outputs: planning from ${releaseRef}.`);
110
+ const targets = await listPendingReleaseTargets(root, releaseRef);
111
+ logPendingReleaseTargets(targets);
112
+ await collectRepairPlatformOutputs(releaseRepairOutputsShell(root, options.targets, join(outputRoot, 'repairs')), targets, restoreRef);
113
+ }
98
114
  export async function releaseTrustPublisher(root, options) {
99
115
  const repository = githubRepositoryFromRootPackage(root);
100
116
  const workflow = 'publish.yml';
@@ -111,18 +127,20 @@ export async function releaseTrustPublisher(root, options) {
111
127
  promptOtp: (packageName) => promptForNpmOtp(packageName),
112
128
  log: (message) => console.log(message),
113
129
  }, bootstrapOptions),
114
- trustPublisher: (pkg, dryRun, env) => {
115
- const args = ['trust', 'github', pkg.name, '--file', workflow, '--repo', repository, '--yes'];
116
- if (dryRun) {
117
- args.push('--dry-run');
118
- }
119
- return runLatestNpmTrust(root, args, env);
120
- },
130
+ trustPublisher: (pkg, dryRun, env) => runLatestNpmTrust(root, npmTrustGithubArgs(pkg.name, repository, workflow, dryRun), env),
121
131
  trustedPublishers: (pkg) => listTrustedPublishers(root, pkg),
132
+ login: () => runLatestNpm(root, ['login', '--auth-type=web']),
122
133
  log: (message) => console.log(message),
123
134
  error: (message) => console.error(message),
124
135
  }, options);
125
136
  }
137
+ export function npmTrustGithubArgs(packageName, repository, workflow, dryRun) {
138
+ const args = ['trust', 'github', packageName, '--file', workflow, '--repo', repository, '--allow-publish', '--yes'];
139
+ if (dryRun) {
140
+ args.push('--dry-run');
141
+ }
142
+ return args;
143
+ }
126
144
  export async function configureTrustedPublishers(shell, options) {
127
145
  const packages = shell.listReleasePackages();
128
146
  const selectedPackages = selectedTrustPublisherPackages(packages, options.packages ?? []);
@@ -149,7 +167,7 @@ export async function configureTrustedPublishers(shell, options) {
149
167
  const failedPackages = [];
150
168
  for (const pkg of selectedPackages) {
151
169
  if (!options.dryRun) {
152
- const trustedPublishers = await shell.trustedPublishers(pkg);
170
+ const trustedPublishers = await trustedPublishersWithOwnerLogin(shell, pkg);
153
171
  if (hasMatchingGithubTrustedPublisher(trustedPublishers, shell.repository, shell.workflow)) {
154
172
  shell.log(`${pkg.name}: npm trusted publisher is already configured; skipping.`);
155
173
  continue;
@@ -186,6 +204,23 @@ export async function configureTrustedPublishers(shell, options) {
186
204
  shell.error(`Trusted publishing was not configured for: ${failedPackages.join(', ')}`);
187
205
  }
188
206
  }
207
+ async function trustedPublishersWithOwnerLogin(shell, pkg) {
208
+ let result = await shell.trustedPublishers(pkg);
209
+ if (Array.isArray(result)) {
210
+ return result;
211
+ }
212
+ shell.error(`${pkg.name}: npm trust access denied for npm account "${result.identity}". ` +
213
+ `npm trust requires package write access. Package owners:\n${result.owners}`);
214
+ shell.log(`${pkg.name}: opening npm browser login. Sign in as a listed package owner, then return here.`);
215
+ await shell.login();
216
+ result = await shell.trustedPublishers(pkg);
217
+ if (Array.isArray(result)) {
218
+ return result;
219
+ }
220
+ throw new Error(`${pkg.name}: npm trust access denied for npm account "${result.identity}". ` +
221
+ `npm trust requires package write access. Package owners:\n${result.owners}\n` +
222
+ 'npm browser login completed, but the selected account still cannot manage this package.');
223
+ }
189
224
  function selectedTrustPublisherPackages(packages, selections) {
190
225
  if (selections.length === 0) {
191
226
  return packages;
@@ -350,6 +385,14 @@ async function releaseVersionPackages(root, packages, bump) {
350
385
  packageHasHistory: (packagePath) => packageHasHistory(root, packagePath),
351
386
  }, packages);
352
387
  }
388
+ async function releasePlatformPackages(root, packages, bump) {
389
+ const candidates = await releaseVersionPackages(root, packages, bump);
390
+ if (candidates.length === 0) {
391
+ return [];
392
+ }
393
+ // Nx may version additional reverse dependents, so use its dry-run result rather than only the direct candidates.
394
+ return runNxReleaseVersionPreview(root, releasePackageProjects(candidates), bump);
395
+ }
353
396
  async function runNxReleaseVersion(root, projects, bump, dryRun) {
354
397
  if (dryRun) {
355
398
  return runNxReleaseVersionPreview(root, projects, bump);
@@ -392,6 +435,7 @@ async function runNxReleaseVersionPreview(root, projects, bump) {
392
435
  gitPush: false,
393
436
  stageChanges: false,
394
437
  createRelease: false,
438
+ forceChangelogGeneration: true,
395
439
  dryRun: true,
396
440
  });
397
441
  releasePreviewChangelogs.clear();
@@ -568,9 +612,8 @@ function releaseNextShell(root) {
568
612
  },
569
613
  };
570
614
  }
571
- function releaseRepairShell(root) {
615
+ function releaseTargetCheckoutShell(root) {
572
616
  return {
573
- ...releaseCompletionShell(root),
574
617
  checkout: (ref) => run('git', ['switch', '--detach', ref], root),
575
618
  withDevenvEnv: (runWithEnv) => withDevenvEnv(root, runWithEnv),
576
619
  beforeRepairTarget: (target) => {
@@ -581,6 +624,30 @@ function releaseRepairShell(root) {
581
624
  },
582
625
  };
583
626
  }
627
+ function releaseRepairShell(root, platformOutputs) {
628
+ return {
629
+ ...releaseCompletionShell(root),
630
+ ...releaseTargetCheckoutShell(root),
631
+ prepareRepairTarget: async (target) => {
632
+ if (!platformOutputs || target.npmPackages.length === 0) {
633
+ return;
634
+ }
635
+ const output = join(platformOutputs, target.sha);
636
+ console.log(`Repair pending releases: applying cross-platform outputs from ${output}.`);
637
+ await githubCiApplyOutputs(root, [output], target.sha);
638
+ },
639
+ };
640
+ }
641
+ function releaseRepairOutputsShell(root, targetGlobs, outputRoot) {
642
+ return {
643
+ ...releaseTargetCheckoutShell(root),
644
+ collectRepairTargetOutputs: (target) => githubCiNxRunMany(root, {
645
+ targets: targetGlobs,
646
+ projects: releasePackageProjects(target.npmPackages),
647
+ collectOutputs: join(outputRoot, target.sha),
648
+ }),
649
+ };
650
+ }
584
651
  function releaseRetagShell(root, remote) {
585
652
  return {
586
653
  listReleasePackages: () => releasePackages(root),
@@ -596,6 +663,25 @@ function releaseRetagShell(root, remote) {
596
663
  log: (message) => console.log(message),
597
664
  };
598
665
  }
666
+ async function fetchReleaseRepairRef(root, requestedRef) {
667
+ const branch = await releaseBranch(root);
668
+ const remote = await releaseRemote(root, branch);
669
+ console.log(`Repair pending releases: fetching ${remote}/${branch} and tags.`);
670
+ await fetchReleaseRefs(root, remote, branch);
671
+ if (requestedRef) {
672
+ return requestedRef;
673
+ }
674
+ const remoteRef = `${remote}/${branch}`;
675
+ return (await gitRefExists(root, remoteRef)) ? remoteRef : gitHead(root);
676
+ }
677
+ function logPendingReleaseTargets(targets) {
678
+ console.log(targets.length === 0
679
+ ? 'Repair pending releases: no pending durable state repairs found.'
680
+ : `Repair pending releases: ${targets.length} release target${targets.length === 1 ? '' : 's'} need repair.`);
681
+ for (const target of targets) {
682
+ console.log(`Repair pending releases: target ${target.sha.slice(0, 12)} needs ${repairTargetSummary(target)}.`);
683
+ }
684
+ }
599
685
  async function listPendingReleaseTargets(root, ref) {
600
686
  const head = await gitHead(root);
601
687
  return pendingReleaseTargets(await listOwnedReleaseTagRecords(root, ref), head);
@@ -795,7 +881,8 @@ function repairReasons(target, pkg) {
795
881
  return reasons;
796
882
  }
797
883
  async function fetchReleaseRefs(root, remote, branch) {
798
- await run('git', ['fetch', '--tags', remote, branch], root);
884
+ // `retag-unpublished` intentionally moves repairable tags, so the remote tag is authoritative.
885
+ await run('git', ['fetch', '--force', '--tags', remote, branch], root);
799
886
  }
800
887
  async function gitRefExists(root, ref) {
801
888
  const result = await $ `git rev-parse --verify ${ref}`.cwd(root).quiet().nothrow();
@@ -1003,7 +1090,8 @@ async function pushRetaggedReleaseTags(root, remote, updates) {
1003
1090
  await run('git', ['push', '--atomic', ...leases, remote, ...refspecs], root);
1004
1091
  }
1005
1092
  async function githubReleaseExists(root, tag) {
1006
- return (await runStatus('gh', ['release', 'view', tag, '--json', 'tagName'], root, true)) === 0;
1093
+ const result = await $ `gh release view ${tag} --json tagName`.cwd(root).quiet().nothrow();
1094
+ return githubReleaseLookupExists(tag, result.exitCode, decode(result.stdout), decode(result.stderr));
1007
1095
  }
1008
1096
  function githubReleaseUrl(root, tag) {
1009
1097
  return `https://github.com/${githubRepositoryFromRootPackage(root)}/releases/tag/${encodeURIComponent(tag)}`;
@@ -1143,11 +1231,32 @@ async function listTrustedPublishers(root, pkg) {
1143
1231
  }
1144
1232
  result = await runResult('nix', ['shell', 'nixpkgs#nodejs_latest', '-c', 'npm', ...args], root);
1145
1233
  }
1234
+ if (result.exitCode !== 0 && npmTrustListAccessDenied(result.stdout, result.stderr)) {
1235
+ return npmTrustAccessDetails(root, pkg.name);
1236
+ }
1146
1237
  if (result.exitCode !== 0) {
1147
1238
  throw new Error(`nix shell nixpkgs#nodejs_latest -c npm ${args.join(' ')} failed with exit code ${result.exitCode}`);
1148
1239
  }
1149
1240
  return parseTrustedPublishers(result.stdout, pkg.name);
1150
1241
  }
1242
+ export function npmTrustListAccessDenied(stdout, stderr) {
1243
+ return /\bE403\b/.test(`${stdout}\n${stderr}`);
1244
+ }
1245
+ async function npmTrustAccessDetails(root, packageName) {
1246
+ const [identityResult, ownersResult] = await Promise.all([
1247
+ runResult('nix', ['shell', 'nixpkgs#nodejs_latest', '-c', 'npm', 'whoami'], root),
1248
+ runResult('nix', ['shell', 'nixpkgs#nodejs_latest', '-c', 'npm', 'owner', 'ls', packageName], root),
1249
+ ]);
1250
+ return {
1251
+ status: 'access-denied',
1252
+ identity: identityResult.exitCode === 0 && identityResult.stdout.trim().length > 0
1253
+ ? identityResult.stdout.trim()
1254
+ : '(not authenticated)',
1255
+ owners: ownersResult.exitCode === 0 && ownersResult.stdout.trim().length > 0
1256
+ ? ownersResult.stdout.trim()
1257
+ : '(owner lookup unavailable)',
1258
+ };
1259
+ }
1151
1260
  export function parseTrustedPublishers(stdout, packageName) {
1152
1261
  if (stdout.trim().length === 0) {
1153
1262
  return [];
@@ -27,12 +27,18 @@ export interface ReleaseCompletionShell<Package extends ReleasePackageInfo = Rel
27
27
  export interface ReleaseNextShell<Package extends ReleasePackageInfo = ReleasePackageInfo> {
28
28
  bumpStablePackagesToNext(packages: Package[]): Promise<void>;
29
29
  }
30
- export interface ReleaseRepairShell<Package extends ReleasePackageInfo = ReleasePackageInfo> extends ReleaseCompletionShell<Package> {
30
+ export interface ReleaseTargetCheckoutShell<Package extends ReleasePackageInfo = ReleasePackageInfo> {
31
31
  checkout(ref: string): Promise<void>;
32
32
  withDevenvEnv<T>(runWithEnv: () => Promise<T>): Promise<T>;
33
33
  beforeRepairTarget?(target: ReleaseTarget<Package>): void;
34
34
  afterRepairTarget?(target: ReleaseTarget<Package>): void;
35
35
  }
36
+ export interface ReleaseRepairShell<Package extends ReleasePackageInfo = ReleasePackageInfo> extends ReleaseCompletionShell<Package>, ReleaseTargetCheckoutShell<Package> {
37
+ prepareRepairTarget?(target: ReleaseTarget<Package>): Promise<void>;
38
+ }
39
+ export interface ReleaseRepairOutputsShell<Package extends ReleasePackageInfo = ReleasePackageInfo> extends ReleaseTargetCheckoutShell<Package> {
40
+ collectRepairTargetOutputs(target: ReleaseTarget<Package>): Promise<void>;
41
+ }
36
42
  export interface ReleaseVersionShell<Package extends ReleasePackageInfo = ReleasePackageInfo> {
37
43
  releasePackagesAtHead(): Promise<Package[]>;
38
44
  releaseVersionPackages(bump: string): Promise<Package[]>;
@@ -53,5 +59,6 @@ export declare function runReleaseVersion<Package extends ReleasePackageInfo>(sh
53
59
  export declare function completeReleaseAtHead<Package extends ReleasePackageInfo>(shell: ReleaseCompletionShell<Package>, packages: Package[], dryRun: boolean, rerunRequired: boolean): Promise<ReleaseSummary<Package>>;
54
60
  export declare function bumpStableReleaseToNext<Package extends ReleasePackageInfo>(shell: ReleaseNextShell<Package>, packages: Package[], dryRun: boolean, rerunRequired: boolean): Promise<Package[]>;
55
61
  export declare function repairPendingTargets<Package extends ReleasePackageInfo>(shell: ReleaseRepairShell<Package>, targets: Array<ReleaseTarget<Package>>, restoreRef: string, dryRun: boolean): Promise<Array<ReleaseSummary<Package>>>;
62
+ export declare function collectRepairPlatformOutputs<Package extends ReleasePackageInfo>(shell: ReleaseRepairOutputsShell<Package>, targets: Array<ReleaseTarget<Package>>, restoreRef: string): Promise<void>;
56
63
  export declare function completeRepairTargetAtHead<Package extends ReleasePackageInfo>(shell: ReleaseCompletionShell<Package>, target: ReleaseTarget<Package>, dryRun: boolean): Promise<ReleaseSummary<Package>>;
57
64
  //# sourceMappingURL=orchestration.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"orchestration.d.ts","sourceRoot":"","sources":["../../src/release/orchestration.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"orchestration.d.ts","sourceRoot":"","sources":["../../src/release/orchestration.ts"],"names":[],"mappings":"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"}
@@ -72,7 +72,10 @@ export async function repairPendingTargets(shell, targets, restoreRef, dryRun) {
72
72
  }
73
73
  shell.beforeRepairTarget?.(target);
74
74
  try {
75
- summaries.push(await shell.withDevenvEnv(() => completeRepairTargetAtHead(shell, target, dryRun)));
75
+ summaries.push(await shell.withDevenvEnv(async () => {
76
+ await shell.prepareRepairTarget?.(target);
77
+ return completeRepairTargetAtHead(shell, target, dryRun);
78
+ }));
76
79
  }
77
80
  finally {
78
81
  shell.afterRepairTarget?.(target);
@@ -81,9 +84,43 @@ export async function repairPendingTargets(shell, targets, restoreRef, dryRun) {
81
84
  }
82
85
  finally {
83
86
  await shell.checkout(restoreRef);
87
+ if (targets.length > 0) {
88
+ // Loading devenv at a historical release can rebuild ignored tool outputs
89
+ // from that checkout. Refresh after restoring HEAD so later release phases
90
+ // cannot combine the current CLI with an older Nx plugin build.
91
+ await shell.withDevenvEnv(async () => undefined);
92
+ }
84
93
  }
85
94
  return summaries;
86
95
  }
96
+ export async function collectRepairPlatformOutputs(shell, targets, restoreRef) {
97
+ const outputTargets = targets.filter((target) => target.npmPackages.length > 0);
98
+ if (outputTargets.length === 0) {
99
+ return;
100
+ }
101
+ try {
102
+ for (const target of outputTargets) {
103
+ await shell.checkout(target.sha);
104
+ if (target.packages.length === 0) {
105
+ // invariant throw: release target discovery must never yield a package-free target.
106
+ throw new Error(`Release commit ${target.sha} has no release packages after checkout.`);
107
+ }
108
+ shell.beforeRepairTarget?.(target);
109
+ try {
110
+ await shell.withDevenvEnv(() => shell.collectRepairTargetOutputs(target));
111
+ }
112
+ finally {
113
+ shell.afterRepairTarget?.(target);
114
+ }
115
+ }
116
+ }
117
+ finally {
118
+ await shell.checkout(restoreRef);
119
+ // Historical devenv activation may rebuild ignored tool outputs. Restore the
120
+ // dispatch environment before the macOS job performs any further work.
121
+ await shell.withDevenvEnv(async () => undefined);
122
+ }
123
+ }
87
124
  function repairDryRunSummary(target) {
88
125
  return {
89
126
  sha: target.sha,
@@ -46,6 +46,11 @@ install_devenv() {
46
46
 
47
47
  build_devenv_shell() {
48
48
  devenv shell --verbose -- date
49
+ # enterShell exports this for the bootstrap itself; persist it for the
50
+ # independent workflow step shells that run after this composite action.
51
+ if [ -n "${GITHUB_ENV:-}" ]; then
52
+ echo "TTSC_TSGO_BINARY=$repo_root/node_modules/@typescript/native/bin/tsc" >> "$GITHUB_ENV"
53
+ fi
49
54
  # Add repo-local tools only after the shell exists; cleanup steps use an
50
55
  # explicit PATH because failures before this point must still refresh caches.
51
56
  add_repo_paths
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env bun
2
2
  import { existsSync } from 'node:fs';
3
- import { mkdir, rmdir } from 'node:fs/promises';
3
+ import { mkdir, rmdir, stat } from 'node:fs/promises';
4
4
  import path from 'node:path';
5
5
  import { $ } from 'bun';
6
6
 
@@ -8,6 +8,13 @@ const devenvRoot = process.env.DEVENV_ROOT;
8
8
  const projectRoot = path.resolve(`${devenvRoot}/../..`);
9
9
  const startedWithoutNodeModules = !existsSync(path.join(projectRoot, 'node_modules'));
10
10
 
11
+ // A legitimate concurrent setup finishes well within this; anything older is a
12
+ // leftover from an interrupted run (CTRL-C/kill before the finally-cleanup) and
13
+ // would otherwise wedge every future shell load behind the 120s spin + EEXIST.
14
+ // NOTE: must be declared ABOVE the top-level setup block below — module consts
15
+ // are not hoisted, and the lock loop runs during that block.
16
+ const STALE_LOCK_MS = 10 * 60_000;
17
+
11
18
  class CapturedCommandError extends Error {
12
19
  constructor(
13
20
  public readonly command: string,
@@ -67,7 +74,9 @@ try {
67
74
  }
68
75
 
69
76
  async function installLocalDependencies(): Promise<void> {
70
- // Serialize concurrent direnv activations installing into the same node_modules.
77
+ // bun install runs the root prepare script, which patches TypeScript with
78
+ // ts-patch. Multiple concurrent direnv activations can otherwise race while
79
+ // mutating the same files under node_modules.
71
80
  await withSetupLock(async () => {
72
81
  await runSetupCommand('bun install --no-summary', $`bun install --no-summary`);
73
82
  });
@@ -104,14 +113,42 @@ async function acquireLock(lockDir: string): Promise<void> {
104
113
  await mkdir(lockDir, { recursive: false });
105
114
  return;
106
115
  } catch (error) {
107
- if (!(error instanceof Error && 'code' in error && error.code === 'EEXIST') || Date.now() > deadline) {
116
+ if (!isFileExistsError(error) || Date.now() > deadline) {
108
117
  throw error;
109
118
  }
119
+ if (await isStaleLock(lockDir)) {
120
+ // Surface the self-heal so an interrupted-run leftover is visible in
121
+ // the direnv log rather than silently absorbed.
122
+ console.error(`! Breaking stale setup lock (${lockDir}) left by an interrupted run`);
123
+ // Best-effort: if a concurrent process breaks it first, the rmdir
124
+ // fails silently and the next mkdir attempt settles the race.
125
+ await rmdir(lockDir).catch(() => undefined);
126
+ continue;
127
+ }
110
128
  await Bun.sleep(100);
111
129
  }
112
130
  }
113
131
  }
114
132
 
133
+ async function isStaleLock(lockDir: string): Promise<boolean> {
134
+ try {
135
+ const info = await stat(lockDir);
136
+ return Date.now() - info.mtimeMs > STALE_LOCK_MS;
137
+ } catch (error) {
138
+ // Only "lock vanished" is expected here (a concurrent process released
139
+ // it); anything else must surface — a swallowed ReferenceError in this
140
+ // exact spot once disabled stale detection entirely.
141
+ if (error instanceof Error && 'code' in error && error.code === 'ENOENT') {
142
+ return false; // gone — let the mkdir retry acquire it
143
+ }
144
+ throw error;
145
+ }
146
+ }
147
+
148
+ function isFileExistsError(error: unknown): boolean {
149
+ return error instanceof Error && 'code' in error && error.code === 'EEXIST';
150
+ }
151
+
115
152
  function replayCapturedOutput(error: unknown): void {
116
153
  if (!(error instanceof CapturedCommandError)) {
117
154
  return;
@@ -33,10 +33,10 @@ runs:
33
33
  ~/.local/state/nix/profiles
34
34
  ~/.cache/nix
35
35
  key:
36
- ${{ runner.os }}-nix-v3-${{ hashFiles('tooling/direnv/devenv.yaml', 'tooling/direnv/devenv.nix',
37
- 'tooling/direnv/devenv.lock') }}
36
+ ${{ runner.os }}-${{ runner.arch }}-nix-v3-${{ hashFiles('tooling/direnv/devenv.yaml',
37
+ 'tooling/direnv/devenv.nix', 'tooling/direnv/devenv.lock') }}
38
38
  restore-keys: |
39
- ${{ runner.os }}-nix-v3-
39
+ ${{ runner.os }}-${{ runner.arch }}-nix-v3-
40
40
 
41
41
  - name: Save Nix profiles and store NAR
42
42
  if: ${{ inputs.segment == 'nix' && inputs.mode == 'save' }}
@@ -48,8 +48,8 @@ runs:
48
48
  ~/.local/state/nix/profiles
49
49
  ~/.cache/nix
50
50
  key:
51
- ${{ runner.os }}-nix-v3-${{ hashFiles('tooling/direnv/devenv.yaml', 'tooling/direnv/devenv.nix',
52
- 'tooling/direnv/devenv.lock') }}
51
+ ${{ runner.os }}-${{ runner.arch }}-nix-v3-${{ hashFiles('tooling/direnv/devenv.yaml',
52
+ 'tooling/direnv/devenv.nix', 'tooling/direnv/devenv.lock') }}
53
53
 
54
54
  # .devenv/.direnv are small, but they contain absolute /nix/store pointers.
55
55
  # Workflows restore this segment only after an exact Nix cache hit.
@@ -62,10 +62,11 @@ runs:
62
62
  ${{ github.workspace }}/tooling/direnv/.devenv
63
63
  ${{ github.workspace }}/tooling/direnv/.direnv
64
64
  key:
65
- ${{ runner.os }}-devenv-v3-${{ hashFiles('tooling/direnv/devenv.yaml', 'tooling/direnv/devenv.nix',
66
- 'tooling/direnv/devenv.lock', 'tooling/direnv/envrc.sh', 'tooling/direnv/setup-environment.ts') }}
65
+ ${{ runner.os }}-${{ runner.arch }}-devenv-v3-${{ hashFiles('tooling/direnv/devenv.yaml',
66
+ 'tooling/direnv/devenv.nix', 'tooling/direnv/devenv.lock', 'tooling/direnv/envrc.sh',
67
+ 'tooling/direnv/setup-environment.ts') }}
67
68
  restore-keys: |
68
- ${{ runner.os }}-devenv-v3-
69
+ ${{ runner.os }}-${{ runner.arch }}-devenv-v3-
69
70
 
70
71
  - name: Save devenv and direnv state
71
72
  if: ${{ inputs.segment == 'devenv' && inputs.mode == 'save' }}
@@ -75,5 +76,6 @@ runs:
75
76
  ${{ github.workspace }}/tooling/direnv/.devenv
76
77
  ${{ github.workspace }}/tooling/direnv/.direnv
77
78
  key:
78
- ${{ runner.os }}-devenv-v3-${{ hashFiles('tooling/direnv/devenv.yaml', 'tooling/direnv/devenv.nix',
79
- 'tooling/direnv/devenv.lock', 'tooling/direnv/envrc.sh', 'tooling/direnv/setup-environment.ts') }}
79
+ ${{ runner.os }}-${{ runner.arch }}-devenv-v3-${{ hashFiles('tooling/direnv/devenv.yaml',
80
+ 'tooling/direnv/devenv.nix', 'tooling/direnv/devenv.lock', 'tooling/direnv/envrc.sh',
81
+ 'tooling/direnv/setup-environment.ts') }}
@@ -8,6 +8,7 @@ runs:
8
8
  uses: actions/cache@v5.0.5
9
9
  with:
10
10
  path: node_modules
11
- key: ${{ runner.os }}-node-{{NODE_MODULES_CACHE_KEY}}
11
+ # prettier-ignore
12
+ key: ${{ runner.os }}-${{ runner.arch }}-node-{{NODE_MODULES_CACHE_KEY}}
12
13
  restore-keys: |
13
- ${{ runner.os }}-node-
14
+ ${{ runner.os }}-${{ runner.arch }}-node-
@@ -16,6 +16,6 @@ runs:
16
16
  path: |
17
17
  .nx/cache
18
18
  .nx/workspace-data/*.db*
19
- key: ${{ runner.os }}-nx-db-v1-${{ github.sha }}
19
+ key: ${{ runner.os }}-${{ runner.arch }}-nx-db-v1-${{ github.sha }}
20
20
  restore-keys: |
21
- ${{ runner.os }}-nx-db-v1-
21
+ ${{ runner.os }}-${{ runner.arch }}-nx-db-v1-
@@ -14,13 +14,21 @@ inputs:
14
14
  runs:
15
15
  using: composite
16
16
  steps:
17
- - name: 🧹 Cleanup and cache Nix store
17
+ - name: 🧹 Prepare Nix/devenv cache save
18
18
  id: cleanup-cache
19
19
  shell: bash
20
20
  working-directory: tooling/direnv
21
- # build-shell normally adds repo paths to GITHUB_PATH, but this cleanup
22
- # must still run when build-shell fails before that happens.
21
+ env:
22
+ NIX_CACHE_HIT: ${{ inputs.nix-cache-hit }}
23
+ # An exact Nix cache hit is immutable and cannot be overwritten by
24
+ # actions/cache. Avoid rebuilding its ~2 GB NAR just to discard it.
25
+ # build-shell normally adds repo paths to GITHUB_PATH, but cleanup must
26
+ # still run after a cache miss when build-shell fails before that happens.
23
27
  run: |
28
+ if [[ "$NIX_CACHE_HIT" == 'true' ]]; then
29
+ echo 'cache-ready=true' >> "$GITHUB_OUTPUT"
30
+ exit 0
31
+ fi
24
32
  export PATH="$(../../tooling/direnv/repo-path)"
25
33
  smoo github-ci cleanup-cache
26
34