@smoothbricks/cli 0.11.16 → 0.11.17

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 (49) hide show
  1. package/README.md +43 -0
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +44 -0
  4. package/dist/github-ci/index.d.ts +1 -1
  5. package/dist/github-ci/index.d.ts.map +1 -1
  6. package/dist/github-ci/index.js +7 -10
  7. package/dist/lib/secret-names.d.ts +35 -0
  8. package/dist/lib/secret-names.d.ts.map +1 -0
  9. package/dist/lib/secret-names.js +61 -0
  10. package/dist/monorepo/ci-workflow.d.ts.map +1 -1
  11. package/dist/monorepo/ci-workflow.js +15 -6
  12. package/dist/monorepo/publish-workflow.d.ts +10 -1
  13. package/dist/monorepo/publish-workflow.d.ts.map +1 -1
  14. package/dist/monorepo/publish-workflow.js +58 -20
  15. package/dist/secrets/commands.d.ts +45 -0
  16. package/dist/secrets/commands.d.ts.map +1 -0
  17. package/dist/secrets/commands.js +189 -0
  18. package/dist/secrets/index.d.ts +83 -0
  19. package/dist/secrets/index.d.ts.map +1 -0
  20. package/dist/secrets/index.js +149 -0
  21. package/dist/wrangler/deploy-stage.d.ts +13 -2
  22. package/dist/wrangler/deploy-stage.d.ts.map +1 -1
  23. package/dist/wrangler/deploy-stage.js +39 -54
  24. package/dist/wrangler/deployed-version.d.ts +44 -0
  25. package/dist/wrangler/deployed-version.d.ts.map +1 -0
  26. package/dist/wrangler/deployed-version.js +87 -0
  27. package/dist/wrangler/live-version.d.ts +146 -0
  28. package/dist/wrangler/live-version.d.ts.map +1 -0
  29. package/dist/wrangler/live-version.js +326 -0
  30. package/package.json +2 -2
  31. package/src/cli.ts +46 -1
  32. package/src/github-ci/index.test.ts +92 -8
  33. package/src/github-ci/index.ts +7 -10
  34. package/src/lib/secret-names.ts +70 -0
  35. package/src/monorepo/__tests__/ci-workflow.test.ts +27 -2
  36. package/src/monorepo/__tests__/publish-workflow.test.ts +33 -15
  37. package/src/monorepo/ci-workflow.ts +17 -6
  38. package/src/monorepo/managed-files.test.ts +1 -1
  39. package/src/monorepo/publish-workflow.ts +65 -19
  40. package/src/monorepo/secret-references.test.ts +1 -1
  41. package/src/release/__tests__/private-npm-status.test.ts +2 -2
  42. package/src/secrets/commands.ts +210 -0
  43. package/src/secrets/index.test.ts +92 -0
  44. package/src/secrets/index.ts +183 -0
  45. package/src/wrangler/deploy-stage.test.ts +190 -12
  46. package/src/wrangler/deploy-stage.ts +72 -45
  47. package/src/wrangler/deployed-version.test.ts +150 -0
  48. package/src/wrangler/deployed-version.ts +130 -0
  49. package/src/wrangler/live-version.ts +363 -0
package/README.md CHANGED
@@ -428,6 +428,49 @@ that runs after Validate and the e2e job succeed on a push to the staging push b
428
428
  stage-derived — carry `stage-deploy-target` or deploy through `smoo wrangler deploy-stage` — otherwise `--select-tag`
429
429
  finds nothing and the job logs `No run-many deploy projects; skipping production.`
430
430
 
