npm install from GitHub in specific environment

My team uses a private npm registry. We install packages from this private registry when developing locally and when deploying to production. When deploying to staging, however, we'd like to pull from GitHub instead. I thought this would be possible using a preinstall script which rewrites package.json to use the appropriate git+ssh:// URLs in place of the version numbers if NODE_ENV=staging.

This appears not to work, possibly because npm ignores the changes made to package.json (having already required it).

Perhaps I'm going about this in completely the wrong way. What is the recommended way of achieving this?

You could try running npm-install, which will resolve and install all of your dependencies, then npm-shrinkwrap, which will generate the file npm-shrinkwrap.json.

You can run your pre-install script on npm-shrinkwrap.json and insert 'git+ssh://' URL's as needed, which already has all of the resolved dependencies you need. This should give you a shrink-wrapped package.json file which points to your github repositories.

Check out https://www.npmjs.org/doc/cli/npm-shrinkwrap.html#Building-shrinkwrapped-packages for more info on shrink-wrapping.

For private repository you have to put it under dependencies.

{
    "private": true
    "name": "foo",
    "dependencies": {
        "private-repo": "git+ssh://gitolite@my.server:my/project",
    }
    [...]
}

You can use two different package.json files, one for staging and one for development and production. These files can be stored on the corresponding SCM branches.

You can specify dependencies for npm in many ways.

Git URL

{
  "dependencies": {
    "private_dependency": git://user@hostname:project.git#ref
  }
}

Simply supply the URL to the dependency. #ref is a git reference. If you omit this it will default to master.

GitHub URL

{
  "dependencies": {
    "private_dependency": user/project
  }
}

Tarball URL

{
  "dependencies": {
    "private_dependency": example.com/tarball.tar.gz
  }
}

For more information about supported formats see here.

Having a setup similar to yours, we are using roco to run various tasks such as old-tags-cleanup, test-run, etc. If configured properly, it will come down to roco staging deploy and roco production deploy :)