Semantic Release Survival Guide
This is a collection of tips and things I learned from using semantic release in various scenarios
I first came across semantic release when working on an npm module (currently private but will be public soon) for my company, datree.io.
The benefits were immediately clear to me: easy releases, version bumping, release notes, clear and structured commit messages. The flow was elegant and easy to integrate as we host our code on GitHub and build with Travis CI.
The simple use case is clear and well documented on the readme. I encountered some problems with semantic release when i needed to release locally and when working on a project that doesn’t include publishing a module to npm. All these problems are fixable but solutions are scattered and it’s hard to pinpoint the source of the problem. Messages like semantic-release ERR! pre ENOTINHISTORY Commit not in history Error
don’t give too much insight into the underlying problem or the possible solution. Let’s look at some of the use cases:
- Releasing from a local machine
- Releasing without publishing to NPM
- Releasing during Travis build stages
- recovering from ENOTINHISTORY error
Releasing Locally
Releasing locally is hardly the recommended way of releasing but sometimes it’s needed, even if only for fixing another problem with semantic release (more on that later on).
To release locally you need 3 things:
- running the commands with
debug=false
.
I added another script to mypackage.json
calledsemantic-release-local
that does just that
Having the right environment variables. semantic release requires a GH_TOKEN
environment variable which you can acquire from GitHub and an NPM_TOKEN
environment variable, that can be acquired by taking the part following_authToken=
in .npmrc
after younpm login
- The final part for a successful local release is disabling the
verifyConditions
plugin to prevent semantic release from checking that it’s run on a CI Server. This is done by pointingverifyConditions
to a specialplugin-noop
. Add the following to yourpackage.json
Once this is done you can npm run semantic-release-local
to release locally. Avoid committing the verifyConditions
part since you want all the checks semantic release provides in that plugin.
Releasing without publishing to NPM
That was by far the hardest and the most useful use case. Once I saw the benefits of semantic release and started using it in my npm modules, I wanted to apply the same comfort and ease to my web servers and other repositories that are not npm modules. This proved to be very hard as semantic release relies on the previously published version to detect changes and if you don’t publish you can only do a single release and in the subsequent attempts to release you’ll get this useful message: semantic-release ERR! post Failed to publish release notes. { [Error: {“message”:”Reference already exists”,”documentation_url”:”https://developer.github.com/v3/git/refs/#create-a-reference"}]
To release without publishing you need 2 things:
- A plugin to detect the changes from git tags instead of npm publishes. semantic release have a stub repo for it, last-release-git-tag, but it has nothing in it and it obviously doesn’t work. What does work is last-release-git. You add it to the release part of
package.json
after you install it as a dev dependency.
- Remove the
npm publish
part of yoursemantic-release
npm script
Releasing in Travis build stages
Build stages is a new feature in travis that in it’s simplest form allows to run a job once other jobs complete. If the “normal” way of releasing with semantic release is to do it in the after_success
part of travis.yml
this method doesn’t work well if, for example, you only have a single build agent and your build process tests on several node versions. In that case the first job, running tests on node 6, waits for the rest of the jobs to complete before running the after_success
part. But, the other jobs, node 8 for example, can’t run because you only have a single agent and it’s busy-waiting. You’re in a deadlock! Another case is when you have a build process that consists of many jobs, in that case you have an agent that busy-waits for who knows how long till all the other jobs complete and it may resume the after_success
step. In this case you’d want to release in the jobs
part of travis.yml
.
To release in Travis Build Stages you need 2 things:
- The
plugin-noop
part from the first section. You need it because one of the thingsverifyConditions
checks is that it’s run in theafter_success
stage of the build. To run it in build stages you need to disable this check and that’s the easiest way I found to do it:
- The job configuration in your
travis.yml
. This is an example job I use.
That’s it, you’re done. In travis you’ll see it at the bottom as a separate job and all your agents will be free to actually do some real work.
ENOTINHISTORY Commit not in history Error
This is one of the most annoying messages you get when using semantic release and the hardest to pinpoint IMHO. I don’t have a definite solution but these are the tips and solutions that worked for me in several cases.
- Deleting the last tag and release in GitHub and trying to push again.
- Sometimes you’ll find a suggestion to release manually, that’s what the “Release Locally” part is for. It worked for me, once.
- Make sure you also publish to npm or use a release that doesn’t publish to npm (see above)
Before you leave…
If you found this article helpful, hit the👏 button below and share the article. If you have something to add or correct please comment below