@smoothbricks/cli 0.10.1 → 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 (77) 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 +145 -14
  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/lib/conflict-markers.d.ts.map +1 -1
  10. package/dist/lib/workspace.d.ts +1 -1
  11. package/dist/lib/workspace.d.ts.map +1 -1
  12. package/dist/monorepo/ci-workflow.d.ts.map +1 -1
  13. package/dist/monorepo/ci-workflow.js +2 -1
  14. package/dist/monorepo/managed-files.d.ts +2 -0
  15. package/dist/monorepo/managed-files.d.ts.map +1 -1
  16. package/dist/monorepo/managed-files.js +50 -5
  17. package/dist/monorepo/package-policy.d.ts.map +1 -1
  18. package/dist/monorepo/package-policy.js +26 -0
  19. package/dist/monorepo/packs/index.d.ts +3 -0
  20. package/dist/monorepo/packs/index.d.ts.map +1 -1
  21. package/dist/monorepo/packs/index.js +5 -2
  22. package/dist/monorepo/publish-workflow.d.ts +1 -0
  23. package/dist/monorepo/publish-workflow.d.ts.map +1 -1
  24. package/dist/monorepo/publish-workflow.js +240 -2
  25. package/dist/monorepo/tool-validation.d.ts.map +1 -1
  26. package/dist/monorepo/tool-validation.js +20 -7
  27. package/dist/nx/index.d.ts +6 -0
  28. package/dist/nx/index.d.ts.map +1 -1
  29. package/dist/nx/index.js +55 -5
  30. package/dist/release/github-release.d.ts +5 -2
  31. package/dist/release/github-release.d.ts.map +1 -1
  32. package/dist/release/github-release.js +11 -0
  33. package/dist/release/index.d.ts +19 -1
  34. package/dist/release/index.d.ts.map +1 -1
  35. package/dist/release/index.js +140 -31
  36. package/dist/release/orchestration.d.ts +8 -1
  37. package/dist/release/orchestration.d.ts.map +1 -1
  38. package/dist/release/orchestration.js +38 -1
  39. package/dist/wrangler/prepare-env.d.ts.map +1 -1
  40. package/dist/wrangler/prepare-env.js +1 -1
  41. package/dist/wrangler/scaffold.d.ts.map +1 -1
  42. package/dist/wrangler/scaffold.js +1 -1
  43. package/managed/raw/tooling/direnv/github-actions-bootstrap.sh +5 -0
  44. package/managed/raw/tooling/direnv/setup-environment.ts +32 -1
  45. package/managed/templates/github/actions/cache-nix-devenv/action.yml +12 -10
  46. package/managed/templates/github/actions/cache-node-modules/action.yml +3 -2
  47. package/managed/templates/github/actions/cache-nx/action.yml +2 -2
  48. package/managed/templates/github/actions/save-nix-devenv/action.yml +11 -3
  49. package/package.json +7 -14
  50. package/src/cli.ts +30 -4
  51. package/src/github-ci/index.test.ts +486 -0
  52. package/src/github-ci/index.ts +177 -16
  53. package/src/github-ci/outputs.ts +506 -0
  54. package/src/monorepo/__tests__/ci-workflow.test.ts +13 -0
  55. package/src/monorepo/__tests__/publish-workflow.test.ts +234 -5
  56. package/src/monorepo/ci-workflow.ts +3 -1
  57. package/src/monorepo/managed-files.test.ts +75 -0
  58. package/src/monorepo/managed-files.ts +61 -5
  59. package/src/monorepo/package-policy.test.ts +57 -38
  60. package/src/monorepo/package-policy.ts +28 -0
  61. package/src/monorepo/packs/index.test.ts +18 -1
  62. package/src/monorepo/packs/index.ts +7 -3
  63. package/src/monorepo/publish-workflow.ts +481 -2
  64. package/src/monorepo/tool-validation.test.ts +59 -24
  65. package/src/monorepo/tool-validation.ts +21 -7
  66. package/src/monorepo/wrangler.test.ts +9 -2
  67. package/src/nx/index.test.ts +39 -0
  68. package/src/nx/index.ts +65 -5
  69. package/src/release/__tests__/fixture-repo.test.ts +18 -16
  70. package/src/release/__tests__/github-release.test.ts +11 -0
  71. package/src/release/__tests__/orchestration.test.ts +57 -2
  72. package/src/release/__tests__/trust-publisher.test.ts +91 -2
  73. package/src/release/github-release.ts +12 -0
  74. package/src/release/index.ts +218 -40
  75. package/src/release/orchestration.ts +55 -3
  76. package/src/wrangler/prepare-env.ts +14 -4
  77. package/src/wrangler/scaffold.ts +8 -3
