🚀 Automate NPM package publish & GIT versioning
Tags: npm, git, productivity, webdev
Published: 2021-01-20 18:29:22

---
title: 🚀 Automate NPM package publish & GIT versioning
published: true
description: Automating NPM package publish & GIT versioning
tags: npm, git, productivity, webdev
cover_image: https://voice4thought.org/wp-content/uploads/2018/11/online-publishing-tools-2.png
---

Save time, improve your build process by streamlining releases.

## Intro
Assuming a scenario for a typical package (which yourself is the sole author of), such as some sort of web component, CSS library, etc. which is intended to be used in a *client* and has some sort of a build process.

As mentioned above, this article is not meant for multi-developers codebase which are actively working on branches, because we don't want to tag anything when pushing, and certainly not publishing, since doing that is reserved for a dedicated pipeline (*devops*). 

For the sake of example, this article presents a portion of code used in one of my packages - [knobs](https://github.com/yairEO/knobs), which is a pretty small project which uses [Rollup](https://github.com/rollup/rollup) to [bundle](https://dev.to/tanhauhau/what-is-module-bundler-and-how-does-it-work-3gp2) the *JS* & *SCSS*.

## 📜 NPM scripts - basics
This topic has been [addressed a lot](https://dev.to/search?q=npm+scripts) and this article assumes basic knowledge of working with NPM custom scripts and with lifecycle ones, such as `start`, `test`, `version`, `prepublishOnly` and so on.

## 😥 What can go wrong without automatic release flow:
Since the project requires a build process, without automating the release flow as much as possible, *unwanted outcome* might occur:
1. Accidentally deleted imported distribution file 
2. Forgetting to build before releasing
3. Forgetting to tag the version 
4. Using wrong git tag (mismatch with `version` in `package.json`
5. Not sure of the order of which things should be done before `publish`: [*should tag before committing or after?*](https://stackoverflow.com/q/35221147/104380)
6. Forgetting to push the tags

🦺 **Wanted:** *Something* which guarantees nothing of above happens. 

### `package.json` *before* the change:

```json
{
  "scripts": {
    "start": "rollup -c rollup.config.dev.js -w",
    "build:prod": "npm run clean && npm run bundle:prod",
    "bundle:prod": "rollup -c rollup.config.prod.js",
    "clean": "rm -rf knobs.min.js",
    "test": "echo \"No test specified\"",
  }
}
```

Pretty standard bunch of scripts, nothing interesting to talk about.

In order to publish the package, a *non-automated* release flow example would require to first run `npm build:prod`, which will run the cleanup script and then the bundling script, which runs without the `watch` command, because watching is unnecessary just before deploying since there is no code change. Then commit, and add a git tag and push *with* the tag, everything, and then publish the code. (or publish and then push).

### Lets improve by adding a few scripts:
There are many ways to automate the above workflow (or half-automate), but I would like to talk about a specific tool which I find very helpful:

<a href="https://github.com/sindresorhus/np" >https://github.com/sindresorhus/np</a>
<a href="https://github.com/sindresorhus/np" target="_blank">
<img src="https://github.com/sindresorhus/np/raw/master/screenshot.gif"/></a>

1. [`np`](https://github.com/sindresorhus/np) is best installed globally: `npm i -g np`
2. [`headr`](https://github.com/heldr/headr) is a great package for automating header comment in the dist files, which includes information from the `package.json` file itself, such as version, author name, repository url, etc. **install** it also if you wish.
3. [`pkg-ok`](https://github.com/typicode/pkg-ok) is another script which ensures no (important) file is missing, I advise using it.

### `package.json` *after* the change 🤟:

```json
{
  "scripts": {
    "start": "rollup -c rollup.config.dev.js -w",
    "build:prod": "npm run clean && npm run bundle:prod",
    "bundle:prod": "rollup -c rollup.config.prod.js",
    "clean": "rm -rf knobs.min.js",
    "test": "echo \"No test specified\"",

    "header": "headr knobs.min.js -o=knobs.min.js --version --homepage",
    "version": "npm run build:prod && npm run header && git add .",
    "prepublishOnly": "pkg-ok"
  }
}
```

And the command used to publish & push is:
```js
np --yolo
```

🧐 **Note** that I am using the `--yolo` flag because I want to skip tests (I don't have tests) and not clean the `node_modules` and reinstall everything which can take long minutes. 

> `np` package also allows writing a [pre-defined configuration](https://github.com/sindresorhus/np#config) within `package.json` itself, using the `np` property.

`version` (*npm* scripts property) is a [lifecycle script hook](https://docs.npmjs.com/cli/v6/using-npm/scripts) which runs exactly at the appropriate time to build the code, output the bundle and add a header comment (to any file) with the just-bumped version number.

`prepublishOnly` (*npm* scripts property) lifecycle hook is a good place to check no file is missing before proceeding, using `pkg-ok`.
 
🏃‍♂️ Running the above command (`np --yolo`) will present a GUI:<br>*(screenshot from `np` repo)*

<img src="https://github.com/sindresorhus/np/raw/master/screenshot-ui.png"/>

If all goes well, the package will be published and a new browser tab/window will open the project's *GIT* repository URL, for you to approve & publish a new ***tagged*** release in the repo.

<img src="https://media1.popsugar-assets.com/files/thumbor/_NabRgXjkct2atlFqs3TCEHaaQo/fit-in/1024x1024/filters:format_auto-!!-:strip_icc-!!-/2014/07/28/909/n/1922507/32a3b2f32e6a8a2e_drops-mic/i/Drops-Mic.jpg">