DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Curious about the future of data-driven systems? Join our Data Engineering roundtable and learn how to build scalable data platforms.

Data Engineering: The industry has come a long way from organizing unstructured data to adopting today's modern data pipelines. See how.

Threat Detection: Learn core practices for managing security risks and vulnerabilities in your organization — don't regret those threats!

Managing API integrations: Assess your use case and needs — plus learn patterns for the design, build, and maintenance of your integrations.

Related

  • Private Cloud's Deployment
  • Continuous Delivery: Create Products Faster with Lower Risks
  • Why Incorporate CI/CD Pipeline in Your SDLC?
  • Releasing MuleSoft API

Trending

  • Making Sense of Open-Source Vulnerability Databases: NVD, OSV, and More
  • Three Habits of Highly Effective Observability Teams
  • AI-Driven Intent-Based Networking: The Future of Network Management Using AI
  • Web GenAI Microservices Creation: An Overview

Semantic Releases With CI/CD

Semantic versioning is a versioning scheme that aims to communicate the level of compatibility between releases at a glance.

By 
Tomas Fernandez user avatar
Tomas Fernandez
·
Sep. 28, 22 · Tutorial
Likes (1)
Comment
Save
Tweet
Share
4.7K Views

Join the DZone community and get the full member experience.

Join For Free

Software is constantly changing — the moment it is released, it begins to grow obsolete. Users need a constant stream of patches and want new features. At the same time, people hate when an update introduces a breaking change, especially when they were not warned about it.

Forever it has been common practice to use version numbers and codenames to track releases. Many projects have incrementing sequences (MS-DOS 6.2, 6.21, 6.22); others use part of the release date (Ubuntu 18.04, 20.04, 22.04). A few have a more whimsical disposition: TeX, for example, uses a numbering scheme that asymptotically approaches π (the current version is 3.141592653), while Metafont does the same with e. Its current version sits at 2.71828182.

Every one of us has done this.
The main problem all these versioning schemes have is failing to communicate how compatible releases are. The only recourse we have is digging through changelogs.

What Is Semantic Versioning?

Semantic versioning is a versioning scheme aiming to communicate the compatibility level between releases at a glance. It uses a three-part numbering system: major.minor.patch (e.g. 1.2.3). And is sometimes suffixed with special identifiers such as -alpha or -rc1.

Each part has a different meaning:

  1. Major: incrementing this number (1.0.0 -> 2.0.0) indicates users should expect significant breaking changes.

  2. Minor: the minor number (1.0.0 -> 1.1.0) is incremented when non-breaking features and changes have been released. Minor releases should be backward-compatible.

  3. Patch: a patch-level change (1.0.0. -> 1.0.1) is a non-breaking upgrade that introduces low-risk changes like fixing bugs or patching security issues.

A developer can quickly assess the risk of upgrading by comparing version numbers. Major releases are risky and should be planned carefully. Minor and patch-level changes have a much lower chance of introducing incompatibilities and are safer to install.

Automating Versions With Semantic-Release

How do we determine the version number in a semantic versioning scheme? It's a tricky question since a typical release includes dozens of commits. Some contain bug fixes, while others may introduce breaking changes. In such a scenario, the only way to determine the appropriate version is by reviewing each commit individually and assessing the impact. If it sounds like a lot of repetitive and error-prone work that's best done with some automated tool, you're right.

Semantic-release is a versioning tool capable of computing semantic version numbers by reading commit messages. It can also generate release notes and publish packages to GitHub and NPM.

As you might imagine, for this to work, commit messages should follow a predefined pattern:

 
<header>
<BLANK LINE>
<body>
<BLANK LINE>
<footer>


The header is the only mandatory part of the message and should be formatted like this:

 
<type>(<scope>): <short summary>


The most important component of the header is the type, which helps semantic-release assess the importance of the changes introduced in the commit. The default behavior follows Angular's message format:

Header Type Result
fix, perf Bump version to the next patch level (1.0.0 -> 1.0.1) and release
feat Bump version to the next minor level (1.0.0 -> 1.1.0) and release
docs, build, ci, refactor, test No version bump. No release.

Regardless of the header type, if the body of the commit message contains the string BREAKING CHANGE or DEPRECATED, semantic-release performs a major version increase.

To clarify, let's look at a few examples and their effects:

Commit message Result
fix(pencil): stop graphite breaking when too much pressure applied Releases a patch.
feat(pencil): add 'graphiteWidth' option Releases a minor version.
perf(pencil): remove the graphiteWidth option   BREAKING CHANGE: The graphiteWidth option has been removed.  The default graphite width of 10mm is always used for performance reasons. Releases a major version.

How to Get Started With Semantic-Release

While semantic-release is a Node-based application, it supports any language, not just JavaScript or TypeScript. You'll need to have Node and NPM installed to use it, though.

To add semantic releases to your project, follow these steps:

  1. Install and run the semantic-release wizard with npx semantic-release-cli setup. When asked which CI platform to use, select Other and copy the environment variables shown. You'll get a token for GitHub and, optionally, one for NPM.

     
     export GH_TOKEN=ghp_Lw83uUpu4paBlLKQuRijD3NMTDusAL07J89l
     export NPM_TOKEN=npm_xWtDqAasy9yBTPPuA6QppCJx7JIu5w1009KY8


  2. Go to your project's Git repository. If the project runs on Node.js, add the semantic-release package:

     
    npm --save-dev semantic-release


  3. Make some code changes and create a commit following the commit guidelines discussed before. For example:

     
    feat: initial commit


  4. Run npx semantic-release. In non-CI environments, the tool runs in dry-run mode. The log shows what version would be assigned in the next release (in the example below, v1.0.0).

     
    ℹ  Running semantic-release version 19.0.5
    ⚠  This run was not triggered in a known CI environment, running in dry-run mode.
    ✔  Allowed to push to the Git repository
    ✔  Completed step "verifyConditions" of plugin "@semantic-release/npm"
    ✔  Completed step "verifyConditions" of plugin "@semantic-release/Github"
    ℹ  No git tag version found on branch master
    ℹ  No previous release found, retrieving all commits
    ℹ  There is no previous release, the next release version is 1.0.0
    ℹ  Start step "generateNotes" of plugin "@semantic-release/release-notes-generator"
    ✔  Completed step "generateNotes" of plugin "@semantic-release/release-notes-generator"
    ⚠  Skip v1.0.0 tag creation in dry-run mode
    ℹ  Release note for version 1.0.0:
    
    # 1.0.0 (2022-08-23)
    
    ### Features
    
        * initial commit


  5. When you're ready to release, execute: npx semantic-release --no-ci. This will tag the release and publish the package.

You can customize the tool's behavior by creating a .releaserc or release.config.js file in the project's root. This will allow you to tweak the commit message format, safelist the branches capable of triggering a release, and enable optional plugins. For more details, check the configuration docs.

Semantic Versioning With CI/CD

In this section, we'll configure a CI/CD pipeline to perform semantic versioning. I assume you have installed semantic-release and already have a continuous integration pipeline.

Initial CI pipeline contains a build and tests jobs.

The starting CI pipeline builds and tests a JavaScript Node.js project.
Before we can add continuous delivery, we need to make two changes in Semaphore:
  • Disable tags, so releases don't trigger CI builds.
  • Add a secret containing the GitHub or NPM credentials.

Disable Tags on Semaphore

Semaphore triggers CI builds on all branches and Git tags by default. The problem with this behavior is that semantic-release creates and pushes a tag on every new version. So, if we don't disable (or safelist) tags on Semaphore, the tool’s release may trigger secondary (and useless) CI/CD runs.

Change the build settings by opening the Semaphore project settings and scrolling down to What to build?. Ensure the tags option is unchecked.

Do not trigger CI builds on Git tags.

Add Authentication Secrets

Semaphore will publish releases to GitHub and NPM on your behalf. So, it needs access to your authorization credentials, which we'll store using a secret.

  1. Go to your organization menu and click on Settings.

  2. Click on Secrets > New Secret

  3. The name of the secret should be semantic-release-credentials. Add your GitHub and/or NPM tokens as shown:


Set Up a Continuous Delivery Pipeline

Let's add a continuous delivery pipeline to automatically release new versions of the project.

  1. Open your project on Semaphore and edit the workflow.

  2. Click on +Add promotion to create a new pipeline. Enable automatic promotions if you want to release new versions automatically.

  3. Select the new block and add the following commands. sem-semantic-release is a thin wrapper around the tool that handles the installation and exports release information into the pipeline.

  4. Open the secrets section and enable the secret created earlier.

  5. Click on Run the workflow > Start to test your pipeline.


Click on Run the workflow > Start to test your pipeline.


Semantic Release Pipeline

 
The continuous delivery pipeline has released a new version.

This setup will execute semantic-release on each commit or merge into the master branch. Depending on the content of the commit messages, the tool might bump the version numbers and publish the release.

Extending the Delivery Pipeline

Executing sem-semantic-release in the CI environment exports special information about the release. For instance, you can determine if a release occurred by executing sem-context get ReleasePublished in a later job.

We can use these details to perform more advanced workflows or continuous deployments. Let's say we want to build a Docker image and tag it with the release number. We can use a command along these lines for that:

 
# e.g. builds my-awesome-app:2.0.1
docker build . -t my-awesome-app:$(sem-context get ReleaseVersion)


Conclusion

Maintaining consistent version numbers will help you gain the trust of users and other developers. Simple projects may only require manual versioning, but highly active codebases with several contributors won't tolerate this. The only sensible alternative is to automate the release chores and remove the human element from the middle with a tool such as semantic-release.

Happy releasing, and thanks for reading!

Contextual design Release (computing)

Published at DZone with permission of Tomas Fernandez. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Private Cloud's Deployment
  • Continuous Delivery: Create Products Faster with Lower Risks
  • Why Incorporate CI/CD Pipeline in Your SDLC?
  • Releasing MuleSoft API

Partner Resources


Comments

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends: