source: Dev/trunk/Gruntfile.js @ 534

Last change on this file since 534 was 533, checked in by hendrikvanantwerpen, 10 years ago

Add watch command to ease client development.

File size: 12.2 KB
RevLine 
[464]1/** Gruntfile - control build and deploy tasks
[453]2 */
[443]3
[469]4var _ = require('underscore');
5
[443]6module.exports = function(grunt) {
7
[469]8    // TASKS
9
[517]10    // default task
[469]11    grunt.registerTask('default', ['compile']);
[517]12    // development
[518]13    grunt.registerTask('compile',
14                       "Lint all sources and compile Coffee and LESS sources.",
15                       ['path-check:svn'
16                       ,'svn-ignore:compile'
17                       ,'jshint:lint-sources'
18                       ,'htmlhint:lint'
19                       ,'coffeelint:lint'
20                       ,'jsonlint:lint'
21                     //,'tv4:lint'
22                       ,'less:compile'
23                       ,'usebanner:generated-css'
24                       ,'coffee:compile'
25                       ,'usebanner:generated-js'
26                       ,'jshint:lint-generated'
27                     //,'amd-check' // too smart about plugins, r.js can't find them
28                       ]);
[533]29    grunt.registerTask('watch-client',
30                       "Watch client source and recompile when things change.",
31                       ['watch:client']);
[518]32    grunt.registerTask('run',
33                       "Compile and start the server locally with foreman.",
34                       ['path-check:foreman'
35                       ,'compile'
[522]36                       ,'foreman:run-src']);
[518]37    grunt.registerTask('build',
38                       "Compile and make a Dojo build of the client (compress sources).",
39                       ['compile'
40                       ,'clean:build'
41                       ,'copy:build'
42                       ,'dojo:build'
43                       ]);
44    grunt.registerTask('run-build',
45                       "Make a build and start server from build locally with foreman.",
46                       ['path-check:foreman'
47                       ,'build'
[522]48                       ,'foreman:run-build']);
[518]49    grunt.registerTask('deploy',
50                       "Make a build and deploy it to Heroku.",
51                       ['path-check:svn'
52                       ,'path-check:git'
53                       ,'svninfo'
54                       ,'build'
[522]55                       ,'git_deploy:deploy-build']);
56    grunt.registerTask('deploy-src',
57                       "Deploy sources to Heroku (FOR DEBUGGING ONLY).",
58                       ['path-check:svn'
59                       ,'path-check:git'
60                       ,'svninfo'
61                       ,'compile'
62                       ,'git_deploy:deploy-src']);
[517]63    // database management
64    grunt.registerTask('db-backup-cloud-to-dated-local',
[518]65                       "Backup the Heroku database to a timestamped local database.",
[517]66                       ['path-check:heroku'
67                       ,'heroku-config'
68                       ,'http:db-backup-cloud-to-dated-local']);
69    grunt.registerTask('db-pull-cloud-to-local',
[518]70                       "Synchronize local database with the Heroku database (pull changes).",
[517]71                       ['path-check:heroku'
72                       ,'heroku-config'
73                       ,'http:db-pull-cloud-to-local']);
74    grunt.registerTask('db-push-local-to-cloud',
[518]75                       "Synchronize the Heroku database with the local database (push changes).",
[517]76                       ['path-check:heroku'
77                       ,'heroku-config'
78                       ,'http:db-push-local-to-cloud']);
[531]79    grunt.registerTask('cloudant-url',
80                       "Print the Cloudant URL to the console.",
81                       ['path-check:heroku'
82                       ,'heroku-config'
83                       ,'print:herokuConfig.CLOUDANT_URL:CLOUDANT_URL'
84                       ]);
[518]85    grunt.registerTask('#',
86                       "---\nTASKS BELOW ARE INTERNAL AND SHOULD NOT USUALLY BE CALLED FROM THE COMMAND-LINE\n---",
87                       []);
[469]88
89    // FILES AND FOLDERS
90   
[464]91    var srcDir   = 'src/';
[463]92    var buildDir = 'build/';
[469]93    var coffeeMap = grunt.file.expandMapping(
94        [ 'client/qed-client/**/*.coffee', 'server/**/*.coffee' ],
95        srcDir,
96        { cwd: srcDir, ext: '.js' });
97    var lessMap = grunt.file.expandMapping(
98        [ 'client/qed-client/css/qed.less' ],
99        srcDir,
100        { cwd: srcDir, ext: '.css' });
[453]101
[519]102    var mode = process.env.QED_ENV || 'dev';
103    var dbNames = {
104        dev: 'qed-dev',
105        production: 'qed'
106    };
107    if ( !( mode in dbNames ) ) {
108        throw new Error("Unknown mode "+mode+" specified.");
109    }
110
[469]111    // TASK CONFIG
[517]112
[443]113    grunt.initConfig({
[517]114        localDbURL: "http://localhost:5984",
[519]115        dbName: dbNames[mode],
[517]116        timestamp: "<%= grunt.template.today(\"UTC:yyyymmdd't'HHMMss'z'\") %>",
117
[469]118        'amd-check': {
119            files: [ srcDir+'client/qed-client/**/*.js' ]
120        },
[458]121        clean: {
[469]122            build: { src: [buildDir] }
[458]123        },
[463]124        coffee: {
[469]125            options: { bare: true },
126            compile: { files: coffeeMap }
[453]127        },
[466]128        coffeelint: {
[469]129            lint: { options: require('./'+srcDir+'.coffeelint.json'),
130                    files: coffeeMap }
[466]131        },
[463]132        copy: {
[469]133            build: { files: [{ expand: true,
134                               cwd: srcDir,
135                               src: ['**', '!client/*/**' ],
136                               dest: buildDir }]}
[458]137        },
[453]138        dojo: {
[469]139            build: { options: { dojo: srcDir+'client/dojo/dojo.js',
140                                profile: srcDir+'client/client.profile.js',
[471]141                                releaseDir: '../../'+buildDir }}
[453]142        },
[517]143        foreman: {
[522]144            'run-src': {
[517]145                options: {
146                    cwd: srcDir
147                }
148            },
[522]149            'run-build': {
[517]150                options: {
151                    cwd: buildDir
152                }
153            }
154        },
[516]155        git_deploy: {
[522]156            'deploy-build': {
[516]157                options: {
158                    url: 'git@heroku.com:quod-erat.git',
159                    branch: 'master',
[522]160                    message: "Build deployment of revision <%= svninfo.rev %> on <%= grunt.template.today() %>."
[516]161                },
162                src: buildDir
[522]163            },
164           
165            'deploy-src': {
166                options: {
167                    url: 'git@heroku.com:quod-erat.git',
168                    branch: 'master',
169                    message: "Source deployment of revision <%= svninfo.rev %> on <%= grunt.template.today() %>."
170                },
171                src: srcDir
[516]172            }
173        },
[517]174        'heroku-config': {
175            options: {
176                app: 'quod-erat',
177                keys: ['CLOUDANT_URL']
178            }
179        },
[453]180        htmlhint: {
[469]181            options: { htmlhintrc: srcDir+".htmlhintrc" },
182            lint: { files: [{ expand: true,
183                              cwd: srcDir,
184                              src: ['client/*.html', 'client/qed-client/**/*.html'] }]}
[443]185        },
[517]186        http: {
187            'db-backup-cloud-to-dated-local': {
188                options: {
189                    url: "<%= localDbURL %>/_replicate",
190                    method: 'POST',
191                    body: {
[519]192                        source: "<%= herokuConfig.CLOUDANT_URL %>/<%= dbName %>",
193                        target: "<%= dbName %>-<%= timestamp %>",
[517]194                        create_target: true
195                    },
196                    json: true
197                }
198            },
199            'db-pull-cloud-to-local': {
200                options: {
201                    url: "<%= localDbURL %>/_replicate",
202                    method: 'POST',
203                    body: {
[519]204                        source: "<%= herokuConfig.CLOUDANT_URL %>/<%= dbName %>",
[520]205                        target: "<%= dbName %>",
206                        create_target: true
[517]207                    },
208                    json: true
209                }
210            },
211            'db-push-local-to-cloud': {
212                options: {
213                    url: "<%= localDbURL %>/_replicate",
214                    method: 'POST',
215                    body: {
[519]216                        source: "<%= dbName %>",
[520]217                        target: "<%= herokuConfig.CLOUDANT_URL %>/<%= dbName %>",
218                        create_target: true
[517]219                    },
220                    json: true
221                }
222            }
223        },
[443]224        jshint: {
[469]225            'lint-sources': { options: { jshintrc: srcDir+".jshintrc" },
[505]226                              files: { src: [ srcDir+'client/qed-client/**/*.js', srcDir+'server/**/*.js' ].concat(exclude(dest(coffeeMap))) } },
[469]227            'lint-generated': { options: { jshintrc: srcDir+".jshintrc-generated" },
[505]228                                files: { src: dest(coffeeMap) } }
[443]229        },
[505]230        jsonlint: {
[516]231            'lint': { files: { src: [ srcDir+'client/qed-client/**/*.json', srcDir+'server/**/*.json' ] } }
[505]232        },
[453]233        less: {
[469]234            options: { strictImports: false,
235                       dumpLineNumbers: "all" },
236            compile: { files: lessMap }
237        },
[516]238        'path-check': {
[517]239            'heroku': {
240                src: ['heroku']
241            },
242            'foreman': {
243                src: ['foreman']
244            },
245            'svn': {
246                src: ['svn']
247            },
248            'git': {
249                src: ['git']
[516]250            }
251        },
[469]252        requirejs: {
253            basePath: srcDir+'client/',
254            packages: [
255                { name: "dojo", location: "dojo" },
256                { name: "dijit", location: "dijit" },
257                { name: "dojox", location: "dojox" },
258                { name: "qed-client", location: "qed-client" }
259            ]
260        },
[474]261        'svn-ignore': {
262            compile: {
263                files: { src: dest(coffeeMap).concat(dest(lessMap)) }
264            }
265        },
266        'svn-ignore-clean': {
267            clean: {
268                files: [{
269                    expand: true,
270                    cwd: srcDir,
271                    src: ['**', '!node_modules/**', '!client/dojo/**', '!client/dijit/**', '!client/dojox/**', '!client/util/**'],
272                    filter: 'isDirectory'
273                }]
274            }
275        },
[487]276        tv4: {
277            lint: {
278                options: {
279                    root: grunt.file.readJSON('json-schema-draft-04.json'),
280                    multi: true
281                },
282                src: [srcDir+'server/config/couchdb-schema.json']
283            }
284        },
[469]285        usebanner: {
286            'generated-css': { options: { position: 'top',
287                                          banner: '/* This CSS file is generated. All edits will be lost on recompile. */'},
288                               files: { src: dest(lessMap) }},
289            'generated-js': { options: { position: 'top',
290                                         banner: '/* This JS file is generated, All edits will be lost on recompile. */'},
291                               files: { src: dest(coffeeMap) }}
[533]292        },
293        watch: {
294            client: {
295                files: [ srcDir+'client/qed-client/**' ],
296                tasks: [ 'compile' ]
297            }
[443]298        }
299    });
300
[469]301    // LOAD TASKS
302
303    grunt.loadNpmTasks('grunt-amd-check');
304    grunt.loadNpmTasks('grunt-banner');
[466]305    grunt.loadNpmTasks('grunt-coffeelint');
[458]306    grunt.loadNpmTasks('grunt-contrib-clean');
[463]307    grunt.loadNpmTasks('grunt-contrib-coffee');
[453]308    grunt.loadNpmTasks('grunt-contrib-copy');
309    grunt.loadNpmTasks('grunt-contrib-jshint');
[443]310    grunt.loadNpmTasks('grunt-contrib-less');
[533]311    grunt.loadNpmTasks('grunt-contrib-watch');
[453]312    grunt.loadNpmTasks('grunt-dojo');
[516]313    grunt.loadNpmTasks('grunt-git-deploy');
[443]314    grunt.loadNpmTasks('grunt-htmlhint');
[517]315    grunt.loadNpmTasks('grunt-http');
[505]316    grunt.loadNpmTasks('grunt-jsonlint');
[516]317    grunt.loadNpmTasks('grunt-path-check');
318    grunt.loadNpmTasks('grunt-svninfo');
[487]319    grunt.loadNpmTasks('grunt-tv4');
[469]320    grunt.loadTasks('./grunt-tasks');
[443]321
[531]322    grunt.registerTask('print',"Print a variable.",
323                       function(varname,name) {
324                            grunt.log.write(grunt.template.process((name||varname)+"=<%= "+varname+" %>"));
325                       });
326
[469]327    // UTIL FUNCTIONS
[464]328
[469]329    function dest(files) {
330        return _.chain(files)
331            .map(function(item){ return item.dest; })
332            .flatten()
333            .value();
334    }
[464]335
[469]336    function exclude(dest) {
337        return _.map(dest, function(dest){ return '!'+dest; });
338    }
339   
[443]340};
Note: See TracBrowser for help on using the repository browser.