@smoothbricks/cli 0.1.1 → 0.2.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.
Files changed (117) hide show
  1. package/README.md +155 -30
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +91 -7
  4. package/dist/devenv/index.d.ts +10 -0
  5. package/dist/devenv/index.d.ts.map +1 -0
  6. package/dist/devenv/index.js +27 -0
  7. package/dist/lib/cli-package.d.ts +4 -0
  8. package/dist/lib/cli-package.d.ts.map +1 -0
  9. package/dist/lib/cli-package.js +15 -0
  10. package/dist/lib/run.d.ts +5 -0
  11. package/dist/lib/run.d.ts.map +1 -1
  12. package/dist/lib/run.js +13 -0
  13. package/dist/lib/workspace.d.ts +15 -1
  14. package/dist/lib/workspace.d.ts.map +1 -1
  15. package/dist/lib/workspace.js +25 -2
  16. package/dist/monorepo/commit-msg.d.ts +8 -1
  17. package/dist/monorepo/commit-msg.d.ts.map +1 -1
  18. package/dist/monorepo/commit-msg.js +85 -7
  19. package/dist/monorepo/index.d.ts +19 -2
  20. package/dist/monorepo/index.d.ts.map +1 -1
  21. package/dist/monorepo/index.js +104 -16
  22. package/dist/monorepo/managed-files.js +1 -1
  23. package/dist/monorepo/nx-sync.d.ts +2 -1
  24. package/dist/monorepo/nx-sync.d.ts.map +1 -1
  25. package/dist/monorepo/nx-sync.js +8 -2
  26. package/dist/monorepo/package-hygiene.d.ts +6 -2
  27. package/dist/monorepo/package-hygiene.d.ts.map +1 -1
  28. package/dist/monorepo/package-hygiene.js +12 -4
  29. package/dist/monorepo/package-policy.d.ts +22 -2
  30. package/dist/monorepo/package-policy.d.ts.map +1 -1
  31. package/dist/monorepo/package-policy.js +1167 -8
  32. package/dist/monorepo/packed-package.d.ts +3 -0
  33. package/dist/monorepo/packed-package.d.ts.map +1 -1
  34. package/dist/monorepo/packed-package.js +68 -36
  35. package/dist/monorepo/packs/index.d.ts +20 -1
  36. package/dist/monorepo/packs/index.d.ts.map +1 -1
  37. package/dist/monorepo/packs/index.js +238 -19
  38. package/dist/monorepo/publish-workflow.d.ts +0 -4
  39. package/dist/monorepo/publish-workflow.d.ts.map +1 -1
  40. package/dist/monorepo/publish-workflow.js +5 -12
  41. package/dist/monorepo/tool-validation.d.ts +22 -0
  42. package/dist/monorepo/tool-validation.d.ts.map +1 -0
  43. package/dist/monorepo/tool-validation.js +399 -0
  44. package/dist/nx/index.d.ts +24 -0
  45. package/dist/nx/index.d.ts.map +1 -0
  46. package/dist/nx/index.js +94 -0
  47. package/dist/release/bootstrap-npm-packages.d.ts +19 -0
  48. package/dist/release/bootstrap-npm-packages.d.ts.map +1 -0
  49. package/dist/release/bootstrap-npm-packages.js +58 -0
  50. package/dist/release/candidates.d.ts +11 -0
  51. package/dist/release/candidates.d.ts.map +1 -0
  52. package/dist/release/candidates.js +181 -0
  53. package/dist/release/core.d.ts +1 -0
  54. package/dist/release/core.d.ts.map +1 -1
  55. package/dist/release/github-release.js +2 -2
  56. package/dist/release/index.d.ts +25 -0
  57. package/dist/release/index.d.ts.map +1 -1
  58. package/dist/release/index.js +247 -49
  59. package/dist/release/npm-auth.d.ts +0 -1
  60. package/dist/release/npm-auth.d.ts.map +1 -1
  61. package/dist/release/npm-auth.js +4 -16
  62. package/dist/release/orchestration.d.ts +2 -1
  63. package/dist/release/orchestration.d.ts.map +1 -1
  64. package/dist/release/orchestration.js +9 -1
  65. package/dist/release/publish-plan.js +1 -1
  66. package/managed/raw/git-format-staged.yml +54 -0
  67. package/managed/raw/tooling/git-hooks/commit-msg.sh +1 -1
  68. package/managed/templates/github/actions/setup-devenv/action.yml +1 -7
  69. package/managed/templates/github/workflows/ci.yml +1 -0
  70. package/package.json +15 -3
  71. package/src/cli.ts +134 -20
  72. package/src/devenv/index.test.ts +49 -0
  73. package/src/devenv/index.ts +38 -0
  74. package/src/lib/cli-package.ts +18 -0
  75. package/src/lib/run.ts +19 -0
  76. package/src/lib/workspace.ts +41 -2
  77. package/src/monorepo/__tests__/publish-workflow.test.ts +16 -9
  78. package/src/monorepo/commit-msg.test.ts +45 -0
  79. package/src/monorepo/commit-msg.ts +107 -7
  80. package/src/monorepo/index.ts +142 -16
  81. package/src/monorepo/managed-files.ts +1 -1
  82. package/src/monorepo/nx-sync.ts +9 -2
  83. package/src/monorepo/package-hygiene.test.ts +34 -0
  84. package/src/monorepo/package-hygiene.ts +26 -4
  85. package/src/monorepo/package-policy.test.ts +902 -0
  86. package/src/monorepo/package-policy.ts +1393 -7
  87. package/src/monorepo/packed-package.ts +89 -37
  88. package/src/monorepo/packs/index.test.ts +189 -0
  89. package/src/monorepo/packs/index.ts +311 -20
  90. package/src/monorepo/publish-workflow.ts +8 -16
  91. package/src/monorepo/setup-test-tracing.test.ts +120 -0
  92. package/src/monorepo/tool-validation.test.ts +261 -0
  93. package/src/monorepo/tool-validation.ts +462 -0
  94. package/src/nx/index.test.ts +64 -0
  95. package/src/nx/index.ts +119 -0
  96. package/src/release/__tests__/bootstrap-npm-packages.test.ts +127 -0
  97. package/src/release/__tests__/candidates.test.ts +217 -0
  98. package/src/release/__tests__/core-properties.test.ts +4 -4
  99. package/src/release/__tests__/core-scenarios.test.ts +15 -5
  100. package/src/release/__tests__/core.test.ts +2 -2
  101. package/src/release/__tests__/fixture-repo.test.ts +22 -13
  102. package/src/release/__tests__/github-release.test.ts +13 -8
  103. package/src/release/__tests__/helpers/fixture-repo.ts +1 -0
  104. package/src/release/__tests__/npm-auth.test.ts +12 -21
  105. package/src/release/__tests__/orchestration.test.ts +51 -7
  106. package/src/release/__tests__/publish-plan.test.ts +9 -3
  107. package/src/release/__tests__/retag-unpublished.test.ts +1 -1
  108. package/src/release/__tests__/trust-publisher.test.ts +133 -0
  109. package/src/release/bootstrap-npm-packages.ts +88 -0
  110. package/src/release/candidates.ts +225 -0
  111. package/src/release/core.ts +1 -0
  112. package/src/release/github-release.ts +2 -2
  113. package/src/release/index.ts +346 -56
  114. package/src/release/npm-auth.ts +4 -33
  115. package/src/release/orchestration.ts +12 -2
  116. package/src/release/publish-plan.ts +1 -1
  117. package/managed/raw/.git-format-staged.yml +0 -47
