deepline 0.3.89 → 0.3.91
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/contracts/install-commands.json +29 -0
- package/dist/bundling-sources/sdk/src/client.ts +221 -43
- package/dist/bundling-sources/sdk/src/index.ts +4 -0
- package/dist/bundling-sources/sdk/src/monitor-fleet-contract.ts +2 -556
- package/dist/bundling-sources/sdk/src/monitor-fleets.ts +2 -2
- package/dist/bundling-sources/sdk/src/pagination.ts +25 -0
- package/dist/bundling-sources/sdk/src/plays/bundle-play-file.ts +1 -1
- package/dist/bundling-sources/sdk/src/release.ts +11 -9
- package/dist/bundling-sources/sdk/src/types.ts +29 -1
- package/dist/bundling-sources/shared_libs/integration-contracts/monitor-fleet-contract.ts +549 -0
- package/dist/bundling-sources/shared_libs/monitors/analytics-public.ts +10 -0
- package/dist/bundling-sources/shared_libs/monitors/fleets/errors.ts +96 -0
- package/dist/bundling-sources/shared_libs/monitors/fleets/limits.ts +8 -0
- package/dist/bundling-sources/shared_libs/monitors/fleets/plan.ts +320 -0
- package/dist/bundling-sources/shared_libs/monitors/fleets/verdict.ts +106 -0
- package/dist/bundling-sources/shared_libs/monitors/http-error-response.ts +8 -1
- package/dist/bundling-sources/shared_libs/monitors/inbound-queue.ts +4 -4
- package/dist/bundling-sources/shared_libs/monitors/inventory-reconciliation.ts +59 -0
- package/dist/bundling-sources/shared_libs/monitors/lifecycle-notifications.ts +7 -9
- package/dist/bundling-sources/shared_libs/monitors/monitor-fleet-limits.ts +2 -12
- package/dist/bundling-sources/shared_libs/monitors/package.json +113 -4
- package/dist/bundling-sources/shared_libs/monitors/provider-monitor-batch-operation.ts +56 -9
- package/dist/bundling-sources/shared_libs/monitors/provider-monitor-consumer-health.ts +2 -2
- package/dist/bundling-sources/shared_libs/monitors/provider-monitor-identity-claims.ts +2 -2
- package/dist/bundling-sources/shared_libs/monitors/provider-monitor-public-aliases.ts +1 -1
- package/dist/bundling-sources/shared_libs/monitors/signal-radars/inbound-dead-letter.ts +245 -0
- package/dist/bundling-sources/shared_libs/monitors/signal-radars/inbound-message.ts +38 -0
- package/dist/bundling-sources/shared_libs/monitors/signal-radars/inbound-queue-ack-probe.ts +94 -0
- package/dist/bundling-sources/shared_libs/monitors/signal-radars/inbound-queue-delivery.ts +60 -0
- package/dist/bundling-sources/shared_libs/monitors/signal-radars/inbound-queue.ts +60 -0
- package/dist/bundling-sources/shared_libs/monitors/snitcher-install-validation.ts +1 -1
- package/dist/bundling-sources/shared_libs/monitors/snitcher-ip2company.ts +2 -2
- package/dist/bundling-sources/shared_libs/monitors/snitcher-radar.ts +1 -1
- package/dist/bundling-sources/shared_libs/monitors/tracking-provider-integrations.ts +1 -1
- package/dist/bundling-sources/shared_libs/observability/build-context.ts +13 -0
- package/dist/bundling-sources/shared_libs/observability/log-metadata.ts +160 -0
- package/dist/bundling-sources/shared_libs/observability/request-context.ts +68 -0
- package/dist/bundling-sources/shared_libs/observability/scheduled-jobs.json +690 -0
- package/dist/bundling-sources/shared_libs/observability/scheduled-work-manual.ts +35 -0
- package/dist/bundling-sources/shared_libs/observability/scheduled-work.ts +5 -0
- package/dist/bundling-sources/shared_libs/play-data-plane/neon-constants.ts +9 -0
- package/dist/bundling-sources/shared_libs/play-data-plane/r2.ts +272 -0
- package/dist/bundling-sources/shared_libs/play-runtime/app-runtime-api.ts +46 -1
- package/dist/bundling-sources/shared_libs/play-runtime/async-operation.ts +66 -1
- package/dist/bundling-sources/shared_libs/play-runtime/async-play-invocation.ts +0 -1
- package/dist/bundling-sources/shared_libs/play-runtime/bounceban-batching.ts +137 -0
- package/dist/bundling-sources/shared_libs/play-runtime/context.ts +779 -140
- package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +46 -0
- package/dist/bundling-sources/shared_libs/play-runtime/daytona-payload-contract.ts +68 -0
- package/dist/bundling-sources/shared_libs/play-runtime/daytona-sandbox-janitor.ts +103 -0
- package/dist/bundling-sources/shared_libs/play-runtime/daytona-sandbox-reaper.ts +725 -0
- package/dist/bundling-sources/shared_libs/play-runtime/db-session-lease-store.ts +578 -0
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/commands/roll-execution-relay.ts +521 -0
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/commands/roll-receipt-gateway.ts +1378 -0
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/commands/runtime-topology.ts +1024 -0
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/fly-gateway-route-probe.ts +193 -0
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/fly-machine-lifecycle.ts +104 -0
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/fly-machines.ts +1844 -0
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/fly-registry.ts +21 -0
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/process-tree.ts +40 -0
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/runtime-gateway-drain.ts +262 -0
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/runtime-surface.ts +98 -0
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/runtime-topology.ts +303 -0
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/runtime-tuple-publication-guardian.ts +70 -0
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/runtime-tuple-recovery.ts +519 -0
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/vercel-fly-rollback-alignment.ts +280 -0
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/vercel-production-gate.ts +159 -0
- package/dist/bundling-sources/shared_libs/play-runtime/durable-call-cache.ts +29 -0
- package/dist/bundling-sources/shared_libs/play-runtime/execution-capabilities.ts +23 -0
- package/dist/bundling-sources/shared_libs/play-runtime/execution-gateway-invocation-fence.ts +442 -0
- package/dist/bundling-sources/shared_libs/play-runtime/execution-protocol.ts +3 -3
- package/dist/bundling-sources/shared_libs/play-runtime/fixture-behavior.ts +18 -0
- package/dist/bundling-sources/shared_libs/play-runtime/governor/app-runtime-rate-state-backend.ts +9 -0
- package/dist/bundling-sources/shared_libs/play-runtime/governor/policy.ts +1 -1
- package/dist/bundling-sources/shared_libs/play-runtime/governor/rate-state-backend.ts +1 -1
- package/dist/bundling-sources/shared_libs/play-runtime/integration-operation-reader-fence/contracts.ts +66 -0
- package/dist/bundling-sources/shared_libs/play-runtime/integration-operation-reader-fence/job.ts +145 -0
- package/dist/bundling-sources/shared_libs/play-runtime/integration-operation-reader-fence/memory-store.ts +114 -0
- package/dist/bundling-sources/shared_libs/play-runtime/integration-operation-reader-fence/ports.ts +21 -0
- package/dist/bundling-sources/shared_libs/play-runtime/integration-operation-reader-fence/postgres-store.ts +170 -0
- package/dist/bundling-sources/shared_libs/play-runtime/internal-bootstrap-token.ts +1322 -0
- package/dist/bundling-sources/shared_libs/play-runtime/internal-step-ids.ts +2 -2
- package/dist/bundling-sources/shared_libs/play-runtime/lane-retirement-gate.ts +1 -1
- package/dist/bundling-sources/shared_libs/play-runtime/launch-source-policy.ts +112 -0
- package/dist/bundling-sources/shared_libs/play-runtime/map-execution-frame.ts +8 -0
- package/dist/bundling-sources/shared_libs/play-runtime/perf-trace.ts +127 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-artifact-runtime-contract.ts +5 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-run-recovery-policy.ts +24 -1
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/admission/contracts.ts +56 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/admission/index.ts +13 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/admission/job.ts +41 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/admission/ports.ts +17 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/admission/postgres-adapter.ts +54 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/attempts/contracts.ts +114 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/attempts/engine-suspension.ts +108 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/attempts/index.ts +36 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/attempts/job.ts +97 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/attempts/ports.ts +104 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/attempts/postgres-fence-adapter.ts +263 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/attempts/worker-terminal-projection.ts +64 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/projection/contracts.ts +29 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/projection/gateway-adapter.ts +56 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/projection/index.ts +15 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/projection/job.ts +65 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/projection/ports.ts +17 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/sandbox-cleanup/contracts.ts +42 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/sandbox-cleanup/index.ts +17 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/sandbox-cleanup/job.ts +142 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/sandbox-cleanup/ports.ts +42 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/sandbox-cleanup/postgres-adapter.ts +102 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/terminal/contracts.ts +60 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/terminal/index.ts +16 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/terminal/job.ts +78 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/terminal/ports.ts +54 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/terminal/postgres-adapter.ts +71 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runtime-batching-registry.ts +4 -0
- package/dist/bundling-sources/shared_libs/play-runtime/protocol.ts +2 -0
- package/dist/bundling-sources/shared_libs/play-runtime/receipt-status.ts +5 -8
- package/dist/bundling-sources/shared_libs/play-runtime/run-failure.ts +3 -5
- package/dist/bundling-sources/shared_libs/play-runtime/run-identity.ts +168 -0
- package/dist/bundling-sources/shared_libs/play-runtime/run-ledger.ts +44 -5
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/child-play-resolver.ts +26 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/index.ts +3662 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/progress-sidecar.ts +47 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-deadline.ts +84 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-gateway-transport.ts +91 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-heartbeat.ts +424 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-progress-push.ts +321 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-sheet-persistence-retry.ts +110 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-terminal-push.ts +625 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-lifecycle.ts +72 -9
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-payload-transport.ts +6 -12
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona.ts +19 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/bundle.ts +0 -1
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/runtime-sandbox-reconciliation.ts +14 -44
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +103 -208
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-authority.ts +201 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-env.ts +6 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-operation-contract.ts +67 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-release-environment.ts +2 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-sandbox-contract.ts +68 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-scheduler-topology.ts +14 -2
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-telemetry.ts +108 -0
- package/dist/bundling-sources/shared_libs/play-runtime/sandbox-runs/contract.ts +4 -0
- package/dist/bundling-sources/shared_libs/play-runtime/sandbox-runs/runner-backend-adapter.ts +3 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backend.ts +7 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-deadline-reconciliation.ts +88 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-play-deploy-task.ts +124 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-play-run-task.ts +68 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-pool.ts +193 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-queue-lifecycle.ts +269 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-queue-suffix.ts +73 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-runtime-worker.ts +6642 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-shared.ts +897 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-worker-metrics.ts +120 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-worker-required-env.ts +76 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd.ts +476 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/gateway-heavy-request-admission.ts +47 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/gateway-progress-registry.ts +147 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/index.ts +27 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/lazy.ts +50 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/play-run-recovery.ts +98 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-budget-state.ts +260 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-pool.ts +1416 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-progress.ts +1255 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-rate-state.ts +942 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts +14636 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/receipt-gateway.ts +888 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/run-ledger-outbox-recovery.ts +355 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/run-terminal-transition.ts +46 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runner-push.ts +60 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-api-origin.ts +33 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-receipt-gateway-health.ts +64 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-sandbox-capacity.ts +835 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-sandbox-ledger-reconciliation.ts +1218 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-sandbox-operation.ts +207 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-scheduler-schema.ts +10 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/scheduler-capacity.ts +123 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/scheduler-launch-read-observability.ts +78 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/submit-admission.ts +169 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/terminal-contract.ts +20 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/worker-queue-metrics.ts +34 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/worker-resource-metrics.ts +249 -0
- package/dist/bundling-sources/shared_libs/play-runtime/sheet-attempt-sql.ts +7 -0
- package/dist/bundling-sources/shared_libs/play-runtime/step-progress.ts +296 -0
- package/dist/bundling-sources/shared_libs/play-runtime/tool-call/native-batch.ts +3 -3
- package/dist/bundling-sources/shared_libs/play-runtime/tool-call/runtime-step-receipts-adapter.ts +20 -1
- package/dist/bundling-sources/shared_libs/play-runtime/tool-execute-retry-policy.ts +60 -15
- package/dist/bundling-sources/shared_libs/play-runtime/tool-execution-outcome.ts +20 -0
- package/dist/bundling-sources/shared_libs/play-runtime/transient-service-error.ts +12 -0
- package/dist/bundling-sources/shared_libs/play-runtime/vercel-protection.ts +14 -1
- package/dist/bundling-sources/shared_libs/play-runtime/webhook-receipt-retry.ts +50 -0
- package/dist/bundling-sources/shared_libs/play-runtime/work-receipt-storage-contract.ts +165 -0
- package/dist/bundling-sources/shared_libs/play-runtime/work-receipts.ts +15 -23
- package/dist/bundling-sources/shared_libs/play-runtime/workflow-executor-auth.ts +169 -0
- package/dist/bundling-sources/shared_libs/play-runtime/zerobounce-batching.ts +122 -0
- package/dist/bundling-sources/shared_libs/plays/artifact-types.ts +2 -0
- package/dist/bundling-sources/shared_libs/plays/bundling/repository-adapter.ts +24 -0
- package/dist/bundling-sources/shared_libs/plays/child-run-projection.ts +174 -0
- package/dist/bundling-sources/shared_libs/plays/contracts.ts +2 -0
- package/dist/bundling-sources/shared_libs/plays/deploy/api-client.ts +267 -0
- package/dist/bundling-sources/shared_libs/plays/deploy/control-plane-types.ts +73 -0
- package/dist/bundling-sources/shared_libs/plays/deploy/manifest.ts +162 -0
- package/dist/bundling-sources/shared_libs/plays/deploy/project-serializer.ts +87 -0
- package/dist/bundling-sources/shared_libs/plays/deploy/source-file-path.ts +26 -0
- package/dist/bundling-sources/shared_libs/plays/deploy/target-paths.ts +36 -0
- package/dist/bundling-sources/shared_libs/plays/deployment-status.ts +1 -1
- package/dist/bundling-sources/shared_libs/plays/docflow.ts +1 -1
- package/dist/bundling-sources/shared_libs/plays/launch/input-contract.ts +400 -0
- package/dist/bundling-sources/shared_libs/plays/launch/prepare.ts +96 -0
- package/dist/bundling-sources/shared_libs/plays/local-file-discovery.ts +385 -0
- package/dist/bundling-sources/shared_libs/plays/play-grep-search.ts +112 -0
- package/dist/bundling-sources/shared_libs/plays/play-reference.ts +117 -0
- package/dist/bundling-sources/shared_libs/plays/run-input-summary.ts +260 -0
- package/dist/bundling-sources/shared_libs/plays/run-summary-types.ts +49 -0
- package/dist/bundling-sources/shared_libs/plays/secrets/errors.ts +19 -0
- package/dist/bundling-sources/shared_libs/plays/share/copy.ts +271 -0
- package/dist/bundling-sources/shared_libs/plays/share/metrics.ts +140 -0
- package/dist/bundling-sources/shared_libs/plays/share/public-read-model.ts +86 -0
- package/dist/bundling-sources/shared_libs/plays/share/seo-quality.ts +181 -0
- package/dist/bundling-sources/shared_libs/plays/share/static-pipeline-summary.ts +658 -0
- package/dist/bundling-sources/shared_libs/plays/share/types.ts +197 -0
- package/dist/bundling-sources/shared_libs/plays/sheet-filter.ts +347 -0
- package/dist/bundling-sources/shared_libs/plays/slack-hitl-timeout-error.ts +37 -0
- package/dist/bundling-sources/shared_libs/plays/standard-webhooks.ts +117 -0
- package/dist/bundling-sources/shared_libs/plays/static-pipeline.ts +6 -1
- package/dist/bundling-sources/shared_libs/plays/status-result.ts +388 -0
- package/dist/bundling-sources/shared_libs/plays/tool-result-types.ts +1 -1
- package/dist/bundling-sources/shared_libs/plays/transform-factor-structure.ts +377 -0
- package/dist/bundling-sources/shared_libs/plays/webhook-payload.ts +113 -0
- package/dist/bundling-sources/shared_libs/product-notifications/configuration.ts +7 -1
- package/dist/bundling-sources/shared_libs/product-notifications/default-policy.ts +3 -2
- package/dist/bundling-sources/shared_libs/product-notifications/overflow.ts +18 -0
- package/dist/bundling-sources/shared_libs/product-notifications/rolling-limit.ts +24 -0
- package/dist/bundling-sources/shared_libs/product-notifications/slack-delivery.ts +624 -0
- package/dist/bundling-sources/shared_libs/product-notifications/slack-payload.ts +140 -0
- package/dist/bundling-sources/shared_libs/product-notifications/slack-transport.ts +75 -0
- package/dist/bundling-sources/shared_libs/runtime-env.ts +6 -0
- package/dist/bundling-sources/shared_libs/security/email-blacklist.ts +42 -0
- package/dist/bundling-sources/shared_libs/security/header-safe-env.ts +10 -3
- package/dist/bundling-sources/shared_libs/security/slack-sanitize.ts +133 -0
- package/dist/cli/getting-started.d.mts +52 -0
- package/dist/cli/getting-started.d.ts +52 -0
- package/dist/cli/getting-started.js +65 -0
- package/dist/cli/getting-started.mjs +36 -0
- package/dist/cli/index.d.mts +9 -0
- package/dist/cli/index.d.ts +9 -0
- package/dist/cli/index.js +895 -407
- package/dist/cli/index.mjs +893 -414
- package/dist/{compiler-manifest-DsLbQaew.d.mts → compiler-manifest-x14KL83E.d.mts} +4 -2
- package/dist/{compiler-manifest-DsLbQaew.d.ts → compiler-manifest-x14KL83E.d.ts} +4 -2
- package/dist/index.d.mts +124 -154
- package/dist/index.d.ts +124 -154
- package/dist/index.js +132 -28
- package/dist/index.mjs +132 -28
- package/dist/install-integrity.json +182 -2
- package/dist/monitor-fleet-contract.d.mts +131 -0
- package/dist/monitor-fleet-contract.d.ts +131 -0
- package/dist/monitor-fleet-contract.js +406 -0
- package/dist/monitor-fleet-contract.mjs +367 -0
- package/dist/plays/bundle-play-file.d.mts +2 -2
- package/dist/plays/bundle-play-file.d.ts +2 -2
- package/dist/release.d.mts +255 -0
- package/dist/release.d.ts +255 -0
- package/dist/release.js +210 -0
- package/dist/release.mjs +183 -0
- package/package.json +21 -4
package/dist/bundling-sources/shared_libs/play-runtime/deployment/commands/roll-execution-relay.ts
ADDED
|
@@ -0,0 +1,521 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Controller-owned execution-relay generation rollout.
|
|
5
|
+
*
|
|
6
|
+
* Fly's blue/green deploy has a fixed kill timeout. That is not a valid drain
|
|
7
|
+
* contract for billable provider requests: an accepted request may outlive
|
|
8
|
+
* that timeout. This controller instead creates a cordoned green generation,
|
|
9
|
+
* switches only new ingress to it, and leaves blue started until each exact
|
|
10
|
+
* blue Machine proves zero live provider dispatches through its metrics port.
|
|
11
|
+
*/
|
|
12
|
+
import { spawnSync } from 'node:child_process';
|
|
13
|
+
import { FlyMachinesClient, requireFlyToken } from '../fly-machines';
|
|
14
|
+
import {
|
|
15
|
+
RECEIPT_GATEWAY_DRAIN_TIMEOUT,
|
|
16
|
+
stopAndDestroyCordonedMachines,
|
|
17
|
+
} from '../../deployment/fly-machine-lifecycle';
|
|
18
|
+
import {
|
|
19
|
+
exactFlyMachineRouteHeaders,
|
|
20
|
+
formatGatewayRouteProbeRetry,
|
|
21
|
+
GatewayRouteProbeHttpError,
|
|
22
|
+
waitForGatewayRouteProbe,
|
|
23
|
+
} from '../fly-gateway-route-probe';
|
|
24
|
+
import {
|
|
25
|
+
gatewayMachineConfig,
|
|
26
|
+
productionGatewayTopology,
|
|
27
|
+
RUNTIME_TOPOLOGY,
|
|
28
|
+
} from '../../deployment/runtime-topology';
|
|
29
|
+
|
|
30
|
+
export const EXECUTION_RELAY_ROLLOUT_METADATA =
|
|
31
|
+
'deepline_execution_relay_rollout';
|
|
32
|
+
export const EXECUTION_RELAY_SOURCE_METADATA =
|
|
33
|
+
'deepline_execution_relay_source_machine';
|
|
34
|
+
const app = RUNTIME_TOPOLOGY.production.components.executionRelay.app;
|
|
35
|
+
const topology = productionGatewayTopology('execution');
|
|
36
|
+
const healthUrl = `https://${app}.fly.dev/readyz`;
|
|
37
|
+
const pollMs = 5_000;
|
|
38
|
+
const timeoutMs = 10 * 60_000;
|
|
39
|
+
|
|
40
|
+
const reportGatewayRouteProbeRetry = (
|
|
41
|
+
retry: Parameters<typeof formatGatewayRouteProbeRetry>[0],
|
|
42
|
+
): void => {
|
|
43
|
+
console.warn(formatGatewayRouteProbeRetry(retry));
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
type FlyMachine = Awaited<
|
|
47
|
+
ReturnType<FlyMachinesClient['listMachines']>
|
|
48
|
+
>[number] & {
|
|
49
|
+
// The Fly API returns this field, but the generated client type has not yet
|
|
50
|
+
// caught up. Keep it optional so older API responses remain valid too.
|
|
51
|
+
cordoned?: boolean;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
function parseFlags(argv: string[]): Map<string, string | boolean> {
|
|
55
|
+
const values = new Map<string, string | boolean>();
|
|
56
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
57
|
+
const token = argv[i]!;
|
|
58
|
+
if (!token.startsWith('--')) throw new Error(`Unexpected ${token}.`);
|
|
59
|
+
const key = token.slice(2);
|
|
60
|
+
const value = argv[i + 1];
|
|
61
|
+
if (!value || value.startsWith('--')) values.set(key, true);
|
|
62
|
+
else {
|
|
63
|
+
values.set(key, value);
|
|
64
|
+
i += 1;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return values;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function requireApply(flags: Map<string, string | boolean>): void {
|
|
71
|
+
if (
|
|
72
|
+
flags.get('environment') !== 'production' ||
|
|
73
|
+
flags.get('apply') !== true
|
|
74
|
+
) {
|
|
75
|
+
throw new Error('Requires --environment production --apply.');
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function requireSha(flags: Map<string, string | boolean>): string {
|
|
80
|
+
const sha = flags.get('sha');
|
|
81
|
+
if (typeof sha !== 'string' || !/^[a-f0-9]{7,40}$/i.test(sha)) {
|
|
82
|
+
throw new Error('--sha must be a 7-40 character git SHA.');
|
|
83
|
+
}
|
|
84
|
+
return sha.toLowerCase();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function image(sha: string): string {
|
|
88
|
+
return `registry.fly.io/${app}:git-${sha}`;
|
|
89
|
+
}
|
|
90
|
+
function active(machine: FlyMachine): boolean {
|
|
91
|
+
return machine.state !== 'destroyed' && machine.state !== 'destroying';
|
|
92
|
+
}
|
|
93
|
+
function healthy(machine: FlyMachine): boolean {
|
|
94
|
+
return (
|
|
95
|
+
machine.state === 'started' &&
|
|
96
|
+
(machine.checks?.length ?? 0) > 0 &&
|
|
97
|
+
machine.checks!.every((check) => check.status === 'passing')
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
function candidateName(sha: string, index: number): string {
|
|
101
|
+
return `execution-${sha.slice(0, 12)}-${index + 1}`;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export function planExecutionRelayCutover(input: {
|
|
105
|
+
blue: FlyMachine[];
|
|
106
|
+
green: FlyMachine[];
|
|
107
|
+
sha: string;
|
|
108
|
+
}): { sourceMachineIds: string[]; greenMachineIds: string[] } {
|
|
109
|
+
if (
|
|
110
|
+
input.blue.length < topology.minimumMachines ||
|
|
111
|
+
input.blue.some(
|
|
112
|
+
(machine) =>
|
|
113
|
+
!healthy(machine) || machine.cordoned !== false || !machine.id,
|
|
114
|
+
)
|
|
115
|
+
) {
|
|
116
|
+
throw new Error(
|
|
117
|
+
'Execution relay serving generation is not a healthy uncordoned fleet.',
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
const images = new Set(
|
|
121
|
+
input.blue.map((machine) => machine.config?.image).filter(Boolean),
|
|
122
|
+
);
|
|
123
|
+
if (images.size !== 1)
|
|
124
|
+
throw new Error('Execution relay serving generation has mixed images.');
|
|
125
|
+
if (
|
|
126
|
+
input.green.length !== input.blue.length ||
|
|
127
|
+
input.green.some(
|
|
128
|
+
(machine) =>
|
|
129
|
+
!healthy(machine) ||
|
|
130
|
+
machine.cordoned !== true ||
|
|
131
|
+
machine.config?.image !== image(input.sha) ||
|
|
132
|
+
!machine.id,
|
|
133
|
+
)
|
|
134
|
+
) {
|
|
135
|
+
throw new Error(
|
|
136
|
+
'Execution relay green generation is not a complete cordoned healthy fleet.',
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
const sources = input.green.map(
|
|
140
|
+
(machine) => machine.config?.metadata?.[EXECUTION_RELAY_SOURCE_METADATA],
|
|
141
|
+
);
|
|
142
|
+
if (
|
|
143
|
+
new Set(sources).size !== input.blue.length ||
|
|
144
|
+
sources.some(
|
|
145
|
+
(id) => !id || !input.blue.some((machine) => machine.id === id),
|
|
146
|
+
)
|
|
147
|
+
) {
|
|
148
|
+
throw new Error(
|
|
149
|
+
'Execution relay candidates do not identify the exact blue generation.',
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
return {
|
|
153
|
+
sourceMachineIds: sources as string[],
|
|
154
|
+
greenMachineIds: input.green.map((machine) => machine.id!),
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Green must prove its full runtime contract before blue is cordoned. Exact
|
|
160
|
+
* readiness is only reachable through Fly Proxy after uncordon, so if that
|
|
161
|
+
* proof fails, immediately remove every green candidate from admission and
|
|
162
|
+
* leave blue serving. This makes an interrupted/retried activation converge
|
|
163
|
+
* on the same safe state instead of stranding a bad green fleet in traffic.
|
|
164
|
+
*/
|
|
165
|
+
export async function validateRelayCandidatesBeforeBlueCordon(input: {
|
|
166
|
+
candidateMachineIds: readonly string[];
|
|
167
|
+
machineIdsToUncordon: readonly string[];
|
|
168
|
+
uncordon: (machineId: string) => Promise<void>;
|
|
169
|
+
assertReady: (machineId: string) => Promise<void>;
|
|
170
|
+
cordon: (machineId: string) => Promise<void>;
|
|
171
|
+
}): Promise<void> {
|
|
172
|
+
try {
|
|
173
|
+
for (const machineId of input.machineIdsToUncordon) {
|
|
174
|
+
await input.uncordon(machineId);
|
|
175
|
+
}
|
|
176
|
+
await Promise.all(input.candidateMachineIds.map(input.assertReady));
|
|
177
|
+
} catch (error) {
|
|
178
|
+
const rollback = await Promise.allSettled(
|
|
179
|
+
input.candidateMachineIds.map(input.cordon),
|
|
180
|
+
);
|
|
181
|
+
const rollbackFailures = rollback
|
|
182
|
+
.filter(
|
|
183
|
+
(entry): entry is PromiseRejectedResult => entry.status === 'rejected',
|
|
184
|
+
)
|
|
185
|
+
.map((entry) =>
|
|
186
|
+
entry.reason instanceof Error
|
|
187
|
+
? entry.reason.message
|
|
188
|
+
: String(entry.reason),
|
|
189
|
+
);
|
|
190
|
+
if (rollbackFailures.length > 0) {
|
|
191
|
+
throw new Error(
|
|
192
|
+
`Execution relay candidate validation failed and green rollback failed: ${rollbackFailures.join('; ')}`,
|
|
193
|
+
{ cause: error },
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
throw error;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Restore the retained source generation after a later tuple check fails.
|
|
202
|
+
* Make blue reachable and prove every exact Machine before cordoning green so
|
|
203
|
+
* a failed Fly operation cannot turn a bad candidate into a gateway outage.
|
|
204
|
+
*/
|
|
205
|
+
export async function restoreRelaySourceGeneration(input: {
|
|
206
|
+
greenMachineIds: readonly string[];
|
|
207
|
+
blueMachineIds: readonly string[];
|
|
208
|
+
uncordon: (machineId: string) => Promise<void>;
|
|
209
|
+
cordon: (machineId: string) => Promise<void>;
|
|
210
|
+
assertReady: (machineId: string) => Promise<void>;
|
|
211
|
+
}): Promise<void> {
|
|
212
|
+
if (input.greenMachineIds.length === 0 || input.blueMachineIds.length === 0) {
|
|
213
|
+
throw new Error(
|
|
214
|
+
'Execution relay rollback requires exact green and blue Machine identities.',
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
for (const machineId of input.blueMachineIds) {
|
|
218
|
+
await input.uncordon(machineId);
|
|
219
|
+
}
|
|
220
|
+
await Promise.all(input.blueMachineIds.map(input.assertReady));
|
|
221
|
+
for (const machineId of input.greenMachineIds) {
|
|
222
|
+
await input.cordon(machineId);
|
|
223
|
+
}
|
|
224
|
+
await Promise.all(input.blueMachineIds.map(input.assertReady));
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function run(command: string, args: string[]): void {
|
|
228
|
+
const result = spawnSync(command, args, {
|
|
229
|
+
encoding: 'utf8',
|
|
230
|
+
stdio: 'inherit',
|
|
231
|
+
});
|
|
232
|
+
if (result.status !== 0)
|
|
233
|
+
throw new Error(
|
|
234
|
+
`${command} ${args.join(' ')} failed with ${result.status}.`,
|
|
235
|
+
);
|
|
236
|
+
}
|
|
237
|
+
async function inventory(client: FlyMachinesClient): Promise<FlyMachine[]> {
|
|
238
|
+
return await client.listMachines();
|
|
239
|
+
}
|
|
240
|
+
function candidates(machines: FlyMachine[], sha: string): FlyMachine[] {
|
|
241
|
+
return machines.filter(
|
|
242
|
+
(machine) =>
|
|
243
|
+
active(machine) &&
|
|
244
|
+
machine.config?.metadata?.[EXECUTION_RELAY_ROLLOUT_METADATA] === sha,
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
function serving(machines: FlyMachine[]): FlyMachine[] {
|
|
248
|
+
return machines.filter(
|
|
249
|
+
(machine) => active(machine) && machine.cordoned === false,
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
async function waitForGreen(
|
|
253
|
+
client: FlyMachinesClient,
|
|
254
|
+
sha: string,
|
|
255
|
+
count: number,
|
|
256
|
+
): Promise<FlyMachine[]> {
|
|
257
|
+
const deadline = Date.now() + timeoutMs;
|
|
258
|
+
let last = 'waiting for candidates';
|
|
259
|
+
while (Date.now() < deadline) {
|
|
260
|
+
const green = candidates(await inventory(client), sha);
|
|
261
|
+
try {
|
|
262
|
+
if (green.length !== count)
|
|
263
|
+
last = `expected ${count} candidates; found ${green.length}`;
|
|
264
|
+
else if (
|
|
265
|
+
green.some((machine) => !healthy(machine) || machine.cordoned !== true)
|
|
266
|
+
)
|
|
267
|
+
last = 'candidate health or cordon state is not ready';
|
|
268
|
+
else return green;
|
|
269
|
+
} catch (error) {
|
|
270
|
+
last = error instanceof Error ? error.message : String(error);
|
|
271
|
+
}
|
|
272
|
+
await new Promise((resolve) => setTimeout(resolve, pollMs));
|
|
273
|
+
}
|
|
274
|
+
throw new Error(`Execution relay candidates did not become ready: ${last}`);
|
|
275
|
+
}
|
|
276
|
+
async function assertExactReadyOnce(machineId: string): Promise<void> {
|
|
277
|
+
const response = await fetch(healthUrl, {
|
|
278
|
+
headers: exactFlyMachineRouteHeaders(machineId),
|
|
279
|
+
signal: AbortSignal.timeout(10_000),
|
|
280
|
+
});
|
|
281
|
+
if (!response.ok) {
|
|
282
|
+
const body = await response.text();
|
|
283
|
+
throw new GatewayRouteProbeHttpError({
|
|
284
|
+
status: response.status,
|
|
285
|
+
body,
|
|
286
|
+
expectedMachineId: machineId,
|
|
287
|
+
actualMachineId: response.headers.get('x-deepline-gateway-machine-id'),
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
if (response.headers.get('x-deepline-gateway-machine-id') !== machineId) {
|
|
291
|
+
throw new Error(
|
|
292
|
+
`Execution relay Machine ${machineId} failed its exact readiness probe.`,
|
|
293
|
+
);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
async function assertExactReady(machineId: string): Promise<void> {
|
|
298
|
+
await waitForGatewayRouteProbe({
|
|
299
|
+
description: `Execution relay Machine ${machineId}`,
|
|
300
|
+
probe: () => assertExactReadyOnce(machineId),
|
|
301
|
+
onRetry: reportGatewayRouteProbeRetry,
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
async function prepare(sha: string): Promise<void> {
|
|
305
|
+
run('bun', [
|
|
306
|
+
'scripts/ensure-runtime-image.ts',
|
|
307
|
+
'--kind',
|
|
308
|
+
'gateway',
|
|
309
|
+
'--app',
|
|
310
|
+
app,
|
|
311
|
+
'--config',
|
|
312
|
+
RUNTIME_TOPOLOGY.production.components.executionRelay.image.config,
|
|
313
|
+
'--dockerfile',
|
|
314
|
+
RUNTIME_TOPOLOGY.production.components.executionRelay.image.dockerfile,
|
|
315
|
+
'--sha',
|
|
316
|
+
sha,
|
|
317
|
+
]);
|
|
318
|
+
const client = new FlyMachinesClient(app, requireFlyToken(), fetch);
|
|
319
|
+
const initial = await inventory(client);
|
|
320
|
+
const existing = candidates(initial, sha);
|
|
321
|
+
const blue = serving(initial);
|
|
322
|
+
if (existing.length > 0 && existing.every((machine) => healthy(machine))) {
|
|
323
|
+
const alreadyPublic = existing.every(
|
|
324
|
+
(machine) => machine.cordoned === false,
|
|
325
|
+
);
|
|
326
|
+
const stillCordoned = existing.every(
|
|
327
|
+
(machine) => machine.cordoned === true,
|
|
328
|
+
);
|
|
329
|
+
if (!alreadyPublic && !stillCordoned) {
|
|
330
|
+
throw new Error(
|
|
331
|
+
'Execution relay candidates have mixed routing state; resume activation instead of preparing a replacement.',
|
|
332
|
+
);
|
|
333
|
+
}
|
|
334
|
+
if (alreadyPublic) {
|
|
335
|
+
await Promise.all(
|
|
336
|
+
existing.map((machine) => assertExactReady(machine.id!)),
|
|
337
|
+
);
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
if (existing.length === 0) {
|
|
342
|
+
if (
|
|
343
|
+
blue.length < topology.minimumMachines ||
|
|
344
|
+
blue.some((machine) => !healthy(machine) || !machine.id)
|
|
345
|
+
)
|
|
346
|
+
throw new Error(
|
|
347
|
+
'Cannot prepare an execution relay generation without a healthy serving fleet.',
|
|
348
|
+
);
|
|
349
|
+
for (const [index, source] of blue.entries()) {
|
|
350
|
+
await client.createMachine({
|
|
351
|
+
name: candidateName(sha, index),
|
|
352
|
+
region: topology.region,
|
|
353
|
+
skip_service_registration: true,
|
|
354
|
+
config: gatewayMachineConfig({
|
|
355
|
+
profile: 'production',
|
|
356
|
+
role: 'execution',
|
|
357
|
+
image: image(sha),
|
|
358
|
+
metadata: {
|
|
359
|
+
deepline_gateway_role: 'execution',
|
|
360
|
+
[EXECUTION_RELAY_ROLLOUT_METADATA]: sha,
|
|
361
|
+
[EXECUTION_RELAY_SOURCE_METADATA]: source.id!,
|
|
362
|
+
fly_process_group: topology.processGroup,
|
|
363
|
+
},
|
|
364
|
+
}),
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
await waitForGreen(client, sha, blue.length);
|
|
369
|
+
// Candidate proof before activation is the Fly health check alone. Exact
|
|
370
|
+
// readiness runs immediately after uncordon in `activate`, before the blue
|
|
371
|
+
// generation is cordoned or any later release promotion may proceed.
|
|
372
|
+
//
|
|
373
|
+
// That leaves a window in which unproven green briefly takes public ingress.
|
|
374
|
+
// The receipt gateway does not have this window: it force-routes a fixture
|
|
375
|
+
// through each still-cordoned candidate with `fly-force-instance-id` and
|
|
376
|
+
// re-asserts the cordon on both sides of the probe. Forced routing does
|
|
377
|
+
// reach a cordoned Machine -- that path passes on every production release
|
|
378
|
+
// -- so this rollout can adopt the same pre-uncordon proof. Tracked
|
|
379
|
+
// separately; do not assume the header is the blocker.
|
|
380
|
+
}
|
|
381
|
+
async function activate(sha: string): Promise<void> {
|
|
382
|
+
const client = new FlyMachinesClient(app, requireFlyToken(), fetch);
|
|
383
|
+
const machines = await inventory(client);
|
|
384
|
+
const green = candidates(machines, sha);
|
|
385
|
+
if (
|
|
386
|
+
green.length < topology.minimumMachines ||
|
|
387
|
+
green.some(
|
|
388
|
+
(machine) =>
|
|
389
|
+
!healthy(machine) ||
|
|
390
|
+
machine.config?.image !== image(sha) ||
|
|
391
|
+
!machine.id,
|
|
392
|
+
)
|
|
393
|
+
) {
|
|
394
|
+
throw new Error(
|
|
395
|
+
'Execution relay activation has no complete healthy green generation.',
|
|
396
|
+
);
|
|
397
|
+
}
|
|
398
|
+
const sourceMachineIds = green.map(
|
|
399
|
+
(machine) => machine.config?.metadata?.[EXECUTION_RELAY_SOURCE_METADATA],
|
|
400
|
+
);
|
|
401
|
+
if (
|
|
402
|
+
new Set(sourceMachineIds).size !== green.length ||
|
|
403
|
+
sourceMachineIds.some((id) => !id)
|
|
404
|
+
) {
|
|
405
|
+
throw new Error('Execution relay activation has no exact blue generation.');
|
|
406
|
+
}
|
|
407
|
+
await validateRelayCandidatesBeforeBlueCordon({
|
|
408
|
+
candidateMachineIds: green.map((machine) => machine.id!),
|
|
409
|
+
machineIdsToUncordon: green
|
|
410
|
+
.filter((machine) => machine.cordoned === true)
|
|
411
|
+
.map((machine) => machine.id!),
|
|
412
|
+
uncordon: async (machineId) => {
|
|
413
|
+
run('flyctl', ['machine', 'uncordon', machineId, '-a', app]);
|
|
414
|
+
},
|
|
415
|
+
assertReady: assertExactReady,
|
|
416
|
+
cordon: async (machineId) => {
|
|
417
|
+
run('flyctl', ['machine', 'cordon', machineId, '-a', app]);
|
|
418
|
+
},
|
|
419
|
+
});
|
|
420
|
+
const refreshed = await inventory(client);
|
|
421
|
+
for (const machineId of sourceMachineIds as string[]) {
|
|
422
|
+
const blue = refreshed.find((machine) => machine.id === machineId);
|
|
423
|
+
if (!blue) continue;
|
|
424
|
+
if (!active(blue)) {
|
|
425
|
+
throw new Error(
|
|
426
|
+
`Execution relay source Machine ${machineId} is no longer active.`,
|
|
427
|
+
);
|
|
428
|
+
}
|
|
429
|
+
if (blue.cordoned === false) {
|
|
430
|
+
run('flyctl', ['machine', 'cordon', machineId, '-a', app]);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
async function rollback(sha: string): Promise<void> {
|
|
436
|
+
const client = new FlyMachinesClient(app, requireFlyToken(), fetch);
|
|
437
|
+
const current = await inventory(client);
|
|
438
|
+
const green = candidates(current, sha);
|
|
439
|
+
if (
|
|
440
|
+
green.length < topology.minimumMachines ||
|
|
441
|
+
green.some((machine) => !machine.id)
|
|
442
|
+
) {
|
|
443
|
+
throw new Error(
|
|
444
|
+
'Execution relay rollback requires a complete candidate generation.',
|
|
445
|
+
);
|
|
446
|
+
}
|
|
447
|
+
const sourceMachineIds = green.map(
|
|
448
|
+
(machine) => machine.config?.metadata?.[EXECUTION_RELAY_SOURCE_METADATA],
|
|
449
|
+
);
|
|
450
|
+
if (
|
|
451
|
+
new Set(sourceMachineIds).size !== green.length ||
|
|
452
|
+
sourceMachineIds.some((machineId) => !machineId)
|
|
453
|
+
) {
|
|
454
|
+
throw new Error('Execution relay rollback has no exact source generation.');
|
|
455
|
+
}
|
|
456
|
+
const blue = current.filter((machine) =>
|
|
457
|
+
(sourceMachineIds as string[]).includes(machine.id ?? ''),
|
|
458
|
+
);
|
|
459
|
+
if (
|
|
460
|
+
blue.length !== sourceMachineIds.length ||
|
|
461
|
+
blue.some((machine) => !machine.id || !active(machine) || !healthy(machine))
|
|
462
|
+
) {
|
|
463
|
+
throw new Error(
|
|
464
|
+
'Execution relay rollback source generation is not a complete healthy retained fleet.',
|
|
465
|
+
);
|
|
466
|
+
}
|
|
467
|
+
await restoreRelaySourceGeneration({
|
|
468
|
+
greenMachineIds: green.map((machine) => machine.id!),
|
|
469
|
+
blueMachineIds: sourceMachineIds as string[],
|
|
470
|
+
uncordon: async (machineId) => {
|
|
471
|
+
run('flyctl', ['machine', 'uncordon', machineId, '-a', app]);
|
|
472
|
+
},
|
|
473
|
+
cordon: async (machineId) => {
|
|
474
|
+
run('flyctl', ['machine', 'cordon', machineId, '-a', app]);
|
|
475
|
+
},
|
|
476
|
+
assertReady: assertExactReady,
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
/** Remove only a candidate that never received public traffic. This mirrors
|
|
480
|
+
* receipt cleanup so a failed pre-commit proof cannot strand relay Machines. */
|
|
481
|
+
async function cleanup(sha: string): Promise<void> {
|
|
482
|
+
const client = new FlyMachinesClient(app, requireFlyToken(), fetch);
|
|
483
|
+
const targets = candidates(await inventory(client), sha);
|
|
484
|
+
if (targets.some((machine) => !machine.id)) {
|
|
485
|
+
throw new Error(
|
|
486
|
+
'Execution relay candidate cleanup requires exact Fly Machine identities.',
|
|
487
|
+
);
|
|
488
|
+
}
|
|
489
|
+
if (targets.some((machine) => machine.cordoned !== true)) {
|
|
490
|
+
throw new Error(
|
|
491
|
+
'Refusing to remove an execution relay candidate that received public traffic.',
|
|
492
|
+
);
|
|
493
|
+
}
|
|
494
|
+
await stopAndDestroyCordonedMachines({
|
|
495
|
+
machineIds: targets.map((machine) => machine.id!),
|
|
496
|
+
readMachines: () => inventory(client),
|
|
497
|
+
listProviderMachineIds: async () =>
|
|
498
|
+
(await client.listMachines())
|
|
499
|
+
.map((machine) => machine.id)
|
|
500
|
+
.filter((id): id is string => Boolean(id)),
|
|
501
|
+
stopMachine: (machineId) =>
|
|
502
|
+
client.stopMachine(machineId, {
|
|
503
|
+
signal: 'SIGTERM',
|
|
504
|
+
timeout: RECEIPT_GATEWAY_DRAIN_TIMEOUT,
|
|
505
|
+
}),
|
|
506
|
+
deleteMachine: (machineId) => client.deleteMachine(machineId, false),
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
export async function main(): Promise<void> {
|
|
510
|
+
const command = process.argv[2];
|
|
511
|
+
const flags = parseFlags(process.argv.slice(3));
|
|
512
|
+
requireApply(flags);
|
|
513
|
+
const sha = requireSha(flags);
|
|
514
|
+
if (command === 'prepare') return await prepare(sha);
|
|
515
|
+
if (command === 'activate') return await activate(sha);
|
|
516
|
+
if (command === 'rollback') return await rollback(sha);
|
|
517
|
+
if (command === 'cleanup') return await cleanup(sha);
|
|
518
|
+
throw new Error(
|
|
519
|
+
'Usage: roll-execution-relay.ts prepare|activate|rollback|cleanup --environment production --sha <sha> --apply',
|
|
520
|
+
);
|
|
521
|
+
}
|