431
+ #### Ordering one deploy after another
432
+
433
+ When a project's deploy calls into what another project deploys — a site that signs in to its stage's backend — say so
434
+ with an ordinary Nx edge on the deploying project:
435
+
436
+ ```json
437
+ { "nx": { "targets": { "deploy": { "dependsOn": ["...", "app-backend:deploy"] } } } }
438
+ ```
439
+
440
+ Nx then orders it, at any depth: `site:deploy` after `app-backend:deploy` after `db:deploy` all resolve inside the one
441
+ `nx run-many` that `smoo github-ci nx-deploy` already issues, and `nx deploy site --stage=…` run by hand gets the same
442
+ order. Keep the leading `"..."`: it expands the `deploy-build` edge the plugin infers (below), which a bare list would
443
+ drop.
444
+
445
+ What makes the edge safe is that a deploy is never cached and always cheap when there is nothing to do:
446
+
447
+ - `@smoothbricks/nx-plugin` gives every declared `deploy` target `cache: false`. An Nx cache hit on a deploy means "we
448
+ once uploaded this hash", which a rollback silently falsifies — the workspace is unchanged, so the hash is unchanged,
449
+ so a cached deploy would report success while the previous version keeps serving.
450
+ - `smoo wrangler deploy-stage` reads live state first. If the version tagged with this task's hash is already the one
451
+ serving 100% of traffic, it returns `remote-cache-hit` after two API calls: no upload, no migration, no traffic shift.
452
+ - The expensive, purely file-derived half belongs in a sibling `deploy-build` target (build the artifact, register it,
453
+ refresh what the build needs). The plugin gives that one `cache: true` and makes `deploy` depend on it, so a redundant
454
+ deploy costs two API calls rather than a rebuild.
455
+ - A deploy does not finish when Cloudflare accepts the traffic shift; it finishes when the new version is the one being
456
+ served. `deploy-stage` polls `wrangler deployments status` until the tag it activated is live, and fails with what it
457
+ expected and what it saw if that never happens. Pass `--version-endpoint <url>` to also require an endpoint served by
458
+ the worker — whose trimmed response body is the running version tag — to answer with it. Without that wait, an edge
459
+ onto a deploy orders nothing: the step returns while the edge still serves the old code.
460
+
461
+ **The policy caveat, plainly.** A cross-project edge is part of the graph, not of the selection: a run that selects only
462
+ the dependent project will still evaluate the dependency's `deploy`. When the dependency is already at that hash, that
463
+ evaluation is a no-op — two API calls. But it is not inert: if the dependency is intentionally behind (its production
464
+ deploy is being held back, say), a run that selects only the dependent project **will advance the dependency to the hash
465
+ the current workspace produces**. If you need a project to be deployable without touching what it depends on, do not add
466
+ the edge; sequence those two deploys as separate CI jobs instead.
467
+
468
+ `smoo wrangler deployed-version --stage <stage>` prints the tag serving all traffic for the project's worker on that
469
+ stage, so an operator can check the same fact the deploy checks. It caches its answer briefly under Nx's workspace data
470
+ directory; that cache is a convenience for repeated queries only. Nothing that decides whether to deploy reads it, and
471
+ it refuses — rather than answering `unknown` — without credentials, on an API error, or while traffic is split between
472
+ two versions.
473
+
431
474
  Pushes to the staging push branch queue behind a running workflow instead of canceling it, so a newer push never cancels
432
475
  a production deployment mid-flight. Pull requests and other branches keep canceling superseded runs. The e2e and
433
476
  production jobs repeat the Cargo credential and sibling-source preflight before SetupDevenv, so their `--step` anchors
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAWA,wBAAsB,MAAM,CAAC,IAAI,WAAwB,GAAG,OAAO,CAAC,IAAI,CAAC,CAcxE;AAQD,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAiBhD"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAaA,wBAAsB,MAAM,CAAC,IAAI,WAAwB,GAAG,OAAO,CAAC,IAAI,CAAC,CAcxE;AAQD,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAiBhD"}
package/dist/cli.js CHANGED
@@ -6,7 +6,9 @@ import { cliPackageVersion } from './lib/cli-package.js';
6
6
  import { decode, findRepoRoot, printCommandOutput } from './lib/run.js';
7
7
  import { ensureChromium } from './playwright/index.js';
8
8
  import { resolvePrConflicts } from './pr/index.js';
9
+ import { secretsSet, secretsStatus, secretsSync } from './secrets/commands.js';
9
10
  import { cleanupPullRequest, deployStage } from './wrangler/deploy-stage.js';
11
+ import { deployedVersion } from './wrangler/deployed-version.js';
10
12
  import { scaffold } from './wrangler/scaffold.js';
