Package detail

rf-release

rpflorence42MIT0.4.0

tag, push, and publish to npm and bower

release

readme

rf-release

Tag, push, changelog, and publish your repositories with one command.

Installation

npm install rf-release
# or
npm install rf-release -g

Usage

BEFORE YOUR FIRST RUN

There are a couple gotchas I haven't spent time to smooth over. Before your first run:

  1. Ensure you have a semver style git tag in the past, otherwise the changelog script will fail.

    git checkout <some old commit>
    git tag v0.0.0
    git checkout master
    
  2. Make sure you've committed a blank CHANGELOG.md to git. The code that creates the release commit uses git commit -am so if CHANGELOG.md is a new file, it won't be included in the commit.

     touch CHANGELOG.md
     git add CHANGELOG.md
     git commit -m 'added changelog because ryan is lazy'
    

Okay, now you're ready:

# if `node_modules/.bin` is in your path
# or you installed globally:
$ release

# otherwise
$ node_modules/.bin/release

What it does

  1. prompts you for the new version
  2. updates package.json and bower.json (if they exist)
  3. commits the version updates with a simple commit message ("release {version}")
  4. creates the tag "v{version}"
  5. generates a changelog with rf-changelog
  6. pushes master and the new tag to origin
  7. publishes to npm

But I have a build step before I can tag and publish!

That's fine, just do your build first w/o committing, then run release. It'll all go in the same commit. For example, react-router's release script does this.

License and Copyright

MIT License

(c) 2014 Ryan Florence

changelog

!/usr/bin/env node

var prompt = require('prompt'); var fs = require('fs'); var exec = require('child_process').exec; var color = require('cli-color'); var cyan = color.cyan; var yellow = color.yellow; var changelog = require('rf-changelog');

var schema = { properties: { version: { description: 'version? (old is '+version()+')', pattern: /^[0-9].[0-9]+.0-9?/, message: 'Must be a valid semver string i.e. 1.0.2, 2.3.0-beta.1', required: true } } };

prompt.start();

prompt.get(schema, function(err, result) { var rawVersion = result.version; var version = 'v'+rawVersion; updateJSON('package', rawVersion); updateJSON('bower', rawVersion); ex('npm test', function() { changelog('-t '+version, function() { commit(version, function() { tag(version, function() { publish(version); }); }); }); }); });

function commit(version, cb) { ex('git commit -am "release '+version+'"', cb); }

function tag(version, cb) { ex('git tag '+version, function() { ex('git tag latest -f', cb); }); }

function publish(version) { ex('git push origin master', function() { ex('git push origin '+version, function() { ex('npm publish'); }); }); }

function ex(command, cb) { log(cyan('exec:'), yellow(command)); exec(command, execHandler(cb)); }

function execHandler(cb) { return function(err, stdout, stderr) { if (err) throw new Error(err); console.log(stdout); console.log(stderr); if (cb) cb(); } }

function updateJSON(pkg, version) { var path = pkg+'.json'; if (!fs.existsSync(path)) { return; } var json = readJSON(path); json.version = version; writeJSON(path, json); log(cyan('updated'), path); }

function version() { return readJSON('./package.json').version; }

function readJSON(path) { return JSON.parse(fs.readFileSync(path).toString()); }

function writeJSON(path, data) { fs.writeFileSync(path, JSON.stringify(data, null, 2)); }

function log() { var args = [].slice.call(arguments, 0); console.log.apply(console, [cyan('release:')].concat(args)); }