@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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloudflare.d.ts","sourceRoot":"","sources":["../../src/wrangler/cloudflare.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"cloudflare.d.ts","sourceRoot":"","sources":["../../src/wrangler/cloudflare.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type CloudflareClient } from './cloudflare.js';
|
|
2
|
-
import { type
|
|
2
|
+
import { type DeploymentStage } from './stage.js';
|
|
3
3
|
export interface ProcessResult {
|
|
4
4
|
exitCode: number;
|
|
5
5
|
stdout: string;
|
|
@@ -22,15 +22,15 @@ export interface WranglerCommandDependencies {
|
|
|
22
22
|
cloudflare?: CloudflareClient;
|
|
23
23
|
processEnv?: NodeJS.ProcessEnv;
|
|
24
24
|
}
|
|
25
|
-
export interface
|
|
26
|
-
|
|
25
|
+
export interface DeployStageResult {
|
|
26
|
+
stage: DeploymentStage;
|
|
27
27
|
workerName: string;
|
|
28
28
|
action: 'deployed' | 'activated' | 'remote-cache-hit';
|
|
29
29
|
versionTag?: string;
|
|
30
30
|
}
|
|
31
|
-
export declare function
|
|
31
|
+
export declare function deployStage(cwd: string, stageValue: string, dependencies?: WranglerCommandDependencies): Promise<DeployStageResult>;
|
|
32
32
|
export interface CleanupResult {
|
|
33
|
-
|
|
33
|
+
stage: `pr${number}`;
|
|
34
34
|
deleted: {
|
|
35
35
|
workers: number;
|
|
36
36
|
routes: number;
|
|
@@ -45,4 +45,4 @@ export declare function cleanupPullRequest(cwd: string, prNumber: number, depend
|
|
|
45
45
|
export declare function nxTaskVersionTag(environment: NodeJS.ProcessEnv): string | undefined;
|
|
46
46
|
export declare function findVersionIdByTag(value: unknown, tag: string): string | null;
|
|
47
47
|
export declare function isFullCurrentDeployment(value: unknown, versionId: string): boolean;
|
|
48
|
-
//# sourceMappingURL=deploy-
|
|
48
|
+
//# sourceMappingURL=deploy-stage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deploy-stage.d.ts","sourceRoot":"","sources":["../../src/wrangler/deploy-stage.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,gBAAgB,EAAwB,MAAM,iBAAiB,CAAC;AAE9E,OAAO,EAEL,KAAK,eAAe,EASrB,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;CACtH;AAED,qBAAa,gBAAiB,YAAW,aAAa;IAC9C,GAAG,CACP,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,GACrD,OAAO,CAAC,aAAa,CAAC,CAcxB;CACF;AAED,MAAM,WAAW,2BAA2B;IAC1C,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CAChC;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,eAAe,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,UAAU,GAAG,WAAW,GAAG,kBAAkB,CAAC;IACtD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAID,wBAAsB,WAAW,CAC/B,GAAG,EAAE,MAAM,EACX,UAAU,EAAE,MAAM,EAClB,YAAY,GAAE,2BAAgC,GAC7C,OAAO,CAAC,iBAAiB,CAAC,CA2H5B;AACD,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,KAAK,MAAM,EAAE,CAAC;IACrB,OAAO,EAAE;QACP,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;QAChB,YAAY,EAAE,MAAM,CAAC;QACrB,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;CACH;AAED,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM,EAChB,YAAY,GAAE,2BAAgC,GAC7C,OAAO,CAAC,aAAa,CAAC,CA2DxB;AAwFD,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,GAAG,SAAS,CAgBnF;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAuB7E;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAelF"}
|
|
@@ -4,8 +4,8 @@ import { readFile, rm, writeFile } from 'node:fs/promises';
|
|
|
4
4
|
import { join } from 'node:path';
|
|
5
5
|
import typia from 'typia';
|
|
6
6
|
import { CloudflareRestClient } from './cloudflare.js';
|
|
7
|
-
import { derivePullRequestWranglerConfig, environmentResourceName, hasExactEnvironmentSegment, isPullRequestEnvironment, parseEnvironmentToken, planConfiguredEnvironmentResources, planPullRequestResources, pullRequestEnvironment, } from './environment.js';
|
|
8
7
|
import { parseDevVarsExample } from './prepare-env.js';
|
|
8
|
+
import { derivePullRequestWranglerConfig, hasExactStageSegment, isPullRequestStage, parseDeploymentStage, planConfiguredStageResources, planPullRequestResources, pullRequestStage, stageResourceName, } from './stage.js';
|
|
9
9
|
export class BunProcessRunner {
|
|
10
10
|
async run(command, args, options) {
|
|
11
11
|
const child = Bun.spawn([command, ...args], {
|
|
@@ -32,8 +32,8 @@ const isUnknownRecord = (() => {
|
|
|
32
32
|
});
|
|
33
33
|
return input => "object" === typeof input && null !== input && false === Array.isArray(input) && _io0(input);
|
|
34
34
|
})();
|
|
35
|
-
export async function
|
|
36
|
-
const
|
|
35
|
+
export async function deployStage(cwd, stageValue, dependencies = {}) {
|
|
36
|
+
const stage = parseDeploymentStage(stageValue);
|
|
37
37
|
const processEnv = dependencies.processEnv ?? process.env;
|
|
38
38
|
const accountId = processEnv.CLOUDFLARE_ACCOUNT_ID;
|
|
39
39
|
const apiToken = processEnv.CLOUDFLARE_API_TOKEN;
|
|
@@ -56,18 +56,18 @@ export async function deployEnvironment(cwd, environmentValue, dependencies = {}
|
|
|
56
56
|
let temporaryConfigPath;
|
|
57
57
|
let temporarySecretsPath;
|
|
58
58
|
try {
|
|
59
|
-
if (
|
|
60
|
-
const staging =
|
|
59
|
+
if (isPullRequestStage(stage)) {
|
|
60
|
+
const staging = planConfiguredStageResources(committedToml, 'staging');
|
|
61
61
|
if (!staging.workerName.endsWith('-staging')) {
|
|
62
62
|
throw new Error('[env.staging].name must end with the exact suffix -staging.');
|
|
63
63
|
}
|
|
64
|
-
const workerName =
|
|
64
|
+
const workerName = stageResourceName(staging.workerName.slice(0, -'-staging'.length), stage);
|
|
65
65
|
const firstDeployment = !(await cloudflare.listWorkerScripts()).some((script) => script.id === workerName);
|
|
66
66
|
if (firstDeployment && missingSecrets.length > 0) {
|
|
67
67
|
throw new Error(`First deployment of ${workerName} requires process environment values for: ${missingSecrets.join(', ')}.`);
|
|
68
68
|
}
|
|
69
69
|
const liveNamespaces = await cloudflare.listKvNamespaces();
|
|
70
|
-
const plan = planPullRequestResources(committedToml,
|
|
70
|
+
const plan = planPullRequestResources(committedToml, stage, liveNamespaces);
|
|
71
71
|
const derivedIds = new Map();
|
|
72
72
|
const byTitle = new Map(liveNamespaces.map((namespace) => [namespace.title, namespace]));
|
|
73
73
|
for (const namespace of plan.kvNamespaces) {
|
|
@@ -86,7 +86,7 @@ export async function deployEnvironment(cwd, environmentValue, dependencies = {}
|
|
|
86
86
|
derivedIds.set(namespace.stagingId, live.id);
|
|
87
87
|
}
|
|
88
88
|
const derivedToml = derivePullRequestWranglerConfig(committedToml, {
|
|
89
|
-
|
|
89
|
+
stage: stage,
|
|
90
90
|
accountId,
|
|
91
91
|
kvNamespaceIds: derivedIds,
|
|
92
92
|
});
|
|
@@ -95,16 +95,16 @@ export async function deployEnvironment(cwd, environmentValue, dependencies = {}
|
|
|
95
95
|
configPath = temporaryConfigPath;
|
|
96
96
|
}
|
|
97
97
|
const toml = configPath === committedConfigPath ? committedToml : await readFile(configPath, 'utf8');
|
|
98
|
-
const plan =
|
|
99
|
-
const workerExists = await
|
|
98
|
+
const plan = planConfiguredStageResources(toml, stage);
|
|
99
|
+
const workerExists = await reconcileStageResources(plan, cloudflare);
|
|
100
100
|
const versionTag = nxTaskVersionTag(processEnv);
|
|
101
|
-
const commandContext = { cwd, configPath,
|
|
101
|
+
const commandContext = { cwd, configPath, stage, workerName: plan.workerName };
|
|
102
102
|
if (versionTag && workerExists) {
|
|
103
103
|
const versions = await wranglerJson(runner, ['versions', 'list', '--name', plan.workerName, '--json'], cwd);
|
|
104
104
|
const deployments = await wranglerJson(runner, ['deployments', 'status', '--name', plan.workerName, '--json'], cwd);
|
|
105
105
|
const versionId = findVersionIdByTag(versions, versionTag);
|
|
106
106
|
if (versionId && isFullCurrentDeployment(deployments, versionId)) {
|
|
107
|
-
return {
|
|
107
|
+
return { stage, workerName: plan.workerName, action: 'remote-cache-hit', versionTag };
|
|
108
108
|
}
|
|
109
109
|
if (versionId) {
|
|
110
110
|
await wrangler(runner, [
|
|
@@ -117,13 +117,13 @@ export async function deployEnvironment(cwd, environmentValue, dependencies = {}
|
|
|
117
117
|
'--config',
|
|
118
118
|
configPath,
|
|
119
119
|
'--env',
|
|
120
|
-
|
|
120
|
+
stage,
|
|
121
121
|
'--yes',
|
|
122
122
|
], cwd);
|
|
123
|
-
return {
|
|
123
|
+
return { stage, workerName: plan.workerName, action: 'activated', versionTag };
|
|
124
124
|
}
|
|
125
125
|
}
|
|
126
|
-
const deployArgs = ['deploy', '--config', commandContext.configPath, '--env', commandContext.
|
|
126
|
+
const deployArgs = ['deploy', '--config', commandContext.configPath, '--env', commandContext.stage];
|
|
127
127
|
if (versionTag)
|
|
128
128
|
deployArgs.push('--tag', versionTag);
|
|
129
129
|
if (Object.keys(secretValues).length > 0) {
|
|
@@ -133,7 +133,7 @@ export async function deployEnvironment(cwd, environmentValue, dependencies = {}
|
|
|
133
133
|
}
|
|
134
134
|
await wrangler(runner, deployArgs, cwd);
|
|
135
135
|
return {
|
|
136
|
-
|
|
136
|
+
stage,
|
|
137
137
|
workerName: commandContext.workerName,
|
|
138
138
|
action: 'deployed',
|
|
139
139
|
...(versionTag ? { versionTag } : {}),
|
|
@@ -149,7 +149,7 @@ export async function deployEnvironment(cwd, environmentValue, dependencies = {}
|
|
|
149
149
|
}
|
|
150
150
|
}
|
|
151
151
|
export async function cleanupPullRequest(cwd, prNumber, dependencies = {}) {
|
|
152
|
-
const
|
|
152
|
+
const stage = pullRequestStage(prNumber);
|
|
153
153
|
const processEnv = dependencies.processEnv ?? process.env;
|
|
154
154
|
const cloudflare = dependencies.cloudflare ??
|
|
155
155
|
new CloudflareRestClient(requiredEnvironmentValue(processEnv.CLOUDFLARE_ACCOUNT_ID, 'CLOUDFLARE_ACCOUNT_ID'), requiredEnvironmentValue(processEnv.CLOUDFLARE_API_TOKEN, 'CLOUDFLARE_API_TOKEN'));
|
|
@@ -164,39 +164,39 @@ export async function cleanupPullRequest(cwd, prNumber, dependencies = {}) {
|
|
|
164
164
|
dnsRecords: 0,
|
|
165
165
|
};
|
|
166
166
|
for (const domain of await cloudflare.listWorkerDomains()) {
|
|
167
|
-
if (!
|
|
167
|
+
if (!hasExactStageSegment(domain.hostname, stage))
|
|
168
168
|
continue;
|
|
169
169
|
await cloudflare.deleteWorkerDomain(domain.id);
|
|
170
170
|
deleted.domains += 1;
|
|
171
171
|
}
|
|
172
172
|
for (const zone of await cloudflare.listZones()) {
|
|
173
173
|
for (const route of await cloudflare.listWorkerRoutes(zone.id)) {
|
|
174
|
-
if (!
|
|
174
|
+
if (!hasExactStageSegment(route.pattern, stage))
|
|
175
175
|
continue;
|
|
176
176
|
await cloudflare.deleteWorkerRoute(zone.id, route.id);
|
|
177
177
|
deleted.routes += 1;
|
|
178
178
|
}
|
|
179
179
|
for (const record of await cloudflare.listDnsRecords(zone.id)) {
|
|
180
|
-
if (!
|
|
180
|
+
if (!hasExactStageSegment(record.name, stage))
|
|
181
181
|
continue;
|
|
182
182
|
await cloudflare.deleteDnsRecord(zone.id, record.id);
|
|
183
183
|
deleted.dnsRecords += 1;
|
|
184
184
|
}
|
|
185
185
|
}
|
|
186
186
|
for (const script of await cloudflare.listWorkerScripts()) {
|
|
187
|
-
if (!
|
|
187
|
+
if (!hasExactStageSegment(script.id, stage))
|
|
188
188
|
continue;
|
|
189
189
|
await cloudflare.deleteWorkerScript(script.id);
|
|
190
190
|
deleted.workers += 1;
|
|
191
191
|
}
|
|
192
192
|
for (const namespace of await cloudflare.listKvNamespaces()) {
|
|
193
|
-
if (!
|
|
193
|
+
if (!hasExactStageSegment(namespace.title, stage))
|
|
194
194
|
continue;
|
|
195
195
|
await cloudflare.deleteKvNamespace(namespace.id);
|
|
196
196
|
deleted.kvNamespaces += 1;
|
|
197
197
|
}
|
|
198
198
|
for (const bucket of await cloudflare.listR2Buckets()) {
|
|
199
|
-
if (!
|
|
199
|
+
if (!hasExactStageSegment(bucket.name, stage))
|
|
200
200
|
continue;
|
|
201
201
|
for (const key of await cloudflare.listR2Objects(bucket.name)) {
|
|
202
202
|
await cloudflare.deleteR2Object(bucket.name, key);
|
|
@@ -205,9 +205,9 @@ export async function cleanupPullRequest(cwd, prNumber, dependencies = {}) {
|
|
|
205
205
|
await cloudflare.deleteR2Bucket(bucket.name);
|
|
206
206
|
deleted.r2Buckets += 1;
|
|
207
207
|
}
|
|
208
|
-
return {
|
|
208
|
+
return { stage, deleted };
|
|
209
209
|
}
|
|
210
|
-
async function
|
|
210
|
+
async function reconcileStageResources(plan, cloudflare) {
|
|
211
211
|
const namespaces = await cloudflare.listKvNamespaces();
|
|
212
212
|
const namespaceIds = new Set(namespaces.map((namespace) => namespace.id));
|
|
213
213
|
for (const binding of plan.kvNamespaces) {
|
|
@@ -305,7 +305,7 @@ export function nxTaskVersionTag(environment) {
|
|
|
305
305
|
if (!underNx)
|
|
306
306
|
return undefined;
|
|
307
307
|
if (!hash)
|
|
308
|
-
throw new Error('NX_TASK_HASH is required when deploy-
|
|
308
|
+
throw new Error('NX_TASK_HASH is required when deploy-stage runs under Nx.');
|
|
309
309
|
if (/^(?:0|[1-9][0-9]*)$/.test(hash)) {
|
|
310
310
|
return `nx-${hash}`;
|
|
311
311
|
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
export type DeploymentStage = 'staging' | 'production' | `pr${number}`;
|
|
2
|
+
export declare function pullRequestStage(prNumber: number): `pr${number}`;
|
|
3
|
+
export declare function parseDeploymentStage(value: string): DeploymentStage;
|
|
4
|
+
export declare function isPullRequestStage(stage: DeploymentStage): stage is `pr${number}`;
|
|
5
|
+
export declare function stageDomain(stage: string, zone: string): string;
|
|
6
|
+
export declare function stageResourceName(base: string, stage: string): string;
|
|
7
|
+
export declare function hasExactStageSegment(value: string, stage: `pr${number}`): boolean;
|
|
8
|
+
export interface KvBinding {
|
|
9
|
+
binding: string;
|
|
10
|
+
id: string;
|
|
11
|
+
}
|
|
12
|
+
export interface R2Binding {
|
|
13
|
+
binding: string;
|
|
14
|
+
bucketName: string;
|
|
15
|
+
}
|
|
16
|
+
export interface LiveKvNamespace {
|
|
17
|
+
id: string;
|
|
18
|
+
title: string;
|
|
19
|
+
}
|
|
20
|
+
export interface PullRequestKvResource {
|
|
21
|
+
binding: string;
|
|
22
|
+
stagingId: string;
|
|
23
|
+
stagingTitle: string;
|
|
24
|
+
title: string;
|
|
25
|
+
}
|
|
26
|
+
export interface PullRequestResourcePlan {
|
|
27
|
+
stage: `pr${number}`;
|
|
28
|
+
workerName: string;
|
|
29
|
+
workerBaseName: string;
|
|
30
|
+
kvNamespaces: PullRequestKvResource[];
|
|
31
|
+
r2Buckets: R2Binding[];
|
|
32
|
+
routes: Array<{
|
|
33
|
+
pattern: string;
|
|
34
|
+
zoneName?: string;
|
|
35
|
+
customDomain: boolean;
|
|
36
|
+
}>;
|
|
37
|
+
}
|
|
38
|
+
export interface ConfiguredStageResourcePlan {
|
|
39
|
+
stage: DeploymentStage;
|
|
40
|
+
workerName: string;
|
|
41
|
+
kvNamespaces: KvBinding[];
|
|
42
|
+
r2Buckets: R2Binding[];
|
|
43
|
+
routes: Array<{
|
|
44
|
+
pattern: string;
|
|
45
|
+
zoneName?: string;
|
|
46
|
+
customDomain: boolean;
|
|
47
|
+
}>;
|
|
48
|
+
}
|
|
49
|
+
export declare function planConfiguredStageResources(toml: string, stage: DeploymentStage): ConfiguredStageResourcePlan;
|
|
50
|
+
export declare function planPullRequestResources(toml: string, stage: `pr${number}`, liveNamespaces: LiveKvNamespace[]): PullRequestResourcePlan;
|
|
51
|
+
export interface DerivePullRequestConfigOptions {
|
|
52
|
+
stage: `pr${number}`;
|
|
53
|
+
accountId: string;
|
|
54
|
+
kvNamespaceIds: ReadonlyMap<string, string>;
|
|
55
|
+
}
|
|
56
|
+
export declare function derivePullRequestWranglerConfig(toml: string, options: DerivePullRequestConfigOptions): string;
|
|
57
|
+
export declare function rateLimitNamespaceId(accountId: string, workerBaseName: string, stage: string, bindingName: string): string;
|
|
58
|
+
//# sourceMappingURL=stage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stage.d.ts","sourceRoot":"","sources":["../../src/wrangler/stage.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,YAAY,GAAG,KAAK,MAAM,EAAE,CAAC;AAKvE,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,KAAK,MAAM,EAAE,CAKhE;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,eAAe,CAQnE;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,eAAe,GAAG,KAAK,IAAI,KAAK,MAAM,EAAE,CAEjF;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAM/D;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAMrE;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,MAAM,EAAE,GAAG,OAAO,CAGjF;AAgBD,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;CACZ;AACD,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACpB;AAMD,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,KAAK,MAAM,EAAE,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,qBAAqB,EAAE,CAAC;IACtC,SAAS,EAAE,SAAS,EAAE,CAAC;IACvB,MAAM,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CAC9E;AACD,MAAM,WAAW,2BAA2B;IAC1C,KAAK,EAAE,eAAe,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,SAAS,EAAE,CAAC;IAC1B,SAAS,EAAE,SAAS,EAAE,CAAC;IACvB,MAAM,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CAC9E;AAED,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,GAAG,2BAA2B,CAoB9G;AAyBD,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,KAAK,MAAM,EAAE,EACpB,cAAc,EAAE,eAAe,EAAE,GAChC,uBAAuB,CAwCzB;AAED,MAAM,WAAW,8BAA8B;IAC7C,KAAK,EAAE,KAAK,MAAM,EAAE,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC7C;AAED,wBAAgB,+BAA+B,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,8BAA8B,GAAG,MAAM,CAkD7G;AAgDD,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,MAAM,EACjB,cAAc,EAAE,MAAM,EACtB,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,GAClB,MAAM,CAKR"}
|
|
@@ -3,40 +3,40 @@ import { getStaticTOMLValue, parseTOML } from 'toml-eslint-parser';
|
|
|
3
3
|
import typia from 'typia';
|
|
4
4
|
import { cloneEnvBlock } from './prepare-env.js';
|
|
5
5
|
const MAX_PULL_REQUEST_NUMBER = 999999999;
|
|
6
|
-
const
|
|
7
|
-
export function
|
|
6
|
+
const STAGE_PATTERN = /^(?:staging|production|pr[1-9][0-9]{0,8})$/;
|
|
7
|
+
export function pullRequestStage(prNumber) {
|
|
8
8
|
if (!Number.isInteger(prNumber) || prNumber < 1 || prNumber > MAX_PULL_REQUEST_NUMBER) {
|
|
9
9
|
throw new Error(`Pull request number must be an integer from 1 through ${MAX_PULL_REQUEST_NUMBER}.`);
|
|
10
10
|
}
|
|
11
11
|
return `pr${prNumber}`;
|
|
12
12
|
}
|
|
13
|
-
export function
|
|
14
|
-
if (!
|
|
15
|
-
throw new Error('
|
|
13
|
+
export function parseDeploymentStage(value) {
|
|
14
|
+
if (!STAGE_PATTERN.test(value)) {
|
|
15
|
+
throw new Error('Deployment stage must be exactly staging, production, or pr followed by an integer from 1 through 999999999.');
|
|
16
16
|
}
|
|
17
17
|
if (value === 'staging' || value === 'production')
|
|
18
18
|
return value;
|
|
19
|
-
return
|
|
19
|
+
return pullRequestStage(Number(value.slice(2)));
|
|
20
20
|
}
|
|
21
|
-
export function
|
|
22
|
-
return
|
|
21
|
+
export function isPullRequestStage(stage) {
|
|
22
|
+
return stage.startsWith('pr');
|
|
23
23
|
}
|
|
24
|
-
export function
|
|
25
|
-
const token =
|
|
24
|
+
export function stageDomain(stage, zone) {
|
|
25
|
+
const token = parseDeploymentStage(stage);
|
|
26
26
|
if (!zone || zone.startsWith('.') || zone.endsWith('.')) {
|
|
27
27
|
throw new Error('Zone must be a non-empty DNS name without leading or trailing dots.');
|
|
28
28
|
}
|
|
29
29
|
return token === 'production' ? zone : `${token}.${zone}`;
|
|
30
30
|
}
|
|
31
|
-
export function
|
|
32
|
-
const token =
|
|
31
|
+
export function stageResourceName(base, stage) {
|
|
32
|
+
const token = parseDeploymentStage(stage);
|
|
33
33
|
if (!base) {
|
|
34
34
|
throw new Error('Resource base name must not be empty.');
|
|
35
35
|
}
|
|
36
36
|
return token === 'production' ? base : `${base}-${token}`;
|
|
37
37
|
}
|
|
38
|
-
export function
|
|
39
|
-
const escaped =
|
|
38
|
+
export function hasExactStageSegment(value, stage) {
|
|
39
|
+
const escaped = stage.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
40
40
|
return new RegExp(`(?:^|[-.])${escaped}(?=$|[-.])`).test(value);
|
|
41
41
|
}
|
|
42
42
|
const isWranglerRoot = (() => {
|
|
@@ -86,14 +86,14 @@ const isUnknownRows = (() => {
|
|
|
86
86
|
});
|
|
87
87
|
return input => Array.isArray(input) && input.every(elem => "object" === typeof elem && null !== elem && false === Array.isArray(elem) && _io0(elem));
|
|
88
88
|
})();
|
|
89
|
-
export function
|
|
90
|
-
const block = parseRoot(toml).env?.[
|
|
89
|
+
export function planConfiguredStageResources(toml, stage) {
|
|
90
|
+
const block = parseRoot(toml).env?.[stage];
|
|
91
91
|
if (!isWranglerEnvironment(block)) {
|
|
92
|
-
throw new Error(`Wrangler configuration must declare [env.${
|
|
92
|
+
throw new Error(`Wrangler configuration must declare [env.${stage}].`);
|
|
93
93
|
}
|
|
94
|
-
const workerName = requiredString(block, 'name', `[env.${
|
|
94
|
+
const workerName = requiredString(block, 'name', `[env.${stage}]`);
|
|
95
95
|
return {
|
|
96
|
-
|
|
96
|
+
stage,
|
|
97
97
|
workerName,
|
|
98
98
|
kvNamespaces: readKvBindings(block.kv_namespaces),
|
|
99
99
|
r2Buckets: readRows(block.r2_buckets).map((row) => {
|
|
@@ -127,8 +127,8 @@ function stagingWorkerName(staging) {
|
|
|
127
127
|
}
|
|
128
128
|
return { workerName: staging.name, workerBaseName: staging.name.slice(0, -'-staging'.length) };
|
|
129
129
|
}
|
|
130
|
-
export function planPullRequestResources(toml,
|
|
131
|
-
|
|
130
|
+
export function planPullRequestResources(toml, stage, liveNamespaces) {
|
|
131
|
+
parseDeploymentStage(stage);
|
|
132
132
|
const staging = stagingEnvironment(toml);
|
|
133
133
|
const { workerBaseName } = stagingWorkerName(staging);
|
|
134
134
|
const namespaceById = new Map(liveNamespaces.map((namespace) => [namespace.id, namespace]));
|
|
@@ -137,7 +137,7 @@ export function planPullRequestResources(toml, environment, liveNamespaces) {
|
|
|
137
137
|
if (!stagingNamespace) {
|
|
138
138
|
throw new Error(`Staging KV binding ${binding} references namespace ${id}, which is absent from the account listing.`);
|
|
139
139
|
}
|
|
140
|
-
const title = replaceExactToken(stagingNamespace.title, 'staging',
|
|
140
|
+
const title = replaceExactToken(stagingNamespace.title, 'staging', stage);
|
|
141
141
|
if (title === stagingNamespace.title) {
|
|
142
142
|
throw new Error(`Staging KV namespace title ${stagingNamespace.title} has no exact staging segment.`);
|
|
143
143
|
}
|
|
@@ -146,20 +146,20 @@ export function planPullRequestResources(toml, environment, liveNamespaces) {
|
|
|
146
146
|
const r2Buckets = readRows(staging.r2_buckets).map((row) => {
|
|
147
147
|
const binding = requiredString(row, 'binding', 'R2 binding');
|
|
148
148
|
const stagingBucket = requiredString(row, 'bucket_name', `R2 binding ${binding}`);
|
|
149
|
-
const bucketName = replaceExactToken(stagingBucket, 'staging',
|
|
149
|
+
const bucketName = replaceExactToken(stagingBucket, 'staging', stage);
|
|
150
150
|
if (bucketName === stagingBucket) {
|
|
151
151
|
throw new Error(`Staging R2 bucket ${stagingBucket} has no exact staging segment.`);
|
|
152
152
|
}
|
|
153
153
|
return { binding, bucketName };
|
|
154
154
|
});
|
|
155
155
|
const routes = readRows(staging.routes).map((row) => ({
|
|
156
|
-
pattern: replaceHostnameLabel(requiredString(row, 'pattern', 'route'),
|
|
156
|
+
pattern: replaceHostnameLabel(requiredString(row, 'pattern', 'route'), stage),
|
|
157
157
|
...(typeof row.zone_name === 'string' ? { zoneName: row.zone_name } : {}),
|
|
158
158
|
customDomain: row.custom_domain === true,
|
|
159
159
|
}));
|
|
160
160
|
return {
|
|
161
|
-
|
|
162
|
-
workerName:
|
|
161
|
+
stage,
|
|
162
|
+
workerName: stageResourceName(workerBaseName, stage),
|
|
163
163
|
workerBaseName,
|
|
164
164
|
kvNamespaces,
|
|
165
165
|
r2Buckets,
|
|
@@ -167,14 +167,14 @@ export function planPullRequestResources(toml, environment, liveNamespaces) {
|
|
|
167
167
|
};
|
|
168
168
|
}
|
|
169
169
|
export function derivePullRequestWranglerConfig(toml, options) {
|
|
170
|
-
const
|
|
171
|
-
|
|
170
|
+
const stage = options.stage;
|
|
171
|
+
parseDeploymentStage(stage);
|
|
172
172
|
if (!options.accountId) {
|
|
173
173
|
throw new Error('Cloudflare account id is required to derive rate-limit namespaces.');
|
|
174
174
|
}
|
|
175
175
|
const staging = stagingEnvironment(toml);
|
|
176
176
|
const { workerBaseName } = stagingWorkerName(staging);
|
|
177
|
-
const cloned = cloneEnvBlock(toml, 'staging',
|
|
177
|
+
const cloned = cloneEnvBlock(toml, 'staging', stage);
|
|
178
178
|
const program = parseTOML(cloned);
|
|
179
179
|
const rootValue = getStaticTOMLValue(program);
|
|
180
180
|
if (!isWranglerRoot(rootValue)) {
|
|
@@ -183,7 +183,7 @@ export function derivePullRequestWranglerConfig(toml, options) {
|
|
|
183
183
|
const root = rootValue;
|
|
184
184
|
const edits = [];
|
|
185
185
|
for (const table of program.body[0].body) {
|
|
186
|
-
if (table.type !== 'TOMLTable' || table.resolvedKey[0] !== 'env' || table.resolvedKey[1] !==
|
|
186
|
+
if (table.type !== 'TOMLTable' || table.resolvedKey[0] !== 'env' || table.resolvedKey[1] !== stage) {
|
|
187
187
|
continue;
|
|
188
188
|
}
|
|
189
189
|
const tableValue = valueAtPath(root, table.resolvedKey);
|
|
@@ -193,7 +193,7 @@ export function derivePullRequestWranglerConfig(toml, options) {
|
|
|
193
193
|
for (const keyValue of table.body) {
|
|
194
194
|
const key = cloned.slice(keyValue.key.range[0], keyValue.key.range[1]).trim();
|
|
195
195
|
const current = tableValue[key];
|
|
196
|
-
const next = deriveFieldValue(table.resolvedKey.slice(2), tableValue, key, current,
|
|
196
|
+
const next = deriveFieldValue(table.resolvedKey.slice(2), tableValue, key, current, stage, workerBaseName, options.accountId, options.kvNamespaceIds);
|
|
197
197
|
if (next !== current) {
|
|
198
198
|
edits.push({ start: keyValue.value.range[0], end: keyValue.value.range[1], value: tomlLiteral(next) });
|
|
199
199
|
}
|
|
@@ -206,25 +206,25 @@ export function derivePullRequestWranglerConfig(toml, options) {
|
|
|
206
206
|
parseTOML(derived);
|
|
207
207
|
return derived;
|
|
208
208
|
}
|
|
209
|
-
function deriveFieldValue(path, table, key, current,
|
|
209
|
+
function deriveFieldValue(path, table, key, current, stage, workerBaseName, accountId, kvNamespaceIds) {
|
|
210
210
|
const section = path[0];
|
|
211
211
|
if (path.length === 0 && key === 'name') {
|
|
212
|
-
return
|
|
212
|
+
return stageResourceName(workerBaseName, stage);
|
|
213
213
|
}
|
|
214
214
|
if (section === 'routes' && key === 'pattern' && typeof current === 'string') {
|
|
215
|
-
return replaceHostnameLabel(current,
|
|
215
|
+
return replaceHostnameLabel(current, stage);
|
|
216
216
|
}
|
|
217
217
|
if (section === 'vars' && typeof current === 'string') {
|
|
218
218
|
if (key === 'ENVIRONMENT') {
|
|
219
|
-
return
|
|
219
|
+
return stage;
|
|
220
220
|
}
|
|
221
221
|
if (key === 'AUTH_KEYS_INSTANCE_NAME') {
|
|
222
|
-
return replaceExactToken(current, 'staging',
|
|
222
|
+
return replaceExactToken(current, 'staging', stage);
|
|
223
223
|
}
|
|
224
|
-
return replaceHostnameLabel(current,
|
|
224
|
+
return replaceHostnameLabel(current, stage);
|
|
225
225
|
}
|
|
226
226
|
if (section === 'send_email' && key === 'allowed_sender_addresses' && Array.isArray(current)) {
|
|
227
|
-
return current.map((value) => (typeof value === 'string' ? replaceHostnameLabel(value,
|
|
227
|
+
return current.map((value) => (typeof value === 'string' ? replaceHostnameLabel(value, stage) : value));
|
|
228
228
|
}
|
|
229
229
|
if (section === 'kv_namespaces' && key === 'id' && typeof current === 'string') {
|
|
230
230
|
const derived = kvNamespaceIds.get(current);
|
|
@@ -234,22 +234,22 @@ function deriveFieldValue(path, table, key, current, environment, workerBaseName
|
|
|
234
234
|
return derived;
|
|
235
235
|
}
|
|
236
236
|
if (section === 'r2_buckets' && key === 'bucket_name' && typeof current === 'string') {
|
|
237
|
-
return replaceExactToken(current, 'staging',
|
|
237
|
+
return replaceExactToken(current, 'staging', stage);
|
|
238
238
|
}
|
|
239
239
|
if (section === 'ratelimits' && key === 'namespace_id') {
|
|
240
240
|
const bindingName = requiredString(table, 'name', 'Rate-limit binding');
|
|
241
|
-
return rateLimitNamespaceId(accountId, workerBaseName,
|
|
241
|
+
return rateLimitNamespaceId(accountId, workerBaseName, stage, bindingName);
|
|
242
242
|
}
|
|
243
243
|
return current;
|
|
244
244
|
}
|
|
245
|
-
export function rateLimitNamespaceId(accountId, workerBaseName,
|
|
246
|
-
const token =
|
|
245
|
+
export function rateLimitNamespaceId(accountId, workerBaseName, stage, bindingName) {
|
|
246
|
+
const token = parseDeploymentStage(stage);
|
|
247
247
|
const digest = createHash('sha256').update(`${accountId}:${workerBaseName}:${token}:${bindingName}`).digest();
|
|
248
248
|
const value = digest.readUInt32BE(0) & 2147483647;
|
|
249
249
|
return String(value === 0 ? 1 : value);
|
|
250
250
|
}
|
|
251
|
-
function replaceHostnameLabel(value,
|
|
252
|
-
return value.replace(/(^|[.@/])staging(?=\.)/g, `$1${
|
|
251
|
+
function replaceHostnameLabel(value, stage) {
|
|
252
|
+
return value.replace(/(^|[.@/])staging(?=\.)/g, `$1${stage}`);
|
|
253
253
|
}
|
|
254
254
|
function replaceExactToken(value, from, to) {
|
|
255
255
|
const escaped = from.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@smoothbricks/cli",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.10",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "SmoothBricks monorepo automation CLI",
|
|
6
6
|
"bin": {
|
|
@@ -48,12 +48,12 @@
|
|
|
48
48
|
"import": "./dist/wrangler/prepare-env.js",
|
|
49
49
|
"default": "./dist/wrangler/prepare-env.js"
|
|
50
50
|
},
|
|
51
|
-
"./wrangler/
|
|
52
|
-
"types": "./dist/wrangler/
|
|
53
|
-
"bun": "./src/wrangler/
|
|
54
|
-
"development": "./src/wrangler/
|
|
55
|
-
"import": "./dist/wrangler/
|
|
56
|
-
"default": "./dist/wrangler/
|
|
51
|
+
"./wrangler/stage": {
|
|
52
|
+
"types": "./dist/wrangler/stage.d.ts",
|
|
53
|
+
"bun": "./src/wrangler/stage.ts",
|
|
54
|
+
"development": "./src/wrangler/stage.ts",
|
|
55
|
+
"import": "./dist/wrangler/stage.js",
|
|
56
|
+
"default": "./dist/wrangler/stage.js"
|
|
57
57
|
}
|
|
58
58
|
},
|
|
59
59
|
"sideEffects": [
|
package/src/cli.ts
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
|
|
|
10
10
|
export async function runCli(argv = process.argv.slice(2)): Promise<void> {
|
|
@@ -335,6 +335,7 @@ function buildProgram(): Command {
|
|
|
335
335
|
.option('--step <step>')
|
|
336
336
|
.option('--mode <mode>', 'auto, affected, or run-many', 'auto')
|
|
337
337
|
.option('--configuration <configuration>')
|
|
338
|
+
.option('--stage <stage>')
|
|
338
339
|
.action(
|
|
339
340
|
async (options: {
|
|
340
341
|
target: string;
|
|
@@ -342,6 +343,7 @@ function buildProgram(): Command {
|
|
|
342
343
|
step?: string;
|
|
343
344
|
mode?: 'auto' | 'affected' | 'run-many';
|
|
344
345
|
configuration?: string;
|
|
346
|
+
stage?: string;
|
|
345
347
|
}) => {
|
|
346
348
|
const { githubCiNxSmart } = await import('./github-ci/index.js');
|
|
347
349
|
await githubCiNxSmart(await findRepoRoot(), options);
|
|
@@ -376,14 +378,14 @@ function buildProgram(): Command {
|
|
|
376
378
|
});
|
|
377
379
|
githubCi
|
|
378
380
|
.command('nx-deploy')
|
|
379
|
-
.option('--
|
|
381
|
+
.option('--stage <stage>', 'explicit staging, production, or prN override')
|
|
380
382
|
.option('--mode <mode>', 'auto, affected, or run-many', 'run-many')
|
|
381
383
|
.option('--name <name>')
|
|
382
384
|
.option('--step <step>')
|
|
383
385
|
.option('--verify', 'run build, lint, and test before deploy')
|
|
384
386
|
.action(
|
|
385
387
|
async (options: {
|
|
386
|
-
|
|
388
|
+
stage?: string;
|
|
387
389
|
mode?: 'auto' | 'affected' | 'run-many';
|
|
388
390
|
name?: string;
|
|
389
391
|
step?: string;
|
|
@@ -424,10 +426,10 @@ function buildProgram(): Command {
|
|
|
424
426
|
scaffold(await findRepoRoot(), project, { force: options.force });
|
|
425
427
|
});
|
|
426
428
|
wrangler
|
|
427
|
-
.command('deploy-
|
|
428
|
-
.requiredOption('--
|
|
429
|
-
.action(async (options: {
|
|
430
|
-
await
|
|
429
|
+
.command('deploy-stage')
|
|
430
|
+
.requiredOption('--stage <stage>', 'staging, production, or prN')
|
|
431
|
+
.action(async (options: { stage: string }) => {
|
|
432
|
+
await deployStage(process.cwd(), options.stage);
|
|
431
433
|
});
|
|
432
434
|
wrangler
|
|
433
435
|
.command('cleanup-pr')
|