Deployments

How We Deploy

Terraform + GitHub Actions + Azure Container Apps deployment guide.

How We Deploy

echo ships three containers (docs, server, agent). Infrastructure lives under packages/terraform, images are produced by GitHub Actions, and Azure Container Apps hosts each workload. This page replaces the old packages/docs/DEPLOYMENT.md summary and walks through the process chronologically.

1. Architecture and prerequisites

  • Containers: echo-docs, echo-server, agent.
  • Azure resources: dedicated Container Apps environment per stage (echo-dev-rg, echo-prod-rg), PostgreSQL Flexible Server, and an Azure Container Registry shared by both.
  • Domains: dev endpoints live on dev-*.echo.onenine.ca, prod on *.echo.onenine.ca (see Custom Domains).
  • Tools required: Azure CLI, Terraform ≥ 1.6, access to the GitHub repository, and credentials stored as described in GitHub Secrets).

2. Build artifacts

Each package has its own Dockerfile:

  • apps/docs/Dockerfile – Next.js/Fumadocs static output (next build + standalone server).
  • packages/server/Dockerfile – Express API with pnpm + Drizzle migrations baked in.
  • packages/agent/Dockerfile – Python runtime with uv/poetry lock (see uv.lock).

GitHub Actions build these images on every push to main, tag them with the commit SHA, and push them to Azure Container Registry (see GitHub Secrets for required credentials).

3. Terraform environments

Directory layout:

  • packages/terraform/development
  • packages/terraform/production
  • Shared modules under packages/terraform/modules/{docs,server,agent}

Each environment declares the same resources:

ResourcePurpose
Resource GroupNamespace for all assets.
Container RegistryStores Docker images used by Container Apps and the migration job.
Azure PostgreSQL Flexible ServerBacking store for Express. Connection string is exported for GitHub Secrets.
Container Apps EnvironmentShared infrastructure for the 3 services.
Container Apps (echo-docs, echo-server, agent)Run the built images with secrets wired in.

Apply steps

cd packages/terraform/development
terraform init
terraform apply -var="image_tag=sha-abcdef"

Use the same process for production, but be mindful that the GitHub workflow gates prod deploys behind a manual approval.

4. GitHub Actions workflows

  • Build & push – triggered on every main push, produces Docker images and uploads artifacts that subsequent jobs reuse.
  • Terraform deploy (dev) – pulls the latest image tag, runs pnpm db:migrate in an Azure Container Instance (see MIGRATION_SETUP.md), and then updates the Container Apps rev.
  • Terraform deploy (prod) – same steps, but manual. You must type “production” to confirm.

Secrets referenced in these workflows live in GitHub Secrets.

5. Database migrations

Before each Container App revision rolls out, the workflow:

  1. Starts a temporary Azure Container Instance with the freshly built packages/server image.
  2. Runs pnpm db:migrate (wrapper around Drizzle’s migrate-with-rollback script).
  3. Aborts the deployment and sends a Slack alert if migrations fail (SLACK_WEBHOOK_URL).

Manual rollback commands live in MIGRATION_SETUP.md. Locally you can mimic the same behavior with pnpm db:migrate and pnpm db:rollback -- --count=1 --confirm.

6. Releasing a single package

Need to redeploy only the agent or server? Terraform lets you target modules:

cd packages/terraform/development
terraform plan  -target=module.agent  -var="image_tag=sha-latest"
terraform apply -target=module.agent  -var="image_tag=sha-latest"

This updates just one Container App using the specified image tag.

7. Verification

  • Docs – served from echo-docs Container App and locked behind the middleware in apps/docs/middleware.ts; set DOCS_BASIC_AUTH_USER and DOCS_BASIC_AUTH_PASS secrets on the app before exposing it publicly.
  • ServerGET https://<env-domain>/health.
  • Agent – check LiveKit logs for worker startup; simulate inbound SIP calls.
  • Database – verify drizzle_migrations table contains the new entries.

Follow this order: build → terraform plan/apply → watch GitHub Actions → verify health endpoints. When you need more detail about the CI/CD pieces or infrastructure, jump to Auto-Deployment Flow, GitHub Secrets, and Custom Domains.