Skip to content

Deployment

The deploy stage provisions infrastructure via Terraform and deploys container images to Azure Container Apps. Each application deploys in its own stage with lockBehavior: sequential to prevent concurrent deployments to the same environment.

Deployment Flow

Terraform

Each container app has its own Terraform configuration in azure/infra/. The deploy step runs:

  1. Install -- installs the Terraform CLI
  2. Init -- initializes the backend (Azure Storage Account)
  3. Apply -- applies the plan created in the plan_release stage

Infrastructure and application code are deployed together. This means environment variables, replica scaling, domain configuration, and feature flags can all be changed in the same PR as the application code.

Why Terraform for deployments?

Terraform manages the full Container App configuration alongside the application image. This coupling ensures that infrastructure changes (e.g., adding an env var for a new feature flag) ship with the code that uses them, all in one PR.

Container Apps

The following applications deploy as Azure Container Apps:

  • Web (per site: feyenoord, de-kuip)
  • API
  • Match Gateway
  • API Gateway
  • GraphQL Router

Each deployment is verified after apply.

Deployment Verification

After Terraform applies, the pipeline runs cicd/scripts/verify-container-app-deployment.sh. This script polls the Container App for a healthy state using exponential backoff:

  • Initial delay: 5 seconds
  • Maximum delay: 30 seconds
  • Maximum retries: 12

The script checks:

  • Container App provisioning state
  • Active revision status
  • Running replica count
  • Revision health state

If the deployment fails verification after all retries, the pipeline fails.

CDN Assets

Web application static assets are uploaded to Azure Blob Storage during the build stage, not during deploy. See Docker Builds for details.

The CDN architecture:

EnvironmentStorage AccountCDN Domain
TSTfeyewebsitestestcdnstcdn-tst.feyenoord.com
ACCfeyewebsitesacccdnstcdn-acc.feyenoord.com
PRDfeyewebsitesprodcdnstcdn.feyenoord.com

Cloudflare routes CDN domain requests to the corresponding Azure Blob Storage container. Next.js content-hashed filenames ensure assets from multiple deployments coexist safely in the same storage container.

Static Web Apps

Two applications deploy as Azure Static Web Apps (not Container Apps):

  • Sanity Studio -- deployed with a deploy token, one build per environment
  • Storybook -- deployed to TST only

These use the deploy-static-web-app.yaml step template and do not require Terraform.

Post-Deployment Steps

API

After API deployment:

  1. Algolia reindex -- triggers index rebuilds for all tenant/language combinations (feyenoord + de-kuip, nl + en)
  2. App Insights annotation -- creates a release annotation in Application Insights

All Container Apps

After each container app deployment:

  1. App Insights annotation -- records the release in Application Insights with the format <app> <branch>-<buildId>

Sequential Locking

All deploy stages use lockBehavior: sequential. If two pipelines try to deploy the same app to the same environment concurrently, the second one queues and waits for the first to complete. This prevents deployment conflicts and Terraform state locks.