Getting started with Github Actions and .NET 5
Finding my way around Github Actions as an Azure Pipelines fan
May 17, 2022
December 2022 update
Since I wrote this article in May I've had more hands-on experience with using Github Actions to deploy Umbraco. On this basis I've added a new section about releases to different environments and how to trigger them.
Introduction
Towards the end of 2021 people kept telling me that Github Actions is the future - the implication being that maybe Azure Pipelines' number was up.
At a glance it's fair to say there's plenty of similarities between Actions and Pipeline.
- They are CI/CD tools favouring "pipelines as code"
- They are Microsoft products
- Both support a wide range of development environments (.NET, Node, Python, Java, etc).
Pipelines is part of the wider Azure DevOps suite and Actions is a feature of Github and limited to use by projects on Github (it's worth noting, DevOps can be used with most Git providers, including GitHub).
There's definitely room in the CI/CD world for both Pipelines and Actions. At any rate, Actions seems like an exciting new tool so I decided to jump in and have a go.
Since I often work with Umbraco and it offers an example project beyond a "Hello World" .NET MVC app, I used Umbraco for my testing.
Getting started
It turns out getting started with Github Actions in Azure is incredibly easy because Azure offers to set it up when you provision a Web App.
You can even see a preview of the Workflow (a Github Actions script) before you create the Web App.
The default Workflow is pretty simple and consists of two Jobs (the individual logical parts that make up a Github Workflow), a build
step and a deploy
step. Note that it is necessary to upload the results of the build step to make use of the build in the deploy step.
This Workflow actually works out-of-the-box and results in the following:
So that's it, right?
Performance
You may have noticed a fly in the ointment! In the example above the build and deploy took ~13 minutes which is a really long time for a simple build.
I spent a little time trying to improve performance and made a couple of interesting discoveries.
Always zip your artefact
After a little investigation it seem seems Jobs (Actions' logical steps) in a Workflow need to upload and download Artefacts to share data. In this case, the build
step uploads the build for our deploy
step.
This step is pretty fast if your build has few files but thanks to Umbraco our build contains ~3000 files. It seems Action's upload step doesn't zip the folder and initiates a HTTP request for each file!
After zipping the build the whole workflow took about half the time (~6 mins).
Switch to Linux
It's easy to forget that .NET Core projects can now build on Linux and many Actions .NET examples use windows-latest
.
By switching to ubuntu-latest
the Workflow run time was roughly halved again (~3 mins).
A real world example
A big thank you to Ulrich Ebsen who shared the results of his switch to building on Linux (in Pipelines) đź’Ş.
Thanks @hejgordon for the tip about using Linux as the build server for .NET Core in Azure Devops.. just did a simple test with #umbraco 9.. the middle one used Linux.. ;) pic.twitter.com/6hlVx0e5Fp
— Ulrich Ebsen (@ecoredk) January 27, 2022
Updates
<a id="releases"></a> Releases and deployment
When I originally wrote this article I had not considered deployment/releases. In the default workflow deployment happens every time - which is perfect on a dev branch pushing to a test environment but obviously unsuitable for production.
The only solution I've encountered is to use tags and adding conditions to each deploy step to check the github.ref
for the relevant tag. For example, the staging deploy might check for tags containing staging
:
- name: Deploy to STAGING
if: ${{ contains(github.ref, 'staging-') }}
uses: azure/webapps-deploy@v2
...
A word of caution: make sure your conditions are robust, otherwise feature/keep-alive
branch might trigger a deploy to live
!
This is a satisfactory solution but I still prefer the Release Pipelines of Azure DevOps!
Summary
- Getting started is easy with Azure’s built-in integration.
- Make sure you zip the artefact!
- Use Linux (
ubuntu-latest
) can speed up builds further. - Microsoft’s documentation seems the most thorough for implementing a useful workflow.
Would I switch to Github Actions?
Github Actions seems like a great tool but isn’t as feature rich as Azure Pipelines, Microsoft has a great comparison.
In particular, I love the way Pipelines separates build/test and release pipelines. I think a core aspect of CI/CD is always having a build ready to go to whatever environment and that just isn't the workflow in Github Actions. In Actions Workflow's can’t share artefacts so build and deploy need to be part of the same Workflow.
Lastly, it's hard to say no to Pipelines' effortless Azure integration (especially when setting up release pipelines).
Where Actions does shine though is its generosity with parallelism. Even with Github Free you can have a significant number of builds running in parallel (at some point I had 10+) since you're billed for minutes.
Resources
-
Microsoft's CI/CD docs on Github Actions (probably the most in-depth resource)
-
Umbraco DevOps PART 3: Implementing a CI/CD Workflow Using Github Actions by Simone Chiaretta (interestingly uses Azure Resource Manager templates)
Thanks for reading!
If you'd like to talk about anything in this post, give me a shout on the Umbraco Discord, Mastadon or other means.