Integrate GitHub Actions with Azure
Learn to integrate GitHub Actions with Azure in this hands-on lesson. Step-by-step guidance, troubleshooting, and next steps.
Focus: integrate github actions with azure
You’ve built your app, committed it to GitHub, and now you’re manually clicking through the Azure portal to deploy every update. That workflow is slow, error-prone, and doesn’t scale. Every manual step is a chance to deploy the wrong artifact, forget a setting, or leave your staging environment broken. In this lesson, you’ll learn how to integrate GitHub Actions with Azure, turning your Git pushes into automated, repeatable deployments. By the end, you’ll have a CI/CD pipeline that builds, tests, and deploys your code to Azure — hands-free.
The problem this lesson solves
If you’re still deploying to Azure by hand, you know the pain: SSH into a VM, pull the latest code, run migrations, restart the service. Or worse, you’re downloading a publish profile and uploading it through the portal. These manual steps when you’re in a hurry, they’re inconsistent. One developer forgets to run npm install --production, another deploys from a dirty working tree. Before you know it, your production Azure Web App is running code that was never tested.
Integrate GitHub Actions with Azure solves this by giving you a single source of truth: your Git repository. Every push to main triggers a workflow that builds your project, runs your tests, and deploys the verified artifact to Azure. No more “it works on my machine” — the pipeline runs the same steps every time, in the same order, with the same environment.
The cost of manual deployment isn’t just time. It’s reliability. A study from the DORA (DevOps Research and Assessment) team shows that elite performers deploy 208 times more frequently than low performers, with 7 times lower change failure rate. Automated deployment is what separates a hobby project from a production system. When a colleague asks “how do I deploy?” you can point to a YAML file instead of a 14-step wiki page.
Pro tip: You don’t need to replace your entire deployment process overnight. Start with a single environment (like staging) and expand from there. The best integration is the one that ships your code daily.
Core concept / mental model
Think of GitHub Actions as a personal robot developer that watches your GitHub repository. When you push code, open a pull request, or create a release, the robot wakes up, reads a recipe named deploy.yml, and executes it step by step. That recipe is stored right in your repo under .github/workflows/, which means it’s version-controlled, reviewable, and shared.
Azure, on the other hand, is the destination. It’s the cloud platform where your app actually runs — whether that’s an Azure App Service, a Virtual Machine, Azure Functions, or a Container App. The integration happens when GitHub Actions talks to Azure’s APIs to deploy the built artifact.
The bridge between the two is authentication. Azure needs to know that your workflow is allowed to deploy. There are two common methods:
- OpenID Connect (OIDC) — a modern, short-lived token approach that uses federated credentials. Azure issues a token only when GitHub requests it, and it expires quickly. This is the recommended method for production.
- Service principal secret — you create a service principal (like an app identity) and store its secret in GitHub Secrets. The workflow uses that secret to log in. Simpler, but the secret is long-lived and must be rotated.
A helpful mental model: GitHub Actions is a contractor working with Azure as the client. The contractor (GitHub) presents a badge (OIDC token) that Azure validates. Once validated, the contractor is allowed to build and deploy. The workflow file is the contract — it says exactly what will be built, how it will be tested, and where the final artifact will be placed.
When you integrate GitHub Actions with Azure, you’re not just automating a deployment. You’re creating a feedback loop: every commit gets tested and deployed to a live environment, so bugs surface in minutes, not months.
How it works step by step
Integrating GitHub Actions with Azure follows a predictable path. Let’s walk through it as a logical sequence — each step builds on the previous one.
1. Prepare your Azure resources
Before any workflow runs, you need an Azure App Service (or the service you’re deploying to). Create it in the Azure portal or with the Azure CLI:
az group create -n my-rg -l eastus
az appservice plan create -n my-plan -g my-rg --sku B1
az webapp create -n my-app -g my-rg --plan my-plan
This gives you the target for deployment — a resource that will host your app.
2. Configure authentication (choose your path)
Decide how GitHub will authenticate to Azure. The recommended modern approach is OIDC, but a service principal secret is simpler for a lesson. Here’s how to create a service principal when you’re learning:
az ad sp create-for-rbac --name "my-github-actions" --sdk-auth > gh-credentials.json
The command outputs a JSON object. Copy it and add it as a GitHub Secret named AZURE_CREDENTIALS in your repository settings. This secret is what your workflow will reference.
If you want to use OIDC (better for production), you’d create a federated credential instead — this is covered in more advanced lessons, but the concept is the same: GitHub present a token, Azure verifies it.
3. Create the workflow YAML file
In your repository, create .github/workflows/azure-deploy.yml. This file defines the trigger (e.g., push to main), the jobs, and the steps. Each step runs a specific action — either from the GitHub Marketplace (like azure/webapps-deploy) or a community action.
4. Run the pipeline and observe
Push a commit to the branch you configured. Watch the workflow run in the Actions tab of your GitHub repository. Each step shows logs — you can see where it fails and fix it. When it succeeds, your app is live at https://my-app.azurewebsites.net.
5. Iterate and improve
Your first integration is a starting point. Add a build step to compile your code, a test job to run your suite, and an environment with approval gates for production. Over time, your pipeline becomes a full CI/CD system.
The cause-and-effect relationship is direct: Git push → trigger → authenticated login → build → deploy. If any step fails, the pipeline stops and you get a notification. No silent failures.
Hands-on walkthrough
Let’s put this into practice. We’ll use a simple Node.js app and a service principal for simplicity. You’ll need:
- A GitHub account and repository
- An Azure subscription and CLI installed
- A local copy of the code
Step 1: Create a minimal Node.js app
Create a simple Express app:
# This is the lesson on GitHub Actions, but for the Node example, check the repo
Wait — you’re in a Python track? No, you’re in the Azure Tutorial track. Let’s use a small Node app, or a static HTML file. For this lesson, we’ll deploy a simple HTML page to keep the focus on the integration.
mkdir my-app && cd my-app
echo "<h1>Hello from GitHub Actions!</h1>" > index.html
git init
git add .
git commit -m "Initial commit"
Step 2: Create the service principal and store credentials
Run the Azure CLI command from earlier and copy the JSON output. Then go to your GitHub repo → Settings → Secrets and variables → Actions → New repository secret. Name it AZURE_CREDENTIALS and paste the JSON.
Step 3: Create the workflow file
In your repo, create the directory .github/workflows/ and add a file deploy.yml:
name: Deploy to Azure
on:
push:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Login to Azure
uses: azure/login@v2
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: Deploy to App Service
uses: azure/webapps-deploy@v3
with:
app-name: my-app
package: .
Step 4: Push and watch it run
Commit this file and push to main. In the Actions tab, you’ll see the workflow execute. Check the logs for a green checkmark.
Step 5: Verify the deployment
Open your browser and visit https://my-app.azurewebsites.net. You should see the HTML page. Now push a change — change the HTML text and push again. The page updates automatically.
Expected output: After each push, the workflow runs and the page reflects the latest commit.
Congratulations — you’ve just integrated GitHub Actions with Azure! The same pattern works for Node.js, Python, .NET, and many other runtimes.
Compare options / when to choose what
When you integrate GitHub Actions with Azure, you have choices for authentication and deployment target. Here’s a quick comparison:
| Authentication method | Security | Setup effort | Use case |
|---|---|---|---|
| OIDC (federated) | High — no long-lived secrets | Medium — requires Azure AD setup | Production, enterprise |
| Service principal secret | Medium — secret rotation needed | Low — one command | Personal projects, learning |
| Publish profile | Low — port 443, long-lived | Very low — download from portal | Quick demos, not for production |
| Deployment target | When to use |
|---|---|
| App Service | Web apps with built-in scaling |
| Virtual Machines | Full control over OS and runtime |
| Azure Functions | Event-driven serverless workloads |
| Container Apps/AKS | Microservices and containerized apps |
For most web apps, App Service is the sweet spot. If you’re deploying microservices, Kubernetes-based options give you more orchestration power.
Variations
- Use
azure/webapps-deployfor web apps; the same action supports most App Service runtimes. - For containerized workloads, you can run
docker buildand push to Azure Container Registry before deploying with ahelmorkubectlstep. - You can add a test job before deployment to run
npm testorpytest, ensuring only verified code ships.
Troubleshooting & edge cases
The most common problems when integrating GitHub Actions with Azure are authentication and path-related. Here’s how to fix them:
ERROR: AADSTS70001: Application with identifier ... was not found— This means your service principal was deleted or the tenant ID is wrong. Re-run theaz ad sp create-for-rbaccommand and update the secret.Deployment failed: App Service Deploy failed— Often thepackagepath is incorrect. If your code is in a subdirectory, point to that folder, e.g.,package: ./build. Or you intended to deploy a zip file, but you’re sending a folder.The workflow is skipped because there is no default branch— Ensure your branch name matches the trigger, e.g.,mainvsmaster. Update the YAML trigger.- Pipeline passes but the site doesn’t update — This happens when you deploy to the wrong app name or slot. Double-check the
app-namein the deploy step and the resource group. - Authentication fails with a “secret not found” error — Did you add the secret to the correct repository? It must be in the repo where the workflow runs.
- Slow deployments — If you’re deploying large bundles, consider using a staging slot and swapping. Also, cache your dependencies to speed up builds.
Pro tip: Always check the Actions tab logs — they tell you exactly which step failed. The error messages are surprisingly descriptive.
Another edge case: secrets rotation. If you use a service principal, set a calendar reminder to rotate the secret every 90 days. OIDC avoids this entirely because tokens are short-lived.
What you learned & what's next
You’ve learned how to integrate GitHub Actions with Azure — from setting up authentication to creating a deployable workflow. You understand the mental model of GitHub Actions as an automation robot, and you’ve seen how to automate a push-to-deploy pipeline. You can now explain the core idea, and you’ve completed a practical exercise that deploys a web app.
This skill is the foundation of modern DevOps. Next in the Azure Tutorial, you’ll learn how to use Azure managed identities to secure your application’s access to other Azure resources, so your code can talk to storage, databases, and Key Vaults without hardcoding credentials. That’s the natural next step after automating deployment — securing the runtime.
Keep this pipeline as your base; you’ll build on it in upcoming lessons.
Practice recap
Now that you've deployed a static site, challenge yourself: modify your workflow to include a test job that runs a simple assertion (for example, a shell script that greps the HTML file for a specific string). Push a failing commit to see the pipeline stop before deployment, then fix it and push again. This hands-on practice will cement your understanding of how CI/CD gates work.
Common mistakes
- Using the
azure/webapps-deployaction without logging in first — you must runazure/loginbefore deploying to authenticate the session. - Adding the service principal JSON as a secret but accidentally including extra whitespace or line breaks — GitHub Secrets are literal strings, so copy the JSON exactly.
- Trigging your workflow on a branch that doesn’t exist (e.g.,
masterwhen your default branch ismain) — the workflow will silently skip every push. - Deploying from a subdirectory without adjusting the
packagepath — your app’s files won’t be in the deployment package, causing a ‘file not found’ or a blank page. - Storing long-lived secrets without a rotation plan — if your service principal is compromised, the attacker can deploy arbitrary code to your Azure subscription.
Variations
- Use OpenID Connect (OIDC) with federated credentials instead of a service principal secret — Azure issues a short-lived token, eliminating secret rotation.
- Deploy to Azure Functions using the
azure/functions-actioninstead of theazure/webapps-deployaction, which is optimized for serverless apps. - For containerized apps, build a Docker image, push it to Azure Container Registry, and then deploy to Azure App Service with a custom container image using the
azure/webapps-deployaction with theimagesparameter.
Real-world use cases
- Automatically deploy a microservice to Azure App Service on every push to the
mainbranch, giving the team instant feedback. - Run a GitHub Action workflow that builds a container image and deploys it to Azure Kubernetes Service (AKS) after a test job passes.
- Deploy a static site to Azure Storage static website hosting when a PR is merged to
main, using a simpleazure/storage-static-siteaction.
Key takeaways
- Integrating GitHub Actions with Azure gives you a repeatable, version-controlled deployment pipeline triggered by Git events.
- Authentication is the foundation — use OIDC for production or a service principal secret for simplicity, and always store credentials in GitHub Secrets.
- The workflow YAML file defines triggers, jobs, and steps; keep it under
.github/workflows/for automatic discovery. - A successful integration involves building, testing, and deploying — add test jobs before deployment to catch bugs early.
- Troubleshoot by reading Action logs; common failures are authentication errors, wrong paths, and branch mismatches.
- Start with a single environment (like staging) and expand to production with approval gates as you gain confidence.
Keep learning
Related tutorials, quizzes, and articles for this topic.
Discussion
Questions, corrections, and tips help everyone reading this page.
0 comments
Add a comment
No comments yet — start the thread.