@treeseed/sdk 0.6.24 → 0.6.26
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.
|
@@ -283,6 +283,22 @@ export declare function listD1Databases(tenantRoot: any, env: any): any;
|
|
|
283
283
|
export declare function listQueues(tenantRoot: any, env: any): any;
|
|
284
284
|
export declare function listR2Buckets(tenantRoot: any, env: any): any;
|
|
285
285
|
export declare function listPagesProjects(tenantRoot: any, env: any): any;
|
|
286
|
+
export declare function buildCloudflarePagesFunctionBindings(state: any): {
|
|
287
|
+
r2_buckets?: {
|
|
288
|
+
[x: number]: {
|
|
289
|
+
name: any;
|
|
290
|
+
};
|
|
291
|
+
} | undefined;
|
|
292
|
+
d1_databases?: {
|
|
293
|
+
[x: number]: {
|
|
294
|
+
id: any;
|
|
295
|
+
};
|
|
296
|
+
} | undefined;
|
|
297
|
+
kv_namespaces?: {
|
|
298
|
+
[k: string]: any;
|
|
299
|
+
} | undefined;
|
|
300
|
+
};
|
|
301
|
+
export declare function mergeCloudflarePagesDeploymentConfig(config?: {}, bindings?: {}): {};
|
|
286
302
|
export declare function buildProvisioningSummary(deployConfig: any, state: any, target: any): {
|
|
287
303
|
target: any;
|
|
288
304
|
identity: any;
|
|
@@ -967,6 +983,9 @@ export declare function verifyProvisionedCloudflareResources(tenantRoot: any, op
|
|
|
967
983
|
queue: boolean;
|
|
968
984
|
dlq: boolean;
|
|
969
985
|
r2: boolean;
|
|
986
|
+
pagesFormGuardKvBinding: any;
|
|
987
|
+
pagesD1Binding: any;
|
|
988
|
+
pagesR2Binding: any;
|
|
970
989
|
webCache: boolean;
|
|
971
990
|
};
|
|
972
991
|
state: any;
|
|
@@ -878,18 +878,53 @@ function listPagesProjects(tenantRoot, env) {
|
|
|
878
878
|
});
|
|
879
879
|
return Array.isArray(payload?.result) ? payload.result : [];
|
|
880
880
|
}
|
|
881
|
-
function
|
|
881
|
+
function buildCloudflarePagesFunctionBindings(state) {
|
|
882
|
+
const kvNamespaces = Object.fromEntries(
|
|
883
|
+
Object.entries(state.kvNamespaces ?? {}).map(([key, namespace]) => {
|
|
884
|
+
const binding = namespace?.binding ?? key;
|
|
885
|
+
const namespaceId = namespace?.id;
|
|
886
|
+
return binding && namespaceId && !isPlaceholderResourceId(namespaceId) ? [binding, { namespace_id: namespaceId }] : null;
|
|
887
|
+
}).filter(Boolean)
|
|
888
|
+
);
|
|
889
|
+
const database = state.d1Databases?.SITE_DATA_DB;
|
|
890
|
+
const d1Databases = database?.binding && database?.databaseId && !isPlaceholderResourceId(database.databaseId) ? { [database.binding]: { id: database.databaseId } } : {};
|
|
891
|
+
const contentBinding = state.content?.r2Binding;
|
|
892
|
+
const contentBucketName = state.content?.bucketName;
|
|
893
|
+
const r2Buckets = contentBinding && contentBucketName ? { [contentBinding]: { name: contentBucketName } } : {};
|
|
894
|
+
return {
|
|
895
|
+
...Object.keys(kvNamespaces).length ? { kv_namespaces: kvNamespaces } : {},
|
|
896
|
+
...Object.keys(d1Databases).length ? { d1_databases: d1Databases } : {},
|
|
897
|
+
...Object.keys(r2Buckets).length ? { r2_buckets: r2Buckets } : {}
|
|
898
|
+
};
|
|
899
|
+
}
|
|
900
|
+
function mergeCloudflarePagesDeploymentConfig(config = {}, bindings = {}) {
|
|
901
|
+
return Object.entries(bindings).reduce((merged, [key, value]) => ({
|
|
902
|
+
...merged,
|
|
903
|
+
[key]: {
|
|
904
|
+
...merged[key] ?? {},
|
|
905
|
+
...value
|
|
906
|
+
}
|
|
907
|
+
}), { ...config });
|
|
908
|
+
}
|
|
909
|
+
function ensurePagesProjectCompatibility(accountId, projectName, env, currentProject = null, options = {}) {
|
|
882
910
|
if (!accountId || !projectName) {
|
|
883
911
|
return;
|
|
884
912
|
}
|
|
885
913
|
const projectPath = `/accounts/${encodeURIComponent(accountId)}/pages/projects/${encodeURIComponent(projectName)}`;
|
|
886
914
|
const latestProject = cloudflareApiRequest(projectPath, { env, allowFailure: true })?.result ?? currentProject;
|
|
887
915
|
const currentConfigs = latestProject?.deployment_configs ?? {};
|
|
916
|
+
const target = options.target;
|
|
917
|
+
const targetConfigKey = target?.kind === "persistent" && target.scope === "prod" ? "production" : "preview";
|
|
918
|
+
const bindings = options.state ? buildCloudflarePagesFunctionBindings(options.state) : {};
|
|
888
919
|
const mergeCompatibility = (config = {}) => ({
|
|
889
920
|
...config,
|
|
890
921
|
compatibility_date: config.compatibility_date ?? DEFAULT_COMPATIBILITY_DATE,
|
|
891
922
|
compatibility_flags: [.../* @__PURE__ */ new Set([...config.compatibility_flags ?? [], ...DEFAULT_COMPATIBILITY_FLAGS])]
|
|
892
923
|
});
|
|
924
|
+
const mergeTarget = (key, config = {}) => {
|
|
925
|
+
const compatible = mergeCompatibility(config);
|
|
926
|
+
return key === targetConfigKey && Object.keys(bindings).length ? mergeCloudflarePagesDeploymentConfig(compatible, bindings) : compatible;
|
|
927
|
+
};
|
|
893
928
|
cloudflareApiRequest(
|
|
894
929
|
projectPath,
|
|
895
930
|
{
|
|
@@ -898,8 +933,8 @@ function ensurePagesProjectCompatibility(accountId, projectName, env, currentPro
|
|
|
898
933
|
body: {
|
|
899
934
|
deployment_configs: {
|
|
900
935
|
...currentConfigs,
|
|
901
|
-
preview:
|
|
902
|
-
production:
|
|
936
|
+
preview: mergeTarget("preview", currentConfigs.preview),
|
|
937
|
+
production: mergeTarget("production", currentConfigs.production)
|
|
903
938
|
}
|
|
904
939
|
}
|
|
905
940
|
}
|
|
@@ -1835,7 +1870,7 @@ function provisionCloudflareResources(tenantRoot, options = {}) {
|
|
|
1835
1870
|
const exists = pagesProjects.find((entry) => entry?.name === current.projectName);
|
|
1836
1871
|
if (exists) {
|
|
1837
1872
|
current.url = exists.subdomain ? `https://${exists.subdomain}` : current.url ?? `https://${current.projectName}.pages.dev`;
|
|
1838
|
-
ensurePagesProjectCompatibility(env.CLOUDFLARE_ACCOUNT_ID ?? process.env.CLOUDFLARE_ACCOUNT_ID ?? "", current.projectName, env, exists);
|
|
1873
|
+
ensurePagesProjectCompatibility(env.CLOUDFLARE_ACCOUNT_ID ?? process.env.CLOUDFLARE_ACCOUNT_ID ?? "", current.projectName, env, exists, { state, target });
|
|
1839
1874
|
return;
|
|
1840
1875
|
}
|
|
1841
1876
|
if (dryRun) {
|
|
@@ -1854,7 +1889,7 @@ function provisionCloudflareResources(tenantRoot, options = {}) {
|
|
|
1854
1889
|
capture: true,
|
|
1855
1890
|
env
|
|
1856
1891
|
});
|
|
1857
|
-
ensurePagesProjectCompatibility(env.CLOUDFLARE_ACCOUNT_ID ?? process.env.CLOUDFLARE_ACCOUNT_ID ?? "", current.projectName, env);
|
|
1892
|
+
ensurePagesProjectCompatibility(env.CLOUDFLARE_ACCOUNT_ID ?? process.env.CLOUDFLARE_ACCOUNT_ID ?? "", current.projectName, env, null, { state, target });
|
|
1858
1893
|
current.url = `https://${current.projectName}.pages.dev`;
|
|
1859
1894
|
};
|
|
1860
1895
|
ensureKv("FORM_GUARD_KV");
|
|
@@ -1931,13 +1966,25 @@ function verifyProvisionedCloudflareResources(tenantRoot, options = {}) {
|
|
|
1931
1966
|
const queues = dryRun ? [] : listQueues(tenantRoot, env);
|
|
1932
1967
|
const buckets = dryRun ? [] : listR2Buckets(tenantRoot, env);
|
|
1933
1968
|
const pagesProjects = dryRun ? [] : listPagesProjects(tenantRoot, env);
|
|
1969
|
+
const livePages = pagesProjects.find((entry) => entry?.name === state.pages?.projectName);
|
|
1970
|
+
const pagesProject = dryRun || !env.CLOUDFLARE_ACCOUNT_ID || !state.pages?.projectName ? livePages : cloudflareApiRequest(
|
|
1971
|
+
`/accounts/${encodeURIComponent(env.CLOUDFLARE_ACCOUNT_ID)}/pages/projects/${encodeURIComponent(state.pages.projectName)}`,
|
|
1972
|
+
{ env, allowFailure: true }
|
|
1973
|
+
)?.result ?? livePages;
|
|
1974
|
+
const pagesConfigKey = target.kind === "persistent" && target.scope === "prod" ? "production" : "preview";
|
|
1975
|
+
const pagesConfig = pagesProject?.deployment_configs?.[pagesConfigKey] ?? {};
|
|
1976
|
+
const pagesBindings = buildCloudflarePagesFunctionBindings(state);
|
|
1977
|
+
const pageBindingConfigured = (configKey, binding, expected) => pagesConfig?.[configKey]?.[binding] && Object.entries(expected).every(([key, value]) => pagesConfig[configKey][binding]?.[key] === value);
|
|
1934
1978
|
const checks = {
|
|
1935
|
-
pages: Boolean(state.pages?.projectName &&
|
|
1979
|
+
pages: Boolean(state.pages?.projectName && (livePages || pagesProject?.name === state.pages.projectName)),
|
|
1936
1980
|
formGuardKv: Boolean(state.kvNamespaces?.FORM_GUARD_KV?.name && kvNamespaces.find((entry) => entry?.title === state.kvNamespaces.FORM_GUARD_KV.name)),
|
|
1937
1981
|
d1: Boolean(state.d1Databases?.SITE_DATA_DB?.databaseName && d1Databases.find((entry) => entry?.name === state.d1Databases.SITE_DATA_DB.databaseName)),
|
|
1938
1982
|
queue: Boolean(state.queues?.agentWork?.name && queues.find((entry) => queueName(entry) === state.queues.agentWork.name)),
|
|
1939
1983
|
dlq: !state.queues?.agentWork?.dlqName || Boolean(queues.find((entry) => queueName(entry) === state.queues.agentWork.dlqName)),
|
|
1940
1984
|
r2: Boolean(state.content?.bucketName && buckets.find((entry) => entry?.name === state.content.bucketName)),
|
|
1985
|
+
pagesFormGuardKvBinding: !pagesBindings.kv_namespaces?.FORM_GUARD_KV || pageBindingConfigured("kv_namespaces", "FORM_GUARD_KV", pagesBindings.kv_namespaces.FORM_GUARD_KV),
|
|
1986
|
+
pagesD1Binding: !pagesBindings.d1_databases?.SITE_DATA_DB || pageBindingConfigured("d1_databases", "SITE_DATA_DB", pagesBindings.d1_databases.SITE_DATA_DB),
|
|
1987
|
+
pagesR2Binding: !state.content?.r2Binding || !pagesBindings.r2_buckets?.[state.content.r2Binding] || pageBindingConfigured("r2_buckets", state.content.r2Binding, pagesBindings.r2_buckets[state.content.r2Binding]),
|
|
1941
1988
|
webCache: !shouldManageCloudflareWebCacheRules(deployConfig, target) || state.webCache?.rulesManaged === true
|
|
1942
1989
|
};
|
|
1943
1990
|
const ok = dryRun ? true : Object.values(checks).every(Boolean);
|
|
@@ -1955,7 +2002,6 @@ function verifyProvisionedCloudflareResources(tenantRoot, options = {}) {
|
|
|
1955
2002
|
const liveDlq = queues.find((entry) => queueName(entry) === state.queues.agentWork.dlqName);
|
|
1956
2003
|
state.queues.agentWork.dlqId = queueId(liveDlq) ?? state.queues.agentWork.dlqId ?? null;
|
|
1957
2004
|
}
|
|
1958
|
-
const livePages = pagesProjects.find((entry) => entry?.name === state.pages?.projectName);
|
|
1959
2005
|
if (state.pages) {
|
|
1960
2006
|
const configuredWebUrl = resolveConfiguredSurfaceBaseUrl(deployConfig, target, "web");
|
|
1961
2007
|
if (configuredWebUrl) {
|
|
@@ -2136,6 +2182,7 @@ function printDestroySummary(result) {
|
|
|
2136
2182
|
}
|
|
2137
2183
|
export {
|
|
2138
2184
|
assertDeploymentInitialized,
|
|
2185
|
+
buildCloudflarePagesFunctionBindings,
|
|
2139
2186
|
buildProvisioningSummary,
|
|
2140
2187
|
buildPublicVars,
|
|
2141
2188
|
buildSecretMap,
|
|
@@ -2160,6 +2207,7 @@ export {
|
|
|
2160
2207
|
loadDeployState,
|
|
2161
2208
|
markDeploymentInitialized,
|
|
2162
2209
|
markManagedServicesInitialized,
|
|
2210
|
+
mergeCloudflarePagesDeploymentConfig,
|
|
2163
2211
|
normalizePersistentScope,
|
|
2164
2212
|
printDeploySummary,
|
|
2165
2213
|
printDestroySummary,
|
|
@@ -9,7 +9,7 @@ import { collectInternalDevReferenceIssues } from "./package-reference-policy.js
|
|
|
9
9
|
import { collectTreeseedEnvironmentContext, resolveTreeseedMachineEnvironmentValues, validateTreeseedCommandEnvironment } from "./config-runtime.js";
|
|
10
10
|
import { loadDeployState } from "./deploy.js";
|
|
11
11
|
import { loadCliDeployConfig } from "./runtime-tools.js";
|
|
12
|
-
import { run, workspacePackages } from "./workspace-tools.js";
|
|
12
|
+
import { packagesWithScript, run, workspacePackages } from "./workspace-tools.js";
|
|
13
13
|
const RELEASE_CANDIDATE_CACHE_DIR = ".treeseed/workflow/release-candidates";
|
|
14
14
|
const STABLE_SEMVER = /^\d+\.\d+\.\d+$/u;
|
|
15
15
|
const REHEARSAL_IGNORED_SEGMENTS = /* @__PURE__ */ new Set([
|
|
@@ -224,6 +224,11 @@ function rehearsalVerifyScript(root) {
|
|
|
224
224
|
}
|
|
225
225
|
return null;
|
|
226
226
|
}
|
|
227
|
+
function buildRehearsalWorkspacePackageArtifacts(root) {
|
|
228
|
+
for (const pkg of packagesWithScript("build:dist", root)) {
|
|
229
|
+
run("npm", ["--prefix", pkg.dir, "run", "build:dist"], { cwd: root, timeoutMs: 3e5 });
|
|
230
|
+
}
|
|
231
|
+
}
|
|
227
232
|
function runProductionDependencyRehearsal(root, plannedVersions, selectedPackageNames, failures) {
|
|
228
233
|
if (getGitHubAutomationMode() === "stub" || process.env.TREESEED_RELEASE_CANDIDATE_REHEARSAL_MODE === "skip") {
|
|
229
234
|
return "Skipped clean install rehearsal in stub/skip mode.";
|
|
@@ -235,7 +240,8 @@ function runProductionDependencyRehearsal(root, plannedVersions, selectedPackage
|
|
|
235
240
|
tempParent = copied.tempParent;
|
|
236
241
|
applyPlannedStableMetadata(copied.tempRoot, plannedVersions);
|
|
237
242
|
run("npm", ["install", "--package-lock-only", "--ignore-scripts"], { cwd: copied.tempRoot, timeoutMs: 3e5 });
|
|
238
|
-
run("npm", ["ci"], { cwd: copied.tempRoot, timeoutMs: 6e5 });
|
|
243
|
+
run("npm", ["ci", "--ignore-scripts"], { cwd: copied.tempRoot, timeoutMs: 6e5 });
|
|
244
|
+
buildRehearsalWorkspacePackageArtifacts(copied.tempRoot);
|
|
239
245
|
const scriptName = rehearsalVerifyScript(copied.tempRoot);
|
|
240
246
|
if (scriptName) {
|
|
241
247
|
run("npm", ["run", scriptName], { cwd: copied.tempRoot, timeoutMs: 9e5 });
|
|
@@ -3,6 +3,7 @@ import { relative, resolve } from "node:path";
|
|
|
3
3
|
import { collectTreeseedEnvironmentContext, resolveTreeseedMachineEnvironmentValues } from "../operations/services/config-runtime.js";
|
|
4
4
|
import {
|
|
5
5
|
buildPublicVars,
|
|
6
|
+
buildCloudflarePagesFunctionBindings,
|
|
6
7
|
buildProvisioningSummary,
|
|
7
8
|
buildSecretMap,
|
|
8
9
|
cloudflareApiRequest,
|
|
@@ -16,6 +17,7 @@ import {
|
|
|
16
17
|
listPagesProjects,
|
|
17
18
|
listQueues,
|
|
18
19
|
listR2Buckets,
|
|
20
|
+
mergeCloudflarePagesDeploymentConfig,
|
|
19
21
|
loadDeployState,
|
|
20
22
|
queueId,
|
|
21
23
|
queueName,
|
|
@@ -595,7 +597,7 @@ function syncPagesEnvironmentVariablesForTarget(input, { dryRun = false } = {})
|
|
|
595
597
|
const mergedDeploymentConfigs = {
|
|
596
598
|
...deploymentConfigs,
|
|
597
599
|
[branchConfigKey]: {
|
|
598
|
-
...currentBranchConfig,
|
|
600
|
+
...mergeCloudflarePagesDeploymentConfig(currentBranchConfig, buildCloudflarePagesFunctionBindings(state)),
|
|
599
601
|
env_vars: {
|
|
600
602
|
...currentBranchConfig?.env_vars ?? {},
|
|
601
603
|
...envVars
|
|
@@ -1070,6 +1072,11 @@ function verifyCloudflareUnitOnce(input, postconditions) {
|
|
|
1070
1072
|
const branchKey = input.context.target.kind === "persistent" && input.context.target.scope === "prod" ? "production" : "preview";
|
|
1071
1073
|
const branchConfig = project?.deployment_configs?.[branchKey] ?? {};
|
|
1072
1074
|
const envVars = branchConfig?.env_vars && typeof branchConfig.env_vars === "object" ? branchConfig.env_vars : {};
|
|
1075
|
+
const pageBindings = buildCloudflarePagesFunctionBindings(state);
|
|
1076
|
+
const pageBindingConfigured = (configKey, binding, expected) => {
|
|
1077
|
+
const observed = branchConfig?.[configKey]?.[binding];
|
|
1078
|
+
return Boolean(observed && Object.entries(expected).every(([key, value]) => observed?.[key] === value));
|
|
1079
|
+
};
|
|
1073
1080
|
const sync = collectCloudflareEnvironmentSync(input);
|
|
1074
1081
|
const expectedVars = Object.entries(sync.vars).filter(([, value]) => typeof value === "string" && value.length > 0);
|
|
1075
1082
|
const checks = [
|
|
@@ -1106,6 +1113,33 @@ function verifyCloudflareUnitOnce(input, postconditions) {
|
|
|
1106
1113
|
issues: envVars[name] ? [] : [`Pages secret ${name} is missing from the ${branchKey} deployment config.`]
|
|
1107
1114
|
}));
|
|
1108
1115
|
}
|
|
1116
|
+
for (const [binding, expected] of Object.entries(pageBindings.kv_namespaces ?? {})) {
|
|
1117
|
+
checks.push(verificationCheck(`pages.kv:${binding}`, `Pages KV binding ${binding} points at the expected namespace`, "api", {
|
|
1118
|
+
exists: Boolean(branchConfig?.kv_namespaces?.[binding]),
|
|
1119
|
+
configured: pageBindingConfigured("kv_namespaces", binding, expected),
|
|
1120
|
+
expected,
|
|
1121
|
+
observed: branchConfig?.kv_namespaces?.[binding] ?? null,
|
|
1122
|
+
issues: pageBindingConfigured("kv_namespaces", binding, expected) ? [] : [`Pages KV binding ${binding} is missing or points at the wrong namespace for ${branchKey}.`]
|
|
1123
|
+
}));
|
|
1124
|
+
}
|
|
1125
|
+
for (const [binding, expected] of Object.entries(pageBindings.d1_databases ?? {})) {
|
|
1126
|
+
checks.push(verificationCheck(`pages.d1:${binding}`, `Pages D1 binding ${binding} points at the expected database`, "api", {
|
|
1127
|
+
exists: Boolean(branchConfig?.d1_databases?.[binding]),
|
|
1128
|
+
configured: pageBindingConfigured("d1_databases", binding, expected),
|
|
1129
|
+
expected,
|
|
1130
|
+
observed: branchConfig?.d1_databases?.[binding] ?? null,
|
|
1131
|
+
issues: pageBindingConfigured("d1_databases", binding, expected) ? [] : [`Pages D1 binding ${binding} is missing or points at the wrong database for ${branchKey}.`]
|
|
1132
|
+
}));
|
|
1133
|
+
}
|
|
1134
|
+
for (const [binding, expected] of Object.entries(pageBindings.r2_buckets ?? {})) {
|
|
1135
|
+
checks.push(verificationCheck(`pages.r2:${binding}`, `Pages R2 binding ${binding} points at the expected bucket`, "api", {
|
|
1136
|
+
exists: Boolean(branchConfig?.r2_buckets?.[binding]),
|
|
1137
|
+
configured: pageBindingConfigured("r2_buckets", binding, expected),
|
|
1138
|
+
expected,
|
|
1139
|
+
observed: branchConfig?.r2_buckets?.[binding] ?? null,
|
|
1140
|
+
issues: pageBindingConfigured("r2_buckets", binding, expected) ? [] : [`Pages R2 binding ${binding} is missing or points at the wrong bucket for ${branchKey}.`]
|
|
1141
|
+
}));
|
|
1142
|
+
}
|
|
1109
1143
|
return summarizeVerification(input.unit.unitId, checks);
|
|
1110
1144
|
}
|
|
1111
1145
|
default:
|