SwiftDeploy is a deployment automation demo for a containerized FastAPI service. Describe the deployment in manifest.yaml; the Python CLI renders Docker Compose and Nginx configuration, deploys the stack, checks health and policy, and records events for an audit report.
It brings together four parts of a deployment workflow:
- Configuration generation from a manifest and Jinja templates
- Policy checks with Open Policy Agent (OPA)
- Service and deployment observability through FastAPI and Prometheus metrics
- Deployment history and audit reports for reviewing what happened
| Path | Purpose |
|---|---|
swiftdeploy |
CLI for rendering configuration, deploying, checking status, and creating audit reports |
manifest.yaml |
Service, network, Nginx, and OPA settings |
templates/ |
Jinja templates for generated Compose and Nginx configuration |
app/ |
FastAPI service, runtime dependencies, and test dependencies |
policies/ |
OPA infrastructure and canary policies with Rego tests |
tests/ |
Python endpoint and chaos-control tests |
.github/workflows/deploy.yaml |
CI checks and container integration workflow |
Generated docker-compose.yml and nginx.conf files are created from the manifest and templates; they are intentionally not committed.
| Command | Responsibility |
|---|---|
init |
Generate Compose and Nginx configuration |
validate |
Preflight check of configuration and dependencies |
deploy |
Policy-check, deploy, and health-check |
promote |
Switch canary/stable mode and verify it |
status |
Continuously observe application + policies |
audit |
Turn event history into an audit report |
teardown |
Remove the deployment |
Run ./swiftdeploy without a command to see the supported command syntax.
- Configuration validation (
validate): is the deployment configuration valid? - Runtime health (
/healthz): is the application alive and responding? - Policy validation (OPA): does the current state satisfy the defined operational rules?
- Observability (
/metrics,status,history.jsonl,audit_report.md): what is happening, and what happened?
manifest
β
load configuration
β
check infrastructure policy
β
generate Compose + Nginx
β
docker compose up
β
wait for /healthz
β
record deployment
Set SWIFTDEPLOY_REQUIRE_OPA=1 to make policy gates fail when OPA is
unavailable instead of warning and continuing. It is enabled in CI; leaving it
unset preserves the default local-development behavior.
When currently on canary:
canary
β
scrape metrics
β
calculate error rate + P99
β
check canary policy
β
allowed?
βββ NO β stop
βββ YES
β
change manifest
β
regenerate Compose
β
recreate app
β
verify /healthz
β
stable
metrics
β
calculate operational state
β
query OPA
β
display dashboard
β
record history
β
repeat every 5 seconds
history.jsonl
β
parse events
β
identify violations
β
summarize promotions
β
audit_report.md
status is a deployment observability console. Every 5 seconds it scrapes /metrics and collects application, policy, and host information.
/metrics
β
βΌ
scrape_metrics()
β
βββββββββ΄βββββββββ
βΌ βΌ
traffic stats app state
β β
βββ req/s βββ uptime
βββ error rate βββ mode
βββ P99 βββ chaos
β
βΌ
OPA policies
/ \
infra policy canary policy
Application metrics
- Req/s: throughput
- Error rate: percentage of 5xx responses
- P99 latency: tail latency
- Also reads uptime, current deployment mode, and chaos state
Policy evaluation
The dashboard displays service metrics and asks OPA whether they meet the configured policies:
query_opa(manifest, "swiftdeploy/canary", canary_input) # canary safety
query_opa(manifest, "swiftdeploy/infra", host_stats) # host/infrastructureExample output:
Infrastructure Policy: β PASS
Canary Safety Policy: β PASS
Infrastructure Policy: β FAIL
β³ disk free below threshold
Canary Safety Policy: β FAIL
β³ error rate exceeds threshold
Metrics tell you what is happening. Policy tells you whether that is acceptable under your rules.
The app exposes its chaos state as a metric, which status displays:
The POST /chaos control endpoint is available only in canary mode and requires
the X-Chaos-Token request header. Set CHAOS_TOKEN in the environment before
generating or starting the Compose stack; if it is unset, the endpoint is
disabled. Keep this token private and do not commit it.
chaos_val = int(metrics.get("chaos_active", 0))| Value | State |
|---|---|
| 0 | none |
| 1 | slow |
| 2 | error |
This is shown next to throughput, errors, latency, deployment mode, and policy compliance, which gives a clear demo workflow:
Normal
β
Inject chaos
β
Latency/errors change
β
Metrics reflect degradation
β
OPA evaluates canary safety
β
Promotion can be blocked
SwiftDeploy calls append_history(...) throughout the program. The file is JSON Lines: each line is an independent JSON event.
Events recorded:
deploypromoteteardownpolicy_checkopa_unavailablemetrics_scrape_failedstatus_scrape
Example:
{"timestamp":"...","event":"deploy","mode":"canary"}
{"timestamp":"...","event":"policy_check","gate":"pre_deploy","allowed":true}
{"timestamp":"...","event":"status_scrape","req_s":4.2}./swiftdeploy auditReads history.jsonl and writes audit_report.md with three sections:
- Timeline: deploy, promote, teardown, policy checks, OPA unavailable, metrics scrape failures
- Policy violations: found in both
policy_checkevents and livestatus_scrapeevents - Mode changes: e.g.
canary β stable,stable β canary
Application
β
SwiftDeploy events
β
history.jsonl
β
audit
β
audit_report.md
- Python 3.11 (the version used by CI) for the CLI and tests
- Docker Engine with the Docker Compose plugin
The app runs in a Python container. The local CLI uses PyYAML, Jinja2, and psutil.
From the repository root:
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install pyyaml jinja2 psutil
docker build -t swiftdeploy:latest .
./swiftdeploy init
docker compose config --quiet
./swiftdeploy deployThe default manifest deploys the app in canary mode. Once deployment is healthy,
the service is available at http://localhost:5050. Useful endpoints:
| Endpoint | Purpose |
|---|---|
/healthz |
Service health and deployment metadata |
/metrics |
Prometheus-format metrics |
POST /chaos |
Authenticated chaos controls; canary mode only |
The chaos endpoint is disabled unless CHAOS_TOKEN is set. Export a private
token before deploying if you want to use it:
export CHAOS_TOKEN="$(python -c 'import secrets; print(secrets.token_urlsafe(32))')"
./swiftdeploy deploySend the token in the X-Chaos-Token header to activate a test scenario or
recover the service:
curl -X POST http://localhost:5050/chaos \
-H "X-Chaos-Token: $CHAOS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"mode":"error","rate":0.5}'
curl -X POST http://localhost:5050/chaos \
-H "X-Chaos-Token: $CHAOS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"mode":"recover"}'python -m pip install -r app/requirements-test.txt
python -m pytest tests/The test requirements include the app's runtime requirements, plus pytest and
httpx. The Docker image installs only app/requirements.txt.
The GitHub Actions workflow runs Python linting and tests, checks and tests the
OPA policies, generates the deployment configuration, validates it with
docker compose config, then deploys the container stack and checks its health.
CI requires OPA to be available for the pre-deployment policy gate.
Set SWIFTDEPLOY_REQUIRE_OPA=1 locally to make the CLI fail if OPA is
unavailable. By default, an unavailable OPA service produces a warning and the
CLI continues, which is useful during local development.
Use ./swiftdeploy teardown to stop and remove the stack and its volumes. Add
--clean to also remove generated configuration files.
