@treeseed/sdk 0.6.3 → 0.6.5

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.
@@ -1444,9 +1444,30 @@ function resolveTreeseedLaunchEnvironment({
1444
1444
  overrides = {}
1445
1445
  }) {
1446
1446
  warnDeprecatedTreeseedLocalEnvFiles(tenantRoot);
1447
+ let machineValues = {};
1448
+ try {
1449
+ machineValues = resolveTreeseedMachineEnvironmentValues(tenantRoot, scope);
1450
+ } catch (error) {
1451
+ if (!(error instanceof TreeseedKeyAgentError)) {
1452
+ throw error;
1453
+ }
1454
+ }
1455
+ const registry = collectTreeseedEnvironmentContext(tenantRoot);
1456
+ const seedValues = scope === "local" ? { ...baseEnv, ...machineValues } : { ...machineValues, ...baseEnv };
1457
+ const suggestedValues = getTreeseedEnvironmentSuggestedValues({
1458
+ scope,
1459
+ purpose: "deploy",
1460
+ deployConfig: registry.context.deployConfig,
1461
+ tenantConfig: registry.context.tenantConfig,
1462
+ plugins: registry.context.plugins,
1463
+ values: seedValues
1464
+ });
1465
+ const nonSecretSuggestedValues = Object.fromEntries(
1466
+ registry.entries.filter((entry) => entry.sensitivity !== "secret" && typeof suggestedValues[entry.id] === "string" && suggestedValues[entry.id].length > 0).map((entry) => [entry.id, suggestedValues[entry.id]])
1467
+ );
1468
+ const scopedValues = scope === "local" ? { ...nonSecretSuggestedValues, ...baseEnv, ...machineValues } : { ...nonSecretSuggestedValues, ...machineValues, ...baseEnv };
1447
1469
  return {
1448
- ...baseEnv,
1449
- ...resolveTreeseedMachineEnvironmentValues(tenantRoot, scope),
1470
+ ...scopedValues,
1450
1471
  ...overrides
1451
1472
  };
1452
1473
  }