11
13
  export async function runCli(argv = process.argv.slice(2)) {
12
14
  const program = buildProgram();
@@ -420,6 +422,30 @@ function buildProgram() {
420
422
  .action(async () => {
421
423
  await ensureChromium();
422
424
  });
425
+ const secrets = program
426
+ .command('secrets')
427
+ .description('Reconcile declared secrets: what Workers need, what workflows pass, what the repository holds');
428
+ secrets
429
+ .command('status')
430
+ .description('Show every declared secret and refuse when a workflow passes one the repository lacks')
431
+ .option('--repo <owner/name>', 'repository to read secrets from; defaults to the current checkout')
432
+ .action(async (options) => {
433
+ process.exitCode = secretsStatus(await findRepoRoot(), options);
434
+ });
435
+ secrets
436
+ .command('set <name>')
437
+ .description('Set one repository secret from a pasted value; the value is read without echo and never logged')
438
+ .option('--repo <owner/name>', 'repository to set the secret on')
439
+ .action(async (name, options) => {
440
+ process.exitCode = await secretsSet(name, options);
441
+ });
442
+ secrets
443
+ .command('sync')
444
+ .description('Push every secret smoo.secrets can fetch locally to the repository')
445
+ .option('--repo <owner/name>', 'repository to set the secrets on')
446
+ .action(async (options) => {
447
+ process.exitCode = await secretsSync(await findRepoRoot(), options);
448
+ });
423
449
  const wrangler = program.command('wrangler').description('Cloudflare wrangler project helpers');
424
450
  wrangler
425
451
  .command('scaffold <project>')
@@ -432,11 +458,29 @@ function buildProgram() {
432
458
  .command('deploy-stage')
433
459
  .requiredOption('--stage <stage>', 'staging, production, or prN')
434
460
  .option('--config <path>', 'deploy a build-generated flat wrangler.json instead of ./wrangler.toml')
461
+ .option('--version-endpoint <url>', 'URL served by this worker whose trimmed body is the running version tag')
435
462
  .action(async (options) => {
436
463
  await deployStage(process.cwd(), {
437
464
  stage: options.stage,
438
465
  ...(options.config ? { config: resolve(options.config) } : {}),
466
+ ...(options.versionEndpoint ? { versionEndpoint: options.versionEndpoint } : {}),
467
+ });
468
+ });
469
+ wrangler
470
+ .command('deployed-version')
471
+ .description('Print the version tag serving all traffic for this project\u2019s worker on a stage')
472
+ .requiredOption('--stage <stage>', 'staging, production, or prN')
473
+ .option('--config <path>', 'resolve the worker name from a build-generated flat wrangler.json')
474
+ .option('--refresh', 'ask Cloudflare even when a fresh cached answer exists')
475
+ .action(async (options) => {
476
+ const report = await deployedVersion(process.cwd(), {
477
+ stage: options.stage,
478
+ ...(options.config ? { config: resolve(options.config) } : {}),
479
+ ...(options.refresh ? { refresh: true } : {}),
439
480
  });
481
+ // The tag alone on stdout: this is read by humans and by `$(...)`, and a version deployed
482
+ // outside Nx genuinely has no tag, which `untagged` says without pretending to be one.
483
+ console.log(report.versionTag ?? 'untagged');
440
484
  });
441
485
  wrangler
442
486
  .command('cleanup-pr')
@@ -68,7 +68,7 @@ export interface GithubCiNxDeployOptions {
68
68
  selectTag?: string;
69
69
  }
70
70
  export interface GithubCiNxDeployDependencies {
71
- listProjects?: (root: string, target: string, mode: 'affected' | 'run-many', stage: DeploymentStage, selectTag?: string) => Promise<string[]>;
71
+ listProjects?: (root: string, mode: 'affected' | 'run-many', stage: DeploymentStage, selectTag?: string) => Promise<string[]>;
72
72
  runNx?: (args: string[], root: string) => Promise<number>;
73
73
  appendSummary?: (summaryPath: string, content: string) => Promise<void>;
74
74
  appendOutput?: (outputPath: string, content: string) => Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/github-ci/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/github-ci/index.ts"],"names":[],"mappings":"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"}
@@ -260,9 +260,9 @@ export async function githubCiNxDeploy(root, options, dependencies = {}) {
260
260
  const setStatus = dependencies.setStatus ??
261
261
  ((state) => state === 'pending' ? createGithubStatus(name, step) : updateGithubStatus(name, state, step));
262
262
  const mode = resolveNxSmartMode(options.mode ?? 'run-many');
263
- const listProjects = dependencies.listProjects ?? listNxProjectsWithTarget;
263
+ const listProjects = dependencies.listProjects ?? listNxDeployProjects;
264
264
  const runNx = dependencies.runNx ?? ((args, commandRoot) => runStatus('nx', args, commandRoot));
265
- const projects = await listProjects(root, 'deploy', mode, stage, options.selectTag);
265
+ const projects = await listProjects(root, mode, stage, options.selectTag);
266
266
  if (projects.length === 0) {
267
267
  console.log(`No ${mode} deploy projects; skipping ${stage}.`);
268
268
  await setStatus('pending');
@@ -275,8 +275,8 @@ export async function githubCiNxDeploy(root, options, dependencies = {}) {
275
275
  ? { stage, urls: previewUrlsForStage(github?.previewUrls, stage) }
276
276
  : undefined;
277
277
  await setStatus('pending');
278
- const projectList = projects.join(',');
279
278
  const targets = options.verify === true ? ['build', 'lint', 'test', 'deploy'] : ['deploy'];
279
+ const projectList = projects.join(',');
280
280
  for (const target of targets) {
281
281
  const nxArgs = [
282
282
  'run-many',
@@ -286,6 +286,8 @@ export async function githubCiNxDeploy(root, options, dependencies = {}) {
286
286
  `--exclude=${deployExclusions(stage)}`,
287
287
  `--parallel=${NX_PARALLEL}`,
288
288
  ];
289
+ // Deploy ordering is a `dependsOn` edge in the project graph, not a second round here: one run-many
290
+ // already sequences any depth of `a:deploy -> b:deploy -> c:deploy`.
289
291
  if (target === 'deploy') {
290
292
  nxArgs.push(`--stage=${stage}`);
291
293
  }
@@ -413,17 +415,12 @@ function previewUrlFromTemplate(template, stage) {
413
415
  throw new Error(`preview URL template "${template}" must contain {stage}`);
414
416
  return template.replaceAll('{stage}', stage);
415
417
  }
416
- async function listNxProjectsWithTarget(root, target, mode, stage, selectTag) {
418
+ async function listNxDeployProjects(root, mode, stage, selectTag) {
417
419
  const listArgs = ['show', 'projects'];
418
420
  if (mode === 'affected')
419
421
  listArgs.push('--affected');
420
- listArgs.push('--withTarget', target);
421
- if (target === 'deploy')
422
- listArgs.push(`--exclude=${deployExclusions(stage)}`);
423
- listArgs.push('--json');
422
+ listArgs.push('--withTarget', 'deploy', `--exclude=${deployExclusions(stage)}`, '--json');
424
423
  const candidates = nxProjectList(await runText('nx', listArgs, root)).sort((left, right) => left.localeCompare(right));
425
- if (target !== 'deploy')
426
- return candidates;
427
424
  return selectStageDeployProjects(candidates, stage, selectTag, async (project) => {
428
425
  const parsed = parseNxProjectDeployTarget(await runText('nx', ['show', 'project', project, '--json'], root));
429
426
  if (!parsed)
@@ -0,0 +1,35 @@
1
+ /**
2
+ * One rule for naming the repository secret behind an environment variable, so
3
+ * the workflow renderer, the reconciler and an operator all derive the same
4
+ * name instead of maintaining a map.
5
+ *
6
+ * GitHub refuses to create a secret whose name starts with `GITHUB_` (hence
7
+ * `RepositorySecretName`'s pattern), which is why a Worker's
8
+ * `GITHUB_CLIENT_SECRET` cannot be stored under its own name. Prefixing with
9
+ * the repository owner is the workaround operators already reach for by hand
10
+ * (`ACME_GITHUB_CLIENT_SECRET` for `acme/app`); making it the convention means
11
+ * nothing has to declare it.
12
+ */
13
+ /** Names GitHub reserves: it rejects `gh secret set GITHUB_*` outright. */
14
+ export declare function isReservedRepositorySecretName(envName: string): boolean;
15
+ /**
16
+ * The repository secret an env name lives in. Identity for every name GitHub
17
+ * accepts; owner-prefixed for the reserved ones. `owner` comes from the
18
+ * repository URL, so a fork or a rename derives its own names rather than
19
+ * inheriting a hardcoded prefix.
20
+ */
21
+ export declare function conventionalRepositorySecretName(envName: string, owner: string): string;
22
+ /**
23
+ * Resolve the whole env -> secret mapping for a set of declared env names.
24
+ * Explicit entries win: an exception stays expressible, but a repository that
25
+ * follows the convention declares nothing.
26
+ */
27
+ export declare function repositorySecretMapping(envNames: readonly string[], owner: string, declared?: Readonly<Record<string, string>>): Record<string, string>;
28
+ /**
29
+ * Repository owner from a repository URL — `acme` from
30
+ * `https://github.com/acme/app.git`, and the same for an ssh or forge
31
+ * URL. The owner is derived rather than configured so a fork or a rename
32
+ * carries its own prefix instead of inheriting one.
33
+ */
34
+ export declare function repositoryOwnerFromUrl(url: string): string | null;
35
+ //# sourceMappingURL=secret-names.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secret-names.d.ts","sourceRoot":"","sources":["../../src/lib/secret-names.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,2EAA2E;AAC3E,wBAAgB,8BAA8B,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEvE;AAED;;;;;GAKG;AACH,wBAAgB,gCAAgC,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAYvF;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,SAAS,MAAM,EAAE,EAC3B,KAAK,EAAE,MAAM,EACb,QAAQ,GAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAM,GAC9C,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CASxB;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAKjE"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * One rule for naming the repository secret behind an environment variable, so
3
+ * the workflow renderer, the reconciler and an operator all derive the same
4
+ * name instead of maintaining a map.
5
+ *
6
+ * GitHub refuses to create a secret whose name starts with `GITHUB_` (hence
7
+ * `RepositorySecretName`'s pattern), which is why a Worker's
8
+ * `GITHUB_CLIENT_SECRET` cannot be stored under its own name. Prefixing with
9
+ * the repository owner is the workaround operators already reach for by hand
10
+ * (`ACME_GITHUB_CLIENT_SECRET` for `acme/app`); making it the convention means
11
+ * nothing has to declare it.
12
+ */
13
+ /** Names GitHub reserves: it rejects `gh secret set GITHUB_*` outright. */
14
+ export function isReservedRepositorySecretName(envName) {
15
+ return /^GITHUB_/i.test(envName);
16
+ }
17
+ /**
18
+ * The repository secret an env name lives in. Identity for every name GitHub
19
+ * accepts; owner-prefixed for the reserved ones. `owner` comes from the
20
+ * repository URL, so a fork or a rename derives its own names rather than
21
+ * inheriting a hardcoded prefix.
22
+ */
23
+ export function conventionalRepositorySecretName(envName, owner) {
24
+ if (!isReservedRepositorySecretName(envName))
25
+ return envName;
26
+ const prefix = owner
27
+ .replace(/[^A-Za-z0-9]+/g, '_')
28
+ .replace(/^_+|_+$/g, '')
29
+ .toUpperCase();
30
+ if (prefix.length === 0) {
31
+ throw new Error(`Cannot derive a repository secret name for ${envName}: GitHub reserves the GITHUB_ prefix and the repository owner is empty.`);
32
+ }
33
+ return `${prefix}_${envName}`;
34
+ }
35
+ /**
36
+ * Resolve the whole env -> secret mapping for a set of declared env names.
37
+ * Explicit entries win: an exception stays expressible, but a repository that
38
+ * follows the convention declares nothing.
39
+ */
40
+ export function repositorySecretMapping(envNames, owner, declared = {}) {
41
+ const mapping = {};
42
+ for (const envName of [...envNames].sort((left, right) => left.localeCompare(right))) {
43
+ mapping[envName] = declared[envName] ?? conventionalRepositorySecretName(envName, owner);
44
+ }
45
+ for (const [envName, secretName] of Object.entries(declared)) {
46
+ mapping[envName] = secretName;
47
+ }
48
+ return mapping;
49
+ }
50
+ /**
51
+ * Repository owner from a repository URL — `acme` from
52
+ * `https://github.com/acme/app.git`, and the same for an ssh or forge
53
+ * URL. The owner is derived rather than configured so a fork or a rename
54
+ * carries its own prefix instead of inheriting one.
55
+ */
56
+ export function repositoryOwnerFromUrl(url) {
57
+ const withoutProtocol = url.replace(/^[a-z+]+:\/\//i, '').replace(/^git@/i, '');
58
+ const path = withoutProtocol.replace(/^[^/:]+[/:]/, '');
59
+ const owner = path.split('/')[0];
60
+ return owner && owner.length > 0 ? owner.replace(/\.git$/i, '') : null;
61
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"ci-workflow.d.ts","sourceRoot":"","sources":["../../src/monorepo/ci-workflow.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ci-workflow.d.ts","sourceRoot":"","sources":["../../src/monorepo/ci-workflow.ts"],"names":[],"mappings":"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"}
@@ -64,12 +64,19 @@ permissions:
64
64
  ${options.deploy ? ' deployments: write\n' : ''} statuses: write
65
65
 
66
66
  concurrency:
67
- # One in-flight run per ref. Pushes to the staging push branch queue behind a
68
- # running workflow instead of canceling it, so a newer push never cancels a
69
- # production deployment mid-flight. Pull requests and other branches keep
70
- # canceling superseded runs.
67
+ ${options.deploy
68
+ ? ` # One in-flight run per ref. Pushes to the staging push branch queue behind a
69
+ # running workflow instead of canceling it, so a newer push never cancels the
70
+ # deploy job mid-flight. Pull requests and other branches keep canceling
71
+ # superseded runs.
71
72
  group: \${{ github.workflow }}-\${{ github.ref }}
72
- cancel-in-progress: \${{ github.ref != ${stagingRefLiteral(options)} }}
73
+ cancel-in-progress: \${{ github.ref != ${stagingRefLiteral(options)} }}`
74
+ : ` # This workflow validates and never deploys, so there is no in-flight
75
+ # deployment for a newer push to protect: every ref cancels its superseded
76
+ # runs. Queuing them instead serializes the staging branch, and a burst of
77
+ # pushes then reports the newest commit one full run per queued push late.
78
+ group: \${{ github.workflow }}-\${{ github.ref }}
79
+ cancel-in-progress: true`}
73
80
 
74
81
  defaults:
75
82
  run:
@@ -828,6 +835,7 @@ function renderProductionDeployJob(options) {
828
835
  needs: ${needs}
829
836
  ${renderRunsOnLine(options.runsOn)}
830
837
  timeout-minutes: 30
838
+ # prettier-ignore
831
839
  if: \${{ !cancelled() && github.event_name == 'push' && github.ref == ${stagingRefLiteral(options)} && needs.main.result == 'success'${e2eGate} }}
832
840
  ${environmentLine(options.environments?.production)} env:
833
841
  GH_TOKEN: \${{ github.token }}
@@ -835,7 +843,8 @@ ${remoteCacheJobEnvLines(options.remoteCache)}${cargoCredentialJobEnvLines(optio
835
843
  ${renderCiWorkflowSteps(followUpSetupSteps(options, numbers), options)}
836
844
  # Step ${numbers.middle}
837
845
  - name: 🚀 Deploy Production
838
- ${renderOptionalLines(deployStepSecretEnvLines(options))} run: smoo github-ci nx-deploy --stage production --mode run-many --select-tag ${PRODUCTION_PUSH_DEPLOY_TAG} --name "Deploy Production" --step ${numbers.middle}
846
+ ${renderOptionalLines(deployStepSecretEnvLines(options))} # prettier-ignore
847
+ run: smoo github-ci nx-deploy --stage production --mode run-many --select-tag ${PRODUCTION_PUSH_DEPLOY_TAG} --name "Deploy Production" --step ${numbers.middle}
839
848
 
840
849
  ${renderCiWorkflowSteps(followUpCleanupStep(numbers), options)}`;
841
850
  }
@@ -2,7 +2,7 @@ import type { PackageCargoCredentialsConfig, PackagePrivateNpmConfig, PackageRem
2
2
  import { type DeployStepSecretConfig } from './ci-workflow.js';
3
3
  import { type WorkflowRunsOn } from './github-runs-on.js';
4
4
  export type PublishWorkflowBump = 'auto' | 'patch' | 'minor' | 'major' | 'prerelease';
5
- export type PublishWorkflowCondition = 'version-mode-not-none' | 'deploy-production' | 'deploy-production-standalone' | 'failure' | 'always';
5
+ export type PublishWorkflowCondition = 'plan-mode-not-none' | 'version-mode-not-none' | 'deploy-production' | 'deploy-production-standalone' | 'failure' | 'always';
6
6
  export type PublishWorkflowNxTarget = 'build' | 'lint' | 'test';
7
7
  export type PublishWorkflowDeployStage = 'none' | 'production';
8
8
  export declare enum PublishWorkflowStepKind {
@@ -13,6 +13,7 @@ export declare enum PublishWorkflowStepKind {
13
13
  ConfigureReleaseAuthor = "configure-release-author",
14
14
  BuildNxVersionActions = "build-nx-version-actions",
15
15
  RepairPendingReleases = "repair-pending-releases",
16
+ PlanRelease = "plan-release",
16
17
  VersionRelease = "version-release",
17
18
  CheckManagedMonorepoFiles = "check-managed-monorepo-files",
18
19
  Build = "build",
@@ -105,6 +106,14 @@ export interface PublishWorkflowCallbacks {
105
106
  bump: PublishWorkflowBump;
106
107
  dryRun: boolean;
107
108
  }): Promise<PublishWorkflowVersionOutputs>;
109
+ /**
110
+ * The selection the bump WILL make, computed without writing anything, so the
111
+ * gates that run before the version commit know what to run over. Defaults to
112
+ * a dry-run `versionRelease` when a caller supplies none.
113
+ */
114
+ planRelease?(input: {
115
+ bump: PublishWorkflowBump;
116
+ }): Promise<PublishWorkflowVersionOutputs>;
108
117
  checkManagedMonorepoFiles(): Promise<void>;
109
118
  nxRunMany(input: {
110
119
  target: PublishWorkflowNxTarget;
@@ -1 +1 @@
1
- {"version":3,"file":"publish-workflow.d.ts","sourceRoot":"","sources":["../../src/monorepo/publish-workflow.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"publish-workflow.d.ts","sourceRoot":"","sources":["../../src/monorepo/publish-workflow.ts"],"names":[],"mappings":"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"}
@@ -31,6 +31,7 @@ export var PublishWorkflowStepKind;
31
31
  PublishWorkflowStepKind["ConfigureReleaseAuthor"] = "configure-release-author";
32
32
  PublishWorkflowStepKind["BuildNxVersionActions"] = "build-nx-version-actions";
33
33
  PublishWorkflowStepKind["RepairPendingReleases"] = "repair-pending-releases";
34
+ PublishWorkflowStepKind["PlanRelease"] = "plan-release";
34
35
  PublishWorkflowStepKind["VersionRelease"] = "version-release";
35
36
  PublishWorkflowStepKind["CheckManagedMonorepoFiles"] = "check-managed-monorepo-files";
36
37
  PublishWorkflowStepKind["Build"] = "build";
@@ -45,6 +46,9 @@ export var PublishWorkflowStepKind;
45
46
  })(PublishWorkflowStepKind || (PublishWorkflowStepKind = {}));
46
47
  export function definePublishWorkflow(options = {}) {
47
48
  const versionMode = githubExpression('steps.version.outputs.mode');
49
+ // Steps that run before the bump must label themselves from the plan: the
50
+ // version step's outputs do not exist yet, so the interpolation renders empty.
51
+ const planMode = githubExpression('steps.plan.outputs.mode');
48
52
  if (options.release === false) {
49
53
  return { steps: defineDeployOnlyWorkflowSteps(options) };
50
54
  }
@@ -86,30 +90,37 @@ export function definePublishWorkflow(options = {}) {
86
90
  kind: PublishWorkflowStepKind.RepairPendingReleases,
87
91
  name: '🧯 Repair pending releases',
88
92
  },
89
- { kind: PublishWorkflowStepKind.VersionRelease, name: '🔢 Version release', id: 'version' },
93
+ // Plan first, gate second, bump third. Lint and test hash the source, so
94
+ // running them BEFORE the version commit means their task hashes match
95
+ // the ones ci already computed for the same source — the publish reuses
96
+ // that cache instead of re-running 189 tasks. Build stays after the bump
97
+ // on purpose: an artifact built from pre-bump sources would ship the
98
+ // previous version string.
99
+ { kind: PublishWorkflowStepKind.PlanRelease, name: '🧭 Plan release', id: 'plan' },
90
100
  {
91
101
  kind: PublishWorkflowStepKind.CheckManagedMonorepoFiles,
92
- name: `✅ Check managed monorepo files (${versionMode})`,
93
- condition: 'version-mode-not-none',
94
- },
95
- {
96
- kind: PublishWorkflowStepKind.Build,
97
- name: `🔨 Build (${versionMode})`,
98
- condition: 'version-mode-not-none',
99
- nxTarget: 'build',
102
+ name: `✅ Check managed monorepo files (${planMode})`,
103
+ condition: 'plan-mode-not-none',
100
104
  },
101
105
  {
102
106
  kind: PublishWorkflowStepKind.Lint,
103
- name: `🔍 Lint (${versionMode})`,
104
- condition: 'version-mode-not-none',
107
+ name: `🔍 Lint (${planMode})`,
108
+ condition: 'plan-mode-not-none',
105
109
  nxTarget: 'lint',
106
110
  },
107
111
  {
108
112
  kind: PublishWorkflowStepKind.UnitTests,
109
- name: `🧪 Unit Tests (${versionMode})`,
110
- condition: 'version-mode-not-none',
113
+ name: `🧪 Unit Tests (${planMode})`,
114
+ condition: 'plan-mode-not-none',
111
115
  nxTarget: 'test',
112
116
  },
117
+ { kind: PublishWorkflowStepKind.VersionRelease, name: '🔢 Version release', id: 'version' },
118
+ {
119
+ kind: PublishWorkflowStepKind.Build,
120
+ name: `🔨 Build (${versionMode})`,
121
+ condition: 'version-mode-not-none',
122
+ nxTarget: 'build',
123
+ },
113
124
  { kind: PublishWorkflowStepKind.UploadTraceDbs, name: '📎 Upload trace DBs', condition: 'failure' },
114
125
  {
115
126
  kind: PublishWorkflowStepKind.ValidateMonorepoConfig,
@@ -158,10 +169,11 @@ function numberWorkflowSteps(steps) {
158
169
  export async function runPublishWorkflow(workflow, context) {
159
170
  let setupOutputs = { nixCacheHit: '', devenvCacheHit: '' };
160
171
  let version = { mode: 'none', projects: [] };
172
+ let plan = { mode: 'none', projects: [] };
161
173
  let failed = false;
162
174
  let failure;
163
175
  for (const step of workflow.steps) {
164
- if (!shouldRunStep(step, version, failed, context.inputs)) {
176
+ if (!shouldRunStep(step, version, failed, context.inputs, plan)) {
165
177
  continue;
166
178
  }
167
179
  try {
@@ -187,6 +199,11 @@ export async function runPublishWorkflow(workflow, context) {
187
199
  dryRun: context.inputs.dryRun,
188
200
  });
189
201
  break;
202
+ case PublishWorkflowStepKind.PlanRelease:
203
+ plan = context.callbacks.planRelease
204
+ ? await context.callbacks.planRelease({ bump: context.inputs.bump })
205
+ : await context.callbacks.versionRelease({ bump: context.inputs.bump, dryRun: true });
206
+ break;
190
207
  case PublishWorkflowStepKind.VersionRelease:
191
208
  version = await context.callbacks.versionRelease(context.inputs);
192
209
  break;
@@ -199,7 +216,12 @@ export async function runPublishWorkflow(workflow, context) {
199
216
  if (!step.nxTarget) {
200
217
  throw new Error(`Workflow step ${step.kind} is missing an Nx target.`);
201
218
  }
202
- await context.callbacks.nxRunMany({ target: step.nxTarget, projects: version.projects });
219
+ // Lint and test run before the bump exists, so they select from the
220
+ // plan; build runs after it and selects from the written version.
221
+ await context.callbacks.nxRunMany({
222
+ target: step.nxTarget,
223
+ projects: step.kind === PublishWorkflowStepKind.Build ? version.projects : plan.projects,
224
+ });
203
225
  break;
204
226
  case PublishWorkflowStepKind.UploadTraceDbs:
205
227
  await context.callbacks.uploadTraceDbs();
@@ -234,7 +256,10 @@ export async function runPublishWorkflow(workflow, context) {
234
256
  }
235
257
  return { version, failed };
236
258
  }
237
- function shouldRunStep(step, version, failed, inputs) {
259
+ function shouldRunStep(step, version, failed, inputs, plan = version) {
260
+ if (step.condition === 'plan-mode-not-none') {
261
+ return plan.mode !== 'none';
262
+ }
238
263
  if (step.condition === 'version-mode-not-none') {
239
264
  return version.mode !== 'none';
240
265
  }
@@ -421,6 +446,16 @@ function yamlLinesForStep(step, options) {
421
446
  ...privateNpmPublisherStepEnv(options),
422
447
  ` run: smoo release repair-pending --dry-run "${githubExpression('inputs.dry_run')}"`,
423
448
  ];
449
+ case PublishWorkflowStepKind.PlanRelease:
450
+ // The same selection the bump will make, computed without writing: the
451
+ // gates need `mode` and `projects` before any version commit exists.
452
+ return [
453
+ ` - name: ${step.name}`,
454
+ ' id: plan',
455
+ ' run:',
456
+ ` smoo release version --bump "${githubExpression('inputs.bump')}" --projects "${githubExpression('inputs.projects')}" --dry-run "true" --github-output`,
457
+ ' "$GITHUB_OUTPUT"',
458
+ ];
424
459
  case PublishWorkflowStepKind.VersionRelease:
425
460
  return [
426
461
  ` - name: ${step.name}`,
@@ -436,9 +471,9 @@ function yamlLinesForStep(step, options) {
436
471
  case PublishWorkflowStepKind.Build:
437
472
  return conditionalRunStep(step, `smoo github-ci nx-run-many --targets build --projects "${githubExpression('steps.version.outputs.projects')}"`);
438
473
  case PublishWorkflowStepKind.Lint:
439
- return conditionalRunStep(step, `smoo github-ci nx-run-many --targets lint --projects "${githubExpression('steps.version.outputs.projects')}"`);
474
+ return conditionalRunStep(step, `smoo github-ci nx-run-many --targets lint --projects "${githubExpression('steps.plan.outputs.projects')}"`);
440
475
  case PublishWorkflowStepKind.UnitTests:
441
- return conditionalRunStep(step, `smoo github-ci nx-run-many --targets test --projects "${githubExpression('steps.version.outputs.projects')}"`);
476
+ return conditionalRunStep(step, `smoo github-ci nx-run-many --targets test --projects "${githubExpression('steps.plan.outputs.projects')}"`);
442
477
  case PublishWorkflowStepKind.UploadTraceDbs:
443
478
  return artifactStepLines(options.actionsProvider, step.name, 'upload', [
444
479
  `name: trace-results-${githubExpression('github.run_id')}`,
@@ -513,8 +548,11 @@ function deployProductionStep(step, options) {
513
548
  ];
514
549
  }
515
550
  function conditionalRunStep(step, run) {
516
- const condition = "steps.version.outputs.mode != 'none'";
517
- return [` - name: ${step.name}`, ` if: ${condition}`, ` run: ${run}`];
551
+ // A step gated on the plan must read the PLAN's mode: it runs before the
552
+ // version step exists, and `steps.version.outputs.mode` is empty there, which
553
+ // silently skips the gate rather than running it.
554
+ const source = step.condition === 'plan-mode-not-none' ? 'plan' : 'version';
555
+ return [` - name: ${step.name}`, ` if: steps.${source}.outputs.mode != 'none'`, ` run: ${run}`];
518
556
  }
519
557
  function siblingSourceCheckoutStepLines(options) {
520
558
  const checkouts = options.sourceCheckouts;
@@ -0,0 +1,45 @@
1
+ /**
2
+ * `smoo secrets` — the operator side of the reconciliation in ./index.ts.
3
+ *
4
+ * Values are handed to `gh` over stdin, never through argv (a process list is
5
+ * world-readable) and never printed. Reading one from the terminal disables
6
+ * echo, so a pasted key does not end up in a scrollback buffer or a screen
7
+ * share.
8
+ */
9
+ /** Repository secret names GitHub currently holds, or a refusal naming what failed. */
10
+ export declare function readRepositorySecrets(repo: string | undefined): {
11
+ ok: true;
12
+ names: string[];
13
+ } | {
14
+ ok: false;
15
+ reason: string;
16
+ };
17
+ /** Write one secret, value over stdin so it never reaches argv. */
18
+ export declare function writeRepositorySecret(name: string, value: string, repo: string | undefined): Promise<{
19
+ ok: true;
20
+ } | {
21
+ ok: false;
22
+ reason: string;
23
+ }>;
24
+ /**
25
+ * Print every known secret with its sources. Exit code 1 when a workflow
26
+ * promises a value the repository does not hold — that combination is the one
27
+ * that fails a deploy, and it fails talking about the value rather than the
28
+ * missing secret.
29
+ */
30
+ export declare function secretsStatus(root: string, options: {
31
+ repo?: string;
32
+ }): number;
33
+ /** Set one secret from a pasted value. */
34
+ export declare function secretsSet(name: string, options: {
35
+ repo?: string;
36
+ }): Promise<number>;
37
+ /**
38
+ * Push every locally fetchable secret to the repository. Only names
39
+ * `smoo.secrets` declares a command for: everything else has no source here
40
+ * and must be pasted with `smoo secrets set`.
41
+ */
42
+ export declare function secretsSync(root: string, options: {
43
+ repo?: string;
44
+ }): Promise<number>;
45
+ //# sourceMappingURL=commands.d.ts.map