Simple Flask project for practicing and validating CI/CD workflows.
- General overview
- Local run
- Azure setup
- GitHub secrets (required)
- Azure template deployment
- VS Code manual deploy
- Deployment Flow
- Notes
- Troubleshooting
- Additional documentation
- Practice secure OIDC-based Azure deployments
- Avoid publishing long-lived credentials
- Validate ARM-based infrastructure automation
- Create a reusable CI/CD template for future projects
- Create venv:
python -m venv .venv - Activate venv:
\.venv\Scripts\Activate.ps1 - Install deps:
pip install -r requirements.txt
Prerequisites:
- Install Azure CLI (
az) locally.
Quick commands:
# Login
az login
# List subscriptions
az account list --output table
# Set the subscription you want to deploy to
az account set --subscription <your-subscription-id>Create GitHub secrets:
AZURE_CLIENT_IDAZURE_TENANT_IDAZURE_SUBSCRIPTION_ID
Important:
AZURE_CLIENT_IDshould be the client ID of the identity used for OIDC authentication (managed identity or App Registration).AZURE_TENANT_IDmust match that identity tenant.AZURE_SUBSCRIPTION_IDmust be the target subscription.
In this repository the ARM template provisions a system-assigned managed identity attached to the Web App.
Alternatively, an Azure App Registration (Service Principal) can be used for CI/CD authentication.
In general:
- App Registration is typically preferred for CI/CD pipelines, since it represents an external workload (e.g., GitHub Actions) authenticating to Azure using OIDC.
- Managed Identity is commonly used by Azure resources themselves (VMs, App Service, Functions) to securely access other Azure services such as Key Vault, Storage, or databases.
See the additional documentation for a step-by-step guide on configuring App Registration with OIDC:
Flexible Federated Credential Setup
- Scripts prompt for
WEBAPP_NAME,LOCATION,GITHUB_ORGANIZATION_NAME, andRESOURCE_GROUP. - Defaults come from
azuredeploy.parameters.json. - Customize values such as
webAppName,location,githubOrganizationName, SKU settings, andtagsin the parameters file. WEBAPP_NAMEmust be globally unique in Azure App Service.- Not all Azure regions support all SKUs/resources - (Canada Central is recommended for testing).
- Federated credential creation can fail if the specified values do not match your GitHub Actions OIDC subject.
- Deployment provisions App Service and identity resources from
azuredeploy.json.
Follow these steps on your local machine:
# Login to Azure and set subscription if not done before
az login
az account set --subscription <your-subscription-id>PowerShell (Windows):
# Go to the azure directory to have access to the scripts
cd azure
$env:WEBAPP_NAME="your-webapp-name"
$env:LOCATION="canadacentral"
$env:GITHUB_ORGANIZATION_NAME="your-github-user-or-org"
$env:RESOURCE_GROUP="your-rg-name"
# Run Script File
./deploy-webapp-powershell.ps1
#Force prompt without persisting new values:
./deploy-webapp-powershell.ps1 -NoCache
# Clear cached prompt values:
./deploy-webapp-powershell.ps1 -ClearCache
Bash:
# Go to the azure directory to have access to the scripts
cd azure
export WEBAPP_NAME=your-webapp-name
export LOCATION=canadacentral
export GITHUB_ORGANIZATION_NAME=your-github-user-or-org
export RESOURCE_GROUP=your-rg-name
# Run Script File
bash ./deploy-webapp-bash.sh
# Force prompt and ignore shell-cached values:
bash ./deploy-webapp-bash.sh --no-cache
# Clear cached prompt values:
bash ./deploy-webapp-bash.sh --clear-cache
# Optional: deploy directly with parameters file
az deployment group create \
--resource-group <your-rg> \
--template-file azuredeploy.json \
--parameters @azuredeploy.parameters.json- Linux App Service Plan (B1)
- Linux Python Web App (Python 3.12)
- System-assigned managed identity
- Startup command: Empty by default - (set later by deployment workflow or manual config)
- Tags including
repo=<repository-name>
- Install Azure App Service extension
- Sign in and select your Web App
- Right-click project folder -> Deploy to Web App...
- Configure the Managed Identity or App Registration in the Azure portal
- Add Federated credential and permissions to the Managed Identity / App Registration
- Startup command (if needed):
gunicorn --bind=0.0.0.0 --timeout 600 app.main:app
Main workflow deploys to an existing Azure Web App. It does not create one.
flowchart LR
A[GitHub Push] --> B[GitHub Actions]
B --> C[Build + Package]
C --> D[Azure OIDC Login]
D --> E[Deploy to App Service]
E --> F[Restart + Set Startup Command]
- Main deploy workflow:
.github/workflows/build-flask-wapp.yml - Optional dispatch inputs:
webapp_name,resource_group,tag_key(defaultrepo),tag_value - Resolution order:
webapp_name- repo variable
WEBAPP_NAME - tag lookup (
tag_key+tag_valueor repo-name default)
- Upload artifact with
app/andrequirements.txt - Download to
deploy_pkg, validate required files - Zip as
deploy.zip - Deploy attempt 1
- On failure: restart app + wait 20s, then deploy attempt 2
- On success: set startup command and restart app
- Startup command used:
gunicorn --bind=0.0.0.0 --timeout 600 app.main:app
- Prefer manual
workflow_dispatchwhen validating Azure changes. - Set subscription once per shell and verify with
az account show. - App Service names are globally unique.
- Security: GitHub OIDC only (no long-lived Azure secrets), least-privilege RBAC, and isolated Web App identity.
- No web app resolved: provide
WEBAPP_NAMEvariable,webapp_nameon workflow run, or matching tag on the web app. AuthorizationFailed: grant at least Reader on the target Web App/Resource Group.- OIDC mismatch: ensure federated credential subject matches repo/branch/ref.
- Wrong subscription: run
az account showandaz account set --subscription <id>.
Detailed guides related to this CI/CD setup:
-
Flexible Federated Credential Setup
Step-by-step configuration for Azure OIDC authentication using flexible federated credentials. -
GitHub App Authentication Example
Overview of GitHub App authentication in GitHub Actions, explaining how it differs from PATs and enables secure cross-repository automation.
-
Azure OIDC authentication with GitHub Actions
https://learn.microsoft.com/en-us/azure/developer/github/connect-from-azure-openid-connect -
Flexible Federated Identity Credentials (Microsoft Entra)
https://learn.microsoft.com/en-us/entra/workload-id/workload-identities-flexible-federated-identity-credentials -
Azure App Service deployment with GitHub Actions
https://learn.microsoft.com/en-us/azure/app-service/deploy-github-actions
