Use GitHub → Settings → Secrets and variables → Actions. Secrets = sensitive; Variables = non-sensitive. Define Variables at repository scope (not only GitHub Environments) so OIDC can stay branch-based—see OIDC.
Runs on every push to main and on pull requests:
python -m ruff checkonsrc,api,src/testspython -m pytestdocker build -f api/Dockerfile(smoke)
No GitHub secrets or variables required.
| Secret | Purpose |
|---|---|
AZURE_CLIENT_ID |
Entra app registration Application (client) ID (OIDC) |
AZURE_TENANT_ID |
Entra Directory (tenant) ID |
AZURE_SUBSCRIPTION_ID |
Azure subscription GUID |
ACR_NAME |
Container Registry name only (alphanumeric, 5–50 chars; no .azurecr.io) |
AZURE_OPENAI_API_KEY |
Azure OpenAI (azure-openai-api-key) |
Not applied by these workflows (set on the Container App or elsewhere): e.g. DATABASE_URL only if you override the image default (SQLite under /app/data), CHROMADB_AUTH_TOKEN, ADMIN_BOOTSTRAP_KEY—see chromadb/AZURE.md and api/README.md.
Auth is Microsoft Entra JWT only (Authorization: Bearer). Register an API app + SPA/native clients; set Variables below (ENTRA_*). Do not expose Chroma publicly—the API remains the only gateway to Chroma and to Postgres-backed users/authz.
Repository variables. Optional _DEV / _PROD overrides apply when the workflow Target environment is dev or prod; if an override is empty, the unsuffixed name is used.
| Variable | Purpose |
|---|---|
AZURE_RESOURCE_GROUP |
Resource group for Container Apps |
AZURE_LOCATION |
Azure region (e.g. westeurope) |
AZURE_CONTAINERAPPS_ENV |
Container Apps environment resource name |
APP_NAME_CHROMA |
Container App name for Chroma |
APP_NAME_API |
Container App name for API |
APP_NAME_UI |
Container App name for UI |
If you still have old secrets ACA_RESOURCE_GROUP / ACA_API_APP_NAME, copy their values into AZURE_RESOURCE_GROUP / APP_NAME_API variables, then delete those secrets—they are not read by the workflow.
Optional: AZURE_RESOURCE_GROUP_DEV, AZURE_RESOURCE_GROUP_PROD, AZURE_LOCATION_DEV, AZURE_LOCATION_PROD, AZURE_CONTAINERAPPS_ENV_DEV, AZURE_CONTAINERAPPS_ENV_PROD, APP_NAME_CHROMA_DEV / _PROD, APP_NAME_API_DEV / _PROD, APP_NAME_UI_DEV / _PROD.
Important: azure-deploy.yml always pushes these names to the Container App. If a GitHub Variable is missing, Actions expands it to empty, which overrides defaults in quack_db.config.Settings / .env.example. For Azure, set variables explicitly.
| Variable | Set in Azure? | Default if unset | Notes |
|---|---|---|---|
AZURE_OPENAI_ENDPOINT |
Yes in prod | example placeholder | Your Azure OpenAI resource URL. |
CHROMADB_HOST |
Yes | localhost |
Internal Chroma hostname/FQDN in ACA. |
CHROMADB_PORT |
Recommended | 8000 |
|
ENTRA_AUDIENCE |
Yes | "" |
API app scope / Application ID URI audience. |
ENTRA_TENANT_ID |
Yes* | "" |
Directory (tenant) GUID. When set, defaults ENTRA_ISSUER and ENTRA_JWKS_URL to the usual single-tenant v2.0 URLs if those are empty. |
ENTRA_JWKS_URL |
Yes* | "" |
Override JWKS URL, or leave empty when ENTRA_TENANT_ID is set. |
ENTRA_ISSUER |
Yes* | "" |
Override issuer(s), or leave empty when ENTRA_TENANT_ID is set. Some flows issue v1 tokens (iss = https://sts.windows.net/<tid>/); the tenant-id default allows both v1 and v2 issuers. |
ENTRA_AUTO_PROVISION_TIER |
Optional | "" |
If set (e.g. everyone), first Entra login creates a DB user with that tier. Empty = admin must pre-create users by email. |
AUTH_DISABLED |
Never in prod | false |
If true, API uses DEV_IMPERSONATE_USER_EMAIL (local dev only). |
DEV_IMPERSONATE_USER_EMAIL |
With AUTH_DISABLED |
"" |
Existing users.email row to impersonate. |
Workflow sets container env API_BASE_URL from UI_API_BASE_URL.
| Variable | Set in Azure? | Default in app_config.py if env is unset |
Notes |
|---|---|---|---|
UI_API_BASE_URL |
Yes | http://127.0.0.1:8001 |
Public https://… URL of the API Container App. |
ENABLE_UI_INGEST |
Optional | false |
|
COLLECTIONS |
Optional | test |
CSV |
DEFAULT_COLLECTION |
Optional | first entry of COLLECTIONS or test |
Manual only (workflow_dispatch): Target environment dev / prod and per-component true/false choices for Chroma / API / UI (string choices so the build and deploy jobs agree). Builds only what you enable (api/Dockerfile; UI needs ./ui— leave UI false if the folder is missing). Image tags look like quack-api:{env}-{shortSha} (and :latest). After changing workflow inputs, use Re-run all jobs if a previous run skipped the build but still tried to deploy.
Configure Secrets and Variables above. Resource group, region, Container Apps environment, and APP_NAME_* values come only from Variables.
OIDC: add a federated credential for each branch you dispatch from (e.g. repo:OWNER/REPO:ref:refs/heads/main). Avoid GitHub environment: on jobs unless you also add repo:…:environment:* credentials in Entra.
If azure/login fails with AADSTS70025 (“client has no configured federated identity credentials”), the Entra app registration tied to AZURE_CLIENT_ID has no (matching) federated credential.
- Entra ID → App registrations → your app → Certificates & secrets → Federated credentials → Add credential.
- Federated credential scenario: GitHub Actions deploying Azure resources.
- Organization / repository: your GitHub org or user and repo name (must match where the workflow runs).
- Entity type: Branch, tag, or pull request — for runs triggered from
main, use branchmain. If you start the workflow from another branch, add a matching federated credential for that ref.
Subject identifier for this workflow (no GitHub environment: on jobs):
| Example | |
|---|---|
Runs from main |
repo:OWNER/REPO:ref:refs/heads/main |
Replace OWNER/REPO with your real path (case-sensitive). Add another federated credential if you run the workflow from other branches.
AADSTS700213 with environment:prod in the error means some job still had environment: prod (or similar)—the subject then requires a matching environment federated credential. This repo’s azure-deploy.yml does not use that, so you should only see branch subjects.
Then grant that app's enterprise application (service principal) AcrPush on the registry and rights to create/update Container Apps and resource groups as needed (azure-deploy.yml creates the RG and Container Apps environment if missing).
If OIDC succeeds but the log shows No subscriptions found (or az account list would be empty), the identity is signed in but has no access to the subscription you passed as AZURE_SUBSCRIPTION_ID, or the subscription ID in GitHub is wrong.
- In Azure Portal → Subscriptions, open the subscription that holds ACR and Container Apps and copy its Subscription ID. It must match
AZURE_SUBSCRIPTION_IDin GitHub secrets exactly (no quotes or spaces). - On that same subscription → Access control (IAM) → Add role assignment → assign at least Reader to verify access; for
azure-deploy.ymlyou typically need Contributor on the subscription (or a narrower custom role on the RG + ACR + Container Apps). - Assign the role to User, group, or service principal → search for the display name of your app registration (e.g. “QuackDB”), not the client ID string.
Cloud Shell / local CLI: az account show --query id -o tsv proves your user can see the subscription. Actions uses only the app registration behind AZURE_CLIENT_ID. Confirm that principal has roles on that subscription (replace IDs):
SUBSCRIPTION_ID="<same value as AZURE_SUBSCRIPTION_ID / az account show --query id -o tsv>"
APP_CLIENT_ID="<Application (client) ID from Entra — same as AZURE_CLIENT_ID>"
az role assignment list --assignee "$APP_CLIENT_ID" --scope "/subscriptions/$SUBSCRIPTION_ID" -o tableIf the table is empty, add Contributor (or Reader + scoped roles) on that subscription for the app, then re-run the workflow. OIDC setup steps are in the Azure/login README — Login with OpenID Connect.
Wait a few minutes after IAM changes, then re-run the workflow.
- Create an Entra app registration; add a federated credential for each branch you use (e.g.
repo:OWNER/REPO:ref:refs/heads/main). - Grant that app’s service principal Contributor (or narrower) on the subscription / RG / ACR as needed.
- Add Secrets and Variables as documented above for
azure-deploy.yml.
See chromadb/AZURE.md for Postgres, Chroma wiring, and Container App env not covered by the workflows.