@smoothbricks/cli 0.10.4 โ 0.10.6
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/dist/cli.js +5 -5
- package/dist/github-ci/index.d.ts.map +1 -1
- package/dist/github-ci/index.js +5 -3
- package/dist/lib/json.d.ts +5 -1
- package/dist/lib/json.d.ts.map +1 -1
- package/dist/lib/json.js +18 -16
- package/dist/monorepo/ci-workflow.d.ts +2 -0
- package/dist/monorepo/ci-workflow.d.ts.map +1 -1
- package/dist/monorepo/ci-workflow.js +10 -4
- package/dist/monorepo/github-runs-on.d.ts +14 -0
- package/dist/monorepo/github-runs-on.d.ts.map +1 -0
- package/dist/monorepo/github-runs-on.js +43 -0
- package/dist/monorepo/index.d.ts +3 -3
- package/dist/monorepo/index.d.ts.map +1 -1
- package/dist/monorepo/index.js +20 -8
- package/dist/monorepo/lockfile.d.ts +2 -1
- package/dist/monorepo/lockfile.d.ts.map +1 -1
- package/dist/monorepo/lockfile.js +1 -1
- package/dist/monorepo/managed-files.d.ts +30 -3
- package/dist/monorepo/managed-files.d.ts.map +1 -1
- package/dist/monorepo/managed-files.js +83 -63
- package/dist/monorepo/packs/index.js +2 -2
- package/dist/monorepo/publish-workflow.d.ts +3 -0
- package/dist/monorepo/publish-workflow.d.ts.map +1 -1
- package/dist/monorepo/publish-workflow.js +17 -14
- package/dist/monorepo/tool-validation.d.ts +2 -2
- package/dist/monorepo/tool-validation.d.ts.map +1 -1
- package/dist/monorepo/tool-validation.js +110 -16
- package/dist/release/index.d.ts.map +1 -1
- package/dist/release/index.js +6 -0
- package/managed/raw/envrc +5 -3
- package/managed/raw/patches/ttsc@0.19.3.patch +67 -0
- package/managed/raw/tooling/direnv/github-actions-bootstrap.sh +24 -7
- package/managed/raw/tooling/direnv/setup-environment.ts +23 -3
- package/managed/templates/github/actions/cache-nix-devenv/action.yml +13 -11
- package/managed/templates/github/actions/save-nix-devenv/action.yml +34 -3
- package/managed/templates/github/actions/setup-devenv/action.yml +44 -15
- package/managed/templates/github/workflows/managed-files.yml +64 -12
- package/package.json +2 -2
- package/src/cli.ts +6 -6
- package/src/github-ci/index.test.ts +3 -3
- package/src/github-ci/index.ts +6 -3
- package/src/lib/json.ts +5 -1
- package/src/monorepo/__tests__/ci-workflow.test.ts +37 -1
- package/src/monorepo/__tests__/publish-workflow.test.ts +28 -1
- package/src/monorepo/ci-workflow.ts +14 -4
- package/src/monorepo/github-runs-on.ts +45 -0
- package/src/monorepo/index.ts +20 -8
- package/src/monorepo/lockfile.ts +3 -2
- package/src/monorepo/managed-files.test.ts +49 -0
- package/src/monorepo/managed-files.ts +105 -64
- package/src/monorepo/packs/index.ts +2 -2
- package/src/monorepo/publish-workflow.ts +23 -15
- package/src/monorepo/tool-validation.test.ts +38 -16
- package/src/monorepo/tool-validation.ts +114 -16
- package/src/release/index.ts +6 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { execFileSync } from 'node:child_process';
|
|
2
1
|
import { appendFileSync, existsSync, lstatSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
3
2
|
import { dirname, join, resolve } from 'node:path';
|
|
4
3
|
import { fileURLToPath } from 'node:url';
|
|
5
4
|
import { PLATFORM_TARGET_GLOBS } from '@smoothbricks/nx-plugin/workspace-config-policy';
|
|
6
|
-
|
|
5
|
+
// Nx package exports are CLI-oriented; this is the module the CLI uses for graph + daemon IPC.
|
|
6
|
+
import { createProjectGraphAsync } from 'nx/src/project-graph/project-graph.js';
|
|
7
7
|
import { listReleasePackages, readPackageJson } from '../lib/workspace.js';
|
|
8
8
|
import { renderCiWorkflowYaml } from './ci-workflow.js';
|
|
9
9
|
import { renderPublishWorkflowYaml } from './publish-workflow.js';
|
|
@@ -146,6 +146,11 @@ const managedFiles = [
|
|
|
146
146
|
target: 'tooling/direnv/merge-newer-pins.sh',
|
|
147
147
|
executable: true,
|
|
148
148
|
},
|
|
149
|
+
{
|
|
150
|
+
kind: 'raw',
|
|
151
|
+
source: 'patches/ttsc@0.19.3.patch',
|
|
152
|
+
target: 'patches/ttsc@0.19.3.patch',
|
|
153
|
+
},
|
|
149
154
|
{
|
|
150
155
|
kind: 'generated',
|
|
151
156
|
source: 'ci-workflow',
|
|
@@ -194,8 +199,8 @@ const managedFiles = [
|
|
|
194
199
|
},
|
|
195
200
|
];
|
|
196
201
|
const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..', '..');
|
|
197
|
-
export function applyManagedFiles(root, mode) {
|
|
198
|
-
const context = getManagedFileContext(root);
|
|
202
|
+
export async function applyManagedFiles(root, mode) {
|
|
203
|
+
const context = await getManagedFileContext(root);
|
|
199
204
|
return managedFiles.map((file) => applyManagedFile(root, file, mode, context));
|
|
200
205
|
}
|
|
201
206
|
function applyManagedFile(root, file, mode, context) {
|
|
@@ -239,6 +244,7 @@ function getManagedContent(file, context) {
|
|
|
239
244
|
deploy: context.hasStagingDeployTargets,
|
|
240
245
|
deployProvider: context.stagingDeployProvider,
|
|
241
246
|
pushBranches: context.ciPushBranches,
|
|
247
|
+
runsOn: context.ciRunsOn,
|
|
242
248
|
});
|
|
243
249
|
}
|
|
244
250
|
if (file.source === 'publish-workflow') {
|
|
@@ -247,6 +253,7 @@ function getManagedContent(file, context) {
|
|
|
247
253
|
deployProvider: context.productionDeployProvider,
|
|
248
254
|
repoName: context.repoName,
|
|
249
255
|
platformTargetGlobs: context.platformTargetGlobs,
|
|
256
|
+
runsOn: context.ciRunsOn,
|
|
250
257
|
});
|
|
251
258
|
}
|
|
252
259
|
throw new Error(`Unknown generated managed file source ${file.source}`);
|
|
@@ -259,13 +266,16 @@ function getManagedContent(file, context) {
|
|
|
259
266
|
}
|
|
260
267
|
return renderTemplate(context, content);
|
|
261
268
|
}
|
|
262
|
-
function getManagedFileContext(root) {
|
|
269
|
+
async function getManagedFileContext(root) {
|
|
263
270
|
const packageJson = readPackageJson(join(root, 'package.json'));
|
|
264
271
|
const repoName = packageJson?.name ?? 'monorepo';
|
|
265
272
|
const ciPushBranches = getCiPushBranches(packageJson?.json);
|
|
266
|
-
const
|
|
267
|
-
|
|
268
|
-
const
|
|
273
|
+
const ciRunsOn = getCiRunsOn(packageJson?.json);
|
|
274
|
+
// In-process Nx API โ daemon socket (no second Node/`nx` CLI process).
|
|
275
|
+
const nxProjects = await loadNxGraphProjects(root);
|
|
276
|
+
const stagingDeploy = deployTargetInfoFromProjects(nxProjects, 'staging');
|
|
277
|
+
const productionDeploy = deployTargetInfoFromProjects(nxProjects, 'production');
|
|
278
|
+
const platformTargetGlobs = platformTargetGlobsForTest(targetNamesFromProjects(nxProjects));
|
|
269
279
|
const nodeModulesCacheKey = existsSync(join(root, 'bun.lock'))
|
|
270
280
|
? `$${"{{ hashFiles('bun.lock', 'package.json', 'packages/*/package.json') }}"}`
|
|
271
281
|
: `$${"{{ hashFiles('bun.lockb', 'package.json', 'packages/*/package.json') }}"}`;
|
|
@@ -276,6 +286,7 @@ function getManagedFileContext(root) {
|
|
|
276
286
|
stagingDeployProvider: stagingDeploy.provider,
|
|
277
287
|
productionDeployProvider: productionDeploy.provider,
|
|
278
288
|
ciPushBranches,
|
|
289
|
+
ciRunsOn,
|
|
279
290
|
nodeModulesCacheKey,
|
|
280
291
|
repoName,
|
|
281
292
|
platformTargetGlobs,
|
|
@@ -288,77 +299,86 @@ export function platformTargetGlobsForTest(targetNames) {
|
|
|
288
299
|
return names.some((name) => name.endsWith(suffix));
|
|
289
300
|
});
|
|
290
301
|
}
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
302
|
+
/**
|
|
303
|
+
* Load resolved project nodes via Nx's programmatic API.
|
|
304
|
+
*
|
|
305
|
+
* `createProjectGraphAsync` is what the CLI uses: with the daemon up it speaks the
|
|
306
|
+
* daemon unix socket instead of rebuilding the graph in a fresh Node process.
|
|
307
|
+
* Spawning `nx graph` / `nx show` only added CLI boot + plugin-worker overhead on
|
|
308
|
+
* top of that. smoo runs under Bun; Bun can import this CJS module directly.
|
|
309
|
+
*/
|
|
310
|
+
async function loadNxGraphProjects(root) {
|
|
311
|
+
const prevCwd = process.cwd();
|
|
312
|
+
process.chdir(root);
|
|
313
|
+
try {
|
|
314
|
+
const graph = (await createProjectGraphAsync());
|
|
315
|
+
const out = {};
|
|
316
|
+
for (const [name, node] of Object.entries(graph.nodes)) {
|
|
317
|
+
out[name] = { data: { targets: node.data?.targets ?? {} } };
|
|
318
|
+
}
|
|
319
|
+
return out;
|
|
320
|
+
}
|
|
321
|
+
finally {
|
|
322
|
+
process.chdir(prevCwd);
|
|
300
323
|
}
|
|
324
|
+
}
|
|
325
|
+
function targetsOfProject(node) {
|
|
326
|
+
return node.data?.targets ?? node.targets ?? {};
|
|
327
|
+
}
|
|
328
|
+
/** Test seam: collect target names from a graph.nodes map. */
|
|
329
|
+
export function targetNamesFromProjects(nodes) {
|
|
301
330
|
const targetNames = new Set();
|
|
302
|
-
for (const
|
|
303
|
-
const
|
|
304
|
-
|
|
305
|
-
encoding: 'utf8',
|
|
306
|
-
stdio: ['ignore', 'pipe', 'inherit'],
|
|
307
|
-
});
|
|
308
|
-
const projectJson = parseNxProjectJsonText(projectOutput);
|
|
309
|
-
const targets = projectJson?.targets;
|
|
310
|
-
if (targets) {
|
|
311
|
-
for (const targetName of Object.keys(targets)) {
|
|
312
|
-
targetNames.add(targetName);
|
|
313
|
-
}
|
|
331
|
+
for (const node of Object.values(nodes)) {
|
|
332
|
+
for (const name of Object.keys(targetsOfProject(node))) {
|
|
333
|
+
targetNames.add(name);
|
|
314
334
|
}
|
|
315
335
|
}
|
|
316
336
|
return [...targetNames];
|
|
317
337
|
}
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
.replaceAll('{{REPO_NAME}}', context.repoName)
|
|
321
|
-
.replaceAll('__SMOO_CI_PUSH_BRANCHES__', renderYamlFlowList(context.ciPushBranches))
|
|
322
|
-
.replaceAll('{{NODE_MODULES_CACHE_KEY}}', context.nodeModulesCacheKey);
|
|
323
|
-
}
|
|
324
|
-
function getDeployTargetInfo(root, configuration) {
|
|
325
|
-
const output = execFileSync('nx', ['show', 'projects', '--withTarget', 'deploy', '--json'], {
|
|
326
|
-
cwd: root,
|
|
327
|
-
encoding: 'utf8',
|
|
328
|
-
stdio: ['ignore', 'pipe', 'inherit'],
|
|
329
|
-
});
|
|
330
|
-
const projects = parseStringArrayText(output);
|
|
331
|
-
if (!projects) {
|
|
332
|
-
return { exists: false };
|
|
333
|
-
}
|
|
338
|
+
/** Test seam: deploy configuration presence/provider from graph nodes. */
|
|
339
|
+
export function deployTargetInfoFromProjects(nodes, configuration) {
|
|
334
340
|
let exists = false;
|
|
335
341
|
let provider;
|
|
336
|
-
for (const
|
|
337
|
-
const
|
|
338
|
-
if (!
|
|
342
|
+
for (const node of Object.values(nodes)) {
|
|
343
|
+
const info = deployTargetInfoFromTargets(targetsOfProject(node), configuration);
|
|
344
|
+
if (!info.exists) {
|
|
339
345
|
continue;
|
|
340
346
|
}
|
|
341
347
|
exists = true;
|
|
342
|
-
provider ??=
|
|
348
|
+
provider ??= info.provider;
|
|
343
349
|
}
|
|
344
350
|
return { exists, provider };
|
|
345
351
|
}
|
|
346
|
-
function
|
|
347
|
-
const
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
const projectJson = parseNxProjectJsonText(output);
|
|
353
|
-
const deploy = projectJson?.targets?.deploy;
|
|
354
|
-
const config = deploy?.configurations?.[configuration];
|
|
352
|
+
function deployTargetInfoFromTargets(targets, configuration) {
|
|
353
|
+
const deploy = targets.deploy;
|
|
354
|
+
if (!deploy) {
|
|
355
|
+
return { exists: false };
|
|
356
|
+
}
|
|
357
|
+
const config = deploy.configurations?.[configuration];
|
|
355
358
|
if (!config) {
|
|
356
359
|
return { exists: false };
|
|
357
360
|
}
|
|
358
|
-
const commandValue = config.command ?? config.options?.command ?? deploy
|
|
361
|
+
const commandValue = config.command ?? config.options?.command ?? deploy.options?.command ?? deploy.command;
|
|
359
362
|
const command = typeof commandValue === 'string' ? commandValue : '';
|
|
360
363
|
return { exists: true, provider: command.includes('wrangler ') ? 'cloudflare' : undefined };
|
|
361
364
|
}
|
|
365
|
+
function renderTemplate(context, template) {
|
|
366
|
+
return template
|
|
367
|
+
.replaceAll('{{REPO_NAME}}', context.repoName)
|
|
368
|
+
.replaceAll('__SMOO_CI_PUSH_BRANCHES__', renderYamlFlowList(context.ciPushBranches))
|
|
369
|
+
.replaceAll('{{NODE_MODULES_CACHE_KEY}}', context.nodeModulesCacheKey);
|
|
370
|
+
}
|
|
371
|
+
function getCiRunsOn(packageJson) {
|
|
372
|
+
const configured = packageJson?.smoo?.github?.runsOn;
|
|
373
|
+
if (configured === undefined) {
|
|
374
|
+
return 'ubuntu-latest';
|
|
375
|
+
}
|
|
376
|
+
if (typeof configured === 'string') {
|
|
377
|
+
return configured.length > 0 ? configured : 'ubuntu-latest';
|
|
378
|
+
}
|
|
379
|
+
const labels = configured.filter((label) => label.length > 0);
|
|
380
|
+
return labels.length > 0 ? labels : 'ubuntu-latest';
|
|
381
|
+
}
|
|
362
382
|
function getCiPushBranches(packageJson) {
|
|
363
383
|
const configured = readCiPushBranches(packageJson);
|
|
364
384
|
return configured.length > 0 ? configured : ['main'];
|
|
@@ -379,8 +399,8 @@ export function printResults(results) {
|
|
|
379
399
|
console.log(`${result.action.padEnd(15)} ${result.target}`);
|
|
380
400
|
}
|
|
381
401
|
}
|
|
382
|
-
export function validateManagedFiles(root) {
|
|
383
|
-
const results = applyManagedFiles(root, 'check');
|
|
402
|
+
export async function validateManagedFiles(root) {
|
|
403
|
+
const results = await applyManagedFiles(root, 'check');
|
|
384
404
|
printResults(results);
|
|
385
405
|
const failures = results.filter((result) => result.action === 'drifted').length;
|
|
386
406
|
if (failures > 0) {
|
|
@@ -398,8 +418,8 @@ export function validateManagedFiles(root) {
|
|
|
398
418
|
* Under GitHub Actions the drifted-file count is published as the step output
|
|
399
419
|
* `drifted`, so downstream steps gate declaratively instead of parsing logs.
|
|
400
420
|
*/
|
|
401
|
-
export function warnOnManagedFileDrift(root) {
|
|
402
|
-
const results = applyManagedFiles(root, 'check');
|
|
421
|
+
export async function warnOnManagedFileDrift(root) {
|
|
422
|
+
const results = await applyManagedFiles(root, 'check');
|
|
403
423
|
printResults(results);
|
|
404
424
|
const drifted = results.filter((result) => result.action === 'drifted');
|
|
405
425
|
if (process.env.GITHUB_OUTPUT) {
|
|
@@ -40,10 +40,10 @@ const packs = [
|
|
|
40
40
|
// Managed-file drift is derived state (CLI template x pinned version) with
|
|
41
41
|
// its own remediation flow; it warns instead of failing so validation only
|
|
42
42
|
// blocks on actual package issues. See warnOnManagedFileDrift.
|
|
43
|
-
warnOnManagedFileDrift(ctx.root);
|
|
43
|
+
await warnOnManagedFileDrift(ctx.root);
|
|
44
44
|
return (runtimeFailures +
|
|
45
45
|
validateRootPackagePolicy(ctx.root) +
|
|
46
|
-
validateToolConfig(ctx.root) +
|
|
46
|
+
(await validateToolConfig(ctx.root)) +
|
|
47
47
|
validateNxProjectNames(ctx.root) +
|
|
48
48
|
validateNxReleaseConfig(ctx.root) +
|
|
49
49
|
validateBunLockfileVersions(ctx.root) +
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type WorkflowRunsOn } from './github-runs-on.js';
|
|
1
2
|
export type PublishWorkflowBump = 'auto' | 'patch' | 'minor' | 'major' | 'prerelease';
|
|
2
3
|
export type PublishWorkflowCondition = 'version-mode-not-none' | 'deploy-production' | 'failure' | 'always';
|
|
3
4
|
export type PublishWorkflowNxTarget = 'build' | 'lint' | 'test';
|
|
@@ -35,6 +36,8 @@ export interface PublishWorkflowDefinitionOptions {
|
|
|
35
36
|
deployProvider?: 'cloudflare';
|
|
36
37
|
repoName?: string;
|
|
37
38
|
platformTargetGlobs?: readonly string[];
|
|
39
|
+
/** Linux jobs only. Default ubuntu-latest. Same smoo.github.runsOn as CI. */
|
|
40
|
+
runsOn?: WorkflowRunsOn;
|
|
38
41
|
}
|
|
39
42
|
export interface PublishWorkflowInputs {
|
|
40
43
|
bump: PublishWorkflowBump;
|
|
@@ -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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"}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import synchronizedPrettier from '@prettier/sync';
|
|
3
3
|
import { LINUX_PLATFORM_TARGET_GLOBS, MACOS_PLATFORM_TARGET_GLOBS, } from '@smoothbricks/nx-plugin/workspace-config-policy';
|
|
4
4
|
import { isSmoothBricksCodebasePackageName } from '../lib/cli-package.js';
|
|
5
|
+
import { renderRunsOnLine } from './github-runs-on.js';
|
|
5
6
|
const PUBLISH_WORKFLOW_FORMAT_OPTIONS = Object.freeze({
|
|
6
7
|
parser: 'yaml',
|
|
7
8
|
printWidth: 120,
|
|
@@ -338,7 +339,8 @@ function yamlLinesForStep(step, options) {
|
|
|
338
339
|
case PublishWorkflowStepKind.UploadTraceDbs:
|
|
339
340
|
return [
|
|
340
341
|
` - name: ${step.name}`,
|
|
341
|
-
|
|
342
|
+
' # Default is success(); failure() uploads traces only when the job already failed.',
|
|
343
|
+
' if: failure()',
|
|
342
344
|
' uses: actions/upload-artifact@v7.0.1',
|
|
343
345
|
' with:',
|
|
344
346
|
` name: trace-results-${githubExpression('github.run_id')}`,
|
|
@@ -362,7 +364,8 @@ function yamlLinesForStep(step, options) {
|
|
|
362
364
|
case PublishWorkflowStepKind.SaveNixDevenv:
|
|
363
365
|
return [
|
|
364
366
|
` - name: ${step.name}`,
|
|
365
|
-
|
|
367
|
+
' # success() is default; always() still saves GH Nix cache after a red job.',
|
|
368
|
+
' if: always()',
|
|
366
369
|
' uses: ./.github/actions/save-nix-devenv',
|
|
367
370
|
' with:',
|
|
368
371
|
` nix-cache-hit: ${githubExpression('steps.setup.outputs.nix-cache-hit')}`,
|
|
@@ -392,7 +395,7 @@ function deployEnvLines(options) {
|
|
|
392
395
|
}
|
|
393
396
|
function conditionalRunStep(step, run) {
|
|
394
397
|
const condition = "steps.version.outputs.mode != 'none'";
|
|
395
|
-
return [` - name: ${step.name}`, ` if: ${
|
|
398
|
+
return [` - name: ${step.name}`, ` if: ${condition}`, ` run: ${run}`];
|
|
396
399
|
}
|
|
397
400
|
function renderSingleJobPublishWorkflowSteps(steps, options) {
|
|
398
401
|
const lines = [];
|
|
@@ -402,7 +405,7 @@ function renderSingleJobPublishWorkflowSteps(steps, options) {
|
|
|
402
405
|
lines.push(...yamlLinesForStep(step, options));
|
|
403
406
|
lines.push('');
|
|
404
407
|
if (step.kind === PublishWorkflowStepKind.Build) {
|
|
405
|
-
lines.push(' - name: ๐ง Build supplemental Linux targets',
|
|
408
|
+
lines.push(' - name: ๐ง Build supplemental Linux targets', " if: steps.version.outputs.mode != 'none'", ` run: smoo github-ci nx-run-many --targets "${LINUX_PLATFORM_TARGET_GLOBS.join(',')}" --projects "${githubExpression('steps.version.outputs.projects')}"`, '');
|
|
406
409
|
}
|
|
407
410
|
}
|
|
408
411
|
return `${lines.join('\n').trimEnd()}\n`;
|
|
@@ -447,7 +450,7 @@ defaults:
|
|
|
447
450
|
|
|
448
451
|
jobs:
|
|
449
452
|
linux-release-candidate:
|
|
450
|
-
|
|
453
|
+
${renderRunsOnLine(options.runsOn)}
|
|
451
454
|
permissions:
|
|
452
455
|
contents: write
|
|
453
456
|
id-token: none
|
|
@@ -508,7 +511,7 @@ function renderLinuxReleaseCandidateSteps(steps, options) {
|
|
|
508
511
|
lines.push(` - name: ${step.name}`, ' uses: actions/checkout@v6.0.2', ' with:', ` ref: ${githubExpression('github.sha')}`, ' filter: blob:none', ' fetch-depth: 0');
|
|
509
512
|
}
|
|
510
513
|
else if (step.kind === PublishWorkflowStepKind.Build) {
|
|
511
|
-
lines.push(` - name: ${step.name}`,
|
|
514
|
+
lines.push(` - name: ${step.name}`, " if: 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"`);
|
|
512
515
|
}
|
|
513
516
|
else {
|
|
514
517
|
lines.push(...yamlLinesForStep(step, options));
|
|
@@ -519,16 +522,16 @@ function renderLinuxReleaseCandidateSteps(steps, options) {
|
|
|
519
522
|
stepNumber += 1;
|
|
520
523
|
}
|
|
521
524
|
if (step.kind === PublishWorkflowStepKind.Build && hasLinuxPlatformTargets(options)) {
|
|
522
|
-
lines.push('', ` # Step ${stepNumber}`, ' - name: ๐ง Build supplemental Linux targets',
|
|
525
|
+
lines.push('', ` # Step ${stepNumber}`, ' - name: ๐ง Build supplemental Linux targets', " if: 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"`);
|
|
523
526
|
stepNumber += 1;
|
|
524
527
|
}
|
|
525
528
|
lines.push('');
|
|
526
529
|
}
|
|
527
|
-
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',
|
|
530
|
+
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: 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');
|
|
528
531
|
if (hasLinuxPlatformTargets(options)) {
|
|
529
|
-
lines.push('', ` # Step ${stepNumber++}`, ' - name: ๐ค Upload supplemental Linux outputs',
|
|
532
|
+
lines.push('', ` # Step ${stepNumber++}`, ' - name: ๐ค Upload supplemental Linux outputs', " if: 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');
|
|
530
533
|
}
|
|
531
|
-
lines.push('', ' # --- Cleanup ------------------------------------------------------------', '', ` # Step ${stepNumber}`, ' - name: ๐งน Cleanup and cache Nix/devenv',
|
|
534
|
+
lines.push('', ' # --- Cleanup ------------------------------------------------------------', '', ` # Step ${stepNumber}`, ' - name: ๐งน Cleanup and cache Nix/devenv', ' # success() is default; always() still saves GH Nix cache after a red job.', ' if: 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')}`);
|
|
532
535
|
return lines.join('\n').trimEnd();
|
|
533
536
|
}
|
|
534
537
|
function renderMacosPlatformSteps(options) {
|
|
@@ -554,7 +557,7 @@ function renderMacosPlatformSteps(options) {
|
|
|
554
557
|
if (isSmoothBricksCodebasePackageName(options.repoName)) {
|
|
555
558
|
lines.push('', ` # Step ${stepNumber++}`, ' - name: ๐๏ธ Build self-hosted smoo', ' # SmoothBricks self-hosts smoo from source for release commands.', ' run: nx build cli');
|
|
556
559
|
}
|
|
557
|
-
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',
|
|
560
|
+
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', ' # success() is default; always() still saves GH Nix cache after a red job.', ' if: 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')}`);
|
|
558
561
|
return lines.join('\n').trimEnd();
|
|
559
562
|
}
|
|
560
563
|
function renderFinalLinuxPublishSteps(options) {
|
|
@@ -597,15 +600,15 @@ function renderFinalLinuxPublishSteps(options) {
|
|
|
597
600
|
lines.push('', ` # Step ${stepNumber++}`, ' - name: ๐๏ธ Build self-hosted smoo', ' # SmoothBricks self-hosts smoo from source for release commands.', ' run: nx build cli');
|
|
598
601
|
}
|
|
599
602
|
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")"`);
|
|
600
|
-
lines.push('', ' # --- Validation ---------------------------------------------------------', '', ` # Step ${stepNumber++}`, ' - name: ๐ฆ Apply verified Linux outputs', ` if: ${
|
|
603
|
+
lines.push('', ' # --- Validation ---------------------------------------------------------', '', ` # Step ${stepNumber++}`, ' - name: ๐ฆ Apply verified Linux outputs', ` if: ${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')}"`);
|
|
601
604
|
if (hasLinuxPlatformTargets(options)) {
|
|
602
605
|
lines.push(` "${githubExpression('runner.temp')}/publish-artifacts/publish-linux-outputs-${githubExpression('github.run_id')}"`);
|
|
603
606
|
}
|
|
604
|
-
lines.push('', ` # Step ${stepNumber++}`, ' - name: ๐ Apply verified macOS outputs', ` if: ${
|
|
607
|
+
lines.push('', ` # Step ${stepNumber++}`, ' - name: ๐ Apply verified macOS outputs', ` if: ${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: ${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')}"`);
|
|
605
608
|
if (options.deploy === true) {
|
|
606
609
|
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"');
|
|
607
610
|
}
|
|
608
|
-
lines.push('', ' # --- Cleanup ------------------------------------------------------------', '', ` # Step ${stepNumber}`, ' - name: ๐งน Cleanup and cache Nix/devenv',
|
|
611
|
+
lines.push('', ' # --- Cleanup ------------------------------------------------------------', '', ` # Step ${stepNumber}`, ' - name: ๐งน Cleanup and cache Nix/devenv', ' # success() is default; always() still saves GH Nix cache after a red job.', ' if: 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')}`);
|
|
609
612
|
return lines.join('\n').trimEnd();
|
|
610
613
|
}
|
|
611
614
|
function hasMacosPlatformTargets(options) {
|
|
@@ -9,7 +9,7 @@ export interface ToolContext {
|
|
|
9
9
|
policy: ToolPolicy;
|
|
10
10
|
}
|
|
11
11
|
export declare function applyToolConfigDefaults(root: string): Promise<void>;
|
|
12
|
-
export declare function validateToolConfig(root: string): number
|
|
12
|
+
export declare function validateToolConfig(root: string): Promise<number>;
|
|
13
13
|
export declare function applyRootDevDependencyDefaults(root: string, context: ToolContext): Promise<void>;
|
|
14
14
|
export declare function applyToolingPackageDefaults(root: string, policy: ToolPolicy): void;
|
|
15
15
|
export declare function applyToolingWorkspaceDefault(root: string): void;
|
|
@@ -18,5 +18,5 @@ export declare function validateRootDevDependencies(policy: ToolPolicy, rootPack
|
|
|
18
18
|
export declare function validateToolingPackage(root: string, policy: ToolPolicy): number;
|
|
19
19
|
export declare function validateToolingWorkspace(rootPackage: PackageJson | null): number;
|
|
20
20
|
export declare function validateDevenvPackages(root: string): number;
|
|
21
|
-
export declare function readToolContext(root: string): ToolContext
|
|
21
|
+
export declare function readToolContext(root: string): Promise<ToolContext>;
|
|
22
22
|
//# sourceMappingURL=tool-validation.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-validation.d.ts","sourceRoot":"","sources":["../../src/monorepo/tool-validation.ts"],"names":[],"mappings":"AAWA,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":"AAWA,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;AAkDD,wBAAsB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAKzE;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAStE;AAED,wBAAsB,8BAA8B,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAwBtG;AA2CD,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;AAsBD,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,CAqB3D;AAsED,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAQxE"}
|