What this converter does
Paste an azure-pipelines.yml and you get a GitHub Actions workflow plus a list of everything that did not map cleanly. Stages, jobs, deployment jobs, steps and more than fifty built-in tasks are handled. Conversion runs entirely in your browser; nothing is uploaded.
Templates (- template:, extends:) are not fetched: paste the expanded pipeline, or convert each template separately. Anything without a clean equivalent becomes a TODO step that fails loudly.
How Azure Pipelines concepts map to GitHub Actions
| Azure Pipelines | GitHub Actions | Notes |
|---|---|---|
trigger: / pr: | on.push / on.pull_request | Branch, tag and path include/exclude; batch: true becomes concurrency. |
schedules: | on.schedule | Runs on the default branch only. |
parameters: | workflow_dispatch.inputs | ${{ parameters.x }} becomes ${{ inputs.x }}; values become a choice. |
variables: | env: | Variable groups must be recreated as repository or environment secrets. |
$(Build.SourceBranchName) … | github.* context | Thirty-odd predefined variables are mapped; user variables become ${{ env.X }}. |
pool: vmImage | runs-on | Named pools become [self-hosted, …]. |
stages: / dependsOn: | needs: | Stage dependencies fan in to every job of the stage. |
condition: | if: | succeeded(), and/or/not, eq/ne/startsWith/contains/in, variables[...]. |
strategy: matrix | strategy.matrix.include | Legs keep their names; an image column becomes runs-on. |
deployment: job | environment: | runOnce/rolling/canary hooks flattened into steps. |
script / bash / pwsh / powershell | run: | With the matching shell:. |
NodeTool, UsePythonVersion, UseDotNet, JavaToolInstaller, GoTool | actions/setup-* | |
Npm, DotNetCoreCLI, Maven, Gradle, VSBuild, CmdLine, Bash, PowerShell | run: commands | Globs in DotNetCoreCLI are flagged. |
PublishBuildArtifacts, PublishPipelineArtifact, download: | upload-artifact / download-artifact | |
PublishTestResults | mikepenz/action-junit-report or dorny/test-reporter | By result format. |
Cache@2 | actions/cache | File parts of the key become hashFiles(). |
Docker@2 | docker/login-action + docker/build-push-action | Service connection becomes registry secrets. |
AzureCLI, AzureWebApp, AzureFunctionApp, AzureStaticWebApp | azure/login + azure/* actions | Use OIDC federated credentials. |
Kubernetes, HelmDeploy, Terraform*, SonarQube*, GitHubRelease | Matching actions or TODO |
Things to check by hand
- Service connections have no equivalent. Each becomes a set of secrets (or an OIDC login) you create in GitHub.
- Artifact staging.
$(Build.ArtifactStagingDirectory)becomes_artifactsin the workspace; create it before writing to it. - Runtime expressions (
$[ ... ]) are left as-is for you to translate.
FAQ
Is my pipeline uploaded anywhere?
No. The converter runs in your tab. Read azure.js on GitHub.
How does this compare with GitHub Actions Importer?
Actions Importer connects to Azure DevOps and converts in bulk, including task mappings you configure. This page needs nothing installed and no connection. The same converter runs as npx jenkins-to-actions convert azure-pipelines.yml.
Migrating a whole organisation?
The same converters ship as a command-line audit. Point it at a GitHub organisation, a GitLab group, an Azure DevOps organisation, a Bitbucket workspace or a Jenkins server and it inventories every CI configuration it finds, converts what it can, estimates the effort per repository and lists the secrets to create. With --open-prs it opens a pull request in each GitHub repository with the workflow and the notes. Nothing is sent anywhere except the platform you point it at.
GITHUB_TOKEN=… npx jenkins-to-actions audit --github-org acme # report + workflows GITHUB_TOKEN=… npx jenkins-to-actions audit --github-org acme --open-prs # one PR per repository GITLAB_TOKEN=… npx jenkins-to-actions audit --gitlab-group acme/platform AZURE_DEVOPS_TOKEN=… npx jenkins-to-actions audit --azure-org acme npx jenkins-to-actions audit --bitbucket-workspace acme --user me --token APP_PASSWORD npx jenkins-to-actions audit --url https://jenkins.example.com --user me --token APITOKEN
See a real result: this pull request was opened by one command on a repository holding one config per system. The README has the details, and the migration page describes the fixed-fee audit if you would rather have it done for you. Once you are on Actions, the cost calculator and the free CI Cost Report action show what the minutes cost.