Step-by-step instructions for releasing a public unscoped package using semantic versioning leveraging the power of GitHub Actions
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.
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:
"test": "echo \"Error: no test specified\" && exit 1"
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:
echo "# Tokky\n\nA simple zero dependency logger for node js." > README.md
Finally, install the development dependencies:
npm i -D esbuild eslint prettier
In our initial setup, we need to address several key points in the
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
falsebecause our package is intended to be public.
publishConfig: Access for this must be set to
After these configurations, your
package.json should look like the following:
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.
Next, head to GitHub and create a new repository. Name it after your package.
Continue by running the following commands:
git add .
git commit -m "first commit"
git branch -M main
git remote add origin email@example.com:<your_github_username>/tokky.git
git push -u origin main
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:
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
Running Semantic Release, which will determine version changes and manage the release process based on commit messages, requires environment variables (
NPM_TOKEN) to function properly. The tokens are mined from GitHub secrets, ensuring their confidentiality.
GITHUB_TOKENnavigate here: https://github.com/settings/tokens
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:
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:
and generate a “classic” token with the “publish” option.
Copy the generated token value and navigate to GitHub secrets:
and put a new secret like
NPM_TOKEN to the secrets of the repository:
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:
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.
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? https://registry.npmjs.org/
? 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 https://github.com/s
? 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:
and new script:
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.
Now let’s push all our changes with:
git add . && git commit -m "semantic release" && git push
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:
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
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.
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
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
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.
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
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.