Reading Time: 3 minutes

Most of us have used git and probably GitHub as well. For quite some time they have made GitHub Actions available. This is a pipeline feature inside GitHub has the possibility to do amazing things. Big difference from AppVeyor or Travis CI is that you can include standard blocks, called actions, into your workload. The only thing you need to add are your parameters. Just like you would need when executing a command on your favorite shell.

GitTools is an organisation that creates the GitVersion and GitReleaseManager tools. GitVersion is a tool that helps you achieve Symantic Versioning to your project, while GitReleaseManager is a tool that helps you release your application or product with the help of milestones, generates Release notes and closes your milestone.

For a BoxStarter project that I have been working on, I wanted to release the software in an automated and consistent way. Therefore I created my own GitHub Actions workflow called Release. This workflow only triggers on a branch that is created that starts with the word release and runs on the latest Ubuntu image available in GitHub Actions

name: Release
      - release/*

    name: Release
    if: startsWith(github.ref, 'refs/heads/release')
    runs-on: ubuntu-latest

In this workflow execute the following steps:

  • Checkout the repository
  • Fetch all tags and branches
  • ZIP the release
  • Extract owner and repo
  • Install GitVersion
  • Get the version, using GitVersion
  • Install GitReleaseManager
  • Create the release, using GitReleaseManager
  • Publish the release, using GitReleaseManager
  • Close milestone

The actions explained

The first three steps where the somewhat easy steps. These steps are probably used in every Release workflow. The first thing I execute in my Workflow is the checkout step. For this I am using the default Checkout Action available from GitHub. After the checkout, I am fetching all the history using the default git command. I don’t believe there is currently an default action for this and this is the current best practice to do so. Same goes for creating a zip archive, I haven’t found an action that does that. But since I am using an Ubuntu image to release my application, zip is available on the OS. I am excluding all the .git files and folders, as I don’t believe they should be available in a release. Perhaps I should have excluded the “.vscode” folder as well, but I haven’t done this (yet).

    - name: Checkout repository
        uses: actions/checkout@v2
      - name: Fetch all history for all tags and branches
        run: git fetch --prune --unshallow

      - name: Zip Release
        run: zip -x '*.git*' -r . 

GitHub Actions has some default variables available. One of these variables is “github.repository”. In this variable the owner and repository name are concatenated with a forward slash. When using GitReleaseManager the owner and repository are required to be provided separately. Therefore I used the jungwinter/split action. Within this action you can split a variable up in multiple variables by providing a separator character. This character can be anything like a space, underscore or, in my case, a forward slash. By providing an ID to the action, you will be able to use the output of this action in an other action.

      - name: Extract owner and repo
        uses: jungwinter/split@v1
        id: repo
          seperator: '/'
          msg: ${{ github.repository }}

GitTools actions

The next variable that I need is my version number that I am going to release. Here is where GitTool’s GitVerison comes into play. The usage of this tool is pretty straight forward. However it’s not installed by default on the GitHub Action images. Therefore an extra action should be executed to install the package and its dependencies inside your environment. After you have it installed, you can execute it. Again, by adding an ID, the output can be used in an other action.

      - name: Install GitVersion
        uses: gittools/actions/gitversion/setup@v0.9.2
          versionSpec: '5.x'

      - name: Use GitVersion
        uses: gittools/actions/gitversion/execute@v0.9.2
        id: gitversion

We now have all the things we need for the release using GitReleaseManager. Same as with GitVersion, GitReleaseManager needs to be installed. After that, you can create your draft release with the release notes and attach your assets to it, in our case After that, you should publish your release. And, as our last step, close the milestone. These steps utilizes all the values that we gathered using the previous steps. and , the “secrets.GITHUB_TOKEN” variable. This is a magic variable set by GitHub Actions and uses a token available in GitHub.

      - name: Install GitReleaseManager
        uses: gittools/actions/gitreleasemanager/setup@v0.9
          versionSpec: '0.11.x'

      - name: Create release with GitReleaseManager
        uses: gittools/actions/gitreleasemanager/create@v0.9
          token: ${{ secrets.GITHUB_TOKEN }}
          owner: ${{ steps.repo.outputs._0 }}
          repository: ${{ steps.repo.outputs._1 }}
          milestone: ${{ steps.gitversion.outputs.majorMinorPatch }}
          name: 'Release ${{ steps.gitversion.outputs.majorMinorPatch }}'
          assets:  |
      - name: Publish release with GitReleaseManager
        uses: gittools/actions/gitreleasemanager/publish@v0.9
          token: ${{ secrets.GITHUB_TOKEN }}
          owner: ${{ steps.repo.outputs._0 }}
          repository: ${{ steps.repo.outputs._1 }}
          tagName: ${{ steps.gitversion.outputs.majorMinorPatch }}

      - name: Close release with GitReleaseManager
        uses: gittools/actions/gitreleasemanager/close@v0.9
          token: ${{ secrets.GITHUB_TOKEN }}
          owner: ${{ steps.repo.outputs._0 }}
          repository: ${{ steps.repo.outputs._1 }}
          milestone: ${{ steps.gitversion.outputs.majorMinorPatch }}

For more information about GitTools Actions, please have a look at their GitHub repo. You could do more with the GitHub Actions than I have done. This was not applicable to my release and therefore not utilized.