Release Cycles

Utilizing and automating Github Releases in your repo
Author
Affiliations

Frank Aragona

Washington Department of Health

Data Integration/Quality Assurance

Published

September 1, 2023

Modified

September 10, 2024

Summary

  • Github Releases
  • Helps devs and end users
  • Changelogs and semantic versioning
  • Automate the release process


Github Releases

In the right panel of your Github repo there is a section labeled Releases. Here you can create or find a version of your repo’s code base. Each version comes with a changelog, tags, and downloadable source code. Developers and end-users may find this helpful to navigate to what the repo contained at specific release versions and have the source code available for download at the specific version.


If you click on the releases you can see different release tags/versions. Each comes with a changelog, tag, git hash number, and zip files to download the repo at the time the specific version was released. This means you can automatically save repo snapshots and backups whenever your project cycle is released.


you can flip through different releases and tags here


You can click on a tag and it will take you to the repo at the time the specific version was released

Semantic Versioning

Software projects often label their releases using semantic versioning. It looks like this, where the software version numbers all have a definition:

https://www.softwarecraftsperson.com/2020/12/06/semantic-versioning-semver-introduction/

https://www.softwarecraftsperson.com/2020/12/06/semantic-versioning-semver-introduction/

Conventional Commits

To create the release cycle in your repo you may want to use Conventional Commits.

Conventional Commits are a way to format and standardize your commit messages, which can be used to then automate the repo’s release cycle. For example, one conventional naming method is to label any commit associated with a new feature as feat: plus a commit message.

  • The word feat: can trigger a Github Action to add that commit to your changelog under the Features header,
  • and it will up-version the minor release version number.
  • So if you are on release 1.0.0, a new feat will up-version the cycle to 1.1.0
  • Commit titles that start with the word fix: as in a bug fix will up-version the patch number of the, i.e. 1.0.0 to 1.0.1

Automating The Release Cycle

You should consider automating your release cycle so that your project cycle is consistent and predictable. There are many different ways to approach this.

Some repos have semi-automatic cycles where there is some manual component of releasing their software, whereas others are fully automated. Manual releases can work too for some scenarios.

Github Action for auto releases

I recommend first creating a test repo for this. In the repo, create a Github Action workflow called changelog.yml. You can copy the full file below:

.github/workflows/changelog.yml
name: Changelog
on:
  push:
    branches:
      - main

jobs:
  changelog:
    runs-on: ubuntu-latest
    
    permissions:
      # write permission is required to create a github release
      contents: write

    steps:
      - uses: actions/checkout@v2

      - name: Conventional Changelog Action
        id: changelog
        uses: TriPSs/conventional-changelog-action@v3
        with:
          github-token: ${{ secrets.github_token }}
          create-summary: true

      - name: Create Release
        uses: actions/create-release@v1
        if: ${{ steps.changelog.outputs.skipped == 'false' }}
        env:
          GITHUB_TOKEN: ${{ secrets.github_token }}
        with:
          prerelease: false
          tag_name: ${{ steps.changelog.outputs.tag }}
          release_name: ${{ steps.changelog.outputs.tag }}
          body: ${{ steps.changelog.outputs.clean_changelog }}

This workflow will be triggered everytime a branch is merged to main. If that branch has conventinal commit messages the commits will be summarized in the changelog. See an example workflow below:


If I make a branch off of main, I can add features, bug fixes, and more. If I used conventional commit messages in the title (i.e. feat: message, fix: message) the Github Action workflow will detect the trigger word in the title and divide the commit accordingly in the changelog. Notice how the commit title message gets output automatically into the changelog under the header Bug Fixes and the commit + commit hash number are generated.

A new version will be released, and since this was just a bug fix the version number went from v2.1.4 to v2.1.5 since bug fixes only up-version the patch numbers

The first step uses the Github Action TriPSs/conventional-changelog-action@v3 which will scan your

.github/workflows/changelog.yml
steps:
  - uses: actions/checkout@v2

  - name: Conventional Changelog Action
    id: changelog
    uses: TriPSs/conventional-changelog-action@v3
    with:
      github-token: ${{ secrets.github_token }}
      create-summary: true