@@ -1 +1 @@
1
- {"version":3,"file":"prepare-env.d.ts","sourceRoot":"","sources":["../../src/wrangler/prepare-env.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"prepare-env.d.ts","sourceRoot":"","sources":["../../src/wrangler/prepare-env.ts"],"names":[],"mappings":"AAyBA,wBAAgB,QAAQ,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEjE;AA4DD,sHAAsH;AACtH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAK5D;AAED,kFAAkF;AAClF,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAG9D;AAED,yFAAyF;AACzF,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAK7E;AAED,oIAAoI;AACpI,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAKrF;AAED,yFAAyF;AACzF,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAOjF;AAED,iIAAiI;AACjI,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAIrG;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAW5E;AAED,qGAAqG;AACrG,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAO9E;AAED,2GAA2G;AAC3G,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED,iGAAiG;AACjG,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAOjF;AAED,2HAA2H;AAC3H,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQnF;AAED,2JAA2J;AAC3J,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAIpG;AAED,yGAAyG;AACzG,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAE5D;AAqBD,8FAA8F;AAC9F,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAE7C;AAED,8DAA8D;AAC9D,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAGzD;AAID,MAAM,WAAW,QAAQ;IACvB,8FAA8F;IAC9F,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,6FAA6F;IAC7F,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,0EAA0E;IAC1E,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,mGAAmG;IACnG,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,oGAAoG;AACpG,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAS1D;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,QAAQ,CAYhE;AAID,0EAA0E;AAC1E,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAE5C;AAED,kGAAkG;AAClG,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKhD;AAED,kIAAkI;AAClI,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEzD;AAID,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;CACf;AAkBD,8EAA8E;AAC9E,wBAAgB,OAAO,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAK5C;AAED,0HAA0H;AAC1H,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAMxE;AAED;;;;GAIG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CASnH;AAMD,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAaD,8FAA8F;AAC9F,wBAAsB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAMxE;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAShH;AAMD,uHAAuH;AACvH,wBAAsB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAMjF;AAED,2GAA2G;AAC3G,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOvG"}
@@ -295,7 +295,7 @@ export async function ensureNamespace(logical, existing, cwd) {
295
295
  await $ `bunx wrangler kv namespace create ${logical}`.cwd(cwd).quiet();
296
296
  }
297
297
  catch (err) {
298
- return errText(err).includes('already') ? (await reList(logical, cwd)) : null;
298
+ return errText(err).includes('already') ? await reList(logical, cwd) : null;
299
299
  }
300
300
  return reList(logical, cwd);
301
301
  }
@@ -1 +1 @@
1
- {"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../../src/wrangler/scaffold.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,eAAe;IAC9B,oDAAoD;IACpD,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAmMD,4FAA4F;AAC5F,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB,GAAG,MAAM,CA2B7F"}
1
+ {"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../../src/wrangler/scaffold.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,eAAe;IAC9B,oDAAoD;IACpD,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAsMD,4FAA4F;AAC5F,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB,GAAG,MAAM,CA6B7F"}
@@ -76,7 +76,7 @@ async function checkMode(env: string): Promise<void> {
76
76
  for (const binding of kvBindings) {
77
77
  const inToml = pe.getKvId(toml, env, binding);
78
78
  const liveId = live.find((n) => n.title === kvTitle(binding, env))?.id ?? null;
79
- p.log.message(\` KV \${binding}: \${!liveId ? '✗ not created' : inToml === liveId ? \`✓ \${liveId}\` : \`⚠ drift (live \${liveId}, toml \${inToml ?? 'unset'})\`}\`);
79
+ p.log.message(\` KV \${binding}: \${!liveId ? '✗ not created' : inToml === liveId ? \`✓ \${liveId}\` : \`! drift (live \${liveId}, toml \${inToml ?? 'unset'})\`}\`);
80
80
  }
81
81
  for (const name of vars) {
82
82
  p.log.message(\` var \${name}: \${pe.getVar(toml, env, name) ? '✓ set' : '✗ empty'}\`);
@@ -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,
@@ -109,11 +116,35 @@ async function acquireLock(lockDir: string): Promise<void> {
109
116
  if (!isFileExistsError(error) || Date.now() > deadline) {
110
117
  throw error;
111
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
+ }
112
128
  await Bun.sleep(100);
113
129
  }
114
130
  }
115
131
  }
116
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
+
117
148
  function isFileExistsError(error: unknown): boolean {
118
149
  return error instanceof Error && 'code' in error && error.code === 'EEXIST';
119
150
  }
@@ -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
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smoothbricks/cli",
3
- "version": "0.10.1",
3
+ "version": "0.10.3",
4
4
  "type": "module",
5
5
  "description": "SmoothBricks monorepo automation CLI",
6
6
  "bin": {
@@ -52,14 +52,17 @@
52
52
  ],
53
53
  "dependencies": {
54
54
  "@arethetypeswrong/core": "^0.18.2",
55
- "@smoothbricks/nx-plugin": "0.3.0",
56
- "@smoothbricks/validation": "0.1.1",
55
+ "@prettier/sync": "^0.6.1",
56
+ "@smoothbricks/nx-plugin": "0.3.2",
57
+ "@smoothbricks/validation": "0.1.3",
57
58
  "commander": "^14.0.3",
59
+ "prettier": "^3.6.1",
58
60
  "publint": "^0.3.18",
59
61
  "semver": "^7.7.4",
60
62
  "sherif": "^1.11.1",
61
63
  "toml-eslint-parser": "^1.0.3",
62
- "tslib": "^2.8.1"
64
+ "tslib": "^2.8.1",
65
+ "typia": "13.1.1"
63
66
  },
64
67
  "devDependencies": {
65
68
  "fast-check": "^4.4.0"
@@ -67,16 +70,6 @@
67
70
  "nx": {
68
71
  "targets": {
69
72
  "lint": {},
70
- "typecheck-tests": {
71
- "executor": "nx:run-commands",
72
- "options": {
73
- "command": "tsc --noEmit -p tsconfig.test.json",
74
- "cwd": "packages/cli"
75
- },
76
- "dependsOn": [
77
- "build"
78
- ]
79
- },
80
73
  "test": {
81
74
  "executor": "@smoothbricks/nx-plugin:bounded-exec",
82
75
  "options": {
package/src/cli.ts CHANGED
@@ -147,10 +147,25 @@ function buildProgram(): Command {
147
147
  .command('repair-pending')
148
148
  .description('Repair incomplete older release commits before releasing the current HEAD')
149
149
  .option('--dry-run [dryRun]', 'run without pushing, publishing, or writing GitHub Releases')
150
- .action(async (options: { dryRun?: string | boolean }) => {
150
+ .option('--ref <ref>', 'fixed release graph ref to inspect')
151
+ .option('--platform-outputs <path>', 'cross-platform repair outputs grouped by release SHA')
152
+ .action(async (options: { dryRun?: string | boolean; platformOutputs?: string; ref?: string }) => {
153
+ // The source self-hosting shim has no Typia transform; release commands import transformed output validators.
151
154
  const { releaseRepairPending } = await import('./release/index.js');
152
155
  await releaseRepairPending(await findRepoRoot(), { ...options, dryRun: booleanOption(options.dryRun) });
153
156
  });
157
+ release
158
+ .command('build-platform-outputs')
159
+ .description('Build selected current and pending-release platform outputs')
160
+ .requiredOption('--bump <bump>', 'auto, patch, minor, major, or prerelease')
161
+ .requiredOption('--targets <targets>', 'comma-separated Nx platform target names or globs')
162
+ .requiredOption('--output <path>', 'output directory for current and repair artifacts')
163
+ .option('--ref <ref>', 'fixed release graph ref to inspect')
164
+ .action(async (options: { bump: string; output: string; ref?: string; targets: string }) => {
165
+ // The source self-hosting shim has no Typia transform; release commands import transformed output validators.
166
+ const { releaseCollectPlatformOutputs } = await import('./release/index.js');
167
+ await releaseCollectPlatformOutputs(await findRepoRoot(), options);
168
+ });
154
169
  release
155
170
  .command('version')
156
171
  .option('--bump <bump>', 'auto, patch, minor, major, or prerelease', 'auto')
@@ -322,9 +337,20 @@ function buildProgram(): Command {
322
337
  .requiredOption('--targets <targets>')
323
338
  .option('--projects <projects>')
324
339
  .option('--configuration <configuration>')
325
- .action(async (options: { targets: string; projects?: string; configuration?: string }) => {
326
- const { githubCiNxRunMany } = await import('./github-ci/index.js');
327
- await githubCiNxRunMany(await findRepoRoot(), options);
340
+ .option('--collect-outputs <directory>')
341
+ .action(
342
+ async (options: { targets: string; projects?: string; configuration?: string; collectOutputs?: string }) => {
343
+ const { githubCiNxRunMany } = await import('./github-ci/index.js');
344
+ await githubCiNxRunMany(await findRepoRoot(), options);
345
+ },
346
+ );
347
+ githubCi
348
+ .command('apply-outputs <directories...>')
349
+ .requiredOption('--source-sha <sha>', 'expected source commit SHA')
350
+ .action(async (directories: string[], options: { sourceSha: string }) => {
351
+ // GitHub CI commands stay lazy so source self-hosting can initialize Typia only at manifest boundaries.
352
+ const { githubCiApplyOutputs } = await import('./github-ci/index.js');
353
+ await githubCiApplyOutputs(await findRepoRoot(), directories, options.sourceSha);
328
354
  });
329
355
  githubCi
330
356
  .command('nx-deploy')