Orchestrator & Strategies

The orchestrator (foundry-ops/orchestrator/deploy.py) is the single deploy brain. It reads the central manifest, looks up one service, and dispatches on its deploy.strategy. It uses only the Python standard library plus the tofu, aws, and shell tools available on the runner.

Invocation

python3 orchestrator/deploy.py deploy \
  --service web --env prod \
  --manifest ops/platform.json \
  --repo-root caller [--auto-approve]

The reusable workflow supplies these arguments — see the thin-caller & reusable workflow.

Strategy status

StrategyStatusBehavior
staticimplementedSmart IaC → build → S3 sync → CloudFront invalidate
servicestubbedExits with a Phase-3 message (ECS engine not yet relocated here)
desktopstubbedExits; the launcher still ships via a separate tag-release workflow
game-publisherstubbedExits with a Phase-3 message (UE5 publish not yet relocated)
noneno-opLogs that there is nothing to deploy and returns

The static path (implemented)

  1. Smart IaC. tofu init, then tofu plan -detailed-exitcode: exit 0 = no changes (skip apply), exit 2 = changes (apply the saved plan), exit 1 = error (fail). It then reads the bucket and distribution id from the stack's OpenTofu outputs.
  2. Build. Runs the service's buildCommand from the caller repo root, with deploy.iac.buildEnv merged into the environment.
  3. Publish. aws s3 sync <distDir> s3://<bucket> --delete then a CloudFront invalidation of /*.

Approval

The reusable workflow passes --auto-approve, so the orchestrator never blocks on a prompt. Manual approval for an environment is enforced by the GitHub Environment's required reviewers, driven by autoApprove — not by the script.

The stubbed strategies are tracked as “Phase 3” — relocating the existing ECS / Tauri / UE5 deploy engines into foundry-ops for parity. Until then, only static deploys through this orchestrator.