diff --git a/.gitignore b/.gitignore index 114956a07d99b..296c6fa548de2 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ node_modules trash bundles target +/build .jruby .idea *.iml diff --git a/Gruntfile.js b/Gruntfile.js index 9e837033d02c6..3f3dbeca4ab9b 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -26,16 +26,7 @@ module.exports = function (grunt) { } }()), - nodeVersion: '0.10.35', - platforms: ['darwin-x64', 'linux-x64', 'linux-x86', 'windows'], - services: [ - ['launchd', '10.9'], - ['upstart', '1.5'], - ['systemd', 'default'], - ['sysv', 'lsb-3.1'] - ], - - devPlugins: 'devMode', + nodeVersion: '2.5.0', meta: { banner: '/*! <%= package.name %> - v<%= package.version %> - ' + @@ -44,16 +35,40 @@ module.exports = function (grunt) { ' * Copyright (c) <%= grunt.template.today("yyyy") %> <%= package.author.company %>;' + ' Licensed <%= package.license %> */\n' }, + lintThese: [ 'Gruntfile.js', '<%= root %>/tasks/**/*.js', '<%= src %>/**/*.js', '!<%= src %>/fixtures/**/*.js' - ] + ], + + deepModules: { + 'caniuse-db': '1.0.30000265', + 'chalk': '1.1.0', + 'glob': '4.5.3', + 'har-validator': '1.8.0', + 'json5': '0.4.0', + 'loader-utils': '0.2.11', + 'micromatch': '2.2.0', + 'postcss-normalize-url': '2.1.1', + 'postcss-reduce-idents': '1.0.2', + 'postcss-unique-selectors': '1.0.0', + 'postcss-minify-selectors': '1.4.6', + 'postcss-single-charset': '0.3.0', + 'regenerator': '0.8.36' + } }; grunt.config.merge(config); + config.userScriptsDir = __dirname + '/build/userScripts'; + // ensure that these run first, other configs need them + config.services = require('./tasks/config/services')(grunt); + config.platforms = require('./tasks/config/platforms')(grunt); + + grunt.config.merge(config); + // load plugins require('load-grunt-config')(grunt, { configPath: __dirname + '/tasks/config', @@ -66,4 +81,5 @@ module.exports = function (grunt) { // load task definitions grunt.task.loadTasks('tasks'); + grunt.task.loadTasks('tasks/build'); }; diff --git a/package.json b/package.json index 7e2e8217d1a5f..3fb6a8c7da449 100644 --- a/package.json +++ b/package.json @@ -56,12 +56,12 @@ "angular-nvd3": "panda01/angular-nvd3#kibana", "angular-route": "1.2.28", "ansicolors": "^0.3.2", - "auto-preload-rjscommon-deps-loader": "^1.0.4", "autoprefixer": "^5.2.0", "autoprefixer-loader": "^2.0.0", "babel": "^5.8.21", "babel-core": "^5.8.21", "babel-loader": "^5.3.2", + "babel-runtime": "^5.8.20", "bluebird": "^2.9.27", "boom": "^2.8.0", "bootstrap": "^3.3.5", @@ -96,7 +96,7 @@ "less": "^2.5.1", "less-loader": "^2.2.0", "lodash": "^3.10.0", - "marked": "^0.3.3", + "marked": "0.3.3", "memory-fs": "^0.2.0", "minimatch": "^2.0.8", "mkdirp": "^0.5.1", @@ -106,9 +106,10 @@ "numeral": "^1.5.3", "nvd3": "panda01/nvd3#kibana", "raw-loader": "^0.5.1", - "request": "^2.40.0", + "request": "^2.60.0", "requirefrom": "^0.2.0", "rimraf": "^2.4.1", + "rjs-repack-loader": "^1.0.6", "script-loader": "^0.6.1", "semver": "^4.3.6", "style-loader": "^0.12.3", @@ -126,9 +127,9 @@ "expect.js": "^0.3.1", "faker": "^1.1.0", "grunt": "^0.4.5", + "grunt-babel": "^5.0.1", "grunt-cli": "0.1.13", "grunt-contrib-clean": "^0.6.0", - "grunt-contrib-compress": "^0.13.0", "grunt-contrib-copy": "^0.8.0", "grunt-esvm": "^1.1.3", "grunt-karma": "^0.12.0", @@ -154,7 +155,8 @@ "portscanner": "^1.0.0", "simple-git": "^1.3.0", "sinon": "^1.15.4", - "source-map": "^0.4.4" + "source-map": "^0.4.4", + "wreck": "^6.1.0" }, "engines": { "node": ">=2" diff --git a/src/cli/index.build.js b/src/cli/index.build.js new file mode 100644 index 0000000000000..5a6cc6a7b3a92 --- /dev/null +++ b/src/cli/index.build.js @@ -0,0 +1,12 @@ +var _ = require('lodash'); +var fromRoot = require('requirefrom')('src/utils')('fromRoot'); + +var babelOpts = _.defaults({ + ignore: [ + fromRoot('src'), + /[\\\/](node_modules|bower_components)[\\\/]/ + ] +}, require('../optimize/babelOptions')); + +require('babel/register')(babelOpts); +require('./cli'); diff --git a/src/cli/plugin/__tests__/npmInstall.js b/src/cli/plugin/__tests__/npmInstall.js deleted file mode 100644 index 7a8ee7596b31b..0000000000000 --- a/src/cli/plugin/__tests__/npmInstall.js +++ /dev/null @@ -1,69 +0,0 @@ -var expect = require('expect.js'); -var nock = require('nock'); -var glob = require('glob'); -var rimraf = require('rimraf'); -var fs = require('fs'); -var { join } = require('path'); -var sinon = require('sinon'); - -var pluginLogger = require('../pluginLogger'); -var npmInstall = require('../npmInstall'); - -describe('kibana cli', function () { - - describe('plugin installer', function () { - - describe('npmInstall', function () { - - var testWorkingPath = join(__dirname, '.test.data'); - var logger; - var statSyncStub; - - beforeEach(function () { - statSyncStub = undefined; - logger = pluginLogger(false); - rimraf.sync(testWorkingPath); - sinon.stub(logger, 'log'); - sinon.stub(logger, 'error'); - }); - - afterEach(function () { - logger.log.restore(); - logger.error.restore(); - rimraf.sync(testWorkingPath); - if (statSyncStub) statSyncStub.restore(); - }); - - it('should throw an error if there is no package.json file in the archive', function () { - fs.mkdirSync(testWorkingPath); - - var errorStub = sinon.stub(); - return npmInstall(testWorkingPath, logger) - .catch(errorStub) - .then(function (data) { - expect(errorStub.called).to.be(true); - expect(errorStub.lastCall.args[0].message).to.match(/package.json/); - }); - }); - - it('should rethrow any errors other than "ENOENT" from fs.statSync', function () { - fs.mkdirSync(testWorkingPath); - - statSyncStub = sinon.stub(fs, 'statSync', function () { - throw new Error('This is unexpected.'); - }); - - var errorStub = sinon.stub(); - return npmInstall(testWorkingPath, logger) - .catch(errorStub) - .then(function (data) { - expect(errorStub.called).to.be(true); - expect(errorStub.lastCall.args[0].message).to.match(/This is unexpected./); - }); - }); - - }); - - }); - -}); diff --git a/src/cli/plugin/npmInstall.js b/src/cli/plugin/npmInstall.js deleted file mode 100644 index a8e1ee34c5de4..0000000000000 --- a/src/cli/plugin/npmInstall.js +++ /dev/null @@ -1,35 +0,0 @@ -var Promise = require('bluebird'); -var fs = require('fs'); -var path = require('path'); -var exec = require('child_process').exec; - -module.exports = function (dest, logger) { - return new Promise(function (resolve, reject) { - //throw an exception if package.json does not exist - try { - var packageFile = path.join(dest, 'package.json'); - fs.statSync(packageFile); - } catch (e) { - if (e.code !== 'ENOENT') throw e; - - return reject(new Error('Plugin does not contain package.json file')); - } - - var cmd = '"' + path.resolve(path.dirname(process.execPath), 'npm').replace(/\\/g, '/') + '" install --production'; - - var child = exec(cmd, { cwd: dest }); - child.on('error', function (err) { - reject(err); - }); - child.on('exit', function (code, signal) { - if (code === 0) { - resolve(); - } else { - reject(new Error('npm install failed with code ' + code)); - } - }); - - logger.error(child.stderr); - logger.log(child.stdout); - }); -}; diff --git a/src/cli/plugin/pluginInstaller.js b/src/cli/plugin/pluginInstaller.js index aedfc50dfb750..fae2d150d45ee 100644 --- a/src/cli/plugin/pluginInstaller.js +++ b/src/cli/plugin/pluginInstaller.js @@ -1,6 +1,5 @@ var pluginDownloader = require('./pluginDownloader'); var pluginCleaner = require('./pluginCleaner'); -var npmInstall = require('./npmInstall'); var fs = require('fs'); module.exports = { @@ -26,9 +25,6 @@ function install(settings, logger) { .then(function () { return downloader.download(); }) - .then(function () { - return npmInstall(settings.workingPath, logger); - }) .then(function (curious) { fs.renameSync(settings.workingPath, settings.pluginPath); logger.log('Plugin installation complete'); diff --git a/src/cli/serve/serve.js b/src/cli/serve/serve.js index 0af3b370a8a6b..6515aab6a07fe 100644 --- a/src/cli/serve/serve.js +++ b/src/cli/serve/serve.js @@ -6,6 +6,14 @@ let cwd = process.cwd(); let src = require('requirefrom')('src'); let fromRoot = src('utils/fromRoot'); +let canCluster; +try { + require.resolve('../cluster/ClusterManager'); + canCluster = true; +} catch (e) { + canCluster = false; +} + let pathCollector = function () { let paths = []; return function (path) { @@ -18,8 +26,9 @@ let pluginDirCollector = pathCollector(); let pluginPathCollector = pathCollector(); module.exports = function (program) { - program - .command('serve') + let command = program.command('serve'); + + command .description('Run the kibana server') .collectUnknownOptions() .option('-e, --elasticsearch ', 'Elasticsearch instance') @@ -47,11 +56,17 @@ module.exports = function (program) { pluginPathCollector, [] ) - .option('--plugins ', 'an alias for --plugin-dir', pluginDirCollector) - .option('--dev', 'Run the server with development mode defaults') - .option('--no-watch', 'Prevents automatic restarts of the server in --dev mode') + .option('--plugins ', 'an alias for --plugin-dir', pluginDirCollector); + + if (canCluster) { + command + .option('--dev', 'Run the server with development mode defaults') + .option('--no-watch', 'Prevents automatic restarts of the server in --dev mode'); + } + + command .action(async function (opts) { - if (opts.dev && !isWorker) { + if (canCluster && opts.dev && !isWorker) { // stop processing the action and handoff to cluster manager let ClusterManager = require('../cluster/ClusterManager'); new ClusterManager(opts); diff --git a/src/optimize/BaseOptimizer.js b/src/optimize/BaseOptimizer.js index 170a892f59b3f..f30f7b863cad7 100644 --- a/src/optimize/BaseOptimizer.js +++ b/src/optimize/BaseOptimizer.js @@ -108,7 +108,7 @@ class BaseOptimizer { { test: /\.(html|tmpl)$/, loader: 'raw' }, { test: /\.png$/, loader: 'url?limit=10000&name=[path][name].[ext]' }, { test: /\.(woff|woff2|ttf|eot|svg|ico)(\?|$)/, loader: 'file?name=[path][name].[ext]' }, - { test: /[\/\\]src[\/\\](plugins|ui)[\/\\].+\.js$/, loader: `auto-preload-rjscommon-deps${mapQ}` }, + { test: /[\/\\]src[\/\\](plugins|ui)[\/\\].+\.js$/, loader: `rjs-repack${mapQ}` }, { test: /\.js$/, exclude: /[\/\\](node_modules|bower_components)[\/\\]/, diff --git a/src/plugins/kibana/public/visualize/editor/styles/.editor.less b/src/plugins/kibana/public/visualize/editor/styles/_editor.less similarity index 100% rename from src/plugins/kibana/public/visualize/editor/styles/.editor.less rename to src/plugins/kibana/public/visualize/editor/styles/_editor.less diff --git a/src/plugins/kibana/public/visualize/styles/main.less b/src/plugins/kibana/public/visualize/styles/main.less index 4dc46a0b3c75a..19bd8b643bcaa 100644 --- a/src/plugins/kibana/public/visualize/styles/main.less +++ b/src/plugins/kibana/public/visualize/styles/main.less @@ -56,4 +56,4 @@ } -@import "../editor/styles/.editor.less"; +@import "../editor/styles/_editor.less"; diff --git a/tasks/build.js b/tasks/build.js deleted file mode 100644 index d0e796011ac48..0000000000000 --- a/tasks/build.js +++ /dev/null @@ -1,26 +0,0 @@ -module.exports = function (grunt) { - grunt.registerTask('build', [ - 'get_build_props', - 'clean:target', - 'clean:build', - 'less:build', - 'copy:kibana_src', - 'clean:noDistPlugins', - - 'webpack:build', - 'clean:unneeded_source_in_build', - - 'copy:dist', - 'dist_readme', - 'dist_package_json', - 'chmod_kibana', - 'make_plugin_dir', - 'copy:plugin_readme', - 'clean:test_from_node_modules', - 'download_node_binaries', - 'copy:versioned_dist', - 'create_services', - 'create_packages', - 'create_shasums' - ]); -}; diff --git a/tasks/build/archives.js b/tasks/build/archives.js new file mode 100644 index 0000000000000..2639ab86e28fc --- /dev/null +++ b/tasks/build/archives.js @@ -0,0 +1,39 @@ +module.exports = function createPackages(grunt) { + let { config } = grunt; + let { resolve } = require('path'); + let { execFile } = require('child_process'); + let { all, fromNode } = require('bluebird'); + + let buildPath = resolve(config.get('root'), 'build'); + let exec = async (cmd, args) => { + grunt.log.writeln(` > ${cmd} ${args.join(' ')}`); + await fromNode(cb => execFile(cmd, args, { cwd: buildPath }, cb)); + }; + + + let archives = async (platform) => { + // kibana.tar.gz + await exec('tar', ['-zchf', platform.tarPath, platform.buildName]); + + // kibana.zip + if (/windows/.test(platform.name)) { + await exec('zip', ['-rq', '-ll', platform.zipPath, platform.buildName]); + } else { + await exec('zip', ['-rq', platform.zipPath, platform.buildName]); + } + }; + + grunt.registerTask('_build:archives', function () { + + all( + grunt.config.get('platforms') + .map(async platform => { + + grunt.file.mkdir('target'); + await archives(platform); + }) + ) + .nodeify(this.async()); + + }); +}; diff --git a/tasks/build/cliIndex.js b/tasks/build/cliIndex.js new file mode 100644 index 0000000000000..d6850998c9228 --- /dev/null +++ b/tasks/build/cliIndex.js @@ -0,0 +1,13 @@ +module.exports = function (grunt) { + + var srcFile = 'build/kibana/src/cli/index.js'; + var buildFile = 'build/kibana/src/cli/index.build.js'; + var rename = require('fs').renameSync; + var unlink = require('fs').unlinkSync; + + grunt.registerTask('_build:cliIndex', function () { + unlink(srcFile); + rename(buildFile, srcFile); + }); + +}; diff --git a/tasks/build/downloadNodes.js b/tasks/build/downloadNodes.js new file mode 100644 index 0000000000000..3de1cdfc39f91 --- /dev/null +++ b/tasks/build/downloadNodes.js @@ -0,0 +1,85 @@ +module.exports = function (grunt) { + let { map, fromNode } = require('bluebird'); + let { resolve } = require('path'); + let { pluck } = require('lodash'); + let { createWriteStream } = require('fs'); + let { createGunzip } = require('zlib'); + let { Extract } = require('tar'); + let { rename } = require('fs'); + let wreck = require('wreck'); + + let platforms = grunt.config.get('platforms'); + let activeDownloads = []; + + let start = async (platform) => { + let finalDir = platform.nodeDir; + let downloadDir = `${finalDir}.temp`; + + if (grunt.file.isDir(platform.nodeDir)) { + grunt.log.ok(`${platform.name} exists`); + return; + } + + let resp = await fromNode(cb => { + let req = wreck.request('GET', platform.nodeUrl, null, function (err, resp) { + if (err) { + return cb(err); + } + + if (resp.statusCode !== 200) { + return cb(new Error(`${platform.nodeUrl} failed with a ${resp.statusCode} response`)); + } + + return cb(null, resp); + }); + }); + + // use an async iife to store promise for download + // then store platform in active downloads list + // which we will read from in the finish task + platform.downloadPromise = (async () => { + grunt.file.mkdir(downloadDir); + + if (platform.name === 'windows') { + await fromNode(cb => { + resp + .pipe(createWriteStream(resolve(downloadDir, 'node.exe'))) + .on('error', cb) + .on('finish', cb); + }); + } else { + await fromNode(cb => { + resp + .pipe(createGunzip()) + .on('error', cb) + .pipe(new Extract({ path: downloadDir, strip: 1 })) + .on('error', cb) + .on('end', cb); + }); + } + + await fromNode(cb => { + rename(downloadDir, finalDir, cb); + }); + }()); + + activeDownloads.push(platform); + + var bytes = parseInt(resp.headers['content-length'], 10) || 'unknown number of'; + var mb = ((bytes / 1024) / 1024).toFixed(2); + grunt.log.ok(`downloading ${platform.name} - ${mb} mb`); + }; + + grunt.registerTask('_build:downloadNodes:start', function () { + map(platforms, start).nodeify(this.async()); + }); + + grunt.registerTask('_build:downloadNodes:finish', function () { + map(activeDownloads, async (platform) => { + await platform.downloadPromise; + grunt.log.ok(`${platform.name} download complete`); + }) + .nodeify(this.async()); + }); +}; + diff --git a/tasks/get_build_props.js b/tasks/build/getProps.js similarity index 52% rename from tasks/get_build_props.js rename to tasks/build/getProps.js index 9c2dc15476195..458139b7df9d8 100644 --- a/tasks/get_build_props.js +++ b/tasks/build/getProps.js @@ -1,7 +1,7 @@ module.exports = function (grunt) { var exec = require('child_process').execSync; - grunt.registerTask('get_build_props', function () { + grunt.registerTask('_build:getProps', function () { grunt.config.set('buildSha', String(exec('git rev-parse HEAD')).trim()); - grunt.config.set('buildNum', parseFloat(exec('git log --format="%h" | wc -l')).trim()); + grunt.config.set('buildNum', parseFloat(String(exec('git log --format="%h" | wc -l')).trim())); }); }; diff --git a/tasks/build/index.js b/tasks/build/index.js new file mode 100644 index 0000000000000..3fe9e53fce41f --- /dev/null +++ b/tasks/build/index.js @@ -0,0 +1,29 @@ +module.exports = function (grunt) { + let { flatten } = require('lodash'); + + grunt.registerTask('build', flatten([ + '_build:getProps', + 'clean:build', + 'clean:target', + '_build:downloadNodes:start', + 'copy:devSource', + 'babel:build', + '_build:cliIndex', + '_build:installedPlugins', + '_build:packageJson', + '_build:readme', + '_build:installNpmDeps', + 'clean:testsFromModules', + 'clean:deepModules', + 'run:optimizeBuild', + 'stop:optimizeBuild', + '_build:downloadNodes:finish', + '_build:versionedLinks', + '_build:archives', + !grunt.option('os-packages') ? [] : [ + '_build:pleaseRun', + '_build:osPackages', + ], + '_build:shasums' + ])); +}; diff --git a/tasks/build/installNpmDeps.js b/tasks/build/installNpmDeps.js new file mode 100644 index 0000000000000..e7198706f5c58 --- /dev/null +++ b/tasks/build/installNpmDeps.js @@ -0,0 +1,14 @@ +module.exports = function (grunt) { + var { exec } = require('child_process'); + var { resolve } = require('path'); + + grunt.registerTask('_build:installNpmDeps', function () { + grunt.file.mkdir('build/kibana/node_modules'); + + exec('npm install --production --no-optional', { + cwd: grunt.config.process('<%= root %>/build/kibana') + }, this.async()); + }); +}; + + diff --git a/tasks/build/installedPlugins.js b/tasks/build/installedPlugins.js new file mode 100644 index 0000000000000..7d8d6618ff488 --- /dev/null +++ b/tasks/build/installedPlugins.js @@ -0,0 +1,5 @@ +module.exports = function (grunt) { + grunt.registerTask('_build:installedPlugins', function () { + grunt.file.mkdir('build/kibana/installedPlugins'); + }); +}; diff --git a/tasks/build/osPackages.js b/tasks/build/osPackages.js new file mode 100644 index 0000000000000..d62dcec88d2b1 --- /dev/null +++ b/tasks/build/osPackages.js @@ -0,0 +1,50 @@ +module.exports = function (grunt) { + let { resolve } = require('path'); + let { indexBy } = require('lodash'); + + let { config } = grunt; + let exec = require('../utils/exec'); + let targetDir = config.get('target'); + let version = config.get('pkg.version'); + let userScriptsDir = config.get('userScriptsDir'); + let servicesByName = indexBy(config.get('services'), 'name'); + + grunt.registerTask('_build:osPackages', function () { + grunt.config.get('platforms').forEach(({ name, buildDir }) => { + // TODO(sissel): Check if `fpm` is available + + let arch = /x64$/.test(name) ? 'x86_64' : 'i686'; + let fpm = args => exec('fpm', args); + + let args = [ + '--force', + '--package', targetDir, + '-s', 'dir', // input type + '--name', 'kibana', + '--version', version, + '--after-install', resolve(userScriptsDir, 'installer.sh'), + '--after-remove', resolve(userScriptsDir, 'remover.sh'), + '--config-files', '/opt/kibana/config/kibana.yml' + ]; + + let files = buildDir + '/=/opt/kibana'; + grunt.file.mkdir(targetDir); + + // kibana.rpm and kibana.deb + if (/linux-x(86|64)$/.test(name)) { + let sysv = servicesByName.sysv.outputDir + '/etc/=/etc/'; + fpm(args.concat('-t', 'rpm', '-a', arch, '--rpm-os', 'linux', files, sysv)); + fpm(args.concat('-t', 'deb', '-a', arch, files, sysv)); + return; + } + + // kibana.pkg + if (/darwin-x(86|64)$/.test(name)) { + let launchd = servicesByName.launchd.outputDir + '/=/'; + fpm(args.concat('-t', 'osxpkg', '-a', arch, files, launchd)); + return; + } + + }); + }); +}; diff --git a/tasks/build/packageJson.js b/tasks/build/packageJson.js new file mode 100644 index 0000000000000..edb8dd6b6d336 --- /dev/null +++ b/tasks/build/packageJson.js @@ -0,0 +1,25 @@ +module.exports = function (grunt) { + let { defaults } = require('lodash'); + + let pkg = grunt.config.get('pkg'); + let deepModules = grunt.config.get('deepModules'); + + grunt.registerTask('_build:packageJson', function () { + + grunt.file.write( + 'build/kibana/package.json', + JSON.stringify({ + name: pkg.name, + description: pkg.description, + keywords: pkg.keywords, + version: pkg.version, + build: { + number: grunt.config.get('buildNum'), + sha: grunt.config.get('buildSha') + }, + repository: pkg.repository, + dependencies: defaults({}, pkg.dependencies, deepModules) + }, null, ' ') + ); + }); +}; diff --git a/tasks/build/pleaserun.js b/tasks/build/pleaserun.js new file mode 100644 index 0000000000000..3b8b21da01b76 --- /dev/null +++ b/tasks/build/pleaserun.js @@ -0,0 +1,30 @@ +module.exports = function createServices(grunt) { + var { resolve } = require('path'); + + let exec = require('../utils/exec'); + let userScriptsPath = grunt.config.get('userScriptsPath'); + + grunt.registerTask('_build:pleaseRun', function () { + // TODO(sissel): Detect if 'pleaserun' is found, and provide a useful error + // to the user if it is missing. + + grunt.config.get('services').forEach(function (service) { + grunt.file.mkdir(service.outputDir); + exec('pleaserun', [ + '--install', + '--no-install-actions', + '--install-prefix', service.outputDir, + '--overwrite', + '--user', 'kibana', + '--sysv-log-path', '/var/log/kibana/', + '-p', service.name, + '-v', service.version, + '/opt/kibana/bin/kibana' + ]); + }); + + grunt.file.mkdir(userScriptsPath); + exec('please-manage-user', ['--output', userScriptsPath, 'kibana']); + + }); +}; diff --git a/tasks/build/readme.js b/tasks/build/readme.js new file mode 100644 index 0000000000000..a89039dba9f73 --- /dev/null +++ b/tasks/build/readme.js @@ -0,0 +1,37 @@ +let marked = require('marked'); +let Promise = require('bluebird'); +let { join } = require('path'); +let TextRenderer = require('marked-text-renderer'); +let _ = require('lodash'); +let fs = require('fs'); +let { AllHtmlEntities } = require('html-entities'); +let entities = new AllHtmlEntities(); + +TextRenderer.prototype.heading = function (text, level, raw) { + return '\n\n' + text + '\n' + _.map(text, function () { return '='; }).join('') + '\n'; +}; + +module.exports = function (grunt) { + + grunt.registerTask('_build:readme', function () { + let transform = function (input) { + let output = input.replace(/<\!\-\- [^\-]+ \-\->/g, '\n'); + output = marked(output); + return entities.decode(output); + }; + + marked.setOptions({ + renderer: new TextRenderer(), + tables: true, + breaks: false, + pedantic: false, + sanitize: false, + smartLists: true, + smartypants: false + }); + + grunt.file.write('build/kibana/README.txt', transform(grunt.file.read('README.md'))); + grunt.file.write('build/kibana/LICENSE.txt', transform(grunt.file.read('LICENSE.md'))); + }); + +}; diff --git a/tasks/create_shasums.js b/tasks/build/shasums.js similarity index 57% rename from tasks/create_shasums.js rename to tasks/build/shasums.js index 3a32c53948d92..c5dcedeba8f29 100644 --- a/tasks/create_shasums.js +++ b/tasks/build/shasums.js @@ -1,12 +1,9 @@ -var childProcess = require('child_process'); -var Promise = require('bluebird'); -var fs = require('fs'); -var readdir = Promise.promisify(fs.readdir); -var exec = Promise.promisify(childProcess.exec); -var _ = require('lodash'); -module.exports = function (grunt) { +var { promisify } = require('bluebird'); +var readdir = promisify(require('fs').readdir); +var exec = promisify(require('child_process').exec); - grunt.registerTask('create_shasums', function () { +module.exports = function (grunt) { + grunt.registerTask('_build:shasums', function () { var targetDir = grunt.config.get('target'); readdir(targetDir) diff --git a/tasks/build/versionedLinks.js b/tasks/build/versionedLinks.js new file mode 100644 index 0000000000000..c78b2b84bb1e5 --- /dev/null +++ b/tasks/build/versionedLinks.js @@ -0,0 +1,29 @@ +module.exports = function (grunt) { + let { basename, resolve } = require('path'); + let { forOwn } = require('lodash'); + + let exec = require('../utils/exec').silent; + + grunt.registerTask('_build:versionedLinks', function () { + let rootPath = grunt.config.get('root'); + + let buildFiles = grunt.file.expand('build/kibana/{*,.*}') + .map(function (file) { + return resolve(rootPath, file); + }); + + let ln = (source, link) => exec('ln', ['-s', source, link]); + + grunt.config.get('platforms').forEach(function (platform) { + grunt.file.mkdir(platform.buildDir); + + // link all files at the root of the build + buildFiles.forEach(function (source) { + ln(source, resolve(platform.buildDir, basename(source))); + }); + + // link the node modules + ln(platform.nodeDir, resolve(platform.buildDir, 'node')); + }); + }); +}; diff --git a/tasks/config/babel.js b/tasks/config/babel.js new file mode 100644 index 0000000000000..08a2e3a059a0b --- /dev/null +++ b/tasks/config/babel.js @@ -0,0 +1,19 @@ +let { defaults } = require('lodash'); +let babelOptions = require('requirefrom')('src')('optimize/babelOptions'); + +module.exports = { + build: { + options: defaults({ + optional: ['runtime'] + }, babelOptions), + src: [ + 'build/kibana/**/*.js', + '!**/public/**', + '!**/node_modules/**', + '!**/bower_components/**', + '!**/__tests__/**' + ], + dest: '.', + expand: true + } +}; diff --git a/tasks/config/clean.js b/tasks/config/clean.js index 291ba4e5f4bdf..db5f004f6a35d 100644 --- a/tasks/config/clean.js +++ b/tasks/config/clean.js @@ -1,6 +1,9 @@ module.exports = function (grunt) { + let modules = Object.keys(grunt.config.get('deepModules')); return { - build: '<%= build %>', - target: '<%= target %>' + build: 'build', + target: 'target', + testsFromModules: 'build/kibana/node_modules/**/*test*/**', + deepModules: 'build/kibana/node_modules/*/node_modules/**/{' + modules.join(',') + '}/**' }; }; diff --git a/tasks/config/compress.js b/tasks/config/compress.js deleted file mode 100644 index d38be88dc7629..0000000000000 --- a/tasks/config/compress.js +++ /dev/null @@ -1,49 +0,0 @@ -module.exports = function (grunt) { - var _ = require('lodash'); - var archiveName = function (plugin) { - return '<%= target %>/<%= pkg.name %>-' + (plugin ? 'plugin-' : '') + '<%= pkg.version %>'; - }; - - return _.mapValues({ - build_zip: archiveName() + '.zip', - build_tarball: archiveName() + '.tar.gz', - plugin: archiveName(true) + '.tar.gz' - }, function (filename, task) { - return { - options: { - archive: filename - }, - files: [ - { - flatten: true, - src: '<%= build %>/dist/bin/kibana', - dest: '<%= pkg.name %>/bin/kibana', - mode: 755 - }, - { - flatten: true, - src: '<%= build %>/dist/bin/kibana.bat', - dest: '<%= pkg.name %>/bin/kibana.bat' - }, - { - expand: true, - cwd: '<%= build %>/dist/config', - src: ['**/*'], - dest: '<%= pkg.name %>/config' - }, - { - expand: true, - cwd: '<%= build %>/dist/lib', - src: ['**/*'], - dest: '<%= pkg.name %>/lib' - }, - { - expand: true, - cwd: '<%= build %>/dist', - src: ['*.txt'], - dest: '<%= pkg.name %>' - } - ] - }; - }); -}; diff --git a/tasks/config/copy.js b/tasks/config/copy.js index a1d3c629983fc..d91005f8968d8 100644 --- a/tasks/config/copy.js +++ b/tasks/config/copy.js @@ -1,122 +1,20 @@ module.exports = function (grunt) { - var version = grunt.config.get('pkg.version'); - var platforms = grunt.config.get('platforms'); - var config = { - - kibana_src: { - expand: true, - cwd: '<%= app %>', - src: '**', - dest: '<%= build %>/src/' - }, - - server_src: { - files: [ - { - src: '<%= root %>/package.json', - dest: '<%= build %>/kibana/package.json' - }, - { - src: '<%= server %>/app.js', - dest: '<%= build %>/kibana/app.js' - }, - { - src: '<%= server %>/index.js', - dest: '<%= build %>/kibana/index.js' - }, - { - expand: true, - cwd: '<%= server %>/bin/', - src: '**', - dest: '<%= build %>/kibana/bin' - }, - { - expand: true, - cwd: '<%= server %>/config/', - src: '*.yml', - dest: '<%= build %>/kibana/config' - }, - { - expand: true, - cwd: '<%= server %>/lib/', - src: '**', - dest: '<%= build %>/kibana/lib' - }, - { - expand: true, - cwd: '<%= server %>/plugins/', - src: '**', - dest: '<%= build %>/kibana/plugins' - }, - { - expand: true, - cwd: '<%= server %>/routes/', - src: '**', - dest: '<%= build %>/kibana/routes' - }, - { - expand: true, - cwd: '<%= server %>/views/', - src: '**', - dest: '<%= build %>/kibana/views' - } - ] - }, - - dist: { - options: { mode: true }, - files: [ - { - expand: true, - cwd: '<%= build %>/kibana', - src: '**', - dest: '<%= build %>/dist/kibana/src' - }, - { - expand: true, - cwd: '<%= server %>/config/', - src: 'kibana.yml', - dest: '<%= build %>/dist/kibana/config/' - }, - { - expand: true, - cwd: '<%= bowerComponentsDir %>/ace-builds/src-noconflict/', - src: 'worker-json.js', - dest: '<%= build %>/dist/kibana/src/public/' - } - ] - }, - - versioned_dist: { + return { + devSource: { options: { mode: true }, - files: [] + src: [ + 'src/**', + 'bin/**', + 'config/kibana.yml', + '!src/**/__tests__/**', + '!src/testUtils/**', + '!src/fixtures/**', + '!src/plugins/devMode/**', + '!src/plugins/testsBundle/**', + '!src/cli/cluster/**', + ], + dest: 'build/kibana', + expand: true }, - - plugin_readme: { - files: [ - { - src: '<%= build %>/kibana/public/plugins/README.txt', - dest: '<%= build %>/dist/kibana/plugins/README.txt' - } - ] - } - }; - - platforms.forEach(function (platform) { - config.versioned_dist.files.push({ - expand: true, - cwd: '<%= build %>/dist/kibana', - src: '**', - dest: '<%= build %>/dist/kibana-' + version + '-' + platform - }); - config.versioned_dist.files.push({ - expand: true, - cwd: '<%= root %>/.node_binaries/' + platform, - src: '**', - dest: '<%= build %>/dist/kibana-' + version + '-' + platform + '/node' - }); - }); - - return config; }; diff --git a/tasks/config/platforms.js b/tasks/config/platforms.js new file mode 100644 index 0000000000000..0d93bc6dd866a --- /dev/null +++ b/tasks/config/platforms.js @@ -0,0 +1,37 @@ +module.exports = function (grunt) { + let { resolve } = require('path'); + + let version = grunt.config.get('pkg.version'); + let nodeVersion = grunt.config.get('nodeVersion'); + let rootPath = grunt.config.get('root'); + let baseUri = `https://iojs.org/dist/v${nodeVersion}`; + + return [ + 'darwin-x64', + 'linux-x64', + 'linux-x86', + 'windows' + ].map(function (name) { + let win = name === 'windows'; + + let nodeUrl = win ? `${baseUri}/win-x86/iojs.exe` : `${baseUri}/iojs-v${nodeVersion}-${name}.tar.gz`; + let nodeDir = resolve(rootPath, `.node_binaries/${nodeVersion}/${name}`); + + let buildName = `kibana-${version}-${name}`; + let buildDir = resolve(rootPath, `build/${buildName}`); + + let tarName = `${buildName}.tar.gz`; + let tarPath = resolve(rootPath, `target/${tarName}`); + + let zipName = `${buildName}.zip`; + let zipPath = resolve(rootPath, `target/${zipName}`); + + return { + name, win, + nodeUrl, nodeDir, + buildName, buildDir, + tarName, tarPath, + zipName, zipPath, + }; + }); +}; diff --git a/tasks/config/run.js b/tasks/config/run.js index 56ae1a7da48c5..056768f0f0bcc 100644 --- a/tasks/config/run.js +++ b/tasks/config/run.js @@ -17,6 +17,21 @@ module.exports = function (grunt) { '--optimize.tests=true', '--optimize.lazy=false' ] + }, + + optimizeBuild: { + options: { + wait: false, + ready: /Optimization .+ complete/, + quiet: true + }, + cmd: './build/kibana/bin/kibana', + args: [ + '--env.name=production', + '--logging.json=false', + '--plugins.initialize=false', + '--server.autoListen=false' + ] } }; diff --git a/tasks/config/s3.js b/tasks/config/s3.js index 21cb599c0f018..edea5f487f585 100644 --- a/tasks/config/s3.js +++ b/tasks/config/s3.js @@ -1,31 +1,27 @@ -var createPackages = require('../create_packages'); var _ = require('lodash'); -var getBaseNames = createPackages.getBaseNames; module.exports = function (grunt) { - var upload = _(getBaseNames(grunt)) - .map(function (basename) { - return [ - basename + '.tar.gz', - basename + '.tar.gz.sha1.txt', - basename + '.zip', - basename + '.zip.sha1.txt' - ]; - }) - .flattenDeep() - .map(function (filename) { - return { - src: 'target/' + filename, - dest: 'kibana/kibana/' + filename - }; - }) - .value(); + var { config } = grunt; return { release: { bucket: 'download.elasticsearch.org', access: 'private', - // debug: true, // uncommment to prevent actual upload - upload: upload + debug: false, + upload: config.get('platforms') + .reduce(function (files, platform) { + return files.concat( + platform.tarName, + platform.tarName + '.sha1.txt', + platform.zipName, + platform.zipName + '.sha1.txt' + ); + }, []) + .map(function (filename) { + return { + src: 'target/' + filename, + dest: 'kibana/kibana/' + filename + }; + }) } }; }; diff --git a/tasks/config/services.js b/tasks/config/services.js new file mode 100644 index 0000000000000..8b74b36c0319e --- /dev/null +++ b/tasks/config/services.js @@ -0,0 +1,14 @@ +module.exports = function (grunt) { + let { resolve } = require('path'); + let rootDir = grunt.config.get('root'); + + return [ + ['launchd', '10.9'], + ['upstart', '1.5'], + ['systemd', 'default'], + ['sysv', 'lsb-3.1'] + ] + .map(function ([ name, version ]) { + return { name, version, outputDir: resolve(rootDir, `build/services/${name}`) }; + }); +}; diff --git a/tasks/create_packages.js b/tasks/create_packages.js deleted file mode 100644 index b706c02684f4a..0000000000000 --- a/tasks/create_packages.js +++ /dev/null @@ -1,76 +0,0 @@ -/* eslint camelcase:0 */ - -var child_process = require('child_process'); -var Promise = require('bluebird'); -var { join } = require('path'); -var mkdirp = Promise.promisifyAll(require('mkdirp')); - -var execFile = Promise.promisify(child_process.execFile); - -var getBaseNames = function (grunt) { - var packageName = grunt.config.get('pkg.name'); - var version = grunt.config.get('pkg.version'); - var platforms = grunt.config.get('platforms'); - return platforms.map(function (platform) { - return packageName + '-' + version + '-' + platform; - }); -}; - -function createPackages(grunt) { - grunt.registerTask('create_packages', function () { - var done = this.async(); - var target = grunt.config.get('target'); - var distPath = join(grunt.config.get('build'), 'dist'); - var version = grunt.config.get('pkg.version'); - - var createPackage = function (name) { - var options = { cwd: distPath }; - var archiveName = join(target, name); - var commands = []; - var arch = /x64$/.test(name) ? 'x86_64' : 'i686'; - - var fpm_options = [ 'fpm', '-f', '-p', target, '-s', 'dir', '-n', 'kibana', '-v', version, - '--after-install', join(distPath, 'user', 'installer.sh'), - '--after-remove', join(distPath, 'user', 'remover.sh'), - '--config-files', '/opt/kibana/config/kibana.yml' ]; - var fpm_files = join(distPath, name) + '/=/opt/kibana'; - - // kibana.tar.gz - commands.push([ 'tar', '-zcf', archiveName + '.tar.gz', name ]); - - // kibana.zip - if (/windows/.test(name)) { - commands.push([ 'zip', '-rq', '-ll', archiveName + '.zip', name ]); - } else { - commands.push([ 'zip', '-rq', archiveName + '.zip', name ]); - } - - if (grunt.option('os-packages')) { - // TODO(sissel): Add before-install scripts to create kibana user - // TODO(sissel): Check if `fpm` is available - if (/linux-x(86|64)$/.test(name)) { - // kibana.rpm and kibana.deb - var sysv_init = join(distPath, 'services', 'sysv') + '/etc/=/etc/'; - commands.push(fpm_options.concat(['-t', 'rpm', '-a', arch, '--rpm-os', 'linux', fpm_files, sysv_init])); - commands.push(fpm_options.concat(['-t', 'deb', '-a', arch, fpm_files, sysv_init])); - } else if (/darwin-x(86|64)$/.test(name)) { - // kibana.pkg - var launchd = join(distPath, 'services', 'launchd') + '/=/'; - commands.push(fpm_options.concat(['-t', 'osxpkg', '-a', arch, fpm_files, launchd])); - } - } - - return mkdirp.mkdirpAsync(target) - .then(function (arg) { - return Promise.map(commands, function (cmd) { - return execFile(cmd.shift(), cmd, options); - }); - }, function (err) { console.log('Failure on ' + name + ': ' + err); }); - }; - - Promise.map(getBaseNames(grunt), createPackage).finally(done); - }); -} - -module.exports = createPackages; -createPackages.getBaseNames = getBaseNames; diff --git a/tasks/create_services.js b/tasks/create_services.js deleted file mode 100644 index 52655a56cccf0..0000000000000 --- a/tasks/create_services.js +++ /dev/null @@ -1,51 +0,0 @@ -/* eslint camelcase:0 */ - -var childProcess = require('child_process'); -var Promise = require('bluebird'); -var { join } = require('path'); -var mkdirp = Promise.promisifyAll(require('mkdirp')); -var execFile = Promise.promisify(childProcess.execFile); - -function createServices(grunt) { - grunt.registerTask('create_services', function () { - var done = this.async(); - var target = grunt.config.get('target'); - var distPath = join(grunt.config.get('build'), 'dist'); - var services = grunt.config.get('services'); - - var createService = function (arg) { - var service = arg[0]; - var service_version = arg[1]; - var options = { cwd: distPath }; - var output = join(distPath, 'services', service); - var pleaserun_args = ['--install', '--no-install-actions', - '--install-prefix', output, '--overwrite', - '--user', 'kibana', - '--sysv-log-path', '/var/log/kibana/', - '-p', service, '-v', service_version, - '/opt/kibana/bin/kibana']; - - return mkdirp.mkdirpAsync(target) - .then(function (arg) { - return execFile('pleaserun', pleaserun_args, options); - }, function (err) { console.log('pleaserun failed: ' + err + '. Args: ' + pleaserun_args.join(' ')); }); - }; - - // TODO(sissel): Detect if 'pleaserun' is found, and provide a useful error - // to the user if it is missing. - mkdirp.mkdirpAsync(distPath) - .then(function () { - return Promise.map(services, createService); - }) - .then(function (arg) { - // Create the user-management scripts - var output = join(distPath, 'user'); - return mkdirp.mkdirpAsync(output).then(function () { - return execFile('please-manage-user', ['--output', output, 'kibana'], { cwd: distPath }); - }); - }, function (err) { console.log('please-manage-user failed: ' + err + '.'); }) - .finally(done); - }); -} - -module.exports = createServices; diff --git a/tasks/dist_package_json.js b/tasks/dist_package_json.js deleted file mode 100644 index fca775f089e6a..0000000000000 --- a/tasks/dist_package_json.js +++ /dev/null @@ -1,19 +0,0 @@ -module.exports = function (grunt) { - grunt.registerTask('dist_package_json', function () { - var path = grunt.config.process('<%= build %>/kibana/package.json'); - var pkg = grunt.config.get('pkg'); - - grunt.file.write(path, JSON.stringify({ - name: pkg.name, - description: pkg.description, - keywords: pkg.keywords, - version: pkg.version, - build: { - number: grunt.config.get('buildNum'), - sha: grunt.config.get('buildSha') - }, - repository: pkg.repository, - dependencies: pkg.dependencies - }, null, ' ')); - }); -}; diff --git a/tasks/dist_readme.js b/tasks/dist_readme.js deleted file mode 100644 index 23445a485bdfd..0000000000000 --- a/tasks/dist_readme.js +++ /dev/null @@ -1,61 +0,0 @@ -var marked = require('marked'); -var Promise = require('bluebird'); -var { join } = require('path'); -var TextRenderer = require('marked-text-renderer'); -var _ = require('lodash'); -var fs = require('fs'); -var { AllHtmlEntities } = require('html-entities'); -var entities = new AllHtmlEntities(); - -var readFile = Promise.promisify(fs.readFile); -var writeFile = Promise.promisify(fs.writeFile); - -TextRenderer.prototype.heading = function (text, level, raw) { - return '\n\n' + text + '\n' + _.map(text, function () { return '='; }).join('') + '\n'; -}; - -var process = function (input) { - var output = input.replace(/<\!\-\- [^\-]+ \-\->/g, '\n'); - output = marked(output); - return entities.decode(output); -}; - -module.exports = function (grunt) { - - grunt.registerTask('dist_readme', function () { - var done = this.async(); - var root = grunt.config.get('root'); - var build = grunt.config.get('build'); - - var srcReadme = join(root, 'README.md'); - var distReadme = join(build, 'dist', 'kibana', 'README.txt'); - - var srcLicense = join(root, 'LICENSE.md'); - var distLicense = join(build, 'dist', 'kibana', 'LICENSE.txt'); - - marked.setOptions({ - renderer: new TextRenderer(), - tables: true, - breaks: false, - pedantic: false, - sanitize: false, - smartLists: true, - smartypants: false - }); - - readFile(srcReadme, 'utf-8') - .then(function (data) { - return writeFile(distReadme, process(data.toString())); - }) - .then(function () { - return readFile(srcLicense, 'utf-8'); - }) - .then(function (data) { - return writeFile(distLicense, process(data.toString())); - }) - .then(done) - .catch(done); - - }); - -}; diff --git a/tasks/download_node_binaries.js b/tasks/download_node_binaries.js deleted file mode 100644 index 758803c01d31c..0000000000000 --- a/tasks/download_node_binaries.js +++ /dev/null @@ -1,65 +0,0 @@ -var _ = require('lodash'); -var zlib = require('zlib'); -var tar = require('tar'); -var request = require('request'); -var mkdirp = require('mkdirp'); -var fs = require('fs'); -var { join } = require('path'); -var filesPatern = _.template('node-v<%- version %>-<%- platform %>.tar.gz'); -var urlPattern = _.template('http://nodejs.org/dist/v<%- version %>/<%- file %>'); -var Promise = require('bluebird'); - -module.exports = function (grunt) { - grunt.registerTask('download_node_binaries', 'Download the node.js binaries', function () { - var platforms = _.without(grunt.config.get('platforms'), 'windows'); - var rootPath = grunt.config.get('root'); - var version = grunt.config.get('nodeVersion'); - - var handle404 = function (response) { - if (response.statusCode !== 200) { - throw new Error(response.request.href + ' failed with a ' + response.statusCode); - } - }; - - var downloadWindows = function (cb) { - return new Promise(function (resolve, reject) { - var dest = join(rootPath, '.node_binaries', 'windows'); - fs.stat(dest, function (err) { - if (!err) return resolve(); // skip downloading if we already have them - var url = urlPattern({ version: version, file: 'node.exe'}); - mkdirp(dest, function (err) { - if (err) return reject(err); - var out = fs.createWriteStream(join(dest, 'node.exe')); - out.on('close', resolve).on('error', reject); - var req = request.get(url); - req.on('response', handle404); - req.pipe(out); - }); - }); - }); - }; - - var download = function (platform) { - return new Promise(function (resolve, reject) { - var dest = join(rootPath, '.node_binaries', platform); - fs.stat(dest, function (err) { - if (!err) return resolve(); // skip downloading if we already have them - var file = filesPatern({ version: version, platform: platform }); - var url = urlPattern({ version: version, file: file }); - mkdirp(dest, function (err) { - if (err) return reject(err); - var unzip = zlib.createGunzip(); - var out = new tar.Extract({ path: dest, strip: 1 }); - out.on('close', resolve).on('error', reject); - var req = request.get(url); - req.on('response', handle404); - req.pipe(unzip).pipe(out); - }); - }); - }); - }; - - return Promise.map(platforms, download).then(downloadWindows).nodeify(this.async()); - }); -}; - diff --git a/tasks/licenses.js b/tasks/licenses.js index d0dabe0adf26f..b7977b418630b 100644 --- a/tasks/licenses.js +++ b/tasks/licenses.js @@ -10,7 +10,7 @@ module.exports = function (grunt) { var done = this.async(); var result = {}; - var options = {start: process.cwd(), json: true }; + var options = { start: process.cwd(), json: true }; var checkQueueLength = 2; function processPackage(info, dependency) { diff --git a/tasks/npm_install_kibana.js b/tasks/npm_install_kibana.js deleted file mode 100644 index b70a878503512..0000000000000 --- a/tasks/npm_install_kibana.js +++ /dev/null @@ -1,21 +0,0 @@ -module.exports = function (grunt) { - var childProcess = require('child_process'); - var { join } = require('path'); - - grunt.registerTask('npm_install_kibana', 'NPM install kibana server into dist', function () { - var done = this.async(); - var cwd = join(grunt.config.get('build'), 'dist', 'kibana', 'src'); - var command = 'npm install --production --no-optional'; - var options = { cwd: cwd }; - childProcess.exec(command, options, function (err, stdout, stderr) { - if (err) { - grunt.log.error(stderr); - return done(err); - } - grunt.log.writeln(stdout); - return done(); - }); - }); -}; - - diff --git a/tasks/plugins.js b/tasks/plugins.js deleted file mode 100644 index 43d06f04be103..0000000000000 --- a/tasks/plugins.js +++ /dev/null @@ -1,27 +0,0 @@ -module.exports = function (grunt) { - grunt.registerTask('make_plugin_dir', function () { - var dir = grunt.config.process('<%= build %>/dist/kibana/plugins'); - grunt.file.mkdir(dir); - }); - - grunt.registerTask('describe_bundled_plugins', function () { - var configKey = 'bundled_plugin_ids'; - var file = grunt.config.process('<%= build %>/dist/kibana/config/kibana.yml'); - var idList = grunt.config.get('bundled_plugin_module_ids').map(function (id) { - return ' - ' + id; - }).join('\n'); - - var contents = grunt.file.read(file); - if (contents.indexOf(configKey) !== -1) { - grunt.log.error('bundled plugin ids already written to config/kibana.yml'); - return; - } - - contents += - '\n# Plugins that are included in the build, and no longer found in the plugins/ folder' + - '\n' + configKey + ':' + - '\n' + idList; - - grunt.file.write(file, contents); - }); -}; diff --git a/tasks/release.js b/tasks/release.js index b6d4207875cc8..563b57673537d 100644 --- a/tasks/release.js +++ b/tasks/release.js @@ -1,18 +1,51 @@ module.exports = function (grunt) { + var readline = require('readline'); + // build, then zip and upload to s3 grunt.registerTask('release', [ - 'distribute:load_s3_config', + '_release:confirmUpload', + '_release:loadS3Config', 'build', 's3:release', + '_release:complete' ]); + grunt.registerTask('_release:confirmUpload', function () { + var rl = readline.createInterface({ + input: process.stdin, + output: process.stdout + }); + + rl.on('close', this.async()); + rl.question('Do you want to actually upload the files to s3 after building?, [N/y] ', function (resp) { + var debug = resp.toLowerCase().trim()[0] !== 'y'; + grunt.config.set('s3.release.debug', debug); + rl.close(); + }); + }); + // collect the key and secret from the .aws-config.json file, finish configuring the s3 task - grunt.registerTask('distribute:load_s3_config', function () { + grunt.registerTask('_release:loadS3Config', function () { var config = grunt.file.readJSON('.aws-config.json'); grunt.config('s3.options', { key: config.key, secret: config.secret }); }); + + grunt.registerTask('_release:complete', function () { + grunt.log.ok('Builds released'); + grunt.log.write( +` +${grunt.config.get('platforms').reduce((t, p) => { + return ( +`${t}https://download.elastic.co/kibana/kibana/${p.buildName}.tar.gz +https://download.elastic.co/kibana/kibana/${p.buildName}.zip +` + ); +}, '')} +` +); + }); }; diff --git a/tasks/utils/exec.js b/tasks/utils/exec.js new file mode 100644 index 0000000000000..ec63ada6f9afd --- /dev/null +++ b/tasks/utils/exec.js @@ -0,0 +1,26 @@ +let { execFileSync } = require('child_process'); + +function exec(cmd, args, opts) { + console.log(' >', cmd, args.join(' ')); + exec.silent(cmd, args, opts); +}; + +exec.silent = function (cmd, args, opts) { + opts = opts || {}; + if (!opts.stdio) opts.stdio = ['ignore', 1, 2]; + try { + execFileSync(cmd, args, opts); + } catch (e) { + if (opts.stdio[1] !== 1) { + console.log(e.stdout + ''); + } + + if (opts.stdio[2] !== 2) { + console.log(e.stderr + ''); + } + + throw e; + } +}; + +module.exports = exec;