Deploy Model
A multi-repo deploy is manifest-driven and orchestrated centrally. A service repo holds almost no deploy logic — it just calls into foundry-ops, which owns the pipeline.
The flow
service-repo push
→ thin caller workflow (in the service repo)
→ foundry-ops reusable deploy.yml (workflow_call)
→ orchestrator (orchestrator/deploy.py)
→ reads foundry-ops/platform.json, dispatches on deploy.strategy
→ smart IaC: tofu plan → apply ONLY on change
→ build
→ publish (e.g. S3 sync + CloudFront invalidate for static)Who owns what
| Piece | Lives in | Role |
|---|---|---|
| Platform shape | foundry-ops/platform.json | Declares services, strategies, IaC targets |
| Thin caller | Each service repo | Minimal workflow that calls foundry-ops |
| Reusable workflow + orchestrator | foundry-ops | Checkout, credentials, and the deploy engine |
| Infrastructure | foundry-iac + per-repo ci/iac | Shared control plane + app-edge stacks |
Smart IaC
The orchestrator plans the service's IaC stack with tofu plan -detailed-exitcode and only applies when there is an actual change (exit code 2); a no-change plan (exit 0) skips the apply. This keeps every deploy cheap and idempotent. Details in Orchestrator & Strategies.
Two deploy models coexist today
Monorepo (in-repo):foundry generateemits a self-contained pipeline +ci/scripts/that run inside the same repo as the manifest. This is what a single-repo platform uses.
Multi-repo (orchestrated): the flow above, owned byfoundry-ops. Today it implements thestaticstrategy end-to-end;service,desktop, andgame-publisherare stubbed. Thin callers are generated from the central manifest byfoundry generate callers; the reusable workflow and orchestrator engine are hand-maintained in the ops repo.