Azure DevOps pipeline for the GALS API
The pipeline in azure-pipelines.yml builds, tests, pushes a container image, optionally applies Storage/Scripts/000_all.sql and Storage/Scripts/022_seed_superadmin_role_permissions.sql once each (tracked in system_dbo."AppliedScript"), updates ACI aci-gals-api-dev-c98f, and smokes GET /hc.
Create the pipeline
1. Apply gals.infrastructure.terraform to PTL DEV first, including environments/ptl-dev.secrets.tfvars. 2. In Azure DevOps, create a pipeline from this repository's azure-pipelines.yml. 3. Set parameter azureServiceConnection to the ARM service connection used by Terraform.
The connection needs AcrPush on acrgalsdevc98f, Contributor on RG-WE-GALSDEV, and Key Vault Get/List for the postgres-admin-* secrets used only by the schema job.
Runtime secrets
Do not create an API variable group for secrets. ACI already receives KEY_VAULT_URI and AZURE_CLIENT_ID. The host calls AddAzureKeyVault when KEY_VAULT_URI is set and binds:
- -
DatabaseContextConfiguration--DefaultConnection - -
AzureAd--ClientSecret - -
BusinessCentralConfiguration--ClientSecret - -
MitaNotificationsConfiguration--Secret(optional; created by Terraform only whenmita_notifications_secretis set)
Non-secret settings are Terraform ACI environment variables.
Local development keeps using appsettings.Local.json / appsettings.Development.json when KEY_VAULT_URI is unset.
Parameters
| Parameter | Default | Purpose |
|---|---|---|
azureServiceConnection | placeholder | ARM service connection |
resourceGroup | RG-WE-GALSDEV | Target resource group |
containerRegistry | acrgalsdevc98f | Image registry |
containerGroupName | aci-gals-api-dev-c98f | ACI group to update |
keyVaultName | kv-gals-dev-c98f | Source of Postgres ops secrets |
postgresServerName | psql-gals-dev-c98f | Firewall + psql target |
applyDatabaseScripts | false | One-time bootstrap. Turn on for a single run to apply 000_all.sql and the SuperAdmin seed. Later runs leave it off. AppliedScript also skips a script that was already applied. |
First deploy
1. Confirm Terraform has created ACR, the user-assigned identity, Key Vault secrets, and the ACI DNS name gals-api-dev-c98f. 2. Run the pipeline on main with applyDatabaseScripts enabled. Leave that parameter off on later runs. 3. Confirm GET https://gals-api-dev2-c98f.italynorth.azurecontainer.io/hc returns 200 (Caddy TLS sidecar on PTL DEV). 4. Portal VITE_APP_API_URL / Key Vault portal-api-base-url must be that HTTPS URL. MITA uses Cloudflare HTTPS instead of the Caddy sidecar.
Deploy updates the ACI image in place with az container create on the existing group (no delete). See Update container instances. Caddy certs persist on an Azure Files share so image updates do not burn Let's Encrypt rate limits.
MITA DEV manual deploy
For client subscription GovMT Hybrid Dev / resource group GALS-DIN-rg, do not use the PTL pipeline defaults above. Follow the runbook in the infrastructure repo:
gals.infrastructure.terraform/docs/manual-mita-dev-deploy.md
| Resource | MITA DEV name |
|---|---|
| Subscription | c66c9181-95ae-4824-87f8-43a6209b83c9 |
| Resource group | GALS-DIN-rg |
| ACR | acrgalsdevc66c |
| ACI | aci-gals-api-dev-c98f (private VNet; container name matches group) |
| Identity | id-gals-api-dev-c66c |
Scripts:
<pre><code class="language-bash">./scripts/Build-Push-ApiImage.sh acrgalsdevc66c gals-api mita-dev ./scripts/Update-AciImage.sh GALS-DIN-rg aci-gals-api-dev-c98f \ acrgalsdevc66c.azurecr.io/gals-api:mita-dev \ aci-gals-api-dev-c98f
Smoke GET /hc on the public HTTPS API URL (Cloudflare when configured). Set Key Vault portal-api-base-url to that same HTTPS base so the portal build can use it.
Docs site (Mintlify static export)
The same pipeline publishes OpenAPI from Service.dll, builds a Mintlify static export with scripts/Build-DocsStatic.sh, pushes gals-docs to ACR, and updates ACI group aci-gals-docs-dev (container gals-docs).
| Parameter | Default | Purpose |
|---|---|---|
docsContainerGroupName | aci-gals-docs-dev | Docs ACI group |
docsSiteUrl | https://gals-docs-dev.local | Canonical URL passed to staticmint |
Terraform must create the docs ACI group (nginx + oauth2-proxy) and Entra app registration before the Docs stage can succeed. See Docs hosting.
Local OpenAPI regeneration:
<pre><code class="language-powershell">./scripts/Export-OpenApi.ps1
Local Mintlify preview (after OpenAPI export):
<pre><code class="language-bash">npm i -g mint cd docs mint dev