Merge pull request #4675 from spalger/fix/build

Fix build
This commit is contained in:
Joe Fleming 2015-08-17 14:42:37 -05:00
commit ce19ecc2a2
43 changed files with 617 additions and 680 deletions

1
.gitignore vendored
View file

@ -5,6 +5,7 @@ node_modules
trash
bundles
target
/build
.jruby
.idea
*.iml

View file

@ -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');
};

View file

@ -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"

12
src/cli/index.build.js Normal file
View file

@ -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');

View file

@ -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./);
});
});
});
});
});

View file

@ -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);
});
};

View file

@ -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');

View file

@ -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 <uri>', 'Elasticsearch instance')
@ -47,11 +56,17 @@ module.exports = function (program) {
pluginPathCollector,
[]
)
.option('--plugins <path>', '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 <path>', '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);

View file

@ -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)[\/\\]/,

View file

@ -56,4 +56,4 @@
}
@import "../editor/styles/.editor.less";
@import "../editor/styles/_editor.less";

View file

@ -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'
]);
};

39
tasks/build/archives.js Normal file
View file

@ -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());
});
};

13
tasks/build/cliIndex.js Normal file
View file

@ -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);
});
};

View file

@ -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());
});
};

View file

@ -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()));
});
};

29
tasks/build/index.js Normal file
View file

@ -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'
]));
};

View file

@ -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());
});
};

View file

@ -0,0 +1,5 @@
module.exports = function (grunt) {
grunt.registerTask('_build:installedPlugins', function () {
grunt.file.mkdir('build/kibana/installedPlugins');
});
};

50
tasks/build/osPackages.js Normal file
View file

@ -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;
}
});
});
};

View file

@ -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, ' ')
);
});
};

30
tasks/build/pleaserun.js Normal file
View file

@ -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']);
});
};

37
tasks/build/readme.js Normal file
View file

@ -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')));
});
};

View file

@ -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)

View file

@ -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'));
});
});
};

19
tasks/config/babel.js Normal file
View file

@ -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
}
};

View file

@ -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(',') + '}/**'
};
};

View file

@ -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 %>'
}
]
};
});
};

View file

@ -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: {
return {
devSource: {
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/'
}
]
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
},
versioned_dist: {
options: { mode: true },
files: []
},
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;
};

37
tasks/config/platforms.js Normal file
View file

@ -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,
};
});
};

View file

@ -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'
]
}
};

View file

@ -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
};
})
}
};
};

14
tasks/config/services.js Normal file
View file

@ -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}`) };
});
};

View file

@ -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;

View file

@ -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;

View file

@ -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, ' '));
});
};

View file

@ -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);
});
};

View file

@ -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());
});
};

View file

@ -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) {

View file

@ -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();
});
});
};

View file

@ -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);
});
};

View file

@ -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
`
);
}, '')}
`
);
});
};

26
tasks/utils/exec.js Normal file
View file

@ -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;