About: Words on React, GraphQL, Next.JS, Cypress, Privacy and Remote Work
Location:
Toronto
Joined:
Jul 24, 2017
Publishing a JavaScript Package to NPM automatically with Github Actions
Publish Date: Mar 25 '20
14 1
Want more great content like this? Sign up for my newsletter, visit: alec.coffee/signup
Maintaining an open-source package can be a time-consuming task. Issues to be triaged, pull requests to be reviewed and changelogs to write. Publishing new versions of the code is usually done manually and making it automated is often on the back-burner of the maintainers' to-do list. There are a couple of key features of a rock-solid release process, the changelog, Git tags, NPM versions, and enforcing Semantic Versioning. Keeping all these in sync makes it so users understand changes in a release and understand how to keep up-to-date. Maintainers who fail to perform all of these steps will have a hard time triaging issues, which leads to more time debugging and less time spent coding. I recently came across a combo of tools, semantic-release and Github Actions, which made the entire release process automated, transparent, and simple to understand.
📦🚀 Fully automated version management and package publishing
📦🚀 semantic-release
Fully automated version management and package publishing
semantic-release automates the whole package release workflow including: determining the next version number, generating the release notes, and publishing the package.
This removes the immediate connection between human emotions and version numbers, strictly following the Semantic Versioning specification and communicating the impact of changes to consumers.
Trust us, this will change your workflow for the better. – egghead.io
Before we talk about implementation, it's important to understand what work our tools will perform. That way, if there are problems or modifications, we can fix them. semantic-release is going to do the majority of the work here, they say it best on their README.
It automates the whole package release workflow including determining the next version number, generating the release notes and publishing the package.
The Next Version Number
During a release, to determine the next version number, the tool reads commits since the last release. It knows your last release by looking at your Git tags. Based on the type of commit, it can determine how to bump up the version of the package. For this to work, commits need to be written in a certain way. By default, semantic-release uses the Angular Commit Message Conventions. This is critical because consumers of the package need to know if a new version releases a new feature, introduces breaking changes or both. For example, if someone commits fix(pencil): stop graphite breaking when too much pressure applied, semantic-release knows this contains a fix and to create a patch release. This will increase the version in the minor version range (0.0.x).
After analyzing all the commits, it takes the highest priority type of change and makes sure that is the one that is applied. For example, if two commits were introduced since the last release, one breaking (x.0.0) and one minor (0.0.x), it would know to just up the version by breaking range.
Generating Release Notes
Once it has done finding out what type of release the next version is, changelog notes are generated based on the commits. semantic-release doesn't use conventional CHANGELOG.md file to notify users of what has changed, it does so with a Github Release which is attached to a Git tag.
So semantic-release will be the tool to perform most of the work, but we still need a service to run the tool on. That is where Github Actions comes into play. When pull-requests are merged into master (or any base branch you configure), Github Actions will run a job that simply runs semantic-release with your configuration. All of the work we described previously will be performed.
The last step is to create a Github Action YAML file. This will tell Github Actions what to do when a commit is made to the repository.
# .github/workflows/test-and-release.yamlname:Test and Releaseon:[push]jobs:test-and-release:name:Run tests and releaseruns-on:ubuntu-18.04steps:-name:Checkoutuses:actions/checkout@v1-name:Setup Node.jsuses:actions/setup-node@v1with:node-version:12-name:Install dependenciesrun:npm ci-name:Run testsrun:npm test-name:Releaseenv:GITHUB_TOKEN:${{ secrets.GITHUB_TOKEN }}NPM_TOKEN:${{ secrets.NPM_TOKEN }}run:npm run semantic-release
Add NPM_TOKEN to the secrets in the Github repos settings page. You can generate one of these from your NPM account at https://www.npmjs.com/settings//tokens
And that's it! You have a fully automated package release process 🎉
Bonus
I implemented this on a repo we recently open-sourced at Yolk AI. It's named next-utils and everything described here can be found there.
This module is distributed via npm which is bundled with node and
should be installed as one of your project's dependencies:
npm install @yolkai/next-utils
Note
NOTE: Using any of these Higher-Order-Components will disable Automatic Static Optimization (statically built pages), since the Higher-Order-Component forces every page to implement getInitialProps.
Another great thing about using semantic-release with Github Actions is that it has out-of-the-box support for bot comments. It will go into every issue and pull-request closed since the last release and comment to make sure everyone is aware. Here is an example:
That's amazing, thanks for the tutorial it really helped me out setting ci for my library for the first time.