How to automate semantic version of your project


What is semantic versioning?

Semantic Versioning, often abbreviated as SemVer, provides a standardized way to indicate the compatibility and impact of updates, making it easier for developers and users to understand how a new version of a software component relates to previous versions.

Semantic Versioning consists of three main components:

[Major].[Minor].[Patch]
  1. Major Version:

Incremented when there are incompatible changes, such as breaking changes or significant new features that require modification in how the software is used.

  1. Minor Version:

Incremented when new features are added in a backward-compatible manner or when there are significant improvements.

  1. Patch Version:

Incremented for backward-compatible bug fixes, patches, or minor improvements that don't introduce new features or breaking changes.

Automate semantic versioning of your project with @semantic-release

I introduced @semantic-release package to my colleagues to automate our projects versioning. It is very convenient since it is simple to set up and automatically creates changelog.md and release note according to the commit message. Before using this package you must follow the structured rules of commit messages.

Commit message rules

Every commit message you write in your project consists of three parts:

[header] <- mandatory
// empty line
[body] <- optional
// empty line
[footer] <- optional

You can omit [body] and [footer], but not [header] part. And each part should be divided by empty line.

<type>(<scope(optional)>): <short summary>
  │       │                      │
  │       │                      └─⫸ Summary of commit
  │       │
  │       └─⫸ Commit Scope: define where the commit belongs to (optional)
  │
  └─⫸ Commit Type: build|ci|docs|feat|fix|perf|refactor|test|chore
  • build: Changes that affect the build system or external dependencies (example scopes: npm)
  • ci: Changes to our CI configuration files and scripts (examples: CircleCi, SauceLabs)
  • docs: Documentation only changes
  • feat: A new feature
  • fix: A bug fix
  • perf: A code change that improves performance
  • refactor: A code change that neither fixes a bug nor adds a feature
  • test: Adding missing tests or correcting existing tests
  • feedback(feature_name): Adapt feedback about the feature
  • chore: this will be ignore by the semantic release process and not appear in the changelog

🐥 body : optional

explain why you are making the change.

The footer can contain information about breaking changes and deprecations and is also the place to reference GitLab issues and other PRs that this commit closes or is related to.

bash

# If your MR has big changes and need to bump up a major version
BREAKING CHANGE: <breaking change summary>

# If your MR make feature deprecated
DEPRECATED: <what is deprecated>

Setup

  1. Download packages

bash

yarn add -D semantic-release @semantic-release/changelog @semantic-release/git @semantic-release/gitlab
  1. Create release.config.js

js

module.exports = {
  branches: ['main'], // The branch where semantic-release check your commits
  ci: false, // If you run this in 
  dryRun: process.env.IS_LOCAL === 'true', // for local testing
  plugins: [
    '@semantic-release/commit-analyzer',
    '@semantic-release/release-notes-generator',
    [
      '@semantic-release/changelog',
      {
        changelogFile: './CHANGELOG.md'
      }
    ],
    [
      '@semantic-release/npm',
      {
        npmPublish: false,
      }
    ],
    [
      '@semantic-release/git',
      {
        message: 'chore(release): ${nextRelease.version} [skip ci] [skip-cd]\n\n${nextRelease.notes}'
      }
    ],
    [
      '@semantic-release/gitlab',
      {
        gitlabUrl: 'https://gitlab.com/'
      }
    ]
  ]
}
  1. Test in local (Must set dryRun true in release.config.js)

bash

yarn semantic-release

If there is at least one feat commit, the minor version is incremented.

bash

# version updated X.0.X -> X.1.0
feat: some feature update
feat: some feature update2

If there is no feat commit and at least one fix commit, the patch version is incremented.

bash

# version updated X.X.0 -> X.X.1
fix: some fix
refactor: some refactor..
fix: some fix2
  1. Add Gitlab CI step

yml

semantic-release:
  stage: deploy
  needs: ['unit-tests']
  interruptible: true
  rules:
    - if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == $PROD_BRANCH
      when: on_success
    - when: never
  script:
    - yarn semantic-release

Reference