Tips for automating your GitHub release creation

Last Update : 17 May 2022

Why the need for releases?

Developing software, at least great ones requires you to seek constant feedback for your product and the changes that you deliver. In other words, you need to bring your work to your client as often as possible by making it available in your production environment.

This means that your team needs to monitor closely any modifications and be able to roll back any changes by coming back to a clean and working version of your software in production.

This is evenly true for your client-facing application or for the libraries that you develop and use internally on your main applications.

Yet, as Dave Farley wrote in “Continuous Delivery: Reliable Software Releases through Build, Test, and Deployment Automation”:

Releasing software is too often an art; it should be an engineering discipline.

So how can we shift from a mystical art to a systemic approach?

The first step towards this can be made by using version control. This can be achieved with the help of GitHub releases. Nowadays, most development project uses Git as the main local tool for managing changes and leveraging platform for collaboration like GitLab, BitBucket, or Github which will be our focus here.

What is a (GitHub) release?

A release commonly refers to a set of changes that are intended to be delivered to a production environment. It usually contains some features as well as some bug fixes, among other stuff like documentation, etc.

A GitHub release is based on a specific git tag which refers to a specific historical point in a repository. It usually comes with a note on the changes that were made and of course the source code.

📕 Learn more about git tags here

What is a good-looking release?


A good release uses a principle called semantic versioning.

It provides a simple guide for numbering it consistently. Not going into too many details, a version consists of 3 numbers separated by dots. Those numbers are incremented based on the changes that are embedded in a specific release.

Note that you can also add a suffix for designating, alpha (2.1.4-a.1) or bêta version, pre-releases also known as release candidates (1.1.2-rc.3), and so on.

Documented changes

A good release comes with its associated documentation or Changelog. It describes the changes that were made from the previous one. It can be as simple as a bullet point list describing each change and providing a link to a potential ticket or issue associated with it.

Here is an example of a changelog for the Java / Android library okhttp


Still, we developers are lazy and, let’s admit it, not very keen on writing documentation of any sort so let’s see how we can automate that!

Leverage conventional commits for readability

What is a conventional commit?

A conventional commit is a commit with a name following a specific pattern.

<type>[optional scope]: <description> [optional body] [optional footer(s)]

I usually only use the first part <type>[optional scope]: <description>

feat(user-dashboard): allow users to change their personal background color’

‘fix(ordering): remove unwanted duplicated items from shopping cart’

Type Description
feat! Breaking change
feat New feature
fix A bug fix
revert Rollback of a change
docs Adding some documentation
ci Changes made to an infrastructure job
chore Upgrades, cleaning up...
perf A performance improvement
refactor A change in the code that does not affect the overall behavior
style Formatting change
test Adding some test cases


📕 Click here to see the full documentation

Enforce conventional commits on your team project

Of course, they are plenty of libraries that can help you achieve that based on which language you use. One of their key advantages is that they can be added to your build and therefore automatically install hooks without the developer noticing it.


However, let me show you an easy way to enforce conventional commits through the use of git hooks. When you create a git repository by using git init a .git folder is created which contains different sub-folders like hooks which is the one we are interested in here. A hook is a script that will run every time a specific event occurs, for example, you guessed it, a new commit is made. To activate one, just remove the hook file you want by removing the .sample suffix.

💡 Tips: If you are using a JetBrains tool, this .git is hidden by default. See here how to display it.

In order to enforce a simple pattern for your commit messages, just create the commit-msg file and add the following lines to it. This will check the format of your commit and will block it if it is not compliant with the pattern you defined


commit_msg=$(cat "${1:?Missing commit message file}")

if ! echo "$commit_msg" | grep -Eq "^(build|chore|ci|docs|feat|feat!|fix|perf|refactor|revert|style|test)(\(.+\))?: .*$" ; then

  echo "Invalid commit message"

    exit 1


echo "Commit message is valid!"


💡 You can always bypass the check by adding --no-verify after your commit message.

Well done, you have successfully enforced conventional commits on... your local version of the project! But how to share it with your teammates?

In fact, you’ll find out that you can’t push your .git folder to a remote repository. One of the most simple ways of achieving that is to add the file to a dedicated folder at the root of the project like git-hooks and to push it on the remote repository so that everyone can use it.

You can even create a small script that will take care of copying the file to the .git/hooks folder like so:


cp git-hooks/commit-msg ./.git/hooks

echo "Git commit hook successfully installed, you are ready to go!"


💡Add a line on your project Readme file to invite contributors to install it by executing the above file.

Automate your release process on GitHub

Let’s now leverage those conventional commits to create a Github action that will take care of the boring part when creating a release!

📕 Here is some documentation if you are not already familiar with the great CI/CD automation tool that is Github action.

Here we will create a manual action that will...

  • Create a new release
  • Generate short and clean documentation for it
  • Increment the version number accordingly

... all of this is in one single click.


Start by creating a release.yml file under the .github/workflows folder at the root of your project.

name: Release # Workflow name displayed on GitHub


  workflow_dispatch: # Trigger manually

   branches: main # Branch on which the workflow will run



      runs-on: ubuntu-latest


         - uses: actions/checkout@v3 # Checkout our working repository

         - name: Conventional Changelog Action

             id: changelog

             uses: TriPSs/conventional-changelog-action@v3


                 github-token: ${{ secrets.github_token }

                 output-file: "false"

  - name: Create Release # This action will create the actual release

             uses: actions/create-release@v1

             if: ${{ steps.changelog.outputs.skipped == 'false' }


                GITHUB_TOKEN: ${{ secrets.github_token }

                with: tag_name: ${{ steps.changelog.outputs.tag }

                release_name: ${{ steps.changelog.outputs.tag }

                body: ${{ steps.changelog.outputs.clean_changelog }


🗒️ In this example we are using the conventional-changelog-action from TriPSs for generating the changelog. There are many solutions available on Github to achieve that. Note that the numbering might be different than the one you expect based on the commit-hook regex you’ve chosen.

This file will create a GitHub action that you will be able to trigger manually directly from the GitHub Actions tab by clicking the run workflow as shown below.

The action will then create a new release based on your commits!

Final word

Releasing is a key part of the software delivery process and should therefore be kept seamless to do it as often as possible! 
If you want to take a step forward and measure how far you are from being an elite DevOps, have a look at The Four Key Metrics