@treeseed/sdk 0.10.27 → 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 +11 -4
- package/dist/index.js +71 -7
- 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/template-registry.js +14 -7
- 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/template-catalog.test.js +7 -7
- package/dist/scripts/tenant-workflow-action.js +10 -1
- package/dist/sdk-types.d.ts +172 -5
- package/dist/sdk-types.js +28 -3
- 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 +497 -138
- 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
- package/dist/treeseed/template-catalog/templates/starter-basic/template/astro.config.d.ts +0 -3
- package/dist/treeseed/template-catalog/templates/starter-basic/template/astro.config.ts +0 -6
- package/dist/treeseed/template-catalog/templates/starter-basic/template/package.json +0 -35
- package/dist/treeseed/template-catalog/templates/starter-basic/template/src/api/server.js +0 -4
- package/dist/treeseed/template-catalog/templates/starter-basic/template/src/config.yaml +0 -65
- package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content/decisions/adopt-initial-proposal-loop.mdx +0 -22
- package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content/empty/.gitkeep +0 -1
- package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content/knowledge/handbook/index.mdx +0 -11
- package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content/pages/welcome.mdx +0 -11
- package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content/people/starter-steward.mdx +0 -11
- package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content/proposals/establish-initial-proposal-loop.mdx +0 -17
- package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content.config.d.ts +0 -1
- package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content.config.ts +0 -3
- package/dist/treeseed/template-catalog/templates/starter-basic/template/src/env.yaml +0 -1
- package/dist/treeseed/template-catalog/templates/starter-basic/template/src/manifest.yaml +0 -26
- package/dist/treeseed/template-catalog/templates/starter-basic/template/treeseed.site.yaml +0 -74
- package/dist/treeseed/template-catalog/templates/starter-basic/template/tsconfig.json +0 -9
- package/dist/treeseed/template-catalog/templates/starter-basic/template.config.json +0 -103
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { TreeseedDeployConfig } from '../platform/contracts.ts';
|
|
2
2
|
export type TreeseedReconcileProviderId = string;
|
|
3
|
-
export type TreeseedReconcileActionKind = 'noop' | 'create' | 'update' | '
|
|
3
|
+
export type TreeseedReconcileActionKind = 'noop' | 'create' | 'update' | 'replace' | 'delete' | 'adopt' | 'rename' | 'reattach' | 'retain' | 'taint' | 'blocked';
|
|
4
4
|
export type TreeseedReconcileStatusKind = 'pending' | 'ready' | 'drifted' | 'error';
|
|
5
5
|
export type TreeseedReconcileVerificationSource = 'cli' | 'api' | 'sdk' | 'derived';
|
|
6
|
-
export type TreeseedReconcileUnitType = 'web-ui' | 'api-runtime' | '
|
|
6
|
+
export type TreeseedReconcileUnitType = 'web-ui' | 'api-runtime' | 'operations-runner-runtime' | 'workday-manager-runtime' | 'worker-runner-runtime' | 'edge-worker' | 'content-store' | 'queue' | 'database' | 'kv-form-guard' | 'turnstile-widget' | 'pages-project' | 'custom-domain:web' | 'custom-domain:api' | 'dns-record' | 'railway-service:api' | 'railway-service:operations-runner' | 'railway-service:workday-manager' | 'railway-service:worker-runner';
|
|
7
7
|
export type TreeseedReconcileTarget = {
|
|
8
8
|
kind: 'persistent';
|
|
9
9
|
scope: 'local' | 'staging' | 'prod';
|
|
@@ -115,6 +115,7 @@ export interface TreeseedReconcileRunContext {
|
|
|
115
115
|
target: TreeseedReconcileTarget;
|
|
116
116
|
deployConfig: TreeseedDeployConfig;
|
|
117
117
|
launchEnv: NodeJS.ProcessEnv;
|
|
118
|
+
dryRun?: boolean;
|
|
118
119
|
write?: (line: string) => void;
|
|
119
120
|
session: Map<string, unknown>;
|
|
120
121
|
}
|
|
@@ -129,11 +130,11 @@ export interface TreeseedReconcileAdapter {
|
|
|
129
130
|
supports(unitType: TreeseedReconcileUnitType, providerId: TreeseedReconcileProviderId): boolean;
|
|
130
131
|
validate?(input: TreeseedReconcileAdapterInput): Promise<void> | void;
|
|
131
132
|
requiredPostconditions?(input: TreeseedReconcileAdapterInput): Promise<TreeseedUnitPostcondition[]> | TreeseedUnitPostcondition[];
|
|
132
|
-
|
|
133
|
-
|
|
133
|
+
refresh(input: TreeseedReconcileAdapterInput): Promise<TreeseedObservedUnitState> | TreeseedObservedUnitState;
|
|
134
|
+
diff(input: TreeseedReconcileAdapterInput & {
|
|
134
135
|
observed: TreeseedObservedUnitState;
|
|
135
136
|
}): Promise<TreeseedUnitDiff> | TreeseedUnitDiff;
|
|
136
|
-
|
|
137
|
+
apply(input: TreeseedReconcileAdapterInput & {
|
|
137
138
|
observed: TreeseedObservedUnitState;
|
|
138
139
|
diff: TreeseedUnitDiff;
|
|
139
140
|
}): Promise<TreeseedReconcileResult> | TreeseedReconcileResult;
|
|
@@ -146,6 +147,9 @@ export interface TreeseedReconcileAdapter {
|
|
|
146
147
|
destroy?(input: TreeseedReconcileAdapterInput & {
|
|
147
148
|
observed: TreeseedObservedUnitState;
|
|
148
149
|
}): Promise<TreeseedReconcileResult> | TreeseedReconcileResult;
|
|
150
|
+
importOrAdopt?(input: TreeseedReconcileAdapterInput & {
|
|
151
|
+
observed: TreeseedObservedUnitState;
|
|
152
|
+
}): Promise<TreeseedReconcileResult> | TreeseedReconcileResult;
|
|
149
153
|
}
|
|
150
154
|
export interface TreeseedReconcileStateRecord {
|
|
151
155
|
version: 1;
|
|
@@ -38,6 +38,7 @@ export declare function deriveTreeseedDesiredUnits({ tenantRoot, target, }: {
|
|
|
38
38
|
previewProjectName: string | undefined;
|
|
39
39
|
productionBranch: string;
|
|
40
40
|
stagingBranch: string;
|
|
41
|
+
buildCommand: string | undefined;
|
|
41
42
|
buildOutputDir: string | undefined;
|
|
42
43
|
} | undefined;
|
|
43
44
|
r2: {
|
|
@@ -11,8 +11,8 @@ function railwayConcreteUnitTypeForServiceKey(serviceKey) {
|
|
|
11
11
|
switch (serviceKey) {
|
|
12
12
|
case "api":
|
|
13
13
|
return "railway-service:api";
|
|
14
|
-
case "
|
|
15
|
-
return "railway-service:
|
|
14
|
+
case "operationsRunner":
|
|
15
|
+
return "railway-service:operations-runner";
|
|
16
16
|
case "workdayManager":
|
|
17
17
|
return "railway-service:workday-manager";
|
|
18
18
|
case "workerRunner":
|
|
@@ -204,7 +204,7 @@ function deriveTreeseedDesiredUnits({
|
|
|
204
204
|
const scope = target.kind === "persistent" ? target.scope : "staging";
|
|
205
205
|
for (const configuredService of configuredRailwayServices(tenantRoot, scope)) {
|
|
206
206
|
const serviceKey = configuredService.key;
|
|
207
|
-
const service = deployConfig.services?.[serviceKey];
|
|
207
|
+
const service = configuredService.serviceConfig ?? deployConfig.services?.[serviceKey];
|
|
208
208
|
const serviceState = legacyState.services?.[serviceKey];
|
|
209
209
|
if (!service || service.enabled === false || service.provider !== "railway") {
|
|
210
210
|
continue;
|
|
@@ -284,8 +284,8 @@ function deriveTreeseedDesiredUnits({
|
|
|
284
284
|
switch (serviceKey) {
|
|
285
285
|
case "api":
|
|
286
286
|
return "api-runtime";
|
|
287
|
-
case "
|
|
288
|
-
return "
|
|
287
|
+
case "operationsRunner":
|
|
288
|
+
return "operations-runner-runtime";
|
|
289
289
|
case "workdayManager":
|
|
290
290
|
return "workday-manager-runtime";
|
|
291
291
|
case "workerRunner":
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { TreeseedObservedUnitState, TreeseedReconcilePlan, TreeseedReconcileResult, TreeseedReconcileStateRecord, TreeseedReconcileTarget, TreeseedUnitVerificationResult } from './contracts.ts';
|
|
2
2
|
import { type TreeseedRunnableBootstrapSystem } from './bootstrap-systems.ts';
|
|
3
3
|
import { type TreeseedTimingEntry } from '../timing.ts';
|
|
4
|
-
export declare function
|
|
4
|
+
export declare function refreshTreeseedUnits({ tenantRoot, target, env, systems, write, }: {
|
|
5
5
|
tenantRoot: string;
|
|
6
6
|
target: TreeseedReconcileTarget;
|
|
7
7
|
env?: NodeJS.ProcessEnv;
|
|
@@ -46,6 +46,7 @@ export declare function observeTreeseedUnits({ tenantRoot, target, env, systems,
|
|
|
46
46
|
previewProjectName: string | undefined;
|
|
47
47
|
productionBranch: string;
|
|
48
48
|
stagingBranch: string;
|
|
49
|
+
buildCommand: string | undefined;
|
|
49
50
|
buildOutputDir: string | undefined;
|
|
50
51
|
} | undefined;
|
|
51
52
|
r2: {
|
|
@@ -249,6 +250,7 @@ export declare function planTreeseedReconciliation({ tenantRoot, target, env, sy
|
|
|
249
250
|
previewProjectName: string | undefined;
|
|
250
251
|
productionBranch: string;
|
|
251
252
|
stagingBranch: string;
|
|
253
|
+
buildCommand: string | undefined;
|
|
252
254
|
buildOutputDir: string | undefined;
|
|
253
255
|
} | undefined;
|
|
254
256
|
r2: {
|
|
@@ -406,12 +408,13 @@ export declare function planTreeseedReconciliation({ tenantRoot, target, env, sy
|
|
|
406
408
|
};
|
|
407
409
|
};
|
|
408
410
|
}>;
|
|
409
|
-
export declare function reconcileTreeseedTarget({ tenantRoot, target, env, systems, write, }: {
|
|
411
|
+
export declare function reconcileTreeseedTarget({ tenantRoot, target, env, systems, write, dryRun, }: {
|
|
410
412
|
tenantRoot: string;
|
|
411
413
|
target: TreeseedReconcileTarget;
|
|
412
414
|
env?: NodeJS.ProcessEnv;
|
|
413
415
|
systems?: TreeseedRunnableBootstrapSystem[];
|
|
414
416
|
write?: (line: string) => void;
|
|
417
|
+
dryRun?: boolean;
|
|
415
418
|
}): Promise<{
|
|
416
419
|
target: TreeseedReconcileTarget;
|
|
417
420
|
units: import("./contracts.ts").TreeseedDesiredUnit[];
|
package/dist/reconcile/engine.js
CHANGED
|
@@ -26,13 +26,14 @@ function formatVerificationFailure(verification) {
|
|
|
26
26
|
].filter(Boolean);
|
|
27
27
|
return details.length > 0 ? `Verification failed (${details.join(" | ")})` : "Verification failed.";
|
|
28
28
|
}
|
|
29
|
-
function createRunContext(tenantRoot, target, launchEnv, write) {
|
|
29
|
+
function createRunContext(tenantRoot, target, launchEnv, write, dryRun = false) {
|
|
30
30
|
const { deployConfig } = deriveTreeseedDesiredUnits({ tenantRoot, target });
|
|
31
31
|
return {
|
|
32
32
|
tenantRoot,
|
|
33
33
|
target,
|
|
34
34
|
deployConfig,
|
|
35
35
|
launchEnv,
|
|
36
|
+
dryRun,
|
|
36
37
|
write,
|
|
37
38
|
session: /* @__PURE__ */ new Map()
|
|
38
39
|
};
|
|
@@ -123,7 +124,7 @@ async function verifyPlanUnits({
|
|
|
123
124
|
}
|
|
124
125
|
return verificationResults;
|
|
125
126
|
}
|
|
126
|
-
async function
|
|
127
|
+
async function refreshTreeseedUnits({
|
|
127
128
|
tenantRoot,
|
|
128
129
|
target,
|
|
129
130
|
env = process.env,
|
|
@@ -138,18 +139,18 @@ async function observeTreeseedUnits({
|
|
|
138
139
|
const context = createRunContext(tenantRoot, target, env, write);
|
|
139
140
|
const observations = /* @__PURE__ */ new Map();
|
|
140
141
|
await runByDependencyLevel(topologicallySortDesiredUnits(units), async (unit) => {
|
|
141
|
-
write?.(`
|
|
142
|
+
write?.(`Refreshing ${unit.provider}:${unit.unitType}...`);
|
|
142
143
|
const adapter = registry.get(unit.unitType, unit.provider);
|
|
143
144
|
const persisted = ensureTreeseedPersistedUnitState(reconcileState, unit);
|
|
144
145
|
let observed;
|
|
145
146
|
try {
|
|
146
|
-
observed = await Promise.resolve(adapter.
|
|
147
|
+
observed = await Promise.resolve(adapter.refresh({
|
|
147
148
|
context,
|
|
148
149
|
unit,
|
|
149
150
|
persistedState: persisted
|
|
150
151
|
}));
|
|
151
152
|
} catch (error) {
|
|
152
|
-
wrapAdapterFailure("
|
|
153
|
+
wrapAdapterFailure("refresh", unit.provider, unit.unitType, unit.unitId, error);
|
|
153
154
|
}
|
|
154
155
|
observations.set(unit.unitId, observed);
|
|
155
156
|
});
|
|
@@ -167,7 +168,7 @@ async function planTreeseedReconciliation({
|
|
|
167
168
|
systems,
|
|
168
169
|
write
|
|
169
170
|
}) {
|
|
170
|
-
const observed = await
|
|
171
|
+
const observed = await refreshTreeseedUnits({ tenantRoot, target, env, systems, write });
|
|
171
172
|
const registry = createTreeseedReconcileRegistry(observed.deployConfig);
|
|
172
173
|
const context = createRunContext(tenantRoot, target, env, write);
|
|
173
174
|
const plans = [];
|
|
@@ -177,14 +178,14 @@ async function planTreeseedReconciliation({
|
|
|
177
178
|
const observation = observed.observations.get(unit.unitId);
|
|
178
179
|
let diff;
|
|
179
180
|
try {
|
|
180
|
-
diff = await Promise.resolve(adapter.
|
|
181
|
+
diff = await Promise.resolve(adapter.diff({
|
|
181
182
|
context,
|
|
182
183
|
unit,
|
|
183
184
|
persistedState: persisted,
|
|
184
185
|
observed: observation
|
|
185
186
|
}));
|
|
186
187
|
} catch (error) {
|
|
187
|
-
wrapAdapterFailure("
|
|
188
|
+
wrapAdapterFailure("diff", unit.provider, unit.unitType, unit.unitId, error);
|
|
188
189
|
}
|
|
189
190
|
plans.push({
|
|
190
191
|
unit,
|
|
@@ -203,11 +204,12 @@ async function reconcileTreeseedTarget({
|
|
|
203
204
|
target,
|
|
204
205
|
env = process.env,
|
|
205
206
|
systems,
|
|
206
|
-
write
|
|
207
|
+
write,
|
|
208
|
+
dryRun = false
|
|
207
209
|
}) {
|
|
208
210
|
const planned = await planTreeseedReconciliation({ tenantRoot, target, env, systems, write });
|
|
209
211
|
const registry = createTreeseedReconcileRegistry(planned.deployConfig);
|
|
210
|
-
const context = createRunContext(tenantRoot, target, env, write);
|
|
212
|
+
const context = createRunContext(tenantRoot, target, env, write, dryRun);
|
|
211
213
|
const results = [];
|
|
212
214
|
const verificationMap = /* @__PURE__ */ new Map();
|
|
213
215
|
const timingEntries = [];
|
|
@@ -225,7 +227,7 @@ async function reconcileTreeseedTarget({
|
|
|
225
227
|
await runByDependencyLevel(topologicallySortDesiredUnits(planned.units), async (unit) => {
|
|
226
228
|
const plan = planByUnitId.get(unit.unitId);
|
|
227
229
|
const unitTiming = {
|
|
228
|
-
name: `
|
|
230
|
+
name: `apply:${plan.unit.provider}:${plan.unit.unitType}:${plan.unit.logicalName}`,
|
|
229
231
|
durationMs: 0,
|
|
230
232
|
status: "running",
|
|
231
233
|
children: [],
|
|
@@ -233,7 +235,7 @@ async function reconcileTreeseedTarget({
|
|
|
233
235
|
};
|
|
234
236
|
const unitStartMs = performance.now();
|
|
235
237
|
timingEntries.push(unitTiming);
|
|
236
|
-
write?.(`
|
|
238
|
+
write?.(`Applying ${plan.unit.provider}:${plan.unit.unitType} (${plan.unit.logicalName})...`);
|
|
237
239
|
const adapter = registry.get(plan.unit.unitType, plan.unit.provider);
|
|
238
240
|
const persisted = ensureTreeseedPersistedUnitState(planned.state, plan.unit);
|
|
239
241
|
try {
|
|
@@ -261,27 +263,40 @@ async function reconcileTreeseedTarget({
|
|
|
261
263
|
let result;
|
|
262
264
|
try {
|
|
263
265
|
const stageStartMs = performance.now();
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
266
|
+
if (dryRun) {
|
|
267
|
+
result = {
|
|
268
|
+
unit: plan.unit,
|
|
269
|
+
observed: plan.observed,
|
|
270
|
+
diff: plan.diff,
|
|
271
|
+
action: plan.diff.action,
|
|
272
|
+
warnings: [...plan.observed.warnings, "dry run: apply skipped"],
|
|
273
|
+
resourceLocators: plan.observed.locators,
|
|
274
|
+
state: plan.observed.live,
|
|
275
|
+
verification: null
|
|
276
|
+
};
|
|
277
|
+
} else {
|
|
278
|
+
result = await Promise.resolve(adapter.apply({
|
|
279
|
+
context,
|
|
280
|
+
unit: plan.unit,
|
|
281
|
+
persistedState: persisted,
|
|
282
|
+
observed: plan.observed,
|
|
283
|
+
diff: plan.diff
|
|
284
|
+
}));
|
|
285
|
+
}
|
|
271
286
|
unitTiming.children?.push({
|
|
272
|
-
name: `${unitTiming.name}:
|
|
287
|
+
name: `${unitTiming.name}:apply`,
|
|
273
288
|
durationMs: elapsedMs(stageStartMs),
|
|
274
|
-
status: "success"
|
|
289
|
+
status: dryRun ? "skipped" : "success"
|
|
275
290
|
});
|
|
276
291
|
} catch (error) {
|
|
277
292
|
unitTiming.children?.push({
|
|
278
|
-
name: `${unitTiming.name}:
|
|
293
|
+
name: `${unitTiming.name}:apply`,
|
|
279
294
|
durationMs: elapsedMs(unitStartMs),
|
|
280
295
|
status: "failed"
|
|
281
296
|
});
|
|
282
297
|
unitTiming.durationMs = elapsedMs(unitStartMs);
|
|
283
298
|
unitTiming.status = "failed";
|
|
284
|
-
wrapAdapterFailure("
|
|
299
|
+
wrapAdapterFailure("apply", plan.unit.provider, plan.unit.unitType, plan.unit.unitId, error);
|
|
285
300
|
}
|
|
286
301
|
write?.(`Verifying ${plan.unit.provider}:${plan.unit.unitType} (${plan.unit.logicalName})...`);
|
|
287
302
|
const postconditions = await Promise.resolve(adapter.requiredPostconditions?.({
|
|
@@ -329,13 +344,19 @@ async function reconcileTreeseedTarget({
|
|
|
329
344
|
unitTiming.status = verification.verified ? "success" : "failed";
|
|
330
345
|
write?.(`Finished ${plan.unit.provider}:${plan.unit.unitType} (${plan.unit.logicalName}) in ${formatDurationMs(unitTiming.durationMs)}.`);
|
|
331
346
|
if (!verification.verified) {
|
|
332
|
-
|
|
347
|
+
if (!dryRun) {
|
|
348
|
+
await persistVerifiedResult(persisted, verifiedResult);
|
|
349
|
+
}
|
|
333
350
|
throw new Error(`Treeseed reconcile verification failed for ${plan.unit.provider}:${plan.unit.unitType} (${plan.unit.unitId}): ${formatVerificationFailure(verification)}`);
|
|
334
351
|
}
|
|
335
|
-
|
|
352
|
+
if (!dryRun) {
|
|
353
|
+
await persistVerifiedResult(persisted, verifiedResult);
|
|
354
|
+
}
|
|
336
355
|
results.push(verifiedResult);
|
|
337
356
|
});
|
|
338
|
-
|
|
357
|
+
if (!dryRun) {
|
|
358
|
+
writeTreeseedReconcileState(tenantRoot, planned.state);
|
|
359
|
+
}
|
|
339
360
|
return {
|
|
340
361
|
target,
|
|
341
362
|
units: planned.units,
|
|
@@ -365,13 +386,13 @@ async function destroyTreeseedTargetUnits({
|
|
|
365
386
|
const persisted = ensureTreeseedPersistedUnitState(reconcileState, unit);
|
|
366
387
|
let observed;
|
|
367
388
|
try {
|
|
368
|
-
observed = await Promise.resolve(adapter.
|
|
389
|
+
observed = await Promise.resolve(adapter.refresh({
|
|
369
390
|
context,
|
|
370
391
|
unit,
|
|
371
392
|
persistedState: persisted
|
|
372
393
|
}));
|
|
373
394
|
} catch (error) {
|
|
374
|
-
wrapAdapterFailure("
|
|
395
|
+
wrapAdapterFailure("refresh", unit.provider, unit.unitType, unit.unitId, error);
|
|
375
396
|
}
|
|
376
397
|
let result;
|
|
377
398
|
try {
|
|
@@ -394,14 +415,14 @@ async function collectTreeseedReconcileStatus({
|
|
|
394
415
|
env = process.env,
|
|
395
416
|
systems
|
|
396
417
|
}) {
|
|
397
|
-
const observed = await
|
|
418
|
+
const observed = await refreshTreeseedUnits({ tenantRoot, target, env, systems });
|
|
398
419
|
const registry = createTreeseedReconcileRegistry(observed.deployConfig);
|
|
399
420
|
const context = createRunContext(tenantRoot, target, env);
|
|
400
421
|
const plans = await Promise.all(observed.units.map(async (unit) => {
|
|
401
422
|
const adapter = registry.get(unit.unitType, unit.provider);
|
|
402
423
|
const persisted = ensureTreeseedPersistedUnitState(observed.state, unit);
|
|
403
424
|
const observation = observed.observations.get(unit.unitId);
|
|
404
|
-
const diff = await Promise.resolve(adapter.
|
|
425
|
+
const diff = await Promise.resolve(adapter.diff({
|
|
405
426
|
context,
|
|
406
427
|
unit,
|
|
407
428
|
persistedState: persisted,
|
|
@@ -448,7 +469,7 @@ async function collectTreeseedReconcileStatus({
|
|
|
448
469
|
export {
|
|
449
470
|
collectTreeseedReconcileStatus,
|
|
450
471
|
destroyTreeseedTargetUnits,
|
|
451
|
-
observeTreeseedUnits,
|
|
452
472
|
planTreeseedReconciliation,
|
|
453
|
-
reconcileTreeseedTarget
|
|
473
|
+
reconcileTreeseedTarget,
|
|
474
|
+
refreshTreeseedUnits
|
|
454
475
|
};
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
export * from './contracts.ts';
|
|
2
|
+
export * from './platform.ts';
|
|
2
3
|
export * from './bootstrap-systems.ts';
|
|
3
4
|
export * from './desired-state.ts';
|
|
4
5
|
export * from './engine.ts';
|
|
5
6
|
export * from './errors.ts';
|
|
7
|
+
export * from './live-acceptance.ts';
|
|
6
8
|
export * from './registry.ts';
|
|
7
9
|
export * from './state.ts';
|
|
8
10
|
export * from './units.ts';
|
package/dist/reconcile/index.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
export * from "./contracts.js";
|
|
2
|
+
export * from "./platform.js";
|
|
2
3
|
export * from "./bootstrap-systems.js";
|
|
3
4
|
export * from "./desired-state.js";
|
|
4
5
|
export * from "./engine.js";
|
|
5
6
|
export * from "./errors.js";
|
|
7
|
+
export * from "./live-acceptance.js";
|
|
6
8
|
export * from "./registry.js";
|
|
7
9
|
export * from "./state.js";
|
|
8
10
|
export * from "./units.js";
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { type TreeseedCanonicalAction, type TreeseedCanonicalDrift, type TreeseedCanonicalGraphNode, type TreeseedCanonicalReconcileReport } from './platform.ts';
|
|
2
|
+
export type TreeseedLiveReconcileProvider = 'railway' | 'cloudflare' | 'github' | 'local';
|
|
3
|
+
export type TreeseedLiveReconcileMode = 'smoke' | 'acceptance' | 'cleanup';
|
|
4
|
+
export type TreeseedLiveReconcileEnvironment = 'local' | 'staging' | 'prod';
|
|
5
|
+
export interface TreeseedLiveReconcileScenarioResult {
|
|
6
|
+
id: string;
|
|
7
|
+
provider: TreeseedLiveReconcileProvider;
|
|
8
|
+
capability: string;
|
|
9
|
+
mode: TreeseedLiveReconcileMode;
|
|
10
|
+
ok: boolean;
|
|
11
|
+
phase: 'smoke' | 'validate' | 'create' | 'update' | 'replace' | 'verify' | 'destroy' | 'cleanup' | 'blocked';
|
|
12
|
+
action: TreeseedCanonicalAction['kind'];
|
|
13
|
+
reason: string;
|
|
14
|
+
startedAt: string;
|
|
15
|
+
completedAt: string;
|
|
16
|
+
durationMs: number;
|
|
17
|
+
locators: Record<string, string | null>;
|
|
18
|
+
createdResources: TreeseedCanonicalGraphNode[];
|
|
19
|
+
updatedResources: TreeseedCanonicalGraphNode[];
|
|
20
|
+
replacedResources: TreeseedCanonicalGraphNode[];
|
|
21
|
+
destroyedResources: TreeseedCanonicalGraphNode[];
|
|
22
|
+
retainedResources: TreeseedCanonicalGraphNode[];
|
|
23
|
+
issues: string[];
|
|
24
|
+
}
|
|
25
|
+
export interface TreeseedLiveReconcileProviderReport {
|
|
26
|
+
provider: TreeseedLiveReconcileProvider;
|
|
27
|
+
mode: TreeseedLiveReconcileMode;
|
|
28
|
+
runId: string;
|
|
29
|
+
resourcePrefix: string;
|
|
30
|
+
scenarioResults: TreeseedLiveReconcileScenarioResult[];
|
|
31
|
+
coverage: {
|
|
32
|
+
total: number;
|
|
33
|
+
passed: number;
|
|
34
|
+
failed: number;
|
|
35
|
+
capabilities: string[];
|
|
36
|
+
};
|
|
37
|
+
createdResources: TreeseedCanonicalGraphNode[];
|
|
38
|
+
updatedResources: TreeseedCanonicalGraphNode[];
|
|
39
|
+
replacedResources: TreeseedCanonicalGraphNode[];
|
|
40
|
+
destroyedResources: TreeseedCanonicalGraphNode[];
|
|
41
|
+
retainedResources: TreeseedCanonicalGraphNode[];
|
|
42
|
+
cleanupDrift: TreeseedCanonicalDrift[];
|
|
43
|
+
report: TreeseedCanonicalReconcileReport;
|
|
44
|
+
ok: boolean;
|
|
45
|
+
}
|
|
46
|
+
export interface TreeseedLiveReconcileRunResult {
|
|
47
|
+
command: 'reconcile test-live';
|
|
48
|
+
mode: TreeseedLiveReconcileMode;
|
|
49
|
+
environment: TreeseedLiveReconcileEnvironment;
|
|
50
|
+
runId: string;
|
|
51
|
+
resourcePrefix: string;
|
|
52
|
+
providers: TreeseedLiveReconcileProviderReport[];
|
|
53
|
+
ok: boolean;
|
|
54
|
+
}
|
|
55
|
+
export interface TreeseedLiveReconcileProgressEvent {
|
|
56
|
+
provider: TreeseedLiveReconcileProvider;
|
|
57
|
+
mode: TreeseedLiveReconcileMode;
|
|
58
|
+
environment: TreeseedLiveReconcileEnvironment;
|
|
59
|
+
runId: string;
|
|
60
|
+
resourcePrefix: string;
|
|
61
|
+
capability?: string;
|
|
62
|
+
phase: 'start' | 'cleanup' | 'create' | 'verify' | 'destroy' | 'complete' | 'blocked';
|
|
63
|
+
message: string;
|
|
64
|
+
elapsedMs?: number;
|
|
65
|
+
}
|
|
66
|
+
export interface RunTreeseedLiveReconcileTestsOptions {
|
|
67
|
+
cwd: string;
|
|
68
|
+
environment: TreeseedLiveReconcileEnvironment;
|
|
69
|
+
providers: TreeseedLiveReconcileProvider[];
|
|
70
|
+
mode?: TreeseedLiveReconcileMode;
|
|
71
|
+
env?: NodeJS.ProcessEnv | Record<string, string | undefined>;
|
|
72
|
+
runId?: string;
|
|
73
|
+
now?: Date;
|
|
74
|
+
fetchImpl?: typeof fetch;
|
|
75
|
+
onProgress?: (event: TreeseedLiveReconcileProgressEvent) => void;
|
|
76
|
+
}
|
|
77
|
+
export declare function treeseedLiveReconcileProviderCapabilities(provider: TreeseedLiveReconcileProvider): string[];
|
|
78
|
+
export declare function treeseedLiveReconcileResourcePrefix(environment: TreeseedLiveReconcileEnvironment, provider: TreeseedLiveReconcileProvider, runId: string): string;
|
|
79
|
+
export declare function runTreeseedLiveReconcileTests(options: RunTreeseedLiveReconcileTestsOptions): Promise<TreeseedLiveReconcileRunResult>;
|