Azure Container Apps Provider
Deploy preview environments to Azure Container Apps.
How it works
- Build: uses Azure Container Registry (ACR) Tasks to build the Docker image remotely. ACR clones the repo and builds without requiring local Docker.
- Deploy: creates or updates an Azure Container App in your managed environment.
- Delete: deletes the Container App (the managed environment persists).
- List: lists all Container Apps in the resource group tagged with Previewops metadata.
Prerequisites
- An Azure subscription.
- An Azure resource group.
- An Azure Container Registry (ACR).
- An Azure Container Apps managed environment.
- An Azure service principal with the right permissions.
Step 1 — Create a resource group (if needed)
az group create --name previewops-rg --location eastus
Step 2 — Create an Azure Container Registry
az acr create \
--resource-group previewops-rg \
--name mypreviewops \
--sku Basic
Note: the registry name must be globally unique. The acrServer value will be mypreviewops.azurecr.io.
Step 3 — Create a Container Apps managed environment
az containerapp env create \
--name previewops-env \
--resource-group previewops-rg \
--location eastus
This also creates a Log Analytics workspace automatically (~$2–5/month depending on log volume).
Step 4 — Create a service principal
# Get your subscription ID
SUBSCRIPTION_ID=$(az account show --query id -o tsv)
# Create the service principal
az ad sp create-for-rbac \
--name previewops-sp \
--role Contributor \
--scopes /subscriptions/$SUBSCRIPTION_ID/resourceGroups/previewops-rg \
--sdk-auth
This outputs JSON with clientId, clientSecret, tenantId, and subscriptionId.
Store each value as a secret:
| Secret | JSON field |
|---|---|
AZURE_CLIENT_ID |
clientId |
AZURE_CLIENT_SECRET |
clientSecret |
AZURE_TENANT_ID |
tenantId |
AZURE_SUBSCRIPTION_ID |
subscriptionId |
Step 5 — Grant ACR push permission to the service principal
ACR_ID=$(az acr show --name mypreviewops --resource-group previewops-rg --query id -o tsv)
az role assignment create \
--assignee <clientId-from-step-4> \
--role AcrPush \
--scope $ACR_ID
Step 6 — Enable managed identity on the environment and grant AcrPull
Previewops configures Container Apps to pull images using the managed environment's system-assigned identity. You must enable it and grant it AcrPull on your registry:
# Enable system-assigned identity on the managed environment
az containerapp env identity assign \
--name previewops-env \
--resource-group previewops-rg \
--system-assigned
# Get the identity's principal ID
ENV_PRINCIPAL_ID=$(az containerapp env show \
--name previewops-env \
--resource-group previewops-rg \
--query identity.principalId -o tsv)
# Grant AcrPull to the managed environment identity
az role assignment create \
--assignee $ENV_PRINCIPAL_ID \
--role AcrPull \
--scope $ACR_ID
Without this step, Container Apps will fail to pull the built image at deploy time.
Step 7 — Configure the repo
provider: azure-container-apps
providerConfig:
resourceGroup: previewops-rg # required
managedEnvironment: previewops-env # required — Container Apps environment name
acrServer: mypreviewops.azurecr.io # required — ACR login server
registryName: mypreviewops # required — ACR name without .azurecr.io
location: eastus # optional (default: eastus)
Step 8 — Verify
Comment /validate-previewops on any open PR. The bot acquires a management API token using the service principal and reports success.
Cost notes
| Resource | Cost |
|---|---|
| Container Apps | ~$0.01–$0.05/hour per preview (one replica per PR, running until the PR is closed) |
| Managed environment | ~$0 infrastructure, charged per replica |
| Log Analytics workspace | ~$2–5/month |
| ACR Basic | ~$5/month |
Total baseline cost: ~$7–10/month for the environment and registry.
Troubleshooting
| Error | Fix |
|---|---|
AZURE_CLIENT_ID / AZURE_CLIENT_SECRET are required |
Set all 4 Azure secrets |
azure-container-apps providerConfig.resourceGroup is required |
Add resourceGroup to providerConfig |
AuthenticationError |
Service principal may be expired — re-create it |
The resource group was not found |
Check the resourceGroup name and location match what you created |
| ACR build fails | Ensure the service principal has AcrPush on the registry (step 5) |