GitHub Actions on Azure
Replicate the CI/CD workflow using GitHub Actions with the azure/webapps-deploy action, and understand when to choose GitHub Actions over Azure Pipelines.
GitHub Actions on Azure is a free Cloud & IT Cert Prep lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Cloud & IT Cert Prep learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
What Is GitHub Actions?
GitHub Actions is GitHub's built-in CI/CD and automation platform. Workflows are defined in YAML files stored in the .github/workflows/ directory of your repository and triggered by GitHub events — pushes, pull requests, releases, and more. GitHub Actions is deeply integrated with the GitHub ecosystem (issues, PRs, packages, security scanning) and provides a rich marketplace of community actions for tasks like building, testing, and deploying to Azure.
GitHub Actions Workflow Structure
A GitHub Actions workflow file has three top-level sections. on defines the trigger events. env sets global environment variables. jobs defines one or more jobs, each running on a runner (GitHub-hosted or self-hosted). Each job has steps — either run (shell script) or uses (a pre-built action). Jobs run in parallel by default; use needs to create sequential dependencies.
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
NODE_VERSION: '18.x'
jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- run: npm ci
- run: npm testAuthenticating to Azure from GitHub Actions
The recommended way to authenticate GitHub Actions to Azure is OpenID Connect (OIDC) — it issues short-lived tokens without storing long-lived secrets in GitHub. Configure a federated identity credential on an Azure App Registration or Managed Identity, granting it trust for your GitHub repository and branch. Use the azure/login@v2 action to exchange the GitHub OIDC token for an Azure access token — no client secrets in GitHub Secrets required.
# Configure OIDC federated credential in Azure
az ad app federated-credential create \
--id <AppRegistrationObjectId> \
--parameters '{
"name": "github-oidc",
"issuer": "https://token.actions.githubusercontent.com",
"subject": "repo:myorg/myrepo:ref:refs/heads/main",
"audiences": ["api://AzureADTokenExchange"]
}'
# In the workflow: login via OIDC
# permissions:
# id-token: write
# contents: read
# - uses: azure/login@v2
# with:
# client-id: ${{ vars.AZURE_CLIENT_ID }}
# tenant-id: ${{ vars.AZURE_TENANT_ID }}
# subscription-id: ${{ vars.AZURE_SUBSCRIPTION_ID }}Deploying to Azure App Service
The azure/webapps-deploy@v3 action deploys code or a container image to Azure App Service. It handles slot deployment, package-based deploy, and Docker image deploy. Pair it with azure/login@v2 for authentication. You can target a staging slot, run smoke tests, then swap with the azure/CLI@v2 action running the slot swap command — replicating the Azure Pipelines blue-green deployment pattern entirely in GitHub Actions.
# .github/workflows/deploy.yml
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
steps:
- uses: actions/checkout@v4
- uses: azure/login@v2
with:
client-id: ${{ vars.AZURE_CLIENT_ID }}
tenant-id: ${{ vars.AZURE_TENANT_ID }}
subscription-id: ${{ vars.AZURE_SUBSCRIPTION_ID }}
- name: Build and zip app
run: npm ci && npm run build && zip -r app.zip dist/
- uses: azure/webapps-deploy@v3
with:
app-name: myUniqueWebApp
slot-name: staging
package: app.zipDeploying to Azure Kubernetes Service
Deploy to AKS from GitHub Actions using the azure/k8s-deploy@v5 action. This action uses kubectl apply to deploy manifests, performs image substitution (replacing the image tag with the current build's tag), and monitors rollout health. The azure/aks-set-context@v4 action configures kubectl credentials by fetching the cluster kubeconfig using the authenticated Azure session.
jobs:
deploy-aks:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
steps:
- uses: actions/checkout@v4
- uses: azure/login@v2
with:
client-id: ${{ vars.AZURE_CLIENT_ID }}
tenant-id: ${{ vars.AZURE_TENANT_ID }}
subscription-id: ${{ vars.AZURE_SUBSCRIPTION_ID }}
- uses: azure/aks-set-context@v4
with:
resource-group: MyRG
cluster-name: myAKSCluster
- uses: azure/k8s-deploy@v5
with:
namespace: production
manifests: k8s/
images: 'mycontainerregistry.azurecr.io/myapp:${{ github.sha }}'GitHub Secrets and Variables
Store sensitive values in GitHub Secrets — encrypted values accessible as ${{ secrets.SECRET_NAME }} in workflows. Non-sensitive configuration goes in GitHub Variables — accessible as ${{ vars.VARIABLE_NAME }}. Both can be scoped to a repository, environment, or organisation. Use environments in GitHub Actions to add protection rules (required reviewers, deployment branches) similar to Azure DevOps Environments.
# Reference secrets and variables in a workflow
steps:
- name: Configure app settings
uses: azure/CLI@v2
with:
inlineScript: |
az webapp config appsettings set \
--name myUniqueWebApp \
--resource-group MyRG \
--settings \
DATABASE_URL='${{ secrets.DATABASE_URL }}' \
API_VERSION='${{ vars.API_VERSION }}'Environment Protection Rules
GitHub Actions Environments (configured in repository Settings → Environments) add deployment gates similar to Azure DevOps environments. You can require required reviewers who must approve before a job targeting the environment runs, restrict deployments to specific branches (only main can deploy to Production), and add wait timers to delay deployments. Jobs targeting a protected environment pause until all protection rules are satisfied.
# Workflow job targeting a protected GitHub environment
jobs:
deploy-production:
runs-on: ubuntu-latest
environment:
name: Production # Must have 2 approvers in GitHub settings
url: https://myapp.contoso.com
needs: deploy-staging
steps:
- uses: azure/login@v2
with:
client-id: ${{ vars.AZURE_CLIENT_ID }}
tenant-id: ${{ vars.AZURE_TENANT_ID }}
subscription-id: ${{ vars.AZURE_SUBSCRIPTION_ID }}
- uses: azure/webapps-deploy@v3
with:
app-name: myUniqueWebApp
package: app.zipReusable Workflows and Composite Actions
Avoid duplicating CI/CD logic across repositories using two GitHub Actions features. Reusable workflows let you define a workflow in one repository and call it from workflows in other repositories using uses: myorg/shared-workflows/.github/workflows/deploy.yml@main. Composite actions bundle multiple steps into a single action stored in a repository, reusable with uses: myorg/my-actions/deploy@v1. Both promote DRY principles across your organisation's CI/CD pipelines.
# Call a reusable workflow from another workflow
jobs:
deploy:
uses: myorg/shared-workflows/.github/workflows/deploy-appservice.yml@main
with:
app-name: myUniqueWebApp
slot-name: staging
package-path: dist/
secrets:
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}GitHub Actions vs Azure Pipelines: When to Choose
Choose GitHub Actions when: your code is hosted on GitHub, your team prefers the GitHub UI, you want tight integration with GitHub PR checks and code scanning, or you are building open-source projects (generous free minutes). Choose Azure Pipelines when: you need Azure Boards integration, advanced testing with Azure Test Plans, Azure Artifacts feed management, code is in Azure Repos, or you need complex multi-stage release management with gates across many environments. Both support deploying to Azure equally well.
GitHub Actions Marketplace
The GitHub Actions Marketplace hosts thousands of community and official actions for common tasks. Microsoft publishes official Azure actions: azure/login, azure/webapps-deploy, azure/aks-set-context, azure/k8s-deploy, azure/CLI, azure/arm-deploy, and many more. Always pin actions to a specific version tag (e.g., @v3) or a commit SHA to prevent supply chain attacks from a compromised action being updated with malicious code.
# Pin actions to specific version (recommended)
- uses: actions/checkout@v4 # Pinned to v4 tag
- uses: azure/login@v2 # Pinned to v2
- uses: azure/webapps-deploy@v3 # Pinned to v3
# Extra security: pin to commit SHA
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
# Avoid unpinned 'latest' or branch references
# - uses: some-action@main # UNSAFE - could change at any timeSelf-Hosted Runners for Private Networks
GitHub-hosted runners have public internet access only — they cannot reach private Azure resources (SQL databases, internal APIs) without exposing those resources publicly. Use self-hosted runners on Azure VMs inside your VNet for deployments to private resources. Register a runner by downloading the GitHub Actions runner agent, configuring it with your repository URL and registration token, and running it as a service. Scale self-hosted runners with Azure Container Apps for elastic runner pools.
# Register a self-hosted runner on an Azure VM
# 1. Download runner (run on the VM)
curl -O -L https://github.com/actions/runner/releases/download/v2.317.0/actions-runner-linux-x64-2.317.0.tar.gz
mkdir actions-runner && tar xzf ./actions-runner-linux-x64-2.317.0.tar.gz -C actions-runner
cd actions-runner
# 2. Configure (use token from GitHub Settings > Actions > Runners)
./config.sh --url https://github.com/myorg/myrepo --token <REGISTRATION_TOKEN>
# 3. Run as a service
sudo ./svc.sh install && sudo ./svc.sh start
# Use in workflow
# runs-on: self-hostedQuick Check
Test your understanding of Microsoft Azure Fundamentals (AZ-900) concepts from this lesson.
Lesson Recap
In this lesson you learned: GitHub Actions workflows are YAML files in .github/workflows/ triggered by GitHub events and executed on runners, OIDC federated credentials enable secretless Azure authentication from GitHub Actions, and GitHub Environments with protection rules add approval gates to production deployments. This completes the Azure DevOps course — next up is Azure Monitor and Log Analytics.
Frequently asked questions
Is the “GitHub Actions on Azure” lesson free?
Yes — the full text of “GitHub Actions on Azure” is free to read here on the web, and the Cloud & IT Cert Prep course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Cloud & IT Cert Prep course, upgrade to CoddyKit PRO.
What will I learn in “GitHub Actions on Azure”?
Replicate the CI/CD workflow using GitHub Actions with the azure/webapps-deploy action, and understand when to choose GitHub Actions over Azure Pipelines. You practise Cloud & IT Cert Prep with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Cloud & IT Cert Prep?
No prior experience is required. Cloud & IT Cert Prep on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “GitHub Actions on Azure” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Cloud & IT Cert Prep lesson?
Yes. Every Cloud & IT Cert Prep lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.