The second step uses the Github Action actions/create-release@v1 which will create git tags with the version number and a changelog with downloadable source code

.github/workflows/changelog.yml
- name: Create Release
  uses: actions/create-release@v1
  if: ${{ steps.changelog.outputs.skipped == 'false' }}
  env:
    GITHUB_TOKEN: ${{ secrets.github_token }}
  with:
    prerelease: false
    tag_name: ${{ steps.changelog.outputs.tag }}
    release_name: ${{ steps.changelog.outputs.tag }}
    body: ${{ steps.changelog.outputs.clean_changelog }}

Step by Step Instructions

  1. Make a test repo in Github, then clone it locally
  2. Make a folder in the root of the repo named .github
  3. In the .github folder make another folder named workflows . the .github/workflows folder needs to be spelled the same and in the in exact same place for a github action to work.
  4. In the workflows folder make a file called changelog.yml and paste code below in it:
.github/workflows/changelog.yml
name: Changelog
on:
  push:
    branches:
      - main

jobs:
  changelog:
    runs-on: ubuntu-latest
    
    permissions:
      # write permission is required to create a github release
      contents: write

    steps:
      - uses: actions/checkout@v2

      - name: Conventional Changelog Action
        id: changelog
        uses: TriPSs/conventional-changelog-action@v3
        with:
          github-token: ${{ secrets.github_token }}
          create-summary: true

      - name: Create Release
        uses: actions/create-release@v1
        if: ${{ steps.changelog.outputs.skipped == 'false' }}
        env:
          GITHUB_TOKEN: ${{ secrets.github_token }}
        with:
          prerelease: false
          tag_name: ${{ steps.changelog.outputs.tag }}
          release_name: ${{ steps.changelog.outputs.tag }}
          body: ${{ steps.changelog.outputs.clean_changelog }}
Note

Now when you commit something to the repo and have a convential commit message it will trigger the Github Action to make a changelog.

For example, if you make a commit with a bug fix and in the commit title you write the word fix: like this - fix: this commit is a bugfix - the action will get triggered to make a new changelog with the commit and bump up the minor version (like from v1.0.0 to v1.0.1)

This is great, but if you do not write a conventional commit message it will not work. Step 5 has instructions on how to make sure everyone on your team writes conventional commits. It uses a pre-commit hook, which will prevent any commit that does not have a conventional commit message from being pushed to the repo.

For example, this commit message will error out and not be pushed to the repo - this commit is a feature. But this commit message will work - feat: this commit is a feature

  1. (Optional, but recommended) Make a pre-commit hook

    Command Prompt
    pip install pre-commit
    • Check that pre-commit is working by running the code below. If you get an error message with this you may need to install pip
    Command Prompt
    pre-commit --version
    • In the root of you repo, make a file called .pre-commit-config.yaml and put the following code in it (note the . is necessary in the file name):
    .pre-commit-config.yaml
    repos:
    - repo: https://github.com/compilerla/conventional-pre-commit
      rev: v2.4.0
      hooks:
        - id: conventional-pre-commit
          stages: [commit-msg]
          args: []
      # args is optional: list of Conventional Commits types to allow e.g. [feat, fix, ci, chore, test]
    • Last, in the Windows Command Prompt, run this:
    Command Prompt
    pre-commit install --hook-type commit-msg

Now you will be required to use conventional commit messages when pushing new code to the repo.

Here’s a common guide:

conventional commit keyword expected outcome
feat: new changelog, bump up the minor release version (i.e, 1.0.0 to 1.1.0)
fix: new changelog, bump up the patch release version (i.e, 1.0.0 to 1.0.1)

chore:

docs:

test:

no changes
any keyword plus BREAKING CHANGE: in the commit message new changelog, bump up the MAJOR release version (i.e, 1.0.0 to 2.0.0)

NOTE: breaking changes need to be written like this:

Resources

These videos are excellent summaries of how to use Github Releases and semantic versioning