@@ -1467,7 +1488,7 @@ function formatTreeseedConfigEnvironmentReport({ tenantRoot, scope, env = proces
1467
1488
  function applyTreeseedEnvironmentToProcess({ tenantRoot, scope, override = false }) {
1468
1489
  let resolvedValues = {};
1469
1490
  try {
1470
- resolvedValues = resolveTreeseedLaunchEnvironment({ tenantRoot, scope, baseEnv: {} });
1491
+ resolvedValues = resolveTreeseedLaunchEnvironment({ tenantRoot, scope });
1471
1492
  } catch (error) {
1472
1493
  if (!(error instanceof TreeseedKeyAgentError)) {
1473
1494
  throw error;
@@ -305,6 +305,7 @@ function requiredGitHubSecrets(tenantRoot) {
305
305
  function renderTenantWorkflowActionCommand() {
306
306
  return [
307
307
  "EXTRA_ARGS=()",
308
+ 'if [[ "${TREESEED_WORKFLOW_SKIP_PROVISION:-}" == "1" ]]; then EXTRA_ARGS+=(--skip-provision); fi',
308
309
  'if [[ -n "${TREESEED_WORKFLOW_PROJECT:-}" ]]; then EXTRA_ARGS+=(--project-id "${TREESEED_WORKFLOW_PROJECT}"); fi',
309
310
  'if [[ -n "${TREESEED_WORKFLOW_PREVIEW_ID:-}" ]]; then EXTRA_ARGS+=(--preview-id "${TREESEED_WORKFLOW_PREVIEW_ID}"); fi',
310
311
  "if test -f ./packages/sdk/scripts/tenant-workflow-action.ts; then",
@@ -14,7 +14,7 @@ import {
14
14
  import { createPublishedContentPipeline } from "../../platform/published-content-pipeline.js";
15
15
  import { collectTreeseedReconcileStatus, reconcileTreeseedTarget, resolveTreeseedBootstrapSelection } from "../../reconcile/index.js";
16
16
  import { loadTreeseedManifest } from "../../platform/tenant-config.js";
17
- import { applyTreeseedEnvironmentToProcess } from "./config-runtime.js";
17
+ import { applyTreeseedEnvironmentToProcess, assertTreeseedCommandEnvironment } from "./config-runtime.js";
18
18
  import {
19
19
  assertDeploymentInitialized,
20
20
  createPersistentDeployTarget,
@@ -115,6 +115,19 @@ function resolveProjectPlatformBootstrapSystems(options, siteConfig = loadCliDep
115
115
  }
116
116
  return selection.runnable.filter((system) => system !== "github");
117
117
  }
118
+ function runTenantPublishContentPreflight(options) {
119
+ const target = createPersistentDeployTarget(options.scope === "local" ? "staging" : options.scope);
120
+ applyTreeseedEnvironmentToProcess({ tenantRoot: options.tenantRoot, scope: options.scope, override: true });
121
+ if (options.scope !== "local") {
122
+ assertTreeseedCommandEnvironment({
123
+ tenantRoot: options.tenantRoot,
124
+ scope: options.scope,
125
+ purpose: "deploy"
126
+ });
127
+ assertDeploymentInitialized(options.tenantRoot, { target });
128
+ }
129
+ return target;
130
+ }
118
131
  function runWrangler(tenantRoot, args, extraEnv = {}, options = {}) {
119
132
  const result = spawnSync(process.execPath, [resolveWranglerBin(), ...args], {
120
133
  cwd: tenantRoot,
@@ -630,6 +643,7 @@ function probeScaleConfiguration(siteConfig, state) {
630
643
  };
631
644
  }
632
645
  async function publishContent(options, reporter) {
646
+ const target = runTenantPublishContentPreflight(options);
633
647
  const siteConfig = loadCliDeployConfig(options.tenantRoot);
634
648
  const tenantConfig = loadTreeseedManifest(resolve(options.tenantRoot, "src", "manifest.yaml"));
635
649
  const teamId = String(process.env.TREESEED_HOSTING_TEAM_ID ?? siteConfig.hosting?.teamId ?? siteConfig.slug).trim() || siteConfig.slug;
@@ -638,7 +652,6 @@ async function publishContent(options, reporter) {
638
652
  const branchName = currentRef(options.tenantRoot);
639
653
  const previewId = options.previewId ?? `staging-${sanitizeSegment(branchName, "preview")}-${sanitizeSegment(commitSha?.slice(0, 12), "latest")}`;
640
654
  const locator = resolveTeamScopedContentLocator(siteConfig, teamId);
641
- const target = createPersistentDeployTarget(options.scope === "local" ? "staging" : options.scope);
642
655
  const { wranglerPath } = ensureGeneratedWranglerConfig(options.tenantRoot, { target });
643
656
  const wranglerEnv = { CLOUDFLARE_ACCOUNT_ID: String(process.env.CLOUDFLARE_ACCOUNT_ID ?? siteConfig.cloudflare.accountId ?? "").trim() };
644
657
  const bucketName = String(process.env.TREESEED_CONTENT_BUCKET_NAME ?? siteConfig.cloudflare.r2?.bucketName ?? "").trim();
@@ -1141,7 +1154,7 @@ async function deployProjectPlatform(options) {
1141
1154
  scheduleVerification: railwayScheduleVerification
1142
1155
  });
1143
1156
  }
1144
- const monitor = await monitorProjectPlatform({ ...options, reporter });
1157
+ const monitor = await monitorProjectPlatform({ ...options, reporter, bootstrapSystems });
1145
1158
  await reportDeployment(reporter, {
1146
1159
  environment: options.scope,
1147
1160
  deploymentKind: "code",
@@ -1171,15 +1184,20 @@ async function monitorProjectPlatform(options) {
1171
1184
  const reporter = resolveReporter(options.tenantRoot, options.reporter);
1172
1185
  const target = createPersistentDeployTarget(options.scope === "local" ? "staging" : options.scope);
1173
1186
  const siteConfig = loadCliDeployConfig(options.tenantRoot);
1187
+ const selectedSystems = new Set(resolveProjectPlatformBootstrapSystems(options, siteConfig));
1188
+ const apiSelected = selectedSystems.has("api");
1189
+ const agentsSelected = selectedSystems.has("agents");
1174
1190
  const state = loadDeployState(options.tenantRoot, siteConfig, { target });
1175
1191
  const webProbeUrl = resolveImmediatePagesProbeUrl(siteConfig, state, target);
1176
1192
  const apiBaseUrl = resolveImmediateApiProbeUrl(siteConfig, state, target);
1193
+ const skippedApiCheck = apiSelected ? { ok: false, skipped: true, reason: "api_url_unconfigured" } : { ok: true, skipped: true, reason: "api_not_selected" };
1194
+ const skippedAgentCheck = agentsSelected ? { ok: false, skipped: true, reason: "api_url_unconfigured" } : { ok: true, skipped: true, reason: "agents_not_selected" };
1177
1195
  const checks = {
1178
1196
  pages: await probeHttp(webProbeUrl),
1179
- apiHealth: apiBaseUrl ? await probeHttp(`${String(apiBaseUrl).replace(/\/+$/u, "")}/healthz`) : { ok: false, skipped: true, reason: "api_url_unconfigured" },
1180
- apiReady: apiBaseUrl ? await probeHttp(`${String(apiBaseUrl).replace(/\/+$/u, "")}/readyz`) : { ok: false, skipped: true, reason: "api_url_unconfigured" },
1181
- d1Health: apiBaseUrl ? await probeHttp(`${String(apiBaseUrl).replace(/\/+$/u, "")}/healthz/deep`) : { ok: false, skipped: true, reason: "api_url_unconfigured" },
1182
- agentHealth: apiBaseUrl ? await probeHttp(`${String(apiBaseUrl).replace(/\/+$/u, "")}/internal/core/agent/healthz`) : { ok: false, skipped: true, reason: "api_url_unconfigured" },
1197
+ apiHealth: apiSelected && apiBaseUrl ? await probeHttp(`${String(apiBaseUrl).replace(/\/+$/u, "")}/healthz`) : skippedApiCheck,
1198
+ apiReady: apiSelected && apiBaseUrl ? await probeHttp(`${String(apiBaseUrl).replace(/\/+$/u, "")}/readyz`) : skippedApiCheck,
1199
+ d1Health: apiSelected && apiBaseUrl ? await probeHttp(`${String(apiBaseUrl).replace(/\/+$/u, "")}/healthz/deep`) : skippedApiCheck,
1200
+ agentHealth: agentsSelected && apiBaseUrl ? await probeHttp(`${String(apiBaseUrl).replace(/\/+$/u, "")}/internal/core/agent/healthz`) : skippedAgentCheck,
1183
1201
  r2: options.dryRun ? { ok: true, skipped: true, reason: "dry_run" } : probeR2(options.tenantRoot, siteConfig, state, target),
1184
1202
  queue: options.dryRun ? Promise.resolve({ ok: true, skipped: true, reason: "dry_run" }) : probeQueue(siteConfig, state),
1185
1203
  scaleProbe: probeScaleConfiguration(siteConfig, state),
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env node
2
+ import { pathToFileURL } from 'node:url';
2
3
  import { resolveScope, runProjectPlatformAction, } from '../operations/services/project-platform.js';
3
4
  const tenantRoot = process.cwd();
4
5
  function parseArgs(argv) {
@@ -8,6 +9,7 @@ function parseArgs(argv) {
8
9
  projectId: null,
9
10
  previewId: null,
10
11
  dryRun: false,
12
+ skipProvision: false,
11
13
  };
12
14
  const rest = [...argv];
13
15
  while (rest.length) {
@@ -50,6 +52,10 @@ function parseArgs(argv) {
50
52
  parsed.dryRun = true;
51
53
  continue;
52
54
  }
55
+ if (current === '--skip-provision') {
56
+ parsed.skipProvision = true;
57
+ continue;
58
+ }
53
59
  throw new Error(`Unknown workflow action argument: ${current}`);
54
60
  }
55
61
  return parsed;
@@ -63,9 +69,13 @@ async function main() {
63
69
  projectId: options.projectId ?? process.env.TREESEED_PROJECT_ID ?? null,
64
70
  previewId: options.previewId,
65
71
  dryRun: options.dryRun,
72
+ skipProvision: options.skipProvision,
66
73
  });
67
74
  if (result !== undefined) {
68
75
  process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
69
76
  }
70
77
  }
71
- await main();
78
+ if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
79
+ await main();
80
+ }
81
+ export { parseArgs };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@treeseed/sdk",
3
- "version": "0.6.3",
3
+ "version": "0.6.5",
4
4
  "description": "Shared Treeseed SDK for content-backed and D1-backed object models.",
5
5
  "license": "AGPL-3.0-only",
6
6
  "repository": {
@@ -98,9 +98,12 @@ jobs:
98
98
  while IFS= read -r path; do
99
99
  [[ -z "${path}" ]] && continue
100
100
  case "${path}" in
101
- src/content/*|content/*|books/*|docs/*|migrations/*)
101
+ src/content/*|content/*|books/*|docs/*)
102
102
  content_changed="true"
103
103
  ;;
104
+ migrations/*)
105
+ code_changed="true"
106
+ ;;
104
107
  *)
105
108
  code_changed="true"
106
109
  ;;
@@ -131,6 +134,8 @@ jobs:
131
134
  needs.classify.outputs.release_tag == 'true'
132
135
  permissions:
133
136
  contents: read
137
+ env:
138
+ TREESEED_BOOTSTRAP_MODE: auto
134
139
  steps:
135
140
  - name: Checkout
136
141
  uses: actions/checkout@v4
@@ -178,6 +183,7 @@ __WORKING_DIRECTORY_BLOCK__
178
183
  deployments: write
179
184
  environment: ${{ needs.classify.outputs.scope == 'prod' && 'production' || 'staging' }}
180
185
  env:
186
+ TREESEED_BOOTSTRAP_MODE: auto
181
187
  CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
182
188
  CLOUDFLARE_ACCOUNT_ID: ${{ vars.CLOUDFLARE_ACCOUNT_ID }}
183
189
  TREESEED_CLOUDFLARE_PAGES_PROJECT_NAME: ${{ vars.TREESEED_CLOUDFLARE_PAGES_PROJECT_NAME }}
@@ -195,7 +201,31 @@ __WORKING_DIRECTORY_BLOCK__
195
201
  TREESEED_SMTP_FROM: ${{ vars.TREESEED_SMTP_FROM }}
196
202
  TREESEED_SMTP_REPLY_TO: ${{ vars.TREESEED_SMTP_REPLY_TO }}
197
203
  RAILWAY_API_TOKEN: ${{ secrets.RAILWAY_API_TOKEN }}
204
+ TREESEED_RAILWAY_WORKSPACE: ${{ vars.TREESEED_RAILWAY_WORKSPACE }}
205
+ TREESEED_HOSTING_KIND: ${{ vars.TREESEED_HOSTING_KIND }}
206
+ TREESEED_HOSTING_REGISTRATION: ${{ vars.TREESEED_HOSTING_REGISTRATION }}
207
+ TREESEED_HOSTING_TEAM_ID: ${{ vars.TREESEED_HOSTING_TEAM_ID }}
198
208
  TREESEED_MARKET_API_BASE_URL: ${{ vars.TREESEED_MARKET_API_BASE_URL }}
209
+ TREESEED_PROJECT_DOMAINS: ${{ vars.TREESEED_PROJECT_DOMAINS }}
210
+ TREESEED_API_BASE_URL: ${{ vars.TREESEED_API_BASE_URL }}
211
+ TREESEED_BETTER_AUTH_SECRET: ${{ secrets.TREESEED_BETTER_AUTH_SECRET }}
212
+ TREESEED_WEB_SERVICE_ID: ${{ vars.TREESEED_WEB_SERVICE_ID }}
213
+ TREESEED_WEB_SERVICE_SECRET: ${{ secrets.TREESEED_WEB_SERVICE_SECRET }}
214
+ TREESEED_WEB_ASSERTION_SECRET: ${{ secrets.TREESEED_WEB_ASSERTION_SECRET }}
215
+ TREESEED_WEB_CSRF_SECRET: ${{ secrets.TREESEED_WEB_CSRF_SECRET }}
216
+ TREESEED_AUTH_GITHUB_CLIENT_ID: ${{ vars.TREESEED_AUTH_GITHUB_CLIENT_ID }}
217
+ TREESEED_AUTH_GITHUB_CLIENT_SECRET: ${{ secrets.TREESEED_AUTH_GITHUB_CLIENT_SECRET }}
218
+ TREESEED_AUTH_GOOGLE_CLIENT_ID: ${{ vars.TREESEED_AUTH_GOOGLE_CLIENT_ID }}
219
+ TREESEED_AUTH_GOOGLE_CLIENT_SECRET: ${{ secrets.TREESEED_AUTH_GOOGLE_CLIENT_SECRET }}
220
+ TREESEED_AUTH_MICROSOFT_CLIENT_ID: ${{ vars.TREESEED_AUTH_MICROSOFT_CLIENT_ID }}
221
+ TREESEED_AUTH_MICROSOFT_CLIENT_SECRET: ${{ secrets.TREESEED_AUTH_MICROSOFT_CLIENT_SECRET }}
222
+ TREESEED_AUTH_APPLE_CLIENT_ID: ${{ vars.TREESEED_AUTH_APPLE_CLIENT_ID }}
223
+ TREESEED_AUTH_APPLE_CLIENT_SECRET: ${{ secrets.TREESEED_AUTH_APPLE_CLIENT_SECRET }}
224
+ TREESEED_API_D1_DATABASE_ID: ${{ vars.TREESEED_API_D1_DATABASE_ID }}
225
+ TREESEED_API_WEB_SERVICE_ID: ${{ vars.TREESEED_API_WEB_SERVICE_ID }}
226
+ TREESEED_API_WEB_SERVICE_SECRET: ${{ secrets.TREESEED_API_WEB_SERVICE_SECRET }}
227
+ TREESEED_API_WEB_ASSERTION_SECRET: ${{ secrets.TREESEED_API_WEB_ASSERTION_SECRET }}
228
+ TREESEED_API_BOOTSTRAP_ADMIN_ALLOWLIST: ${{ vars.TREESEED_API_BOOTSTRAP_ADMIN_ALLOWLIST }}
199
229
  TREESEED_PROJECT_ID: ${{ inputs.project_id || vars.TREESEED_PROJECT_ID }}
200
230
  TREESEED_PROJECT_RUNNER_TOKEN: ${{ secrets.TREESEED_PROJECT_RUNNER_TOKEN }}
201
231
  TREESEED_WORKER_POOL_SCALER: ${{ vars.TREESEED_WORKER_POOL_SCALER }}
@@ -252,6 +282,7 @@ __WORKING_DIRECTORY_BLOCK__
252
282
  needs.classify.outputs.release_tag == 'true'
253
283
  environment: ${{ needs.classify.outputs.scope == 'prod' && 'production' || 'staging' }}
254
284
  env:
285
+ TREESEED_BOOTSTRAP_MODE: auto
255
286
  CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
256
287
  CLOUDFLARE_ACCOUNT_ID: ${{ vars.CLOUDFLARE_ACCOUNT_ID }}
257
288
  TREESEED_CLOUDFLARE_PAGES_PROJECT_NAME: ${{ vars.TREESEED_CLOUDFLARE_PAGES_PROJECT_NAME }}
@@ -269,7 +300,31 @@ __WORKING_DIRECTORY_BLOCK__
269
300
  TREESEED_SMTP_FROM: ${{ vars.TREESEED_SMTP_FROM }}
270
301
  TREESEED_SMTP_REPLY_TO: ${{ vars.TREESEED_SMTP_REPLY_TO }}
271
302
  RAILWAY_API_TOKEN: ${{ secrets.RAILWAY_API_TOKEN }}
303
+ TREESEED_RAILWAY_WORKSPACE: ${{ vars.TREESEED_RAILWAY_WORKSPACE }}
304
+ TREESEED_HOSTING_KIND: ${{ vars.TREESEED_HOSTING_KIND }}
305
+ TREESEED_HOSTING_REGISTRATION: ${{ vars.TREESEED_HOSTING_REGISTRATION }}
306
+ TREESEED_HOSTING_TEAM_ID: ${{ vars.TREESEED_HOSTING_TEAM_ID }}
272
307
  TREESEED_MARKET_API_BASE_URL: ${{ vars.TREESEED_MARKET_API_BASE_URL }}
308
+ TREESEED_PROJECT_DOMAINS: ${{ vars.TREESEED_PROJECT_DOMAINS }}
309
+ TREESEED_API_BASE_URL: ${{ vars.TREESEED_API_BASE_URL }}
310
+ TREESEED_BETTER_AUTH_SECRET: ${{ secrets.TREESEED_BETTER_AUTH_SECRET }}
311
+ TREESEED_WEB_SERVICE_ID: ${{ vars.TREESEED_WEB_SERVICE_ID }}
312
+ TREESEED_WEB_SERVICE_SECRET: ${{ secrets.TREESEED_WEB_SERVICE_SECRET }}
313
+ TREESEED_WEB_ASSERTION_SECRET: ${{ secrets.TREESEED_WEB_ASSERTION_SECRET }}
314
+ TREESEED_WEB_CSRF_SECRET: ${{ secrets.TREESEED_WEB_CSRF_SECRET }}
315
+ TREESEED_AUTH_GITHUB_CLIENT_ID: ${{ vars.TREESEED_AUTH_GITHUB_CLIENT_ID }}
316
+ TREESEED_AUTH_GITHUB_CLIENT_SECRET: ${{ secrets.TREESEED_AUTH_GITHUB_CLIENT_SECRET }}
317
+ TREESEED_AUTH_GOOGLE_CLIENT_ID: ${{ vars.TREESEED_AUTH_GOOGLE_CLIENT_ID }}
318
+ TREESEED_AUTH_GOOGLE_CLIENT_SECRET: ${{ secrets.TREESEED_AUTH_GOOGLE_CLIENT_SECRET }}
319
+ TREESEED_AUTH_MICROSOFT_CLIENT_ID: ${{ vars.TREESEED_AUTH_MICROSOFT_CLIENT_ID }}
320
+ TREESEED_AUTH_MICROSOFT_CLIENT_SECRET: ${{ secrets.TREESEED_AUTH_MICROSOFT_CLIENT_SECRET }}
321
+ TREESEED_AUTH_APPLE_CLIENT_ID: ${{ vars.TREESEED_AUTH_APPLE_CLIENT_ID }}
322
+ TREESEED_AUTH_APPLE_CLIENT_SECRET: ${{ secrets.TREESEED_AUTH_APPLE_CLIENT_SECRET }}
323
+ TREESEED_API_D1_DATABASE_ID: ${{ vars.TREESEED_API_D1_DATABASE_ID }}
324
+ TREESEED_API_WEB_SERVICE_ID: ${{ vars.TREESEED_API_WEB_SERVICE_ID }}
325
+ TREESEED_API_WEB_SERVICE_SECRET: ${{ secrets.TREESEED_API_WEB_SERVICE_SECRET }}
326
+ TREESEED_API_WEB_ASSERTION_SECRET: ${{ secrets.TREESEED_API_WEB_ASSERTION_SECRET }}
327
+ TREESEED_API_BOOTSTRAP_ADMIN_ALLOWLIST: ${{ vars.TREESEED_API_BOOTSTRAP_ADMIN_ALLOWLIST }}
273
328
  TREESEED_PROJECT_ID: ${{ inputs.project_id || vars.TREESEED_PROJECT_ID }}
274
329
  TREESEED_PROJECT_RUNNER_TOKEN: ${{ secrets.TREESEED_PROJECT_RUNNER_TOKEN }}
275
330
  TREESEED_WORKER_POOL_SCALER: ${{ vars.TREESEED_WORKER_POOL_SCALER }}
@@ -290,6 +345,7 @@ __WORKING_DIRECTORY_BLOCK__
290
345
  TREESEED_CONTENT_SERVING_MODE: published_runtime
291
346
  TREESEED_WORKFLOW_ACTION: deploy_code
292
347
  TREESEED_WORKFLOW_ENVIRONMENT: ${{ needs.classify.outputs.scope }}
348
+ TREESEED_WORKFLOW_SKIP_PROVISION: "1"
293
349
  TREESEED_WORKFLOW_PROJECT: ${{ inputs.project_id || vars.TREESEED_PROJECT_ID }}
294
350
  TREESEED_WORKFLOW_PREVIEW_ID: ${{ inputs.preview_id || needs.classify.outputs.preview_id }}
295
351
  steps:
@@ -332,11 +388,14 @@ __WORKING_DIRECTORY_BLOCK__
332
388
  contents: read
333
389
  deployments: write
334
390
  if: |
391
+ always() &&
392
+ needs.provision.result == 'success' &&
335
393
  (needs.classify.outputs.workflow_action == 'publish_content' ||
336
394
  needs.classify.outputs.content_changed == 'true') &&
337
395
  (needs['deploy-code'].result == 'success' || needs['deploy-code'].result == 'skipped')
338
396
  environment: ${{ needs.classify.outputs.scope == 'prod' && 'production' || 'staging' }}
339
397
  env:
398
+ TREESEED_BOOTSTRAP_MODE: auto
340
399
  CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
341
400
  CLOUDFLARE_ACCOUNT_ID: ${{ vars.CLOUDFLARE_ACCOUNT_ID }}
342
401
  TREESEED_CLOUDFLARE_PAGES_PROJECT_NAME: ${{ vars.TREESEED_CLOUDFLARE_PAGES_PROJECT_NAME }}
@@ -354,7 +413,31 @@ __WORKING_DIRECTORY_BLOCK__
354
413
  TREESEED_SMTP_FROM: ${{ vars.TREESEED_SMTP_FROM }}
355
414
  TREESEED_SMTP_REPLY_TO: ${{ vars.TREESEED_SMTP_REPLY_TO }}
356
415
  RAILWAY_API_TOKEN: ${{ secrets.RAILWAY_API_TOKEN }}
416
+ TREESEED_RAILWAY_WORKSPACE: ${{ vars.TREESEED_RAILWAY_WORKSPACE }}
417
+ TREESEED_HOSTING_KIND: ${{ vars.TREESEED_HOSTING_KIND }}
418
+ TREESEED_HOSTING_REGISTRATION: ${{ vars.TREESEED_HOSTING_REGISTRATION }}
419
+ TREESEED_HOSTING_TEAM_ID: ${{ vars.TREESEED_HOSTING_TEAM_ID }}
357
420
  TREESEED_MARKET_API_BASE_URL: ${{ vars.TREESEED_MARKET_API_BASE_URL }}
421
+ TREESEED_PROJECT_DOMAINS: ${{ vars.TREESEED_PROJECT_DOMAINS }}
422
+ TREESEED_API_BASE_URL: ${{ vars.TREESEED_API_BASE_URL }}
423
+ TREESEED_BETTER_AUTH_SECRET: ${{ secrets.TREESEED_BETTER_AUTH_SECRET }}
424
+ TREESEED_WEB_SERVICE_ID: ${{ vars.TREESEED_WEB_SERVICE_ID }}
425
+ TREESEED_WEB_SERVICE_SECRET: ${{ secrets.TREESEED_WEB_SERVICE_SECRET }}
426
+ TREESEED_WEB_ASSERTION_SECRET: ${{ secrets.TREESEED_WEB_ASSERTION_SECRET }}
427
+ TREESEED_WEB_CSRF_SECRET: ${{ secrets.TREESEED_WEB_CSRF_SECRET }}
428
+ TREESEED_AUTH_GITHUB_CLIENT_ID: ${{ vars.TREESEED_AUTH_GITHUB_CLIENT_ID }}
429
+ TREESEED_AUTH_GITHUB_CLIENT_SECRET: ${{ secrets.TREESEED_AUTH_GITHUB_CLIENT_SECRET }}
430
+ TREESEED_AUTH_GOOGLE_CLIENT_ID: ${{ vars.TREESEED_AUTH_GOOGLE_CLIENT_ID }}
431
+ TREESEED_AUTH_GOOGLE_CLIENT_SECRET: ${{ secrets.TREESEED_AUTH_GOOGLE_CLIENT_SECRET }}
432
+ TREESEED_AUTH_MICROSOFT_CLIENT_ID: ${{ vars.TREESEED_AUTH_MICROSOFT_CLIENT_ID }}
433
+ TREESEED_AUTH_MICROSOFT_CLIENT_SECRET: ${{ secrets.TREESEED_AUTH_MICROSOFT_CLIENT_SECRET }}
434
+ TREESEED_AUTH_APPLE_CLIENT_ID: ${{ vars.TREESEED_AUTH_APPLE_CLIENT_ID }}
435
+ TREESEED_AUTH_APPLE_CLIENT_SECRET: ${{ secrets.TREESEED_AUTH_APPLE_CLIENT_SECRET }}
436
+ TREESEED_API_D1_DATABASE_ID: ${{ vars.TREESEED_API_D1_DATABASE_ID }}
437
+ TREESEED_API_WEB_SERVICE_ID: ${{ vars.TREESEED_API_WEB_SERVICE_ID }}
438
+ TREESEED_API_WEB_SERVICE_SECRET: ${{ secrets.TREESEED_API_WEB_SERVICE_SECRET }}
439
+ TREESEED_API_WEB_ASSERTION_SECRET: ${{ secrets.TREESEED_API_WEB_ASSERTION_SECRET }}
440
+ TREESEED_API_BOOTSTRAP_ADMIN_ALLOWLIST: ${{ vars.TREESEED_API_BOOTSTRAP_ADMIN_ALLOWLIST }}
358
441
  TREESEED_PROJECT_ID: ${{ inputs.project_id || vars.TREESEED_PROJECT_ID }}
359
442
  TREESEED_PROJECT_RUNNER_TOKEN: ${{ secrets.TREESEED_PROJECT_RUNNER_TOKEN }}
360
443
  TREESEED_WORKER_POOL_SCALER: ${{ vars.TREESEED_WORKER_POOL_SCALER }}
@@ -404,6 +487,8 @@ __WORKING_DIRECTORY_BLOCK__
404
487
  - deploy-code
405
488
  - publish-content
406
489
  if: |
490
+ always() &&
491
+ needs.provision.result == 'success' &&
407
492
  (needs.classify.outputs.workflow_action == 'monitor' ||
408
493
  needs.classify.outputs.code_changed == 'true' ||
409
494
  needs.classify.outputs.content_changed == 'true' ||
@@ -415,12 +500,37 @@ __WORKING_DIRECTORY_BLOCK__
415
500
  deployments: write
416
501
  environment: ${{ needs.classify.outputs.scope == 'prod' && 'production' || 'staging' }}
417
502
  env:
503
+ TREESEED_BOOTSTRAP_MODE: auto
418
504
  CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
419
505
  CLOUDFLARE_ACCOUNT_ID: ${{ vars.CLOUDFLARE_ACCOUNT_ID }}
420
506
  TREESEED_CONTENT_BUCKET_NAME: ${{ vars.TREESEED_CONTENT_BUCKET_NAME }}
421
507
  TREESEED_CONTENT_BUCKET_BINDING: ${{ vars.TREESEED_CONTENT_BUCKET_BINDING }}
422
508
  RAILWAY_API_TOKEN: ${{ secrets.RAILWAY_API_TOKEN }}
509
+ TREESEED_RAILWAY_WORKSPACE: ${{ vars.TREESEED_RAILWAY_WORKSPACE }}
510
+ TREESEED_HOSTING_KIND: ${{ vars.TREESEED_HOSTING_KIND }}
511
+ TREESEED_HOSTING_REGISTRATION: ${{ vars.TREESEED_HOSTING_REGISTRATION }}
512
+ TREESEED_HOSTING_TEAM_ID: ${{ vars.TREESEED_HOSTING_TEAM_ID }}
423
513
  TREESEED_MARKET_API_BASE_URL: ${{ vars.TREESEED_MARKET_API_BASE_URL }}
514
+ TREESEED_PROJECT_DOMAINS: ${{ vars.TREESEED_PROJECT_DOMAINS }}
515
+ TREESEED_API_BASE_URL: ${{ vars.TREESEED_API_BASE_URL }}
516
+ TREESEED_BETTER_AUTH_SECRET: ${{ secrets.TREESEED_BETTER_AUTH_SECRET }}
517
+ TREESEED_WEB_SERVICE_ID: ${{ vars.TREESEED_WEB_SERVICE_ID }}
518
+ TREESEED_WEB_SERVICE_SECRET: ${{ secrets.TREESEED_WEB_SERVICE_SECRET }}
519
+ TREESEED_WEB_ASSERTION_SECRET: ${{ secrets.TREESEED_WEB_ASSERTION_SECRET }}
520
+ TREESEED_WEB_CSRF_SECRET: ${{ secrets.TREESEED_WEB_CSRF_SECRET }}
521
+ TREESEED_AUTH_GITHUB_CLIENT_ID: ${{ vars.TREESEED_AUTH_GITHUB_CLIENT_ID }}
522
+ TREESEED_AUTH_GITHUB_CLIENT_SECRET: ${{ secrets.TREESEED_AUTH_GITHUB_CLIENT_SECRET }}
523
+ TREESEED_AUTH_GOOGLE_CLIENT_ID: ${{ vars.TREESEED_AUTH_GOOGLE_CLIENT_ID }}
524
+ TREESEED_AUTH_GOOGLE_CLIENT_SECRET: ${{ secrets.TREESEED_AUTH_GOOGLE_CLIENT_SECRET }}
525
+ TREESEED_AUTH_MICROSOFT_CLIENT_ID: ${{ vars.TREESEED_AUTH_MICROSOFT_CLIENT_ID }}
526
+ TREESEED_AUTH_MICROSOFT_CLIENT_SECRET: ${{ secrets.TREESEED_AUTH_MICROSOFT_CLIENT_SECRET }}
527
+ TREESEED_AUTH_APPLE_CLIENT_ID: ${{ vars.TREESEED_AUTH_APPLE_CLIENT_ID }}
528
+ TREESEED_AUTH_APPLE_CLIENT_SECRET: ${{ secrets.TREESEED_AUTH_APPLE_CLIENT_SECRET }}
529
+ TREESEED_API_D1_DATABASE_ID: ${{ vars.TREESEED_API_D1_DATABASE_ID }}
530
+ TREESEED_API_WEB_SERVICE_ID: ${{ vars.TREESEED_API_WEB_SERVICE_ID }}
531
+ TREESEED_API_WEB_SERVICE_SECRET: ${{ secrets.TREESEED_API_WEB_SERVICE_SECRET }}
532
+ TREESEED_API_WEB_ASSERTION_SECRET: ${{ secrets.TREESEED_API_WEB_ASSERTION_SECRET }}
533
+ TREESEED_API_BOOTSTRAP_ADMIN_ALLOWLIST: ${{ vars.TREESEED_API_BOOTSTRAP_ADMIN_ALLOWLIST }}
424
534
  TREESEED_PROJECT_ID: ${{ inputs.project_id || vars.TREESEED_PROJECT_ID }}
425
535
  TREESEED_PROJECT_RUNNER_TOKEN: ${{ secrets.TREESEED_PROJECT_RUNNER_TOKEN }}
426
536
  TREESEED_WORKER_POOL_SCALER: ${{ vars.TREESEED_WORKER_POOL_SCALER }}