What is semantic-release and how to work with it

Hello! I am Alexey Bondarenko, I work in the Banki.ru Platform team. Today I want to talk about semantic-release and its practical application using the example of simplifying the development and implementation of a library in a project.

The plan is:

  • I’ll start with definitions and versioning principles that are needed to understand the topic;

  • I’ll tell you what using semantic-release gives you;

  • I’ll figure out how the tool works, what its features and limitations are.

At the end of the article there will be a link to the repository. It can be used as a starting point for working with semantic-release.

What is versioning

Although most people are familiar with this concept, I think it’s worth reminding.

We come across versioning often. Be it a car model in different generations and modifications or a literary work in different editions.

It's a similar story with the code. We write the code, start using it – one version. We make improvements, enable new functionality, and another one appears.
The question arises – what to call these versions? In words that convey the meaning of the changes, should they be numbered in order or something else?

In development, different options for assigning versions to code are used. For example, Calendar Versioning (CalVer), zer0ver. You can read more about them in this article.

But the most popular is probably semantic versioning or semver.

Principles of semantic versioning

Semantic versioning is a set of rules and requirements that determine how version numbers are assigned and incremented.

In semantic versioning, a version is three numbers separated by a dot.

Where:

Z — a patch version, when something changes inside and the public API remains the same. For example, the sorting method in one of the elements changed, the library began to work faster.

Y — minor version, when new functionality is added and not violated API backwards compatibility. An additional optional parameter has been added to the public method.

X – major version when broken backwards compatible API . For example, a public method was renamed.

Let me give you an analogy from the life of a motorist.
Z – we changed the light bulbs in the car's headlights: the light remained the same, the headlights simply began to burn brighter.
Y – a new mode has appeared for the air conditioner: rear window blowing has been added.
Z – the controls were changed: the button was moved from one place to another. You can't do this without reading the instructions.

What does semver give

A proper versioning scheme helps developers easily identify the current release, changes made, and whether a version is compatible with previous ones. Specifically semantic versioning only makes sense when library development: there is one code base, but there are many consumers.

As my colleague wrote in one of articles, we have come a long way from a monolith with submodules, to microfrontends with a large number of shared libraries. Our team develops and supports internal UI-KIT components that are used in projects of all product verticals of the company. Within the company, we work with this library as an open-source project: each team can make changes and send them for review.

Previously, the component library was connected to the main monolithic project using a submodule (git submodule). There were risks in such a scheme: it was possible to set a pointer to the wrong commit and break the code. To avoid this, we had to use a script that checked that the submodule hash in the release pointed to the commit from the master.

In our case, the use of semantic versioning helps to understand and determine the scale of the “disaster” when installing a package update. Allows you to plan your work and make it more predictable. Saves time, effort and nerves.

How to get started using semantic versioning

Let's say we realized that semantic versioning is great and decided to use it. What is needed for this?
Let's start with the minimum – manual version management and changes without deployment.
Let's imagine that we have a repository where we store code.

One option is to add a tag to the code, also known as a version:

git tag 1.0.0

and send to the repository (with all tags):

git push --tags

Then install from there:

npm i <путь к репозиторию>#<тег> 
// например npm i https://github.com/shakacode/bootstrap-loader.git#v1.0.10

You can also assign a tag through the git web interface of the repository.

It is possible to work with this minimum, but it is inconvenient. One important point is missing. As was written above, semantic versioning helps to understand what changes were made. This means that information about these changes needs to be stored somewhere. They are usually recorded in the changelog.md file.

How is it all synchronize? And put a tag, and write what changes were made specifically in this version.

Installing a package directly from a git repository is a good solution to start with, but it’s not very suitable for production development. Because the package source code is usually different from the supplied code

Everyone wants simplicity: installing ready-to-use libraries using their names. Typically a package registry is used for this. npm. The code is prepared and published in this registry. The important thing here is to ensure that the version in package.json is correct. If necessary, assign a tag.

The task becomes more complicated again: you need to synchronize git repository, information about the changes made (changelog.md) And package registry.

