From 3cbc0d2440fd8b38432dc4526e96e73f351a6c6c Mon Sep 17 00:00:00 2001 From: Kieran Sedgwick Date: Wed, 14 May 2014 12:16:14 -0400 Subject: [PATCH] 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 :) --- .gitignore | 1 + .travis.yml | 2 + CONTRIBUTING.md | 30 +++++++++++ bower.json | 2 +- config/environment.js | 5 ++ env.sample | 14 +++++ gruntfile.js | 119 +++++++++++++++++++++++++++++++++++++++++- package.json | 26 ++++++--- 8 files changed, 191 insertions(+), 8 deletions(-) create mode 100644 config/environment.js create mode 100644 env.sample diff --git a/.gitignore b/.gitignore index c794f4b..3af4620 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ node_modules bower_components +.env *~ diff --git a/.travis.yml b/.travis.yml index 15e3620..789f9fb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,3 +5,5 @@ before_install: npm install -g grunt-cli notifications: email: false irc: "irc.mozilla.org#filer" +env: + - "FILER_UPSTREAM_URI=\"default\" FILER_UPSTREAM_BRANCH=\"default\" FILER_UPSTREAM_REMOTE_NAME=\"default\"" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 53e6bc8..97e4152 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -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 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 are writting using [Mocha](http://visionmedia.github.io/mocha/) and [Chai](http://chaijs.com/api/bdd/). diff --git a/bower.json b/bower.json index 24d9c70..56f37a5 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "filer", - "version": "0.0.4", + "version": "0.0.6", "main": "dist/filer.js", "devDependencies": { "mocha": "1.17.1", diff --git a/config/environment.js b/config/environment.js new file mode 100644 index 0000000..c4ab3e9 --- /dev/null +++ b/config/environment.js @@ -0,0 +1,5 @@ +module.exports = (function() { + var habitat = require('habitat'); + habitat.load(); + return new habitat(); +})(); diff --git a/env.sample b/env.sample new file mode 100644 index 0000000..00ffa33 --- /dev/null +++ b/env.sample @@ -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" diff --git a/gruntfile.js b/gruntfile.js index 4fd102e..beb6b3f 100644 --- a/gruntfile.js +++ b/gruntfile.js @@ -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) { // Project configuration. @@ -8,7 +19,7 @@ module.exports = function(grunt) { uglify: { options: { - banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n' + banner: '/*! <%= pkg.name %> <%= pkg.version %> <%= grunt.template.today("yyyy-mm-dd") %> */\n' }, develop: { src: 'dist/filer.js', @@ -20,6 +31,7 @@ module.exports = function(grunt) { // Don't bother with src/path.js all: [ 'gruntfile.js', + 'config/environment.js', 'src/constants.js', 'src/errors.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-mocha'); 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('release', ['develop', 'uglify']); grunt.registerTask('check', ['jshint']); 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']); }; diff --git a/package.json b/package.json index 7a5fbde..324abd5 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,16 @@ { "name": "filer", "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", "author": "Alan K (http://blog.modeswitch.org)", "homepage": "http://js-platform.github.io/filer", @@ -20,15 +29,20 @@ }, "devDependencies": { "grunt": "~0.4.0", + "grunt-bump": "0.0.13", "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-uglify": "~0.1.2", "grunt-contrib-watch": "~0.3.1", - "grunt-contrib-compress": "~0.4.1", - "grunt-contrib-connect": "~0.1.2", - "grunt-contrib-concat": "~0.1.3", - "grunt-contrib-jshint": "~0.7.1", + "grunt-git": "0.2.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" } }