npm scripting: git, version and deploy

Posted by Marcus Hammarberg on August 24, 2015

npm scripting: git, version and deploy

In the last post I promised to write something about “git, pushing and deploying”. This is purely from a personal need since I have used make for those things. I wanted to see if I can move all of that to use npm and package.json instead.
I’ll also add a compile and minification step, just since that it’s a common need.
[UPDATED]
This, and other posts on npm scripting, has drawn a lot of attention. I wanted you to know that I have created a PluralSight course on this topic, published in late October 2015. You can find it here.
Also, don’t miss the other posts on this blog on npm scripting:
npm scripting: git, version and deploy
npm scripting: configs and arguments… and some more tricks
Pre and Post hooks for npm scripting
If you liked this post I know you will love the course! Thank you for reading this

In the last post I promised to write something about “git, pushing and deploying”. This is purely from a personal need since I have used make for those things. I wanted to see if I can move all of that to use npm and package.json instead.

I’ll also add a compile and minification step, just since that it’s a common need.

[UPDATED]
This, and other posts on npm scripting, has drawn a lot of attention. I wanted you to know that I have created a PluralSight course on this topic, published in late October 2015. You can find it here.

Each of those tasks can be started individually and there’s also a deployToProd task which just runs them all in order.

To make this a little bit more “complete” we should probably add some sorts of compilation step before (and maybe a minification step after) 1.

Well - time waits for no-one. Let’s go. You can find the full code here, by the way.

Compilation

Everytime I write “compilation” when it comes to JavaScript I cannot help but to giggle a little. Wasn’t it supposed to be interpreted? What have we done? Well, well… Typescript and CoffeeScript are two very common options to spice up your JavaScript or your productivity.

The pattern here will be the same as for all our tasks; add npm tool to devDependencies, write script for task, plug task into over-all deploy script.

Both TypeScript and CoffeeScript (as well as most any tool you can think of) have npm packages. Typically package for tools like these also have command line tools that you easily can use in your build process. Hmmm… maybe using npm as a build tool isn’t such a bad idea after all.

Let’s do both just for the fun of it. Here’s my package.json updates with tasks to compile coffee-script.

Note that I don't require this to be installed globally on the users computer. Including these tools as a devDependecies will make sure that I can use them.

Also note the nice comment from Juho Vepsäläinen below that told me how to clean up my scripts from paths to the ./node_modules/ directory

There’s two scripts that is interesting so far compile:coffee and compile. In the compile:coffee script I just compiles the coffee-script to the lib-folder.
The compile-script will be an overarching script, where I do all compilation.

varshould=require("should");varapp=require("../");describe("Test placeholder",function(){it("testing frameworks",function(done){app.should.not.be.null;done();});it("calls into stuff written in coffeescript",function(done){app.fillMyJar("Java").should.equal("Filling the jar with Java...");done();});it("calls into stuff written in typescript too",function(done){app.greetAType("Marcus").should.equal("A type-scripting greeting to you, Marcus");done();});});

This means that we now create a test and a suitable pretest task that runs the compilation before the testing, as we learned about in the last post.

Just to make sure that everything is safe, let’s clear out the lib-folder, with a clean task.

[UPDATED]
Got a nice tip from maxdow about using rimraf to clean the folder out. It’s a normal Node package and in doing so we can ensure that this runs on any platform, nothing “Linux” or “Windows” specific in the scripts.

Now that you go npm t (short cut for npm test, remember) the following happens:

pretest is run

clean is run

compile is run

compile:coffee is run

compile:ts is run

test is run

Pssst - you can slience the output from npm with npm t -s.

There should probably be some linting in there too, but I did that in the last post and this is running log already.

Versioning

That was compilation and testing from my list in the start of this post. Let’s tackle versioning. The challenge here is that we want to update the version number in the package.json but also set a tag in our git log, marking a new version.

If you think this sounds daunting, fear no more: this is actually built right into npm itself. Let’s check the command with npm version -h:

What it’s trying to say is that you can either set the version yourself or use one of the predefined constants. For example: npm version patch to increment the patch part of your version number (this 0.0.X.0) and write that too your package.json version field.

Amazingly this will also set the tag in git for you.

Let’s try it out. I have "version": "1.0.0" in my package.json and no tags in git.

The git push heroku master will do quite a lot of things on the remote side; get dependencies, build and deploy. We don’t need to care about that here, just wait it out.

Launching the app

I’ve grown into the custom of always starting the application once it’s pushed to it’s environment, just to make sure it shows up. A little silly thing maybe, but it saved me from embarrassment a few times.

In my case, being on a OS X system, launching the application once it’s deployed is very easy:

open [url] # for example 'open http://koavote.herokuapp.com'

For Windows they tell me it’s start "http://koavote.herokuapp.com".

Putting it all together

Now we are ready to create our deployToProd script. And it will just be stitching things together.

You might have noticed that I’m using some kind of grouping with the push:git, compile:ts. I picked that up (among most everything I learned about npm scripting) from this post. I like the idea of grouping the task, but might switch to push_git that I think reads nicer.

Some quick notes on chaining tasks

Chaining tasks is very easy, you just use && between each task. If it get’s long and unwieldy we can always group scripts together (as we did in the refactoring part of the last post) and also use the pre/post-scripts to manage it.

This is the approach we will take below and it looks something like this:

"deploy":"npm run test && npm run version:patch && npm run deploy"

Another thing that might be useful is to send the output from one script execution into the next script. You might want to bundle your JavaScript files and then minify them, for browser based applications. That can be accomplished with the | (pipe) functionality. Like this example “stolen” from a great article here:

Oh, for the start command I've added a small web application, just to make sure it shows up. It's written using [koa](http://koajs.org) of course and hence I need the --harmony flag... Not on [iojs](www.pluralsight.com/courses/running-node-applications-io-js) but still on Node... :P

Summary

This means that I can go npm run deploy:prod and it will clean, test, version, push, deploy and launch my application. Just using npm and the package.json file.

There’s no external tools dependencies but everything is downloaded with npm install which makes 0 to deploying very fast.