Many of the questions we receive around DevOps transformation usually involve one of two topics. They concern either migrating source code to GitHub or leveraging the power of GitHub Actions to rebuild Azure Pipelines after a successful code migration. Today we'll talk about the second topic. At a very basic level, GitHub Actions and Azure Pipelines share the same fundamental elements which empower Continuous Delivery. The difference is that Azure DevOps is more often used in enterprises, whereas GitHub Actions works for everyone “beyond code” using YAML.
How to migrate an Azure Pipeline?
Let’s take a look at one such migration from Azure Pipelines to GitHub Actions. We have built a sample to demonstrate just how easy it can be.Here is a summary of our steps:
- Move the YAML file
- Publish the YAML file
- Add the Triggers
- Define the environment variables
- Modify steps
- Open the Runner and validate
If you would like to follow along, the Azure Pipeline build is available under this link and the source code is located on GitHub.Tip: Start simple and build upon your success!This Azure Pipeline is relatively straightforward. Here’s the breakdown: Every merge to the master triggers the pipeline, builds the code, and publishes the results to NuGet.
At first glance, the GitHub Actions editor looks quite similar to the Azure Pipeline interface in Azure DevOps. The interface is very intuitive. On the right, you can easily discover tasks that are available to use out of the box.
While the number and variety of tasks available are quite impressive, they are tiny in comparison to what has been made available by GitHub users. Not all of the Azure Pipeline tasks are available as GitHub Actions, but if you can’t find what you need, you can always build it yourself and contribute to the community!
Move and publish the YAML file
To begin our migration, we have to move our YAML file to “.github/workflows.” GitHub Actions requires that it be stored in the .github/workflows folder. After publishing, GitHub will automatically detect a new Action to perform.
Add the triggers
Next, we will begin to add the required to support our automation. A trigger is a definition of what and how our action will be run. The same mechanism is available in the Azure Pipeline but it is not quite as elaborate.The screenshot below highlights the key differences in the structure of this workflow when comparing Azure Pipelines to GitHub Actions.
Right now, pr and trigger are combined with one object called “on”. This is broken down further into two sections; “push” and “pull_request.” When comparing the two workflows, think of “push” as “trigger” and “pull_request” as “pr”.GitHub Actions is more generous on build triggers than Azure pipelines. You can trigger your GitHub Actions for a wide variety of event types. Just a few examples are:
- fork
- issues
- label
- milestone
- page build
- public
- release
- watch
- discussion
and many more. If you’d like to see just how many triggers are available to you, see GitHub’s documentation.
Define GitHub Actions environment variables
A crucial part of Azure Pipelines are the Jobs. As you most likely already know, Jobs are stored steps that run to achieve a required result using pre-defined variables. By comparison, GitHub actions don’t have private variables. Everything is stored as an Environment variable.This is a key difference between the two tools. In Azure Pipelines, you can define global variable groups that can be declared and called from within Jobs. In GitHub Actions, you will define variables as environment variables only at the workflow level. This provides a tremendous amount of flexibility in the architecture and use of your GitHub Actions.
How do jobs work in GitHub?
Inside a job, you will define the permissions required to complete the necessary steps. For example, you can write instructions that allow this job to create a pull request and approve it as part of the same set of steps. In Azure DevOps, it is possible to define this level of permissions as well, but the issue is that these changes would then be global for the entire organisation. This is not something our InfoSec teams would be very happy about. The flexibility and variety of jobs within GitHub Actions allow us to be very creative in meeting the business requirements of our organisation in as efficient a manner as possible.Another key difference between GitHub Actions and Azure Pipelines lies in GitHub’s ability to pass the output of one job so that it may be used by another job. In Azure Pipelines, you can’t manifestly expose the output from one job to be used by a dependent job. We accomplish this in GitHub by leveraging the Outputs section.
Modify steps
The biggest hurdle for most users making the move from Azure Pipelines to GitHub Actions will be the significant syntax change is in the steps area.Azure Pipeline tasks are incredibly easy to use. In GitHub Actions, we don’t have tasks, but we can use actions or script against the shell by using JavaScript or container that encompasses a group of steps, pre-defined activities, the installation of SDK, etc. As a best practice, the preferred method is to use the shell. In our case, we use a setup-dotnet action to install dotnet on the job machine Dotnet Core Tool, and then we use a shell script to build and pack everything up in a convenient way for reuse.
All actions are available on the official GitHub Marketplace. Using a shell instead of depending on a task is a good approach when considering quality and reliability. In addition, it’s easier to reproduce steps from your local machine to your actions if you do run into a problem requiring debug work.
Open the Runner and validate
The last thing we’d like to mention as part of our migration outline tutorial is the Runner window. The Runner is a single instance of our action where everything is invoked. Everything that is defined in the YAML file is generated and filled with the required data using the appropriate context and triggers; including necessary pull requests to support the action. Inside the Runner, we can find all logs, artifacts, and an intuitive UI of our definitions.
The final note on GitHub Actions
In conclusion, while GitHub Actions offer tremendous flexibility and creativity to accomplish automation beyond code, they are still missing a few required components if we want to fully replace our enterprise pipelines at scale. A good example of this lies in centrally managing variables for many GitHub Actions, changing the name of the build dynamically, or keeping many dependent stages in a single GitHub Action. Tip: GitHub Actions do not include service connections. There are only webhooks. This is not enough to orchestrate many environments in the cloud. Build full Proof of Concept implementations to make sure the functionality you need is available or contact us, so that we can save you time and money in your move from Azure Pipelines to GitHub Actions!Watching the roadmap and documentation, it's apparent that GitHub will resolve this key requirement for enterprise organisations very soon. Microsoft is introducing new features and functionalities every day. Some upcoming features we are particularly looking forward to are templates and reusable templates.