I love the new Github Actions and all the options it gives to automate things in my workflow such as automating CICD.

When i got added to the beta i wanted to try out if i could create a full CICD pipeline that would first build my code and release it afterwards to Azure. I used Azure DevOps quite a lot in the past and what i loved there was the separation between build and release steps where build creates an immutable artifact that will be deployed in the release stage.

gh actions

I wanted to recreate something similar so my approach was the following:

  • Create a build workflow that compiles my code
  • Let the build workflow create a release in Github containing artifacts that could be downloaded later on.
  • create a release workflow that downloads the release artifacts and deploys them to my Azure environment.

Creating the workflow that compiles code isn’t that hard. There are plenty of samples out there and Github helps you with a starter workflow by checking what kind of code is in your repo as well. Then it was time to create a release in my workflow and upload the artifacts to it. First thing i did was search the marketplace and look for tasks that could do this for me. But after not finding anything i thought to myself: Shouldn’t it be possible to do this from the command line? When building these workflows i see myself doing more and more plain command line tasks instead of using some marketplace tasks that are often not that much more than just a wrapper on top of some CLI API.

Github has a hub CLI that can automate a lot of things from the command line such as creating releases so my thoughts were just calling some hub commands and everything would be OK.. Well it wasn’t that simple because the hub cli isn’t installed by default on the build agents. To fix this I created my own marketplace task to install this CLI to the build agent and from then on you can just use all hub commands from within your Actions workflow.

Creating a release using the hub cli is easy. Just use hub release create.  There is a range of other methods you could also use in your own workflow but in this post we’ll focus on the hub release part. Hub release create does need some more setting up though because creating releases does need some authentication and we’ll need some more parameters. Let’s look at all the details. But first here is a sample full build workflow.

Install Hub CLI

As i wrote above I’ve created a custom Github Action called setup-hub that installs the hub cli on your build agent so you can use it in your workflow. If you want to use the hub CLI yourself just add these 2 lines to the workflow steps and hub CLI will be installed and added to the path.

 - name: Install hub cli
   uses: geertvdc/setup-hub@master


gh action setup-hub

Authentication

We’ll be using the hub cli from within a script block of the workflow. By default hub CLI will prompt you for an interactive login when doing authenticated calls such as creating a release. In an Actions workflow however there is already a default secret defined called GITHUB_TOKEN which you can use to authenticate.  You will have to pass it into the ‘Run’ task by setting it as an environment variable

 env:
   GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

gh actions release1

The github token will execute the command using a generic “github-actions” user. This is fine in most cases but there are some limitations. Actions created by the Github Actions user will never trigger further other actions. So in my case where i wanted to trigger a deploy workflow after a release is created wouldn’t work. To change this you can use a work around that will execute the task using  your own personal user. To do this create 2 secrets. 1 called GITHUB_USER containing your Github username and 1 secret called GITHUB_PAT that contains a personal access token for your user. Pass this PAT secret into the GITHUB_TOKEN environment variable and now the hub cli command will be executed as if it was executed by you.

 env:
   GITHUB_USER: ${{ secrets.GITHUB_USER }}
   GITHUB_TOKEN: ${{ secrets.GITHUB_PAT }}

gh action release 2

Release Versioning

Ok so now we can do authenticated calls towards the hub CLI. Now we can create a release but to actually create a release we’ll need a version number of some sort. What i do in my builds is just auto incrementing the previous release by 1. To do this we can use the hub cli to query the last release by calling hub release -L 1. this gives us the last release. Now we’ll add some bash script to increment this version

 version=$(hub release -L 1| awk -F. -v OFS=. 'NF==1{print ++$NF}; NF>1{$NF=sprintf("%0*d", length($NF), ($NF+1)); print}')
 echo $version

This oneliner will take the current version number in the form of v#.#.# and will increase the lastest number by 1.

now we have everything to call hub release in our workflow. using the -a tag you can upload artifacts as you can see in the full example i listed above.

hub release create -m $version -a $HOME/artifacts/frontend-$version.zip $version

That’s all. Now each time a push is made to the master branch a new release will be created and saved in your Github releases.  You could hook up another workflow that triggers on a release creation using the following yaml:

 on:
   release: 
     types: [created]

Hub CLI can do far more than just releases. It can also help you in automation around pr’s,or issues. I’m really curious what others will use it for. Please let me and the other readers know in the comments if you found new cool ways of using this.

If you like my setup-hub Github Action please give it a star on Github or give feedback on Twitter

Happy Coding!

Geert van der Cruijsen