@treeseed/sdk 0.6.0 → 0.6.2

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.
Files changed (32) hide show
  1. package/dist/operations/services/bootstrap-runner.d.ts +33 -0
  2. package/dist/operations/services/bootstrap-runner.js +136 -0
  3. package/dist/operations/services/config-runtime.d.ts +27 -8
  4. package/dist/operations/services/config-runtime.js +297 -124
  5. package/dist/operations/services/github-api.d.ts +33 -0
  6. package/dist/operations/services/github-api.js +118 -4
  7. package/dist/operations/services/github-automation.d.ts +30 -0
  8. package/dist/operations/services/github-automation.js +107 -1
  9. package/dist/operations/services/project-platform.d.ts +38 -2
  10. package/dist/operations/services/project-platform.js +281 -9
  11. package/dist/operations/services/railway-deploy.d.ts +6 -2
  12. package/dist/operations/services/railway-deploy.js +26 -18
  13. package/dist/operations/services/runtime-tools.d.ts +0 -2
  14. package/dist/operations/services/runtime-tools.js +0 -2
  15. package/dist/platform/env.yaml +68 -96
  16. package/dist/platform/environment.js +51 -0
  17. package/dist/reconcile/bootstrap-systems.d.ts +32 -0
  18. package/dist/reconcile/bootstrap-systems.js +175 -0
  19. package/dist/reconcile/builtin-adapters.js +24 -9
  20. package/dist/reconcile/desired-state.js +16 -14
  21. package/dist/reconcile/engine.d.ts +9 -4
  22. package/dist/reconcile/engine.js +57 -14
  23. package/dist/reconcile/index.d.ts +1 -0
  24. package/dist/reconcile/index.js +1 -0
  25. package/dist/scripts/config-treeseed.js +30 -0
  26. package/dist/scripts/package-tools.js +0 -2
  27. package/dist/scripts/tenant-deploy.js +16 -36
  28. package/dist/scripts/test-cloudflare-local.js +0 -2
  29. package/dist/workflow/operations.js +23 -4
  30. package/dist/workflow.d.ts +5 -0
  31. package/package.json +1 -1
  32. package/templates/github/deploy.workflow.yml +15 -15
@@ -16,12 +16,14 @@ import { collectTreeseedReconcileStatus, reconcileTreeseedTarget } from "../../r
16
16
  import { loadTreeseedManifest } from "../../platform/tenant-config.js";
17
17
  import { applyTreeseedEnvironmentToProcess } from "./config-runtime.js";
18
18
  import {
19
+ assertDeploymentInitialized,
19
20
  createPersistentDeployTarget,
20
21
  deployTargetLabel,
21
22
  ensureGeneratedWranglerConfig,
22
23
  finalizeDeploymentState,
23
24
  loadDeployState,
24
25
  purgePublishedContentCaches,
26
+ resolveConfiguredCloudflareAccountId,
25
27
  resolveConfiguredSurfaceBaseUrl,
26
28
  writeDeployState
27
29
  } from "./deploy.js";
@@ -36,6 +38,8 @@ import {
36
38
  } from "./railway-deploy.js";
37
39
  import { loadCliDeployConfig, packageScriptPath, resolveWranglerBin } from "./runtime-tools.js";
38
40
  import { CloudflareQueuePullClient, CloudflareQueuePushClient } from "../../remote.js";
41
+ import { runPrefixedCommand, runTreeseedBootstrapDag, sleep, writeTreeseedBootstrapLine } from "./bootstrap-runner.js";
42
+ import { runTenantDeployPreflight } from "./save-deploy-preflight.js";
39
43
  function stableHash(value) {
40
44
  return createHash("sha256").update(value).digest("hex");
41
45
  }
@@ -98,6 +102,165 @@ function runWrangler(tenantRoot, args, extraEnv = {}, options = {}) {
98
102
  }
99
103
  return result;
100
104
  }
