DEV Community

Qumber Hussain
Qumber Hussain

Posted on

How to be smart about releasing software -Semantic Release Conventional Commits and GitHub actions

There are a multitude of ways to release software. In this article we will be discussing deployment of software with Semantic Release, Conventional Commits and GitHub actions.

In an Agile world we want to release software often. So the question becomes how do we release software in such a way that we can release often, not break existing deployments and keep track of what was released - without the need for manual reporting on features implemented and bugs fixed.

So how do we go about releasing and deploying this.

Starting with Conventional commits

Conventional commits are git commit messages that have a defined structure to make commits human and machine readable. Here are what a few typical commits may look like.

feat(data): add JSON file with 1 meme entry

fix(data): correct the path of meme

build: add new script command for tests

feat(header): add Header component

Each commit is prefixed with a type - feat, fix, docs, build etc - see documentation for full list. The type is followed by optional scope surrounded by parenthesis to describe the thing being worked on feat(component-name), docs(component-name) etc.

As a team, all developers must follow this convention in order for Semantic Release to work correctly. This is because these commits will be what get added in the release notes generated by Semantic Release.

[Developers sign up for this convention typically at the start of a project]

Semantic Versioning

Semantic versioning or SemVer for short is a specification that describes how software should be versioned. When you see a software version like 12.6.1, which is very common these days, the 12 in this case is the MAJOR version, the 6 the MINOR version and the 1 a PATCH version.

A MAJOR version number is incremented by 1 (usually) to describe this new version is incompatible with the previous version, so it is a major change. The MINOR version number is also incremented by 1 which describes new functionality has been added in a backwards compatible manner. The PATCH version describes, what usually are, bug fixes to the existing software version.

Semantic Release

Semantic Release uses the specification designed by Semantic Versioning (SemVer) and couples that with Conventional Commits and a CI (continuous integration) environment to create fully automated releases.

Example of Semantic Release in GitHub

Example of Semantic Release in GitHub

Semantic Release for GitHub

So we know that we need to use Conventional Commits, and that Semantic Releases uses those to generate releases and increment the software version. But how do releases get generated in GitHub? This is where the GitHub Semantic Release package comes in.

GitHub actions

GitHub Actions is a tool used for automating software development workflows, such as building, testing, and deploying code. When a workflow is triggered, GitHub Actions runs a series of steps in a virtual environment, such as running a script, checking out code, or deploying to a server. We will create a GitHub action by adding a release.yml file in to the .github/workflows folder in the repo.

Getting Started

Let’s now create a barebones repository structure to demonstrate how Conventional Commits, Semantic Release and GitHub Actions all work together. Be sure to have the latest Node installed on your machine.

  1. Create new repo and clone it to your machine

Image description

  1. Change directory to cloned repository and initialise an NPM project

    cd dev-project-2023
    npm init -y
    

    This create a new Node project which allows us to take advantage of NPM and many packages that facilitate our development

  2. Install Jest

    yarn add jest
    

    Jest is a testing framework, setup here just as an example for the project.

  3. Set up files

    1. Create an index.js file - this is typically where our application might start from
    function get2() {
      return 2;
    }
    
    module.exports = get2;
    

    b. Create a test.js file

    const get2 = require("./index.js");
    
    test("Runs get2 returns 2", () => {
      expect(get2()).toBe(2);
    });
    
  4. Install SR and GHSR - Lets install SemanticRelease and GitHub Semantic Release packages

    yarn add semantic-release github-semantic-release
    
  5. Create an .releaser.json file

    {
      "plugins": [
        "@semantic-release/commit-analyzer",
        "@semantic-release/release-notes-generator",
        "@semantic-release/github"
      ],
      "branches": ["main"]
    }
    
  6. Create a .release.yml file inside .github/workflows folder

    name: Release
    "on":
      push:
        branches:
          - main
    jobs:
      release:
        name: release
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v3
          - uses: actions/setup-node@v3
            with:
              node-version: 14.17
          - run: yarn install --frozen-lockfile
          - run: npx semantic-release
            env:
              GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
    
  7. Secrets

    Secrets are encrypted variables that we use for authentication needed for the GitHub Semantic Release package to use. The secret (secrets.GH_TOKEN) will contain your personal access token that you will need to generate in the settings tab of the repo. Follow the instructions here https://github.com/semantic-release/github#configuration

  8. Create a new branch called next off main

    1. Create a feature branch called feature-branch-x off next
  9. Conventional commits

    1. Make a change any change, lets say to the function and test file. And commit:

    feat(index): change function

    function get3() {
      return 3;
    }
    
    module.exports = get3;
    

    test(index): change test file

    const get3 = require("./index.js");
    
    test("Runs get3 returns 3", () => {
      expect(get3()).toBe(3);
    });
    
  10. Merge feature branch back into next

  11. Then do a pull request into main and merge

    PR into main branch

  12. See GitHub action running generating tag and release

    Image description

  13. List of tags and releases

list of tags in GitHub
List of releases generated by Semantic Release in GitHub

Here we can see that after making several changes, how a tag is created and a subsequent release generated.

Conclusion

Together Semantic versioning, conventional commits, Github Semantic Release, and Github Actions form a powerful suite of tools that can help to streamline the software development process and ensure the delivery of high-quality software releases. By utilizing these tools, developers can work more efficiently, reduce the risk of errors, and focus on delivering valuable software to users.

Top comments (0)