Grunt automation of build/tag/publish

Filer's build process was a multi-step process, and grunt is powerful enough to automate it. Now we have :)
This commit is contained in:
Kieran Sedgwick 2014-05-14 12:16:14 -04:00
parent 14c584ab8e
commit 3cbc0d2440
8 changed files with 191 additions and 8 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
node_modules node_modules
bower_components bower_components
.env
*~ *~

View File

@ -5,3 +5,5 @@ before_install: npm install -g grunt-cli
notifications: notifications:
email: false email: false
irc: "irc.mozilla.org#filer" irc: "irc.mozilla.org#filer"
env:
- "FILER_UPSTREAM_URI=\"default\" FILER_UPSTREAM_BRANCH=\"default\" FILER_UPSTREAM_REMOTE_NAME=\"default\""

View File

@ -28,6 +28,36 @@ make a pull request. If you're patch includes code, make sure to check that all
unit tests pass, including any new tests you wrote. Finally, make sure you add yourself unit tests pass, including any new tests you wrote. Finally, make sure you add yourself
to the `AUTHORS` file. to the `AUTHORS` file.
<<<<<<< HEAD
=======
### Releasing a new version
`grunt publish` will:
* Run the `grunt release` task
* Bump `bower.json` & `package.json` version numbers according to a [Semver](http://semver.org/) compatible scheme (see "How to Publish" below)
* Create a git tag at the new version number
* Create a release commit including `dist/filer.js`, `dist/filer.min.js`, `bower.json` and `package.json`
* Push tag & commit to `origin/develop`
* Update the `gh-pages` branch with the contents of the `develop` branch
* Force push the `gh-pages` branch to `origin/gh-pages`
* Publish the new version of the module to NPM
#### How to configure
1. Copy `env.sample` to `.env`
2. Modify as needed, or leave alone for defaults
#### How to Publish
`grunt publish` can be run in four ways:
1. `grunt publish` - does a patch (x.x.X) bump
2. `grunt publish:patch` - also does a patch (x.x.X) bump
3. `grunt publish:minor` - does a minor (x.X.x) bump
4. `grunt publish:major` - does a major (X.x.x) bump
The user *must* be on their local `develop` branch before running any form of `grunt publish`, or else the task will fail loudly.
>>>>>>> 13e682b... Updated tag/commit messages
## Tests ## Tests
Tests are writting using [Mocha](http://visionmedia.github.io/mocha/) and [Chai](http://chaijs.com/api/bdd/). Tests are writting using [Mocha](http://visionmedia.github.io/mocha/) and [Chai](http://chaijs.com/api/bdd/).

View File

@ -1,6 +1,6 @@
{ {
"name": "filer", "name": "filer",
"version": "0.0.4", "version": "0.0.6",
"main": "dist/filer.js", "main": "dist/filer.js",
"devDependencies": { "devDependencies": {
"mocha": "1.17.1", "mocha": "1.17.1",

5
config/environment.js Normal file
View File

@ -0,0 +1,5 @@
module.exports = (function() {
var habitat = require('habitat');
habitat.load();
return new habitat();
})();

14
env.sample Normal file
View File

@ -0,0 +1,14 @@
###
# Dev ENVIRONMENT file
#
# Copy to .env to use defaults
###
# GIT (upstream) url to publish to
export FILER_UPSTREAM_URI="git@github.com:js-platform/filer.git"
# GIT (upstream) branch to publish to
export FILER_UPSTREAM_BRANCH="develop"
# Remote name for upstream repo
export FILER_UPSTREAM_REMOTE_NAME="origin"

View File

@ -1,3 +1,14 @@
var semver = require('semver'),
fs = require('fs'),
currentVersion = JSON.parse(fs.readFileSync('./package.json', 'utf8')).version,
env = require('./config/environment');
// Globals
var PROMPT_CONFIRM_CONFIG = 'confirmation',
GIT_BRANCH = env.get('FILER_UPSTREAM_BRANCH'),
GIT_REMOTE = env.get('FILER_UPSTREAM_REMOTE_NAME'),
GIT_FULL_REMOTE = env.get('FILER_UPSTREAM_URI') + ' ' + GIT_BRANCH;
module.exports = function(grunt) { module.exports = function(grunt) {
// Project configuration. // Project configuration.
@ -8,7 +19,7 @@ module.exports = function(grunt) {
uglify: { uglify: {
options: { options: {
banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n' banner: '/*! <%= pkg.name %> <%= pkg.version %> <%= grunt.template.today("yyyy-mm-dd") %> */\n'
}, },
develop: { develop: {
src: 'dist/filer.js', src: 'dist/filer.js',
@ -20,6 +31,7 @@ module.exports = function(grunt) {
// Don't bother with src/path.js // Don't bother with src/path.js
all: [ all: [
'gruntfile.js', 'gruntfile.js',
'config/environment.js',
'src/constants.js', 'src/constants.js',
'src/errors.js', 'src/errors.js',
'src/fs.js', 'src/fs.js',
@ -83,6 +95,77 @@ module.exports = function(grunt) {
} }
} }
} }
},
bump: {
options: {
files: ['package.json', 'bower.json'],
commit: true,
commitMessage: 'v%VERSION%',
commitFiles: ['package.json', 'bower.json', './dist/filer.js', './dist/filer.min.js'],
createTag: true,
tagName: 'v%VERSION%',
tagMessage: 'v%VERSION%',
push: true,
pushTo: GIT_FULL_REMOTE
}
},
'npm-checkBranch': {
options: {
branch: GIT_BRANCH
}
},
'npm-publish': {
options: {
abortIfDirty: true
}
},
prompt: {
confirm: {
options: {
questions: [
{
config: PROMPT_CONFIRM_CONFIG,
type: 'confirm',
message: 'Bump version from ' + (currentVersion).cyan +
' to ' + semver.inc(currentVersion, "patch").yellow + '?',
default: false
}
],
then: function(results) {
if (!results[PROMPT_CONFIRM_CONFIG]) {
return grunt.fatal('User aborted...');
}
}
}
}
},
gitcheckout: {
publish: {
options: {
branch: 'gh-pages',
overwrite: true
}
},
revert: {
options: {
branch: GIT_BRANCH
}
}
},
gitpush: {
publish: {
options: {
remote: GIT_REMOTE,
branch: 'gh-pages',
force: true
}
}
} }
}); });
@ -92,11 +175,45 @@ module.exports = function(grunt) {
grunt.loadNpmTasks('grunt-contrib-jshint'); grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-mocha'); grunt.loadNpmTasks('grunt-mocha');
grunt.loadNpmTasks('grunt-contrib-connect'); grunt.loadNpmTasks('grunt-contrib-connect');
grunt.loadNpmTasks('grunt-bump');
grunt.loadNpmTasks('grunt-npm');
grunt.loadNpmTasks('grunt-git');
grunt.loadNpmTasks('grunt-prompt');
grunt.registerTask('develop', ['clean', 'requirejs']); grunt.registerTask('develop', ['clean', 'requirejs']);
grunt.registerTask('release', ['develop', 'uglify']); grunt.registerTask('release', ['develop', 'uglify']);
grunt.registerTask('check', ['jshint']); grunt.registerTask('check', ['jshint']);
grunt.registerTask('test', ['check', 'connect', 'mocha']); grunt.registerTask('test', ['check', 'connect', 'mocha']);
grunt.registerTask('publish', 'Publish filer as a new version to NPM, bower and github.', function(patchLevel) {
var allLevels = ['patch', 'minor', 'major'];
// No level specified defaults to 'patch'
patchLevel = (patchLevel || 'patch').toLowerCase();
// Fail out if the patch level isn't recognized
if (allLevels.filter(function(el) { return el == patchLevel; }).length === 0) {
return grunt.fatal('Patch level not recognized! "Patch", "minor" or "major" only.');
}
// Set prompt message
var promptOpts = grunt.config('prompt.confirm.options');
promptOpts.questions[0].message = 'Bump version from ' + (currentVersion).cyan +
' to ' + semver.inc(currentVersion, patchLevel).yellow + '?';
grunt.config('prompt.confirm.options', promptOpts);
// TODO: ADD NPM RELEASE
grunt.task.run([
'prompt:confirm',
'checkBranch',
'release',
'bump:' + patchLevel,
'gitcheckout:publish',
'gitpush:publish',
'gitcheckout:revert',
'npm-publish'
]);
});
grunt.registerTask('default', ['develop']); grunt.registerTask('default', ['develop']);
}; };

View File

@ -1,7 +1,16 @@
{ {
"name": "filer", "name": "filer",
"description": "Node-like file system for browsers", "description": "Node-like file system for browsers",
"keywords": ["fs", "node", "file", "system", "browser", "indexeddb", "idb", "websql"], "keywords": [
"fs",
"node",
"file",
"system",
"browser",
"indexeddb",
"idb",
"websql"
],
"version": "0.0.6", "version": "0.0.6",
"author": "Alan K <ack@modeswitch.org> (http://blog.modeswitch.org)", "author": "Alan K <ack@modeswitch.org> (http://blog.modeswitch.org)",
"homepage": "http://js-platform.github.io/filer", "homepage": "http://js-platform.github.io/filer",
@ -20,15 +29,20 @@
}, },
"devDependencies": { "devDependencies": {
"grunt": "~0.4.0", "grunt": "~0.4.0",
"grunt-bump": "0.0.13",
"grunt-contrib-clean": "~0.4.0", "grunt-contrib-clean": "~0.4.0",
"grunt-contrib-compress": "~0.4.1",
"grunt-contrib-concat": "~0.1.3",
"grunt-contrib-connect": "~0.7.1",
"grunt-contrib-jshint": "~0.7.1",
"grunt-contrib-requirejs": "~0.4.0", "grunt-contrib-requirejs": "~0.4.0",
"grunt-contrib-uglify": "~0.1.2", "grunt-contrib-uglify": "~0.1.2",
"grunt-contrib-watch": "~0.3.1", "grunt-contrib-watch": "~0.3.1",
"grunt-contrib-compress": "~0.4.1", "grunt-git": "0.2.10",
"grunt-contrib-connect": "~0.1.2",
"grunt-contrib-concat": "~0.1.3",
"grunt-contrib-jshint": "~0.7.1",
"grunt-mocha": "0.4.10", "grunt-mocha": "0.4.10",
"grunt-contrib-connect": "~0.7.1" "grunt-npm": "git://github.com/sedge/grunt-npm.git#branchcheck",
"grunt-prompt": "^1.1.0",
"habitat": "^1.1.0",
"semver": "^2.3.0"
} }
} }