From 0143b133fedda386101ac070f7c4986b07f281c8 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 14 Sep 2015 16:54:27 -0700 Subject: [PATCH 1/4] Add railcar script --- script/railcar | 102 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100755 script/railcar diff --git a/script/railcar b/script/railcar new file mode 100755 index 000000000..e97360fe4 --- /dev/null +++ b/script/railcar @@ -0,0 +1,102 @@ +#!/usr/bin/env node + +var fs = require('fs') +var exec = require('child_process').exec +var async = require('../build/node_modules/async') + +var branchName, leadingBranchName + +async.series([ + parseArguments, + checkCleanWorkingTree, + checkoutBranch, + pullUpstreamChanges, + mergeLeadingBranch, + fetchUpstreamTags, + updateVersionNumber, + pushLocalChanges, + pushLocalTags, +], finish) + +function parseArguments(next) { + branchName = process.argv[2] + switch (branchName) { + case 'beta': + leadingBranchName = 'master' + break + case 'stable': + leadingBranchName = 'beta' + break + default: + return next(new Error('Usage: script/railcar ')) + } + next() +} + +function checkCleanWorkingTree(next) { + console.log('Checking for a clean working tree'); + exec('git status --porcelain', function(error, output) { + var modifiedEntries = output.split('\n').filter(function(line) { + return !/^\?\?/.test(line) && line.length > 0 + }); + + next( + modifiedEntries.length === 0 ? + null : + new Error('Cannot run the railcars with a dirty working tree') + ) + }) +} + +function checkoutBranch(next) { + console.log('Checking out ' + branchName); + exec('git checkout ' + branchName, next) +} + +function pullUpstreamChanges(next) { + console.log('Pulling upstream changes on ' + branchName); + exec('git pull --ff-only origin ' + branchName, next) +} + +function mergeLeadingBranch(next) { + console.log('Merging new changes from ' + leadingBranchName); + exec('git pull --ff-only origin ' + leadingBranchName, next) +} + +function fetchUpstreamTags(next) { + console.log('Fetching upstream tags'); + exec('git fetch --tags', next) +} + +function updateVersionNumber(next) { + var newVersion + if (branchName === 'beta') { + newVersion = require('../package.json') + .version + .replace(/-\w+$/, '-beta-0') + } else { + newVersion = 'patch' + } + + console.log('Updating version to ' + newVersion); + exec('npm version ' + newVersion, next) +} + +function pushLocalChanges(next) { + console.log('Pushing local changes'); + exec('git push origin ' + branchName, next) +} + +function pushLocalTags(next) { + console.log('Pushing local tags'); + exec('git push --tags origin', next) +} + +function finish(error) { + if (error) { + console.log('Error: ' + error.message) + process.exit(1) + } + + console.log('Success! Now just wait for all CI builds to pass on ' + branchName) +} From 01a73e3ad3a2bd71cd1baf8091829c1fbabb9950 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 14 Sep 2015 17:34:41 -0700 Subject: [PATCH 2/4] Handle errors from 'git status' --- script/railcar | 2 ++ 1 file changed, 2 insertions(+) diff --git a/script/railcar b/script/railcar index e97360fe4..151c84154 100755 --- a/script/railcar +++ b/script/railcar @@ -36,6 +36,8 @@ function parseArguments(next) { function checkCleanWorkingTree(next) { console.log('Checking for a clean working tree'); exec('git status --porcelain', function(error, output) { + if (error) return next(error) + var modifiedEntries = output.split('\n').filter(function(line) { return !/^\?\?/.test(line) && line.length > 0 }); From 6bfa467a154f3c1e33b3bd11932da74e1e31aa70 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 14 Sep 2015 17:34:47 -0700 Subject: [PATCH 3/4] Remove unused require --- script/railcar | 1 - 1 file changed, 1 deletion(-) diff --git a/script/railcar b/script/railcar index 151c84154..2d98d2c68 100755 --- a/script/railcar +++ b/script/railcar @@ -1,6 +1,5 @@ #!/usr/bin/env node -var fs = require('fs') var exec = require('child_process').exec var async = require('../build/node_modules/async') From a9845e3d7f2646a734864470b565bca686bc4c8a Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Tue, 15 Sep 2015 10:45:02 -0700 Subject: [PATCH 4/4] Script stable and beta releases together --- script/railcar | 146 ++++++++++++++++++++++--------------------------- 1 file changed, 66 insertions(+), 80 deletions(-) diff --git a/script/railcar b/script/railcar index 2d98d2c68..fa3fca2cb 100755 --- a/script/railcar +++ b/script/railcar @@ -1,103 +1,89 @@ #!/usr/bin/env node +var fs = require('fs') var exec = require('child_process').exec -var async = require('../build/node_modules/async') +var series = require('async').series +var semver = require('semver') -var branchName, leadingBranchName - -async.series([ - parseArguments, +series([ + section('Preparing to roll the railcars'), checkCleanWorkingTree, - checkoutBranch, - pullUpstreamChanges, - mergeLeadingBranch, - fetchUpstreamTags, - updateVersionNumber, - pushLocalChanges, - pushLocalTags, + run('git fetch origin master:master beta:beta stable:stable'), + run('git fetch origin --tags'), + + section('Updating stable branch'), + run('git checkout stable'), + run('git merge --ff-only origin/stable'), + run('git merge --ff-only origin/beta'), + bumpStableVersion, + + section('Updating beta branch'), + run('git checkout beta'), + run('git merge --ff-only origin/beta'), + run('git merge --ff-only origin/master'), + run('git merge --strategy ours origin/stable'), + bumpBetaVersion, + + section('Updating master branch'), + run('git checkout master'), + run('git merge --ff-only origin/master'), + run('git merge --strategy ours origin/beta'), + bumpDevVersion, + + section('Pushing changes upstream'), + run('git push origin master:master beta:beta stable:stable'), + run('git push origin --tags') ], finish) -function parseArguments(next) { - branchName = process.argv[2] - switch (branchName) { - case 'beta': - leadingBranchName = 'master' - break - case 'stable': - leadingBranchName = 'beta' - break - default: - return next(new Error('Usage: script/railcar ')) - } - next() -} - -function checkCleanWorkingTree(next) { - console.log('Checking for a clean working tree'); - exec('git status --porcelain', function(error, output) { +function checkCleanWorkingTree (next) { + run('git status --porcelain')(function (error, output) { if (error) return next(error) - - var modifiedEntries = output.split('\n').filter(function(line) { - return !/^\?\?/.test(line) && line.length > 0 - }); - - next( - modifiedEntries.length === 0 ? - null : - new Error('Cannot run the railcars with a dirty working tree') - ) + if (output.trim().length > 0) return next(new Error('Cannot run the railcars with a dirty working tree')) + next() }) } -function checkoutBranch(next) { - console.log('Checking out ' + branchName); - exec('git checkout ' + branchName, next) +function bumpStableVersion (next) { + run('npm version patch')(next) } -function pullUpstreamChanges(next) { - console.log('Pulling upstream changes on ' + branchName); - exec('git pull --ff-only origin ' + branchName, next) +function bumpBetaVersion (next) { + var newVersion = semver.inc(getCurrentVersion(), 'prerelease', 'beta') + run('npm version ' + newVersion)(next) } -function mergeLeadingBranch(next) { - console.log('Merging new changes from ' + leadingBranchName); - exec('git pull --ff-only origin ' + leadingBranchName, next) +function bumpDevVersion (next) { + var newVersion = semver.inc(getCurrentVersion(), 'preminor', 'dev') + series([ + run('npm --no-git-tag-version version ' + newVersion), + run('git commit -am "' + newVersion + '"') + ], next) } -function fetchUpstreamTags(next) { - console.log('Fetching upstream tags'); - exec('git fetch --tags', next) -} - -function updateVersionNumber(next) { - var newVersion - if (branchName === 'beta') { - newVersion = require('../package.json') - .version - .replace(/-\w+$/, '-beta-0') - } else { - newVersion = 'patch' - } - - console.log('Updating version to ' + newVersion); - exec('npm version ' + newVersion, next) -} - -function pushLocalChanges(next) { - console.log('Pushing local changes'); - exec('git push origin ' + branchName, next) -} - -function pushLocalTags(next) { - console.log('Pushing local tags'); - exec('git push --tags origin', next) -} - -function finish(error) { +function finish (error) { if (error) { console.log('Error: ' + error.message) process.exit(1) } - console.log('Success! Now just wait for all CI builds to pass on ' + branchName) + console.log('OK, now just wait for all CI builds to pass on beta and stable') +} + +function getCurrentVersion () { + return JSON.parse(fs.readFileSync(require.resolve('../package.json'))).version +} + +function run (command) { + return function (next) { + console.log('>', command) + exec(command, next) + } +} + +function section (message) { + return function (next) { + console.log() + console.log(message) + next() + } }