GitHub Actions Tutorial — Deploy to Azure

1 minute read

Deploy to Azure

Azure provides first-party GitHub Actions for deploying to App Service, Container Apps, Functions, and AKS. Authentication uses OIDC with Azure AD workload identity — no secrets to rotate.


Authentication — OIDC with Azure AD

1. Create a Service Principal and Federated Credential

# Create the app registration
az ad app create --display-name "github-actions-deploy"

# Create a service principal
az ad sp create --id <app-id>

# Add federated credential for GitHub
az ad app federated-credential create --id <app-id> \
  --parameters '{
    "name": "github-main",
    "issuer": "https://token.actions.githubusercontent.com",
    "subject": "repo:my-org/my-repo:ref:refs/heads/main",
    "audiences": ["api://AzureADTokenExchange"]
  }'

2. Use in Workflow


permissions:
  id-token: write
  contents: read

steps:
  - uses: azure/login@v2
    with:
      client-id: ${{ secrets.AZURE_CLIENT_ID }}
      tenant-id: ${{ secrets.AZURE_TENANT_ID }}
      subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}


Deploy to Azure App Service


name: Deploy to App Service

on:
  push:
    branches: [main]

permissions:
  id-token: write
  contents: read

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: production
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: '20'

      - run: npm ci && npm run build

      - uses: azure/login@v2
        with:
          client-id: ${{ secrets.AZURE_CLIENT_ID }}
          tenant-id: ${{ secrets.AZURE_TENANT_ID }}
          subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}

      - uses: azure/webapps-deploy@v3
        with:
          app-name: my-web-app
          package: .


Deploy to Azure Container Apps


name: Deploy to Container Apps

on:
  push:
    branches: [main]

permissions:
  id-token: write
  contents: read

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: production
    steps:
      - uses: actions/checkout@v4

      - uses: azure/login@v2
        with:
          client-id: ${{ secrets.AZURE_CLIENT_ID }}
          tenant-id: ${{ secrets.AZURE_TENANT_ID }}
          subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}

      - uses: azure/container-apps-deploy-action@v2
        with:
          containerAppName: my-container-app
          resourceGroup: my-rg
          imageToDeploy: ghcr.io/my-org/my-app:${{ github.sha }}


Deploy Azure Functions


name: Deploy Azure Function

on:
  push:
    branches: [main]

permissions:
  id-token: write
  contents: read

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-python@v5
        with:
          python-version: '3.12'

      - run: pip install -r requirements.txt

      - uses: azure/login@v2
        with:
          client-id: ${{ secrets.AZURE_CLIENT_ID }}
          tenant-id: ${{ secrets.AZURE_TENANT_ID }}
          subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}

      - uses: azure/functions-action@v2
        with:
          app-name: my-function-app
          package: .


Common Mistakes

Mistake Fix
Federated credential subject mismatch Subject must match exactly: repo:org/repo:ref:refs/heads/main
Missing id-token: write Required for OIDC token generation
Wrong subscription scope Grant the service principal access to the target subscription
azure/login version outdated Use @v2 for OIDC support

Quick Reference

Target Key Action
Auth (OIDC) azure/login@v2
App Service azure/webapps-deploy@v3
Container Apps azure/container-apps-deploy-action@v2
Functions azure/functions-action@v2
AKS azure/aks-set-context@v4 + kubectl apply

← Previous: Deploy to AWS

Next: Deploy to Kubernetes →

Updated: