Implementing Semantic Release for Unscoped Public Packages | by Anton Kalik | September 2023


Thanks to Sunday Harper Since Unsplash for that picture

In the evolving software development landscape, maintaining release consistency and automating the release process is more important than ever. Enter Semantic liberation: a tool designed to ensure clear and structured versioning. For developers leveraging public, unscoped packages, the process can seem daunting. However, with the power of GitHub Actions at your fingertips, automation becomes child’s play.

This article offers a detailed and comprehensive guide, providing step-by-step instructions for seamlessly integrating Semantic Release into your workflow, especially tailored for those using public, unscoped packages. Dive in and discover the streamlined approach to software releases.

When I created my public package, I ran into some obstacles publishing it seamlessly on NPM. It was a challenge to ensure the correct configurations.

To achieve this, let’s walk through a step-by-step experience for properly publishing public packages to MNP.

Package Name

Before we start implementing our package, it is best to find the appropriate name for it. To be sure the name is not already taken, check my_package_name and take it for your package. I chose “tokky”. From this moment, reserving the package name is impossible. For the name in npm, you must publish the package.

Create a plan

The goal is to develop a simple package that displays content on the console. We need to make sure we can install and run it. For the construction process, let’s use simple build. During this article I will use the package name tokky. Let’s create package.json with the initial data.

mkdir tokky && cd tokky && npm init -y

After running the command, the system generated a default value package.json file for the project, which looks like this:

"name": "tokky",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
"keywords": (),
"author": "",
"license": "ISC"

In this guide, the package.json The file plays a crucial role in ensuring the correct configuration. At this point, let’s specify the node version for our package:

echo "v18" > .nvmrc

and activate the specified version with the following:

nvm use

For the deposit:

echo "# Tokky\n\nA simple zero dependency logger for node js." >

Finally, install the development dependencies:

npm i -D esbuild eslint prettier

In our initial setup, we need to address several key points in the package.json:

  • main: This designates the main entry point of the module.
  • bin: Here you will specify all the executables provided by your module.
  • files: This should contain an array of file templates that will be included when the package is compressed and then published to the npm registry.
  • private: Make sure this setting is set to false because our package is intended to be public.
  • publishConfig: Access for this must be set to public.

After these configurations, your package.json should look like the following:

package.json after initial setup

Additionally, let’s add two ignored files:


and for npm:


Finally, I will describe my setup for ESLint. Keep in mind, however, that configuration may vary depending on your specific plan requirements.

Configuring .eslintrc.js

Next, head to GitHub and create a new repository. Name it after your package.

GitHub create repository
Create a repository on GitHub

Continue by running the following commands:

git init
git add .
git commit -m "first commit"
git branch -M main
git remote add origin<your_github_username>/tokky.git
git push -u origin main

Package Source

Next, let’s create a base application and configure it for building. Inside of src folder, generate a index.js file and fill it with the following content:

Simple script for sample package

The concept is simple: execute my_package_name hi should show “Hello (username)”. To validate this functionality, run the command directly from your repository using:

node src/index.js hi

If the result matches expectations, it’s time to create the source:

npm run build

Successful execution of this command will produce a dist folder containing a minified index.js deposit.


Running Semantic Release, which will determine version changes and manage the release process based on commit messages, requires environment variables (GITHUB_TOKEN, NPM_TOKEN) to function properly. The tokens are mined from GitHub secrets, ensuring their confidentiality.

Set up GITHUB_TOKENnavigate here:

Generate the token using a drop-down list. Click on the new Personal Access Token (classic) and set the authorization as in the image. Use your package name as shown below:

Set GitHub token

Once generated, copy the token value and keep it confidential: it is crucial not to share it with others. Temporarily store this token safely, as we will need it soon for the CLI Semantic Release.

To generate the NPM_TOKENyou first need an account on npm official website. If you have not yet registered, follow the registration process. After that, navigate to:<your_user_name>/tokens/new

and generate a “classic” token with the “publish” option.

NPM generate token

Copy the generated token value and navigate to GitHub secrets:<your_user_name>/<your_repo_name>/settings/secrets/actions/new

and put a new secret like NPM_TOKEN to the secrets of the repository:

NPM token on GitHub repository secrets

Once we have our secrets configured, we can configure GitHub Actions.

Configuring GitHub Actions

To automate our processes, we will use GitHub Actions. It is a CI/CD tool integrated with GitHub. It allows developers to automate workflows directly from their GitHub repositories, such as building, testing, and deploying applications. By defining workflows in YAML files, users can trigger actions based on specific events such as push and pull requests or scheduled times, making the software development process more efficient and automated.

To get started, create a .github directory at the root of your project. Within this directory, establish a workflows subfolder. Here, create our configuration file named release.yml and fill it with the following content:

Github Semantic Release Action

This workflow triggers a push event to the main branch. It is configured to run work on the latest Ubuntu GitHub virtual machine offerings. While it’s not imperative to review every job, let’s highlight a few in particular. Towards the end, note how we invoke npm run semantic-release using the designated tokens.

Semantic liberation

For the automated release process, we will use Semantic Release. This tool manages versioning and publishing packages based on the semantics of commit messages. It follows Semantic Versioning (SemVer) conventions to determine version changes (major, minor or fixes). By analyzing commit messages, it eliminates manual versioning steps, ensures consistent version numbers, and streamlines the release process. Let’s install it.

For this configuration we will use this GitHub code and run it on your repository:

npx semantic-release-cli setup

And follow the questions:

% npx semantic-release-cli setup
? What is your npm registry?
? What is your npm username? your_user_name
? What is your npm password? (hidden)
? What is your NPM two-factor authentication code? 00000000
? Provide a GitHub Personal Access Token (create a token at
ettings/tokens/new?scopes=repo) ghp_your_token_here
? What CI are you using? Github Actions

You should already have your personal token. Just enter it when prompted. Likewise, the GitHub actions we have implemented will use the NPM_TOKEN which we have previously established in the secrets of the repository. If you now check your package.jsonthe version will display as:

"version": "0.0.0-development",

and new script:

"semantic-release": "semantic-release"

which was automatically generated by the Semantic Release CLI. We will need to improve this script as follows:

"semantic-release": "semantic-release --branches main"

This indicates that releases will only be made from the master branch.

Additionally, Semantic Release generates a description based on the repository field in your package.json. This field provides details about the location of the package source code.

"repository": {
"type": "git",
"url": "<your_github_username>/your_github_repo.git"

Now let’s push all our changes with:

git add . && git commit -m "semantic release" && git push

Validation format

Semantic Release relies on the convention of structured commit messages to determine the type of version change (major, minor, or patch) and generate change logs. This commit convention is often called the “Conventional Commits” format.

For this setup we will need several plugins. Make sure your package.json contains the following content:

For the configuration validation format tool, we will use to commit. To install it, follow this command:

npx commitizen init cz-conventional-changelog --save-dev --save-exact

This command will take a few minutes. Then update your package.json with a new script:

  "scripts": {
// ...
"commit": "cz"

and it’s time to use this script. Start by executing git add .then run npm run commit and provide the details necessary for your commitment. This is what it looks like:

? Select the type of change that you're committing: feat: A new feature
? What is the scope of this change (e.g. component or file name): (press enter
to skip) commit
? Write a short, imperative tense description of the change (max 86 chars):
(14) add commitizen
? Provide a longer description of the change: (press enter to skip)
? Are there any breaking changes? No
? Does this change affect any open issues? No

After that, do a git push.

In the GitHub Actions, you will see that our commit failed because we still haven’t installed the rest of the packages for the automated commit message process.

npm i -D @semantic-release/commit-analyzer @semantic-release/release-notes-generator @semantic-release/npm @semantic-release/changelog

A crucial step, often overlooked in most benchmarks, is setting workflow permissions. Move towards and configure permissions to allow GitHub actions both read and write.

GitHub workflow actions permissions
Allow read and write permissions

Next, let’s change things up a bit. Engage with a specific keyword, feat:followed by your message.

git add . && git commit -m "feat: my feature commit" && git push

Do you remember the releaseRules within package.json? These rules dictate how we increment our package version. Once this is in place, you can create a pull request using specific keywords like feat, fix, refactor, And so on. Once this pull request is approved and then merged into the main branch, it will fire a trigger. This trigger then activates the GitHub action, automates the publishing process and ensures that your package is updated seamlessly.

Package released

The package has been successfully released and the entire process has been automated for greater efficiency. To confirm the publication, go to your npm settings and look under the packages section; there you will find your newly released package.

Now with a simple command like npx your_package_name hi, you can immediately see the results of our development tests. Additionally, the package can be installed globally using the command npm i -g your_package_name.

As we’ve seen throughout this article, while initial setups can be fraught with challenges, the reward lies in establishing a streamlined and consistent publishing process. Leveraging GitHub Actions simplifies these complexities, ensuring that developers can focus on code quality rather than logistical intricacies.

Whether you’re just starting your journey with public packages or have encountered setbacks in your publishing efforts, there is undeniable value in adopting a structured, automated workflow. By integrating Semantic Release, you ensure consistent release management and champion a forward-looking approach to software development.

So much for seamless publishing, fewer headaches, and more time spent perfecting the code that powers our digital world.

Remember that it is essential that both NPM_TOKEN And GITHUB_TOKEN have the appropriate permissions in GitHub Actions. Additionally, your package.json must be correctly configured with the settings of publishConfig access and ensure that the private the configuration is set to false. If you encounter any problems or have any ideas, please feel free to comment.

Semantic version CLI:
To commit :


Source link

Related Articles

Back to top button