@synth-deploy/server 0.1.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/dist/agent/debrief-retention.d.ts +12 -0
- package/dist/agent/debrief-retention.d.ts.map +1 -0
- package/dist/agent/debrief-retention.js +27 -0
- package/dist/agent/debrief-retention.js.map +1 -0
- package/dist/agent/envoy-client.d.ts +216 -0
- package/dist/agent/envoy-client.d.ts.map +1 -0
- package/dist/agent/envoy-client.js +266 -0
- package/dist/agent/envoy-client.js.map +1 -0
- package/dist/agent/envoy-registry.d.ts +102 -0
- package/dist/agent/envoy-registry.d.ts.map +1 -0
- package/dist/agent/envoy-registry.js +319 -0
- package/dist/agent/envoy-registry.js.map +1 -0
- package/dist/agent/health-checker.d.ts +39 -0
- package/dist/agent/health-checker.d.ts.map +1 -0
- package/dist/agent/health-checker.js +49 -0
- package/dist/agent/health-checker.js.map +1 -0
- package/dist/agent/mcp-client-manager.d.ts +36 -0
- package/dist/agent/mcp-client-manager.d.ts.map +1 -0
- package/dist/agent/mcp-client-manager.js +106 -0
- package/dist/agent/mcp-client-manager.js.map +1 -0
- package/dist/agent/stale-deployment-detector.d.ts +15 -0
- package/dist/agent/stale-deployment-detector.d.ts.map +1 -0
- package/dist/agent/stale-deployment-detector.js +50 -0
- package/dist/agent/stale-deployment-detector.js.map +1 -0
- package/dist/agent/step-runner.d.ts +31 -0
- package/dist/agent/step-runner.d.ts.map +1 -0
- package/dist/agent/step-runner.js +80 -0
- package/dist/agent/step-runner.js.map +1 -0
- package/dist/agent/synth-agent.d.ts +168 -0
- package/dist/agent/synth-agent.d.ts.map +1 -0
- package/dist/agent/synth-agent.js +1195 -0
- package/dist/agent/synth-agent.js.map +1 -0
- package/dist/api/agent.d.ts +36 -0
- package/dist/api/agent.d.ts.map +1 -0
- package/dist/api/agent.js +867 -0
- package/dist/api/agent.js.map +1 -0
- package/dist/api/api-keys.d.ts +4 -0
- package/dist/api/api-keys.d.ts.map +1 -0
- package/dist/api/api-keys.js +118 -0
- package/dist/api/api-keys.js.map +1 -0
- package/dist/api/artifacts.d.ts +5 -0
- package/dist/api/artifacts.d.ts.map +1 -0
- package/dist/api/artifacts.js +142 -0
- package/dist/api/artifacts.js.map +1 -0
- package/dist/api/auth.d.ts +4 -0
- package/dist/api/auth.d.ts.map +1 -0
- package/dist/api/auth.js +280 -0
- package/dist/api/auth.js.map +1 -0
- package/dist/api/deployments.d.ts +11 -0
- package/dist/api/deployments.d.ts.map +1 -0
- package/dist/api/deployments.js +1098 -0
- package/dist/api/deployments.js.map +1 -0
- package/dist/api/environments.d.ts +5 -0
- package/dist/api/environments.d.ts.map +1 -0
- package/dist/api/environments.js +69 -0
- package/dist/api/environments.js.map +1 -0
- package/dist/api/envoy-reports.d.ts +17 -0
- package/dist/api/envoy-reports.d.ts.map +1 -0
- package/dist/api/envoy-reports.js +138 -0
- package/dist/api/envoy-reports.js.map +1 -0
- package/dist/api/envoys.d.ts +5 -0
- package/dist/api/envoys.d.ts.map +1 -0
- package/dist/api/envoys.js +192 -0
- package/dist/api/envoys.js.map +1 -0
- package/dist/api/fleet.d.ts +11 -0
- package/dist/api/fleet.d.ts.map +1 -0
- package/dist/api/fleet.js +394 -0
- package/dist/api/fleet.js.map +1 -0
- package/dist/api/graph.d.ts +8 -0
- package/dist/api/graph.d.ts.map +1 -0
- package/dist/api/graph.js +355 -0
- package/dist/api/graph.js.map +1 -0
- package/dist/api/health.d.ts +20 -0
- package/dist/api/health.d.ts.map +1 -0
- package/dist/api/health.js +248 -0
- package/dist/api/health.js.map +1 -0
- package/dist/api/idp-schemas.d.ts +41 -0
- package/dist/api/idp-schemas.d.ts.map +1 -0
- package/dist/api/idp-schemas.js +17 -0
- package/dist/api/idp-schemas.js.map +1 -0
- package/dist/api/idp.d.ts +6 -0
- package/dist/api/idp.d.ts.map +1 -0
- package/dist/api/idp.js +620 -0
- package/dist/api/idp.js.map +1 -0
- package/dist/api/intake.d.ts +10 -0
- package/dist/api/intake.d.ts.map +1 -0
- package/dist/api/intake.js +418 -0
- package/dist/api/intake.js.map +1 -0
- package/dist/api/partitions.d.ts +5 -0
- package/dist/api/partitions.d.ts.map +1 -0
- package/dist/api/partitions.js +113 -0
- package/dist/api/partitions.js.map +1 -0
- package/dist/api/progress-event-store.d.ts +62 -0
- package/dist/api/progress-event-store.d.ts.map +1 -0
- package/dist/api/progress-event-store.js +118 -0
- package/dist/api/progress-event-store.js.map +1 -0
- package/dist/api/schemas.d.ts +1000 -0
- package/dist/api/schemas.d.ts.map +1 -0
- package/dist/api/schemas.js +328 -0
- package/dist/api/schemas.js.map +1 -0
- package/dist/api/security-boundaries.d.ts +4 -0
- package/dist/api/security-boundaries.d.ts.map +1 -0
- package/dist/api/security-boundaries.js +32 -0
- package/dist/api/security-boundaries.js.map +1 -0
- package/dist/api/settings.d.ts +4 -0
- package/dist/api/settings.d.ts.map +1 -0
- package/dist/api/settings.js +99 -0
- package/dist/api/settings.js.map +1 -0
- package/dist/api/system.d.ts +75 -0
- package/dist/api/system.d.ts.map +1 -0
- package/dist/api/system.js +558 -0
- package/dist/api/system.js.map +1 -0
- package/dist/api/telemetry.d.ts +4 -0
- package/dist/api/telemetry.d.ts.map +1 -0
- package/dist/api/telemetry.js +24 -0
- package/dist/api/telemetry.js.map +1 -0
- package/dist/api/users.d.ts +4 -0
- package/dist/api/users.d.ts.map +1 -0
- package/dist/api/users.js +173 -0
- package/dist/api/users.js.map +1 -0
- package/dist/archive-unpacker.d.ts +24 -0
- package/dist/archive-unpacker.d.ts.map +1 -0
- package/dist/archive-unpacker.js +239 -0
- package/dist/archive-unpacker.js.map +1 -0
- package/dist/artifact-analyzer.d.ts +59 -0
- package/dist/artifact-analyzer.d.ts.map +1 -0
- package/dist/artifact-analyzer.js +334 -0
- package/dist/artifact-analyzer.js.map +1 -0
- package/dist/auth/idp/index.d.ts +9 -0
- package/dist/auth/idp/index.d.ts.map +1 -0
- package/dist/auth/idp/index.js +5 -0
- package/dist/auth/idp/index.js.map +1 -0
- package/dist/auth/idp/ldap.d.ts +56 -0
- package/dist/auth/idp/ldap.d.ts.map +1 -0
- package/dist/auth/idp/ldap.js +276 -0
- package/dist/auth/idp/ldap.js.map +1 -0
- package/dist/auth/idp/oidc.d.ts +27 -0
- package/dist/auth/idp/oidc.d.ts.map +1 -0
- package/dist/auth/idp/oidc.js +97 -0
- package/dist/auth/idp/oidc.js.map +1 -0
- package/dist/auth/idp/role-mapping.d.ts +9 -0
- package/dist/auth/idp/role-mapping.d.ts.map +1 -0
- package/dist/auth/idp/role-mapping.js +16 -0
- package/dist/auth/idp/role-mapping.js.map +1 -0
- package/dist/auth/idp/saml.d.ts +40 -0
- package/dist/auth/idp/saml.d.ts.map +1 -0
- package/dist/auth/idp/saml.js +117 -0
- package/dist/auth/idp/saml.js.map +1 -0
- package/dist/auth/idp/types.d.ts +23 -0
- package/dist/auth/idp/types.d.ts.map +1 -0
- package/dist/auth/idp/types.js +2 -0
- package/dist/auth/idp/types.js.map +1 -0
- package/dist/fleet/fleet-executor.d.ts +35 -0
- package/dist/fleet/fleet-executor.d.ts.map +1 -0
- package/dist/fleet/fleet-executor.js +228 -0
- package/dist/fleet/fleet-executor.js.map +1 -0
- package/dist/fleet/fleet-store.d.ts +13 -0
- package/dist/fleet/fleet-store.d.ts.map +1 -0
- package/dist/fleet/fleet-store.js +13 -0
- package/dist/fleet/fleet-store.js.map +1 -0
- package/dist/fleet/index.d.ts +5 -0
- package/dist/fleet/index.d.ts.map +1 -0
- package/dist/fleet/index.js +4 -0
- package/dist/fleet/index.js.map +1 -0
- package/dist/fleet/representative-selector.d.ts +15 -0
- package/dist/fleet/representative-selector.d.ts.map +1 -0
- package/dist/fleet/representative-selector.js +71 -0
- package/dist/fleet/representative-selector.js.map +1 -0
- package/dist/graph/graph-executor.d.ts +36 -0
- package/dist/graph/graph-executor.d.ts.map +1 -0
- package/dist/graph/graph-executor.js +348 -0
- package/dist/graph/graph-executor.js.map +1 -0
- package/dist/graph/graph-inference.d.ts +22 -0
- package/dist/graph/graph-inference.d.ts.map +1 -0
- package/dist/graph/graph-inference.js +149 -0
- package/dist/graph/graph-inference.js.map +1 -0
- package/dist/graph/graph-store.d.ts +12 -0
- package/dist/graph/graph-store.d.ts.map +1 -0
- package/dist/graph/graph-store.js +61 -0
- package/dist/graph/graph-store.js.map +1 -0
- package/dist/graph/index.d.ts +5 -0
- package/dist/graph/index.d.ts.map +1 -0
- package/dist/graph/index.js +4 -0
- package/dist/graph/index.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +837 -0
- package/dist/index.js.map +1 -0
- package/dist/intake/index.d.ts +6 -0
- package/dist/intake/index.d.ts.map +1 -0
- package/dist/intake/index.js +5 -0
- package/dist/intake/index.js.map +1 -0
- package/dist/intake/intake-processor.d.ts +17 -0
- package/dist/intake/intake-processor.d.ts.map +1 -0
- package/dist/intake/intake-processor.js +99 -0
- package/dist/intake/intake-processor.js.map +1 -0
- package/dist/intake/intake-store.d.ts +7 -0
- package/dist/intake/intake-store.d.ts.map +1 -0
- package/dist/intake/intake-store.js +7 -0
- package/dist/intake/intake-store.js.map +1 -0
- package/dist/intake/registry-poller.d.ts +41 -0
- package/dist/intake/registry-poller.d.ts.map +1 -0
- package/dist/intake/registry-poller.js +202 -0
- package/dist/intake/registry-poller.js.map +1 -0
- package/dist/intake/webhook-handlers.d.ts +37 -0
- package/dist/intake/webhook-handlers.d.ts.map +1 -0
- package/dist/intake/webhook-handlers.js +268 -0
- package/dist/intake/webhook-handlers.js.map +1 -0
- package/dist/logger.d.ts +5 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +15 -0
- package/dist/logger.js.map +1 -0
- package/dist/mcp/resources.d.ts +9 -0
- package/dist/mcp/resources.d.ts.map +1 -0
- package/dist/mcp/resources.js +72 -0
- package/dist/mcp/resources.js.map +1 -0
- package/dist/mcp/server.d.ts +15 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +20 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools.d.ts +9 -0
- package/dist/mcp/tools.d.ts.map +1 -0
- package/dist/mcp/tools.js +88 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/middleware/auth.d.ts +29 -0
- package/dist/middleware/auth.d.ts.map +1 -0
- package/dist/middleware/auth.js +76 -0
- package/dist/middleware/auth.js.map +1 -0
- package/dist/middleware/permissions.d.ts +13 -0
- package/dist/middleware/permissions.d.ts.map +1 -0
- package/dist/middleware/permissions.js +32 -0
- package/dist/middleware/permissions.js.map +1 -0
- package/dist/pattern-store.d.ts +104 -0
- package/dist/pattern-store.d.ts.map +1 -0
- package/dist/pattern-store.js +299 -0
- package/dist/pattern-store.js.map +1 -0
- package/package.json +54 -0
- package/src/agent/debrief-retention.ts +44 -0
- package/src/agent/envoy-client.ts +474 -0
- package/src/agent/envoy-registry.ts +384 -0
- package/src/agent/health-checker.ts +70 -0
- package/src/agent/mcp-client-manager.ts +131 -0
- package/src/agent/stale-deployment-detector.ts +79 -0
- package/src/agent/step-runner.ts +124 -0
- package/src/agent/synth-agent.ts +1567 -0
- package/src/api/agent.ts +1075 -0
- package/src/api/api-keys.ts +129 -0
- package/src/api/artifacts.ts +194 -0
- package/src/api/auth.ts +320 -0
- package/src/api/deployments.ts +1347 -0
- package/src/api/environments.ts +97 -0
- package/src/api/envoy-reports.ts +159 -0
- package/src/api/envoys.ts +237 -0
- package/src/api/fleet.ts +510 -0
- package/src/api/graph.ts +516 -0
- package/src/api/health.ts +311 -0
- package/src/api/idp-schemas.ts +19 -0
- package/src/api/idp.ts +735 -0
- package/src/api/intake.ts +537 -0
- package/src/api/partitions.ts +147 -0
- package/src/api/progress-event-store.ts +153 -0
- package/src/api/schemas.ts +376 -0
- package/src/api/security-boundaries.ts +54 -0
- package/src/api/settings.ts +118 -0
- package/src/api/system.ts +704 -0
- package/src/api/telemetry.ts +32 -0
- package/src/api/users.ts +210 -0
- package/src/archive-unpacker.ts +271 -0
- package/src/artifact-analyzer.ts +438 -0
- package/src/auth/idp/index.ts +8 -0
- package/src/auth/idp/ldap.ts +340 -0
- package/src/auth/idp/oidc.ts +117 -0
- package/src/auth/idp/role-mapping.ts +22 -0
- package/src/auth/idp/saml.ts +148 -0
- package/src/auth/idp/types.ts +22 -0
- package/src/fleet/fleet-executor.ts +309 -0
- package/src/fleet/fleet-store.ts +13 -0
- package/src/fleet/index.ts +4 -0
- package/src/fleet/representative-selector.ts +83 -0
- package/src/graph/graph-executor.ts +446 -0
- package/src/graph/graph-inference.ts +184 -0
- package/src/graph/graph-store.ts +75 -0
- package/src/graph/index.ts +4 -0
- package/src/index.ts +916 -0
- package/src/intake/index.ts +5 -0
- package/src/intake/intake-processor.ts +111 -0
- package/src/intake/intake-store.ts +7 -0
- package/src/intake/registry-poller.ts +230 -0
- package/src/intake/webhook-handlers.ts +328 -0
- package/src/logger.ts +19 -0
- package/src/mcp/resources.ts +98 -0
- package/src/mcp/server.ts +34 -0
- package/src/mcp/tools.ts +117 -0
- package/src/middleware/auth.ts +103 -0
- package/src/middleware/permissions.ts +35 -0
- package/src/pattern-store.ts +409 -0
- package/tests/agent-mode.test.ts +536 -0
- package/tests/api-handlers.test.ts +1245 -0
- package/tests/archive-unpacker.test.ts +179 -0
- package/tests/artifact-analyzer.test.ts +240 -0
- package/tests/auth-middleware.test.ts +189 -0
- package/tests/decision-diary.test.ts +957 -0
- package/tests/diary-reader.test.ts +782 -0
- package/tests/envoy-client.test.ts +342 -0
- package/tests/envoy-reports.test.ts +156 -0
- package/tests/mcp-tools.test.ts +213 -0
- package/tests/orchestration.test.ts +536 -0
- package/tests/partition-deletion.test.ts +143 -0
- package/tests/partition-isolation.test.ts +830 -0
- package/tests/pattern-store.test.ts +371 -0
- package/tests/rbac-enforcement.test.ts +409 -0
- package/tests/ssrf-validation.test.ts +56 -0
- package/tests/stale-deployment.test.ts +85 -0
- package/tests/step-runner.test.ts +308 -0
- package/tests/ui-journey.test.ts +330 -0
- package/tsconfig.json +11 -0
- package/vitest.config.ts +27 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/auth/idp/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAElD;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,wCAAwC;IACxC,IAAI,EAAE,MAAM,CAAC;IAEb;;;OAGG;IACH,YAAY,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAEhD;;;OAGG;IACH,cAAc,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC9E"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/auth/idp/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { FleetDeployment, FleetProgress, FleetValidationResult, DeploymentPlan } from "@synth-deploy/core";
|
|
2
|
+
import type { EnvoyRegistry } from "../agent/envoy-registry.js";
|
|
3
|
+
import { EnvoyClient } from "../agent/envoy-client.js";
|
|
4
|
+
export interface FleetProgressEvent {
|
|
5
|
+
type: "validation-started" | "validation-complete" | "batch-started" | "envoy-started" | "envoy-completed" | "envoy-failed" | "batch-completed" | "fleet-completed" | "fleet-failed" | "fleet-paused";
|
|
6
|
+
envoyId?: string;
|
|
7
|
+
envoyName?: string;
|
|
8
|
+
batchIndex?: number;
|
|
9
|
+
progress: FleetProgress;
|
|
10
|
+
error?: string;
|
|
11
|
+
}
|
|
12
|
+
export declare class FleetExecutor {
|
|
13
|
+
private envoyRegistry;
|
|
14
|
+
private createEnvoyClient;
|
|
15
|
+
constructor(envoyRegistry: EnvoyRegistry, createEnvoyClient: (url: string, token: string) => EnvoyClient);
|
|
16
|
+
/**
|
|
17
|
+
* Validate a deployment plan against all target envoys in the fleet.
|
|
18
|
+
* Probes each envoy and asks it to validate the plan steps.
|
|
19
|
+
*/
|
|
20
|
+
validateFleet(fleetDeployment: FleetDeployment, plan: DeploymentPlan): Promise<FleetValidationResult>;
|
|
21
|
+
/**
|
|
22
|
+
* Execute a progressive rollout across the fleet.
|
|
23
|
+
* Yields progress events as an async generator so callers can stream them.
|
|
24
|
+
*/
|
|
25
|
+
executeRollout(fleetDeployment: FleetDeployment, plan: DeploymentPlan, rollbackPlan?: DeploymentPlan): AsyncGenerator<FleetProgressEvent>;
|
|
26
|
+
/**
|
|
27
|
+
* Build execution batches based on the rollout strategy.
|
|
28
|
+
*/
|
|
29
|
+
private buildBatches;
|
|
30
|
+
/**
|
|
31
|
+
* Get all envoy IDs assigned to a given environment.
|
|
32
|
+
*/
|
|
33
|
+
private getEnvironmentEnvoyIds;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=fleet-executor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fleet-executor.d.ts","sourceRoot":"","sources":["../../src/fleet/fleet-executor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,aAAa,EACb,qBAAqB,EAErB,cAAc,EAEf,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAMvD,MAAM,WAAW,kBAAkB;IACjC,IAAI,EACA,oBAAoB,GACpB,qBAAqB,GACrB,eAAe,GACf,eAAe,GACf,iBAAiB,GACjB,cAAc,GACd,iBAAiB,GACjB,iBAAiB,GACjB,cAAc,GACd,cAAc,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,aAAa,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAmCD,qBAAa,aAAa;IAEtB,OAAO,CAAC,aAAa;IACrB,OAAO,CAAC,iBAAiB;gBADjB,aAAa,EAAE,aAAa,EAC5B,iBAAiB,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,WAAW;IAGxE;;;OAGG;IACG,aAAa,CACjB,eAAe,EAAE,eAAe,EAChC,IAAI,EAAE,cAAc,GACnB,OAAO,CAAC,qBAAqB,CAAC;IA+CjC;;;OAGG;IACI,cAAc,CACnB,eAAe,EAAE,eAAe,EAChC,IAAI,EAAE,cAAc,EACpB,YAAY,CAAC,EAAE,cAAc,GAC5B,cAAc,CAAC,kBAAkB,CAAC;IAkIrC;;OAEG;IACH,OAAO,CAAC,YAAY;IA2BpB;;OAEG;IACH,OAAO,CAAC,sBAAsB;CAU/B"}
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Helpers
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
function delay(ms) {
|
|
5
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
6
|
+
}
|
|
7
|
+
function makeProgress(totalEnvoys, validated, executing, succeeded, failed, currentBatch, totalBatches) {
|
|
8
|
+
return {
|
|
9
|
+
totalEnvoys,
|
|
10
|
+
validated,
|
|
11
|
+
executing,
|
|
12
|
+
succeeded,
|
|
13
|
+
failed,
|
|
14
|
+
pending: totalEnvoys - succeeded - failed - executing,
|
|
15
|
+
currentBatch,
|
|
16
|
+
totalBatches,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
// FleetExecutor — orchestrates validation and progressive rollout
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
export class FleetExecutor {
|
|
23
|
+
envoyRegistry;
|
|
24
|
+
createEnvoyClient;
|
|
25
|
+
constructor(envoyRegistry, createEnvoyClient) {
|
|
26
|
+
this.envoyRegistry = envoyRegistry;
|
|
27
|
+
this.createEnvoyClient = createEnvoyClient;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Validate a deployment plan against all target envoys in the fleet.
|
|
31
|
+
* Probes each envoy and asks it to validate the plan steps.
|
|
32
|
+
*/
|
|
33
|
+
async validateFleet(fleetDeployment, plan) {
|
|
34
|
+
const targetEnvoyIds = fleetDeployment.envoyFilter ?? this.getEnvironmentEnvoyIds(fleetDeployment.environmentId);
|
|
35
|
+
const results = [];
|
|
36
|
+
for (const envoyId of targetEnvoyIds) {
|
|
37
|
+
const entry = this.envoyRegistry.get(envoyId);
|
|
38
|
+
if (!entry) {
|
|
39
|
+
results.push({
|
|
40
|
+
envoyId,
|
|
41
|
+
envoyName: "unknown",
|
|
42
|
+
validated: false,
|
|
43
|
+
issues: [`Envoy ${envoyId} not found in registry`],
|
|
44
|
+
});
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
const client = this.createEnvoyClient(entry.url, entry.token);
|
|
48
|
+
try {
|
|
49
|
+
const validation = await client.validatePlan(plan.steps);
|
|
50
|
+
results.push({
|
|
51
|
+
envoyId,
|
|
52
|
+
envoyName: entry.name,
|
|
53
|
+
validated: validation.valid,
|
|
54
|
+
issues: validation.violations?.map((v) => v.reason),
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
results.push({
|
|
59
|
+
envoyId,
|
|
60
|
+
envoyName: entry.name,
|
|
61
|
+
validated: false,
|
|
62
|
+
issues: [
|
|
63
|
+
`Validation failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
64
|
+
],
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
total: results.length,
|
|
70
|
+
validated: results.filter((r) => r.validated).length,
|
|
71
|
+
failed: results.filter((r) => !r.validated).length,
|
|
72
|
+
results,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Execute a progressive rollout across the fleet.
|
|
77
|
+
* Yields progress events as an async generator so callers can stream them.
|
|
78
|
+
*/
|
|
79
|
+
async *executeRollout(fleetDeployment, plan, rollbackPlan) {
|
|
80
|
+
const validatedEnvoys = fleetDeployment.validationResult?.results.filter((r) => r.validated) ?? [];
|
|
81
|
+
const config = fleetDeployment.rolloutConfig;
|
|
82
|
+
const totalEnvoys = validatedEnvoys.length;
|
|
83
|
+
if (totalEnvoys === 0) {
|
|
84
|
+
yield {
|
|
85
|
+
type: "fleet-failed",
|
|
86
|
+
progress: makeProgress(0, 0, 0, 0, 0),
|
|
87
|
+
error: "No validated envoys to execute against",
|
|
88
|
+
};
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
// Build batches based on rollout strategy
|
|
92
|
+
const batches = this.buildBatches(validatedEnvoys, config);
|
|
93
|
+
const totalBatches = batches.length;
|
|
94
|
+
let succeeded = 0;
|
|
95
|
+
let failureCount = 0;
|
|
96
|
+
for (let i = 0; i < batches.length; i++) {
|
|
97
|
+
yield {
|
|
98
|
+
type: "batch-started",
|
|
99
|
+
batchIndex: i,
|
|
100
|
+
progress: makeProgress(totalEnvoys, totalEnvoys, batches[i].length, succeeded, failureCount, i, totalBatches),
|
|
101
|
+
};
|
|
102
|
+
for (const envoy of batches[i]) {
|
|
103
|
+
yield {
|
|
104
|
+
type: "envoy-started",
|
|
105
|
+
envoyId: envoy.envoyId,
|
|
106
|
+
envoyName: envoy.envoyName,
|
|
107
|
+
batchIndex: i,
|
|
108
|
+
progress: makeProgress(totalEnvoys, totalEnvoys, 1, succeeded, failureCount, i, totalBatches),
|
|
109
|
+
};
|
|
110
|
+
const entry = this.envoyRegistry.get(envoy.envoyId);
|
|
111
|
+
if (!entry) {
|
|
112
|
+
failureCount++;
|
|
113
|
+
yield {
|
|
114
|
+
type: "envoy-failed",
|
|
115
|
+
envoyId: envoy.envoyId,
|
|
116
|
+
envoyName: envoy.envoyName,
|
|
117
|
+
batchIndex: i,
|
|
118
|
+
progress: makeProgress(totalEnvoys, totalEnvoys, 0, succeeded, failureCount, i, totalBatches),
|
|
119
|
+
error: `Envoy ${envoy.envoyId} not found in registry`,
|
|
120
|
+
};
|
|
121
|
+
if (failureCount >= config.haltOnFailureCount) {
|
|
122
|
+
yield {
|
|
123
|
+
type: "fleet-failed",
|
|
124
|
+
progress: makeProgress(totalEnvoys, totalEnvoys, 0, succeeded, failureCount, i, totalBatches),
|
|
125
|
+
error: `Halted: ${failureCount} failure(s) reached threshold of ${config.haltOnFailureCount}`,
|
|
126
|
+
};
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
const client = this.createEnvoyClient(entry.url, entry.token);
|
|
132
|
+
try {
|
|
133
|
+
await client.executeApprovedPlan({
|
|
134
|
+
deploymentId: fleetDeployment.id,
|
|
135
|
+
plan,
|
|
136
|
+
rollbackPlan: rollbackPlan ?? plan,
|
|
137
|
+
artifactType: "fleet",
|
|
138
|
+
artifactName: fleetDeployment.artifactId,
|
|
139
|
+
environmentId: fleetDeployment.environmentId,
|
|
140
|
+
});
|
|
141
|
+
succeeded++;
|
|
142
|
+
yield {
|
|
143
|
+
type: "envoy-completed",
|
|
144
|
+
envoyId: envoy.envoyId,
|
|
145
|
+
envoyName: envoy.envoyName,
|
|
146
|
+
batchIndex: i,
|
|
147
|
+
progress: makeProgress(totalEnvoys, totalEnvoys, 0, succeeded, failureCount, i, totalBatches),
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
catch (err) {
|
|
151
|
+
failureCount++;
|
|
152
|
+
yield {
|
|
153
|
+
type: "envoy-failed",
|
|
154
|
+
envoyId: envoy.envoyId,
|
|
155
|
+
envoyName: envoy.envoyName,
|
|
156
|
+
batchIndex: i,
|
|
157
|
+
progress: makeProgress(totalEnvoys, totalEnvoys, 0, succeeded, failureCount, i, totalBatches),
|
|
158
|
+
error: err instanceof Error ? err.message : String(err),
|
|
159
|
+
};
|
|
160
|
+
if (failureCount >= config.haltOnFailureCount) {
|
|
161
|
+
yield {
|
|
162
|
+
type: "fleet-failed",
|
|
163
|
+
progress: makeProgress(totalEnvoys, totalEnvoys, 0, succeeded, failureCount, i, totalBatches),
|
|
164
|
+
error: `Halted: ${failureCount} failure(s) reached threshold of ${config.haltOnFailureCount}`,
|
|
165
|
+
};
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
yield {
|
|
171
|
+
type: "batch-completed",
|
|
172
|
+
batchIndex: i,
|
|
173
|
+
progress: makeProgress(totalEnvoys, totalEnvoys, 0, succeeded, failureCount, i, totalBatches),
|
|
174
|
+
};
|
|
175
|
+
// Health check wait between batches
|
|
176
|
+
if (config.healthCheckWaitMs > 0 && i < batches.length - 1) {
|
|
177
|
+
await delay(config.healthCheckWaitMs);
|
|
178
|
+
}
|
|
179
|
+
// Pause between batches if configured — yield paused event and return.
|
|
180
|
+
// Caller resumes by calling executeRollout again with remaining batches.
|
|
181
|
+
if (config.pauseBetweenBatches && i < batches.length - 1) {
|
|
182
|
+
yield {
|
|
183
|
+
type: "fleet-paused",
|
|
184
|
+
batchIndex: i,
|
|
185
|
+
progress: makeProgress(totalEnvoys, totalEnvoys, 0, succeeded, failureCount, i, totalBatches),
|
|
186
|
+
};
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
yield {
|
|
191
|
+
type: "fleet-completed",
|
|
192
|
+
progress: makeProgress(totalEnvoys, totalEnvoys, 0, succeeded, failureCount, totalBatches - 1, totalBatches),
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Build execution batches based on the rollout strategy.
|
|
197
|
+
*/
|
|
198
|
+
buildBatches(envoys, config) {
|
|
199
|
+
if (envoys.length === 0)
|
|
200
|
+
return [];
|
|
201
|
+
if (config.strategy === "all-at-once") {
|
|
202
|
+
return [envoys];
|
|
203
|
+
}
|
|
204
|
+
if (config.strategy === "canary") {
|
|
205
|
+
// First batch: single canary, second batch: everything else
|
|
206
|
+
return [[envoys[0]], envoys.slice(1)];
|
|
207
|
+
}
|
|
208
|
+
// batched strategy
|
|
209
|
+
const size = config.batchSize ??
|
|
210
|
+
Math.max(1, Math.ceil(envoys.length * (config.batchPercent ?? 10) / 100));
|
|
211
|
+
const batches = [];
|
|
212
|
+
for (let i = 0; i < envoys.length; i += size) {
|
|
213
|
+
batches.push(envoys.slice(i, i + size));
|
|
214
|
+
}
|
|
215
|
+
return batches;
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Get all envoy IDs assigned to a given environment.
|
|
219
|
+
*/
|
|
220
|
+
getEnvironmentEnvoyIds(environmentId) {
|
|
221
|
+
return this.envoyRegistry
|
|
222
|
+
.list()
|
|
223
|
+
.filter((e) => e.assignedEnvironments.length === 0 ||
|
|
224
|
+
e.assignedEnvironments.includes(environmentId))
|
|
225
|
+
.map((e) => e.id);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
//# sourceMappingURL=fleet-executor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fleet-executor.js","sourceRoot":"","sources":["../../src/fleet/fleet-executor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Re-exports the persistent fleet deployment store from @synth-deploy/core.
|
|
3
|
+
* Fleet deployments are now SQLite-backed to survive server restarts.
|
|
4
|
+
*
|
|
5
|
+
* Note: In-flight fleet operations that are mid-execution when the server
|
|
6
|
+
* crashes cannot be resumed — their status is persisted, but the active
|
|
7
|
+
* orchestration state (batch progress, in-flight envoy connections) is
|
|
8
|
+
* ephemeral. On restart, in-flight operations will appear as stale entries
|
|
9
|
+
* that users can inspect and manually re-trigger. Terminal states (completed,
|
|
10
|
+
* failed, rolled_back) are fully durable.
|
|
11
|
+
*/
|
|
12
|
+
export { PersistentFleetDeploymentStore as FleetDeploymentStore } from "@synth-deploy/core";
|
|
13
|
+
//# sourceMappingURL=fleet-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fleet-store.d.ts","sourceRoot":"","sources":["../../src/fleet/fleet-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,8BAA8B,IAAI,oBAAoB,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Re-exports the persistent fleet deployment store from @synth-deploy/core.
|
|
3
|
+
* Fleet deployments are now SQLite-backed to survive server restarts.
|
|
4
|
+
*
|
|
5
|
+
* Note: In-flight fleet operations that are mid-execution when the server
|
|
6
|
+
* crashes cannot be resumed — their status is persisted, but the active
|
|
7
|
+
* orchestration state (batch progress, in-flight envoy connections) is
|
|
8
|
+
* ephemeral. On restart, in-flight operations will appear as stale entries
|
|
9
|
+
* that users can inspect and manually re-trigger. Terminal states (completed,
|
|
10
|
+
* failed, rolled_back) are fully durable.
|
|
11
|
+
*/
|
|
12
|
+
export { PersistentFleetDeploymentStore as FleetDeploymentStore } from "@synth-deploy/core";
|
|
13
|
+
//# sourceMappingURL=fleet-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fleet-store.js","sourceRoot":"","sources":["../../src/fleet/fleet-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,8BAA8B,IAAI,oBAAoB,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { selectRepresentatives } from "./representative-selector.js";
|
|
2
|
+
export { FleetExecutor } from "./fleet-executor.js";
|
|
3
|
+
export type { FleetProgressEvent } from "./fleet-executor.js";
|
|
4
|
+
export { FleetDeploymentStore } from "./fleet-store.js";
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/fleet/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,YAAY,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/fleet/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { EnvoyRegistryEntry } from "../agent/envoy-registry.js";
|
|
2
|
+
/**
|
|
3
|
+
* Select a representative subset of envoys for plan validation.
|
|
4
|
+
*
|
|
5
|
+
* Strategy:
|
|
6
|
+
* 1. Filter to healthy envoys only (health === "OK")
|
|
7
|
+
* 2. Group by platform (e.g. linux, darwin, windows)
|
|
8
|
+
* 3. Pick one per platform group, preferring most recently seen
|
|
9
|
+
* 4. Cap at MAX_REPRESENTATIVES
|
|
10
|
+
* 5. If all envoys share the same platform, pick 1
|
|
11
|
+
*
|
|
12
|
+
* Returns an array of envoy IDs.
|
|
13
|
+
*/
|
|
14
|
+
export declare function selectRepresentatives(envoys: EnvoyRegistryEntry[], _artifactId: string): string[];
|
|
15
|
+
//# sourceMappingURL=representative-selector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"representative-selector.d.ts","sourceRoot":"","sources":["../../src/fleet/representative-selector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAQrE;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,kBAAkB,EAAE,EAC5B,WAAW,EAAE,MAAM,GAClB,MAAM,EAAE,CAoCV"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Maximum number of representative envoys to select for plan validation.
|
|
3
|
+
* Keeps validation fast while covering platform diversity.
|
|
4
|
+
*/
|
|
5
|
+
const MAX_REPRESENTATIVES = 3;
|
|
6
|
+
/**
|
|
7
|
+
* Select a representative subset of envoys for plan validation.
|
|
8
|
+
*
|
|
9
|
+
* Strategy:
|
|
10
|
+
* 1. Filter to healthy envoys only (health === "OK")
|
|
11
|
+
* 2. Group by platform (e.g. linux, darwin, windows)
|
|
12
|
+
* 3. Pick one per platform group, preferring most recently seen
|
|
13
|
+
* 4. Cap at MAX_REPRESENTATIVES
|
|
14
|
+
* 5. If all envoys share the same platform, pick 1
|
|
15
|
+
*
|
|
16
|
+
* Returns an array of envoy IDs.
|
|
17
|
+
*/
|
|
18
|
+
export function selectRepresentatives(envoys, _artifactId) {
|
|
19
|
+
// 1. Filter to healthy envoys
|
|
20
|
+
const healthy = envoys.filter((e) => e.health === "OK");
|
|
21
|
+
if (healthy.length === 0)
|
|
22
|
+
return [];
|
|
23
|
+
// 2. Group by platform
|
|
24
|
+
const byPlatform = new Map();
|
|
25
|
+
for (const envoy of healthy) {
|
|
26
|
+
// Normalize: null/undefined platform treated as "unknown"
|
|
27
|
+
const platform = envoy.platform ?? "unknown";
|
|
28
|
+
const group = byPlatform.get(platform) ?? [];
|
|
29
|
+
group.push(envoy);
|
|
30
|
+
byPlatform.set(platform, group);
|
|
31
|
+
}
|
|
32
|
+
// 3. If all same platform, pick the most recently seen one
|
|
33
|
+
if (byPlatform.size <= 1) {
|
|
34
|
+
const best = pickMostRecentlySeen(healthy);
|
|
35
|
+
return best ? [best.id] : [];
|
|
36
|
+
}
|
|
37
|
+
// 4. Pick one per platform group (prefer most recently seen)
|
|
38
|
+
const representatives = [];
|
|
39
|
+
for (const group of byPlatform.values()) {
|
|
40
|
+
const best = pickMostRecentlySeen(group);
|
|
41
|
+
if (best)
|
|
42
|
+
representatives.push(best);
|
|
43
|
+
}
|
|
44
|
+
// 5. Cap at MAX_REPRESENTATIVES (sort by lastSeen descending, take top N)
|
|
45
|
+
representatives.sort((a, b) => {
|
|
46
|
+
const aTime = a.lastSeen ? new Date(a.lastSeen).getTime() : 0;
|
|
47
|
+
const bTime = b.lastSeen ? new Date(b.lastSeen).getTime() : 0;
|
|
48
|
+
return bTime - aTime;
|
|
49
|
+
});
|
|
50
|
+
return representatives.slice(0, MAX_REPRESENTATIVES).map((e) => e.id);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Pick the envoy with the most recent `lastSeen` timestamp from a group.
|
|
54
|
+
*/
|
|
55
|
+
function pickMostRecentlySeen(group) {
|
|
56
|
+
if (group.length === 0)
|
|
57
|
+
return undefined;
|
|
58
|
+
if (group.length === 1)
|
|
59
|
+
return group[0];
|
|
60
|
+
let best = group[0];
|
|
61
|
+
let bestTime = best.lastSeen ? new Date(best.lastSeen).getTime() : 0;
|
|
62
|
+
for (let i = 1; i < group.length; i++) {
|
|
63
|
+
const t = group[i].lastSeen ? new Date(group[i].lastSeen).getTime() : 0;
|
|
64
|
+
if (t > bestTime) {
|
|
65
|
+
best = group[i];
|
|
66
|
+
bestTime = t;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return best;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=representative-selector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"representative-selector.js","sourceRoot":"","sources":["../../src/fleet/representative-selector.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,mBAAmB,GAAG,CAAC,CAAC;AAE9B;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,qBAAqB,CACnC,MAA4B,EAC5B,WAAmB;IAEnB,8BAA8B;IAC9B,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC;IACxD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAEpC,uBAAuB;IACvB,MAAM,UAAU,GAAG,IAAI,GAAG,EAAgC,CAAC;IAC3D,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,0DAA0D;QAC1D,MAAM,QAAQ,GAAI,KAAsC,CAAC,QAAQ,IAAI,SAAS,CAAC;QAC/E,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QAC7C,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAClB,UAAU,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAClC,CAAC;IAED,2DAA2D;IAC3D,IAAI,UAAU,CAAC,IAAI,IAAI,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAC;QAC3C,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/B,CAAC;IAED,6DAA6D;IAC7D,MAAM,eAAe,GAAyB,EAAE,CAAC;IACjD,KAAK,MAAM,KAAK,IAAI,UAAU,CAAC,MAAM,EAAE,EAAE,CAAC;QACxC,MAAM,IAAI,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAC;QACzC,IAAI,IAAI;YAAE,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvC,CAAC;IAED,0EAA0E;IAC1E,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QAC5B,MAAM,KAAK,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9D,MAAM,KAAK,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9D,OAAO,KAAK,GAAG,KAAK,CAAC;IACvB,CAAC,CAAC,CAAC;IAEH,OAAO,eAAe,CAAC,KAAK,CAAC,CAAC,EAAE,mBAAmB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AACxE,CAAC;AAED;;GAEG;AACH,SAAS,oBAAoB,CAC3B,KAA2B;IAE3B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IACzC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC;IAExC,IAAI,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IACpB,IAAI,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAErE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,QAAS,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QACzE,IAAI,CAAC,GAAG,QAAQ,EAAE,CAAC;YACjB,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YAChB,QAAQ,GAAG,CAAC,CAAC;QACf,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { DeploymentGraph, DeploymentGraphNode, DeploymentGraphEdge, DeploymentPlan } from "@synth-deploy/core";
|
|
2
|
+
import type { EnvoyRegistry } from "../agent/envoy-registry.js";
|
|
3
|
+
import type { EnvoyClient } from "../agent/envoy-client.js";
|
|
4
|
+
export interface GraphProgressEvent {
|
|
5
|
+
type: "node-started" | "node-completed" | "node-failed" | "node-skipped" | "graph-completed" | "graph-failed";
|
|
6
|
+
nodeId?: string;
|
|
7
|
+
graphId: string;
|
|
8
|
+
progress: {
|
|
9
|
+
completed: number;
|
|
10
|
+
total: number;
|
|
11
|
+
executing: number;
|
|
12
|
+
failed: number;
|
|
13
|
+
};
|
|
14
|
+
outputCapture?: Record<string, string>;
|
|
15
|
+
error?: string;
|
|
16
|
+
}
|
|
17
|
+
export declare function topologicalSort(nodes: DeploymentGraphNode[], edges: DeploymentGraphEdge[]): string[];
|
|
18
|
+
export declare function computeDepths(nodes: DeploymentGraphNode[], edges: DeploymentGraphEdge[]): Map<string, number>;
|
|
19
|
+
export declare class GraphExecutor {
|
|
20
|
+
private envoyRegistry;
|
|
21
|
+
private createClient;
|
|
22
|
+
constructor(envoyRegistry: EnvoyRegistry, createClient: (url: string, timeoutMs: number) => EnvoyClient);
|
|
23
|
+
/**
|
|
24
|
+
* Execute a deployment graph with depth-based parallelism.
|
|
25
|
+
* Nodes at the same depth run concurrently via Promise.allSettled().
|
|
26
|
+
* If a node fails, all its downstream dependents are skipped,
|
|
27
|
+
* but sibling nodes at the same depth continue executing.
|
|
28
|
+
*/
|
|
29
|
+
execute(graph: DeploymentGraph, plans: Map<string, DeploymentPlan>, partitionVariables?: Record<string, string>): AsyncGenerator<GraphProgressEvent>;
|
|
30
|
+
/**
|
|
31
|
+
* Rollback completed nodes in reverse topological order.
|
|
32
|
+
* Only rolls back nodes that completed successfully.
|
|
33
|
+
*/
|
|
34
|
+
rollback(graph: DeploymentGraph, rollbackPlans: Map<string, DeploymentPlan>): AsyncGenerator<GraphProgressEvent>;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=graph-executor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph-executor.d.ts","sourceRoot":"","sources":["../../src/graph/graph-executor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,mBAAmB,EACnB,mBAAmB,EACnB,cAAc,EACf,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,KAAK,EAAE,WAAW,EAAqB,MAAM,0BAA0B,CAAC;AAM/E,MAAM,WAAW,kBAAkB;IACjC,IAAI,EACA,cAAc,GACd,gBAAgB,GAChB,aAAa,GACb,cAAc,GACd,iBAAiB,GACjB,cAAc,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE;QACR,SAAS,EAAE,MAAM,CAAC;QAClB,KAAK,EAAE,MAAM,CAAC;QACd,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAMD,wBAAgB,eAAe,CAC7B,KAAK,EAAE,mBAAmB,EAAE,EAC5B,KAAK,EAAE,mBAAmB,EAAE,GAC3B,MAAM,EAAE,CAqCV;AAMD,wBAAgB,aAAa,CAC3B,KAAK,EAAE,mBAAmB,EAAE,EAC5B,KAAK,EAAE,mBAAmB,EAAE,GAC3B,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAyBrB;AAkCD,qBAAa,aAAa;IAEtB,OAAO,CAAC,aAAa;IACrB,OAAO,CAAC,YAAY;gBADZ,aAAa,EAAE,aAAa,EAC5B,YAAY,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,WAAW;IAGvE;;;;;OAKG;IACI,OAAO,CACZ,KAAK,EAAE,eAAe,EACtB,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,EAClC,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC1C,cAAc,CAAC,kBAAkB,CAAC;IAuOrC;;;OAGG;IACI,QAAQ,CACb,KAAK,EAAE,eAAe,EACtB,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,GACzC,cAAc,CAAC,kBAAkB,CAAC;CA8CtC"}
|