@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.
- package/README.md +25 -13
- package/dist/cli.js +24 -0
- package/dist/github-ci/index.d.ts +17 -2
- package/dist/github-ci/index.d.ts.map +1 -1
- package/dist/github-ci/index.js +145 -14
- package/dist/github-ci/outputs.d.ts +22 -0
- package/dist/github-ci/outputs.d.ts.map +1 -0
- package/dist/github-ci/outputs.js +649 -0
- package/dist/lib/conflict-markers.d.ts.map +1 -1
- package/dist/lib/workspace.d.ts +1 -1
- package/dist/lib/workspace.d.ts.map +1 -1
- package/dist/monorepo/ci-workflow.d.ts.map +1 -1
- package/dist/monorepo/ci-workflow.js +2 -1
- package/dist/monorepo/managed-files.d.ts +2 -0
- package/dist/monorepo/managed-files.d.ts.map +1 -1
- package/dist/monorepo/managed-files.js +50 -5
- package/dist/monorepo/package-policy.d.ts.map +1 -1
- package/dist/monorepo/package-policy.js +26 -0
- package/dist/monorepo/packs/index.d.ts +3 -0
- package/dist/monorepo/packs/index.d.ts.map +1 -1
- package/dist/monorepo/packs/index.js +5 -2
- package/dist/monorepo/publish-workflow.d.ts +1 -0
- package/dist/monorepo/publish-workflow.d.ts.map +1 -1
- package/dist/monorepo/publish-workflow.js +240 -2
- package/dist/monorepo/tool-validation.d.ts.map +1 -1
- package/dist/monorepo/tool-validation.js +20 -7
- package/dist/nx/index.d.ts +6 -0
- package/dist/nx/index.d.ts.map +1 -1
- package/dist/nx/index.js +55 -5
- package/dist/release/github-release.d.ts +5 -2
- package/dist/release/github-release.d.ts.map +1 -1
- package/dist/release/github-release.js +11 -0
- package/dist/release/index.d.ts +19 -1
- package/dist/release/index.d.ts.map +1 -1
- package/dist/release/index.js +140 -31
- package/dist/release/orchestration.d.ts +8 -1
- package/dist/release/orchestration.d.ts.map +1 -1
- package/dist/release/orchestration.js +38 -1
- package/dist/wrangler/prepare-env.d.ts.map +1 -1
- package/dist/wrangler/prepare-env.js +1 -1
- package/dist/wrangler/scaffold.d.ts.map +1 -1
- package/dist/wrangler/scaffold.js +1 -1
- package/managed/raw/tooling/direnv/github-actions-bootstrap.sh +5 -0
- package/managed/raw/tooling/direnv/setup-environment.ts +32 -1
- package/managed/templates/github/actions/cache-nix-devenv/action.yml +12 -10
- package/managed/templates/github/actions/cache-node-modules/action.yml +3 -2
- package/managed/templates/github/actions/cache-nx/action.yml +2 -2
- package/managed/templates/github/actions/save-nix-devenv/action.yml +11 -3
- package/package.json +7 -14
- package/src/cli.ts +30 -4
- package/src/github-ci/index.test.ts +486 -0
- package/src/github-ci/index.ts +177 -16
- package/src/github-ci/outputs.ts +506 -0
- package/src/monorepo/__tests__/ci-workflow.test.ts +13 -0
- package/src/monorepo/__tests__/publish-workflow.test.ts +234 -5
- package/src/monorepo/ci-workflow.ts +3 -1
- package/src/monorepo/managed-files.test.ts +75 -0
- package/src/monorepo/managed-files.ts +61 -5
- package/src/monorepo/package-policy.test.ts +57 -38
- package/src/monorepo/package-policy.ts +28 -0
- package/src/monorepo/packs/index.test.ts +18 -1
- package/src/monorepo/packs/index.ts +7 -3
- package/src/monorepo/publish-workflow.ts +481 -2
- package/src/monorepo/tool-validation.test.ts +59 -24
- package/src/monorepo/tool-validation.ts +21 -7
- package/src/monorepo/wrangler.test.ts +9 -2
- package/src/nx/index.test.ts +39 -0
- package/src/nx/index.ts +65 -5
- package/src/release/__tests__/fixture-repo.test.ts +18 -16
- package/src/release/__tests__/github-release.test.ts +11 -0
- package/src/release/__tests__/orchestration.test.ts +57 -2
- package/src/release/__tests__/trust-publisher.test.ts +91 -2
- package/src/release/github-release.ts +12 -0
- package/src/release/index.ts +218 -40
- package/src/release/orchestration.ts +55 -3
- package/src/wrangler/prepare-env.ts +14 -4
- package/src/wrangler/scaffold.ts +8 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ci-workflow.d.ts","sourceRoot":"","sources":["../../src/monorepo/ci-workflow.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ci-workflow.d.ts","sourceRoot":"","sources":["../../src/monorepo/ci-workflow.ts"],"names":[],"mappings":"AAEA,oBAAY,kBAAkB;IAC5B,QAAQ,aAAa;IACrB,WAAW,iBAAiB;IAC5B,SAAS,gBAAgB;IACzB,cAAc,qBAAqB;IACnC,KAAK,UAAU;IACf,IAAI,SAAS;IACb,SAAS,eAAe;IACxB,MAAM,WAAW;IACjB,WAAW,kBAAkB;IAC7B,cAAc,qBAAqB;IACnC,aAAa,oBAAoB;CAClC;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,kBAAkB,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,2BAA2B;IAC1C,MAAM,EAAE,OAAO,CAAC;IAChB,cAAc,CAAC,EAAE,YAAY,CAAC;IAC9B,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAID,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,2BAA2B,GAAG,cAAc,EAAE,CAmBvF;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,2BAA2B,GAAG,MAAM,CAGjF"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* biome-ignore-all lint/suspicious/noTemplateCurlyInString: GitHub Actions expressions are emitted literally. */
|
|
1
2
|
export var CiWorkflowStepKind;
|
|
2
3
|
(function (CiWorkflowStepKind) {
|
|
3
4
|
CiWorkflowStepKind["Checkout"] = "checkout";
|
|
@@ -154,7 +155,7 @@ function yamlLinesForStep(step, options) {
|
|
|
154
155
|
' path: |',
|
|
155
156
|
' .nx/cache',
|
|
156
157
|
' .nx/workspace-data/*.db*',
|
|
157
|
-
' key: ${{ runner.os }}-nx-db-v1-${{ github.sha }}',
|
|
158
|
+
' key: ${{ runner.os }}-${{ runner.arch }}-nx-db-v1-${{ github.sha }}',
|
|
158
159
|
];
|
|
159
160
|
case CiWorkflowStepKind.UploadTraceDbs:
|
|
160
161
|
return [
|
|
@@ -27,6 +27,7 @@ export declare const INLINE_LOCAL_END = "# smoo-local-end";
|
|
|
27
27
|
interface InlineLocalBlock {
|
|
28
28
|
anchor: string;
|
|
29
29
|
lines: string;
|
|
30
|
+
markerIndent?: string;
|
|
30
31
|
}
|
|
31
32
|
/** Pull inline local blocks out of a managed section, returning the section
|
|
32
33
|
* with each block (and its markers) removed, plus the extracted blocks in
|
|
@@ -47,6 +48,7 @@ export interface FileResult {
|
|
|
47
48
|
action: 'created' | 'updated' | 'unchanged' | 'skipped' | 'skipped-symlink' | 'drifted' | 'ok-symlink';
|
|
48
49
|
}
|
|
49
50
|
export declare function applyManagedFiles(root: string, mode: 'update' | 'check' | 'diff'): FileResult[];
|
|
51
|
+
export declare function platformTargetGlobsForTest(targetNames: Iterable<string>): string[];
|
|
50
52
|
export declare function printResults(results: FileResult[]): void;
|
|
51
53
|
export declare function validateManagedFiles(root: string): number;
|
|
52
54
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"managed-files.d.ts","sourceRoot":"","sources":["../../src/monorepo/managed-files.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"managed-files.d.ts","sourceRoot":"","sources":["../../src/monorepo/managed-files.ts"],"names":[],"mappings":"AAWA;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,yEAAyE,CAAC;AAU3G,sFAAsF;AACtF,iBAAS,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAIlF;AAED,uCAAuC;AACvC,eAAO,MAAM,wBAAwB,0BAAoB,CAAC;AAE1D;;;;;;;;;GASG;AACH,eAAO,MAAM,kBAAkB,uBAAuB,CAAC;AACvD,eAAO,MAAM,gBAAgB,qBAAqB,CAAC;AAEnD,UAAU,gBAAgB;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;8BAE8B;AAC9B,iBAAS,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,aAAa,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,gBAAgB,EAAE,CAAA;CAAE,CAkCxG;AAED,wCAAwC;AACxC,eAAO,MAAM,+BAA+B,iCAA2B,CAAC;AAExE;+EAC+E;AAC/E,iBAAS,yBAAyB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,GAAG,MAAM,CAqBtF;AAED,yCAAyC;AACzC,eAAO,MAAM,gCAAgC,kCAA4B,CAAC;AAE1E,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,iBAAiB,GAAG,SAAS,GAAG,YAAY,CAAC;CACxG;AA+GD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,UAAU,EAAE,CAG/F;AA6FD,wBAAgB,0BAA0B,CAAC,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,MAAM,EAAE,CAMlF;AAsHD,wBAAgB,YAAY,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,IAAI,CAIxD;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQzD"}
|
|
@@ -2,6 +2,7 @@ import { execFileSync } from 'node:child_process';
|
|
|
2
2
|
import { existsSync, lstatSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
3
3
|
import { dirname, join, resolve } from 'node:path';
|
|
4
4
|
import { fileURLToPath } from 'node:url';
|
|
5
|
+
import { PLATFORM_TARGET_GLOBS } from '@smoothbricks/nx-plugin/workspace-config-policy';
|
|
5
6
|
import { listReleasePackages, readPackageJson } from '../lib/workspace.js';
|
|
6
7
|
import { renderCiWorkflowYaml } from './ci-workflow.js';
|
|
7
8
|
import { renderPublishWorkflowYaml } from './publish-workflow.js';
|
|
@@ -57,7 +58,12 @@ function extractInlineLocalBlocks(managed) {
|
|
|
57
58
|
if (i >= lines.length) {
|
|
58
59
|
throw new Error(`${INLINE_LOCAL_BEGIN} anchored on "${anchor}" has no matching ${INLINE_LOCAL_END}`);
|
|
59
60
|
}
|
|
60
|
-
|
|
61
|
+
const markerIndent = line.slice(0, line.length - line.trimStart().length);
|
|
62
|
+
blocks.push({
|
|
63
|
+
anchor,
|
|
64
|
+
lines: blockLines.join('\n'),
|
|
65
|
+
...(markerIndent === '' ? {} : { markerIndent }),
|
|
66
|
+
});
|
|
61
67
|
i += 1; // skip the END marker line itself
|
|
62
68
|
continue;
|
|
63
69
|
}
|
|
@@ -80,7 +86,8 @@ function reinsertInlineLocalBlocks(content, blocks) {
|
|
|
80
86
|
throw new Error(`${INLINE_LOCAL_BEGIN} block anchored on "${block.anchor}" no longer matches any line in the updated ` +
|
|
81
87
|
'template โ reconcile the repo-owned block manually');
|
|
82
88
|
}
|
|
83
|
-
|
|
89
|
+
const markerIndent = block.markerIndent ?? '';
|
|
90
|
+
lines.splice(index + 1, 0, `${markerIndent}${INLINE_LOCAL_BEGIN}`, ...block.lines.split('\n'), `${markerIndent}${INLINE_LOCAL_END}`);
|
|
84
91
|
}
|
|
85
92
|
return lines.join('\n');
|
|
86
93
|
}
|
|
@@ -228,6 +235,7 @@ function getManagedContent(file, context) {
|
|
|
228
235
|
deploy: context.hasProductionDeployTargets,
|
|
229
236
|
deployProvider: context.productionDeployProvider,
|
|
230
237
|
repoName: context.repoName,
|
|
238
|
+
platformTargetGlobs: context.platformTargetGlobs,
|
|
231
239
|
});
|
|
232
240
|
}
|
|
233
241
|
throw new Error(`Unknown generated managed file source ${file.source}`);
|
|
@@ -246,6 +254,7 @@ function getManagedFileContext(root) {
|
|
|
246
254
|
const ciPushBranches = getCiPushBranches(packageJson?.json);
|
|
247
255
|
const stagingDeploy = getDeployTargetInfo(root, 'staging');
|
|
248
256
|
const productionDeploy = getDeployTargetInfo(root, 'production');
|
|
257
|
+
const platformTargetGlobs = platformTargetGlobsForTest(readResolvedNxTargetNames(root));
|
|
249
258
|
const nodeModulesCacheKey = existsSync(join(root, 'bun.lock'))
|
|
250
259
|
? `$${"{{ hashFiles('bun.lock', 'package.json', 'packages/*/package.json') }}"}`
|
|
251
260
|
: `$${"{{ hashFiles('bun.lockb', 'package.json', 'packages/*/package.json') }}"}`;
|
|
@@ -258,8 +267,43 @@ function getManagedFileContext(root) {
|
|
|
258
267
|
ciPushBranches,
|
|
259
268
|
nodeModulesCacheKey,
|
|
260
269
|
repoName,
|
|
270
|
+
platformTargetGlobs,
|
|
261
271
|
};
|
|
262
272
|
}
|
|
273
|
+
export function platformTargetGlobsForTest(targetNames) {
|
|
274
|
+
const names = [...targetNames];
|
|
275
|
+
return PLATFORM_TARGET_GLOBS.filter((glob) => {
|
|
276
|
+
const suffix = glob.startsWith('*') ? glob.slice(1) : glob;
|
|
277
|
+
return names.some((name) => name.endsWith(suffix));
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
function readResolvedNxTargetNames(root) {
|
|
281
|
+
const output = execFileSync('nx', ['show', 'projects', '--json'], {
|
|
282
|
+
cwd: root,
|
|
283
|
+
encoding: 'utf8',
|
|
284
|
+
stdio: ['ignore', 'pipe', 'inherit'],
|
|
285
|
+
});
|
|
286
|
+
const projects = JSON.parse(output);
|
|
287
|
+
if (!Array.isArray(projects) || !projects.every((project) => typeof project === 'string')) {
|
|
288
|
+
return [];
|
|
289
|
+
}
|
|
290
|
+
const targetNames = new Set();
|
|
291
|
+
for (const project of projects) {
|
|
292
|
+
const projectOutput = execFileSync('nx', ['show', 'project', project, '--json'], {
|
|
293
|
+
cwd: root,
|
|
294
|
+
encoding: 'utf8',
|
|
295
|
+
stdio: ['ignore', 'pipe', 'inherit'],
|
|
296
|
+
});
|
|
297
|
+
const projectJson = JSON.parse(projectOutput);
|
|
298
|
+
const targets = recordValue(recordValue(projectJson)?.targets);
|
|
299
|
+
if (targets) {
|
|
300
|
+
for (const targetName of Object.keys(targets)) {
|
|
301
|
+
targetNames.add(targetName);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
return [...targetNames];
|
|
306
|
+
}
|
|
263
307
|
function renderTemplate(context, template) {
|
|
264
308
|
return template
|
|
265
309
|
.replaceAll('{{REPO_NAME}}', context.repoName)
|
|
@@ -325,9 +369,10 @@ function readCiPushBranches(packageJson) {
|
|
|
325
369
|
return branches.filter((branch) => typeof branch === 'string' && branch.length > 0);
|
|
326
370
|
}
|
|
327
371
|
function recordValue(value) {
|
|
328
|
-
return value
|
|
329
|
-
|
|
330
|
-
|
|
372
|
+
return isRecord(value) ? value : undefined;
|
|
373
|
+
}
|
|
374
|
+
function isRecord(value) {
|
|
375
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
331
376
|
}
|
|
332
377
|
function renderYamlFlowList(values) {
|
|
333
378
|
return JSON.stringify(values);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"package-policy.d.ts","sourceRoot":"","sources":["../../src/monorepo/package-policy.ts"],"names":[],"mappings":"AAKA,OAAO,EAGL,KAAK,0BAA0B,EAC/B,KAAK,sBAAsB,EAC5B,MAAM,+CAA+C,CAAC;AACvD,OAAO,EAGL,2BAA2B,EAC3B,uBAAuB,EACxB,MAAM,+CAA+C,CAAC;AA6BvD,YAAY,EAAE,0BAA0B,IAAI,iCAAiC,EAAE,sBAAsB,EAAE,CAAC;AACxG,OAAO,EAAE,2BAA2B,EAAE,uBAAuB,EAAE,CAAC;AAYhE,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAI/D;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAuB1D;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAMxD;AAED,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAuC7D;AAED,wBAAgB,gCAAgC,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,0BAA+B,GAAG,IAAI,CAwB7G;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAMzD;AAED,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAoB7D;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,CAEvE;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAezD;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAsC9D;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAW5D;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAyB3D;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAcvD;AAED,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CA0DlE;AAED,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,0BAA+B,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"package-policy.d.ts","sourceRoot":"","sources":["../../src/monorepo/package-policy.ts"],"names":[],"mappings":"AAKA,OAAO,EAGL,KAAK,0BAA0B,EAC/B,KAAK,sBAAsB,EAC5B,MAAM,+CAA+C,CAAC;AACvD,OAAO,EAGL,2BAA2B,EAC3B,uBAAuB,EACxB,MAAM,+CAA+C,CAAC;AA6BvD,YAAY,EAAE,0BAA0B,IAAI,iCAAiC,EAAE,sBAAsB,EAAE,CAAC;AACxG,OAAO,EAAE,2BAA2B,EAAE,uBAAuB,EAAE,CAAC;AAYhE,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAI/D;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAuB1D;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAMxD;AAED,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAuC7D;AAED,wBAAgB,gCAAgC,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,0BAA+B,GAAG,IAAI,CAwB7G;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAMzD;AAED,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAoB7D;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,CAEvE;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAezD;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAsC9D;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAW5D;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAyB3D;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAcvD;AAED,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CA0DlE;AAED,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,0BAA+B,GAAG,MAAM,CAkC5G"}
|
|
@@ -315,6 +315,7 @@ export function validatePublicPackageMetadata(root) {
|
|
|
315
315
|
}
|
|
316
316
|
export function validateWorkspaceDependencies(root, options = {}) {
|
|
317
317
|
let failures = 0;
|
|
318
|
+
failures += validateCiSkipTags(root, options);
|
|
318
319
|
const workspaceNames = new Set(getWorkspacePackages(root).map((pkg) => pkg.name));
|
|
319
320
|
for (const pkg of listPackageJsonRecords(root)) {
|
|
320
321
|
for (const field of workspaceDependencyFields) {
|
|
@@ -347,6 +348,31 @@ export function validateWorkspaceDependencies(root, options = {}) {
|
|
|
347
348
|
}
|
|
348
349
|
return failures;
|
|
349
350
|
}
|
|
351
|
+
const ciSkipTagPrefix = 'ci:skip:';
|
|
352
|
+
const invalidCiSkipTargetSyntax = /[,*?[\]{}]/;
|
|
353
|
+
function validateCiSkipTags(root, options) {
|
|
354
|
+
let failures = 0;
|
|
355
|
+
for (const pkg of getWorkspacePackages(root)) {
|
|
356
|
+
const resolved = options.resolvedTargetsByProject?.get(pkg.projectName);
|
|
357
|
+
const resolvedTargets = resolved && 'targets' in resolved ? resolved.targets : resolved;
|
|
358
|
+
for (const tag of pkg.tags) {
|
|
359
|
+
if (tag !== 'ci:skip' && !tag.startsWith(ciSkipTagPrefix)) {
|
|
360
|
+
continue;
|
|
361
|
+
}
|
|
362
|
+
const target = tag.startsWith(ciSkipTagPrefix) ? tag.slice(ciSkipTagPrefix.length) : '';
|
|
363
|
+
if (!target || invalidCiSkipTargetSyntax.test(target)) {
|
|
364
|
+
console.error(`${pkg.path}: nx tag ${tag} must use ci:skip:<target> with one exact Nx target name`);
|
|
365
|
+
failures++;
|
|
366
|
+
continue;
|
|
367
|
+
}
|
|
368
|
+
if (resolvedTargets && !resolvedTargets.has(target)) {
|
|
369
|
+
console.error(`${pkg.path}: nx tag ${tag} names missing Nx target ${target}`);
|
|
370
|
+
failures++;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
return failures;
|
|
375
|
+
}
|
|
350
376
|
// ---------------------------------------------------------------------------
|
|
351
377
|
// Helpers kept in CLI (not Nx-specific)
|
|
352
378
|
// ---------------------------------------------------------------------------
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { type ProjectTargets } from '../../nx/index.js';
|
|
2
|
+
import { type ResolvedProjectTargets } from '../package-policy.js';
|
|
1
3
|
export interface MonorepoContext {
|
|
2
4
|
root: string;
|
|
3
5
|
syncRuntime: boolean;
|
|
@@ -26,4 +28,5 @@ export interface ValidatePackResult {
|
|
|
26
28
|
}
|
|
27
29
|
export declare function runInitPacks(ctx: MonorepoContext): Promise<void>;
|
|
28
30
|
export declare function runValidatePacks(ctx: MonorepoContext, options?: ValidatePackOptions, hooks?: ValidatePackRunHooks): Promise<ValidatePackResult>;
|
|
31
|
+
export declare function resolvedTargetsByProject(projects: ProjectTargets[]): Map<string, ResolvedProjectTargets>;
|
|
29
32
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/monorepo/packs/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/monorepo/packs/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,cAAc,EAAsB,MAAM,mBAAmB,CAAC;AAK5E,OAAO,EAKL,KAAK,sBAAsB,EAO5B,MAAM,sBAAsB,CAAC;AAU9B,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,OAAO,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAClD,WAAW,CAAC,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IACzD,YAAY,CAAC,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC1D,gBAAgB,CAAC,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;IAClE,iBAAiB,CAAC,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;CACpE;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,CAAC,EAAE,SAAS,YAAY,EAAE,CAAC;IAChC,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,eAAe,EAAE,OAAO,CAAC,EAAE,mBAAmB,KAAK,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;CAC9F;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;CACtB;AA4GD,wBAAsB,YAAY,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAItE;AAED,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,eAAe,EACpB,OAAO,GAAE,mBAAwB,EACjC,KAAK,GAAE,oBAAyB,GAC/B,OAAO,CAAC,kBAAkB,CAAC,CA0B7B;AAuMD,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,cAAc,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAaxG"}
|
|
@@ -302,18 +302,21 @@ function printCapturedOutput(output) {
|
|
|
302
302
|
console.log(line);
|
|
303
303
|
}
|
|
304
304
|
}
|
|
305
|
-
|
|
306
|
-
const projects = await readProjectTargets(ctx.root);
|
|
305
|
+
export function resolvedTargetsByProject(projects) {
|
|
307
306
|
return new Map(projects.map((project) => [
|
|
308
307
|
project.project,
|
|
309
308
|
{
|
|
310
309
|
targets: new Set(project.targets),
|
|
311
310
|
...(project.buildDependsOn ? { buildDependsOn: project.buildDependsOn } : {}),
|
|
311
|
+
...(project.targetDependencies ? { targetDependencies: project.targetDependencies } : {}),
|
|
312
312
|
...(project.targetExecutors ? { targetExecutors: project.targetExecutors } : {}),
|
|
313
313
|
...(project.targetScripts ? { targetScripts: project.targetScripts } : {}),
|
|
314
314
|
},
|
|
315
315
|
]));
|
|
316
316
|
}
|
|
317
|
+
async function readResolvedTargetsByProject(ctx) {
|
|
318
|
+
return resolvedTargetsByProject(await readProjectTargets(ctx.root));
|
|
319
|
+
}
|
|
317
320
|
function ensureLocalSmooShim(root) {
|
|
318
321
|
const shim = join(root, 'tooling', 'smoo');
|
|
319
322
|
if (!existsSync(shim)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"publish-workflow.d.ts","sourceRoot":"","sources":["../../src/monorepo/publish-workflow.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"publish-workflow.d.ts","sourceRoot":"","sources":["../../src/monorepo/publish-workflow.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,12 @@
|
|
|
1
|
+
/* biome-ignore-all lint/suspicious/noTemplateCurlyInString: GitHub Actions expressions are emitted literally. */
|
|
2
|
+
import synchronizedPrettier from '@prettier/sync';
|
|
3
|
+
import { LINUX_PLATFORM_TARGET_GLOBS, MACOS_PLATFORM_TARGET_GLOBS, } from '@smoothbricks/nx-plugin/workspace-config-policy';
|
|
1
4
|
import { isSmoothBricksCodebasePackageName } from '../lib/cli-package.js';
|
|
5
|
+
const PUBLISH_WORKFLOW_FORMAT_OPTIONS = Object.freeze({
|
|
6
|
+
parser: 'yaml',
|
|
7
|
+
printWidth: 120,
|
|
8
|
+
proseWrap: 'always',
|
|
9
|
+
});
|
|
2
10
|
export var PublishWorkflowStepKind;
|
|
3
11
|
(function (PublishWorkflowStepKind) {
|
|
4
12
|
PublishWorkflowStepKind["Checkout"] = "checkout";
|
|
@@ -174,8 +182,18 @@ function shouldRunStep(step, version, failed, inputs) {
|
|
|
174
182
|
return true;
|
|
175
183
|
}
|
|
176
184
|
export function renderPublishWorkflowYaml(options = {}) {
|
|
177
|
-
|
|
178
|
-
|
|
185
|
+
let workflow;
|
|
186
|
+
if (hasMacosPlatformTargets(options)) {
|
|
187
|
+
workflow = renderPlatformPublishWorkflowYaml(options);
|
|
188
|
+
}
|
|
189
|
+
else if (hasLinuxPlatformTargets(options)) {
|
|
190
|
+
workflow = `${renderPublishWorkflowHeader(options)}${renderSingleJobPublishWorkflowSteps(definePublishWorkflow(options).steps, options)}`;
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
const steps = definePublishWorkflow(options).steps;
|
|
194
|
+
workflow = `${renderPublishWorkflowHeader(options)}${renderPublishWorkflowSteps(steps, options)}`;
|
|
195
|
+
}
|
|
196
|
+
return synchronizedPrettier.format(workflow, PUBLISH_WORKFLOW_FORMAT_OPTIONS);
|
|
179
197
|
}
|
|
180
198
|
function renderPublishWorkflowHeader(options) {
|
|
181
199
|
const deployInput = options.deploy === true
|
|
@@ -374,6 +392,226 @@ function conditionalRunStep(step, run) {
|
|
|
374
392
|
const condition = "steps.version.outputs.mode != 'none'";
|
|
375
393
|
return [` - name: ${step.name}`, ` if: ${githubExpression(condition)}`, ` run: ${run}`];
|
|
376
394
|
}
|
|
395
|
+
function renderSingleJobPublishWorkflowSteps(steps, options) {
|
|
396
|
+
const lines = [];
|
|
397
|
+
for (const step of steps) {
|
|
398
|
+
lines.push(...sectionLinesBefore(step));
|
|
399
|
+
lines.push(...commentLinesForStep(step));
|
|
400
|
+
lines.push(...yamlLinesForStep(step, options));
|
|
401
|
+
lines.push('');
|
|
402
|
+
if (step.kind === PublishWorkflowStepKind.Build) {
|
|
403
|
+
lines.push(' - name: ๐ง Build supplemental Linux targets', ` if: ${githubExpression("steps.version.outputs.mode != 'none'")}`, ` run: smoo github-ci nx-run-many --targets "${LINUX_PLATFORM_TARGET_GLOBS.join(',')}" --projects "${githubExpression('steps.version.outputs.projects')}"`, '');
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
return `${lines.join('\n').trimEnd()}\n`;
|
|
407
|
+
}
|
|
408
|
+
function renderPlatformPublishWorkflowYaml(options) {
|
|
409
|
+
const deployInput = options.deploy === true
|
|
410
|
+
? `
|
|
411
|
+
deploy_environment:
|
|
412
|
+
type: choice
|
|
413
|
+
description: Deploy live systems after a successful publish.
|
|
414
|
+
options: [none, production]
|
|
415
|
+
default: none`
|
|
416
|
+
: '';
|
|
417
|
+
const steps = definePublishWorkflow(options).steps;
|
|
418
|
+
return `name: Publish
|
|
419
|
+
|
|
420
|
+
on:
|
|
421
|
+
workflow_dispatch:
|
|
422
|
+
inputs:
|
|
423
|
+
bump:
|
|
424
|
+
type: choice
|
|
425
|
+
description:
|
|
426
|
+
Use auto for conventional commits, or force a semver bump. Prerelease publishes to next; all others publish to
|
|
427
|
+
latest.
|
|
428
|
+
options: [auto, patch, minor, major, prerelease]
|
|
429
|
+
default: auto
|
|
430
|
+
dry_run:
|
|
431
|
+
type: boolean
|
|
432
|
+
description: Run release commands without writing versions, tags, publishes, or GitHub Releases.
|
|
433
|
+
default: false${deployInput}
|
|
434
|
+
|
|
435
|
+
permissions:
|
|
436
|
+
contents: read
|
|
437
|
+
|
|
438
|
+
concurrency:
|
|
439
|
+
group: release-${githubExpression('github.ref')}
|
|
440
|
+
cancel-in-progress: false
|
|
441
|
+
|
|
442
|
+
defaults:
|
|
443
|
+
run:
|
|
444
|
+
working-directory: tooling/direnv
|
|
445
|
+
|
|
446
|
+
jobs:
|
|
447
|
+
linux-release-candidate:
|
|
448
|
+
runs-on: ubuntu-latest
|
|
449
|
+
permissions:
|
|
450
|
+
contents: write
|
|
451
|
+
id-token: none
|
|
452
|
+
outputs:
|
|
453
|
+
mode: ${githubExpression('steps.version.outputs.mode')}
|
|
454
|
+
release-sha: ${githubExpression('steps.release-state.outputs.sha')}
|
|
455
|
+
env:
|
|
456
|
+
NIX_STORE_NAR: ${githubExpression('github.workspace')}/nix-store.nar
|
|
457
|
+
GH_TOKEN: ${githubExpression('github.token')}
|
|
458
|
+
steps:
|
|
459
|
+
${renderLinuxReleaseCandidateSteps(steps, options)}
|
|
460
|
+
|
|
461
|
+
macos-platform:
|
|
462
|
+
runs-on: macos-latest
|
|
463
|
+
permissions:
|
|
464
|
+
contents: read
|
|
465
|
+
id-token: none
|
|
466
|
+
env:
|
|
467
|
+
NIX_STORE_NAR: ${githubExpression('github.workspace')}/nix-store.nar
|
|
468
|
+
GH_TOKEN: ${githubExpression('github.token')}
|
|
469
|
+
steps:
|
|
470
|
+
${renderMacosPlatformSteps(options)}
|
|
471
|
+
|
|
472
|
+
publish-on-linux:
|
|
473
|
+
needs: [linux-release-candidate, macos-platform]
|
|
474
|
+
runs-on: ubuntu-latest
|
|
475
|
+
permissions:
|
|
476
|
+
contents: write
|
|
477
|
+
id-token: write
|
|
478
|
+
env:
|
|
479
|
+
NIX_STORE_NAR: ${githubExpression('github.workspace')}/nix-store.nar
|
|
480
|
+
GH_TOKEN: ${githubExpression('github.token')}
|
|
481
|
+
steps:
|
|
482
|
+
${renderFinalLinuxPublishSteps(options)}
|
|
483
|
+
`;
|
|
484
|
+
}
|
|
485
|
+
function renderLinuxReleaseCandidateSteps(steps, options) {
|
|
486
|
+
const lines = [];
|
|
487
|
+
let stepNumber = 2;
|
|
488
|
+
for (const step of steps) {
|
|
489
|
+
if (step.kind === PublishWorkflowStepKind.RepairPendingReleases ||
|
|
490
|
+
step.kind === PublishWorkflowStepKind.PublishRelease ||
|
|
491
|
+
step.kind === PublishWorkflowStepKind.DeployProduction ||
|
|
492
|
+
step.kind === PublishWorkflowStepKind.SaveNixDevenv) {
|
|
493
|
+
continue;
|
|
494
|
+
}
|
|
495
|
+
lines.push(...sectionLinesBefore(step));
|
|
496
|
+
if (step.kind === PublishWorkflowStepKind.Checkout) {
|
|
497
|
+
lines.push(' # Step 1: GitHub adds "Set up job" automatically', ` # Step ${stepNumber}`);
|
|
498
|
+
}
|
|
499
|
+
else if (step.kind === PublishWorkflowStepKind.SetupDevenv) {
|
|
500
|
+
lines.push(` # Step ${stepNumber}. Composite action internals do not affect top-level job step`, ' # anchors; update these comments if top-level steps move.');
|
|
501
|
+
}
|
|
502
|
+
else {
|
|
503
|
+
lines.push(` # Step ${stepNumber}`);
|
|
504
|
+
}
|
|
505
|
+
if (step.kind === PublishWorkflowStepKind.Checkout) {
|
|
506
|
+
lines.push(` - name: ${step.name}`, ' uses: actions/checkout@v6.0.2', ' with:', ` ref: ${githubExpression('github.sha')}`, ' filter: blob:none', ' fetch-depth: 0');
|
|
507
|
+
}
|
|
508
|
+
else if (step.kind === PublishWorkflowStepKind.Build) {
|
|
509
|
+
lines.push(` - name: ${step.name}`, ` if: ${githubExpression("steps.version.outputs.mode != 'none'")}`, ' run:', ` smoo github-ci nx-run-many --targets build --projects "${githubExpression('steps.version.outputs.projects')}" --collect-outputs "${githubExpression('runner.temp')}/release-build-outputs"`);
|
|
510
|
+
}
|
|
511
|
+
else {
|
|
512
|
+
lines.push(...yamlLinesForStep(step, options));
|
|
513
|
+
}
|
|
514
|
+
stepNumber += 1;
|
|
515
|
+
if (step.kind === PublishWorkflowStepKind.VersionRelease) {
|
|
516
|
+
lines.push('', ` # Step ${stepNumber}`, ' - name: ๐ Capture candidate release SHA', ' id: release-state', ' run: echo "sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"');
|
|
517
|
+
stepNumber += 1;
|
|
518
|
+
}
|
|
519
|
+
if (step.kind === PublishWorkflowStepKind.Build && hasLinuxPlatformTargets(options)) {
|
|
520
|
+
lines.push('', ` # Step ${stepNumber}`, ' - name: ๐ง Build supplemental Linux targets', ` if: ${githubExpression("steps.version.outputs.mode != 'none'")}`, ' run:', ` smoo github-ci nx-run-many --targets "${LINUX_PLATFORM_TARGET_GLOBS.join(',')}" --projects "${githubExpression('steps.version.outputs.projects')}" --collect-outputs "${githubExpression('runner.temp')}/linux-platform-outputs"`);
|
|
521
|
+
stepNumber += 1;
|
|
522
|
+
}
|
|
523
|
+
lines.push('');
|
|
524
|
+
}
|
|
525
|
+
lines.push(' # --- Candidate transfer --------------------------------------------------', '', ` # Step ${stepNumber++}`, ' - name: ๐ฆ Bundle validated release state', ' run:', ` mkdir -p "${githubExpression('runner.temp')}/publish-release-state" && git bundle create`, ` "${githubExpression('runner.temp')}/publish-release-state/release-state.bundle" HEAD --tags && git rev-parse HEAD >`, ` "${githubExpression('runner.temp')}/publish-release-state/release-head"`, '', ` # Step ${stepNumber++}`, ' - name: ๐ค Upload validated release state', ' uses: actions/upload-artifact@v7.0.1', ' with:', ` name: publish-release-state-${githubExpression('github.run_id')}`, ` path: ${githubExpression('runner.temp')}/publish-release-state`, ' if-no-files-found: error', ' retention-days: 1', '', ` # Step ${stepNumber++}`, ' - name: ๐ค Upload validated build outputs', ` if: ${githubExpression("steps.version.outputs.mode != 'none'")}`, ' uses: actions/upload-artifact@v7.0.1', ' with:', ` name: publish-release-outputs-${githubExpression('github.run_id')}`, ` path: ${githubExpression('runner.temp')}/release-build-outputs`, ' if-no-files-found: error', ' retention-days: 1', ' include-hidden-files: true');
|
|
526
|
+
if (hasLinuxPlatformTargets(options)) {
|
|
527
|
+
lines.push('', ` # Step ${stepNumber++}`, ' - name: ๐ค Upload supplemental Linux outputs', ` if: ${githubExpression("steps.version.outputs.mode != 'none'")}`, ' uses: actions/upload-artifact@v7.0.1', ' with:', ` name: publish-linux-outputs-${githubExpression('github.run_id')}`, ` path: ${githubExpression('runner.temp')}/linux-platform-outputs`, ' if-no-files-found: error', ' retention-days: 1', ' include-hidden-files: true');
|
|
528
|
+
}
|
|
529
|
+
lines.push('', ' # --- Cleanup ------------------------------------------------------------', '', ` # Step ${stepNumber}`, ' - name: ๐งน Cleanup and cache Nix/devenv', ` if: ${githubExpression('always()')}`, ' uses: ./.github/actions/save-nix-devenv', ' with:', ` nix-cache-hit: ${githubExpression('steps.setup.outputs.nix-cache-hit')}`, ` devenv-cache-hit: ${githubExpression('steps.setup.outputs.devenv-cache-hit')}`);
|
|
530
|
+
return lines.join('\n').trimEnd();
|
|
531
|
+
}
|
|
532
|
+
function renderMacosPlatformSteps(options) {
|
|
533
|
+
let stepNumber = 4;
|
|
534
|
+
const lines = [
|
|
535
|
+
' # --- Setup --------------------------------------------------------------',
|
|
536
|
+
'',
|
|
537
|
+
' # Step 1: GitHub adds "Set up job" automatically',
|
|
538
|
+
' # Step 2',
|
|
539
|
+
' - name: ๐ฅ Checkout dispatch commit',
|
|
540
|
+
' uses: actions/checkout@v6.0.2',
|
|
541
|
+
' with:',
|
|
542
|
+
` ref: ${githubExpression('github.sha')}`,
|
|
543
|
+
' filter: blob:none',
|
|
544
|
+
' fetch-depth: 0',
|
|
545
|
+
'',
|
|
546
|
+
' # Step 3. Composite action internals do not affect top-level job step',
|
|
547
|
+
' # anchors; update these comments if top-level steps move.',
|
|
548
|
+
' - name: ๐งฑ Setup Nix/devenv',
|
|
549
|
+
' id: setup',
|
|
550
|
+
' uses: ./.github/actions/setup-devenv',
|
|
551
|
+
];
|
|
552
|
+
if (isSmoothBricksCodebasePackageName(options.repoName)) {
|
|
553
|
+
lines.push('', ` # Step ${stepNumber++}`, ' - name: ๐๏ธ Build self-hosted smoo', ' # SmoothBricks self-hosts smoo from source for release commands.', ' run: nx build cli');
|
|
554
|
+
}
|
|
555
|
+
lines.push('', ` # Step ${stepNumber++}`, ' - name: ๐ Build selected macOS and iOS release outputs', ' run:', ` smoo release build-platform-outputs --bump "${githubExpression('inputs.bump')}" --ref "${githubExpression('github.sha')}" --targets "${MACOS_PLATFORM_TARGET_GLOBS.join(',')}" --output`, ` "${githubExpression('runner.temp')}/macos-platform-outputs"`, '', ` # Step ${stepNumber++}`, ' - name: ๐ค Upload macOS platform outputs', ' uses: actions/upload-artifact@v7.0.1', ' with:', ` name: publish-macos-outputs-${githubExpression('github.run_id')}`, ` path: ${githubExpression('runner.temp')}/macos-platform-outputs`, ' if-no-files-found: error', ' retention-days: 1', ' include-hidden-files: true', '', ' # --- Cleanup ------------------------------------------------------------', '', ` # Step ${stepNumber}`, ' - name: ๐งน Cleanup and cache Nix/devenv', ` if: ${githubExpression('always()')}`, ' uses: ./.github/actions/save-nix-devenv', ' with:', ` nix-cache-hit: ${githubExpression('steps.setup.outputs.nix-cache-hit')}`, ` devenv-cache-hit: ${githubExpression('steps.setup.outputs.devenv-cache-hit')}`);
|
|
556
|
+
return lines.join('\n').trimEnd();
|
|
557
|
+
}
|
|
558
|
+
function renderFinalLinuxPublishSteps(options) {
|
|
559
|
+
const mode = 'needs.linux-release-candidate.outputs.mode';
|
|
560
|
+
let stepNumber = 2;
|
|
561
|
+
const lines = [
|
|
562
|
+
' # --- Setup --------------------------------------------------------------',
|
|
563
|
+
'',
|
|
564
|
+
' # Step 1: GitHub adds "Set up job" automatically',
|
|
565
|
+
` # Step ${stepNumber++}`,
|
|
566
|
+
' - name: ๐ฅ Checkout dispatch commit',
|
|
567
|
+
' uses: actions/checkout@v6.0.2',
|
|
568
|
+
' with:',
|
|
569
|
+
` ref: ${githubExpression('github.sha')}`,
|
|
570
|
+
' filter: blob:none',
|
|
571
|
+
' fetch-depth: 0',
|
|
572
|
+
'',
|
|
573
|
+
` # Step ${stepNumber++}`,
|
|
574
|
+
' - name: ๐ฅ Download candidate artifacts',
|
|
575
|
+
' uses: actions/download-artifact@v8.0.1',
|
|
576
|
+
' with:',
|
|
577
|
+
` pattern: publish-*-${githubExpression('github.run_id')}`,
|
|
578
|
+
` path: ${githubExpression('runner.temp')}/publish-artifacts`,
|
|
579
|
+
' merge-multiple: false',
|
|
580
|
+
'',
|
|
581
|
+
` # Step ${stepNumber}. Composite action internals do not affect top-level job step`,
|
|
582
|
+
' # anchors; update these comments if top-level steps move.',
|
|
583
|
+
' - name: ๐งฑ Setup Nix/devenv',
|
|
584
|
+
' id: setup',
|
|
585
|
+
' uses: ./.github/actions/setup-devenv',
|
|
586
|
+
'',
|
|
587
|
+
` # Step ${++stepNumber}`,
|
|
588
|
+
' - name: ๐ค Configure release author',
|
|
589
|
+
' run:',
|
|
590
|
+
' git config user.name "github-actions[bot]" && git config user.email',
|
|
591
|
+
' "41898282+github-actions[bot]@users.noreply.github.com"',
|
|
592
|
+
];
|
|
593
|
+
stepNumber += 1;
|
|
594
|
+
if (isSmoothBricksCodebasePackageName(options.repoName)) {
|
|
595
|
+
lines.push('', ` # Step ${stepNumber++}`, ' - name: ๐๏ธ Build self-hosted smoo', ' # SmoothBricks self-hosts smoo from source for release commands.', ' run: nx build cli');
|
|
596
|
+
}
|
|
597
|
+
lines.push('', ' # --- Repair -------------------------------------------------------------', '', ` # Step ${stepNumber++}`, ' - name: ๐งฏ Repair pending releases', ' run:', ` smoo release repair-pending --ref "${githubExpression('github.sha')}" --platform-outputs "${githubExpression('runner.temp')}/publish-artifacts/publish-macos-outputs-${githubExpression('github.run_id')}/repairs" --dry-run`, ` "${githubExpression('inputs.dry_run')}"`, '', ` # Step ${stepNumber++}`, ' - name: โป๏ธ Restore validated release state', ' run:', ` git fetch "${githubExpression('runner.temp')}/publish-artifacts/publish-release-state-${githubExpression('github.run_id')}/release-state.bundle" HEAD --tags && git reset`, ` --hard "$(cat "${githubExpression('runner.temp')}/publish-artifacts/publish-release-state-${githubExpression('github.run_id')}/release-head")"`);
|
|
598
|
+
lines.push('', ' # --- Validation ---------------------------------------------------------', '', ` # Step ${stepNumber++}`, ' - name: ๐ฆ Apply verified Linux outputs', ` if: ${githubExpression(`${mode} != 'none'`)}`, ' run:', ` smoo github-ci apply-outputs --source-sha "${githubExpression('needs.linux-release-candidate.outputs.release-sha')}"`, ` "${githubExpression('runner.temp')}/publish-artifacts/publish-release-outputs-${githubExpression('github.run_id')}"`);
|
|
599
|
+
if (hasLinuxPlatformTargets(options)) {
|
|
600
|
+
lines.push(` "${githubExpression('runner.temp')}/publish-artifacts/publish-linux-outputs-${githubExpression('github.run_id')}"`);
|
|
601
|
+
}
|
|
602
|
+
lines.push('', ` # Step ${stepNumber++}`, ' - name: ๐ Apply verified macOS outputs', ` if: ${githubExpression(`${mode} != 'none'`)}`, ' run:', ` smoo github-ci apply-outputs --source-sha "${githubExpression('github.sha')}"`, ` "${githubExpression('runner.temp')}/publish-artifacts/publish-macos-outputs-${githubExpression('github.run_id')}/current"`, '', ` # Step ${stepNumber++}`, ` - name: โ
Validate restored release (${githubExpression(mode)})`, ` if: ${githubExpression(`${mode} != 'none'`)}`, ' run: smoo monorepo validate', '', ' # --- Release ------------------------------------------------------------', '', ` # Step ${stepNumber++}`, ` - name: ๐ฆ Publish release (${githubExpression(mode)})`, ' # smoo packs with Bun, then publishes tarballs with npm. Existing', ' # packages must already exist on npm and use trusted publishing/OIDC.', ' # Missing package names are bootstrapped locally before trust setup.', ` run: smoo release publish --bump "${githubExpression('inputs.bump')}" --dry-run "${githubExpression('inputs.dry_run')}"`);
|
|
603
|
+
if (options.deploy === true) {
|
|
604
|
+
lines.push('', ` # Step ${stepNumber++}`, ' - name: ๐ Deploy production', ' if:', " ${{ needs.linux-release-candidate.outputs.mode != 'none' && inputs.deploy_environment == 'production' &&", " inputs.dry_run != 'true' }}", ...deployEnvLines(options), ' run: smoo github-ci nx-deploy --configuration production --mode run-many --verify --name "Deploy Production"');
|
|
605
|
+
}
|
|
606
|
+
lines.push('', ' # --- Cleanup ------------------------------------------------------------', '', ` # Step ${stepNumber}`, ' - name: ๐งน Cleanup and cache Nix/devenv', ` if: ${githubExpression('always()')}`, ' uses: ./.github/actions/save-nix-devenv', ' with:', ` nix-cache-hit: ${githubExpression('steps.setup.outputs.nix-cache-hit')}`, ` devenv-cache-hit: ${githubExpression('steps.setup.outputs.devenv-cache-hit')}`);
|
|
607
|
+
return lines.join('\n').trimEnd();
|
|
608
|
+
}
|
|
609
|
+
function hasMacosPlatformTargets(options) {
|
|
610
|
+
return MACOS_PLATFORM_TARGET_GLOBS.some((glob) => options.platformTargetGlobs?.includes(glob) === true);
|
|
611
|
+
}
|
|
612
|
+
function hasLinuxPlatformTargets(options) {
|
|
613
|
+
return LINUX_PLATFORM_TARGET_GLOBS.some((glob) => options.platformTargetGlobs?.includes(glob) === true);
|
|
614
|
+
}
|
|
377
615
|
function githubExpression(expression) {
|
|
378
616
|
return ['$', '{{ ', expression, ' }}'].join('');
|
|
379
617
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-validation.d.ts","sourceRoot":"","sources":["../../src/monorepo/tool-validation.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,WAAW,EAAyB,MAAM,qBAAqB,CAAC;AAU9E,MAAM,WAAW,UAAU;IACzB,sBAAsB,EAAE,OAAO,CAAC;IAChC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,WAAW,GAAG,IAAI,CAAC;IAChC,MAAM,EAAE,UAAU,CAAC;CACpB;
|
|
1
|
+
{"version":3,"file":"tool-validation.d.ts","sourceRoot":"","sources":["../../src/monorepo/tool-validation.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,WAAW,EAAyB,MAAM,qBAAqB,CAAC;AAU9E,MAAM,WAAW,UAAU;IACzB,sBAAsB,EAAE,OAAO,CAAC;IAChC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,WAAW,GAAG,IAAI,CAAC;IAChC,MAAM,EAAE,UAAU,CAAC;CACpB;AAiCD,wBAAsB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAKzE;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQvD;AAED,wBAAsB,8BAA8B,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAuBtG;AAoCD,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,CAkBlF;AAED,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAY/D;AAED,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CA0B7D;AAED,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,GAAG,IAAI,GAAG,MAAM,CAyBvG;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,MAAM,CAoB/E;AAED,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,WAAW,GAAG,IAAI,GAAG,MAAM,CAWhF;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAmB3D;AA0DD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAQzD"}
|
|
@@ -5,11 +5,11 @@ import { getOrCreateRecord, readJsonObject, recordProperty, setStringProperty, w
|
|
|
5
5
|
import { readPackageJsonObject } from '../lib/workspace.js';
|
|
6
6
|
const rootDevDependencies = [
|
|
7
7
|
{ name: '@biomejs/biome', fallbackVersion: '^2.3.5', minimumVersion: '2.3.0', prefix: '^' },
|
|
8
|
-
{ name: '@nx/js', fallbackVersion: '
|
|
8
|
+
{ name: '@nx/js', fallbackVersion: '23.1.0', minimumVersion: '23.1.0' },
|
|
9
9
|
{
|
|
10
10
|
name: '@smoothbricks/nx-plugin',
|
|
11
|
-
fallbackVersion: '^0.0
|
|
12
|
-
minimumVersion: '0.0
|
|
11
|
+
fallbackVersion: '^0.3.0',
|
|
12
|
+
minimumVersion: '0.3.0',
|
|
13
13
|
prefix: '^',
|
|
14
14
|
useWorkspaceRangeInCodebase: true,
|
|
15
15
|
},
|
|
@@ -21,8 +21,11 @@ const rootDevDependencies = [
|
|
|
21
21
|
prefix: '^',
|
|
22
22
|
useWorkspaceRangeInCodebase: true,
|
|
23
23
|
},
|
|
24
|
-
{ name: 'nx', fallbackVersion: '
|
|
24
|
+
{ name: 'nx', fallbackVersion: '23.1.0', minimumVersion: '23.1.0' },
|
|
25
25
|
{ name: 'prettier', fallbackVersion: '^3.6.1', minimumVersion: '3.6.0', prefix: '^' },
|
|
26
|
+
{ name: 'ttsc', fallbackVersion: '^0.18.4', minimumVersion: '0.18.4', prefix: '^' },
|
|
27
|
+
// Nx and typescript-eslint still load the TypeScript 5.x JavaScript API.
|
|
28
|
+
// Compilation is exclusively delegated to ttsc by the Nx plugin targets.
|
|
26
29
|
{ name: 'typescript', fallbackVersion: '^5.9.3', minimumVersion: '5.9.0', prefix: '^' },
|
|
27
30
|
];
|
|
28
31
|
const cliPackageName = '@smoothbricks/cli';
|
|
@@ -287,16 +290,26 @@ function formatExpectedDependency(policy, dependency) {
|
|
|
287
290
|
}
|
|
288
291
|
export function readToolContext(root) {
|
|
289
292
|
const rootPackage = readPackageJsonObject(join(root, 'package.json'));
|
|
290
|
-
|
|
293
|
+
const toolingPackage = readJsonObject(join(root, 'tooling', 'package.json'));
|
|
294
|
+
const configuredCliRange = recordProperty(toolingPackage ?? {}, 'dependencies')?.[cliPackageName];
|
|
295
|
+
return {
|
|
296
|
+
rootPackage,
|
|
297
|
+
policy: toolPolicy(rootPackage, typeof configuredCliRange === 'string' ? configuredCliRange : null),
|
|
298
|
+
};
|
|
291
299
|
}
|
|
292
|
-
function toolPolicy(rootPackage) {
|
|
300
|
+
function toolPolicy(rootPackage, configuredCliRange) {
|
|
293
301
|
const name = typeof rootPackage?.name === 'string' ? rootPackage.name : null;
|
|
294
302
|
const isCodebase = isSmoothBricksCodebasePackageName(name ?? undefined);
|
|
295
303
|
const toolingName = toolingPackageName(name);
|
|
304
|
+
// A locally linked prerelease can be newer than every published CLI. Keep an existing
|
|
305
|
+
// installable range instead of rewriting the consumer manifest to an unpublished version.
|
|
306
|
+
const publishedCliRange = cliPackageVersion.includes('-') && configuredCliRange && parseVersion(configuredCliRange)
|
|
307
|
+
? configuredCliRange
|
|
308
|
+
: `^${cliPackageVersion}`;
|
|
296
309
|
return {
|
|
297
310
|
isSmoothBricksCodebase: isCodebase,
|
|
298
311
|
toolingPackageName: toolingName,
|
|
299
|
-
cliDependencyRange: isCodebase ? 'workspace:*' :
|
|
312
|
+
cliDependencyRange: isCodebase ? 'workspace:*' : publishedCliRange,
|
|
300
313
|
};
|
|
301
314
|
}
|
|
302
315
|
function toolingPackageName(rootName) {
|
package/dist/nx/index.d.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
export interface ProjectTargets {
|
|
2
2
|
project: string;
|
|
3
|
+
root?: string;
|
|
3
4
|
targets: string[];
|
|
4
5
|
buildDependsOn?: string[];
|
|
6
|
+
targetDependencies?: Map<string, string[]>;
|
|
5
7
|
targetExecutors?: Map<string, string>;
|
|
8
|
+
targetOutputs?: Map<string, string[]>;
|
|
6
9
|
targetScripts?: Map<string, string>;
|
|
7
10
|
}
|
|
8
11
|
export interface CommandInvocation {
|
|
@@ -13,8 +16,11 @@ export declare function nxResetCommand(): CommandInvocation;
|
|
|
13
16
|
export declare function nxShowProjectCommand(project: string): CommandInvocation;
|
|
14
17
|
export declare function nxCacheDirectories(root: string): string[];
|
|
15
18
|
export declare function targetNamesFromNxProjectJson(value: unknown): string[];
|
|
19
|
+
export declare function projectRootFromNxProjectJson(value: unknown): string | undefined;
|
|
16
20
|
export declare function buildDependsOnFromNxProjectJson(value: unknown): string[] | undefined;
|
|
21
|
+
export declare function targetDependenciesFromNxProjectJson(value: unknown): Map<string, string[]>;
|
|
17
22
|
export declare function targetExecutorsFromNxProjectJson(value: unknown): Map<string, string>;
|
|
23
|
+
export declare function targetOutputsFromNxProjectJson(value: unknown): Map<string, string[]>;
|
|
18
24
|
export declare function targetScriptsFromNxProjectJson(value: unknown): Map<string, string>;
|
|
19
25
|
export declare function formatProjectTargetLines(projects: ProjectTargets[]): string;
|
|
20
26
|
export declare function projectNamesWithTarget(projects: ProjectTargets[], target: string): string[];
|