@smoothbricks/cli 0.10.7 → 0.10.9
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.d.ts.map +1 -1
- package/dist/cli.js +24 -1
- package/dist/github-ci/index.d.ts +44 -4
- package/dist/github-ci/index.d.ts.map +1 -1
- package/dist/github-ci/index.js +220 -34
- package/dist/monorepo/ci-workflow.js +16 -6
- package/dist/monorepo/managed-files.d.ts.map +1 -1
- package/dist/monorepo/managed-files.js +19 -1
- package/dist/monorepo/pr-preview-cleanup-workflow.d.ts +5 -0
- package/dist/monorepo/pr-preview-cleanup-workflow.d.ts.map +1 -0
- package/dist/monorepo/pr-preview-cleanup-workflow.js +38 -0
- package/dist/monorepo/publish-workflow.js +3 -3
- package/dist/monorepo/tool-validation.d.ts.map +1 -1
- package/dist/monorepo/tool-validation.js +85 -5
- package/dist/playwright/index.d.ts +22 -0
- package/dist/playwright/index.d.ts.map +1 -0
- package/dist/playwright/index.js +44 -0
- package/dist/release/bootstrap-npm-packages.d.ts +3 -0
- package/dist/release/bootstrap-npm-packages.d.ts.map +1 -1
- package/dist/release/bootstrap-npm-packages.js +21 -0
- package/dist/release/index.d.ts +1 -0
- package/dist/release/index.d.ts.map +1 -1
- package/dist/release/index.js +31 -6
- package/dist/wrangler/cloudflare.d.ts +87 -0
- package/dist/wrangler/cloudflare.d.ts.map +1 -0
- package/dist/wrangler/cloudflare.js +238 -0
- package/dist/wrangler/deploy-environment.d.ts +48 -0
- package/dist/wrangler/deploy-environment.d.ts.map +1 -0
- package/dist/wrangler/deploy-environment.js +383 -0
- package/dist/wrangler/environment.d.ts +58 -0
- package/dist/wrangler/environment.d.ts.map +1 -0
- package/dist/wrangler/environment.js +297 -0
- package/managed/raw/tooling/direnv/github-actions-bootstrap.sh +3 -4
- package/package.json +9 -2
- package/src/cli.ts +27 -3
- package/src/github-ci/index.test.ts +175 -2
- package/src/github-ci/index.ts +274 -31
- package/src/monorepo/__tests__/ci-workflow.test.ts +10 -4
- package/src/monorepo/__tests__/pr-preview-cleanup-workflow.test.ts +23 -0
- package/src/monorepo/__tests__/publish-workflow.test.ts +7 -5
- package/src/monorepo/ci-workflow.ts +16 -6
- package/src/monorepo/managed-files.test.ts +56 -1
- package/src/monorepo/managed-files.ts +20 -1
- package/src/monorepo/pr-preview-cleanup-workflow.ts +44 -0
- package/src/monorepo/publish-workflow.ts +8 -5
- package/src/monorepo/tool-validation.test.ts +85 -0
- package/src/monorepo/tool-validation.ts +94 -5
- package/src/playwright/index.test.ts +90 -0
- package/src/playwright/index.ts +73 -0
- package/src/release/__tests__/bootstrap-npm-packages.test.ts +63 -2
- package/src/release/bootstrap-npm-packages.ts +34 -0
- package/src/release/index.ts +30 -4
- package/src/wrangler/cloudflare.test.ts +76 -0
- package/src/wrangler/cloudflare.ts +292 -0
- package/src/wrangler/deploy-environment.test.ts +354 -0
- package/src/wrangler/deploy-environment.ts +445 -0
- package/src/wrangler/environment.test.ts +173 -0
- package/src/wrangler/environment.ts +366 -0
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AASA,wBAAsB,MAAM,CAAC,IAAI,WAAwB,GAAG,OAAO,CAAC,IAAI,CAAC,CAexE"}
|
package/dist/cli.js
CHANGED
|
@@ -2,7 +2,9 @@ import { Command, CommanderError } from 'commander';
|
|
|
2
2
|
import { variants } from './generate/index.js';
|
|
3
3
|
import { cliPackageVersion } from './lib/cli-package.js';
|
|
4
4
|
import { findRepoRoot } from './lib/run.js';
|
|
5
|
+
import { ensureChromium } from './playwright/index.js';
|
|
5
6
|
import { resolvePrConflicts } from './pr/index.js';
|
|
7
|
+
import { cleanupPullRequest, deployEnvironment } from './wrangler/deploy-environment.js';
|
|
6
8
|
import { scaffold } from './wrangler/scaffold.js';
|
|
7
9
|
export async function runCli(argv = process.argv.slice(2)) {
|
|
8
10
|
const program = buildProgram();
|
|
@@ -147,6 +149,7 @@ function buildProgram() {
|
|
|
147
149
|
.requiredOption('--targets <targets>', 'comma-separated Nx platform target names or globs')
|
|
148
150
|
.requiredOption('--output <path>', 'output directory for current and repair artifacts')
|
|
149
151
|
.option('--ref <ref>', 'fixed release graph ref to inspect')
|
|
152
|
+
.option('--github-output <path>', 'append selected current platform projects to a GitHub Actions output file')
|
|
150
153
|
.action(async (options) => {
|
|
151
154
|
// The source self-hosting shim has no Typia transform; release commands import transformed output validators.
|
|
152
155
|
const { releaseCollectPlatformOutputs } = await import('./release/index.js');
|
|
@@ -307,7 +310,7 @@ function buildProgram() {
|
|
|
307
310
|
});
|
|
308
311
|
githubCi
|
|
309
312
|
.command('nx-deploy')
|
|
310
|
-
.
|
|
313
|
+
.option('--environment <environment>', 'explicit staging, production, or prN override')
|
|
311
314
|
.option('--mode <mode>', 'auto, affected, or run-many', 'run-many')
|
|
312
315
|
.option('--name <name>')
|
|
313
316
|
.option('--step <step>')
|
|
@@ -327,6 +330,14 @@ function buildProgram() {
|
|
|
327
330
|
process.exitCode = exitCode;
|
|
328
331
|
}
|
|
329
332
|
});
|
|
333
|
+
const playwright = program.command('playwright').description('Manage Playwright browsers');
|
|
334
|
+
const playwrightEnsure = playwright.command('ensure').description('Ensure a Playwright browser is available');
|
|
335
|
+
playwrightEnsure
|
|
336
|
+
.command('chromium')
|
|
337
|
+
.description('Ensure Chromium is available for browser tests')
|
|
338
|
+
.action(async () => {
|
|
339
|
+
await ensureChromium();
|
|
340
|
+
});
|
|
330
341
|
const wrangler = program.command('wrangler').description('Cloudflare wrangler project helpers');
|
|
331
342
|
wrangler
|
|
332
343
|
.command('scaffold <project>')
|
|
@@ -335,6 +346,18 @@ function buildProgram() {
|
|
|
335
346
|
.action(async (project, options) => {
|
|
336
347
|
scaffold(await findRepoRoot(), project, { force: options.force });
|
|
337
348
|
});
|
|
349
|
+
wrangler
|
|
350
|
+
.command('deploy-environment')
|
|
351
|
+
.requiredOption('--environment <environment>', 'staging, production, or prN')
|
|
352
|
+
.action(async (options) => {
|
|
353
|
+
await deployEnvironment(process.cwd(), options.environment);
|
|
354
|
+
});
|
|
355
|
+
wrangler
|
|
356
|
+
.command('cleanup-pr')
|
|
357
|
+
.requiredOption('--pr <number>', 'pull-request number')
|
|
358
|
+
.action(async (options) => {
|
|
359
|
+
await cleanupPullRequest(process.cwd(), Number(options.pr));
|
|
360
|
+
});
|
|
338
361
|
return program;
|
|
339
362
|
}
|
|
340
363
|
function booleanOption(value) {
|
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
import { type ProjectTargets } from '../nx/index.js';
|
|
2
|
+
import { type EnvironmentToken } from '../wrangler/environment.js';
|
|
2
3
|
import type { NxTargetRun } from './outputs.js';
|
|
4
|
+
export interface GithubActionsEventPayload {
|
|
5
|
+
action?: string;
|
|
6
|
+
repository?: {
|
|
7
|
+
default_branch?: string;
|
|
8
|
+
full_name?: string;
|
|
9
|
+
};
|
|
10
|
+
pull_request?: {
|
|
11
|
+
number?: number;
|
|
12
|
+
head?: {
|
|
13
|
+
repo?: {
|
|
14
|
+
full_name?: string;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
}
|
|
3
19
|
type NxSmartMode = 'auto' | 'affected' | 'run-many';
|
|
4
20
|
export declare function cleanupGithubCiCache(root: string): Promise<void>;
|
|
5
21
|
export declare function nxSmartArgs(target: string, mode: 'affected' | 'run-many', configuration?: string): string[];
|
|
@@ -26,14 +42,38 @@ export declare function expandNxTargetRuns(projects: ProjectTargets[], options:
|
|
|
26
42
|
export declare function expandNxTargetDependencyRuns(runs: NxTargetRun[]): NxTargetRun[];
|
|
27
43
|
export declare function nxRunManyArgs(run: NxTargetRun, configuration?: string): string[];
|
|
28
44
|
export declare function readGitHeadSha(root: string): Promise<string>;
|
|
29
|
-
export declare function githubCiNxRunMany(root: string, options: NxRunManyOptions): Promise<
|
|
45
|
+
export declare function githubCiNxRunMany(root: string, options: NxRunManyOptions): Promise<ExpandedNxTargetRuns>;
|
|
30
46
|
export declare function githubCiApplyOutputs(root: string, directories: string[], expectedSourceSha: string): Promise<void>;
|
|
31
|
-
export
|
|
32
|
-
|
|
47
|
+
export interface GithubCiNxDeployOptions {
|
|
48
|
+
environment?: string;
|
|
33
49
|
mode?: NxSmartMode;
|
|
34
50
|
name?: string;
|
|
35
51
|
step?: string;
|
|
36
52
|
verify?: boolean;
|
|
37
|
-
}
|
|
53
|
+
}
|
|
54
|
+
export interface GithubCiNxDeployDependencies {
|
|
55
|
+
listProjects?: (root: string, target: string, mode: 'affected' | 'run-many') => Promise<string[]>;
|
|
56
|
+
runNx?: (args: string[], root: string) => Promise<number>;
|
|
57
|
+
appendSummary?: (summaryPath: string, content: string) => Promise<void>;
|
|
58
|
+
publishDeployment?: (environment: `pr${number}`, url: string) => Promise<void>;
|
|
59
|
+
setStatus?: (state: 'pending' | 'success' | 'failure') => Promise<void>;
|
|
60
|
+
processEnv?: NodeJS.ProcessEnv;
|
|
61
|
+
eventPayload?: GithubActionsEventPayload;
|
|
62
|
+
}
|
|
63
|
+
export declare function githubCiNxDeploy(root: string, options: GithubCiNxDeployOptions, dependencies?: GithubCiNxDeployDependencies): Promise<void>;
|
|
64
|
+
export declare function resolveDeploymentEnvironment(explicit: string | undefined, environment: NodeJS.ProcessEnv, event: GithubActionsEventPayload | undefined): EnvironmentToken;
|
|
65
|
+
export declare function selectEnvironmentDeployProjects(candidates: string[], loadProject: (project: string) => Promise<unknown>): Promise<string[]>;
|
|
66
|
+
export interface GithubApiProcessResult {
|
|
67
|
+
exitCode: number;
|
|
68
|
+
stdout: string;
|
|
69
|
+
stderr: string;
|
|
70
|
+
}
|
|
71
|
+
export interface GithubApiProcessRunner {
|
|
72
|
+
run(args: string[], input: string, cwd: string): Promise<GithubApiProcessResult>;
|
|
73
|
+
}
|
|
74
|
+
export declare class NodeGithubApiProcessRunner implements GithubApiProcessRunner {
|
|
75
|
+
run(args: string[], input: string, cwd: string): Promise<GithubApiProcessResult>;
|
|
76
|
+
}
|
|
77
|
+
export declare function publishGithubDeployment(environment: `pr${number}`, url: string, processEnvironment: NodeJS.ProcessEnv, runner?: GithubApiProcessRunner): Promise<void>;
|
|
38
78
|
export {};
|
|
39
79
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/github-ci/index.ts"],"names":[],"mappings":"
|
|
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,EACL,KAAK,gBAAgB,EAItB,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,MAAM,WAAW,yBAAyB;IACxC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE;QACX,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,YAAY,CAAC,EAAE;QACb,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE;YACL,IAAI,CAAC,EAAE;gBACL,SAAS,CAAC,EAAE,MAAM,CAAC;aACpB,CAAC;SACH,CAAC;KACH,CAAC;CACH;AAkBD,KAAK,WAAW,GAAG,MAAM,GAAG,UAAU,GAAG,UAAU,CAAC;AAKpD,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAwBtE;AAmFD,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,UAAU,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAO3G;AAED,wBAAsB,eAAe,CACnC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,WAAW,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAAE,GACpG,OAAO,CAAC,IAAI,CAAC,CAWf;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,WAAW,EAAE,CAAC;IACpB,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,cAAc,EAAE,EAAE,OAAO,EAAE,gBAAgB,GAAG,oBAAoB,CAmD9G;AAED,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,WAAW,EAAE,CAwC/E;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,WAAW,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAehF;AAED,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAGlE;AAED,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAc9G;AAED,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,EAAE,EACrB,iBAAiB,EAAE,MAAM,GACxB,OAAO,CAAC,IAAI,CAAC,CAGf;AA0CD,MAAM,WAAW,uBAAuB;IACtC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,4BAA4B;IAC3C,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,UAAU,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAClG,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1D,aAAa,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACxE,iBAAiB,CAAC,EAAE,CAAC,WAAW,EAAE,KAAK,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/E,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACxE,UAAU,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IAC/B,YAAY,CAAC,EAAE,yBAAyB,CAAC;CAC1C;AAED,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,uBAAuB,EAChC,YAAY,GAAE,4BAAiC,GAC9C,OAAO,CAAC,IAAI,CAAC,CA0Ef;AAiCD,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,WAAW,EAAE,MAAM,CAAC,UAAU,EAC9B,KAAK,EAAE,yBAAyB,GAAG,SAAS,GAC3C,gBAAgB,CAsBlB;AAiCD,wBAAsB,+BAA+B,CACnD,UAAU,EAAE,MAAM,EAAE,EACpB,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,GACjD,OAAO,CAAC,MAAM,EAAE,CAAC,CAYnB;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,sBAAsB;IACrC,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC;CAClF;AAED,qBAAa,0BAA2B,YAAW,sBAAsB;IACvE,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAmB/E;CACF;AAED,wBAAsB,uBAAuB,CAC3C,WAAW,EAAE,KAAK,MAAM,EAAE,EAC1B,GAAG,EAAE,MAAM,EACX,kBAAkB,EAAE,MAAM,CAAC,UAAU,EACrC,MAAM,GAAE,sBAAyD,GAChE,OAAO,CAAC,IAAI,CAAC,CA+Df"}
|
package/dist/github-ci/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
1
2
|
import { existsSync, readFileSync } from 'node:fs';
|
|
2
3
|
import { appendFile, mkdtemp, realpath, rename, rm } from 'node:fs/promises';
|
|
3
4
|
import { dirname, join } from 'node:path';
|
|
@@ -6,22 +7,35 @@ import typia from 'typia';
|
|
|
6
7
|
import { parseStringArrayText } from '../lib/json.js';
|
|
7
8
|
import { decode, run, runStatus } from '../lib/run.js';
|
|
8
9
|
import { readProjectTargets } from '../nx/index.js';
|
|
10
|
+
import { isPullRequestEnvironment, parseEnvironmentToken, pullRequestEnvironment, } from '../wrangler/environment.js';
|
|
9
11
|
const parseGithubActionsEvent = (() => {
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
+
const _ip0 = input => undefined === input["full_name"] || "string" === typeof input["full_name"];
|
|
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));
|
|
14
|
+
const _io1 = input => (undefined === input.default_branch || "string" === typeof input.default_branch) && _ip0(input);
|
|
15
|
+
const _io2 = input => (undefined === input.number || "number" === typeof input.number) && (undefined === input.head || "object" === typeof input.head && null !== input.head && false === Array.isArray(input.head) && _io3(input.head));
|
|
16
|
+
const _io3 = input => undefined === input.repo || "object" === typeof input.repo && null !== input.repo && false === Array.isArray(input.repo) && _io4(input.repo);
|
|
17
|
+
const _io4 = input => _ip0(input);
|
|
12
18
|
const __is = input => "object" === typeof input && null !== input && false === Array.isArray(input) && _io0(input);
|
|
13
19
|
return input => { input = JSON.parse(input); return __is(input) ? input : null; };
|
|
14
20
|
})();
|
|
15
|
-
const
|
|
21
|
+
const isGithubDeployment = (() => {
|
|
22
|
+
const _io0 = input => "number" === typeof input.id;
|
|
23
|
+
return input => "object" === typeof input && null !== input && _io0(input);
|
|
24
|
+
})();
|
|
25
|
+
const isNxProjectDeployTarget = (() => {
|
|
26
|
+
const _ip0 = input => true;
|
|
16
27
|
const _io0 = input => undefined === input.targets || "object" === typeof input.targets && null !== input.targets && false === Array.isArray(input.targets) && _io1(input.targets);
|
|
17
28
|
const _io1 = input => undefined === input.deploy || "object" === typeof input.deploy && null !== input.deploy && false === Array.isArray(input.deploy) && _io2(input.deploy);
|
|
18
|
-
const _io2 = input => undefined === input.
|
|
19
|
-
const _io3 = input =>
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
29
|
+
const _io2 = input => _ip0(input) && (undefined === input.options || "object" === typeof input.options && null !== input.options && false === Array.isArray(input.options) && _io3(input.options));
|
|
30
|
+
const _io3 = input => _ip0(input);
|
|
31
|
+
return input => "object" === typeof input && null !== input && false === Array.isArray(input) && _io0(input);
|
|
32
|
+
})();
|
|
33
|
+
const parseNxProjectDeployTarget = (() => {
|
|
34
|
+
const _ip0 = input => true;
|
|
35
|
+
const _io0 = input => undefined === input.targets || "object" === typeof input.targets && null !== input.targets && false === Array.isArray(input.targets) && _io1(input.targets);
|
|
36
|
+
const _io1 = input => undefined === input.deploy || "object" === typeof input.deploy && null !== input.deploy && false === Array.isArray(input.deploy) && _io2(input.deploy);
|
|
37
|
+
const _io2 = input => _ip0(input) && (undefined === input.options || "object" === typeof input.options && null !== input.options && false === Array.isArray(input.options) && _io3(input.options));
|
|
38
|
+
const _io3 = input => _ip0(input);
|
|
25
39
|
const __is = input => "object" === typeof input && null !== input && false === Array.isArray(input) && _io0(input);
|
|
26
40
|
return input => { input = JSON.parse(input); return __is(input) ? input : null; };
|
|
27
41
|
})();
|
|
@@ -262,6 +276,7 @@ export async function githubCiNxRunMany(root, options) {
|
|
|
262
276
|
const sourceSha = await readGitHeadSha(root);
|
|
263
277
|
await collectNxOutputs(root, options.collectOutputs, expandNxTargetDependencyRuns(expanded.runs), sourceSha);
|
|
264
278
|
}
|
|
279
|
+
return expanded;
|
|
265
280
|
}
|
|
266
281
|
export async function githubCiApplyOutputs(root, directories, expectedSourceSha) {
|
|
267
282
|
const { applyCollectedOutputs } = await loadOutputBoundary();
|
|
@@ -300,31 +315,74 @@ function commaSeparatedValues(value) {
|
|
|
300
315
|
.map((entry) => entry.trim())
|
|
301
316
|
.filter(Boolean);
|
|
302
317
|
}
|
|
303
|
-
export async function githubCiNxDeploy(root, options) {
|
|
304
|
-
const
|
|
318
|
+
export async function githubCiNxDeploy(root, options, dependencies = {}) {
|
|
319
|
+
const processEnv = dependencies.processEnv ?? process.env;
|
|
320
|
+
const eventPayload = dependencies.eventPayload ?? readGithubActionsEvent(processEnv);
|
|
321
|
+
const environment = resolveDeploymentEnvironment(options.environment, processEnv, eventPayload);
|
|
322
|
+
const name = options.name ?? 'Deploy Environment';
|
|
305
323
|
const step = options.step ?? '';
|
|
306
|
-
|
|
324
|
+
const setStatus = dependencies.setStatus ??
|
|
325
|
+
((state) => state === 'pending' ? createGithubStatus(name, step) : updateGithubStatus(name, state, step));
|
|
326
|
+
await setStatus('pending');
|
|
307
327
|
const mode = resolveNxSmartMode(options.mode ?? 'run-many');
|
|
308
|
-
const
|
|
328
|
+
const listProjects = dependencies.listProjects ?? listNxProjectsWithTarget;
|
|
329
|
+
const runNx = dependencies.runNx ?? ((args, commandRoot) => runStatus('nx', args, commandRoot));
|
|
330
|
+
const projects = await listProjects(root, 'deploy', mode);
|
|
309
331
|
if (projects.length === 0) {
|
|
310
|
-
console.log(`No ${mode} deploy projects
|
|
311
|
-
await
|
|
332
|
+
console.log(`No ${mode} deploy projects; skipping ${environment}.`);
|
|
333
|
+
await setStatus('success');
|
|
312
334
|
return;
|
|
313
335
|
}
|
|
314
336
|
const projectList = projects.join(',');
|
|
315
337
|
const targets = options.verify === true ? ['build', 'lint', 'test', 'deploy'] : ['deploy'];
|
|
316
338
|
for (const target of targets) {
|
|
317
|
-
const nxArgs = [
|
|
339
|
+
const nxArgs = [
|
|
340
|
+
'run-many',
|
|
341
|
+
'-t',
|
|
342
|
+
target,
|
|
343
|
+
`--projects=${projectList}`,
|
|
344
|
+
'--exclude=tag:permanent-deploy-target',
|
|
345
|
+
`--parallel=${NX_PARALLEL}`,
|
|
346
|
+
];
|
|
318
347
|
if (target === 'deploy') {
|
|
319
|
-
nxArgs.push(`--
|
|
348
|
+
nxArgs.push(`--environment=${environment}`);
|
|
320
349
|
}
|
|
321
|
-
const status = await
|
|
350
|
+
const status = await runNx(nxArgs, root);
|
|
322
351
|
if (status !== 0) {
|
|
323
|
-
await
|
|
352
|
+
await setStatus('failure');
|
|
324
353
|
throw new Error(`nx ${nxArgs.join(' ')} failed with exit code ${status}`);
|
|
325
354
|
}
|
|
326
355
|
}
|
|
327
|
-
|
|
356
|
+
if (isPullRequestEnvironment(environment)) {
|
|
357
|
+
const url = `https://app.${environment}.conloca.com`;
|
|
358
|
+
const summaryPath = processEnv.GITHUB_STEP_SUMMARY;
|
|
359
|
+
if (summaryPath) {
|
|
360
|
+
const appendSummary = dependencies.appendSummary ?? appendFile;
|
|
361
|
+
await appendSummary(summaryPath, `## ${environment} deployment\n\n[View deployment](${url})\n`);
|
|
362
|
+
}
|
|
363
|
+
const publishDeployment = dependencies.publishDeployment ??
|
|
364
|
+
((token, deploymentUrl) => publishGithubDeployment(token, deploymentUrl, processEnv));
|
|
365
|
+
await publishDeployment(environment, url);
|
|
366
|
+
}
|
|
367
|
+
if (environment !== 'production') {
|
|
368
|
+
const e2eProjects = await listProjects(root, 'e2e-deployed', 'run-many');
|
|
369
|
+
if (e2eProjects.length > 0) {
|
|
370
|
+
const nxArgs = [
|
|
371
|
+
'run-many',
|
|
372
|
+
'-t',
|
|
373
|
+
'e2e-deployed',
|
|
374
|
+
`--projects=${e2eProjects.join(',')}`,
|
|
375
|
+
`--parallel=${NX_PARALLEL}`,
|
|
376
|
+
`--environment=${environment}`,
|
|
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
|
+
}
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
await setStatus('success');
|
|
328
386
|
}
|
|
329
387
|
function resolveNxSmartMode(mode) {
|
|
330
388
|
if (mode === 'affected' || mode === 'run-many') {
|
|
@@ -357,24 +415,152 @@ function eventDefaultBranch() {
|
|
|
357
415
|
return undefined;
|
|
358
416
|
}
|
|
359
417
|
}
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
418
|
+
export function resolveDeploymentEnvironment(explicit, environment, event) {
|
|
419
|
+
if (explicit !== undefined)
|
|
420
|
+
return parseEnvironmentToken(explicit);
|
|
421
|
+
if (environment.GITHUB_EVENT_NAME === 'pull_request') {
|
|
422
|
+
if (!event?.action || !['opened', 'reopened', 'synchronize'].includes(event.action)) {
|
|
423
|
+
throw new Error('Pull-request deployment runs only for opened, reopened, or synchronize events.');
|
|
424
|
+
}
|
|
425
|
+
const repository = event.repository?.full_name;
|
|
426
|
+
const headRepository = event.pull_request?.head?.repo?.full_name;
|
|
427
|
+
if (!repository || !headRepository || repository !== headRepository) {
|
|
428
|
+
throw new Error('Pull-request deployment is restricted to same-repository pull requests.');
|
|
429
|
+
}
|
|
430
|
+
const number = event.pull_request?.number;
|
|
431
|
+
if (number === undefined)
|
|
432
|
+
throw new Error('GitHub pull_request event is missing its PR number.');
|
|
433
|
+
return pullRequestEnvironment(number);
|
|
434
|
+
}
|
|
435
|
+
if (environment.GITHUB_EVENT_NAME === 'push' && environment.GITHUB_REF_NAME === 'private') {
|
|
436
|
+
return 'staging';
|
|
437
|
+
}
|
|
438
|
+
if (environment.GITHUB_EVENT_NAME === 'release') {
|
|
439
|
+
return 'production';
|
|
440
|
+
}
|
|
441
|
+
throw new Error('Cannot resolve a deployment environment from this GitHub event; pass --environment explicitly.');
|
|
442
|
+
}
|
|
443
|
+
function readGithubActionsEvent(environment) {
|
|
444
|
+
const eventPath = environment.GITHUB_EVENT_PATH;
|
|
445
|
+
if (!eventPath)
|
|
446
|
+
return undefined;
|
|
447
|
+
try {
|
|
448
|
+
return parseGithubActionsEvent(readFileSync(eventPath, 'utf8')) || undefined;
|
|
449
|
+
}
|
|
450
|
+
catch {
|
|
451
|
+
return undefined;
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
async function listNxProjectsWithTarget(root, target, mode) {
|
|
455
|
+
const listArgs = ['show', 'projects'];
|
|
456
|
+
if (mode === 'affected')
|
|
457
|
+
listArgs.push('--affected');
|
|
458
|
+
listArgs.push('--withTarget', target);
|
|
459
|
+
if (target === 'deploy')
|
|
460
|
+
listArgs.push('--exclude=tag:permanent-deploy-target');
|
|
461
|
+
listArgs.push('--json');
|
|
364
462
|
const result = await $ `nx ${listArgs}`.cwd(root).quiet();
|
|
365
|
-
const candidates = nxProjectList(decode(result.stdout));
|
|
366
|
-
|
|
463
|
+
const candidates = nxProjectList(decode(result.stdout)).sort((left, right) => left.localeCompare(right));
|
|
464
|
+
if (target !== 'deploy')
|
|
465
|
+
return candidates;
|
|
466
|
+
return selectEnvironmentDeployProjects(candidates, async (project) => {
|
|
467
|
+
const projectResult = await $ `nx show project ${project} --json`.cwd(root).quiet();
|
|
468
|
+
const parsed = parseNxProjectDeployTarget(decode(projectResult.stdout));
|
|
469
|
+
if (!parsed)
|
|
470
|
+
throw new Error(`nx show project ${project} returned invalid JSON.`);
|
|
471
|
+
return parsed;
|
|
472
|
+
});
|
|
473
|
+
}
|
|
474
|
+
export async function selectEnvironmentDeployProjects(candidates, loadProject) {
|
|
475
|
+
const selected = [];
|
|
367
476
|
for (const project of candidates) {
|
|
368
|
-
|
|
369
|
-
|
|
477
|
+
const definition = await loadProject(project);
|
|
478
|
+
if (!isNxProjectDeployTarget(definition))
|
|
479
|
+
continue;
|
|
480
|
+
const deploy = definition.targets?.deploy;
|
|
481
|
+
const commandValue = deploy?.options?.command ?? deploy?.command;
|
|
482
|
+
if (typeof commandValue === 'string' && commandValue.includes('smoo wrangler deploy-environment')) {
|
|
483
|
+
selected.push(project);
|
|
370
484
|
}
|
|
371
485
|
}
|
|
372
|
-
return
|
|
486
|
+
return selected;
|
|
487
|
+
}
|
|
488
|
+
export class NodeGithubApiProcessRunner {
|
|
489
|
+
run(args, input, cwd) {
|
|
490
|
+
const { promise, resolve, reject } = Promise.withResolvers();
|
|
491
|
+
const child = spawn('gh', args, { cwd, stdio: ['pipe', 'pipe', 'pipe'] });
|
|
492
|
+
let stdout = '';
|
|
493
|
+
let stderr = '';
|
|
494
|
+
child.stdout.setEncoding('utf8');
|
|
495
|
+
child.stderr.setEncoding('utf8');
|
|
496
|
+
child.stdout.on('data', (chunk) => {
|
|
497
|
+
stdout += chunk;
|
|
498
|
+
});
|
|
499
|
+
child.stderr.on('data', (chunk) => {
|
|
500
|
+
stderr += chunk;
|
|
501
|
+
});
|
|
502
|
+
child.once('error', reject);
|
|
503
|
+
child.once('close', (code) => {
|
|
504
|
+
resolve({ exitCode: code ?? -1, stdout, stderr });
|
|
505
|
+
});
|
|
506
|
+
child.stdin.end(input);
|
|
507
|
+
return promise;
|
|
508
|
+
}
|
|
373
509
|
}
|
|
374
|
-
async function
|
|
375
|
-
const
|
|
376
|
-
const
|
|
377
|
-
|
|
510
|
+
export async function publishGithubDeployment(environment, url, processEnvironment, runner = new NodeGithubApiProcessRunner()) {
|
|
511
|
+
const repository = processEnvironment.GITHUB_REPOSITORY;
|
|
512
|
+
const sha = processEnvironment.GITHUB_SHA;
|
|
513
|
+
if (!repository || !sha)
|
|
514
|
+
throw new Error('GITHUB_REPOSITORY and GITHUB_SHA are required to publish a deployment.');
|
|
515
|
+
const createBody = JSON.stringify({
|
|
516
|
+
ref: sha,
|
|
517
|
+
environment,
|
|
518
|
+
auto_merge: false,
|
|
519
|
+
required_contexts: [],
|
|
520
|
+
transient_environment: true,
|
|
521
|
+
production_environment: false,
|
|
522
|
+
});
|
|
523
|
+
const createResult = await runner.run([
|
|
524
|
+
'api',
|
|
525
|
+
'--method',
|
|
526
|
+
'POST',
|
|
527
|
+
'-H',
|
|
528
|
+
'Accept: application/vnd.github+json',
|
|
529
|
+
`/repos/${repository}/deployments`,
|
|
530
|
+
'--input',
|
|
531
|
+
'-',
|
|
532
|
+
], createBody, process.cwd());
|
|
533
|
+
if (createResult.exitCode !== 0) {
|
|
534
|
+
throw new Error(`GitHub deployment creation failed with exit code ${createResult.exitCode}: ${createResult.stderr.trim()}`);
|
|
535
|
+
}
|
|
536
|
+
let deployment;
|
|
537
|
+
try {
|
|
538
|
+
deployment = JSON.parse(createResult.stdout);
|
|
539
|
+
}
|
|
540
|
+
catch {
|
|
541
|
+
throw new Error('GitHub returned invalid JSON while creating a deployment.');
|
|
542
|
+
}
|
|
543
|
+
if (!isGithubDeployment(deployment))
|
|
544
|
+
throw new Error('GitHub returned an invalid deployment response.');
|
|
545
|
+
const statusBody = JSON.stringify({
|
|
546
|
+
state: 'success',
|
|
547
|
+
environment,
|
|
548
|
+
environment_url: url,
|
|
549
|
+
auto_inactive: false,
|
|
550
|
+
});
|
|
551
|
+
const statusResult = await runner.run([
|
|
552
|
+
'api',
|
|
553
|
+
'--method',
|
|
554
|
+
'POST',
|
|
555
|
+
'-H',
|
|
556
|
+
'Accept: application/vnd.github+json',
|
|
557
|
+
`/repos/${repository}/deployments/${deployment.id}/statuses`,
|
|
558
|
+
'--input',
|
|
559
|
+
'-',
|
|
560
|
+
], statusBody, process.cwd());
|
|
561
|
+
if (statusResult.exitCode !== 0) {
|
|
562
|
+
throw new Error(`GitHub deployment status failed with exit code ${statusResult.exitCode}: ${statusResult.stderr.trim()}`);
|
|
563
|
+
}
|
|
378
564
|
}
|
|
379
565
|
function nxProjectList(output) {
|
|
380
566
|
return parseStringArrayText(output) ?? [];
|
|
@@ -29,7 +29,7 @@ export function defineCiWorkflow(options) {
|
|
|
29
29
|
{ kind: CiWorkflowStepKind.ManagedFilesDispatch, name: '🔁 Dispatch managed-file drift healing' },
|
|
30
30
|
];
|
|
31
31
|
if (options.deploy) {
|
|
32
|
-
steps.push({ kind: CiWorkflowStepKind.Deploy, name: '🚀 Deploy
|
|
32
|
+
steps.push({ kind: CiWorkflowStepKind.Deploy, name: '🚀 Deploy Environment' });
|
|
33
33
|
}
|
|
34
34
|
steps.push({ kind: CiWorkflowStepKind.SaveNxCache, name: '💾 Save Nx cache' }, { kind: CiWorkflowStepKind.UploadTraceDbs, name: '📎 Upload trace DBs' }, { kind: CiWorkflowStepKind.SaveNixDevenv, name: '🧹 Cleanup and cache Nix/devenv' });
|
|
35
35
|
return steps.map((step, index) => ({ ...step, number: index + 2 }));
|
|
@@ -51,7 +51,7 @@ permissions:
|
|
|
51
51
|
# actions:write lets the drift step dispatch the managed-files workflow.
|
|
52
52
|
actions: write
|
|
53
53
|
contents: read
|
|
54
|
-
statuses: write
|
|
54
|
+
${options.deploy ? ' deployments: write\n' : ''} statuses: write
|
|
55
55
|
|
|
56
56
|
defaults:
|
|
57
57
|
run:
|
|
@@ -167,11 +167,15 @@ function yamlLinesForStep(step, options) {
|
|
|
167
167
|
case CiWorkflowStepKind.Deploy:
|
|
168
168
|
return [
|
|
169
169
|
` - name: ${step.name}`,
|
|
170
|
-
' if:',
|
|
171
|
-
|
|
172
|
-
|
|
170
|
+
' if: >-',
|
|
171
|
+
' ${{',
|
|
172
|
+
" (github.event_name == 'pull_request' &&",
|
|
173
|
+
' contains(fromJSON(\'["opened","reopened","synchronize"]\'), github.event.action) &&',
|
|
174
|
+
' github.event.pull_request.head.repo.full_name == github.repository) ||',
|
|
175
|
+
" (github.event_name == 'push' && github.ref == 'refs/heads/private')",
|
|
176
|
+
' }}',
|
|
173
177
|
...deployEnvLines(options),
|
|
174
|
-
` run: smoo github-ci nx-deploy --
|
|
178
|
+
` run: smoo github-ci nx-deploy --mode run-many --name "Deploy Environment" --step ${step.number}`,
|
|
175
179
|
];
|
|
176
180
|
case CiWorkflowStepKind.SaveNxCache:
|
|
177
181
|
return [
|
|
@@ -220,6 +224,12 @@ function deployEnvLines(options) {
|
|
|
220
224
|
' env:',
|
|
221
225
|
' CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}',
|
|
222
226
|
' 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 }}',
|
|
223
233
|
];
|
|
224
234
|
}
|
|
225
235
|
function nxSmartStep(step, target, name) {
|
|
@@ -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;
|
|
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,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;AAeD,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;AAyGD,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"}
|
|
@@ -5,6 +5,7 @@ import { PLATFORM_TARGET_GLOBS } from '@smoothbricks/nx-plugin/workspace-config-
|
|
|
5
5
|
import { listReleasePackages, readPackageJson } from '../lib/workspace.js';
|
|
6
6
|
import { loadNxProjects, targetNamesFromProjects } from '../nx/index.js';
|
|
7
7
|
import { renderCiWorkflowYaml } from './ci-workflow.js';
|
|
8
|
+
import { renderPrPreviewCleanupWorkflowYaml } from './pr-preview-cleanup-workflow.js';
|
|
8
9
|
import { renderPublishWorkflowYaml } from './publish-workflow.js';
|
|
9
10
|
/**
|
|
10
11
|
* Repos may append their own content to a managed file below this marker —
|
|
@@ -156,6 +157,12 @@ const managedFiles = [
|
|
|
156
157
|
source: 'ci-workflow',
|
|
157
158
|
target: '.github/workflows/ci.yml',
|
|
158
159
|
},
|
|
160
|
+
{
|
|
161
|
+
kind: 'generated',
|
|
162
|
+
source: 'pr-preview-cleanup-workflow',
|
|
163
|
+
target: '.github/workflows/pr-preview-cleanup.yml',
|
|
164
|
+
cloudflareDeployOnly: true,
|
|
165
|
+
},
|
|
159
166
|
{
|
|
160
167
|
kind: 'generated',
|
|
161
168
|
source: 'publish-workflow',
|
|
@@ -208,6 +215,9 @@ function applyManagedFile(root, file, mode, context) {
|
|
|
208
215
|
if (file.releasePackagesOnly === true && !context.hasReleasePackages && !context.hasProductionDeployTargets) {
|
|
209
216
|
return { target: file.target, action: 'skipped' };
|
|
210
217
|
}
|
|
218
|
+
if (file.cloudflareDeployOnly === true && context.stagingDeployProvider !== 'cloudflare') {
|
|
219
|
+
return { target: file.target, action: 'skipped' };
|
|
220
|
+
}
|
|
211
221
|
const target = resolve(root, file.target);
|
|
212
222
|
const content = getManagedContent(file, context);
|
|
213
223
|
if (existsSync(target)) {
|
|
@@ -257,6 +267,9 @@ function getManagedContent(file, context) {
|
|
|
257
267
|
runsOn: context.ciRunsOn,
|
|
258
268
|
});
|
|
259
269
|
}
|
|
270
|
+
if (file.source === 'pr-preview-cleanup-workflow') {
|
|
271
|
+
return renderPrPreviewCleanupWorkflowYaml({ runsOn: context.ciRunsOn });
|
|
272
|
+
}
|
|
260
273
|
throw new Error(`Unknown generated managed file source ${file.source}`);
|
|
261
274
|
}
|
|
262
275
|
const sourceRoot = file.kind === 'raw' ? 'managed/raw' : 'managed/templates';
|
|
@@ -319,11 +332,16 @@ function deployTargetInfoFromTargets(targets, configuration) {
|
|
|
319
332
|
if (!deploy) {
|
|
320
333
|
return { exists: false };
|
|
321
334
|
}
|
|
335
|
+
const baseCommandValue = deploy.options?.command ?? deploy.command;
|
|
336
|
+
const baseCommand = typeof baseCommandValue === 'string' ? baseCommandValue : '';
|
|
337
|
+
if (baseCommand.includes('smoo wrangler deploy-environment')) {
|
|
338
|
+
return { exists: true, provider: 'cloudflare' };
|
|
339
|
+
}
|
|
322
340
|
const config = deploy.configurations?.[configuration];
|
|
323
341
|
if (!config) {
|
|
324
342
|
return { exists: false };
|
|
325
343
|
}
|
|
326
|
-
const commandValue = config.command ?? config.options?.command ??
|
|
344
|
+
const commandValue = config.command ?? config.options?.command ?? baseCommand;
|
|
327
345
|
const command = typeof commandValue === 'string' ? commandValue : '';
|
|
328
346
|
return { exists: true, provider: command.includes('wrangler ') ? 'cloudflare' : undefined };
|
|
329
347
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pr-preview-cleanup-workflow.d.ts","sourceRoot":"","sources":["../../src/monorepo/pr-preview-cleanup-workflow.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,+BAA+B;IAC9C,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CAC5B;AAED,wBAAgB,kCAAkC,CAAC,OAAO,GAAE,+BAAoC,GAAG,MAAM,CAmCxG"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/* biome-ignore-all lint/suspicious/noTemplateCurlyInString: GitHub Actions expressions are emitted literally. */
|
|
2
|
+
import { renderRunsOnLine } from './github-runs-on.js';
|
|
3
|
+
export function renderPrPreviewCleanupWorkflowYaml(options = {}) {
|
|
4
|
+
return `name: PR Preview Cleanup
|
|
5
|
+
|
|
6
|
+
on:
|
|
7
|
+
pull_request:
|
|
8
|
+
types: [closed]
|
|
9
|
+
|
|
10
|
+
permissions:
|
|
11
|
+
contents: read
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
cleanup:
|
|
15
|
+
name: Cleanup PR environment
|
|
16
|
+
if: github.event.pull_request.head.repo.full_name == github.repository
|
|
17
|
+
${renderRunsOnLine(options.runsOn)}
|
|
18
|
+
timeout-minutes: 15
|
|
19
|
+
defaults:
|
|
20
|
+
run:
|
|
21
|
+
working-directory: tooling/direnv
|
|
22
|
+
steps:
|
|
23
|
+
- name: Checkout
|
|
24
|
+
uses: actions/checkout@v6.0.2
|
|
25
|
+
with:
|
|
26
|
+
filter: blob:none
|
|
27
|
+
fetch-depth: 1
|
|
28
|
+
|
|
29
|
+
- name: Setup Nix/devenv
|
|
30
|
+
uses: ./.github/actions/setup-devenv
|
|
31
|
+
|
|
32
|
+
- name: Cleanup PR environment
|
|
33
|
+
env:
|
|
34
|
+
CLOUDFLARE_API_TOKEN: \${{ secrets.CLOUDFLARE_API_TOKEN }}
|
|
35
|
+
CLOUDFLARE_ACCOUNT_ID: \${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
|
36
|
+
run: smoo wrangler cleanup-pr --pr \${{ github.event.pull_request.number }}
|
|
37
|
+
`;
|
|
38
|
+
}
|