105
+ function isTransientWranglerOutput(output) {
106
+ return /fetch failed|timed out|etimedout|econnreset|enetunreach|temporarily unavailable|connectivity issue|internal error|aborted/i.test(output);
107
+ }
108
+ async function runPrefixedWranglerWithRetry(tenantRoot, args, {
109
+ env = {},
110
+ write,
111
+ prefix
112
+ }) {
113
+ let lastOutput = "";
114
+ for (let attempt = 1; attempt <= 3; attempt += 1) {
115
+ const result = await runPrefixedCommand(process.execPath, [resolveWranglerBin(), ...args], {
116
+ cwd: tenantRoot,
117
+ env,
118
+ write,
119
+ prefix
120
+ });
121
+ if (result.status === 0) {
122
+ return result;
123
+ }
124
+ lastOutput = [result.stderr?.trim(), result.stdout?.trim()].filter(Boolean).join("\n");
125
+ if (attempt === 3 || !isTransientWranglerOutput(lastOutput)) {
126
+ throw new Error(lastOutput || `wrangler ${args.join(" ")} failed`);
127
+ }
128
+ writeTreeseedBootstrapLine(
129
+ write,
130
+ { ...prefix, stage: "retry" },
131
+ `Wrangler command hit a transient failure; retrying in ${2 * attempt}s...`,
132
+ "stderr"
133
+ );
134
+ await sleep(2e3 * attempt);
135
+ }
136
+ throw new Error(lastOutput || `wrangler ${args.join(" ")} failed`);
137
+ }
138
+ function prepareTenantCloudflareDeploy({
139
+ tenantRoot,
140
+ scope,
141
+ target: explicitTarget,
142
+ dryRun,
143
+ write,
144
+ env = process.env
145
+ }) {
146
+ const target = explicitTarget ?? createPersistentDeployTarget(scope === "local" ? "staging" : scope);
147
+ if (scope !== "local") {
148
+ assertDeploymentInitialized(tenantRoot, { target });
149
+ runTenantDeployPreflight({ cwd: tenantRoot, scope });
150
+ }
151
+ const { wranglerPath, deployConfig, state } = ensureGeneratedWranglerConfig(tenantRoot, { target });
152
+ const deployState = loadDeployState(tenantRoot, deployConfig, { target });
153
+ const pagesProjectName = target.kind === "persistent" ? deployState.pages?.projectName ?? null : null;
154
+ const pagesBranchName = target.kind === "persistent" ? target.scope === "prod" ? deployState.pages?.productionBranch ?? "main" : deployState.pages?.stagingBranch ?? "staging" : null;
155
+ return {
156
+ tenantRoot,
157
+ scope,
158
+ target,
159
+ dryRun,
160
+ wranglerPath,
161
+ databaseName: state.d1Databases.SITE_DATA_DB.databaseName,
162
+ pagesProjectName,
163
+ pagesBranchName,
164
+ env: {
165
+ ...process.env,
166
+ ...env,
167
+ CLOUDFLARE_ACCOUNT_ID: resolveConfiguredCloudflareAccountId(deployConfig)
168
+ },
169
+ write
170
+ };
171
+ }
172
+ async function runTenantDataMigration(context) {
173
+ if (context.dryRun) {
174
+ writeTreeseedBootstrapLine(context.write, {
175
+ scope: context.scope,
176
+ system: "data",
177
+ task: "d1-migrate",
178
+ stage: "deploy"
179
+ }, `Dry run: would apply remote migrations for ${context.databaseName}.`);
180
+ return { databaseName: context.databaseName, dryRun: true };
181
+ }
182
+ await runPrefixedWranglerWithRetry(context.tenantRoot, [
183
+ "d1",
184
+ "migrations",
185
+ "apply",
186
+ context.databaseName,
187
+ "--remote",
188
+ "--config",
189
+ context.wranglerPath
190
+ ], {
191
+ env: context.env,
192
+ write: context.write,
193
+ prefix: {
194
+ scope: context.scope,
195
+ system: "data",
196
+ task: "d1-migrate",
197
+ stage: "deploy"
198
+ }
199
+ });
200
+ return { databaseName: context.databaseName, dryRun: false };
201
+ }
202
+ async function runTenantWebBuild(context) {
203
+ const prefix = {
204
+ scope: context.scope,
205
+ system: "web",
206
+ task: "build",
207
+ stage: "deploy"
208
+ };
209
+ if (context.dryRun) {
210
+ writeTreeseedBootstrapLine(context.write, prefix, "Dry run: skipped tenant build.");
211
+ return { dryRun: true };
212
+ }
213
+ const result = await runPrefixedCommand(process.execPath, [packageScriptPath("tenant-build")], {
214
+ cwd: context.tenantRoot,
215
+ env: context.env,
216
+ write: context.write,
217
+ prefix
218
+ });
219
+ if (result.status !== 0) {
220
+ throw new Error("tenant-build failed.");
221
+ }
222
+ return { dryRun: false };
223
+ }
224
+ async function runTenantWebPublish(context) {
225
+ const prefix = {
226
+ scope: context.scope,
227
+ system: "web",
228
+ task: "publish",
229
+ stage: "deploy"
230
+ };
231
+ if (context.dryRun) {
232
+ if (context.pagesProjectName) {
233
+ writeTreeseedBootstrapLine(context.write, prefix, `Dry run: would deploy ${deployTargetLabel(context.target)} to Pages project ${context.pagesProjectName} from ${resolve(context.tenantRoot, "dist")}.`);
234
+ } else {
235
+ writeTreeseedBootstrapLine(context.write, prefix, `Dry run: would deploy ${deployTargetLabel(context.target)} with generated Wrangler config at ${resolve(context.wranglerPath)}.`);
236
+ }
237
+ return { dryRun: true };
238
+ }
239
+ if (context.pagesProjectName) {
240
+ const args = [
241
+ "pages",
242
+ "deploy",
243
+ resolve(context.tenantRoot, "dist"),
244
+ "--project-name",
245
+ context.pagesProjectName
246
+ ];
247
+ if (context.pagesBranchName) {
248
+ args.push("--branch", context.pagesBranchName);
249
+ }
250
+ await runPrefixedWranglerWithRetry(context.tenantRoot, args, {
251
+ env: context.env,
252
+ write: context.write,
253
+ prefix
254
+ });
255
+ } else {
256
+ await runPrefixedWranglerWithRetry(context.tenantRoot, ["deploy", "--config", context.wranglerPath], {
257
+ env: context.env,
258
+ write: context.write,
259
+ prefix
260
+ });
261
+ }
262
+ return { dryRun: false };
263
+ }
101
264
  function inferContentType(filePath) {
102
265
  const extension = extname(filePath).toLowerCase();
103
266
  if (extension === ".json") return "application/json";
@@ -806,6 +969,10 @@ async function deployProjectPlatform(options) {
806
969
  const reporter = resolveReporter(options.tenantRoot, options.reporter);
807
970
  const commitSha = currentCommit(options.tenantRoot);
808
971
  const branchName = currentRef(options.tenantRoot);
972
+ const selectedSystems = new Set(options.bootstrapSystems ?? ["data", "web", "api", "agents"]);
973
+ const execution = options.bootstrapExecution ?? "parallel";
974
+ const write = options.write;
975
+ const env = { ...process.env, ...options.env ?? {} };
809
976
  await reportDeployment(reporter, {
810
977
  environment: options.scope,
811
978
  deploymentKind: "code",
@@ -818,19 +985,120 @@ async function deployProjectPlatform(options) {
818
985
  if (!options.skipProvision) {
819
986
  await provisionProjectPlatform({ ...options, reporter });
820
987
  }
821
- runNodeScript(options.tenantRoot, "tenant-deploy", ["--environment", options.scope, ...options.dryRun ? ["--dry-run"] : []]);
822
- const serviceResults = [];
823
- if (options.scope !== "local") {
824
- const validation = validateRailwayDeployPrerequisites(options.tenantRoot, options.scope);
825
- for (const service of validation.services) {
826
- serviceResults.push(await deployRailwayService(options.tenantRoot, service, { dryRun: options.dryRun }));
988
+ const nodes = [];
989
+ let cloudflareContext = null;
990
+ if (options.scope === "local" && selectedSystems.has("web")) {
991
+ nodes.push({
992
+ id: "web:build",
993
+ run: () => runTenantWebBuild({
994
+ tenantRoot: options.tenantRoot,
995
+ scope: "local",
996
+ dryRun: options.dryRun,
997
+ env,
998
+ write
999
+ })
1000
+ });
1001
+ } else if (selectedSystems.has("data") || selectedSystems.has("web")) {
1002
+ cloudflareContext = prepareTenantCloudflareDeploy({
1003
+ tenantRoot: options.tenantRoot,
1004
+ scope: options.scope,
1005
+ dryRun: options.dryRun,
1006
+ write,
1007
+ env
1008
+ });
1009
+ }
1010
+ if (cloudflareContext && selectedSystems.has("data")) {
1011
+ const context = cloudflareContext;
1012
+ nodes.push({
1013
+ id: "data:d1-migrate",
1014
+ run: () => runTenantDataMigration(context)
1015
+ });
1016
+ }
1017
+ if (cloudflareContext && selectedSystems.has("web")) {
1018
+ const context = cloudflareContext;
1019
+ nodes.push({
1020
+ id: "web:build",
1021
+ run: () => runTenantWebBuild(context)
1022
+ });
1023
+ nodes.push({
1024
+ id: "web:publish",
1025
+ dependencies: ["web:build", ...selectedSystems.has("data") ? ["data:d1-migrate"] : []],
1026
+ run: () => runTenantWebPublish(context)
1027
+ });
1028
+ }
1029
+ const serviceResultsByKey = /* @__PURE__ */ new Map();
1030
+ let selectedRailwayServiceKeys = [];
1031
+ if (options.scope !== "local" && (selectedSystems.has("api") || selectedSystems.has("agents"))) {
1032
+ const validation = validateRailwayDeployPrerequisites(options.tenantRoot, options.scope, { env });
1033
+ const selectedServices = validation.services.filter(
1034
+ (service) => service.key === "api" ? selectedSystems.has("api") : selectedSystems.has("agents")
1035
+ );
1036
+ for (const service of selectedServices) {
1037
+ const system = service.key === "api" ? "api" : "agents";
1038
+ const nodeId = `${system}:${service.key}-railway-deploy`;
1039
+ selectedRailwayServiceKeys.push(service.key);
1040
+ nodes.push({
1041
+ id: nodeId,
1042
+ dependencies: selectedSystems.has("data") ? ["data:d1-migrate"] : [],
1043
+ run: async () => {
1044
+ const result = await deployRailwayService(options.tenantRoot, service, {
1045
+ dryRun: options.dryRun,
1046
+ write,
1047
+ env,
1048
+ prefix: {
1049
+ scope: options.scope,
1050
+ system,
1051
+ task: `${service.key}-railway-deploy`,
1052
+ stage: "deploy"
1053
+ }
1054
+ });
1055
+ serviceResultsByKey.set(service.key, result);
1056
+ return result;
1057
+ }
1058
+ });
827
1059
  }
828
- const railwaySchedules = options.scope === "prod" ? await ensureRailwayScheduledJobs(options.tenantRoot, options.scope, { dryRun: options.dryRun }) : [];
829
- const railwayScheduleVerification = options.scope === "prod" && !options.dryRun ? await verifyRailwayScheduledJobs(options.tenantRoot, options.scope) : { ok: true, checks: railwaySchedules, skipped: options.scope !== "prod" ? true : options.dryRun, reason: options.scope !== "prod" ? "prod_only" : "dry_run" };
1060
+ }
1061
+ let railwaySchedules = [];
1062
+ let railwayScheduleVerification = { ok: true, checks: [], skipped: true, reason: !selectedSystems.has("agents") ? "agents_not_selected" : options.scope !== "prod" ? "prod_only" : "dry_run" };
1063
+ if (options.scope === "prod" && selectedSystems.has("agents")) {
1064
+ const agentDeployNodeIds = nodes.filter((node) => node.id.startsWith("agents:") && node.id.endsWith("-railway-deploy")).map((node) => node.id);
1065
+ nodes.push({
1066
+ id: "agents:schedules",
1067
+ dependencies: agentDeployNodeIds,
1068
+ run: async () => {
1069
+ writeTreeseedBootstrapLine(write, {
1070
+ scope: options.scope,
1071
+ system: "agents",
1072
+ task: "schedules",
1073
+ stage: "deploy"
1074
+ }, "Reconciling Railway schedules...");
1075
+ railwaySchedules = await ensureRailwayScheduledJobs(options.tenantRoot, options.scope, { dryRun: options.dryRun, env });
1076
+ railwayScheduleVerification = !options.dryRun ? await verifyRailwayScheduledJobs(options.tenantRoot, options.scope) : { ok: true, checks: railwaySchedules, skipped: true, reason: "dry_run" };
1077
+ return {
1078
+ service: "railway-schedules",
1079
+ status: railwayScheduleVerification.ok ? "verified" : "failed",
1080
+ command: "railway schedules reconcile",
1081
+ cwd: options.tenantRoot,
1082
+ publicBaseUrl: null,
1083
+ schedules: railwaySchedules,
1084
+ scheduleVerification: railwayScheduleVerification
1085
+ };
1086
+ }
1087
+ });
1088
+ }
1089
+ await runTreeseedBootstrapDag({ nodes, execution });
1090
+ const serviceResults = selectedRailwayServiceKeys.map((serviceKey) => serviceResultsByKey.get(serviceKey)).filter(Boolean);
1091
+ if (options.scope !== "local" && !options.dryRun && (selectedSystems.has("web") || serviceResults.length > 0)) {
830
1092
  finalizeDeploymentState(options.tenantRoot, {
831
1093
  target: createPersistentDeployTarget(options.scope),
832
1094
  serviceResults
833
1095
  });
1096
+ }
1097
+ if (options.scope !== "prod" || !selectedSystems.has("agents")) {
1098
+ railwaySchedules = [];
1099
+ railwayScheduleVerification = { ok: true, checks: railwaySchedules, skipped: true, reason: !selectedSystems.has("agents") ? "agents_not_selected" : options.scope !== "prod" ? "prod_only" : "dry_run" };
1100
+ }
1101
+ if (selectedSystems.has("agents")) {
834
1102
  serviceResults.push({
835
1103
  service: "railway-schedules",
836
1104
  status: railwayScheduleVerification.ok ? "verified" : "failed",
@@ -851,7 +1119,7 @@ async function deployProjectPlatform(options) {
851
1119
  triggeredByType: "project_runner",
852
1120
  metadata: {
853
1121
  scope: options.scope,
854
- railway: options.scope === "local" ? [] : configuredRailwayServices(options.tenantRoot, options.scope).map((service) => service.key),
1122
+ railway: options.scope === "local" ? [] : configuredRailwayServices(options.tenantRoot, options.scope).map((service) => service.key).filter((serviceKey) => serviceKey === "api" ? selectedSystems.has("api") : selectedSystems.has("agents")),
855
1123
  monitor
856
1124
  },
857
1125
  finishedAt: (/* @__PURE__ */ new Date()).toISOString()
@@ -980,9 +1248,13 @@ export {
980
1248
  deployProjectPlatform,
981
1249
  inferEnvironmentFromBranch,
982
1250
  monitorProjectPlatform,
1251
+ prepareTenantCloudflareDeploy,
983
1252
  provisionProjectPlatform,
984
1253
  publishProjectContent,
985
1254
  resolveScope,
986
1255
  runProjectPlatformAction,
1256
+ runTenantDataMigration,
1257
+ runTenantWebBuild,
1258
+ runTenantWebPublish,
987
1259
  syncControlPlaneState
988
1260
  };
@@ -1,3 +1,4 @@
1
+ import { type TreeseedBootstrapTaskPrefix, type TreeseedBootstrapWriter } from './bootstrap-runner.ts';
1
2
  export declare function isUsableRailwayToken(value: any): boolean;
2
3
  export declare function resolveRailwayAuthToken(env?: NodeJS.ProcessEnv): string;
3
4
  export declare function buildRailwayCommandEnv(env?: NodeJS.ProcessEnv): {
@@ -269,8 +270,11 @@ export declare function planRailwayServiceDeploy(service: any): {
269
270
  args: any[];
270
271
  cwd: any;
271
272
  };
272
- export declare function deployRailwayService(tenantRoot: any, service: any, { dryRun }?: {
273
- dryRun?: boolean | undefined;
273
+ export declare function deployRailwayService(tenantRoot: any, service: any, { dryRun, write, prefix, env, }?: {
274
+ dryRun?: boolean;
275
+ write?: TreeseedBootstrapWriter;
276
+ prefix?: TreeseedBootstrapTaskPrefix;
277
+ env?: NodeJS.ProcessEnv | Record<string, string | undefined>;
274
278
  }): Promise<{
275
279
  service: any;
276
280
  status: string;
@@ -3,6 +3,7 @@ import { relative, resolve } from "node:path";
3
3
  import { spawnSync } from "node:child_process";
4
4
  import { loadCliDeployConfig } from "./runtime-tools.js";
5
5
  import { createPersistentDeployTarget, resolveTreeseedResourceIdentity } from "./deploy.js";
6
+ import { runPrefixedCommand, sleep } from "./bootstrap-runner.js";
6
7
  import {
7
8
  ensureRailwayEnvironment,
8
9
  ensureRailwayProject,
@@ -900,7 +901,12 @@ async function syncRailwayServiceRuntimeConfigurationAfterDeploy(tenantRoot, ser
900
901
  env
901
902
  });
902
903
  }
903
- async function deployRailwayService(tenantRoot, service, { dryRun = false } = {}) {
904
+ async function deployRailwayService(tenantRoot, service, {
905
+ dryRun = false,
906
+ write,
907
+ prefix,
908
+ env = process.env
909
+ } = {}) {
904
910
  const plan = planRailwayServiceDeploy(service);
905
911
  if (dryRun) {
906
912
  return {
@@ -911,11 +917,19 @@ async function deployRailwayService(tenantRoot, service, { dryRun = false } = {}
911
917
  publicBaseUrl: service.publicBaseUrl
912
918
  };
913
919
  }
920
+ const taskPrefix = prefix ?? {
921
+ scope: normalizeScope(service.scope ?? service.railwayEnvironment ?? "railway"),
922
+ system: service.key === "api" ? "api" : "agents",
923
+ task: `${service.key}-railway-deploy`,
924
+ stage: "deploy"
925
+ };
926
+ const commandEnv = buildRailwayCommandEnv({ ...process.env, ...env });
914
927
  if (service.buildCommand) {
915
- const buildResult = spawnSync("bash", ["-lc", service.buildCommand], {
928
+ const buildResult = await runPrefixedCommand("bash", ["-lc", service.buildCommand], {
916
929
  cwd: service.rootDir,
917
- stdio: "inherit",
918
- env: { ...process.env }
930
+ env: commandEnv,
931
+ write,
932
+ prefix: { ...taskPrefix, stage: "build" }
919
933
  });
920
934
  if (buildResult.status !== 0) {
921
935
  throw new Error(`Railway ${service.key} build command failed.`);
@@ -923,17 +937,12 @@ async function deployRailwayService(tenantRoot, service, { dryRun = false } = {}
923
937
  }
924
938
  let lastFailure = null;
925
939
  for (let attempt = 1; attempt <= 5; attempt += 1) {
926
- const result = runRailway(plan.args, {
940
+ const result = await runPrefixedCommand(plan.command, plan.args, {
927
941
  cwd: service.rootDir,
928
- capture: true,
929
- allowFailure: true
942
+ env: commandEnv,
943
+ write,
944
+ prefix: taskPrefix
930
945
  });
931
- if (result.stdout) {
932
- process.stdout.write(result.stdout);
933
- }
934
- if (result.stderr) {
935
- process.stderr.write(result.stderr);
936
- }
937
946
  if (result.status === 0) {
938
947
  lastFailure = null;
939
948
  break;
@@ -943,16 +952,15 @@ async function deployRailwayService(tenantRoot, service, { dryRun = false } = {}
943
952
  throw new Error(result.stderr?.trim() || result.stdout?.trim() || `railway ${plan.args.join(" ")} failed`);
944
953
  }
945
954
  const backoffMs = 5e3 * attempt;
946
- console.warn(
947
- `Railway deploy for ${service.serviceName ?? service.serviceId ?? service.key} hit a transient failure; retrying in ${Math.round(backoffMs / 1e3)}s...`
948
- );
949
- sleepSync(backoffMs);
955
+ const warning = `Railway deploy for ${service.serviceName ?? service.serviceId ?? service.key} hit a transient failure; retrying in ${Math.round(backoffMs / 1e3)}s...`;
956
+ write ? write(`[${taskPrefix.scope}][${taskPrefix.system}][${taskPrefix.task}][retry] ${warning}`, "stderr") : console.warn(warning);
957
+ await sleep(backoffMs);
950
958
  }
951
959
  if (lastFailure) {
952
960
  throw new Error(lastFailure.stderr?.trim() || lastFailure.stdout?.trim() || `railway ${plan.args.join(" ")} failed`);
953
961
  }
954
962
  const runtimeConfiguration = await syncRailwayServiceRuntimeConfigurationAfterDeploy(tenantRoot, service, {
955
- env: buildRailwayCommandEnv(process.env)
963
+ env: commandEnv
956
964
  });
957
965
  return {
958
966
  service: service.key,
@@ -23,8 +23,6 @@ export declare function loadPackageJson(root?: string): any;
23
23
  export declare function isWorkspaceRoot(root?: string): boolean;
24
24
  export declare function createProductionBuildEnv(extraEnv?: {}): {
25
25
  TREESEED_LOCAL_DEV_MODE: string;
26
- TREESEED_PUBLIC_FORMS_LOCAL_BYPASS_TURNSTILE: string;
27
- TREESEED_FORMS_LOCAL_BYPASS_TURNSTILE: string;
28
26
  TREESEED_FORMS_LOCAL_BYPASS_CLOUDFLARE_GUARDS: string;
29
27
  TREESEED_PUBLIC_DEV_WATCH_RELOAD: string;
30
28
  };
@@ -331,8 +331,6 @@ function isWorkspaceRoot(root = process.cwd()) {
331
331
  function createProductionBuildEnv(extraEnv = {}) {
332
332
  return {
333
333
  TREESEED_LOCAL_DEV_MODE: "cloudflare",
334
- TREESEED_PUBLIC_FORMS_LOCAL_BYPASS_TURNSTILE: "",
335
- TREESEED_FORMS_LOCAL_BYPASS_TURNSTILE: "",
336
334
  TREESEED_FORMS_LOCAL_BYPASS_CLOUDFLARE_GUARDS: "",
337
335
  TREESEED_PUBLIC_DEV_WATCH_RELOAD: "",
338
336
  ...extraEnv