Logo - Harry Gordon

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.

Screenshot of the Deployment tab when creating a Web App in Azure

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:

Workflow execution example - shows the build and deploy steps in a neat diagram

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) đź’Ş.

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

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.

This site is static HTML, managed in Umbraco 13 and then rendered using the Astro framework. The UI uses Tailwind CSS and a tiny amount of vanilla JavaScript.

Designed by Emily Geraghty