Gitlab CI – Automate Versions & Releases

Logo of semantic release

Introduction

Still continuing the series of Gitlab CIs & Automations,
The current article will describe how to automate versions
& Releases publishing with semantic-release.

The workflow I decided for my workflow is adapted from a basic Git
workflow like:

A git workflow model
A git workflow model

Summary

I create my Issue on my Gitlab project, open to branch from the issue, correct inside the branch,
push to dev, the CI/CD deploy onto the dev platform, It fail because "LIFE", I correct inside the branch,
push to dev, version correctly functionnal on dev, merge from dev to master, deploy onto prod, THE END.

So I wanted to be able to automatically publish version & release.
Why ? Because I'm lazy. A computer guy is often lazy.

I want to code and not have to trouble myself to search the last version
number, tag the commit on dev and "et cetera" on master.

It's here that semantic-release software seemed like a good idea,
for a description, here's their Github: https://github.com/semantic-release/semantic-release

How it will works

I will use Angular syntax when publishing my commit,
a CI/CD to launch semantic release with will then detect the commit and create
the tag & release with all the previous commits.

In details

.releaserc.json

{
  "plugins": [
    ["@semantic-release/commit-analyzer", {
      "preset": "angular",
      "releaseRules": [
        {"type": "docs", "scope":"README", "release": "patch"},
        {"type": "feat", "scope":"progress", "release": "patch"},
        {"type": "feat", "scope":"validated", "release": "minor"}
      ],
      "parserOpts": {
        "noteKeywords": ["BREAKING CHANGE", "BREAKING CHANGES"]
      }
    }],
    "@semantic-release/release-notes-generator",
    ["@semantic-release/changelog", {
      "changelogFile": "CHANGELOG.md"
    }],
    ["@semantic-release/git", {
      "assets": ["CHANGELOG.md"],
      "message": "chore(release): ${nextRelease.version}nn${nextRelease.notes}"
     }],
    "@semantic-release/gitlab"
  ],
  "branches": [
      "master",
          "+([0-9])?(.{+([0-9]),x}).x",
      { "name": "dev", "prerelease": "dev"}
  ]
}

/! Start Warning

The part with semantic-release/changelog & semantic-release/git allows me to update automatically the
CHANGELOG.md and push it to my git repo.

I also noted it generate conflict due to using pre-release branch, so I do not advise to use the CHANGELOG at the same times
that the pre-release option.

Please note that I had to redefine the "message" because semantic-release/git use by default "[skip-ci]" in the message,
Which, alas, blocked my deploy CI/CD. I'm currently asking if there is a better way to do this in https://github.com/semantic-release/git/issues/201
let's see if I can improve it again 🙂

/! End Warning

I redefined the releaseRules because i'm still not fluent with Angular default rules.
I'll update it based on my daily needs, I advise you to start with standard (remove releaseRules)
and adapt to your needs.

.release-ci.yml

release:
  image: node:12
  stage: release
  only:
    refs:
    - master
    - dev
    # This matches maintenance branches
    - /^(([0-9]+).)?([0-9]+).x/
    # This matches pre-releases
    - /^([0-9]+).([0-9]+).([0-9]+)(?:-([0-9A-Za-z-]+(?:.[0-9A-Za-z-]+)*))?(?:+[0-9A-Za-z-]+)?$/ 
  script:
    - npm install @semantic-release/gitlab
    - npm install @semantic-release/git
    - npm install @semantic-release/changelog
    - npx semantic-release --debug

The CI/CD will automatically install all the deps and work only on main branches.
I needed to fix the node version to node:12 due to it not working on node:12.

.gitlab-ci.yml

And then the Gitlab CI.

include:
  - local: '.release-ci.yml'

stages:
  - release

Commit linting

In order to use correct commit syntax I also defined a commit linting hook like the following.

.pre-commit-config.yaml

-   repo: https://github.com/jorisroovers/gitlint
    rev:  v0.13.1
    hooks:
    -   id: gitlint
        stages: [commit-msg]

It's installed to interact on commit, following the official documentation, you will need to install it like:
pre-commit install --hook-type commit-msg

Please note that I used specifically gitlint because it's in Python, so you can search for the
equivalent in your project language, maybe it exist, example: Node => commitlint.

Don't forget to add the dependence in your requirements-dev.txt
and here you go.

example_release
Example of release tagging
commit done with semantic release
The example of commit done by semantic release