Migrating CI/CD Pipelines from Azure DevOps to GitHub Actions: A Practical Guide
Why stick with Azure DevOps when GitHub Actions can streamline your entire developer workflow?
Let’s dismantle the migration fears and demonstrate a clear, step-by-step transition that tech leads can implement today without downtime.
As organizations embrace more integrated development ecosystems, migrating CI/CD pipelines from Azure DevOps to GitHub Actions has become a highly valuable skill. Not only does this consolidation reduce overhead by centralizing repositories and automation under one platform, but it also unlocks improved deployment velocity and flexibility — especially if your codebase already lives on GitHub.
In this post, I’ll walk you through a practical guide on how to migrate your pipelines safely and efficiently.
Why Migrate from Azure DevOps to GitHub Actions?
Before diving into the "how," let’s quickly cover the "why":
- Unified platform: Repos, CI/CD, package management, and issue tracking in one place.
- Native integration: GitHub Actions is built directly into GitHub repositories—no need for external service connections.
- Flexible workflows: Write workflows as code (YAML), with marketplace actions extending functionality.
- Community and ecosystem: Larger marketplace of prebuilt actions, templates, and growing adoption.
- Cost savings: Consolidate tooling licenses and simplify maintenance.
Step 1: Inventory Your Azure DevOps Pipelines
Begin by listing and understanding your current pipelines:
- Which pipelines exist (build, test, deploy)?
- What triggers are configured (branch policies, PR validations)?
- What stages/tasks/scripts are part of each pipeline?
- External service integrations (artifacts feeds, Kubernetes clusters, Azure web apps)?
This documentation will be critical for replicating logic in GitHub Actions.
Step 2: Set Up Your GitHub Repository and Enable Actions
If not done already:
- Ensure your source code is hosted on GitHub.
- Navigate to the repo’s Actions tab.
- Enable GitHub Actions (usually enabled by default).
- Review repository permissions for workflows; consider security policies around secrets.
Step 3: Translate Pipeline Triggers
Azure DevOps uses YAML or classic editor triggers like trigger
, pr
, branch filters.
In GitHub Actions:
on:
push:
branches:
- main
- release/*
pull_request:
branches:
- main
This snippet runs workflows on pushes to main
or any release/*
branches, plus PRs targeting main
.
Step 4: Convert Build and Test Steps
Azure DevOps defines steps using tasks such as UseDotNet
, DotNetCoreCLI
, or shell scripts.
Example Azure DevOps job snippet:
steps:
- task: UseDotNet@2
inputs:
packageType: 'sdk'
version: '6.x'
- script: dotnet build --configuration Release
Equivalent in GitHub Actions:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup .NET SDK
uses: actions/setup-dotnet@v3
with:
dotnet-version: 6.0.x
- name: Build project
run: dotnet build --configuration Release
This example shows basic migration of build tasks into the new environment.
Step 5: Migrate Deployment Steps
Suppose your Azure pipeline deploys to Azure App Service:
Azure DevOps sample deploy task:
- task: AzureWebApp@1
inputs:
azureSubscription: 'your-subscription'
appName: 'your-app-service-name'
package: '$(System.DefaultWorkingDirectory)/**/*.zip'
GitHub Actions equivalent using azure/webapps-deploy:
- name: Deploy to Azure Web App
uses: azure/webapps-deploy@v2
with:
app-name: your-app-service-name
publish-profile: ${{ secrets.AZURE_PUBLISH_PROFILE }}
package: '*.zip'
Note: You'll need to create and store your publish profile as a secret (
AZURE_PUBLISH_PROFILE
) in the GitHub repo for secure authentication.
Step 6: Handle Secrets and Service Connections
Azure DevOps uses Service Connections; in GitHub:
- Go to repository Settings → Secrets and variables → Actions → New repository secret.
- Add tokens, passwords, SSH keys here.
- Reference them in workflows with
${{ secrets.NAME }}
.
Keep sensitive data secure throughout migrations!
Step 7: Test Your Workflow Incrementally
Avoid “all-at-once” strategy. Here's best practice:
- Create a new branch in your repo.
- Commit the initial workflow YAML file.
- Push changes; observe logs on the Actions tab.
- Iterate fixing errors step-by-step.
- Once stable, merge into main and disable equivalent Azure pipeline to prevent conflicts or duplicated deployments.
You can also run both pipelines concurrently during testing but restrict deployment triggers until confident.
Additional Tips & Tricks for Smooth Migration
- Use act — a CLI tool for local testing of GitHub Actions workflows before pushing commits.
- Search the GitHub Marketplace to replace custom scripts or complex tasks with community-maintained actions.
- Modularize workflows where possible — e.g., separate build and deploy workflows triggered independently or conditionally.
- Leverage matrix builds for running tests across multiple OS versions or environments smoothly within a single workflow file.
Sample Complete Workflow Example
A simple .NET Core pipeline with build & deploy might look like this:
name: CI/CD Pipeline
on:
push:
branches:
- main
jobs:
build-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup .NET SDK
uses: actions/setup-dotnet@v3
with:
dotnet-version: '6.0.x'
- name: Restore dependencies
run: dotnet restore
- name: Build project
run: dotnet build --configuration Release --no-restore
- name: Run tests
run: dotnet test --no-build --verbosity normal
deploy:
needs: build-test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
# zip artifact packaging step (not shown here)
- name: Deploy to Azure Web App
uses: azure/webapps-deploy@v2
with:
app-name: your-app-service-name
publish-profile: ${{ secrets.AZURE_PUBLISH_PROFILE }}
package: '*.zip'
Conclusion
Migrating CI/CD pipelines from Azure DevOps to GitHub Actions may appear daunting at first glance but becomes manageable when broken down systematically:
- Understand existing pipelines thoroughly.
- Leverage native triggers and reusable community actions in GitHub.
- Gradually translate builds/tests/deployments.
- Securely migrate secrets.
- Test incrementally without downtime.
By following this practical guide and keeping careful notes along the way, you'll unlock tighter integration within your development workflow and benefit from the rich ecosystem that GitHub offers — improving automation flexibility while simplifying management.
Ready to start migration? Go fork your repo now, push that first workflow YAML file, and automate like never before!
If you found this guide helpful or ran into any roadblocks during migration—leave a comment below! I love hearing from readers tackling these scenarios firsthand.