GALS API

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:

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

ParameterDefaultPurpose
azureServiceConnectionplaceholderARM service connection
resourceGroupRG-WE-GALSDEVTarget resource group
containerRegistryacrgalsdevc98fImage registry
containerGroupNameaci-gals-api-dev-c98fACI group to update
keyVaultNamekv-gals-dev-c98fSource of Postgres ops secrets
postgresServerNamepsql-gals-dev-c98fFirewall + psql target
applyDatabaseScriptsfalseOne-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

ResourceMITA DEV name
Subscriptionc66c9181-95ae-4824-87f8-43a6209b83c9
Resource groupGALS-DIN-rg
ACRacrgalsdevc66c
ACIaci-gals-api-dev-c98f (private VNet; container name matches group)
Identityid-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).

ParameterDefaultPurpose
docsContainerGroupNameaci-gals-docs-devDocs ACI group
docsSiteUrlhttps://gals-docs-dev.localCanonical 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