@smoothbricks/cli 0.10.9 → 0.10.10
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 +6 -5
- package/dist/github-ci/index.d.ts +8 -6
- package/dist/github-ci/index.d.ts.map +1 -1
- package/dist/github-ci/index.js +35 -35
- package/dist/monorepo/ci-workflow.d.ts +3 -0
- package/dist/monorepo/ci-workflow.d.ts.map +1 -1
- package/dist/monorepo/ci-workflow.js +59 -15
- package/dist/monorepo/managed-files.d.ts +1 -0
- package/dist/monorepo/managed-files.d.ts.map +1 -1
- package/dist/monorepo/managed-files.js +15 -5
- package/dist/monorepo/publish-workflow.d.ts +2 -2
- package/dist/monorepo/publish-workflow.d.ts.map +1 -1
- package/dist/monorepo/publish-workflow.js +6 -6
- package/dist/wrangler/cloudflare.d.ts +1 -1
- package/dist/wrangler/cloudflare.d.ts.map +1 -1
- package/dist/wrangler/{deploy-environment.d.ts → deploy-stage.d.ts} +6 -6
- package/dist/wrangler/deploy-stage.d.ts.map +1 -0
- package/dist/wrangler/{deploy-environment.js → deploy-stage.js} +26 -26
- package/dist/wrangler/stage.d.ts +58 -0
- package/dist/wrangler/stage.d.ts.map +1 -0
- package/dist/wrangler/{environment.js → stage.js} +44 -44
- package/package.json +7 -7
- package/src/cli.ts +9 -7
- package/src/github-ci/index.test.ts +101 -32
- package/src/github-ci/index.ts +51 -45
- package/src/monorepo/__tests__/ci-workflow.test.ts +87 -49
- package/src/monorepo/__tests__/publish-workflow.test.ts +8 -8
- package/src/monorepo/ci-workflow.ts +67 -14
- package/src/monorepo/managed-files.test.ts +26 -5
- package/src/monorepo/managed-files.ts +18 -5
- package/src/monorepo/publish-workflow.ts +9 -9
- package/src/wrangler/cloudflare.ts +1 -1
- package/src/wrangler/{deploy-environment.test.ts → deploy-stage.test.ts} +11 -11
- package/src/wrangler/{deploy-environment.ts → deploy-stage.ts} +41 -41
- package/src/wrangler/{environment.test.ts → stage.test.ts} +15 -15
- package/src/wrangler/{environment.ts → stage.ts} +49 -52
- package/dist/wrangler/deploy-environment.d.ts.map +0 -1
- package/dist/wrangler/environment.d.ts +0 -58
- package/dist/wrangler/environment.d.ts.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -4,7 +4,7 @@ import { cliPackageVersion } from './lib/cli-package.js';
|
|
|
4
4
|
import { findRepoRoot } from './lib/run.js';
|
|
5
5
|
import { ensureChromium } from './playwright/index.js';
|
|
6
6
|
import { resolvePrConflicts } from './pr/index.js';
|
|
7
|
-
import { cleanupPullRequest,
|
|
7
|
+
import { cleanupPullRequest, deployStage } from './wrangler/deploy-stage.js';
|
|
8
8
|
import { scaffold } from './wrangler/scaffold.js';
|
|
9
9
|
export async function runCli(argv = process.argv.slice(2)) {
|
|
10
10
|
const program = buildProgram();
|
|
@@ -285,6 +285,7 @@ function buildProgram() {
|
|
|
285
285
|
.option('--step <step>')
|
|
286
286
|
.option('--mode <mode>', 'auto, affected, or run-many', 'auto')
|
|
287
287
|
.option('--configuration <configuration>')
|
|
288
|
+
.option('--stage <stage>')
|
|
288
289
|
.action(async (options) => {
|
|
289
290
|
const { githubCiNxSmart } = await import('./github-ci/index.js');
|
|
290
291
|
await githubCiNxSmart(await findRepoRoot(), options);
|
|
@@ -310,7 +311,7 @@ function buildProgram() {
|
|
|
310
311
|
});
|
|
311
312
|
githubCi
|
|
312
313
|
.command('nx-deploy')
|
|
313
|
-
.option('--
|
|
314
|
+
.option('--stage <stage>', 'explicit staging, production, or prN override')
|
|
314
315
|
.option('--mode <mode>', 'auto, affected, or run-many', 'run-many')
|
|
315
316
|
.option('--name <name>')
|
|
316
317
|
.option('--step <step>')
|
|
@@ -347,10 +348,10 @@ function buildProgram() {
|
|
|
347
348
|
scaffold(await findRepoRoot(), project, { force: options.force });
|
|
348
349
|
});
|
|
349
350
|
wrangler
|
|
350
|
-
.command('deploy-
|
|
351
|
-
.requiredOption('--
|
|
351
|
+
.command('deploy-stage')
|
|
352
|
+
.requiredOption('--stage <stage>', 'staging, production, or prN')
|
|
352
353
|
.action(async (options) => {
|
|
353
|
-
await
|
|
354
|
+
await deployStage(process.cwd(), options.stage);
|
|
354
355
|
});
|
|
355
356
|
wrangler
|
|
356
357
|
.command('cleanup-pr')
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type ProjectTargets } from '../nx/index.js';
|
|
2
|
-
import { type
|
|
2
|
+
import { type DeploymentStage } from '../wrangler/stage.js';
|
|
3
3
|
import type { NxTargetRun } from './outputs.js';
|
|
4
4
|
export interface GithubActionsEventPayload {
|
|
5
5
|
action?: string;
|
|
@@ -18,13 +18,14 @@ export interface GithubActionsEventPayload {
|
|
|
18
18
|
}
|
|
19
19
|
type NxSmartMode = 'auto' | 'affected' | 'run-many';
|
|
20
20
|
export declare function cleanupGithubCiCache(root: string): Promise<void>;
|
|
21
|
-
export declare function nxSmartArgs(target: string, mode: 'affected' | 'run-many', configuration?: string): string[];
|
|
21
|
+
export declare function nxSmartArgs(target: string, mode: 'affected' | 'run-many', configuration?: string, stage?: string): string[];
|
|
22
22
|
export declare function githubCiNxSmart(root: string, options: {
|
|
23
23
|
target: string;
|
|
24
24
|
name?: string;
|
|
25
25
|
step?: string;
|
|
26
26
|
mode?: NxSmartMode;
|
|
27
27
|
configuration?: string;
|
|
28
|
+
stage?: string;
|
|
28
29
|
}): Promise<void>;
|
|
29
30
|
export interface NxRunManyOptions {
|
|
30
31
|
targets: string;
|
|
@@ -45,7 +46,7 @@ export declare function readGitHeadSha(root: string): Promise<string>;
|
|
|
45
46
|
export declare function githubCiNxRunMany(root: string, options: NxRunManyOptions): Promise<ExpandedNxTargetRuns>;
|
|
46
47
|
export declare function githubCiApplyOutputs(root: string, directories: string[], expectedSourceSha: string): Promise<void>;
|
|
47
48
|
export interface GithubCiNxDeployOptions {
|
|
48
|
-
|
|
49
|
+
stage?: string;
|
|
49
50
|
mode?: NxSmartMode;
|
|
50
51
|
name?: string;
|
|
51
52
|
step?: string;
|
|
@@ -55,14 +56,15 @@ export interface GithubCiNxDeployDependencies {
|
|
|
55
56
|
listProjects?: (root: string, target: string, mode: 'affected' | 'run-many') => Promise<string[]>;
|
|
56
57
|
runNx?: (args: string[], root: string) => Promise<number>;
|
|
57
58
|
appendSummary?: (summaryPath: string, content: string) => Promise<void>;
|
|
58
|
-
|
|
59
|
+
appendOutput?: (outputPath: string, content: string) => Promise<void>;
|
|
60
|
+
publishDeployment?: (stage: `pr${number}`, url: string) => Promise<void>;
|
|
59
61
|
setStatus?: (state: 'pending' | 'success' | 'failure') => Promise<void>;
|
|
60
62
|
processEnv?: NodeJS.ProcessEnv;
|
|
61
63
|
eventPayload?: GithubActionsEventPayload;
|
|
62
64
|
}
|
|
63
65
|
export declare function githubCiNxDeploy(root: string, options: GithubCiNxDeployOptions, dependencies?: GithubCiNxDeployDependencies): Promise<void>;
|
|
64
|
-
export declare function
|
|
65
|
-
export declare function
|
|
66
|
+
export declare function resolveDeploymentStage(explicit: string | undefined, environment: NodeJS.ProcessEnv, event: GithubActionsEventPayload | undefined): DeploymentStage;
|
|
67
|
+
export declare function selectStageDeployProjects(candidates: string[], loadProject: (project: string) => Promise<unknown>): Promise<string[]>;
|
|
66
68
|
export interface GithubApiProcessResult {
|
|
67
69
|
exitCode: number;
|
|
68
70
|
stdout: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/github-ci/index.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,KAAK,cAAc,EAAsB,MAAM,gBAAgB,CAAC;AACzE,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/github-ci/index.ts"],"names":[],"mappings":"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"}
|
package/dist/github-ci/index.js
CHANGED
|
@@ -7,7 +7,7 @@ import typia from 'typia';
|
|
|
7
7
|
import { parseStringArrayText } from '../lib/json.js';
|
|
8
8
|
import { decode, run, runStatus } from '../lib/run.js';
|
|
9
9
|
import { readProjectTargets } from '../nx/index.js';
|
|
10
|
-
import {
|
|
10
|
+
import { isPullRequestStage, parseDeploymentStage, pullRequestStage } from '../wrangler/stage.js';
|
|
11
11
|
const parseGithubActionsEvent = (() => {
|
|
12
12
|
const _ip0 = input => undefined === input["full_name"] || "string" === typeof input["full_name"];
|
|
13
13
|
const _io0 = input => (undefined === input.action || "string" === typeof input.action) && (undefined === input.repository || "object" === typeof input.repository && null !== input.repository && false === Array.isArray(input.repository) && _io1(input.repository)) && (undefined === input.pull_request || "object" === typeof input.pull_request && null !== input.pull_request && false === Array.isArray(input.pull_request) && _io2(input.pull_request));
|
|
@@ -138,11 +138,14 @@ async function addReferencesFrom(roots, path, cwd) {
|
|
|
138
138
|
}
|
|
139
139
|
}
|
|
140
140
|
}
|
|
141
|
-
export function nxSmartArgs(target, mode, configuration) {
|
|
141
|
+
export function nxSmartArgs(target, mode, configuration, stage) {
|
|
142
142
|
const args = [mode, '-t', target];
|
|
143
143
|
if (configuration) {
|
|
144
144
|
args.push(`--configuration=${configuration}`);
|
|
145
145
|
}
|
|
146
|
+
if (stage) {
|
|
147
|
+
args.push(`--stage=${stage}`);
|
|
148
|
+
}
|
|
146
149
|
args.push(`--exclude=tag:ci:skip:${target}`, `--parallel=${NX_PARALLEL}`);
|
|
147
150
|
return args;
|
|
148
151
|
}
|
|
@@ -151,7 +154,7 @@ export async function githubCiNxSmart(root, options) {
|
|
|
151
154
|
const step = options.step ?? '';
|
|
152
155
|
await createGithubStatus(name, step);
|
|
153
156
|
const mode = resolveNxSmartMode(options.mode ?? 'auto');
|
|
154
|
-
const nxArgs = nxSmartArgs(options.target, mode, options.configuration);
|
|
157
|
+
const nxArgs = nxSmartArgs(options.target, mode, options.configuration, options.stage);
|
|
155
158
|
const status = await runStatus('nx', nxArgs, root);
|
|
156
159
|
await updateGithubStatus(name, status === 0 ? 'success' : 'failure', step);
|
|
157
160
|
if (status !== 0) {
|
|
@@ -318,8 +321,8 @@ function commaSeparatedValues(value) {
|
|
|
318
321
|
export async function githubCiNxDeploy(root, options, dependencies = {}) {
|
|
319
322
|
const processEnv = dependencies.processEnv ?? process.env;
|
|
320
323
|
const eventPayload = dependencies.eventPayload ?? readGithubActionsEvent(processEnv);
|
|
321
|
-
const
|
|
322
|
-
const name = options.name ?? 'Deploy
|
|
324
|
+
const stage = resolveDeploymentStage(options.stage, processEnv, eventPayload);
|
|
325
|
+
const name = options.name ?? 'Deploy Stage';
|
|
323
326
|
const step = options.step ?? '';
|
|
324
327
|
const setStatus = dependencies.setStatus ??
|
|
325
328
|
((state) => state === 'pending' ? createGithubStatus(name, step) : updateGithubStatus(name, state, step));
|
|
@@ -329,7 +332,7 @@ export async function githubCiNxDeploy(root, options, dependencies = {}) {
|
|
|
329
332
|
const runNx = dependencies.runNx ?? ((args, commandRoot) => runStatus('nx', args, commandRoot));
|
|
330
333
|
const projects = await listProjects(root, 'deploy', mode);
|
|
331
334
|
if (projects.length === 0) {
|
|
332
|
-
console.log(`No ${mode} deploy projects; skipping ${
|
|
335
|
+
console.log(`No ${mode} deploy projects; skipping ${stage}.`);
|
|
333
336
|
await setStatus('success');
|
|
334
337
|
return;
|
|
335
338
|
}
|
|
@@ -345,7 +348,7 @@ export async function githubCiNxDeploy(root, options, dependencies = {}) {
|
|
|
345
348
|
`--parallel=${NX_PARALLEL}`,
|
|
346
349
|
];
|
|
347
350
|
if (target === 'deploy') {
|
|
348
|
-
nxArgs.push(`--
|
|
351
|
+
nxArgs.push(`--stage=${stage}`);
|
|
349
352
|
}
|
|
350
353
|
const status = await runNx(nxArgs, root);
|
|
351
354
|
if (status !== 0) {
|
|
@@ -353,33 +356,30 @@ export async function githubCiNxDeploy(root, options, dependencies = {}) {
|
|
|
353
356
|
throw new Error(`nx ${nxArgs.join(' ')} failed with exit code ${status}`);
|
|
354
357
|
}
|
|
355
358
|
}
|
|
356
|
-
if (
|
|
357
|
-
const url = `https://app.${
|
|
359
|
+
if (isPullRequestStage(stage)) {
|
|
360
|
+
const url = `https://app.${stage}.conloca.com`;
|
|
358
361
|
const summaryPath = processEnv.GITHUB_STEP_SUMMARY;
|
|
359
362
|
if (summaryPath) {
|
|
360
363
|
const appendSummary = dependencies.appendSummary ?? appendFile;
|
|
361
|
-
await appendSummary(summaryPath, `## ${
|
|
364
|
+
await appendSummary(summaryPath, `## ${stage} deployment
|
|
365
|
+
|
|
366
|
+
[View deployment](${url})
|
|
367
|
+
`);
|
|
362
368
|
}
|
|
363
369
|
const publishDeployment = dependencies.publishDeployment ??
|
|
364
370
|
((token, deploymentUrl) => publishGithubDeployment(token, deploymentUrl, processEnv));
|
|
365
|
-
await publishDeployment(
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
const
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
];
|
|
378
|
-
const status = await runNx(nxArgs, root);
|
|
379
|
-
if (status !== 0) {
|
|
380
|
-
await setStatus('failure');
|
|
381
|
-
throw new Error(`nx ${nxArgs.join(' ')} failed with exit code ${status}`);
|
|
382
|
-
}
|
|
371
|
+
await publishDeployment(stage, url);
|
|
372
|
+
}
|
|
373
|
+
const outputPath = processEnv.GITHUB_OUTPUT;
|
|
374
|
+
if (outputPath) {
|
|
375
|
+
try {
|
|
376
|
+
const appendOutput = dependencies.appendOutput ?? appendFile;
|
|
377
|
+
await appendOutput(outputPath, `stage=${stage}
|
|
378
|
+
`);
|
|
379
|
+
}
|
|
380
|
+
catch (error) {
|
|
381
|
+
await setStatus('failure');
|
|
382
|
+
throw error;
|
|
383
383
|
}
|
|
384
384
|
}
|
|
385
385
|
await setStatus('success');
|
|
@@ -415,9 +415,9 @@ function eventDefaultBranch() {
|
|
|
415
415
|
return undefined;
|
|
416
416
|
}
|
|
417
417
|
}
|
|
418
|
-
export function
|
|
418
|
+
export function resolveDeploymentStage(explicit, environment, event) {
|
|
419
419
|
if (explicit !== undefined)
|
|
420
|
-
return
|
|
420
|
+
return parseDeploymentStage(explicit);
|
|
421
421
|
if (environment.GITHUB_EVENT_NAME === 'pull_request') {
|
|
422
422
|
if (!event?.action || !['opened', 'reopened', 'synchronize'].includes(event.action)) {
|
|
423
423
|
throw new Error('Pull-request deployment runs only for opened, reopened, or synchronize events.');
|
|
@@ -430,7 +430,7 @@ export function resolveDeploymentEnvironment(explicit, environment, event) {
|
|
|
430
430
|
const number = event.pull_request?.number;
|
|
431
431
|
if (number === undefined)
|
|
432
432
|
throw new Error('GitHub pull_request event is missing its PR number.');
|
|
433
|
-
return
|
|
433
|
+
return pullRequestStage(number);
|
|
434
434
|
}
|
|
435
435
|
if (environment.GITHUB_EVENT_NAME === 'push' && environment.GITHUB_REF_NAME === 'private') {
|
|
436
436
|
return 'staging';
|
|
@@ -438,7 +438,7 @@ export function resolveDeploymentEnvironment(explicit, environment, event) {
|
|
|
438
438
|
if (environment.GITHUB_EVENT_NAME === 'release') {
|
|
439
439
|
return 'production';
|
|
440
440
|
}
|
|
441
|
-
throw new Error('Cannot resolve a deployment
|
|
441
|
+
throw new Error('Cannot resolve a deployment stage from this GitHub event; pass --stage explicitly.');
|
|
442
442
|
}
|
|
443
443
|
function readGithubActionsEvent(environment) {
|
|
444
444
|
const eventPath = environment.GITHUB_EVENT_PATH;
|
|
@@ -463,7 +463,7 @@ async function listNxProjectsWithTarget(root, target, mode) {
|
|
|
463
463
|
const candidates = nxProjectList(decode(result.stdout)).sort((left, right) => left.localeCompare(right));
|
|
464
464
|
if (target !== 'deploy')
|
|
465
465
|
return candidates;
|
|
466
|
-
return
|
|
466
|
+
return selectStageDeployProjects(candidates, async (project) => {
|
|
467
467
|
const projectResult = await $ `nx show project ${project} --json`.cwd(root).quiet();
|
|
468
468
|
const parsed = parseNxProjectDeployTarget(decode(projectResult.stdout));
|
|
469
469
|
if (!parsed)
|
|
@@ -471,7 +471,7 @@ async function listNxProjectsWithTarget(root, target, mode) {
|
|
|
471
471
|
return parsed;
|
|
472
472
|
});
|
|
473
473
|
}
|
|
474
|
-
export async function
|
|
474
|
+
export async function selectStageDeployProjects(candidates, loadProject) {
|
|
475
475
|
const selected = [];
|
|
476
476
|
for (const project of candidates) {
|
|
477
477
|
const definition = await loadProject(project);
|
|
@@ -479,7 +479,7 @@ export async function selectEnvironmentDeployProjects(candidates, loadProject) {
|
|
|
479
479
|
continue;
|
|
480
480
|
const deploy = definition.targets?.deploy;
|
|
481
481
|
const commandValue = deploy?.options?.command ?? deploy?.command;
|
|
482
|
-
if (typeof commandValue === 'string' && commandValue.includes('smoo wrangler deploy-
|
|
482
|
+
if (typeof commandValue === 'string' && commandValue.includes('smoo wrangler deploy-stage')) {
|
|
483
483
|
selected.push(project);
|
|
484
484
|
}
|
|
485
485
|
}
|
|
@@ -4,6 +4,7 @@ export declare enum CiWorkflowStepKind {
|
|
|
4
4
|
SetNxShas = "set-nx-shas",
|
|
5
5
|
RestoreNxCache = "restore-nx-cache",
|
|
6
6
|
Build = "build",
|
|
7
|
+
BrowserTests = "browser-tests",
|
|
7
8
|
Lint = "lint",
|
|
8
9
|
UnitTests = "unit-tests",
|
|
9
10
|
ManagedFilesCheck = "managed-files-check",
|
|
@@ -20,6 +21,8 @@ export interface CiWorkflowStep {
|
|
|
20
21
|
}
|
|
21
22
|
export interface CiWorkflowDefinitionOptions {
|
|
22
23
|
deploy: boolean;
|
|
24
|
+
browserTests: boolean;
|
|
25
|
+
e2eDeployment: boolean;
|
|
23
26
|
deployProvider?: 'cloudflare';
|
|
24
27
|
pushBranches: string[];
|
|
25
28
|
/** Default ubuntu-latest when omitted. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ci-workflow.d.ts","sourceRoot":"","sources":["../../src/monorepo/ci-workflow.ts"],"names":[],"mappings":"AAIA,oBAAY,kBAAkB;IAC5B,QAAQ,aAAa;IACrB,WAAW,iBAAiB;IAC5B,SAAS,gBAAgB;IACzB,cAAc,qBAAqB;IACnC,KAAK,UAAU;IACf,IAAI,SAAS;IACb,SAAS,eAAe;IACxB,iBAAiB,wBAAwB;IACzC,oBAAoB,2BAA2B;IAC/C,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;IACvB,0CAA0C;IAC1C,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CAC5B;AAID,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,2BAA2B,GAAG,cAAc,EAAE,
|
|
1
|
+
{"version":3,"file":"ci-workflow.d.ts","sourceRoot":"","sources":["../../src/monorepo/ci-workflow.ts"],"names":[],"mappings":"AAIA,oBAAY,kBAAkB;IAC5B,QAAQ,aAAa;IACrB,WAAW,iBAAiB;IAC5B,SAAS,gBAAgB;IACzB,cAAc,qBAAqB;IACnC,KAAK,UAAU;IACf,YAAY,kBAAkB;IAC9B,IAAI,SAAS;IACb,SAAS,eAAe;IACxB,iBAAiB,wBAAwB;IACzC,oBAAoB,2BAA2B;IAC/C,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,YAAY,EAAE,OAAO,CAAC;IACtB,aAAa,EAAE,OAAO,CAAC;IACvB,cAAc,CAAC,EAAE,YAAY,CAAC;IAC9B,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,0CAA0C;IAC1C,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CAC5B;AAID,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,2BAA2B,GAAG,cAAc,EAAE,CA0BvF;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,2BAA2B,GAAG,MAAM,CAGjF"}
|
|
@@ -7,6 +7,7 @@ export var CiWorkflowStepKind;
|
|
|
7
7
|
CiWorkflowStepKind["SetNxShas"] = "set-nx-shas";
|
|
8
8
|
CiWorkflowStepKind["RestoreNxCache"] = "restore-nx-cache";
|
|
9
9
|
CiWorkflowStepKind["Build"] = "build";
|
|
10
|
+
CiWorkflowStepKind["BrowserTests"] = "browser-tests";
|
|
10
11
|
CiWorkflowStepKind["Lint"] = "lint";
|
|
11
12
|
CiWorkflowStepKind["UnitTests"] = "unit-tests";
|
|
12
13
|
CiWorkflowStepKind["ManagedFilesCheck"] = "managed-files-check";
|
|
@@ -23,20 +24,20 @@ export function defineCiWorkflow(options) {
|
|
|
23
24
|
{ kind: CiWorkflowStepKind.SetNxShas, name: '🧭 Set Nx SHAs' },
|
|
24
25
|
{ kind: CiWorkflowStepKind.RestoreNxCache, name: '🧠 Restore Nx cache' },
|
|
25
26
|
{ kind: CiWorkflowStepKind.Build, name: '🔨 Build' },
|
|
26
|
-
{ kind: CiWorkflowStepKind.Lint, name: '🔍 Lint' },
|
|
27
|
-
{ kind: CiWorkflowStepKind.UnitTests, name: '🧪 Unit Tests' },
|
|
28
|
-
{ kind: CiWorkflowStepKind.ManagedFilesCheck, name: '🩺 Check managed-file drift' },
|
|
29
|
-
{ kind: CiWorkflowStepKind.ManagedFilesDispatch, name: '🔁 Dispatch managed-file drift healing' },
|
|
30
27
|
];
|
|
31
28
|
if (options.deploy) {
|
|
32
|
-
steps.push({ kind: CiWorkflowStepKind.Deploy, name: '🚀 Deploy
|
|
29
|
+
steps.push({ kind: CiWorkflowStepKind.Deploy, name: '🚀 Deploy Stage' });
|
|
33
30
|
}
|
|
34
|
-
steps.push({ kind: CiWorkflowStepKind.
|
|
31
|
+
steps.push({ kind: CiWorkflowStepKind.Lint, name: '🔍 Lint' }, { kind: CiWorkflowStepKind.UnitTests, name: '🧪 Unit Tests' });
|
|
32
|
+
if (options.browserTests) {
|
|
33
|
+
steps.push({ kind: CiWorkflowStepKind.BrowserTests, name: '🌐 Browser Tests' });
|
|
34
|
+
}
|
|
35
|
+
steps.push({ kind: CiWorkflowStepKind.ManagedFilesCheck, name: '🩺 Check managed-file drift' }, { kind: CiWorkflowStepKind.ManagedFilesDispatch, name: '🔁 Dispatch managed-file drift healing' }, { kind: CiWorkflowStepKind.SaveNxCache, name: '💾 Save Nx cache' }, { kind: CiWorkflowStepKind.UploadTraceDbs, name: '📎 Upload trace DBs' }, { kind: CiWorkflowStepKind.SaveNixDevenv, name: '🧹 Cleanup and cache Nix/devenv' });
|
|
35
36
|
return steps.map((step, index) => ({ ...step, number: index + 2 }));
|
|
36
37
|
}
|
|
37
38
|
export function renderCiWorkflowYaml(options) {
|
|
38
39
|
const steps = defineCiWorkflow(options);
|
|
39
|
-
return `${renderCiWorkflowHeader(options)}${renderCiWorkflowSteps(steps, options)}`;
|
|
40
|
+
return `${renderCiWorkflowHeader(options)}${renderCiWorkflowSteps(steps, options)}${renderE2eDeploymentJob(options)}`;
|
|
40
41
|
}
|
|
41
42
|
function renderCiWorkflowHeader(options) {
|
|
42
43
|
return `name: CI
|
|
@@ -53,6 +54,10 @@ permissions:
|
|
|
53
54
|
contents: read
|
|
54
55
|
${options.deploy ? ' deployments: write\n' : ''} statuses: write
|
|
55
56
|
|
|
57
|
+
concurrency:
|
|
58
|
+
group: \${{ github.workflow }}-\${{ github.ref }}
|
|
59
|
+
cancel-in-progress: true
|
|
60
|
+
|
|
56
61
|
defaults:
|
|
57
62
|
run:
|
|
58
63
|
working-directory: tooling/direnv
|
|
@@ -62,7 +67,11 @@ jobs:
|
|
|
62
67
|
name: Validate
|
|
63
68
|
${renderRunsOnLine(options.runsOn)}
|
|
64
69
|
timeout-minutes: 45
|
|
65
|
-
|
|
70
|
+
${options.e2eDeployment
|
|
71
|
+
? ` outputs:
|
|
72
|
+
deployment-stage: ${githubExpression('steps.deploy.outputs.stage')}
|
|
73
|
+
`
|
|
74
|
+
: ''} env:
|
|
66
75
|
NIX_STORE_NAR: ${githubExpression('github.workspace')}/nix-store.nar
|
|
67
76
|
GH_TOKEN: ${githubExpression('github.token')}
|
|
68
77
|
steps:
|
|
@@ -139,6 +148,8 @@ function yamlLinesForStep(step, options) {
|
|
|
139
148
|
return [` - name: ${step.name}`, ' id: nx-cache', ' uses: ./.github/actions/cache-nx'];
|
|
140
149
|
case CiWorkflowStepKind.Build:
|
|
141
150
|
return nxSmartStep(step, 'build', 'Build');
|
|
151
|
+
case CiWorkflowStepKind.BrowserTests:
|
|
152
|
+
return nxSmartStep(step, 'test-browser', 'Browser Tests');
|
|
142
153
|
case CiWorkflowStepKind.Lint:
|
|
143
154
|
return nxSmartStep(step, 'lint', 'Lint');
|
|
144
155
|
case CiWorkflowStepKind.UnitTests:
|
|
@@ -167,6 +178,7 @@ function yamlLinesForStep(step, options) {
|
|
|
167
178
|
case CiWorkflowStepKind.Deploy:
|
|
168
179
|
return [
|
|
169
180
|
` - name: ${step.name}`,
|
|
181
|
+
' id: deploy',
|
|
170
182
|
' if: >-',
|
|
171
183
|
' ${{',
|
|
172
184
|
" (github.event_name == 'pull_request' &&",
|
|
@@ -175,7 +187,7 @@ function yamlLinesForStep(step, options) {
|
|
|
175
187
|
" (github.event_name == 'push' && github.ref == 'refs/heads/private')",
|
|
176
188
|
' }}',
|
|
177
189
|
...deployEnvLines(options),
|
|
178
|
-
` run: smoo github-ci nx-deploy --mode run-many --name "Deploy
|
|
190
|
+
` run: smoo github-ci nx-deploy --mode run-many --name "Deploy Stage" --step ${step.number}`,
|
|
179
191
|
];
|
|
180
192
|
case CiWorkflowStepKind.SaveNxCache:
|
|
181
193
|
return [
|
|
@@ -224,12 +236,6 @@ function deployEnvLines(options) {
|
|
|
224
236
|
' env:',
|
|
225
237
|
' CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}',
|
|
226
238
|
' CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}',
|
|
227
|
-
' GITHUB_CLIENT_SECRET: ${{ secrets.GITHUB_CLIENT_SECRET }}',
|
|
228
|
-
' GITHUB_APP_PRIVATE_KEY: ${{ secrets.GITHUB_APP_PRIVATE_KEY }}',
|
|
229
|
-
' GITHUB_APP_PRIVATE_KEY_PEM: ${{ secrets.GITHUB_APP_PRIVATE_KEY_PEM }}',
|
|
230
|
-
' OAUTH_STATE_SIGNING_KEY: ${{ secrets.OAUTH_STATE_SIGNING_KEY }}',
|
|
231
|
-
' MAIL_CAPTURE_CONTROL_TOKEN: ${{ secrets.MAIL_CAPTURE_CONTROL_TOKEN }}',
|
|
232
|
-
' TOKEN_ENCRYPTION_KEY: ${{ secrets.TOKEN_ENCRYPTION_KEY }}',
|
|
233
239
|
];
|
|
234
240
|
}
|
|
235
241
|
function nxSmartStep(step, target, name) {
|
|
@@ -242,3 +248,41 @@ function renderYamlList(values, spaces) {
|
|
|
242
248
|
const indent = ' '.repeat(spaces);
|
|
243
249
|
return values.map((value) => `${indent}- ${value}`).join('\n');
|
|
244
250
|
}
|
|
251
|
+
function renderE2eDeploymentJob(options) {
|
|
252
|
+
if (!options.e2eDeployment)
|
|
253
|
+
return '';
|
|
254
|
+
return `
|
|
255
|
+
|
|
256
|
+
e2e-deployment:
|
|
257
|
+
name: Deployment E2E
|
|
258
|
+
needs: main
|
|
259
|
+
${renderRunsOnLine(options.runsOn)}
|
|
260
|
+
timeout-minutes: 15
|
|
261
|
+
if: \${{ needs.main.result == 'success' && needs.main.outputs.deployment-stage != '' }}
|
|
262
|
+
steps:
|
|
263
|
+
# Step 1: GitHub adds "Set up job" automatically
|
|
264
|
+
# Step 2
|
|
265
|
+
- name: 📥 Checkout
|
|
266
|
+
uses: actions/checkout@v6.0.2
|
|
267
|
+
with:
|
|
268
|
+
filter: blob:none
|
|
269
|
+
fetch-depth: 0
|
|
270
|
+
|
|
271
|
+
# Step 3. Composite action internals do not affect top-level job step anchors.
|
|
272
|
+
- name: 🧱 Setup Nix/devenv
|
|
273
|
+
id: setup
|
|
274
|
+
uses: ./.github/actions/setup-devenv
|
|
275
|
+
|
|
276
|
+
# Step 4
|
|
277
|
+
- name: Deployment E2E
|
|
278
|
+
run: smoo github-ci nx-smart --target e2e-deployment --mode run-many --stage "\${{ needs.main.outputs.deployment-stage }}" --name "Deployment E2E" --step 4
|
|
279
|
+
|
|
280
|
+
# Step 5
|
|
281
|
+
- name: 🧹 Cleanup and cache Nix/devenv
|
|
282
|
+
if: always()
|
|
283
|
+
uses: ./.github/actions/save-nix-devenv
|
|
284
|
+
with:
|
|
285
|
+
nix-cache-hit: \${{ steps.setup.outputs.nix-cache-hit }}
|
|
286
|
+
devenv-cache-hit: \${{ steps.setup.outputs.devenv-cache-hit }}
|
|
287
|
+
`;
|
|
288
|
+
}
|
|
@@ -57,6 +57,7 @@ export declare const managedFileTargetsForTest: {
|
|
|
57
57
|
executable: boolean | undefined;
|
|
58
58
|
}[];
|
|
59
59
|
export declare function applyManagedFiles(root: string, mode: 'update' | 'check' | 'diff'): Promise<FileResult[]>;
|
|
60
|
+
export declare function hasExactTargetForTest(targetNames: Iterable<string>, target: string): boolean;
|
|
60
61
|
export declare function platformTargetGlobsForTest(targetNames: Iterable<string>): string[];
|
|
61
62
|
/** Test seam: deploy configuration presence/provider from graph nodes. */
|
|
62
63
|
export declare function deployTargetInfoFromProjects(projects: NxProjects, configuration: string): DeployTargetInfo;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"managed-files.d.ts","sourceRoot":"","sources":["../../src/monorepo/managed-files.ts"],"names":[],"mappings":"AAMA,OAAO,EAAkB,KAAK,UAAU,EAA2B,MAAM,gBAAgB,CAAC;AAO1F;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,yEAAyE,CAAC;AAW3G,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,
|
|
1
|
+
{"version":3,"file":"managed-files.d.ts","sourceRoot":"","sources":["../../src/monorepo/managed-files.ts"],"names":[],"mappings":"AAMA,OAAO,EAAkB,KAAK,UAAU,EAA2B,MAAM,gBAAgB,CAAC;AAO1F;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,yEAAyE,CAAC;AAW3G,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,CAuBtF;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;AAiBD,UAAU,gBAAgB;IACxB,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,YAAY,CAAC;CACzB;AAkHD,eAAO,MAAM,yBAAyB;;;GAAyE,CAAC;AAIhH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAG9G;AA8GD,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAE5F;AAED,wBAAgB,0BAA0B,CAAC,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,MAAM,EAAE,CAMlF;AAED,0EAA0E;AAC1E,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,GAAG,gBAAgB,CAY1G;AA2DD,wBAAgB,YAAY,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,IAAI,CAIxD;AAED,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAQxE;AAED;;;;;;;;;GASG;AACH,wBAAsB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBxE"}
|
|
@@ -82,11 +82,13 @@ function reinsertInlineLocalBlocks(content, blocks) {
|
|
|
82
82
|
return content;
|
|
83
83
|
const lines = content.split('\n');
|
|
84
84
|
for (const block of blocks) {
|
|
85
|
-
const
|
|
86
|
-
if (
|
|
87
|
-
|
|
85
|
+
const matches = lines.flatMap((line, index) => (line === block.anchor ? [index] : []));
|
|
86
|
+
if (matches.length !== 1) {
|
|
87
|
+
const reason = matches.length === 0 ? 'no line' : `${matches.length} lines`;
|
|
88
|
+
throw new Error(`${INLINE_LOCAL_BEGIN} block anchored on "${block.anchor}" matches ${reason} in the updated ` +
|
|
88
89
|
'template — reconcile the repo-owned block manually');
|
|
89
90
|
}
|
|
91
|
+
const index = matches[0];
|
|
90
92
|
const markerIndent = block.markerIndent ?? '';
|
|
91
93
|
lines.splice(index + 1, 0, `${markerIndent}${INLINE_LOCAL_BEGIN}`, ...block.lines.split('\n'), `${markerIndent}${INLINE_LOCAL_END}`);
|
|
92
94
|
}
|
|
@@ -254,6 +256,8 @@ function getManagedContent(file, context) {
|
|
|
254
256
|
return renderCiWorkflowYaml({
|
|
255
257
|
deploy: context.hasStagingDeployTargets,
|
|
256
258
|
deployProvider: context.stagingDeployProvider,
|
|
259
|
+
browserTests: context.hasBrowserTestTargets,
|
|
260
|
+
e2eDeployment: context.hasStagingDeployTargets && context.hasE2eDeploymentTargets,
|
|
257
261
|
pushBranches: context.ciPushBranches,
|
|
258
262
|
runsOn: context.ciRunsOn,
|
|
259
263
|
});
|
|
@@ -289,7 +293,8 @@ async function getManagedFileContext(root) {
|
|
|
289
293
|
const nxProjects = await loadNxProjects(root);
|
|
290
294
|
const stagingDeploy = deployTargetInfoFromProjects(nxProjects, 'staging');
|
|
291
295
|
const productionDeploy = deployTargetInfoFromProjects(nxProjects, 'production');
|
|
292
|
-
const
|
|
296
|
+
const targetNames = targetNamesFromProjects(nxProjects);
|
|
297
|
+
const platformTargetGlobs = platformTargetGlobsForTest(targetNames);
|
|
293
298
|
const nodeModulesCacheKey = existsSync(join(root, 'bun.lock'))
|
|
294
299
|
? `$${"{{ hashFiles('bun.lock', 'package.json', 'packages/*/package.json') }}"}`
|
|
295
300
|
: `$${"{{ hashFiles('bun.lockb', 'package.json', 'packages/*/package.json') }}"}`;
|
|
@@ -297,6 +302,8 @@ async function getManagedFileContext(root) {
|
|
|
297
302
|
hasReleasePackages: listReleasePackages(root, packageJson).length > 0,
|
|
298
303
|
hasStagingDeployTargets: stagingDeploy.exists,
|
|
299
304
|
hasProductionDeployTargets: productionDeploy.exists,
|
|
305
|
+
hasBrowserTestTargets: hasExactTargetForTest(targetNames, 'test-browser'),
|
|
306
|
+
hasE2eDeploymentTargets: hasExactTargetForTest(targetNames, 'e2e-deployment'),
|
|
300
307
|
stagingDeployProvider: stagingDeploy.provider,
|
|
301
308
|
productionDeployProvider: productionDeploy.provider,
|
|
302
309
|
ciPushBranches,
|
|
@@ -306,6 +313,9 @@ async function getManagedFileContext(root) {
|
|
|
306
313
|
platformTargetGlobs,
|
|
307
314
|
};
|
|
308
315
|
}
|
|
316
|
+
export function hasExactTargetForTest(targetNames, target) {
|
|
317
|
+
return [...targetNames].includes(target);
|
|
318
|
+
}
|
|
309
319
|
export function platformTargetGlobsForTest(targetNames) {
|
|
310
320
|
const names = [...targetNames];
|
|
311
321
|
return PLATFORM_TARGET_GLOBS.filter((glob) => {
|
|
@@ -334,7 +344,7 @@ function deployTargetInfoFromTargets(targets, configuration) {
|
|
|
334
344
|
}
|
|
335
345
|
const baseCommandValue = deploy.options?.command ?? deploy.command;
|
|
336
346
|
const baseCommand = typeof baseCommandValue === 'string' ? baseCommandValue : '';
|
|
337
|
-
if (baseCommand.includes('smoo wrangler deploy-
|
|
347
|
+
if (baseCommand.includes('smoo wrangler deploy-stage')) {
|
|
338
348
|
return { exists: true, provider: 'cloudflare' };
|
|
339
349
|
}
|
|
340
350
|
const config = deploy.configurations?.[configuration];
|
|
@@ -2,7 +2,7 @@ import { type WorkflowRunsOn } from './github-runs-on.js';
|
|
|
2
2
|
export type PublishWorkflowBump = 'auto' | 'patch' | 'minor' | 'major' | 'prerelease';
|
|
3
3
|
export type PublishWorkflowCondition = 'version-mode-not-none' | 'deploy-production' | 'failure' | 'always';
|
|
4
4
|
export type PublishWorkflowNxTarget = 'build' | 'lint' | 'test';
|
|
5
|
-
export type
|
|
5
|
+
export type PublishWorkflowDeployStage = 'none' | 'production';
|
|
6
6
|
export declare enum PublishWorkflowStepKind {
|
|
7
7
|
Checkout = "checkout",
|
|
8
8
|
SetupDevenv = "setup-devenv",
|
|
@@ -41,7 +41,7 @@ export interface PublishWorkflowDefinitionOptions {
|
|
|
41
41
|
}
|
|
42
42
|
export interface PublishWorkflowInputs {
|
|
43
43
|
bump: PublishWorkflowBump;
|
|
44
|
-
|
|
44
|
+
deployStage: PublishWorkflowDeployStage;
|
|
45
45
|
dryRun: boolean;
|
|
46
46
|
}
|
|
47
47
|
export interface PublishWorkflowVersionOutputs {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"publish-workflow.d.ts","sourceRoot":"","sources":["../../src/monorepo/publish-workflow.ts"],"names":[],"mappings":"AASA,OAAO,EAAoB,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAQ5E,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,YAAY,CAAC;AACtF,MAAM,MAAM,wBAAwB,GAAG,uBAAuB,GAAG,mBAAmB,GAAG,SAAS,GAAG,QAAQ,CAAC;AAC5G,MAAM,MAAM,uBAAuB,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;AAChE,MAAM,MAAM,
|
|
1
|
+
{"version":3,"file":"publish-workflow.d.ts","sourceRoot":"","sources":["../../src/monorepo/publish-workflow.ts"],"names":[],"mappings":"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"}
|
|
@@ -175,7 +175,7 @@ function shouldRunStep(step, version, failed, inputs) {
|
|
|
175
175
|
return version.mode !== 'none';
|
|
176
176
|
}
|
|
177
177
|
if (step.condition === 'deploy-production') {
|
|
178
|
-
return version.mode !== 'none' && inputs.
|
|
178
|
+
return version.mode !== 'none' && inputs.deployStage === 'production' && !inputs.dryRun;
|
|
179
179
|
}
|
|
180
180
|
if (step.condition === 'failure') {
|
|
181
181
|
return failed;
|
|
@@ -199,7 +199,7 @@ export function renderPublishWorkflowYaml(options = {}) {
|
|
|
199
199
|
function renderPublishWorkflowHeader(options) {
|
|
200
200
|
const deployInput = options.deploy === true
|
|
201
201
|
? `
|
|
202
|
-
|
|
202
|
+
deploy_stage:
|
|
203
203
|
type: choice
|
|
204
204
|
description: Deploy live systems after a successful publish.
|
|
205
205
|
options: [none, production]
|
|
@@ -377,10 +377,10 @@ function deployProductionStep(step, options) {
|
|
|
377
377
|
return [
|
|
378
378
|
` - name: ${step.name}`,
|
|
379
379
|
' if:',
|
|
380
|
-
" ${{ steps.version.outputs.mode != 'none' && inputs.
|
|
380
|
+
" ${{ steps.version.outputs.mode != 'none' && inputs.deploy_stage == 'production' && inputs.dry_run !=",
|
|
381
381
|
" 'true' }}",
|
|
382
382
|
...deployEnvLines(options),
|
|
383
|
-
' run: smoo github-ci nx-deploy --
|
|
383
|
+
' run: smoo github-ci nx-deploy --stage production --mode run-many --verify --name "Deploy Production"',
|
|
384
384
|
];
|
|
385
385
|
}
|
|
386
386
|
function deployEnvLines(options) {
|
|
@@ -413,7 +413,7 @@ function renderSingleJobPublishWorkflowSteps(steps, options) {
|
|
|
413
413
|
function renderPlatformPublishWorkflowYaml(options) {
|
|
414
414
|
const deployInput = options.deploy === true
|
|
415
415
|
? `
|
|
416
|
-
|
|
416
|
+
deploy_stage:
|
|
417
417
|
type: choice
|
|
418
418
|
description: Deploy live systems after a successful publish.
|
|
419
419
|
options: [none, production]
|
|
@@ -606,7 +606,7 @@ function renderFinalLinuxPublishSteps(options) {
|
|
|
606
606
|
}
|
|
607
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')}"`);
|
|
608
608
|
if (options.deploy === true) {
|
|
609
|
-
lines.push('', ` # Step ${stepNumber++}`, ' - name: 🚀 Deploy production', ' if:', " ${{ needs.linux-release-candidate.outputs.mode != 'none' && inputs.
|
|
609
|
+
lines.push('', ` # Step ${stepNumber++}`, ' - name: 🚀 Deploy production', ' if:', " ${{ needs.linux-release-candidate.outputs.mode != 'none' && inputs.deploy_stage == 'production' &&", " inputs.dry_run != 'true' }}", ...deployEnvLines(options), ' run: smoo github-ci nx-deploy --stage production --mode run-many --verify --name "Deploy Production"');
|
|
610
610
|
}
|
|
611
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')}`);
|
|
612
612
|
return lines.join('\n').trimEnd();
|