@@ -5,10 +5,12 @@ import { createInterface } from 'node:readline/promises';
5
5
  import { Writable } from 'node:stream';
6
6
  import { $ } from 'bun';
7
7
  import { withDevenvEnv } from '../lib/devenv.js';
8
- import { isRecord, stringProperty } from '../lib/json.js';
9
- import { decode, run, runStatus } from '../lib/run.js';
8
+ import { isRecord, readJsonObject, stringProperty } from '../lib/json.js';
9
+ import { decode, run, 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
+ import { bootstrapNpmPackages, NPM_BOOTSTRAP_DIST_TAG, NPM_BOOTSTRAP_VERSION, } from './bootstrap-npm-packages.js';
13
+ import { autoReleaseCandidatePackages } from './candidates.js';
12
14
  import { collectOwnedReleaseTagRecords, pendingReleaseTargets, releaseTag, } from './core.js';
13
15
  import { createOrUpdateGithubRelease, renderNxProjectChangelogContents } from './github-release.js';
14
16
  import { publishWithAuthDiagnostics } from './npm-auth.js';
@@ -17,12 +19,12 @@ import { retagUnpublished } from './retag-unpublished.js';
17
19
  export async function releaseVersion(root, options) {
18
20
  const bump = releaseBumpArg(options.bump);
19
21
  const packages = releasePackages(root);
20
- const projects = releasePackageProjects(packages);
21
22
  const result = await runReleaseVersion({
22
23
  releasePackagesAtHead: () => releasePackagesAtHead(root, packages),
24
+ releaseVersionPackages: (releaseBump) => releaseVersionPackages(root, packages, releaseBump),
23
25
  ensureLocalReleaseTags: (releasePackages) => ensureLocalReleaseTags(root, releasePackages),
24
26
  gitHead: () => gitHead(root),
25
- runNxReleaseVersion: (releaseBump, dryRun) => runNxReleaseVersion(root, projects, releaseBump, dryRun),
27
+ runNxReleaseVersion: (releasePackages, releaseBump, dryRun) => runNxReleaseVersion(root, releasePackageProjects(releasePackages), releaseBump, dryRun),
26
28
  assertCleanGitTree: () => assertCleanGitTree(root),
27
29
  }, { bump, dryRun: options.dryRun === true });
28
30
  if (result.status === 'already-release-target') {
@@ -76,56 +78,107 @@ export async function releaseRepairPending(root, options) {
76
78
  export async function releaseTrustPublisher(root, options) {
77
79
  const repository = githubRepositoryFromRootPackage(root);
78
80
  const workflow = 'publish.yml';
79
- const packages = listReleasePackages(root);
81
+ await configureTrustedPublishers({
82
+ repository,
83
+ workflow,
84
+ listReleasePackages: () => listReleasePackages(root),
85
+ packageExists: (name) => npmPackageExists(root, name),
86
+ bootstrapNpmPackages: (bootstrapOptions) => bootstrapNpmPackages({
87
+ listReleasePackages: () => listReleasePackages(root),
88
+ packageExists: (name) => npmPackageExists(root, name),
89
+ login: () => runLatestNpm(root, ['login', '--auth-type=web']),
90
+ publishPlaceholder: (pkg, env) => publishPlaceholderPackage(root, pkg, env),
91
+ promptOtp: (packageName) => promptForNpmOtp(packageName),
92
+ log: (message) => console.log(message),
93
+ }, bootstrapOptions),
94
+ login: () => runLatestNpm(root, ['login', '--auth-type=web']),
95
+ trustPublisher: (pkg, dryRun, env) => {
96
+ const args = ['trust', 'github', pkg.name, '--file', workflow, '--repo', repository, '--yes'];
97
+ if (dryRun) {
98
+ args.push('--dry-run');
99
+ }
100
+ return runLatestNpmTrust(root, args, env);
101
+ },
102
+ promptOtp: (packageName) => promptForNpmOtp(packageName),
103
+ log: (message) => console.log(message),
104
+ error: (message) => console.error(message),
105
+ }, options);
106
+ }
107
+ export async function configureTrustedPublishers(shell, options) {
108
+ const packages = shell.listReleasePackages();
80
109
  if (packages.length === 0) {
81
110
  throw new Error('No owned release packages found.');
82
111
  }
112
+ let bootstrapLoggedIn = false;
113
+ if (options.bootstrap) {
114
+ const bootstrapped = await shell.bootstrapNpmPackages({
115
+ dryRun: options.dryRun === true,
116
+ skipLogin: options.skipLogin === true,
117
+ otp: options.bootstrapOtp,
118
+ packages: [],
119
+ });
120
+ bootstrapLoggedIn = bootstrapped.length > 0 && !options.dryRun && !options.skipLogin;
121
+ }
83
122
  if (!options.dryRun) {
84
- const packageStates = await Promise.all(packages.map(async (pkg) => ((await npmPackageExists(root, pkg.name)) ? null : pkg.name)));
123
+ const packageStates = await Promise.all(packages.map(async (pkg) => ((await shell.packageExists(pkg.name)) ? null : pkg.name)));
85
124
  const missingPackages = packageStates.filter((name) => name !== null);
86
125
  if (missingPackages.length > 0) {
87
126
  throw new Error('npm trusted publishing can only be configured after packages exist on the registry. ' +
88
- 'Bootstrap the first publish with a temporary NPM_TOKEN, then rerun trust-publisher. ' +
127
+ 'Run smoo release trust-publisher --bootstrap locally. ' +
89
128
  `Missing packages: ${missingPackages.join(', ')}`);
90
129
  }
91
130
  }
92
- if (!options.dryRun && !options.skipLogin) {
93
- await runLatestNpm(root, ['login', '--auth-type=web']);
131
+ if (!options.dryRun && !options.skipLogin && !bootstrapLoggedIn) {
132
+ await shell.login();
94
133
  }
95
134
  const failedPackages = [];
96
135
  for (const pkg of packages) {
97
- console.log(`${pkg.name}: trusting GitHub Actions ${repository}/${workflow}`);
98
- const args = ['trust', 'github', pkg.name, '--file', workflow, '--repo', repository, '--yes'];
99
- if (options.dryRun) {
100
- args.push('--dry-run');
101
- }
136
+ shell.log(`${pkg.name}: trusting GitHub Actions ${shell.repository}/${shell.workflow}`);
102
137
  while (true) {
103
- const otp = options.dryRun ? undefined : (options.otp ?? (await promptForNpmOtp(pkg.name)));
138
+ const otp = options.dryRun ? undefined : (options.otp ?? (await shell.promptOtp(pkg.name)));
104
139
  try {
105
- await runLatestNpm(root, args, otp ? { NPM_CONFIG_OTP: otp } : undefined);
140
+ const result = await shell.trustPublisher(pkg, options.dryRun === true, otp ? { NPM_CONFIG_OTP: otp } : undefined);
141
+ if (result === 'already-configured') {
142
+ shell.log(`${pkg.name}: npm trusted publisher is already configured; skipping.`);
143
+ }
106
144
  break;
107
145
  }
108
146
  catch (error) {
109
- console.error(`${pkg.name}: npm trusted publisher setup failed.`);
110
- console.error(error instanceof Error ? error.message : String(error));
147
+ shell.error(`${pkg.name}: npm trusted publisher setup failed.`);
148
+ shell.error(error instanceof Error ? error.message : String(error));
111
149
  if (!options.dryRun) {
112
- console.error('npm OTP codes are single-use. Generate a fresh OTP before retrying this package.');
150
+ shell.error('npm OTP codes are single-use. Generate a fresh OTP before retrying this package.');
113
151
  }
114
152
  if (options.otp || options.dryRun) {
115
153
  failedPackages.push(pkg.name);
116
154
  break;
117
155
  }
118
- console.error('Retrying this package. Press Ctrl-C to stop.');
156
+ shell.error('Retrying this package. Press Ctrl-C to stop.');
119
157
  }
120
158
  }
121
159
  }
122
160
  if (failedPackages.length > 0) {
123
- console.error(`Trusted publishing was not configured for: ${failedPackages.join(', ')}`);
161
+ shell.error(`Trusted publishing was not configured for: ${failedPackages.join(', ')}`);
124
162
  if (options.otp) {
125
- console.error('Rerun smoo release trust-publisher without --otp to enter a fresh OTP for each failed package.');
163
+ shell.error('Rerun smoo release trust-publisher without --otp to enter a fresh OTP for each failed package.');
126
164
  }
127
165
  }
128
166
  }
167
+ export async function releaseBootstrapNpmPackages(root, options) {
168
+ await bootstrapNpmPackages({
169
+ listReleasePackages: () => listReleasePackages(root),
170
+ packageExists: (name) => npmPackageExists(root, name),
171
+ login: () => runLatestNpm(root, ['login', '--auth-type=web']),
172
+ publishPlaceholder: (pkg, env) => publishPlaceholderPackage(root, pkg, env),
173
+ promptOtp: (packageName) => promptForNpmOtp(packageName),
174
+ log: (message) => console.log(message),
175
+ }, {
176
+ dryRun: options.dryRun === true,
177
+ skipLogin: options.skipLogin === true,
178
+ otp: options.otp,
179
+ packages: options.packages ?? [],
180
+ });
181
+ }
129
182
  export async function releaseRetagUnpublished(root, options) {
130
183
  const toRef = options.to ?? 'HEAD';
131
184
  const dispatch = options.dispatch === true;
@@ -159,15 +212,14 @@ async function listUnpublishedPackages(root, packages) {
159
212
  const states = await Promise.all(packages.map(async (pkg) => ({ pkg, published: await npmVersionExists(root, pkg.name, pkg.version) })));
160
213
  return states.filter((state) => !state.published).map((state) => state.pkg);
161
214
  }
162
- async function publishPackedPackage(root, pkg, tag, dryRun, useBootstrapToken) {
215
+ async function publishPackedPackage(root, pkg, tag, dryRun) {
163
216
  const tempDir = await mkdtemp(join(tmpdir(), 'smoo-publish-'));
164
217
  const tarball = join(tempDir, `${safeTarballPrefix(pkg.name)}-${pkg.version}.tgz`);
165
218
  try {
166
219
  console.log(`${pkg.name}@${pkg.version}: packing with bun pm pack`);
167
220
  await run('bun', ['pm', 'pack', '--filename', tarball, '--ignore-scripts', '--quiet'], join(root, pkg.path));
168
221
  await assertPackedWorkspaceDependencies(root, tarball, pkg);
169
- // npm CLI owns authentication here: trusted publishing OIDC when configured,
170
- // or the temporary NODE_AUTH_TOKEN bootstrap path below before trust exists.
222
+ // npm CLI owns authentication here: trusted publishing OIDC when configured.
171
223
  // Bun still produces the tarball so workspace:* dependencies are resolved the
172
224
  // same way smoo validates packed packages before release.
173
225
  const args = ['publish', tarball, '--access', 'public', '--tag', tag, '--provenance'];
@@ -175,7 +227,7 @@ async function publishPackedPackage(root, pkg, tag, dryRun, useBootstrapToken) {
175
227
  args.push('--dry-run');
176
228
  }
177
229
  await publishWithAuthDiagnostics(pkg, {
178
- publish: () => runLatestNpmPublish(root, args, useBootstrapToken),
230
+ publish: () => runLatestNpmPublish(root, args),
179
231
  versionExists: () => npmVersionExists(root, pkg.name, pkg.version),
180
232
  log: (message) => console.log(message),
181
233
  error: (message) => console.error(message),
@@ -186,7 +238,6 @@ async function publishPackedPackage(root, pkg, tag, dryRun, useBootstrapToken) {
186
238
  }
187
239
  },
188
240
  }, {
189
- useBootstrapToken,
190
241
  tokenPresent: npmAuthTokenPresent(),
191
242
  repository: githubRepositoryFromRootPackage(root),
192
243
  });
@@ -198,6 +249,24 @@ async function publishPackedPackage(root, pkg, tag, dryRun, useBootstrapToken) {
198
249
  function npmAuthTokenPresent() {
199
250
  return Boolean(process.env.NODE_AUTH_TOKEN || process.env.NPM_TOKEN || process.env.NPM_CONFIG_USERCONFIG);
200
251
  }
252
+ async function publishPlaceholderPackage(root, pkg, env) {
253
+ const tempDir = await mkdtemp(join(tmpdir(), 'smoo-npm-bootstrap-'));
254
+ try {
255
+ await writeFile(join(tempDir, 'package.json'), `${JSON.stringify({
256
+ name: pkg.name,
257
+ version: NPM_BOOTSTRAP_VERSION,
258
+ description: `Bootstrap placeholder for ${pkg.name}. Real releases are published by SmoothBricks CI.`,
259
+ license: stringProperty(pkg.json, 'license') ?? 'UNLICENSED',
260
+ repository: pkg.json.repository,
261
+ publishConfig: { access: 'public' },
262
+ }, null, 2)}\n`);
263
+ await writeFile(join(tempDir, 'README.md'), `# ${pkg.name}\n\nThis is a bootstrap placeholder. Real package versions are published by SmoothBricks release automation.\n`);
264
+ await runLatestNpm(root, ['publish', tempDir, '--access', 'public', '--tag', NPM_BOOTSTRAP_DIST_TAG], env);
265
+ }
266
+ finally {
267
+ await rm(tempDir, { recursive: true, force: true });
268
+ }
269
+ }
201
270
  function safeTarballPrefix(name) {
202
271
  return name.replace(/^@/, '').replace(/[^a-zA-Z0-9._-]+/g, '-');
203
272
  }
@@ -216,7 +285,20 @@ function releasePackages(root) {
216
285
  return packages;
217
286
  }
218
287
  function releasePackageProjects(packages) {
219
- return packages.map((pkg) => pkg.name).join(',');
288
+ return packages.map((pkg) => pkg.projectName).join(',');
289
+ }
290
+ async function releaseVersionPackages(root, packages, bump) {
291
+ if (bump !== 'auto') {
292
+ return packages;
293
+ }
294
+ return autoReleaseCandidatePackages({
295
+ gitRefExists: (ref) => gitRefExists(root, ref),
296
+ packageChangedFilesSince: (ref, packagePath) => packageChangedFilesSince(root, ref, packagePath),
297
+ packageJsonAtRef: (ref, packagePath) => packageJsonAtRef(root, ref, packagePath),
298
+ currentPackageJson: (packagePath) => currentPackageJson(root, packagePath),
299
+ packageBuildInputPatterns: (projectName, packagePath) => packageBuildInputPatterns(root, projectName, packagePath),
300
+ packageHasHistory: (packagePath) => packageHasHistory(root, packagePath),
301
+ }, packages);
220
302
  }
221
303
  async function runNxReleaseVersion(root, projects, bump, dryRun) {
222
304
  // Nx owns local release mutation: package versions, bun.lock updates, the
@@ -355,7 +437,10 @@ function releaseCompletionShell(root) {
355
437
  buildReleaseCandidate: (packages) => buildReleaseCandidate(root, packages),
356
438
  publishPackage: async (pkg, distTag, dryRun) => {
357
439
  const packageExists = dryRun ? true : await npmPackageExists(root, pkg.name);
358
- await publishPackedPackage(root, pkg, distTag, dryRun, !dryRun && !packageExists);
440
+ if (!packageExists) {
441
+ throw new Error(missingNpmPackagePublishGuidance(pkg));
442
+ }
443
+ await publishPackedPackage(root, pkg, distTag, dryRun);
359
444
  },
360
445
  listGithubMissingPackages: (packages) => listMissingGithubReleasePackages(root, packages),
361
446
  createGithubRelease: (pkg, dryRun) => createGithubRelease(root, pkg, dryRun),
@@ -538,6 +623,125 @@ async function gitRefExists(root, ref) {
538
623
  const result = await $ `git rev-parse --verify ${ref}`.cwd(root).quiet().nothrow();
539
624
  return result.exitCode === 0;
540
625
  }
626
+ async function packageChangedFilesSince(root, ref, packagePath) {
627
+ const result = await $ `git diff --name-only ${`${ref}..HEAD`} -- ${packagePath}`.cwd(root).quiet().nothrow();
628
+ if (result.exitCode !== 0) {
629
+ throw new Error(`Unable to inspect package changes under ${packagePath}.`);
630
+ }
631
+ const packagePrefix = `${packagePath}/`;
632
+ return decode(result.stdout)
633
+ .split('\n')
634
+ .map((path) => path.trim())
635
+ .filter(Boolean)
636
+ .map((path) => (path.startsWith(packagePrefix) ? path.slice(packagePrefix.length) : path));
637
+ }
638
+ async function packageJsonAtRef(root, ref, packagePath) {
639
+ const result = await $ `git show ${`${ref}:${packagePath}/package.json`}`.cwd(root).quiet().nothrow();
640
+ if (result.exitCode !== 0) {
641
+ return null;
642
+ }
643
+ try {
644
+ const parsed = JSON.parse(decode(result.stdout));
645
+ return isRecord(parsed) ? parsed : null;
646
+ }
647
+ catch {
648
+ return null;
649
+ }
650
+ }
651
+ async function currentPackageJson(root, packagePath) {
652
+ return readPackageJson(join(root, packagePath, 'package.json'))?.json ?? null;
653
+ }
654
+ async function packageBuildInputPatterns(root, projectName, _packagePath) {
655
+ const project = await nxProjectJson(root, projectName);
656
+ const nxJson = readJsonObject(join(root, 'nx.json')) ?? {};
657
+ return resolveBuildInputPatterns(project, nxJson);
658
+ }
659
+ async function nxProjectJson(root, projectName) {
660
+ const result = await $ `nx show project ${projectName} --json`.cwd(root).quiet();
661
+ const parsed = JSON.parse(decode(result.stdout));
662
+ if (!isRecord(parsed)) {
663
+ throw new Error(`Unable to inspect Nx project ${projectName}.`);
664
+ }
665
+ return parsed;
666
+ }
667
+ function resolveBuildInputPatterns(project, nxJson) {
668
+ const targets = recordProperty(project, 'targets');
669
+ if (!targets) {
670
+ return [];
671
+ }
672
+ return normalizeInputPatterns(collectBuildInputs(targets), nxJson);
673
+ }
674
+ function collectBuildInputs(targets) {
675
+ const build = recordProperty(targets, 'build');
676
+ if (!build) {
677
+ return ['production'];
678
+ }
679
+ const directInputs = stringArrayProperty(build, 'inputs');
680
+ if (directInputs.length > 0) {
681
+ return directInputs;
682
+ }
683
+ const inputs = [];
684
+ for (const dependency of stringArrayProperty(build, 'dependsOn')) {
685
+ if (dependency.startsWith('^')) {
686
+ continue;
687
+ }
688
+ const targetName = dependency.includes(':') ? dependency.split(':')[1] : dependency;
689
+ if (!targetName) {
690
+ continue;
691
+ }
692
+ inputs.push(...stringArrayProperty(recordProperty(targets, targetName), 'inputs'));
693
+ }
694
+ return inputs.length > 0 ? inputs : ['production'];
695
+ }
696
+ function normalizeInputPatterns(inputs, nxJson) {
697
+ const patterns = [];
698
+ const seen = new Set();
699
+ for (const input of inputs) {
700
+ for (const pattern of expandInputPattern(input, nxJson, seen)) {
701
+ patterns.push(pattern);
702
+ }
703
+ }
704
+ return patterns;
705
+ }
706
+ function expandInputPattern(input, nxJson, seen) {
707
+ if (seen.has(input)) {
708
+ return [];
709
+ }
710
+ seen.add(input);
711
+ if (!input.includes('{')) {
712
+ const namedInputs = recordProperty(nxJson, 'namedInputs');
713
+ const namedInput = namedInputs?.[input];
714
+ if (Array.isArray(namedInput)) {
715
+ return namedInput.flatMap((entry) => (typeof entry === 'string' ? expandInputPattern(entry, nxJson, seen) : []));
716
+ }
717
+ return [];
718
+ }
719
+ const excluded = input.startsWith('!');
720
+ const rawInput = excluded ? input.slice(1) : input;
721
+ if (!rawInput.startsWith('{projectRoot}/')) {
722
+ return [];
723
+ }
724
+ const packageRelative = rawInput.slice('{projectRoot}/'.length);
725
+ return [`${excluded ? '!' : ''}${packageRelative}`];
726
+ }
727
+ function recordProperty(record, key) {
728
+ if (!record) {
729
+ return null;
730
+ }
731
+ const value = record[key];
732
+ return isRecord(value) ? value : null;
733
+ }
734
+ function stringArrayProperty(record, key) {
735
+ const value = record?.[key];
736
+ return Array.isArray(value) ? value.filter((entry) => typeof entry === 'string') : [];
737
+ }
738
+ async function packageHasHistory(root, packagePath) {
739
+ const result = await $ `git log --format=%H -- ${packagePath}`.cwd(root).quiet().nothrow();
740
+ if (result.exitCode !== 0) {
741
+ throw new Error(`Unable to inspect package history under ${packagePath}.`);
742
+ }
743
+ return decode(result.stdout).trim().length > 0;
744
+ }
541
745
  async function gitIsAncestor(root, ancestor, descendant) {
542
746
  const result = await $ `git merge-base --is-ancestor ${ancestor} ${descendant}`.cwd(root).quiet().nothrow();
543
747
  return result.exitCode === 0;
@@ -712,28 +916,22 @@ function githubRepositoryFromUrl(url) {
712
916
  async function runLatestNpm(root, npmArgs, env) {
713
917
  await run('nix', ['shell', 'nixpkgs#nodejs_latest', '-c', 'npm', ...npmArgs], root, env);
714
918
  }
715
- async function runLatestNpmPublish(root, npmArgs, useBootstrapToken) {
716
- if (!useBootstrapToken) {
717
- await runLatestNpm(root, npmArgs, { NODE_AUTH_TOKEN: '', NPM_TOKEN: '' });
718
- return;
719
- }
720
- const token = process.env.NODE_AUTH_TOKEN || process.env.NPM_TOKEN;
721
- if (!token || process.env.NPM_CONFIG_USERCONFIG) {
722
- if (!token && !process.env.NPM_CONFIG_USERCONFIG) {
723
- throw new Error('First publish for a package requires NODE_AUTH_TOKEN or NPM_TOKEN until trusted publishing exists.');
724
- }
725
- await runLatestNpm(root, npmArgs);
726
- return;
727
- }
728
- const tempDir = await mkdtemp(join(tmpdir(), 'smoo-npm-auth-'));
729
- const npmrc = join(tempDir, '.npmrc');
730
- try {
731
- await writeFile(npmrc, `registry=https://registry.npmjs.org/\n//registry.npmjs.org/:_authToken=${token}\n`);
732
- await runLatestNpm(root, npmArgs, { NPM_CONFIG_USERCONFIG: npmrc });
919
+ async function runLatestNpmTrust(root, npmArgs, env) {
920
+ const result = await runResult('nix', ['shell', 'nixpkgs#nodejs_latest', '-c', 'npm', ...npmArgs], root, env);
921
+ if (result.exitCode === 0) {
922
+ return 'configured';
733
923
  }
734
- finally {
735
- await rm(tempDir, { recursive: true, force: true });
924
+ const output = `${result.stdout}\n${result.stderr}`;
925
+ if (/\bE409\b|\b409 Conflict\b/.test(output)) {
926
+ return 'already-configured';
736
927
  }
928
+ throw new Error(`nix shell nixpkgs#nodejs_latest -c npm ${npmArgs.join(' ')} failed with exit code ${result.exitCode}`);
929
+ }
930
+ async function runLatestNpmPublish(root, npmArgs) {
931
+ await runLatestNpm(root, npmArgs, { NODE_AUTH_TOKEN: '', NPM_TOKEN: '' });
932
+ }
933
+ function missingNpmPackagePublishGuidance(pkg) {
934
+ return `${pkg.name} does not exist on npm yet. Run smoo release trust-publisher --bootstrap locally before rerunning the Publish workflow.`;
737
935
  }
738
936
  async function promptForNpmOtp(packageName) {
739
937
  if (!process.stdin.isTTY || !process.stdout.isTTY) {
@@ -1,6 +1,5 @@
1
1
  import type { ReleasePackageInfo } from './core.js';
2
2
  export interface NpmPublishAuthFailureOptions {
3
- useBootstrapToken: boolean;
4
3
  tokenPresent: boolean;
5
4
  repository?: string;
6
5
  }
@@ -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,iBAAiB,EAAE,OAAO,CAAC;IAC3B,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,CAuCR;AAED,wBAAgB,6BAA6B,CAC3C,GAAG,EAAE,IAAI,CAAC,kBAAkB,EAAE,MAAM,GAAG,SAAS,CAAC,EACjD,OAAO,EAAE,4BAA4B,GACpC,MAAM,CAgCR"}
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"}
@@ -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 after the package exists on npm; see the warning banner above for details.`, { cause: error });
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, or the bootstrap NPM_TOKEN is missing/invalid.`,
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, add a temporary NPM_TOKEN repository secret, publish once, then run smoo release trust-publisher.');
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, add a temporary `NPM_TOKEN` repository secret, publish once, then run `smoo release trust-publisher`.');
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) {
@@ -28,9 +28,10 @@ export interface ReleaseRepairShell<Package extends ReleasePackageInfo = Release
28
28
  }
29
29
  export interface ReleaseVersionShell<Package extends ReleasePackageInfo = ReleasePackageInfo> {
30
30
  releasePackagesAtHead(): Promise<Package[]>;
31
+ releaseVersionPackages(bump: string): Promise<Package[]>;
31
32
  ensureLocalReleaseTags(packages: Package[]): Promise<void>;
32
33
  gitHead(): Promise<string>;
33
- runNxReleaseVersion(bump: string, dryRun: boolean): Promise<void>;
34
+ runNxReleaseVersion(packages: Package[], bump: string, dryRun: boolean): Promise<void>;
34
35
  assertCleanGitTree(): Promise<void>;
35
36
  }
36
37
  export interface ReleaseVersionResult<Package extends ReleasePackageInfo = ReleasePackageInfo> {
@@ -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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"}
@@ -7,8 +7,16 @@ 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
+ await shell.runNxReleaseVersion(versionPackages, options.bump, options.dryRun);
12
20
  if (options.dryRun) {
13
21
  return { mode: 'none', packages: [], status: 'dry-run' };
14
22
  }
@@ -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.name),
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
@@ -6,4 +6,4 @@ export PATH="$TOOLING/git-hooks:$TOOLING:$PWD/node_modules/.bin:$TOOLING/direnv/
6
6
 
7
7
  set -e -o pipefail
8
8
 
9
- smoo monorepo validate-commit-msg "$1"
9
+ smoo monorepo validate-commit-msg --fix "$1"
@@ -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-installer-action@v22
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
@@ -18,6 +18,7 @@ defaults:
18
18
  jobs:
19
19
  main:
20
20
  runs-on: ubuntu-latest
21
+ timeout-minutes: 45
21
22
  env:
22
23
  NIX_STORE_NAR: ${{ github.workspace }}/nix-store.nar
23
24
  GH_TOKEN: ${{ github.token }}