2014-05-03 17:34:41 +04:00
// # Task automation for Ghost
//
// Run various tasks when developing for and working with Ghost.
//
// **Usage instructions:** can be found in the [Custom Tasks](#custom%20tasks) section or by running `grunt --help`.
//
// **Debug tip:** If you have any problems with any Grunt tasks, try running them with the `--verbose` command
2016-09-14 13:22:16 +03:00
2017-11-01 16:44:54 +03:00
require ( './core/server/overrides' ) ;
2017-12-11 21:14:05 +03:00
var config = require ( './core/server/config' ) ,
urlService = require ( './core/server/services/url' ) ,
_ = require ( 'lodash' ) ,
chalk = require ( 'chalk' ) ,
fs = require ( 'fs-extra' ) ,
KnexMigrator = require ( 'knex-migrator' ) ,
2017-03-09 22:38:20 +03:00
knexMigrator = new KnexMigrator ( {
knexMigratorFilePath : config . get ( 'paths:appRoot' )
} ) ,
2017-12-11 21:14:05 +03:00
path = require ( 'path' ) ,
2014-08-02 19:21:38 +04:00
2017-12-11 21:14:05 +03:00
escapeChar = process . platform . match ( /^win/ ) ? '^' : '\\' ,
cwd = process . cwd ( ) . replace ( /( |\(|\))/g , escapeChar + '$1' ) ,
2014-08-07 02:17:14 +04:00
buildDirectory = path . resolve ( cwd , '.build' ) ,
2017-12-11 21:14:05 +03:00
distDirectory = path . resolve ( cwd , '.dist' ) ,
2013-09-13 11:24:28 +04:00
2018-04-30 22:16:24 +03:00
hasBuiltClient = false ,
logBuildingClient = function ( grunt ) {
if ( ! hasBuiltClient ) {
grunt . log . writeln ( 'Building admin client... (can take ~1min)' ) ;
setTimeout ( logBuildingClient , 5000 , grunt ) ;
}
} ,
2013-12-06 14:24:25 +04:00
// ## Grunt configuration
2013-06-25 15:43:15 +04:00
configureGrunt = function ( grunt ) {
2014-05-03 17:34:41 +04:00
// #### Load all grunt tasks
//
// Find all of the task which start with `grunt-` and load them, rather than explicitly declaring them all
2014-02-19 07:41:21 +04:00
require ( 'matchdep' ) . filterDev ( [ 'grunt-*' , '!grunt-cli' ] ) . forEach ( grunt . loadNpmTasks ) ;
2013-08-17 22:39:02 +04:00
2013-06-25 15:43:15 +04:00
var cfg = {
2014-05-03 17:34:41 +04:00
// #### Common paths used by tasks
2013-06-25 15:43:15 +04:00
paths : {
build : buildDirectory ,
2013-11-01 19:33:49 +04:00
releaseBuild : path . join ( buildDirectory , 'release' ) ,
2013-06-25 15:43:15 +04:00
dist : distDirectory ,
2013-10-11 19:31:47 +04:00
releaseDist : path . join ( distDirectory , 'release' )
2013-06-25 15:43:15 +04:00
} ,
2014-05-03 17:34:41 +04:00
// Standard build type, for when we have nightlies again.
2013-07-11 18:24:33 +04:00
buildType : 'Build' ,
2014-05-03 17:34:41 +04:00
// Load package.json so that we can create correctly versioned releases.
2013-06-25 15:43:15 +04:00
pkg : grunt . file . readJSON ( 'package.json' ) ,
2016-07-20 13:39:40 +03:00
clientFiles : [
2017-12-06 19:37:54 +03:00
'server/web/admin/views/default.html' ,
2016-07-20 13:39:40 +03:00
'built/assets/ghost.js' ,
'built/assets/ghost.css' ,
'built/assets/vendor.js' ,
'built/assets/vendor.css'
] ,
2014-05-03 17:34:41 +04:00
// ### grunt-contrib-watch
// Watch files and livereload in the browser during development.
// See the [grunt dev](#live%20reload) task for how this is used.
2013-08-17 22:39:02 +04:00
watch : {
livereload : {
files : [
2014-08-06 04:26:42 +04:00
'content/themes/casper/assets/css/*.css' ,
2017-03-30 16:51:22 +03:00
'content/themes/casper/assets/js/*.js'
2013-08-17 22:39:02 +04:00
] ,
options : {
livereload : true
}
} ,
express : {
2017-11-01 16:44:54 +03:00
files : [ 'core/ghost-server.js' , 'core/server/**/*.js' , 'config.*.json' , '!config.testing.json' ] ,
tasks : [ 'express:dev' ] ,
2013-08-17 22:39:02 +04:00
options : {
2017-03-14 16:51:32 +03:00
nospawn : true ,
livereload : true
2013-08-17 22:39:02 +04:00
}
}
} ,
2014-05-03 17:34:41 +04:00
// ### grunt-express-server
2017-08-15 14:29:27 +03:00
// Start a Ghost express server for use in development and testing
2013-08-17 22:39:02 +04:00
express : {
options : {
2013-12-05 00:20:16 +04:00
script : 'index.js' ,
output : 'Ghost is running'
2013-08-17 22:39:02 +04:00
} ,
dev : {
2014-05-03 17:34:41 +04:00
options : { }
2013-08-29 14:04:33 +04:00
} ,
test : {
options : {
node _env : 'testing'
}
2013-08-17 22:39:02 +04:00
}
} ,
2017-11-01 16:44:54 +03:00
// ### grunt-eslint
2014-05-03 17:34:41 +04:00
// Linting rules, run as part of `grunt validate`. See [grunt validate](#validate) and its subtasks for
// more information.
2017-11-01 16:44:54 +03:00
eslint : {
2015-02-19 02:47:55 +03:00
server : {
2017-11-01 16:44:54 +03:00
options : {
config : '.eslintrc.json'
} ,
src : [
'*.js' ,
'core/*.js' ,
'core/server/*.js' ,
'core/server/**/*.js' ,
'!core/server/public/**/*.js'
]
} ,
test : {
options : {
config : './core/test/.eslintrc.json'
} ,
src : [
'core/test/*.js' ,
'core/test/**/*.js' ,
'!core/test/coverage/**'
]
2015-02-19 02:47:55 +03:00
}
} ,
2013-06-25 15:43:15 +04:00
2014-05-03 17:34:41 +04:00
// ### grunt-mocha-cli
// Configuration for the mocha test runner, used to run unit, integration and route tests as part of
// `grunt validate`. See [grunt validate](#validate) and its sub tasks for more information.
2013-07-10 02:54:57 +04:00
mochacli : {
2013-06-25 15:43:15 +04:00
options : {
2013-09-24 14:46:30 +04:00
ui : 'bdd' ,
2014-09-03 23:50:19 +04:00
reporter : grunt . option ( 'reporter' ) || 'spec' ,
2016-09-14 16:16:57 +03:00
timeout : '30000' ,
2016-06-03 11:06:18 +03:00
save : grunt . option ( 'reporter-output' ) ,
2017-11-29 18:22:21 +03:00
require : [ 'core/server/overrides' ] ,
exit : true
2013-05-26 21:17:46 +04:00
} ,
2014-05-03 17:34:41 +04:00
// #### All Unit tests
2013-11-24 18:29:36 +04:00
unit : {
2014-07-17 18:33:21 +04:00
src : [
2017-10-30 15:31:04 +03:00
'core/test/unit/**/*_spec.js'
2014-07-17 18:33:21 +04:00
]
2013-06-25 15:43:15 +04:00
} ,
2013-05-25 20:48:15 +04:00
2014-05-03 17:34:41 +04:00
// #### All Integration tests
2013-10-30 01:34:47 +04:00
integration : {
2014-02-26 21:51:01 +04:00
src : [
2017-10-30 15:31:04 +03:00
'core/test/integration/**/*_spec.js'
2014-02-26 21:51:01 +04:00
]
2013-11-24 18:29:36 +04:00
} ,
2014-05-03 17:34:41 +04:00
// #### All Route tests
2013-12-31 21:09:49 +04:00
routes : {
2014-07-17 18:33:21 +04:00
src : [
2015-04-18 15:20:03 +03:00
'core/test/functional/routes/**/*_spec.js'
2014-07-17 18:33:21 +04:00
]
2014-09-27 21:26:26 +04:00
} ,
// #### All Module tests
module : {
src : [
2015-04-18 15:20:03 +03:00
'core/test/functional/module/**/*_spec.js'
2014-09-27 21:26:26 +04:00
]
2016-05-25 09:02:23 +03:00
} ,
// #### Run single test (src is set dynamically, see grunt task 'test')
single : { }
2013-06-25 15:43:15 +04:00
} ,
2013-06-15 02:12:04 +04:00
2015-04-18 15:20:03 +03:00
// ### grunt-mocha-istanbul
// Configuration for the mocha test coverage generator
// `grunt coverage`.
mocha _istanbul : {
coverage : {
// they can also have coverage generated for them & the order doesn't matter
2016-03-29 22:14:11 +03:00
src : [
2017-10-30 15:31:04 +03:00
'core/test/unit'
2016-03-29 22:14:11 +03:00
] ,
2015-04-18 15:20:03 +03:00
options : {
mask : '**/*_spec.js' ,
2015-07-28 17:02:00 +03:00
coverageFolder : 'core/test/coverage/unit' ,
2017-12-04 15:43:50 +03:00
mochaOptions : [ '--timeout=15000' , '--require' , 'core/server/overrides' , '--exit' ] ,
2016-06-01 14:49:36 +03:00
excludes : [ 'core/client' , 'core/server/built' ]
2015-04-18 15:20:03 +03:00
}
2015-07-28 17:02:00 +03:00
} ,
2016-03-29 22:14:11 +03:00
coverage _all : {
src : [
'core/test/integration' ,
2016-04-13 19:10:40 +03:00
'core/test/functional' ,
'core/test/unit'
2016-03-29 22:14:11 +03:00
] ,
2015-07-28 17:02:00 +03:00
options : {
2016-03-29 22:14:11 +03:00
coverageFolder : 'core/test/coverage/all' ,
2015-07-28 17:02:00 +03:00
mask : '**/*_spec.js' ,
2017-12-04 15:43:50 +03:00
mochaOptions : [ '--timeout=15000' , '--require' , 'core/server/overrides' , '--exit' ] ,
2016-06-01 14:49:36 +03:00
excludes : [ 'core/client' , 'core/server/built' ]
2015-07-28 17:02:00 +03:00
}
2015-04-18 15:20:03 +03:00
}
} ,
2015-02-14 21:43:18 +03:00
bgShell : {
2016-08-07 12:53:28 +03:00
client : {
2018-04-30 22:16:24 +03:00
cmd : function ( ) {
logBuildingClient ( grunt ) ;
return 'grunt subgrunt:watch' ;
} ,
2017-03-30 16:51:22 +03:00
bg : grunt . option ( 'client' ) ? false : true ,
2017-03-30 15:27:07 +03:00
stdout : function ( chunk ) {
2017-03-30 16:51:22 +03:00
// hide certain output to prevent confusion when running alongside server
var filter = grunt . option ( 'client' ) ? false : [
2017-03-30 15:27:07 +03:00
/> ghost-admin/ ,
/^Livereload/ ,
/^Serving on/
] . some ( function ( regexp ) {
return regexp . test ( chunk ) ;
} ) ;
if ( ! filter ) {
grunt . log . write ( chunk ) ;
}
2018-04-30 22:16:24 +03:00
if ( chunk . indexOf ( 'Build successful' ) !== - 1 ) {
hasBuiltClient = true ;
}
2017-03-30 15:27:07 +03:00
} ,
2018-05-03 15:03:29 +03:00
stderr : function ( chunk ) {
hasBuiltClient = true ;
grunt . log . error ( chunk ) ;
}
2015-02-14 21:43:18 +03:00
}
} ,
2016-08-07 12:53:28 +03:00
2017-04-05 22:46:22 +03:00
// ### grunt-shell
// Command line tools where it's easier to run a command directly than configure a grunt plugin
shell : {
master : {
command : function ( ) {
2017-04-10 16:51:32 +03:00
var upstream = grunt . option ( 'upstream' ) || process . env . GHOST _UPSTREAM || 'upstream' ;
grunt . log . writeln ( 'Pulling down the latest master from ' + upstream ) ;
2017-04-17 21:52:07 +03:00
return 'git checkout master; git pull ' + upstream + ' master; ' +
2017-12-11 21:14:05 +03:00
'yarn; git submodule foreach "git checkout master && git pull ' +
upstream + ' master"' ;
2017-04-05 22:46:22 +03:00
}
} ,
dbhealth : {
command : 'knex-migrator health'
}
} ,
2014-05-03 17:34:41 +04:00
// ### grunt-docker
// Generate documentation from code
2014-05-03 15:38:59 +04:00
docker : {
2014-05-03 17:34:41 +04:00
docs : {
2014-05-05 19:26:19 +04:00
dest : 'docs' ,
2014-05-03 15:38:59 +04:00
src : [ '.' ] ,
options : {
2014-05-05 19:26:19 +04:00
onlyUpdated : true ,
2015-05-28 18:16:09 +03:00
exclude : 'node_modules,bower_components,content,core/client,*test,*doc*,' +
2017-03-14 16:51:32 +03:00
'*vendor,config.*.json,*buil*,.dist*,.idea,.git*,.travis.yml,.bower*,.editorconfig,.js*,*.md,' +
'MigratorConfig.js'
2014-05-03 15:38:59 +04:00
}
}
} ,
2014-05-03 17:34:41 +04:00
// ### grunt-contrib-clean
2013-12-06 14:24:25 +04:00
// Clean up files as part of other tasks
2013-09-18 22:56:39 +04:00
clean : {
2014-03-02 18:30:35 +04:00
built : {
2014-09-03 06:58:20 +04:00
src : [
2017-11-16 13:44:15 +03:00
'core/built/**'
2014-09-03 06:58:20 +04:00
]
2014-03-02 18:30:35 +04:00
} ,
2013-11-01 19:33:49 +04:00
release : {
2014-08-06 04:44:23 +04:00
src : [ '<%= paths.releaseBuild %>/**' ]
2013-10-15 07:39:52 +04:00
} ,
test : {
src : [ 'content/data/ghost-test.db' ]
2014-03-10 07:44:08 +04:00
} ,
tmp : {
src : [ '.tmp/**' ]
2015-05-18 00:41:49 +03:00
} ,
dependencies : {
src : [ 'node_modules/**' , 'core/client/bower_components/**' , 'core/client/node_modules/**' ]
2013-09-18 22:56:39 +04:00
}
} ,
2014-05-03 17:34:41 +04:00
// ### grunt-contrib-compress
// Zip up files for builds / releases
2013-06-25 15:43:15 +04:00
compress : {
2013-10-11 19:31:47 +04:00
release : {
options : {
archive : '<%= paths.releaseDist %>/Ghost-<%= pkg.version %>.zip'
} ,
expand : true ,
2013-11-01 19:33:49 +04:00
cwd : '<%= paths.releaseBuild %>/' ,
2017-01-23 14:33:03 +03:00
src : [ '**' ]
2013-06-10 17:52:04 +04:00
}
2013-07-02 00:58:47 +04:00
} ,
2014-05-27 18:37:44 +04:00
// ### grunt-update-submodules
// Grunt task to update git submodules
2014-09-10 08:06:24 +04:00
update _submodules : {
2017-04-10 16:51:32 +03:00
pinned : {
2014-05-27 18:37:44 +04:00
options : {
2014-07-01 03:26:08 +04:00
params : '--init'
2014-05-27 18:37:44 +04:00
}
}
2015-12-10 17:46:58 +03:00
} ,
uglify : {
prod : {
options : {
sourceMap : false
} ,
files : {
2017-07-28 17:23:32 +03:00
'core/server/public/ghost-sdk.min.js' : 'core/server/public/ghost-sdk.js'
2015-12-10 17:46:58 +03:00
}
}
2016-05-31 16:40:20 +03:00
} ,
2017-04-10 12:30:21 +03:00
cssnano : {
prod : {
options : {
sourcemap : false
} ,
files : {
'core/server/public/ghost.min.css' : 'core/server/public/ghost.css'
}
}
} ,
2016-05-31 16:40:20 +03:00
// ### grunt-subgrunt
// Run grunt tasks in submodule Gruntfiles
subgrunt : {
2016-08-07 12:53:28 +03:00
options : {
2017-04-04 13:47:12 +03:00
npmInstall : false ,
npmPath : 'yarn'
2016-08-07 12:53:28 +03:00
} ,
2017-03-14 16:51:32 +03:00
2016-06-18 20:35:51 +03:00
init : {
2017-04-11 20:18:52 +03:00
options : {
npmInstall : true
} ,
2016-08-07 12:53:28 +03:00
projects : {
'core/client' : 'init'
}
} ,
dev : {
'core/client' : 'shell:ember:dev'
} ,
prod : {
'core/client' : 'shell:ember:prod'
} ,
watch : {
2017-03-30 15:27:07 +03:00
projects : {
2017-12-11 21:14:05 +03:00
'core/client' : [ 'shell:ember:watch' , '--live-reload-base-url="' + urlService . utils . getSubdir ( ) + '/ghost/"' ]
2017-03-30 15:27:07 +03:00
}
2016-05-31 16:40:20 +03:00
}
2017-04-13 10:26:48 +03:00
} ,
// ### grunt-contrib-symlink
// Create symlink for git hooks
symlink : {
githooks : {
// Enable overwrite to delete symlinks before recreating them
overwrite : false ,
// Enable force to overwrite symlinks outside the current working directory
force : false ,
// Expand to all files in /hooks
expand : true ,
cwd : '.github/hooks' ,
src : [ '*' ] ,
dest : '.git/hooks'
}
2013-06-25 15:43:15 +04:00
}
2013-06-10 17:52:04 +04:00
} ;
2013-05-13 23:18:20 +04:00
2014-05-03 17:34:41 +04:00
// Load the configuration
2013-06-25 15:43:15 +04:00
grunt . initConfig ( cfg ) ;
2014-05-03 17:34:41 +04:00
// # Custom Tasks
// Ghost has a number of useful tasks that we use every day in development. Tasks marked as *Utility* are used
// by grunt to perform current actions, but isn't useful to developers.
//
// Skip ahead to the section on:
//
// * [Building assets](#building%20assets):
// `grunt init`, `grunt` & `grunt prod` or live reload with `grunt dev`
// * [Testing](#testing):
2015-04-18 15:20:03 +03:00
// `grunt validate`, the `grunt test-*` sub-tasks or generate a coverage report with `grunt coverage`.
2014-05-03 17:34:41 +04:00
// ### Help
// Run `grunt help` on the commandline to get a print out of the available tasks and details of
// what each one does along with any available options. This is an alias for `grunt --help`
grunt . registerTask ( 'help' ,
'Outputs help information if you type `grunt help` instead of `grunt --help`' ,
function ( ) {
2017-11-01 16:44:54 +03:00
grunt . log . writeln ( 'Type `grunt --help` to get the details of available grunt tasks.' ) ;
2014-05-03 17:34:41 +04:00
} ) ;
2013-08-01 11:12:59 +04:00
2014-05-03 17:34:41 +04:00
// ### Documentation
// Run `grunt docs` to generate annotated source code using the documentation described in the code comments.
2014-05-05 19:26:19 +04:00
grunt . registerTask ( 'docs' , 'Generate Docs' , [ 'docker' ] ) ;
2013-08-01 11:12:59 +04:00
2017-03-14 16:51:32 +03:00
// Run `grunt watch-docs` to setup livereload & watch whilst you're editing the docs
2015-05-28 18:16:09 +03:00
grunt . registerTask ( 'watch-docs' , function ( ) {
grunt . config . merge ( {
watch : {
docs : {
2017-03-14 16:51:32 +03:00
files : [ 'core/server/**/*' , 'index.js' , 'Gruntfile.js' ] ,
2015-05-28 18:16:09 +03:00
tasks : [ 'docker' ] ,
options : {
livereload : true
}
}
}
} ) ;
grunt . task . run ( 'watch:docs' ) ;
} ) ;
2014-05-03 17:34:41 +04:00
// ## Testing
2013-08-01 11:12:59 +04:00
2014-05-03 17:34:41 +04:00
// Ghost has an extensive set of test suites. The following section documents the various types of tests
// and how to run them.
//
// TLDR; run `grunt validate`
2013-08-01 11:12:59 +04:00
2014-05-03 17:34:41 +04:00
// #### Set Test Env *(Utility Task)*
// Set the NODE_ENV to 'testing' unless the environment is already set to TRAVIS.
// This ensures that the tests get run under the correct environment, using the correct database, and
// that they work as expected. Trying to run tests with no ENV set will throw an error to do with `client`.
grunt . registerTask ( 'setTestEnv' ,
'Use "testing" Ghost config; unless we are running on travis (then show queries for debugging)' ,
function ( ) {
process . env . NODE _ENV = process . env . TRAVIS ? process . env . NODE _ENV : 'testing' ;
cfg . express . test . options . node _env = process . env . NODE _ENV ;
} ) ;
2013-08-01 11:12:59 +04:00
2016-03-29 22:14:11 +03:00
// ### Test
// **Testing utility**
//
// `grunt test:unit/apps_spec.js` will run just the tests inside the apps_spec.js file
//
// It works for any path relative to the core/test folder. It will also run all the tests in a single directory
2016-06-08 18:31:19 +03:00
// You can also run a test with grunt test:core/test/unit/... to get bash autocompletion
2016-03-29 22:14:11 +03:00
//
// `grunt test:integration/api` - runs the api integration tests
// `grunt test:integration` - runs the integration tests in the root folder and excludes all api & model tests
grunt . registerTask ( 'test' , 'Run a particular spec file from the core/test directory e.g. `grunt test:unit/apps_spec.js`' , function ( test ) {
2014-12-24 16:51:16 +03:00
if ( ! test ) {
2015-09-27 20:29:14 +03:00
grunt . fail . fatal ( 'No test provided. `grunt test` expects a filename. e.g.: `grunt test:unit/apps_spec.js`. Did you mean `npm test` or `grunt validate`?' ) ;
2014-12-24 16:51:16 +03:00
}
2017-04-05 15:47:56 +03:00
if ( ! test . match ( /core\/test/ ) && ! test . match ( /core\/server/ ) ) {
2016-06-08 18:31:19 +03:00
test = 'core/test/' + test ;
}
2016-05-25 09:02:23 +03:00
// CASE: execute folder
if ( ! test . match ( /.js/ ) ) {
test += '/**' ;
} else if ( ! fs . existsSync ( test ) ) {
grunt . fail . fatal ( 'This file does not exist!' ) ;
}
cfg . mochacli . single . src = [ test ] ;
grunt . initConfig ( cfg ) ;
grunt . task . run ( 'test-setup' , 'mochacli:single' ) ;
2014-12-24 16:51:16 +03:00
} ) ;
2016-07-20 13:39:40 +03:00
// #### Stub out ghost files *(Utility Task)*
// Creates stub files in the built directory and the views directory
// so that the test environments do not need to build out the client files
grunt . registerTask ( 'stubClientFiles' , function ( ) {
_ . each ( cfg . clientFiles , function ( file ) {
var filePath = path . resolve ( cwd + '/core/' + file ) ;
fs . ensureFileSync ( filePath ) ;
} ) ;
} ) ;
2017-03-09 22:38:20 +03:00
/ * *
* Ensures the target database get ' s automatically created .
* /
grunt . registerTask ( 'knex-migrator' , function ( ) {
return knexMigrator . init ( { noScripts : true } ) ;
} ) ;
2014-05-03 17:34:41 +04:00
// ### Validate
// **Main testing task**
//
2017-03-14 16:51:32 +03:00
// `grunt validate` will either run all tests or run linting
2014-07-01 16:35:50 +04:00
// `grunt validate` is called by `npm test` and is used by Travis.
2017-03-14 16:51:32 +03:00
grunt . registerTask ( 'validate' , 'Run tests or lint code' , function ( ) {
if ( process . env . TEST _SUITE === 'lint' ) {
return grunt . task . run ( [ 'lint' ] ) ;
2015-11-13 14:54:50 +03:00
}
2017-03-14 19:03:30 +03:00
grunt . task . run ( [ 'test-all' ] ) ;
2017-03-14 16:51:32 +03:00
} ) ;
2014-07-01 16:35:50 +04:00
2015-01-25 23:27:00 +03:00
// ### Test-All
2014-07-01 16:35:50 +04:00
// **Main testing task**
//
2015-01-25 23:27:00 +03:00
// `grunt test-all` will lint and test your pre-built local Ghost codebase.
2014-07-01 16:35:50 +04:00
//
2017-03-14 16:51:32 +03:00
grunt . registerTask ( 'test-all' , 'Run all server tests' ,
2015-12-04 20:45:32 +03:00
[ 'test-routes' , 'test-module' , 'test-unit' , 'test-integration' ] ) ;
2015-11-13 14:54:50 +03:00
2014-09-19 18:52:48 +04:00
// ### Lint
//
2017-11-01 16:44:54 +03:00
// `grunt lint` will run the linter
grunt . registerTask ( 'lint' , 'Run the code style checks for server & tests' ,
[ 'eslint' ]
2016-05-31 16:40:20 +03:00
) ;
2015-01-25 23:27:00 +03:00
// ### test-setup *(utility)(
// `grunt test-setup` will run all the setup tasks required for running tests
grunt . registerTask ( 'test-setup' , 'Setup ready to run tests' ,
2017-03-14 19:03:30 +03:00
[ 'knex-migrator' , 'clean:test' , 'setTestEnv' , 'stubClientFiles' ]
2015-01-25 23:27:00 +03:00
) ;
2014-09-19 18:52:48 +04:00
2014-05-03 17:34:41 +04:00
// ### Unit Tests *(sub task)*
// `grunt test-unit` will run just the unit tests
//
2016-03-29 22:14:11 +03:00
// If you need to run an individual unit test file, you can use the `grunt test:<file_path>` task:
2014-05-03 17:34:41 +04:00
//
2016-03-29 22:14:11 +03:00
// `grunt test:unit/config_spec.js`
2014-05-03 17:34:41 +04:00
//
2016-03-29 22:14:11 +03:00
// This also works for folders (although it isn't recursive), E.g.
2014-05-03 17:34:41 +04:00
//
2017-10-19 14:02:21 +03:00
// `grunt test:unit/helpers`
2014-05-03 17:34:41 +04:00
//
2014-11-27 23:50:15 +03:00
// Unit tests are run with [mocha](http://mochajs.org/) using
2014-05-03 17:34:41 +04:00
// [should](https://github.com/visionmedia/should.js) to describe the tests in a highly readable style.
// Unit tests do **not** touch the database.
// A coverage report can be generated for these tests using the `grunt test-coverage` task.
grunt . registerTask ( 'test-unit' , 'Run unit tests (mocha)' ,
2015-01-25 23:27:00 +03:00
[ 'test-setup' , 'mochacli:unit' ]
) ;
2014-05-03 17:34:41 +04:00
// ### Integration tests *(sub task)*
// `grunt test-integration` will run just the integration tests
//
2017-03-14 16:51:32 +03:00
// Provided you already have a `config.*.json` file, you can run just the model integration tests by running:
2014-05-03 17:34:41 +04:00
//
2016-03-29 22:14:11 +03:00
// `grunt test:integration/model`
2014-05-03 17:34:41 +04:00
//
// Or just the api integration tests by running:
//
2016-03-29 22:14:11 +03:00
// `grunt test:integration/api`
2014-05-03 17:34:41 +04:00
//
2014-11-27 23:50:15 +03:00
// Integration tests are run with [mocha](http://mochajs.org/) using
2014-05-03 17:34:41 +04:00
// [should](https://github.com/visionmedia/should.js) to describe the tests in a highly readable style.
// Integration tests are different to the unit tests because they make requests to the database.
//
2016-03-29 22:14:11 +03:00
// If you need to run an individual integration test file you can use the `grunt test:<file_path>` task:
2014-07-20 18:11:02 +04:00
//
2016-03-29 22:14:11 +03:00
// `grunt test:integration/api/api_tags_spec.js`
2014-07-20 18:11:02 +04:00
//
2014-05-03 17:34:41 +04:00
// Their purpose is to test that both the api and models behave as expected when the database layer is involved.
2016-09-16 12:40:23 +03:00
// These tests are run against sqlite3 and mysql on travis and ensure that differences between the databases
// don't cause bugs.
2014-05-03 17:34:41 +04:00
//
// A coverage report can be generated for these tests using the `grunt test-coverage` task.
grunt . registerTask ( 'test-integration' , 'Run integration tests (mocha + db access)' ,
2015-01-25 23:27:00 +03:00
[ 'test-setup' , 'mochacli:integration' ]
) ;
2014-05-03 17:34:41 +04:00
// ### Route tests *(sub task)*
// `grunt test-routes` will run just the route tests
//
2016-03-29 22:14:11 +03:00
// If you need to run an individual route test file, you can use the `grunt test:<file_path>` task:
2014-05-03 17:34:41 +04:00
//
2016-03-29 22:14:11 +03:00
// `grunt test:functional/routes/admin_spec.js`
2014-05-03 17:34:41 +04:00
//
2014-11-27 23:50:15 +03:00
// Route tests are run with [mocha](http://mochajs.org/) using
2014-05-03 17:34:41 +04:00
// [should](https://github.com/visionmedia/should.js) and [supertest](https://github.com/visionmedia/supertest)
// to describe and create the tests.
//
// Supertest enables us to describe requests that we want to make, and also describe the response we expect to
// receive back. It works directly with express, so we don't have to run a server to run the tests.
//
// The purpose of the route tests is to ensure that all of the routes (pages, and API requests) in Ghost
// are working as expected, including checking the headers and status codes received. It is very easy and
// quick to test many permutations of routes / urls in the system.
grunt . registerTask ( 'test-routes' , 'Run functional route tests (mocha)' ,
2015-01-25 23:27:00 +03:00
[ 'test-setup' , 'mochacli:routes' ]
) ;
2014-05-03 17:34:41 +04:00
2014-09-27 21:26:26 +04:00
// ### Module tests *(sub task)*
// `grunt test-module` will run just the module tests
//
// The purpose of the module tests is to ensure that Ghost can be used as an npm module and exposes all
// required methods to interact with it.
grunt . registerTask ( 'test-module' , 'Run functional module tests (mocha)' ,
2015-01-25 23:27:00 +03:00
[ 'test-setup' , 'mochacli:module' ]
) ;
2014-09-27 21:26:26 +04:00
2014-05-03 17:34:41 +04:00
// ### Coverage
2015-04-18 15:20:03 +03:00
// `grunt coverage` will generate a report for the Unit Tests.
2014-05-03 17:34:41 +04:00
//
// This is not currently done as part of CI or any build, but is a tool we have available to keep an eye on how
// well the unit and integration tests are covering the code base.
// Ghost does not have a minimum coverage level - we're more interested in ensuring important and useful areas
// of the codebase are covered, than that the whole codebase is covered to a particular level.
//
// Key areas for coverage are: helpers and theme elements, apps / GDK, the api and model layers.
2015-04-18 15:20:03 +03:00
grunt . registerTask ( 'coverage' , 'Generate unit and integration (mocha) tests coverage report' ,
[ 'test-setup' , 'mocha_istanbul:coverage' ]
2015-01-25 23:27:00 +03:00
) ;
2014-05-03 17:34:41 +04:00
2016-03-29 22:14:11 +03:00
grunt . registerTask ( 'coverage-all' , 'Generate unit and integration tests coverage report' ,
[ 'test-setup' , 'mocha_istanbul:coverage_all' ]
2015-07-28 17:02:00 +03:00
) ;
2014-05-03 17:34:41 +04:00
// #### Master Warning *(Utility Task)*
// Warns git users not ot use the `master` branch in production.
// `master` is an unstable branch and shouldn't be used in production as you run the risk of ending up with a
// database in an unrecoverable state. Instead there is a branch called `stable` which is the equivalent of the
// release zip for git users.
2014-04-16 13:45:49 +04:00
grunt . registerTask ( 'master-warn' ,
'Outputs a warning to runners of grunt prod, that master shouldn\'t be used for live blogs' ,
function ( ) {
2017-11-01 16:44:54 +03:00
grunt . log . writeln ( chalk . red (
2016-03-29 22:14:11 +03:00
'Use the ' + chalk . bold ( 'stable' ) + ' branch for live blogs. '
+ chalk . bold . underline ( 'Never' ) + ' master!'
) ) ;
2017-11-01 16:44:54 +03:00
grunt . log . writeln ( '>' , 'Always two there are, no more, no less. A master and a ' + chalk . bold ( 'stable' ) + '.' ) ;
2014-04-16 13:45:49 +04:00
} ) ;
2015-02-14 21:43:18 +03:00
// ## Building assets
//
// Ghost's GitHub repository contains the un-built source code for Ghost. If you're looking for the already
// built release zips, you can get these from the [release page](https://github.com/TryGhost/Ghost/releases) on
// GitHub or from https://ghost.org/download. These zip files are created using the [grunt release](#release)
// task.
//
// If you want to work on Ghost core, or you want to use the source files from GitHub, then you have to build
// the Ghost assets in order to make them work.
//
// There are a number of grunt tasks available to help with this. Firstly after fetching an updated version of
2017-04-04 13:47:12 +03:00
// the Ghost codebase, after running `yarn install`, you will need to run [grunt init](#init%20assets).
2015-02-14 21:43:18 +03:00
//
// For production blogs you will need to run [grunt prod](#production%20assets).
//
// For updating assets during development, the tasks [grunt](#default%20asset%20build) and
// [grunt dev](#live%20reload) are available.
2014-05-03 17:34:41 +04:00
// ### Init assets
// `grunt init` - will run an initial asset build for you
//
2017-04-04 13:47:12 +03:00
// Grunt init runs `yarn install && bower install` inside `core/client` as well as the standard asset build
2016-05-23 18:59:42 +03:00
// tasks which occur when you run just `grunt`. This fetches the latest client-side dependencies.
2014-05-03 17:34:41 +04:00
//
2016-05-23 18:59:42 +03:00
// This task is very important, and should always be run when fetching down an updated code base just after
2017-04-04 13:47:12 +03:00
// running `yarn install`.
2014-05-03 17:34:41 +04:00
//
// `bower` does have some quirks, such as not running as root. If you have problems please try running
// `grunt init --verbose` to see if there are any errors.
grunt . registerTask ( 'init' , 'Prepare the project for development' ,
2017-04-10 16:51:32 +03:00
[ 'update_submodules:pinned' , 'subgrunt:init' , 'clean:tmp' , 'default' ] ) ;
2014-05-03 17:34:41 +04:00
2016-08-07 12:53:28 +03:00
// ### Build assets
// `grunt build` - will build client assets (without updating the submodule)
//
// This task is identical to `grunt init`, except it does not build client dependencies
grunt . registerTask ( 'build' , 'Build client app' ,
[ 'subgrunt:init' , 'clean:tmp' , 'default' ] ) ;
2014-05-03 17:34:41 +04:00
// ### Default asset build
// `grunt` - default grunt task
//
2015-02-14 21:43:18 +03:00
// Build assets and dev version of the admin app.
2014-05-03 17:34:41 +04:00
grunt . registerTask ( 'default' , 'Build JS & templates for development' ,
2016-08-07 12:53:28 +03:00
[ 'subgrunt:dev' ] ) ;
2015-02-14 21:43:18 +03:00
// ### Production assets
// `grunt prod` - will build the minified assets used in production.
//
// It is otherwise the same as running `grunt`, but is only used when running Ghost in the `production` env.
grunt . registerTask ( 'prod' , 'Build JS & templates for production' ,
2017-04-10 12:30:21 +03:00
[ 'subgrunt:prod' , 'uglify:prod' , 'cssnano:prod' , 'master-warn' ] ) ;
2014-05-03 17:34:41 +04:00
// ### Live reload
// `grunt dev` - build assets on the fly whilst developing
//
// If you want Ghost to live reload for you whilst you're developing, you can do this by running `grunt dev`.
// This works hand-in-hand with the [livereload](http://livereload.com/) chrome extension.
//
// `grunt dev` manages starting an express server and restarting the server whenever core files change (which
// require a server restart for the changes to take effect) and also manage reloading the browser whenever
// frontend code changes.
//
// Note that the current implementation of watch only works with casper, not other themes.
2017-03-30 16:51:22 +03:00
grunt . registerTask ( 'dev' , 'Dev Mode; watch files and restart server on changes' , function ( ) {
if ( grunt . option ( 'client' ) ) {
2017-11-16 13:44:15 +03:00
grunt . task . run ( [ 'clean:built' , 'bgShell:client' ] ) ;
2017-03-30 16:51:22 +03:00
} else if ( grunt . option ( 'server' ) ) {
grunt . task . run ( [ 'express:dev' , 'watch' ] ) ;
} else {
2017-11-16 13:44:15 +03:00
grunt . task . run ( [ 'clean:built' , 'bgShell:client' , 'express:dev' , 'watch' ] ) ;
2017-03-30 16:51:22 +03:00
}
} ) ;
2014-05-03 17:34:41 +04:00
2017-04-10 16:51:32 +03:00
// ### grunt master
// This command helps you to bring your working directory back to current master.
// It will also update your dependencies to master and shows you if your database is healthy.
// It won't build the client!
//
// `grunt master` [`upstream` is the default upstream to pull from]
// `grunt master --upstream=parent`
2017-04-05 22:46:22 +03:00
grunt . registerTask ( 'master' , 'Update your current working folder to latest master.' ,
2017-04-17 21:52:07 +03:00
[ 'shell:master' , 'subgrunt:init' , 'shell:dbhealth' ]
2017-04-05 22:46:22 +03:00
) ;
2014-05-03 17:34:41 +04:00
// ### Release
// Run `grunt release` to create a Ghost release zip file.
// Uses the files specified by `.npmignore` to know what should and should not be included.
2017-08-02 10:54:45 +03:00
// Runs the asset generation tasks for production and duplicates default-prod.html to default.html
// so it can be run in either production or development, and packages all the files up into a zip.
2014-05-03 17:34:41 +04:00
grunt . registerTask ( 'release' ,
'Release task - creates a final built zip\n' +
2014-07-01 03:26:08 +04:00
' - Do our standard build steps \n' +
2014-05-03 17:34:41 +04:00
' - Copy files to release-folder/#/#{version} directory\n' +
2014-05-05 19:26:19 +04:00
' - Clean out unnecessary files (travis, .git*, etc)\n' +
2014-05-03 17:34:41 +04:00
' - Zip files in release-folder to dist-folder/#{version} directory' ,
2015-11-24 00:20:59 +03:00
function ( ) {
grunt . config . set ( 'copy.release' , {
expand : true ,
// #### Build File Patterns
// A list of files and patterns to include when creating a release zip.
// This is read from the `.npmignore` file and all patterns are inverted as the `.npmignore`
// file defines what to ignore, whereas we want to define what to include.
2017-01-23 14:33:03 +03:00
src : fs . readFileSync ( '.npmignore' , 'utf8' ) . split ( '\n' ) . filter ( Boolean ) . map ( function ( pattern ) {
2015-11-24 00:20:59 +03:00
return pattern [ 0 ] === '!' ? pattern . substr ( 1 ) : '!' + pattern ;
2017-01-23 14:33:03 +03:00
} ) ,
2015-11-24 00:20:59 +03:00
dest : '<%= paths.releaseBuild %>/'
} ) ;
2017-08-02 10:54:45 +03:00
grunt . config . set ( 'copy.admin_html' , {
files : [ {
2017-08-03 11:05:35 +03:00
cwd : '.' ,
2017-12-06 19:37:54 +03:00
src : 'core/server/web/admin/views/default-prod.html' ,
dest : 'core/server/web/admin/views/default.html'
2017-08-02 10:54:45 +03:00
} ]
} ) ;
2017-11-16 13:44:15 +03:00
grunt . task . run ( [ 'update_submodules:pinned' , 'subgrunt:init' , 'clean:built' , 'clean:tmp' , 'prod' , 'clean:release' , 'copy:admin_html' , 'copy:release' , 'compress:release' ] ) ;
2015-11-24 00:20:59 +03:00
}
) ;
2013-06-25 15:43:15 +04:00
} ;
2014-06-02 18:55:49 +04:00
module . exports = configureGrunt ;