Migrating from Azure DevOps Pipelines to GitHub Actions can be a challenging task, especially if you have a large project with complex build definitions. However, the process can be simplified with the help of the GitHub CLI Migration Extension. In this blog post, we will go through the steps involved in using this extension to migrate from Azure DevOps Pipelines to GitHub Actions.
Before We Get Started
Before we jump into migration I must note that migration from Azure DevOps to GitHub is a huge task (at least if you have 20+ pipelines) and you should always plan your migration very carefully. You don’t have to migrate all pipelines at once, but living with two systems can be a pain in the ass, so try to keep it as short as possible.
Install GitHub CLI and Migration Extension
Ok let’s get started with our migration. The first step in using the GitHub CLI migration extension is to install the GitHub CLI itself. The GitHub CLI provides a command-line interface to interact with GitHub repositories and can be installed on various platforms. To install the GitHub CLI visit https://cli.github.com and follow the page instructions.
Next open up terminal (or command prompt) and install the gh-actions-importer extension
gh extension install github/gh-actions-importer
You can verify that the extension works by running following command
gh actions-importer -h
PAT tokens
To run the migration we need two PAT tokens. One for the GitHub and another for the Azure DevOps.
To create a token for GitHub see this guide: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token#creating-a-personal-access-token-classic
GitHub token requires workflow scope to work.
For Azure DevOps see this guide: https://learn.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate?view=azure-devops&tabs=Windows#create-a-pat
Azure DevOps token requires following permissions to work:
- Agents Pool:
Read
- Build:
Read
- Code:
Read
- Release:
Read
- Service Connections:
Read
- Task Groups:
Read
- Variable Groups:
Read
Now we have everything set and we can configure the GH CLI extension by running configure command.
gh actions-importer configure
Answer the questions that wizard asks and use default for GitHub and Azure DevOps base URLs. Don’t add your organization names to these.
Next we need to update the actions importer, even though that we just installed it. I don’t know why this needs to be done, but without it the migration will most probably produce an error. Run update with following command:
gh actions-importer update
Now we are ready to simulate the migration and see how well this tool can handle all of our pipeline quirks. To run the simulation use Audit command with output directory.
gh actions-importer audit azure-devops --output-dir tmp
output-dir needs to be relative path. Giving absolute path like c:\temp will not work. This commands goes through your Azure DevOps pipelines for given project and creates a report how well it can convert pipelines into GitHub Actions. The report gives you some directions, but it is not full truth. The report can say, that importer is able to migrate the pipeline, but it won’t work at GitHub without little tweaking.
For example if you use **/*.csproj paths in your Azure DevOps Pipelines the importer will bring the setting like that into GitHub Actions and it won’t work. To fix this you have two options: Extend the importer or manually fix the paths at GitHub into something like MyProject/MyProject.csproj.
Migration
Finally we can run our importer and do the actual migration. Great thing about this tool is that it will create pull request about the imported action. It won’t just magically create things into your GitHub repository. To be able to create a pull request is a powerful tool to inspect the final result, maybe create an extension and rerun the the migration. Pull request can also be reviewed by your co-workers, so you get that extra security and safety over what you are doing.
Migration is run with migrate azure-devops pipeline command. You need to pass the pipeline-id (if you want to run it just for one pipeline), GitHub target URL and directory for logs. You can find the pipeline id easily by editing a pipeline at Azure DevOps and check the URL.
gh actions-importer migrate azure-devops pipeline --pipeline-id (pipeline id at Azure DevOps) --target-url https://github.com/(your organization)/(your repository) --output-dir ghactionsmigrate
Extending the Importer
If you need to migrate multiple pipelines, it might not be practical to fix all the migration errors one-by-one at GitHub pull request. Luckily we can extend the importer and write our own Ruby scripts, which can convert those pesky paths into proper GitHub Action paths. I will later provide a guide about how to extend the importer, but you should be able to find some good examples at GitHub.
Final Thoughts
Migrating Azure DevOps pipelines into GitHub can be a cumbersome job. You need to plan your migration carefully and then decide what tools to use. You might want to also think about upgrading pipelines into better suitable actions and not just go with the lift and shift approach. If you want to do the later, then GitHub actions-importer is a great tool for that. Happy migration!