Updating a Maintainable NPM Module with Continuous Integration

Continuous Integration and Deployment with Codeship

Continuous integration (CI) is one of those topics that might sound scary and complicated, and of course there are a gazillion aspects of it that could occupy you for years, but getting started doesn’t have to be a major undertaking.

The idea of CI is very coupled to using a code repository (usually git) as well as the idea that testing and building on every committed change and releasing often will help you identify problems early.

Quick introduction to git/CI-based workflows

A common setup with git and CI is to have a branch calleddevelop, which will automatically test/build any changes and deploy to a develop/staging environment (which is only for internal preview/testing), and a branch calledmaster, which will do the same for the production environment.

Each new feature is developed in its own branch. When that’s done, you make a request to merge it todevelop, writing a short description of what functionality your changes adds or what problems they solve. Someone will then read your description, check your code changes, and decide if this can safely be merged into thedevelopbranch and that it is up to the project’s standards.

Of course, if you are the only person working on a project, you are going to have to fill both these roles. I still think doing pull requests (sometimes called merge requests) is worth doing anyway; they give a very nice high-level overview of the changes that are made to a codebase over time.

When starting a project on my own, I often commit directly to themasterordevelopbranch until I have some kind of working proof of concept. Then, when it’s time to start making incremental improvements to the project, I switch to creating a new branch for every feature and making pull requests to myself.

To deploy to production, you then merge thedevelopbranch intomaster. How often this should happen is up for (much) debate.

Some say that every change todevelopshould kick off a series of automated tests on the staging environment, which should be as identical to the production environment as possible, and automatically deploy to production if they succeed. This idea is called continuous deployment.

Some think that continuous deployment is not always practical and that it is enough to automatically verify that every change to the staging environment could be deployed to production. This idea is called continuous delivery.

How does CI/CD apply to an NPM package?

These are the goals I defined for thehuman-date-rangemodule:

  • Make sure that every commit is tested with Jest and built with Rollup to verify that everything works.
  • Make sure that every commit to the project’smasterbranch also publishes successful builds to NPM.

This matches the workflow described above, where “deploy” has simply been translated to “publish a new version to NPM.” There is no “develop environment” here since there is only one NPM. To keep things simple, only commits tomasterwill result in a deploy.

There are ways to have different release “channels.” You can publish a dev version withnpm publish --tag dev, and anyone who doesnpm install human-date-rangewill still get the old stable version. People who like to live dangerously can runnpm install human-date-range@devto get your develop version.

!Sign up for a free Codeship Account hbspt.cta.load(1169977, ‘964db6a6-69da-4366-afea-b129019aff07’, {});

Publishing a New Version to NPM

Publishing new versions is done by changing theversioninpackage.jsonand then runningnpm publishagain. This can be done by runningnpm version, which has the advantage that it can “bump” your current version by one; eithernpm version patchto bump the last number (1.0.X), ornpm version minorto bump the middle number (1.X.0), ornpm version majorto bump the first number (X.0.0).

When run in a project with git, it will also create a version-tagged commit for you with the version change. So if you fix a bug in your module, the correct way to make a new release would be to run:

npm version patch
npm publish

Your module is well prepared for CI since testing, building, and publishing are all configured already.

The idea here is to let you control when to publish which version by letting you manually bump the appropriate version number and push all changes fromdeveloptomasterwhen you feel ready to publish a new version.

Because CI will also test and build every commit todevelopwhen it’s time to release, you can feel confident about the tests passing inmasteras well. That’s the theory, so let’s go ahead and set this up.