It is possible to do this by hand, but it is difficult. The human factor often leads to errors. Semantic-release allows you to automate this entire routine and avoid mistakes.

How semantic-release works

Semantic-release is npm packagewhich fully automates a large amount of work.

Commit Agreement

The most important thing for correct operation semantic-release — write commit messages in a specific format. There are rules for this, described in commit agreements. By default Angular commit message.

When we commit according to conventions, we solve the problem “adding information about changes made” (changelog). In commits we indicate what changes have been made to the code. Semantic-release will analyze these messages and generate a list of changes for a specific version of the code: which changes fall into the major, minor and patch version.

The commit message template looks like this:

<тип>[необязательный контекст]: <описание>

[необязательное тело]

[необязательная(ые) сноска(и)]

An example of such a message:

feat: Добавлена возможность отображения виджета вертикально

Добавлена пропса direction отвечающая за направление отображения виджета.

Task: #WIDGETS-32

Setting up semantic-release

Semantic-release works on the principle of plugins and includes nine steps. At each step, control is transferred to plugins to perform specific actions.

IN semantic-release The following plugins are enabled by default:

@semantic-release/commit-analyzer — analyzes commit messages.
@semantic-release/release-notes-generator — generates a list of changes (changelog) from the latest release to the current commit.
@semantic-release/npm – publishes the package to npm.
@semantic-release/github – work with github releases and comments in issues.

You can start with the default config and plugins.

Semantic-release can be run locally using the command (written below). First you need to commit in accordance with the commit conventions.

NPM_TOKEN=<npm_token> GH_TOKEN=<github_token> npx semantic-release --no-ci --dry-run

This command is with a key --dry-run will make a test run semantic-release (without steps: prepare, publish, add channel, success and failure). Flag --no-ci allows you to run semantic-release from the local machine (skips the continuous integration environment check).

If you want this command to work for real, remove the flag --dry-run.

How to create a github personal token (<github_token>) you can find out – here. And npm token (<npm_token>) — here. The lines that will be generated must be added to the command above.

As a result, we should receive the published package in npm And entry in releases.

To make it really good, two more plugins are missing:

@semantic-release/changelog — makes changes to the changelog file, from which you can then obtain information about changes made to the code (not everyone uses github for packages).
@semantic-release/git — commits changes to the git repository.

Here we can no longer do without a configuration file. In a simple version it will look like this:

// .releaserc
{
    "branches": ["master"],
    "plugins": [
        "@semantic-release/commit-analyzer",
        "@semantic-release/release-notes-generator",
        "@semantic-release/changelog",
        "@semantic-release/npm",
        "@semantic-release/github",
        "@semantic-release/git"
    ]
}

You can read more about configuration here.

After launch semantic-release we should see an entry in the changelog file and a commit with the changes in the git repository. You need to remember that the bot makes a commit in the branch that you have specified for deployment. In our case this is master. Therefore, this user needs to register push rights to the master.

Semantic-release It has many plugins for different occasions. Their list can be found on the official website. Or write mine.

Sandbox for testing semantic-release

To play with semantic-releaseuse one prepared for these purposes github repo. There are more detailed instructions there. And here you can see npm package result.

Limitations of the approach

  1. You won't be able to roll back changes. If a version is released and problems are found in it, this can only be solved by releasing a new version.

  2. Commit messages must be made according to the rules of the commit agreements. This task can be automated. For example, using commitlint.

  3. The process must be approached responsibly. Divide commits into completed portions of changes. Fans of commits like “fix fix fix” will definitely be disappointed.

  4. During the review, make sure that commit messages reflect changes in the code.

  5. For fans of squash commits there will also be disappointments: the agreement will be broken and the semantic release will not see the changes.

Alternatives

Conclusion

Tested out a new approach. Yes, we encountered a lot of problems, but we liked it! Currently 10+ libraries are deployed using semantic-release in fully automatic mode. The deployment speed has increased significantly. There is no need to train anyone to publish packages manually and waste time on it.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *