mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-23 19:02:29 +03:00
Improved dev tooling (#13118)
This commit achieves a few things: - ☑️ No longer having to remember whether a command is yarn something or grunt something - ☑️ Simplification of tools hopefully making them easier to remember and use - ☑️ Complete removal of the need for grunt from our test tooling Several of the tools still use grunt under the hood, but the **entrypoint** should aways be `yarn xxx`. - `grunt main` -> `yarn main` - `grunt dev` -> `yarn dev` - `grunt build` -> `yarn build` - `grunt test:file-or-folder` -> `yarn test file-or-folder` - `grunt test-unit` -> `yarn test:unit` - `grunt test-acceptance` -> `yarn test:acceptance` - `grunt test-regression` -> `yarn test:regression` - `grunt validate` -> removed due to lack of use There is now also `yarn test:all` to run all 3 classes of tests This PR also reorders & restructures the Gruntfile extensively so that: - The remaining useful commands are all at the top of the file - Config and other blah happens after all the useful commands - All release-only config happens in the release task at the very end of the file --- DONE: * Removed all references to npm/bower * Removed all references to lint / deprecated command * Moved debug to yarn dev:debug * Removed all references to travis * Removed broken help task + useless comment * Removed unused knex-migrator and clean:test setup tasks * Added new test commands, removed grunt validate * Moved stubClientFiles to test utility and use in the few tests that need it * Used mocha in yarn directly except grunt test:x * Swapped grunt test for yarn test * extensive cleanup and reshuffling
This commit is contained in:
parent
8a1fd1f57f
commit
7e6800b2b8
6
.github/workflows/test.yml
vendored
6
.github/workflows/test.yml
vendored
@ -104,11 +104,11 @@ jobs:
|
||||
mysql root password: 'root'
|
||||
|
||||
- run: yarn
|
||||
- run: grunt test-acceptance --verbose
|
||||
- run: yarn test:acceptance
|
||||
env:
|
||||
database__connection__filename: /dev/shm/ghost-test.db
|
||||
- run: grunt test-unit --verbose
|
||||
- run: grunt test-regression --verbose
|
||||
- run: yarn test:unit
|
||||
- run: yarn test:regression
|
||||
env:
|
||||
database__connection__filename: /dev/shm/ghost-test.db
|
||||
|
||||
|
484
Gruntfile.js
484
Gruntfile.js
@ -1,24 +1,8 @@
|
||||
// # 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
|
||||
const config = require('./core/shared/config');
|
||||
const _ = require('lodash');
|
||||
const fs = require('fs-extra');
|
||||
const KnexMigrator = require('knex-migrator');
|
||||
const knexMigrator = new KnexMigrator({
|
||||
knexMigratorFilePath: config.get('paths:appRoot')
|
||||
});
|
||||
|
||||
const path = require('path');
|
||||
const escapeChar = process.platform.match(/^win/) ? '^' : '\\';
|
||||
const cwd = process.cwd().replace(/( |\(|\))/g, escapeChar + '$1');
|
||||
const buildDirectory = path.resolve(cwd, '.build');
|
||||
const distDirectory = path.resolve(cwd, '.dist');
|
||||
|
||||
// Utility for outputting messages indicating that the admin is building, as it can take a while.
|
||||
let hasBuiltClient = false;
|
||||
const logBuildingClient = function (grunt) {
|
||||
if (!hasBuiltClient) {
|
||||
@ -27,56 +11,53 @@ const logBuildingClient = function (grunt) {
|
||||
}
|
||||
};
|
||||
|
||||
// ## Grunt configuration
|
||||
const configureGrunt = function (grunt) {
|
||||
// #### Load all grunt tasks
|
||||
grunt.loadNpmTasks('@lodder/grunt-postcss');
|
||||
grunt.loadNpmTasks('grunt-bg-shell');
|
||||
grunt.loadNpmTasks('grunt-contrib-clean');
|
||||
grunt.loadNpmTasks('grunt-contrib-compress');
|
||||
grunt.loadNpmTasks('grunt-contrib-copy');
|
||||
grunt.loadNpmTasks('grunt-contrib-symlink');
|
||||
grunt.loadNpmTasks('grunt-contrib-watch');
|
||||
grunt.loadNpmTasks('grunt-express-server');
|
||||
grunt.loadNpmTasks('grunt-mocha-cli');
|
||||
grunt.loadNpmTasks('grunt-shell');
|
||||
grunt.loadNpmTasks('grunt-subgrunt');
|
||||
grunt.loadNpmTasks('grunt-update-submodules');
|
||||
module.exports = function (grunt) {
|
||||
// grunt dev - use yarn dev instead!
|
||||
// - Start a server & build assets on the fly whilst developing
|
||||
grunt.registerTask('dev', 'Dev Mode; watch files and restart server on changes', function () {
|
||||
if (grunt.option('client')) {
|
||||
grunt.task.run(['clean:built', 'bgShell:client']);
|
||||
} else if (grunt.option('server')) {
|
||||
grunt.task.run(['express:dev', 'watch']);
|
||||
} else {
|
||||
grunt.task.run(['clean:built', 'bgShell:client', 'express:dev', 'watch']);
|
||||
}
|
||||
});
|
||||
|
||||
/** This little bit of weirdness gives the express server chance to shutdown properly */
|
||||
const waitBeforeExit = () => {
|
||||
setTimeout(() => {
|
||||
process.exit(0);
|
||||
}, 1000);
|
||||
};
|
||||
// grunt build -- use yarn build instead!
|
||||
// - Builds the client without a watch task
|
||||
grunt.registerTask('build', 'Build client app in development mode',
|
||||
['subgrunt:init', 'clean:tmp', 'ember']);
|
||||
|
||||
process.on('SIGINT', waitBeforeExit);
|
||||
process.on('SIGTERM', waitBeforeExit);
|
||||
// Helpers for common deprecated tasks
|
||||
grunt.registerTask('main', function () {
|
||||
grunt.log.error('@deprecated: Run `yarn main` instead');
|
||||
});
|
||||
|
||||
grunt.registerTask('validate', function () {
|
||||
grunt.log.error('@deprecated: Run `yarn test` instead');
|
||||
});
|
||||
|
||||
// --- Sub Commands
|
||||
// Used to make other commands work
|
||||
|
||||
// Updates submodules, then installs and builds the client for you
|
||||
grunt.registerTask('init', 'Prepare the project for development',
|
||||
['update_submodules:pinned', 'build']);
|
||||
|
||||
// Runs ember dev
|
||||
grunt.registerTask('ember', 'Build JS & templates for development',
|
||||
['subgrunt:dev']);
|
||||
|
||||
// Production asset build
|
||||
grunt.registerTask('prod', 'Build JS & templates for production',
|
||||
['subgrunt:prod', 'postcss:prod']);
|
||||
|
||||
// --- Configuration
|
||||
const cfg = {
|
||||
// #### Common paths used by tasks
|
||||
paths: {
|
||||
build: buildDirectory,
|
||||
releaseBuild: path.join(buildDirectory, 'release'),
|
||||
dist: distDirectory,
|
||||
releaseDist: path.join(distDirectory, 'release')
|
||||
},
|
||||
// Standard build type, for when we have nightlies again.
|
||||
buildType: 'Build',
|
||||
// Load package.json so that we can create correctly versioned releases.
|
||||
pkg: grunt.file.readJSON('package.json'),
|
||||
|
||||
clientFiles: [
|
||||
'server/web/admin/views/default.html',
|
||||
'built/assets/ghost.js',
|
||||
'built/assets/ghost.css',
|
||||
'built/assets/vendor.js',
|
||||
'built/assets/vendor.css'
|
||||
],
|
||||
|
||||
// ### grunt-contrib-watch
|
||||
// grunt-contrib-watch
|
||||
// Watch files and livereload in the browser during development.
|
||||
// See the [grunt dev](#live%20reload) task for how this is used.
|
||||
// See the grunt dev task for how this is used.
|
||||
watch: grunt.option('no-server-watch') ? {files: []} : {
|
||||
livereload: {
|
||||
files: [
|
||||
@ -107,58 +88,19 @@ const configureGrunt = function (grunt) {
|
||||
}
|
||||
},
|
||||
|
||||
// ### grunt-express-server
|
||||
// grunt-express-server
|
||||
// Start a Ghost express server for use in development and testing
|
||||
express: {
|
||||
dev: {
|
||||
options: {
|
||||
script: 'index.js',
|
||||
output: 'Ghost is running'
|
||||
},
|
||||
|
||||
dev: {
|
||||
options: {}
|
||||
},
|
||||
test: {
|
||||
options: {
|
||||
node_env: 'testing'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// ### grunt-mocha-cli
|
||||
mochacli: {
|
||||
options: {
|
||||
ui: 'bdd',
|
||||
reporter: grunt.option('reporter') || 'spec',
|
||||
timeout: '60000',
|
||||
require: ['core/server/overrides'],
|
||||
flags: ['--trace-warnings'],
|
||||
exit: true
|
||||
},
|
||||
|
||||
unit: {
|
||||
src: [
|
||||
'test/unit/**/*_spec.js'
|
||||
]
|
||||
},
|
||||
|
||||
acceptance: {
|
||||
src: [
|
||||
'test/api-acceptance/**/*_spec.js',
|
||||
'test/frontend-acceptance/**/*_spec.js'
|
||||
]
|
||||
},
|
||||
|
||||
regression: {
|
||||
src: [
|
||||
'test/regression/**/*_spec.js'
|
||||
]
|
||||
},
|
||||
|
||||
// #### Run single test (src is set dynamically, see grunt task 'test')
|
||||
single: {}
|
||||
},
|
||||
|
||||
// grunt-bg-shell
|
||||
// Tools for building the client
|
||||
bgShell: {
|
||||
client: {
|
||||
cmd: function () {
|
||||
@ -205,12 +147,9 @@ const configureGrunt = function (grunt) {
|
||||
}
|
||||
},
|
||||
|
||||
// ### grunt-shell
|
||||
// grunt-shell
|
||||
// Command line tools where it's easier to run a command directly than configure a grunt plugin
|
||||
shell: {
|
||||
lint: {
|
||||
command: 'yarn lint'
|
||||
},
|
||||
main: {
|
||||
command: function () {
|
||||
const upstream = grunt.option('upstream') || process.env.GHOST_UPSTREAM || 'upstream';
|
||||
@ -247,7 +186,7 @@ const configureGrunt = function (grunt) {
|
||||
}
|
||||
},
|
||||
|
||||
// ### grunt-contrib-clean
|
||||
// grunt-contrib-clean
|
||||
// Clean up files as part of other tasks
|
||||
clean: {
|
||||
built: {
|
||||
@ -255,34 +194,12 @@ const configureGrunt = function (grunt) {
|
||||
'core/built/**'
|
||||
]
|
||||
},
|
||||
release: {
|
||||
src: ['<%= paths.releaseBuild %>/**']
|
||||
},
|
||||
test: {
|
||||
src: ['content/data/ghost-test.db']
|
||||
},
|
||||
tmp: {
|
||||
src: ['.tmp/**']
|
||||
},
|
||||
dependencies: {
|
||||
src: ['node_modules/**', 'core/client/bower_components/**', 'core/client/node_modules/**']
|
||||
}
|
||||
},
|
||||
|
||||
// ### grunt-contrib-compress
|
||||
// Zip up files for builds / releases
|
||||
compress: {
|
||||
release: {
|
||||
options: {
|
||||
archive: '<%= paths.releaseDist %>/Ghost-<%= pkg.version %>.zip'
|
||||
},
|
||||
expand: true,
|
||||
cwd: '<%= paths.releaseBuild %>/',
|
||||
src: ['**']
|
||||
}
|
||||
},
|
||||
|
||||
// ### grunt-update-submodules
|
||||
// grunt-update-submodules
|
||||
// Grunt task to update git submodules
|
||||
update_submodules: {
|
||||
pinned: {
|
||||
@ -292,6 +209,8 @@ const configureGrunt = function (grunt) {
|
||||
}
|
||||
},
|
||||
|
||||
// @lodder/grunt-postcss
|
||||
// Generate processed, minified css files
|
||||
postcss: {
|
||||
prod: {
|
||||
options: {
|
||||
@ -305,7 +224,7 @@ const configureGrunt = function (grunt) {
|
||||
}
|
||||
},
|
||||
|
||||
// ### grunt-subgrunt
|
||||
// grunt-subgrunt
|
||||
// Run grunt tasks in submodule Gruntfiles
|
||||
subgrunt: {
|
||||
options: {
|
||||
@ -337,7 +256,7 @@ const configureGrunt = function (grunt) {
|
||||
}
|
||||
},
|
||||
|
||||
// ### grunt-contrib-symlink
|
||||
// grunt-contrib-symlink
|
||||
// Create symlink for git hooks
|
||||
symlink: {
|
||||
githooks: {
|
||||
@ -354,251 +273,69 @@ const configureGrunt = function (grunt) {
|
||||
}
|
||||
};
|
||||
|
||||
// --- Grunt Initialisation
|
||||
|
||||
// Load all grunt tasks
|
||||
grunt.loadNpmTasks('@lodder/grunt-postcss');
|
||||
grunt.loadNpmTasks('grunt-bg-shell');
|
||||
grunt.loadNpmTasks('grunt-contrib-clean');
|
||||
grunt.loadNpmTasks('grunt-contrib-compress');
|
||||
grunt.loadNpmTasks('grunt-contrib-copy');
|
||||
grunt.loadNpmTasks('grunt-contrib-symlink');
|
||||
grunt.loadNpmTasks('grunt-contrib-watch');
|
||||
grunt.loadNpmTasks('grunt-express-server');
|
||||
grunt.loadNpmTasks('grunt-mocha-cli');
|
||||
grunt.loadNpmTasks('grunt-shell');
|
||||
grunt.loadNpmTasks('grunt-subgrunt');
|
||||
grunt.loadNpmTasks('grunt-update-submodules');
|
||||
|
||||
// This little bit of weirdness gives the express server chance to shutdown properly
|
||||
const waitBeforeExit = () => {
|
||||
setTimeout(() => {
|
||||
process.exit(0);
|
||||
}, 1000);
|
||||
};
|
||||
|
||||
process.on('SIGINT', waitBeforeExit);
|
||||
process.on('SIGTERM', waitBeforeExit);
|
||||
|
||||
// Load the configuration
|
||||
grunt.initConfig(cfg);
|
||||
|
||||
// # Custom Tasks
|
||||
// --- Release Tooling
|
||||
|
||||
// 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):
|
||||
// `grunt validate`, the `grunt test-*` sub-tasks.
|
||||
|
||||
// ### 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 () {
|
||||
grunt.log.writeln('Type `grunt --help` to get the details of available grunt tasks.');
|
||||
});
|
||||
|
||||
// ## Testing
|
||||
|
||||
// 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`
|
||||
|
||||
// #### 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.NODE_ENV || 'testing';
|
||||
cfg.express.test.options.node_env = process.env.NODE_ENV;
|
||||
});
|
||||
|
||||
// ### 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 /test/ folder. It will also run all the tests in a single directory
|
||||
// You can also run a test with grunt test:test/unit/... to get bash autocompletion
|
||||
//
|
||||
// `grunt test:regression/api` - runs the api regression tests
|
||||
grunt.registerTask('test', 'Run a particular spec file from the /test/ directory e.g. `grunt test:unit/apps_spec.js`', function (test) {
|
||||
if (!test) {
|
||||
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`?');
|
||||
}
|
||||
|
||||
if (!test.match(/test\//) && !test.match(/core\/server/)) {
|
||||
test = 'test/' + test;
|
||||
}
|
||||
|
||||
// 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');
|
||||
});
|
||||
|
||||
// #### 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) {
|
||||
const filePath = path.resolve(cwd + '/core/' + file);
|
||||
fs.ensureFileSync(filePath);
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Ensures the target database get's automatically created.
|
||||
*/
|
||||
grunt.registerTask('knex-migrator', function () {
|
||||
return knexMigrator.init({noScripts: true});
|
||||
});
|
||||
|
||||
// ### Validate
|
||||
// **Main testing task**
|
||||
//
|
||||
// `grunt validate` will either run all tests or run linting
|
||||
// `grunt validate` is called by `yarn test` and is used by Travis.
|
||||
grunt.registerTask('validate', 'Run tests', function () {
|
||||
grunt.task.run(['test-unit', 'test-acceptance']);
|
||||
});
|
||||
|
||||
grunt.registerTask('test-all', 'Run all server tests',
|
||||
['test-unit', 'test-acceptance', 'test-regression']);
|
||||
|
||||
// ### Lint
|
||||
//
|
||||
// `grunt lint` will run the linter
|
||||
grunt.registerTask('lint', 'Run the code style checks for server & tests',
|
||||
['shell:lint']
|
||||
);
|
||||
|
||||
// ### 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',
|
||||
['knex-migrator', 'clean:test', 'setTestEnv', 'stubClientFiles']
|
||||
);
|
||||
|
||||
// ### Unit Tests *(sub task)*
|
||||
// `grunt test-unit` will run just the unit tests
|
||||
//
|
||||
// If you need to run an individual unit test file, you can use the `grunt test:<file_path>` task:
|
||||
//
|
||||
// `grunt test:unit/config_spec.js`
|
||||
//
|
||||
// This also works for folders (although it isn't recursive), E.g.
|
||||
//
|
||||
// `grunt test:unit/helpers`
|
||||
//
|
||||
// Unit tests are run with [mocha](http://mochajs.org/) using
|
||||
// [should](https://github.com/visionmedia/should.js) to describe the tests in a highly readable style.
|
||||
// Unit tests do **not** touch the database.
|
||||
grunt.registerTask('test-unit', 'Run unit tests (mocha)',
|
||||
['test-setup', 'mochacli:unit']
|
||||
);
|
||||
|
||||
grunt.registerTask('test-regression', 'Run regression tests.',
|
||||
['test-setup', 'mochacli:regression']
|
||||
);
|
||||
|
||||
grunt.registerTask('test-acceptance', 'Run acceptance tests',
|
||||
['test-setup', 'mochacli:acceptance']
|
||||
);
|
||||
|
||||
// ## 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/docs/install/. 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
|
||||
// the Ghost codebase, after running `yarn install`, you will need to run [grunt init](#init%20assets).
|
||||
//
|
||||
// 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.
|
||||
|
||||
// ### Init assets
|
||||
// `grunt init` - will run an initial asset build for you
|
||||
//
|
||||
// Grunt init runs `yarn install && bower install` inside `core/client` as well as the standard asset build
|
||||
// tasks which occur when you run just `grunt`. This fetches the latest client-side dependencies.
|
||||
//
|
||||
// This task is very important, and should always be run when fetching down an updated code base just after
|
||||
// running `yarn install`.
|
||||
//
|
||||
// `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',
|
||||
['update_submodules:pinned', 'subgrunt:init', 'clean:tmp', 'default']);
|
||||
|
||||
// ### 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']);
|
||||
|
||||
// ### Default asset build
|
||||
// `grunt` - default grunt task
|
||||
//
|
||||
// Build assets and dev version of the admin app.
|
||||
grunt.registerTask('default', 'Build JS & templates for development',
|
||||
['subgrunt:dev']);
|
||||
|
||||
// ### 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',
|
||||
['subgrunt:prod', 'postcss:prod']);
|
||||
|
||||
// ### 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.
|
||||
grunt.registerTask('dev', 'Dev Mode; watch files and restart server on changes', function () {
|
||||
if (grunt.option('client')) {
|
||||
grunt.task.run(['clean:built', 'bgShell:client']);
|
||||
} else if (grunt.option('server')) {
|
||||
grunt.task.run(['express:dev', 'watch']);
|
||||
} else {
|
||||
grunt.task.run(['clean:built', 'bgShell:client', 'express:dev', 'watch']);
|
||||
}
|
||||
});
|
||||
|
||||
// ### grunt main
|
||||
// This command helps you to bring your working directory back to current main.
|
||||
// It will also update your dependencies to main and shows you if your database is healthy.
|
||||
// It won't build the client!
|
||||
//
|
||||
// `grunt main` [`upstream` is the default upstream to pull from]
|
||||
// `grunt main --upstream=parent`
|
||||
grunt.registerTask('main', 'Update your current working folder to latest main.',
|
||||
['shell:main', 'subgrunt:init']
|
||||
);
|
||||
|
||||
grunt.registerTask('master', 'Backwards compatible alias for `grunt main`.', 'main');
|
||||
|
||||
// ### Release
|
||||
// Run `grunt release` to create a Ghost release zip file.
|
||||
// grunt release
|
||||
// - create a Ghost release zip file.
|
||||
// Uses the files specified by `.npmignore` to know what should and should not be included.
|
||||
// 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.
|
||||
grunt.registerTask('release',
|
||||
'Release task - creates a final built zip\n' +
|
||||
' - Do our standard build steps \n' +
|
||||
' - Copy files to release-folder/#/#{version} directory\n' +
|
||||
' - Clean out unnecessary files (travis, .git*, etc)\n' +
|
||||
' - Clean out unnecessary files (.git*, etc)\n' +
|
||||
' - Zip files in release-folder to dist-folder/#{version} directory',
|
||||
function () {
|
||||
const escapeChar = process.platform.match(/^win/) ? '^' : '\\';
|
||||
const cwd = process.cwd().replace(/( |\(|\))/g, escapeChar + '$1');
|
||||
const buildDirectory = path.resolve(cwd, '.build');
|
||||
const distDirectory = path.resolve(cwd, '.dist');
|
||||
|
||||
// Common paths used by release
|
||||
grunt.config.set('paths', {
|
||||
build: buildDirectory,
|
||||
releaseBuild: path.join(buildDirectory, 'release'),
|
||||
dist: distDirectory,
|
||||
releaseDist: path.join(distDirectory, 'release')
|
||||
});
|
||||
|
||||
// Load package.json so that we can create correctly versioned releases.
|
||||
grunt.config.set('pkg', grunt.file.readJSON('package.json'));
|
||||
|
||||
// grunt-contrib-copy
|
||||
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.
|
||||
// This is read from the `.npmignore` file and all patterns are inverted as we want to define what to include
|
||||
src: fs.readFileSync('.npmignore', 'utf8').split('\n').filter(Boolean).map(function (pattern) {
|
||||
return pattern[0] === '!' ? pattern.substr(1) : '!' + pattern;
|
||||
}),
|
||||
@ -613,6 +350,21 @@ const configureGrunt = function (grunt) {
|
||||
}]
|
||||
});
|
||||
|
||||
// grunt-contrib-compress
|
||||
grunt.config.set('compress.release', {
|
||||
options: {
|
||||
archive: '<%= paths.releaseDist %>/Ghost-<%= pkg.version %>.zip'
|
||||
},
|
||||
expand: true,
|
||||
cwd: '<%= paths.releaseBuild %>/',
|
||||
src: ['**']
|
||||
});
|
||||
|
||||
// grunt-contrib-clean
|
||||
grunt.config.set('clean.release', {
|
||||
src: ['<%= paths.releaseBuild %>/**']
|
||||
});
|
||||
|
||||
if (!grunt.option('skip-update')) {
|
||||
grunt.task
|
||||
.run('update_submodules:pinned')
|
||||
@ -630,5 +382,3 @@ const configureGrunt = function (grunt) {
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
module.exports = configureGrunt;
|
||||
|
15
package.json
15
package.json
@ -21,12 +21,17 @@
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"start": "node index",
|
||||
"dev": "DEBUG=ghost:* grunt dev",
|
||||
"test": "grunt validate",
|
||||
"test:slow": "grunt validate --reporter=mocha-slow-test-reporter",
|
||||
"ci": "grunt validate --verbose",
|
||||
"ci:regression": "grunt test-regression --verbose",
|
||||
"dev": "grunt",
|
||||
"dev:debug": "DEBUG=ghost:* grunt",
|
||||
"setup": "yarn install && knex-migrator init && grunt symlink && grunt init || (exit 0)",
|
||||
"main": "grunt shell:main && grunt subgrunt:init",
|
||||
"build": "grunt build",
|
||||
"test": "mocha --require=test/utils/overrides.js --exit --trace-warnings --recursive --timeout=60000",
|
||||
"test:all": "yarn test:unit && yarn test:acceptance && yarn test:regression",
|
||||
"test:unit": "mocha --require=test/utils/overrides.js --exit --trace-warnings './test/unit/**/*_spec.js' --timeout=7000",
|
||||
"test:acceptance": "mocha --require=test/utils/overrides.js --exit --trace-warnings './test/api-acceptance/**/*_spec.js' './test/frontend-acceptance/**/*_spec.js' --timeout=10000",
|
||||
"test:regression": "mocha --require=test/utils/overrides.js --exit --trace-warnings './test/regression/**/*_spec.js' --timeout=60000",
|
||||
"test:slow": "yarn test:unit --reporter=mocha-slow-test-reporter && yarn test:acceptance --reporter=mocha-slow-test-reporter",
|
||||
"lint:server": "eslint --ignore-path .eslintignore 'core/server/**/*.js' 'core/*.js' '*.js'",
|
||||
"lint:shared": "eslint --ignore-path .eslintignore 'core/shared/**/*.js'",
|
||||
"lint:frontend": "eslint --ignore-path .eslintignore 'core/frontend/**/*.js'",
|
||||
|
@ -9,6 +9,7 @@ const supertest = require('supertest');
|
||||
const testUtils = require('../../utils');
|
||||
const configUtils = require('../../utils/configUtils');
|
||||
const urlUtils = require('../../utils/urlUtils');
|
||||
const adminUtils = require('../../utils/admin-utils');
|
||||
const ghost = testUtils.startGhost;
|
||||
const i18n = require('../../../core/shared/i18n');
|
||||
const config = require('../../../core/shared/config');
|
||||
@ -44,6 +45,8 @@ describe('Admin Routing', function () {
|
||||
}
|
||||
|
||||
before(function () {
|
||||
adminUtils.stubClientFiles();
|
||||
|
||||
return ghost()
|
||||
.then(function () {
|
||||
request = supertest.agent(config.get('url'));
|
||||
|
@ -2,6 +2,7 @@ const should = require('should');
|
||||
const sinon = require('sinon');
|
||||
const _ = require('lodash');
|
||||
const testUtils = require('../../utils');
|
||||
const adminUtils = require('../../utils/admin-utils');
|
||||
const mockUtils = require('../../utils/mocks');
|
||||
const configUtils = require('../../utils/configUtils');
|
||||
const urlUtils = require('../../utils/urlUtils');
|
||||
@ -15,6 +16,7 @@ describe('Integration - Web - vhosts', function () {
|
||||
before(testUtils.integrationTesting.urlService.resetGenerators);
|
||||
before(testUtils.teardownDb);
|
||||
before(testUtils.setup('users:roles', 'posts'));
|
||||
before(adminUtils.stubClientFiles);
|
||||
|
||||
after(function () {
|
||||
configUtils.restore();
|
||||
|
@ -1,5 +1,3 @@
|
||||
require('../../core/server/overrides');
|
||||
|
||||
// Utility Packages
|
||||
const Promise = require('bluebird');
|
||||
const _ = require('lodash');
|
||||
|
17
test/utils/admin-utils.js
Normal file
17
test/utils/admin-utils.js
Normal file
@ -0,0 +1,17 @@
|
||||
const fs = require('fs-extra');
|
||||
const path = require('path');
|
||||
|
||||
const clientFiles = [
|
||||
'server/web/admin/views/default.html',
|
||||
'built/assets/ghost.js',
|
||||
'built/assets/ghost.css',
|
||||
'built/assets/vendor.js',
|
||||
'built/assets/vendor.css'
|
||||
];
|
||||
|
||||
module.exports.stubClientFiles = () => {
|
||||
clientFiles.forEach((file) => {
|
||||
const filePath = path.resolve(__dirname, '../../core/', file);
|
||||
fs.ensureFileSync(filePath);
|
||||
});
|
||||
};
|
3
test/utils/overrides.js
Normal file
3
test/utils/overrides.js
Normal file
@ -0,0 +1,3 @@
|
||||
process.env.NODE_ENV = process.env.NODE_ENV || 'testing';
|
||||
|
||||
require('../../core/server/overrides');
|
Loading…
Reference in New Issue
Block a user