@treeseed/sdk 0.10.28 → 0.11.0
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/README.md +207 -6
- package/dist/capacity-provider.d.ts +3 -1
- package/dist/capacity-provider.js +25 -5
- package/dist/control-plane.d.ts +1 -0
- package/dist/control-plane.js +38 -13
- package/dist/db/market-schema.d.ts +8860 -6172
- package/dist/db/market-schema.js +108 -0
- package/dist/db/node-sqlite.js +7 -2
- package/dist/hosting/apps.d.ts +12 -0
- package/dist/hosting/apps.js +107 -0
- package/dist/hosting/builtins.d.ts +25 -0
- package/dist/hosting/builtins.js +791 -0
- package/dist/hosting/contracts.d.ts +207 -0
- package/dist/hosting/contracts.js +0 -0
- package/dist/hosting/graph.d.ts +192 -0
- package/dist/hosting/graph.js +1106 -0
- package/dist/hosting/index.d.ts +4 -0
- package/dist/hosting/index.js +4 -0
- package/dist/index.d.ts +10 -3
- package/dist/index.js +63 -6
- package/dist/managed-dependencies.js +1 -2
- package/dist/market-client.d.ts +63 -3
- package/dist/market-client.js +83 -11
- package/dist/operations/services/bootstrap-runner.d.ts +3 -1
- package/dist/operations/services/bootstrap-runner.js +22 -2
- package/dist/operations/services/config-runtime.d.ts +10 -5
- package/dist/operations/services/config-runtime.js +209 -66
- package/dist/operations/services/deploy.d.ts +70 -7
- package/dist/operations/services/deploy.js +579 -64
- package/dist/operations/services/deployment-readiness.d.ts +30 -0
- package/dist/operations/services/deployment-readiness.js +175 -0
- package/dist/operations/services/git-workflow.d.ts +2 -1
- package/dist/operations/services/git-workflow.js +9 -3
- package/dist/operations/services/github-actions-verification.d.ts +1 -0
- package/dist/operations/services/github-actions-verification.js +1 -0
- package/dist/operations/services/github-api.js +1 -1
- package/dist/operations/services/github-automation.d.ts +1 -1
- package/dist/operations/services/github-automation.js +4 -3
- package/dist/operations/services/github-credentials.d.ts +13 -0
- package/dist/operations/services/github-credentials.js +58 -0
- package/dist/operations/services/hosted-service-checks.d.ts +63 -0
- package/dist/operations/services/hosted-service-checks.js +327 -0
- package/dist/operations/services/hub-provider-launch.js +3 -3
- package/dist/operations/services/live-hosted-service-checks.d.ts +25 -0
- package/dist/operations/services/live-hosted-service-checks.js +350 -0
- package/dist/operations/services/managed-host-security.js +1 -1
- package/dist/operations/services/operations-runner-smoke.d.ts +30 -0
- package/dist/operations/services/operations-runner-smoke.js +180 -0
- package/dist/operations/services/package-adapters.d.ts +95 -0
- package/dist/operations/services/package-adapters.js +288 -0
- package/dist/operations/services/package-reference-policy.d.ts +1 -0
- package/dist/operations/services/package-reference-policy.js +15 -2
- package/dist/operations/services/project-platform.d.ts +80 -22
- package/dist/operations/services/project-platform.js +49 -8
- package/dist/operations/services/project-web-monitor.js +26 -4
- package/dist/operations/services/railway-api.d.ts +88 -5
- package/dist/operations/services/railway-api.js +626 -35
- package/dist/operations/services/railway-deploy.d.ts +46 -40
- package/dist/operations/services/railway-deploy.js +261 -293
- package/dist/operations/services/release-candidate.d.ts +19 -0
- package/dist/operations/services/release-candidate.js +375 -38
- package/dist/operations/services/repository-save-orchestrator.d.ts +3 -1
- package/dist/operations/services/repository-save-orchestrator.js +279 -66
- package/dist/operations/services/runtime-tools.d.ts +1 -0
- package/dist/operations/services/runtime-tools.js +10 -9
- package/dist/operations/services/verification-cache.d.ts +25 -0
- package/dist/operations/services/verification-cache.js +71 -0
- package/dist/operations/services/workspace-dependency-mode.js +9 -1
- package/dist/operations/services/workspace-save.js +1 -1
- package/dist/operations/services/workspace-tools.js +2 -1
- package/dist/platform/contracts.d.ts +32 -1
- package/dist/platform/deploy-config.js +73 -8
- package/dist/platform/env.yaml +163 -35
- package/dist/platform/environment.d.ts +1 -0
- package/dist/platform/environment.js +74 -5
- package/dist/platform/plugin.d.ts +9 -0
- package/dist/platform-operation-store.js +2 -2
- package/dist/platform-operations.js +1 -1
- package/dist/reconcile/bootstrap-systems.js +2 -2
- package/dist/reconcile/builtin-adapters.js +372 -189
- package/dist/reconcile/contracts.d.ts +9 -5
- package/dist/reconcile/desired-state.d.ts +1 -0
- package/dist/reconcile/desired-state.js +5 -5
- package/dist/reconcile/engine.d.ts +5 -2
- package/dist/reconcile/engine.js +53 -32
- package/dist/reconcile/index.d.ts +2 -0
- package/dist/reconcile/index.js +2 -0
- package/dist/reconcile/live-acceptance.d.ts +79 -0
- package/dist/reconcile/live-acceptance.js +1615 -0
- package/dist/reconcile/platform.d.ts +104 -0
- package/dist/reconcile/platform.js +100 -0
- package/dist/reconcile/state.js +4 -4
- package/dist/reconcile/units.js +2 -2
- package/dist/scripts/deployment-readiness.js +20 -0
- package/dist/scripts/generate-treedx-openapi-types.js +186 -0
- package/dist/scripts/operations-runner-smoke.js +16 -0
- package/dist/scripts/release-verify.js +4 -1
- package/dist/scripts/tenant-workflow-action.js +10 -1
- package/dist/sdk-types.d.ts +169 -4
- package/dist/sdk-types.js +20 -2
- package/dist/sdk.d.ts +35 -24
- package/dist/sdk.js +186 -17
- package/dist/template-launch-requirements.js +9 -0
- package/dist/treedx/adapters.d.ts +6 -0
- package/dist/treedx/adapters.js +36 -0
- package/dist/treedx/client.d.ts +222 -0
- package/dist/treedx/client.js +871 -0
- package/dist/treedx/errors.d.ts +13 -0
- package/dist/treedx/errors.js +17 -0
- package/dist/treedx/federated-client.d.ts +27 -0
- package/dist/treedx/federated-client.js +158 -0
- package/dist/treedx/generated/openapi-types.d.ts +3558 -0
- package/dist/treedx/generated/openapi-types.js +0 -0
- package/dist/treedx/graph-adapter.d.ts +33 -0
- package/dist/treedx/graph-adapter.js +156 -0
- package/dist/treedx/index.d.ts +14 -0
- package/dist/treedx/index.js +48 -0
- package/dist/treedx/market-integration.d.ts +27 -0
- package/dist/treedx/market-integration.js +131 -0
- package/dist/treedx/ports.d.ts +166 -0
- package/dist/treedx/ports.js +231 -0
- package/dist/treedx/query-adapter.d.ts +19 -0
- package/dist/treedx/query-adapter.js +62 -0
- package/dist/treedx/registry-client.d.ts +11 -0
- package/dist/treedx/registry-client.js +19 -0
- package/dist/treedx/repository-adapter.d.ts +45 -0
- package/dist/treedx/repository-adapter.js +308 -0
- package/dist/treedx/sdk-integration.d.ts +27 -0
- package/dist/treedx/sdk-integration.js +63 -0
- package/dist/treedx/types.d.ts +1084 -0
- package/dist/treedx/types.js +8 -0
- package/dist/treedx/workspace-adapter.d.ts +27 -0
- package/dist/treedx/workspace-adapter.js +65 -0
- package/dist/treedx-backends.d.ts +218 -0
- package/dist/treedx-backends.js +632 -0
- package/dist/treedx-client.d.ts +86 -0
- package/dist/treedx-client.js +175 -0
- package/dist/treeseed/template-catalog/catalog.fixture.json +23 -23
- package/dist/workflow/operations.d.ts +119 -13
- package/dist/workflow/operations.js +309 -53
- package/dist/workflow-state.d.ts +13 -0
- package/dist/workflow-state.js +43 -26
- package/dist/workflow-support.d.ts +11 -3
- package/dist/workflow-support.js +67 -3
- package/dist/workflow.d.ts +5 -0
- package/drizzle/market/0004_treedx_market_integration.sql +99 -0
- package/package.json +34 -3
- package/templates/github/deploy-web.workflow.yml +39 -6
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
3
|
+
import { relative, resolve } from "node:path";
|
|
4
|
+
import { parse as parseYaml } from "yaml";
|
|
5
|
+
import { workspacePackages, workspaceRoot } from "./workspace-tools.js";
|
|
6
|
+
function readJsonFile(filePath) {
|
|
7
|
+
try {
|
|
8
|
+
return JSON.parse(readFileSync(filePath, "utf8"));
|
|
9
|
+
} catch {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
function readStructuredFile(filePath) {
|
|
14
|
+
try {
|
|
15
|
+
const raw = readFileSync(filePath, "utf8");
|
|
16
|
+
return filePath.endsWith(".yaml") || filePath.endsWith(".yml") ? parseYaml(raw) : JSON.parse(raw);
|
|
17
|
+
} catch {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
function readPackageJsonVersion(filePath) {
|
|
22
|
+
const packageJson = readJsonFile(filePath);
|
|
23
|
+
return typeof packageJson?.version === "string" ? packageJson.version : null;
|
|
24
|
+
}
|
|
25
|
+
function normalizeGitHubRepositorySlug(value) {
|
|
26
|
+
const raw = typeof value === "string" ? value : value && typeof value === "object" && !Array.isArray(value) ? value.url : null;
|
|
27
|
+
if (typeof raw !== "string" || !raw.trim()) return null;
|
|
28
|
+
const normalized = raw.trim().replace(/^git\+/u, "").replace(/^ssh:\/\/git@github\.com[:/]/u, "").replace(/^git@github\.com:/u, "").replace(/^https:\/\/github\.com\//u, "").replace(/\.git$/u, "").replace(/\/$/u, "");
|
|
29
|
+
return /^[^/\s]+\/[^/\s]+$/u.test(normalized) ? normalized : null;
|
|
30
|
+
}
|
|
31
|
+
function readMixProjectVersion(filePath) {
|
|
32
|
+
if (!existsSync(filePath)) return null;
|
|
33
|
+
const source = readFileSync(filePath, "utf8");
|
|
34
|
+
const match = source.match(/\bversion:\s*"([^"]+)"/u);
|
|
35
|
+
return match?.[1] ?? null;
|
|
36
|
+
}
|
|
37
|
+
function commandFromScript(dir, script, label) {
|
|
38
|
+
if (typeof script !== "string" || !script.trim()) return null;
|
|
39
|
+
const trimmed = script.trim();
|
|
40
|
+
if (trimmed.startsWith("scripts/")) {
|
|
41
|
+
return { label, command: "bash", args: [trimmed], cwd: dir };
|
|
42
|
+
}
|
|
43
|
+
return { label, command: "bash", args: ["-lc", trimmed], cwd: dir };
|
|
44
|
+
}
|
|
45
|
+
function nodeTypeScriptAdapter(pkg) {
|
|
46
|
+
const manifest = readTreeseedPackageManifest(pkg.dir);
|
|
47
|
+
const scripts = pkg.packageJson?.scripts && typeof pkg.packageJson.scripts === "object" && !Array.isArray(pkg.packageJson.scripts) ? pkg.packageJson.scripts : {};
|
|
48
|
+
const manifestVerify = manifest?.verify && typeof manifest.verify === "object" && !Array.isArray(manifest.verify) ? manifest.verify : {};
|
|
49
|
+
const repository = stringValue(manifest?.repository) ?? normalizeGitHubRepositorySlug(pkg.packageJson?.repository);
|
|
50
|
+
const id = stringValue(manifest?.id) ?? String(pkg.name);
|
|
51
|
+
const name = stringValue(manifest?.name) ?? String(pkg.name);
|
|
52
|
+
const publishTarget = stringValue(manifest?.publishTarget) ?? "npm";
|
|
53
|
+
const hostedVerifyWorkflow = stringValue(stringRecord(manifest?.releaseGate).workflow) ?? (existsSync(resolve(pkg.dir, ".github/workflows/deploy.yml")) ? "deploy.yml" : null);
|
|
54
|
+
const verifyLocal = typeof scripts["verify:local"] === "string" ? "verify:local" : typeof scripts.verify === "string" ? "verify" : typeof scripts["verify:action"] === "string" ? "verify:action" : null;
|
|
55
|
+
return {
|
|
56
|
+
id,
|
|
57
|
+
name,
|
|
58
|
+
kind: "node-typescript",
|
|
59
|
+
dir: pkg.dir,
|
|
60
|
+
relativeDir: pkg.relativeDir,
|
|
61
|
+
version: typeof pkg.packageJson?.version === "string" ? pkg.packageJson.version : null,
|
|
62
|
+
publishTarget,
|
|
63
|
+
manifestPath: treeseedPackageManifestPath(pkg.dir) ?? resolve(pkg.dir, "package.json"),
|
|
64
|
+
versionSource: resolve(pkg.dir, "package.json"),
|
|
65
|
+
verifyCommands: {
|
|
66
|
+
fast: commandFromScript(pkg.dir, manifestVerify.fast, "fast") ?? (typeof scripts.verify === "string" ? { label: "verify", command: "npm", args: ["run", "verify"], cwd: pkg.dir } : null),
|
|
67
|
+
local: commandFromScript(pkg.dir, manifestVerify.local, "local") ?? (verifyLocal ? { label: verifyLocal, command: "npm", args: ["run", verifyLocal], cwd: pkg.dir } : null),
|
|
68
|
+
release: commandFromScript(pkg.dir, manifestVerify.release, "release") ?? (typeof scripts["release:publish"] === "string" ? { label: "release:publish", command: "npm", args: ["run", "release:publish"], cwd: pkg.dir } : null)
|
|
69
|
+
},
|
|
70
|
+
artifacts: [{ provider: "npm", name: String(pkg.name) }],
|
|
71
|
+
releaseChecks: [
|
|
72
|
+
{ kind: "github-workflow", name: "publish workflow", detail: ".github/workflows/publish.yml" },
|
|
73
|
+
{ kind: "npm-pack-dry-run", name: "npm pack", detail: "npm pack --dry-run" }
|
|
74
|
+
],
|
|
75
|
+
metadata: {
|
|
76
|
+
...repository ? { repository } : {},
|
|
77
|
+
...hostedVerifyWorkflow ? {
|
|
78
|
+
hostedVerifyWorkflow: hostedVerifyWorkflow.startsWith(".github/workflows/") ? hostedVerifyWorkflow : `.github/workflows/${hostedVerifyWorkflow}`
|
|
79
|
+
} : {},
|
|
80
|
+
scripts
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
function treeseedPackageManifestPath(dir) {
|
|
85
|
+
for (const fileName of ["treeseed.package.yaml", "treeseed.package.yml", "treeseed.package.json", ".treeseed-package.json"]) {
|
|
86
|
+
const filePath = resolve(dir, fileName);
|
|
87
|
+
if (existsSync(filePath)) return filePath;
|
|
88
|
+
}
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
function readTreeseedPackageManifest(dir) {
|
|
92
|
+
const filePath = treeseedPackageManifestPath(dir);
|
|
93
|
+
return filePath ? readStructuredFile(filePath) : null;
|
|
94
|
+
}
|
|
95
|
+
function stringRecord(value) {
|
|
96
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
97
|
+
}
|
|
98
|
+
function stringValue(value) {
|
|
99
|
+
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
100
|
+
}
|
|
101
|
+
function stringArray(value) {
|
|
102
|
+
return Array.isArray(value) ? value.map((entry) => stringValue(entry)).filter((entry) => Boolean(entry)) : [];
|
|
103
|
+
}
|
|
104
|
+
function beamPackageAdapter(root, dir) {
|
|
105
|
+
const manifest = readTreeseedPackageManifest(dir);
|
|
106
|
+
const hasMixProject = existsSync(resolve(dir, "apps/api/mix.exs")) || existsSync(resolve(dir, "mix.exs"));
|
|
107
|
+
if (!manifest && !hasMixProject) return null;
|
|
108
|
+
const kind = typeof manifest?.kind === "string" ? manifest.kind : "beam-elixir-rust";
|
|
109
|
+
if (kind !== "beam-elixir-rust") return null;
|
|
110
|
+
const id = typeof manifest?.id === "string" && manifest.id.trim() ? manifest.id.trim() : relative(resolve(root, "packages"), dir).replaceAll("\\", "/");
|
|
111
|
+
const name = typeof manifest?.name === "string" && manifest.name.trim() ? manifest.name.trim() : id;
|
|
112
|
+
const versionSourceRel = typeof manifest?.versionSource === "string" && manifest.versionSource.trim() ? manifest.versionSource.trim() : existsSync(resolve(dir, "apps/api/mix.exs")) ? "apps/api/mix.exs" : "mix.exs";
|
|
113
|
+
const versionSource = resolve(dir, versionSourceRel);
|
|
114
|
+
const image = typeof manifest?.image === "string" && manifest.image.trim() ? manifest.image.trim() : id === "treedx" ? "treeseed/treedx" : null;
|
|
115
|
+
const repository = stringValue(manifest?.repository) ?? (id === "treedx" ? "treeseed-ai/treedx" : null);
|
|
116
|
+
const developmentImages = stringRecord(manifest?.developmentImages);
|
|
117
|
+
const developmentImageHosting = stringRecord(developmentImages.hosting);
|
|
118
|
+
const developmentImageWorkflow = image ? stringValue(developmentImages.workflow) ?? (id === "treedx" ? "dev-image.yml" : null) : null;
|
|
119
|
+
const hostedVerifyWorkflow = stringValue(stringRecord(manifest?.releaseGate).workflow) ?? (existsSync(resolve(dir, ".github/workflows/release-gate.yml")) ? "release-gate.yml" : null);
|
|
120
|
+
const developmentImageDefaultBranch = stringValue(developmentImages.defaultBranch) ?? "staging";
|
|
121
|
+
const developmentImageTagPrefix = stringValue(developmentImages.tagPrefix) ?? "dev";
|
|
122
|
+
const developmentImageMovingTag = developmentImages.movingTag === false ? false : true;
|
|
123
|
+
const developmentImageArchitectures = stringArray(developmentImages.architectures);
|
|
124
|
+
const verify = manifest?.verify && typeof manifest.verify === "object" && !Array.isArray(manifest.verify) ? manifest.verify : {};
|
|
125
|
+
const fast = verify.fast ?? (existsSync(resolve(dir, "scripts/test-treedx-fast.sh")) ? "scripts/test-treedx-fast.sh" : null);
|
|
126
|
+
const local = verify.local ?? (existsSync(resolve(dir, "scripts/test-all.sh")) ? "scripts/test-all.sh" : null);
|
|
127
|
+
const releaseGate = manifest?.releaseGate ?? verify.release ?? (existsSync(resolve(dir, "scripts/release-gate.sh")) ? "scripts/release-gate.sh" : null);
|
|
128
|
+
const version = readMixProjectVersion(versionSource);
|
|
129
|
+
const shaTag = "sha-<short-sha>";
|
|
130
|
+
return {
|
|
131
|
+
id,
|
|
132
|
+
name,
|
|
133
|
+
kind: "beam-elixir-rust",
|
|
134
|
+
dir,
|
|
135
|
+
relativeDir: relative(root, dir).replaceAll("\\", "/"),
|
|
136
|
+
version,
|
|
137
|
+
publishTarget: image,
|
|
138
|
+
manifestPath: treeseedPackageManifestPath(dir),
|
|
139
|
+
versionSource,
|
|
140
|
+
verifyCommands: {
|
|
141
|
+
fast: commandFromScript(dir, fast, "fast"),
|
|
142
|
+
local: commandFromScript(dir, local, "local"),
|
|
143
|
+
release: commandFromScript(dir, releaseGate, "release")
|
|
144
|
+
},
|
|
145
|
+
artifacts: image ? [{ provider: "docker", name: image, tags: version ? [version, shaTag] : [shaTag] }] : [],
|
|
146
|
+
releaseChecks: image ? [{ kind: "docker-manifest", name: "Docker image manifest", detail: `${image}:${version ?? "<version>"}` }] : [],
|
|
147
|
+
metadata: {
|
|
148
|
+
hasCargo: existsSync(resolve(dir, "Cargo.toml")),
|
|
149
|
+
hasDockerfile: existsSync(resolve(dir, "Dockerfile")),
|
|
150
|
+
repository,
|
|
151
|
+
versionSource: versionSourceRel,
|
|
152
|
+
...developmentImageWorkflow ? {
|
|
153
|
+
developmentImageWorkflow: developmentImageWorkflow.startsWith(".github/workflows/") ? developmentImageWorkflow : `.github/workflows/${developmentImageWorkflow}`,
|
|
154
|
+
developmentImageDefaultBranch,
|
|
155
|
+
developmentImageTagPrefix,
|
|
156
|
+
developmentImageMovingTag,
|
|
157
|
+
developmentImageArchitectures,
|
|
158
|
+
developmentImageTagPattern: `${image}:${developmentImageTagPrefix}-<branch-slug>-<short-sha>`,
|
|
159
|
+
developmentImageMovingTagPattern: developmentImageMovingTag ? `${image}:${developmentImageTagPrefix}-<branch-slug>` : null,
|
|
160
|
+
developmentImageHosting: Object.keys(developmentImageHosting).length > 0 ? developmentImageHosting : null
|
|
161
|
+
} : {},
|
|
162
|
+
...hostedVerifyWorkflow ? {
|
|
163
|
+
hostedVerifyWorkflow: hostedVerifyWorkflow.startsWith(".github/workflows/") ? hostedVerifyWorkflow : `.github/workflows/${hostedVerifyWorkflow}`
|
|
164
|
+
} : {}
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
function gitOutput(cwd, args) {
|
|
169
|
+
const result = spawnSync("git", args, { cwd, encoding: "utf8", stdio: "pipe" });
|
|
170
|
+
if (result.status !== 0) {
|
|
171
|
+
const stderr = typeof result.stderr === "string" ? result.stderr.trim() : "";
|
|
172
|
+
throw new Error(stderr || `git ${args.join(" ")} failed in ${cwd}.`);
|
|
173
|
+
}
|
|
174
|
+
return result.stdout.trim();
|
|
175
|
+
}
|
|
176
|
+
function branchSlug(value) {
|
|
177
|
+
const normalized = value.toLowerCase().replace(/[^a-z0-9]+/gu, "-").replace(/^-+|-+$/gu, "").slice(0, 40);
|
|
178
|
+
return normalized || "branch";
|
|
179
|
+
}
|
|
180
|
+
function planTreeseedPackageDevelopmentImage(root = workspaceRoot(), idOrName, { branch } = {}) {
|
|
181
|
+
const adapter = findTreeseedPackageAdapter(root, idOrName);
|
|
182
|
+
if (!adapter) {
|
|
183
|
+
throw new Error(`Treeseed package adapter ${idOrName} was not discovered.`);
|
|
184
|
+
}
|
|
185
|
+
const imageName = typeof adapter.publishTarget === "string" && adapter.publishTarget.trim() ? adapter.publishTarget.trim() : null;
|
|
186
|
+
if (!imageName) {
|
|
187
|
+
throw new Error(`${adapter.id} does not declare a publish image target.`);
|
|
188
|
+
}
|
|
189
|
+
const metadata = adapter.metadata;
|
|
190
|
+
const workflow = stringValue(metadata.developmentImageWorkflow)?.replace(/^\.github\/workflows\//u, "") ?? null;
|
|
191
|
+
if (!workflow) {
|
|
192
|
+
throw new Error(`${adapter.id} does not declare a development image workflow.`);
|
|
193
|
+
}
|
|
194
|
+
const selectedBranch = branch ?? stringValue(metadata.developmentImageDefaultBranch) ?? "staging";
|
|
195
|
+
const sha = gitOutput(adapter.dir, ["rev-parse", selectedBranch]);
|
|
196
|
+
const slug = branchSlug(selectedBranch);
|
|
197
|
+
const shortSha = sha.slice(0, 12);
|
|
198
|
+
const tagPrefix = stringValue(metadata.developmentImageTagPrefix) ?? "dev";
|
|
199
|
+
const immutableTag = `${tagPrefix}-${slug}-${shortSha}`;
|
|
200
|
+
const movingTag = metadata.developmentImageMovingTag === false ? null : `${tagPrefix}-${slug}`;
|
|
201
|
+
const architectures = stringArray(metadata.developmentImageArchitectures);
|
|
202
|
+
const hosting = stringRecord(metadata.developmentImageHosting);
|
|
203
|
+
const app = stringValue(hosting.app);
|
|
204
|
+
const environment = stringValue(hosting.environment) ?? selectedBranch;
|
|
205
|
+
const overrideEnvVar = stringValue(hosting.envVar);
|
|
206
|
+
const imageRef = `${imageName}:${immutableTag}`;
|
|
207
|
+
const movingImageRef = movingTag ? `${imageName}:${movingTag}` : null;
|
|
208
|
+
const hostingImageRef = movingImageRef ?? imageRef;
|
|
209
|
+
return {
|
|
210
|
+
package: {
|
|
211
|
+
id: adapter.id,
|
|
212
|
+
name: adapter.name,
|
|
213
|
+
path: adapter.relativeDir,
|
|
214
|
+
kind: adapter.kind,
|
|
215
|
+
version: adapter.version,
|
|
216
|
+
publishTarget: adapter.publishTarget,
|
|
217
|
+
metadata: adapter.metadata
|
|
218
|
+
},
|
|
219
|
+
repository: stringValue(metadata.repository) ?? `${adapter.id}`,
|
|
220
|
+
workflow,
|
|
221
|
+
branch: selectedBranch,
|
|
222
|
+
refs: {
|
|
223
|
+
imageName,
|
|
224
|
+
branch: selectedBranch,
|
|
225
|
+
branchSlug: slug,
|
|
226
|
+
sha,
|
|
227
|
+
shortSha,
|
|
228
|
+
immutableTag,
|
|
229
|
+
movingTag,
|
|
230
|
+
imageRef,
|
|
231
|
+
movingImageRef,
|
|
232
|
+
archImageRefs: architectures.map((arch) => `${imageName}:${immutableTag}-${arch}`)
|
|
233
|
+
},
|
|
234
|
+
hosting: app && overrideEnvVar ? {
|
|
235
|
+
app,
|
|
236
|
+
environment,
|
|
237
|
+
overrideEnvVar,
|
|
238
|
+
override: { [overrideEnvVar]: hostingImageRef },
|
|
239
|
+
command: `${overrideEnvVar}=${hostingImageRef} npx trsd hosting apply --environment ${environment} --app ${app} --execute --json`
|
|
240
|
+
} : null
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
function discoverTreeseedPackageAdapters(root = workspaceRoot()) {
|
|
244
|
+
const adapters = /* @__PURE__ */ new Map();
|
|
245
|
+
for (const pkg of workspacePackages(root)) {
|
|
246
|
+
if (typeof pkg.name === "string" && pkg.name.startsWith("@treeseed/")) {
|
|
247
|
+
adapters.set(pkg.name, nodeTypeScriptAdapter(pkg));
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
const packagesDir = resolve(root, "packages");
|
|
251
|
+
const packageDirs = existsSync(packagesDir) ? readdirSync(packagesDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => resolve(packagesDir, entry.name)) : [];
|
|
252
|
+
for (const dir of packageDirs) {
|
|
253
|
+
if (!existsSync(dir)) continue;
|
|
254
|
+
const adapter = beamPackageAdapter(root, dir);
|
|
255
|
+
if (adapter) adapters.set(adapter.id, adapter);
|
|
256
|
+
}
|
|
257
|
+
return [...adapters.values()].sort((left, right) => {
|
|
258
|
+
if (left.kind !== right.kind) return left.kind === "node-typescript" ? -1 : 1;
|
|
259
|
+
return left.id.localeCompare(right.id);
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
function findTreeseedPackageAdapter(root, idOrName) {
|
|
263
|
+
return discoverTreeseedPackageAdapters(root).find((adapter) => adapter.id === idOrName || adapter.name === idOrName) ?? null;
|
|
264
|
+
}
|
|
265
|
+
function packageAdapterPlanSummary(root = workspaceRoot()) {
|
|
266
|
+
return discoverTreeseedPackageAdapters(root).map((adapter) => ({
|
|
267
|
+
id: adapter.id,
|
|
268
|
+
name: adapter.name,
|
|
269
|
+
kind: adapter.kind,
|
|
270
|
+
path: adapter.relativeDir,
|
|
271
|
+
version: adapter.version,
|
|
272
|
+
publishTarget: adapter.publishTarget,
|
|
273
|
+
verify: Object.fromEntries(Object.entries(adapter.verifyCommands).map(([key, command]) => [
|
|
274
|
+
key,
|
|
275
|
+
command ? `${command.command} ${command.args.join(" ")}` : null
|
|
276
|
+
])),
|
|
277
|
+
artifacts: adapter.artifacts,
|
|
278
|
+
releaseChecks: adapter.releaseChecks,
|
|
279
|
+
metadata: adapter.metadata
|
|
280
|
+
}));
|
|
281
|
+
}
|
|
282
|
+
export {
|
|
283
|
+
discoverTreeseedPackageAdapters,
|
|
284
|
+
findTreeseedPackageAdapter,
|
|
285
|
+
packageAdapterPlanSummary,
|
|
286
|
+
planTreeseedPackageDevelopmentImage,
|
|
287
|
+
readMixProjectVersion
|
|
288
|
+
};
|
|
@@ -52,6 +52,7 @@ export declare function createPackageDependencyReference(input: {
|
|
|
52
52
|
gitDependencyProtocol?: GitDependencyProtocol;
|
|
53
53
|
}): PackageDependencyReference;
|
|
54
54
|
export declare function updateInternalDependencySpecs(packageJson: Record<string, unknown> | null, references: Map<string, PackageDependencyReference>): RewrittenDevReference[];
|
|
55
|
+
export declare function installableInternalDependencyVersions(root: any, versions: Map<string, string>): Map<string, string>;
|
|
55
56
|
export declare function rewriteInternalDependenciesToStableVersions(root: any, versions: Map<string, string>): (RewrittenDevReference & {
|
|
56
57
|
repoName: string;
|
|
57
58
|
packageJsonPath: string;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { resolve } from "node:path";
|
|
3
3
|
import { pathToFileURL } from "node:url";
|
|
4
|
+
import { discoverTreeseedPackageAdapters } from "./package-adapters.js";
|
|
4
5
|
import { run, workspacePackages, workspaceRoot } from "./workspace-tools.js";
|
|
5
6
|
const INTERNAL_DEPENDENCY_FIELDS = ["dependencies", "optionalDependencies", "peerDependencies", "devDependencies"];
|
|
6
7
|
function readJson(filePath) {
|
|
@@ -155,14 +156,24 @@ function updateInternalDependencySpecs(packageJson, references) {
|
|
|
155
156
|
}
|
|
156
157
|
return changed;
|
|
157
158
|
}
|
|
159
|
+
function installableInternalDependencyVersions(root = workspaceRoot(), versions) {
|
|
160
|
+
const publishTargets = /* @__PURE__ */ new Map();
|
|
161
|
+
for (const adapter of discoverTreeseedPackageAdapters(root)) {
|
|
162
|
+
const publishTarget = adapter.publishTarget ?? "npm";
|
|
163
|
+
publishTargets.set(adapter.id, publishTarget);
|
|
164
|
+
publishTargets.set(adapter.name, publishTarget);
|
|
165
|
+
}
|
|
166
|
+
return new Map([...versions.entries()].filter(([packageName]) => (publishTargets.get(packageName) ?? "npm") === "npm"));
|
|
167
|
+
}
|
|
158
168
|
function rewriteInternalDependenciesToStableVersions(root = workspaceRoot(), versions) {
|
|
159
169
|
const rewrites = [];
|
|
170
|
+
const installableVersions = installableInternalDependencyVersions(root, versions);
|
|
160
171
|
for (const pkg of workspacePackages(root)) {
|
|
161
172
|
const packageJsonPath = resolve(pkg.dir, "package.json");
|
|
162
173
|
const packageJson = readJson(packageJsonPath);
|
|
163
174
|
const changed = updateInternalDependencySpecs(
|
|
164
175
|
packageJson,
|
|
165
|
-
new Map([...
|
|
176
|
+
new Map([...installableVersions.entries()].map(([packageName, version]) => [packageName, {
|
|
166
177
|
packageName,
|
|
167
178
|
version,
|
|
168
179
|
spec: version,
|
|
@@ -185,6 +196,7 @@ function rewriteInternalDependenciesToStableVersions(root = workspaceRoot(), ver
|
|
|
185
196
|
}
|
|
186
197
|
function rewriteProjectInternalDependenciesToStableVersions(root = workspaceRoot(), versions) {
|
|
187
198
|
const rewrites = [];
|
|
199
|
+
const installableVersions = installableInternalDependencyVersions(root, versions);
|
|
188
200
|
const targets = [
|
|
189
201
|
{ name: "@treeseed/market", dir: root },
|
|
190
202
|
...workspacePackages(root).map((pkg) => ({ name: pkg.name, dir: pkg.dir }))
|
|
@@ -195,7 +207,7 @@ function rewriteProjectInternalDependenciesToStableVersions(root = workspaceRoot
|
|
|
195
207
|
const packageJson = readJson(packageJsonPath);
|
|
196
208
|
const changed = updateInternalDependencySpecs(
|
|
197
209
|
packageJson,
|
|
198
|
-
new Map([...
|
|
210
|
+
new Map([...installableVersions.entries()].map(([packageName, version]) => [packageName, {
|
|
199
211
|
packageName,
|
|
200
212
|
version,
|
|
201
213
|
spec: version,
|
|
@@ -458,6 +470,7 @@ export {
|
|
|
458
470
|
createPackageDependencyReference,
|
|
459
471
|
devTagFromDependencySpec,
|
|
460
472
|
gitTagMessage,
|
|
473
|
+
installableInternalDependencyVersions,
|
|
461
474
|
internalDependencyFields,
|
|
462
475
|
isGitDependencySpec,
|
|
463
476
|
isPrereleaseVersion,
|
|
@@ -273,6 +273,13 @@ export declare function deployProjectPlatform(options: ProjectPlatformActionOpti
|
|
|
273
273
|
cwd: any;
|
|
274
274
|
publicBaseUrl: any;
|
|
275
275
|
timings: TreeseedTimingEntry[];
|
|
276
|
+
transport: {
|
|
277
|
+
railway: {
|
|
278
|
+
reconcile: string;
|
|
279
|
+
deploy: string;
|
|
280
|
+
};
|
|
281
|
+
};
|
|
282
|
+
deploymentId?: undefined;
|
|
276
283
|
runtimeConfiguration?: undefined;
|
|
277
284
|
} | {
|
|
278
285
|
service: any;
|
|
@@ -281,19 +288,41 @@ export declare function deployProjectPlatform(options: ProjectPlatformActionOpti
|
|
|
281
288
|
cwd: any;
|
|
282
289
|
publicBaseUrl: any;
|
|
283
290
|
timings: TreeseedTimingEntry[];
|
|
291
|
+
deploymentId: any;
|
|
292
|
+
transport: {
|
|
293
|
+
railway: {
|
|
294
|
+
reconcile: string;
|
|
295
|
+
deploy: string;
|
|
296
|
+
};
|
|
297
|
+
};
|
|
298
|
+
runtimeConfiguration: {
|
|
299
|
+
updated: any;
|
|
300
|
+
healthcheckPath: any;
|
|
301
|
+
healthcheckTimeoutSeconds: any;
|
|
302
|
+
runtimeMode: any;
|
|
303
|
+
volume: any;
|
|
304
|
+
} | null;
|
|
305
|
+
} | {
|
|
306
|
+
service: any;
|
|
307
|
+
status: string;
|
|
308
|
+
command: string;
|
|
309
|
+
cwd: any;
|
|
310
|
+
publicBaseUrl: any;
|
|
311
|
+
timings: TreeseedTimingEntry[];
|
|
312
|
+
transport: {
|
|
313
|
+
railway: {
|
|
314
|
+
reconcile: string;
|
|
315
|
+
deploy: string;
|
|
316
|
+
};
|
|
317
|
+
};
|
|
284
318
|
runtimeConfiguration: {
|
|
285
|
-
updated:
|
|
286
|
-
healthcheckPath:
|
|
287
|
-
healthcheckTimeoutSeconds:
|
|
288
|
-
runtimeMode:
|
|
289
|
-
volume:
|
|
290
|
-
id: any;
|
|
291
|
-
name: any;
|
|
292
|
-
mountPath: any;
|
|
293
|
-
created: boolean;
|
|
294
|
-
updated: boolean;
|
|
295
|
-
} | null;
|
|
319
|
+
updated: any;
|
|
320
|
+
healthcheckPath: any;
|
|
321
|
+
healthcheckTimeoutSeconds: any;
|
|
322
|
+
runtimeMode: any;
|
|
323
|
+
volume: any;
|
|
296
324
|
} | null;
|
|
325
|
+
deploymentId?: undefined;
|
|
297
326
|
} | undefined)[];
|
|
298
327
|
timings: TreeseedTimingEntry[];
|
|
299
328
|
}>;
|
|
@@ -816,6 +845,13 @@ export declare function runProjectPlatformAction(action: ProjectPlatformAction,
|
|
|
816
845
|
cwd: any;
|
|
817
846
|
publicBaseUrl: any;
|
|
818
847
|
timings: TreeseedTimingEntry[];
|
|
848
|
+
transport: {
|
|
849
|
+
railway: {
|
|
850
|
+
reconcile: string;
|
|
851
|
+
deploy: string;
|
|
852
|
+
};
|
|
853
|
+
};
|
|
854
|
+
deploymentId?: undefined;
|
|
819
855
|
runtimeConfiguration?: undefined;
|
|
820
856
|
} | {
|
|
821
857
|
service: any;
|
|
@@ -824,19 +860,41 @@ export declare function runProjectPlatformAction(action: ProjectPlatformAction,
|
|
|
824
860
|
cwd: any;
|
|
825
861
|
publicBaseUrl: any;
|
|
826
862
|
timings: TreeseedTimingEntry[];
|
|
863
|
+
deploymentId: any;
|
|
864
|
+
transport: {
|
|
865
|
+
railway: {
|
|
866
|
+
reconcile: string;
|
|
867
|
+
deploy: string;
|
|
868
|
+
};
|
|
869
|
+
};
|
|
870
|
+
runtimeConfiguration: {
|
|
871
|
+
updated: any;
|
|
872
|
+
healthcheckPath: any;
|
|
873
|
+
healthcheckTimeoutSeconds: any;
|
|
874
|
+
runtimeMode: any;
|
|
875
|
+
volume: any;
|
|
876
|
+
} | null;
|
|
877
|
+
} | {
|
|
878
|
+
service: any;
|
|
879
|
+
status: string;
|
|
880
|
+
command: string;
|
|
881
|
+
cwd: any;
|
|
882
|
+
publicBaseUrl: any;
|
|
883
|
+
timings: TreeseedTimingEntry[];
|
|
884
|
+
transport: {
|
|
885
|
+
railway: {
|
|
886
|
+
reconcile: string;
|
|
887
|
+
deploy: string;
|
|
888
|
+
};
|
|
889
|
+
};
|
|
827
890
|
runtimeConfiguration: {
|
|
828
|
-
updated:
|
|
829
|
-
healthcheckPath:
|
|
830
|
-
healthcheckTimeoutSeconds:
|
|
831
|
-
runtimeMode:
|
|
832
|
-
volume:
|
|
833
|
-
id: any;
|
|
834
|
-
name: any;
|
|
835
|
-
mountPath: any;
|
|
836
|
-
created: boolean;
|
|
837
|
-
updated: boolean;
|
|
838
|
-
} | null;
|
|
891
|
+
updated: any;
|
|
892
|
+
healthcheckPath: any;
|
|
893
|
+
healthcheckTimeoutSeconds: any;
|
|
894
|
+
runtimeMode: any;
|
|
895
|
+
volume: any;
|
|
839
896
|
} | null;
|
|
897
|
+
deploymentId?: undefined;
|
|
840
898
|
} | undefined)[];
|
|
841
899
|
timings: TreeseedTimingEntry[];
|
|
842
900
|
}>;
|
|
@@ -48,7 +48,7 @@ import { CloudflareQueuePullClient, CloudflareQueuePushClient } from "../../remo
|
|
|
48
48
|
import { runPrefixedCommand, runTreeseedBootstrapDag, sleep, writeTreeseedBootstrapLine } from "./bootstrap-runner.js";
|
|
49
49
|
import { runTenantDeployPreflight } from "./save-deploy-preflight.js";
|
|
50
50
|
const PROJECT_PLATFORM_BOOTSTRAP_SYSTEMS = ["data", "web", "api", "agents"];
|
|
51
|
-
const WEB_PLATFORM_BOOTSTRAP_SYSTEMS =
|
|
51
|
+
const WEB_PLATFORM_BOOTSTRAP_SYSTEMS = ["data", "web"];
|
|
52
52
|
const PROCESSING_PLATFORM_BOOTSTRAP_SYSTEMS = ["api", "agents"];
|
|
53
53
|
function stableHash(value) {
|
|
54
54
|
return createHash("sha256").update(value).digest("hex");
|
|
@@ -63,6 +63,13 @@ function recordTiming(timings, name, startMs, status = "success", metadata) {
|
|
|
63
63
|
timings.push(entry);
|
|
64
64
|
return entry;
|
|
65
65
|
}
|
|
66
|
+
function writeWorkflowStatus(message) {
|
|
67
|
+
if (!process.env.TREESEED_WORKFLOW_ACTION && !process.env.TREESEED_WORKFLOW_DEBUG) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
process.stderr.write(`[project-platform] ${message}
|
|
71
|
+
`);
|
|
72
|
+
}
|
|
66
73
|
async function timedPhase(timings, name, run, metadata) {
|
|
67
74
|
const startMs = performance.now();
|
|
68
75
|
try {
|
|
@@ -658,10 +665,14 @@ function findFirstMatchingString(value, matcher, seen = /* @__PURE__ */ new Set(
|
|
|
658
665
|
return null;
|
|
659
666
|
}
|
|
660
667
|
function resolveImmediatePagesProbeUrl(siteConfig, state, target) {
|
|
668
|
+
const configuredUrl = resolveConfiguredSurfaceBaseUrl(siteConfig, target, "web");
|
|
669
|
+
if (configuredUrl) {
|
|
670
|
+
return configuredUrl;
|
|
671
|
+
}
|
|
661
672
|
if (target.kind === "persistent" && target.scope === "staging" && state.pages?.projectName) {
|
|
662
673
|
return `https://${state.pages?.stagingBranch ?? "staging"}.${state.pages.projectName}.pages.dev`;
|
|
663
674
|
}
|
|
664
|
-
return state.pages?.url ??
|
|
675
|
+
return state.pages?.url ?? siteConfig.siteUrl;
|
|
665
676
|
}
|
|
666
677
|
function resolveImmediateApiProbeUrl(siteConfig, state, target) {
|
|
667
678
|
const configuredUrl = resolveConfiguredSurfaceBaseUrl(siteConfig, target, "api") ?? siteConfig.services?.api?.environments?.[target.kind === "persistent" ? target.scope : "prod"]?.baseUrl ?? siteConfig.services?.api?.publicBaseUrl ?? process.env.TREESEED_API_BASE_URL ?? state.services?.api?.lastDeployedUrl ?? null;
|
|
@@ -801,8 +812,8 @@ function probeR2(tenantRoot, siteConfig, state, target) {
|
|
|
801
812
|
function probeScaleConfiguration(siteConfig, state) {
|
|
802
813
|
const worker = state.services?.workerRunner ?? state.services?.worker ?? {};
|
|
803
814
|
const workerConfig = siteConfig.services?.workerRunner ?? siteConfig.services?.worker ?? {};
|
|
804
|
-
const marketRunner = state.services?.
|
|
805
|
-
const marketRunnerConfig = siteConfig.services?.
|
|
815
|
+
const marketRunner = state.services?.operationsRunner ?? {};
|
|
816
|
+
const marketRunnerConfig = siteConfig.services?.operationsRunner ?? {};
|
|
806
817
|
const scalerKind = String(process.env.TREESEED_WORKER_POOL_SCALER ?? "").trim();
|
|
807
818
|
if (marketRunnerConfig.provider === "railway" && workerConfig.provider !== "railway") {
|
|
808
819
|
const runnerServiceId = marketRunner.serviceId ?? null;
|
|
@@ -1058,30 +1069,46 @@ async function publishContent(options, reporter, publishOptions = {}) {
|
|
|
1058
1069
|
}
|
|
1059
1070
|
}
|
|
1060
1071
|
async function provisionProjectPlatform(options) {
|
|
1072
|
+
writeWorkflowStatus(`provision:start scope=${options.scope}`);
|
|
1061
1073
|
const timings = [];
|
|
1074
|
+
writeWorkflowStatus("provision:resolve-reporter");
|
|
1062
1075
|
const reporter = resolveReporter(options.tenantRoot, options.reporter);
|
|
1076
|
+
writeWorkflowStatus(`provision:reporter kind=${reporter.kind} enabled=${reporter.enabled ? "true" : "false"}`);
|
|
1063
1077
|
const target = createPersistentDeployTarget(options.scope === "local" ? "staging" : options.scope);
|
|
1078
|
+
writeWorkflowStatus(`provision:target ${deployTargetLabel(target)}`);
|
|
1064
1079
|
const siteConfig = loadCliDeployConfig(options.tenantRoot);
|
|
1080
|
+
writeWorkflowStatus("provision:resolve-bootstrap-systems");
|
|
1065
1081
|
const bootstrapSystems = resolveProjectPlatformBootstrapSystems(options, siteConfig);
|
|
1066
1082
|
const selectedSystems = new Set(bootstrapSystems);
|
|
1067
1083
|
const env = { ...process.env, ...options.env ?? {} };
|
|
1084
|
+
writeWorkflowStatus(`provision:reconcile:start systems=${bootstrapSystems.join(",") || "(none)"}`);
|
|
1068
1085
|
const summary = await timedPhase(timings, "provision:reconcile", () => reconcileTreeseedTarget({
|
|
1069
1086
|
tenantRoot: options.tenantRoot,
|
|
1070
1087
|
target,
|
|
1071
1088
|
env,
|
|
1072
1089
|
systems: bootstrapSystems,
|
|
1073
|
-
write: options.write
|
|
1090
|
+
write: options.write,
|
|
1091
|
+
dryRun: options.dryRun
|
|
1074
1092
|
}));
|
|
1093
|
+
writeWorkflowStatus("provision:reconcile:done");
|
|
1075
1094
|
timings.push(...summary.timings ?? []);
|
|
1095
|
+
writeWorkflowStatus("provision:collect-reconcile-status:start");
|
|
1076
1096
|
const verification = await timedPhase(timings, "provision:collect-reconcile-status", () => collectTreeseedReconcileStatus({
|
|
1077
1097
|
tenantRoot: options.tenantRoot,
|
|
1078
1098
|
target,
|
|
1079
1099
|
env,
|
|
1080
1100
|
systems: bootstrapSystems
|
|
1081
1101
|
}));
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1102
|
+
writeWorkflowStatus("provision:collect-reconcile-status:done");
|
|
1103
|
+
if (selectedSystems.has("data") || selectedSystems.has("web")) {
|
|
1104
|
+
writeWorkflowStatus("provision:ensure-wrangler-config:start");
|
|
1105
|
+
await timedPhase(timings, "provision:ensure-wrangler-config", () => {
|
|
1106
|
+
ensureGeneratedWranglerConfig(options.tenantRoot, { target });
|
|
1107
|
+
});
|
|
1108
|
+
writeWorkflowStatus("provision:ensure-wrangler-config:done");
|
|
1109
|
+
} else {
|
|
1110
|
+
writeWorkflowStatus("provision:ensure-wrangler-config:skipped");
|
|
1111
|
+
}
|
|
1085
1112
|
const shouldValidateRailway = selectedSystems.has("api") || selectedSystems.has("agents");
|
|
1086
1113
|
const railwayValidation = shouldValidateRailway ? options.scope === "local" ? validateRailwayServiceConfiguration(options.tenantRoot, options.scope) : validateRailwayDeployPrerequisites(options.tenantRoot, options.scope, { env }) : { services: [] };
|
|
1087
1114
|
const railwaySchedules = [];
|
|
@@ -1239,16 +1266,22 @@ async function provisionProjectPlatform(options) {
|
|
|
1239
1266
|
};
|
|
1240
1267
|
}
|
|
1241
1268
|
async function deployProjectPlatform(options) {
|
|
1269
|
+
writeWorkflowStatus(`deploy:start scope=${options.scope} dryRun=${options.dryRun ? "true" : "false"}`);
|
|
1242
1270
|
const timings = [];
|
|
1243
1271
|
const deployStartMs = performance.now();
|
|
1272
|
+
writeWorkflowStatus("deploy:resolve-reporter");
|
|
1244
1273
|
const reporter = resolveReporter(options.tenantRoot, options.reporter);
|
|
1274
|
+
writeWorkflowStatus(`deploy:reporter kind=${reporter.kind} enabled=${reporter.enabled ? "true" : "false"}`);
|
|
1245
1275
|
const commitSha = currentCommit(options.tenantRoot);
|
|
1246
1276
|
const branchName = currentRef(options.tenantRoot);
|
|
1277
|
+
writeWorkflowStatus("deploy:resolve-bootstrap-systems");
|
|
1247
1278
|
const bootstrapSystems = resolveProjectPlatformBootstrapSystems(options);
|
|
1248
1279
|
const selectedSystems = new Set(bootstrapSystems);
|
|
1249
1280
|
const execution = options.bootstrapExecution ?? "parallel";
|
|
1250
1281
|
const write = options.write;
|
|
1251
1282
|
const env = { ...process.env, ...options.env ?? {} };
|
|
1283
|
+
writeWorkflowStatus(`deploy:bootstrap-systems ${bootstrapSystems.join(",") || "(none)"}`);
|
|
1284
|
+
writeWorkflowStatus("deploy:report-running");
|
|
1252
1285
|
await reportDeployment(reporter, {
|
|
1253
1286
|
environment: options.scope,
|
|
1254
1287
|
deploymentKind: "code",
|
|
@@ -1258,9 +1291,12 @@ async function deployProjectPlatform(options) {
|
|
|
1258
1291
|
triggeredByType: "project_runner",
|
|
1259
1292
|
metadata: { scope: options.scope }
|
|
1260
1293
|
});
|
|
1294
|
+
writeWorkflowStatus("deploy:reported-running");
|
|
1261
1295
|
if (!options.skipProvision) {
|
|
1296
|
+
writeWorkflowStatus("deploy:provision:start");
|
|
1262
1297
|
const provision = await timedPhase(timings, "deploy:provision", () => provisionProjectPlatform({ ...options, reporter, bootstrapSystems }));
|
|
1263
1298
|
timings.push(...provision.timings ?? []);
|
|
1299
|
+
writeWorkflowStatus("deploy:provision:done");
|
|
1264
1300
|
}
|
|
1265
1301
|
const nodes = [];
|
|
1266
1302
|
let cloudflareContext = null;
|
|
@@ -1565,8 +1601,13 @@ async function runProjectPlatformAction(action, options) {
|
|
|
1565
1601
|
const previousWorkflowPlane = process.env.TREESEED_WORKFLOW_PLANE;
|
|
1566
1602
|
process.env.TREESEED_WORKFLOW_ACTION = action;
|
|
1567
1603
|
process.env.TREESEED_WORKFLOW_PLANE = previousWorkflowPlane ?? "all";
|
|
1604
|
+
writeWorkflowStatus(`action:start ${action} scope=${options.scope}`);
|
|
1605
|
+
writeWorkflowStatus("action:apply-environment:start");
|
|
1568
1606
|
applyTreeseedEnvironmentToProcess({ tenantRoot: options.tenantRoot, scope: options.scope, override: true });
|
|
1607
|
+
writeWorkflowStatus("action:apply-environment:done");
|
|
1608
|
+
writeWorkflowStatus("action:resolve-reporter:start");
|
|
1569
1609
|
const reporter = resolveReporter(options.tenantRoot, options.reporter);
|
|
1610
|
+
writeWorkflowStatus(`action:resolve-reporter:done kind=${reporter.kind} enabled=${reporter.enabled ? "true" : "false"}`);
|
|
1570
1611
|
try {
|
|
1571
1612
|
switch (action) {
|
|
1572
1613
|
case "deploy_web":
|