[7.x] Update gulp related packages (major) (#46665 and #47421) (#47409)

* Update gulp related packages (major) (#46665)

* Update gulp related packages

* ts-ify and gulp4-ify x-pack tasks, remove unused canvas tasks

* remove unnecessary gulp.TaskFunction usage

* fix old references

* update renovate config

* move constants into helpers directory

* typo

* compact tasks a bit, remove unnecessary paths

* fix build directories

* deprecate testonly task

* rather than justifying an unjustifiable ts-ignore, ts-ify the imported module

* update renovate config

* update browser download tests to mock axios

* add root index.d.ts to tsconfig

* export BrowserType

* remove unnecessary `@ts-ignore`

* use consistent casing

* correct import for createAutoJUnitReporter

* Update gulp related packages (#47421)

(cherry picked from commit 35751f9828)
This commit is contained in:
Spencer 2019-10-06 22:49:28 -07:00 committed by GitHub
parent 8ffd187c99
commit ef6727cc52
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
51 changed files with 830 additions and 1128 deletions

View file

@ -344,6 +344,7 @@
"@types/supertest": "^2.0.5",
"@types/type-detect": "^4.0.1",
"@types/uuid": "^3.4.4",
"@types/vinyl-fs": "^2.4.11",
"@types/zen-observable": "^0.8.0",
"@typescript-eslint/eslint-plugin": "1.13.0",
"@typescript-eslint/parser": "1.13.0",

View file

@ -0,0 +1,26 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
export function babelRegister(): void;
export function resolveKibanaPath(path: string): string;
export function readFtrConfigFile(path: string): any;
export function run(
task: 'build' | 'start' | 'testAll' | 'testBrowser' | 'testServer' | 'postinstall',
options: any
): Promise<void>;

View file

@ -21,7 +21,7 @@
"globby": "^8.0.1",
"gulp-babel": "^8.0.0",
"gulp-rename": "1.4.0",
"gulp-zip": "4.2.0",
"gulp-zip": "5.0.1",
"inquirer": "^1.2.2",
"minimatch": "^3.0.4",
"node-sass": "^4.9.4",

View file

@ -0,0 +1,4 @@
{
"extends": "../../tsconfig.json",
"include": ["lib/index.d.ts"]
}

20
packages/kbn-test/index.d.ts vendored Normal file
View file

@ -0,0 +1,20 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
export * from './src/index';

View file

@ -17,18 +17,26 @@
* under the License.
*/
// @ts-ignore not typed yet
export { runTestsCli, startServersCli } from './functional_tests/cli';
// @ts-ignore not typed yet
export { runTests, startServers } from './functional_tests/tasks';
// @ts-ignore not typed yet
export { OPTIMIZE_BUNDLE_DIR, KIBANA_ROOT } from './functional_tests/lib/paths';
// @ts-ignore not typed yet
export { esTestConfig, createEsTestCluster } from './es';
// @ts-ignore not typed yet
export { kbnTestConfig, kibanaServerTestUser, kibanaTestUser, adminTestUser } from './kbn';
// @ts-ignore not typed yet
export { setupUsers, DEFAULT_SUPERUSER_PASS } from './functional_tests/lib/auth';
// @ts-ignore not typed yet
export { readConfigFile } from './functional_test_runner/lib/config/read_config_file';
// @ts-ignore not typed yet
export { runFtrCli } from './functional_test_runner/cli';

View file

@ -2,6 +2,7 @@
"extends": "../../tsconfig.json",
"include": [
"types/**/*",
"src/functional_test_runner/**/*"
"src/**/*",
"index.d.ts"
]
}

25
src/dev/index.ts Normal file
View file

@ -0,0 +1,25 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
// @ts-ignore not typed yet
export { createAutoJUnitReporter } from './auto_junit_reporter';
// @ts-ignore not typed yet
export { setupJUnitReportGeneration } from './junit_report_generation';
// @ts-ignore not typed yet
export { runMochaCli } from './run_mocha_cli';

View file

@ -17,6 +17,9 @@
* under the License.
*/
// @ts-ignore not typed yet
export { createAutoJUnitReporter } from './auto_junit_reporter';
// @ts-ignore not typed yet
export { setupJUnitReportGeneration } from './junit_report_generation';
// @ts-ignore not typed yet
export { runMochaCli } from './run_mocha_cli';

View file

@ -18,25 +18,30 @@
*/
import vfs from 'vinyl-fs';
import { ToolingLog } from '@kbn/dev-utils';
const NOTICE_COMMENT_RE = /\/\*[\s\n\*]*@notice([\w\W]+?)\*\//g;
const NEWLINE_RE = /\r?\n/g;
interface Options {
/**
* Name to print at the top of the notice
*/
productName: string;
/**
* absolute path to the repo to search for @notice comments
*/
directory: string;
log: ToolingLog;
}
/**
* Generates the text for the NOTICE.txt file at the root of the
* repo which details the licenses for code that is copied/vendored
* into the repository.
*
* @param {Object} options
* @property {string} options.productName Name to print at the top of the notice
* @property {ToolingLog} options.log
* @property {string} options.directory absolute path to the repo to search for @notice comments
* @return {string}
*/
export async function generateNoticeFromSource({ productName, directory, log }) {
const globs = [
'**/*.{js,less,css,ts}',
];
export async function generateNoticeFromSource({ productName, directory, log }: Options) {
const globs = ['**/*.{js,less,css,ts}'];
const options = {
cwd: directory,
@ -46,7 +51,7 @@ export async function generateNoticeFromSource({ productName, directory, log })
'packages/*/{node_modules,build,target,dist}/**',
'x-pack/{node_modules,build,target,dist,optimize}/**',
'x-pack/packages/*/{node_modules,build,target,dist}/**',
]
],
};
log.debug('vfs.src globs', globs);
@ -54,10 +59,10 @@ export async function generateNoticeFromSource({ productName, directory, log })
log.info(`Searching ${directory} for multi-line comments starting with @notice`);
const files = vfs.src(globs, options);
const noticeComments = [];
const noticeComments: string[] = [];
await new Promise((resolve, reject) => {
files
.on('data', (file) => {
.on('data', file => {
log.verbose(`Checking for @notice comments in ${file.relative}`);
const source = file.contents.toString('utf8');
@ -75,19 +80,19 @@ export async function generateNoticeFromSource({ productName, directory, log })
let noticeText = '';
noticeText += `${productName}\n`;
noticeText += `Copyright 2012-${(new Date()).getUTCFullYear()} Elasticsearch B.V.\n`;
noticeText += `Copyright 2012-${new Date().getUTCFullYear()} Elasticsearch B.V.\n`;
for (const comment of noticeComments.sort()) {
noticeText += '\n---\n';
noticeText += comment
.split(NEWLINE_RE)
.map(line => (
.map(line =>
line
// trim whitespace
.trim()
// trim leading * and a single space
.replace(/(^\* ?)/, '')
))
)
.join('\n')
.trim();
noticeText += '\n';

View file

@ -18,4 +18,5 @@
*/
export { generateNoticeFromSource } from './generate_notice_from_source';
// @ts-ignore not typed yet
export { generateBuildNoticeText } from './generate_build_notice_text';

View file

@ -4,36 +4,20 @@
* you may not use this file except in compliance with the Elastic License.
*/
require('@kbn/plugin-helpers').babelRegister();
require('dotenv').config({ silent: true });
require('../src/setup_node_env');
const path = require('path');
const gulp = require('gulp');
const mocha = require('gulp-mocha');
const multiProcess = require('gulp-multi-process');
const fancyLog = require('fancy-log');
const pkg = require('./package.json');
const { buildTask } = require('./tasks/build');
const { devTask } = require('./tasks/dev');
const { testTask, testBrowserTask, testBrowserDevTask, testServerTask } = require('./tasks/test');
const { prepareTask } = require('./tasks/prepare');
const buildDir = path.resolve(__dirname, 'build');
const buildTarget = path.resolve(buildDir, 'plugin');
const packageDir = path.resolve(buildDir, 'distributions');
const coverageDir = path.resolve(__dirname, 'coverage');
const gulpHelpers = {
buildDir,
buildTarget,
coverageDir,
log: fancyLog,
mocha,
multiProcess,
packageDir,
pkg,
// export the tasks that are runnable from the CLI
module.exports = {
build: buildTask,
dev: devTask,
prepare: prepareTask,
test: testTask,
testserver: testServerTask,
testbrowser: testBrowserTask,
'testbrowser-dev': testBrowserDevTask,
};
require('./tasks/build')(gulp, gulpHelpers);
require('./tasks/clean')(gulp, gulpHelpers);
require('./tasks/dev')(gulp, gulpHelpers);
require('./tasks/prepare')(gulp, gulpHelpers);
require('./tasks/report')(gulp, gulpHelpers);
require('./tasks/test')(gulp, gulpHelpers);
require('./legacy/plugins/canvas/tasks')(gulp, gulpHelpers);

View file

@ -1,51 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
const { resolve } = require('path');
const register = require('@babel/register');
const options = {
babelrc: false,
presets: [require.resolve('@kbn/babel-preset/node_preset')],
sourceMaps: false,
plugins: [
[
'mock-imports',
[
{
pattern: 'ui/chrome',
location: resolve(__dirname, '..', 'mocks', 'uiChrome'),
},
{
pattern: 'ui/notify',
location: resolve(__dirname, '..', 'mocks', 'uiNotify'),
},
{
pattern: 'ui/storage',
location: resolve(__dirname, '..', 'mocks', 'uiStorage'),
},
{
pattern: 'ui/url/absolute_to_parsed_url',
location: resolve(__dirname, '..', 'mocks', 'absoluteToParsedUrl'),
},
{
// ugly hack so that importing non-js files works, required for the function docs
pattern: '.(less|png|svg)$',
location: resolve(__dirname, '..', 'mocks', 'noop'),
},
{
pattern: 'plugins/canvas/apps',
location: resolve(__dirname, '..', 'mocks', 'noop'),
},
{
pattern: '/state/store',
location: resolve(__dirname, '..', 'mocks', 'stateStore'),
},
],
],
],
};
register(options);

View file

@ -1,23 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { JSDOM } from 'jsdom';
import { APP_ROUTE } from '../../common/lib/constants';
import chrome from '../mocks/uiChrome';
const basePath = chrome.getBasePath();
const basename = `${basePath}${APP_ROUTE}`;
const { window } = new JSDOM('', {
url: `http://localhost:5601/${basename}`,
pretendToBeVisual: true,
});
global.window = window;
global.document = window.document;
global.navigator = window.navigator;
global.requestAnimationFrame = window.requestAnimationFrame;
global.HTMLElement = window.HTMLElement;

View file

@ -1,10 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
configure({ adapter: new Adapter() });

View file

@ -1,11 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import test from './test';
export default function canvasTasks(gulp, gulpHelpers) {
test(gulp, gulpHelpers);
}

View file

@ -1,10 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
export const absoluteToParsedUrl = () => {
getAbsoluteUrl: () =>
'http://localhost:5601/kbp/app/canvas#/workpad/workpad-24d56dad-ae70-42b8-9ef1-c5350ecd426c/page/1';
}; // noop

View file

@ -1,7 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
export default function() {}

View file

@ -1,13 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
export function getState() {
return {
assets: {
yay: { value: 'here is your image' },
},
};
}

View file

@ -1,66 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { resolve, join } from 'path';
export default function testTasks(gulp, { mocha }) {
const canvasRoot = resolve(__dirname, '..');
function runMocha(globs, { withEnzyme = false, withDOM = false } = {}) {
const requires = [join(canvasRoot, 'tasks/helpers/babelhook')];
if (withDOM) {
requires.push(join(canvasRoot, 'tasks/helpers/dom_setup'));
}
if (withEnzyme) {
requires.push(join(canvasRoot, 'tasks/helpers/enzyme_setup'));
}
return gulp.src(globs, { read: false }).pipe(
mocha({
ui: 'bdd',
require: requires,
})
);
}
const getTestGlobs = rootPath => [
join(canvasRoot, `${rootPath}/**/__tests__/**/*.js`),
join(canvasRoot, `!${rootPath}/**/__tests__/fixtures/**/*.js`),
];
const getRootGlobs = rootPath => [join(canvasRoot, `${rootPath}/**/*.js`)];
gulp.task('canvas:test:common', () => {
return runMocha(getTestGlobs('common'), { withDOM: true });
});
gulp.task('canvas:test:server', () => {
return runMocha(getTestGlobs('server'));
});
gulp.task('canvas:test:browser', () => {
return runMocha(getTestGlobs('public'), { withEnzyme: true, withDOM: true });
});
gulp.task('canvas:test:plugins', () => {
return runMocha(getTestGlobs('canvas_plugin_src'));
});
gulp.task('canvas:test', [
'canvas:test:plugins',
'canvas:test:common',
'canvas:test:server',
'canvas:test:browser',
]);
gulp.task('canvas:test:dev', () => {
gulp.watch(getRootGlobs('common'), ['canvas:test:common']);
gulp.watch(getRootGlobs('server'), ['canvas:test:server']);
gulp.watch(getRootGlobs('public'), ['canvas:test:browser']);
gulp.watch(getRootGlobs('canvas_plugin_src'), ['canvas:test:plugins']);
});
}

View file

@ -6,6 +6,8 @@
import * as chromium from './chromium';
export type BrowserType = keyof typeof BROWSERS_BY_TYPE;
export const BROWSERS_BY_TYPE = {
chromium,
};

View file

@ -4,9 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
// @ts-ignore
import { BROWSERS_BY_TYPE } from './browsers';
// @ts-ignore
import { BROWSERS_BY_TYPE, BrowserType } from './browsers';
import { ensureBrowserDownloaded } from './download';
import { installBrowser } from './install';
import { LevelLogger } from '../lib/level_logger';
@ -22,7 +20,7 @@ export async function createBrowserDriverFactory(
const DATA_DIR = config.get('path.data');
const CAPTURE_CONFIG = config.get('xpack.reporting.capture');
const BROWSER_TYPE = CAPTURE_CONFIG.browser.type;
const BROWSER_TYPE: BrowserType = CAPTURE_CONFIG.browser.type;
const BROWSER_AUTO_DOWNLOAD = CAPTURE_CONFIG.browser.autoDownload;
const BROWSER_CONFIG = CAPTURE_CONFIG.browser[BROWSER_TYPE];
const REPORTING_TIMEOUT = config.get('xpack.reporting.queue.timeout');

View file

@ -9,7 +9,7 @@ import { promisify } from 'util';
const getos = promisify(getosSync);
const distroSupportsUnprivilegedUsernamespaces = (distro) => {
const distroSupportsUnprivilegedUsernamespaces = (distro: string) => {
// Debian 7 and 8 don't support usernamespaces by default
// this should be reevaluated when Debian 9 is available
if (distro.toLowerCase() === 'debian') {

View file

@ -7,7 +7,6 @@
import { createHash } from 'crypto';
import { createReadStream } from 'fs';
// @ts-ignore
import { readableEnd } from './util';
export async function md5(path: string) {

View file

@ -14,12 +14,9 @@ import { log, asyncMap } from './util';
/**
* Delete any file in the `dir` that is not in the expectedPaths
* @param {String} dir
* @param {Array<String>} expectedPaths
* @return {Promise<undefined>}
*/
export async function clean(dir, expectedPaths) {
let filenames;
export async function clean(dir: string, expectedPaths: string[]) {
let filenames: string[];
try {
filenames = await readdirSync(dir);
} catch (error) {

View file

@ -7,6 +7,7 @@
import { createHash } from 'crypto';
import { resolve as resolvePath } from 'path';
import { readFileSync } from 'fs';
import { Readable } from 'stream';
import del from 'del';
import { download } from './download';
@ -14,41 +15,27 @@ import { download } from './download';
const TEMP_DIR = resolvePath(__dirname, '__tmp__');
const TEMP_FILE = resolvePath(TEMP_DIR, 'foo/bar/download');
jest.mock('request', () => {
let resp = '';
const sinon = require('sinon');
const Readable = require('stream').Readable;
const request = sinon.spy(function () {
return new Readable({
read() {
if (resp instanceof Error) {
this.emit('error', resp);
return;
}
class ReadableOf extends Readable {
constructor(private readonly responseBody: string) {
super();
}
this.push(resp.shift());
_read() {
this.push(this.responseBody);
this.push(null);
}
}
if (resp.length === 0) {
this.push(null);
}
}
});
});
request._setResponse = (chunks) => {
if (typeof chunks === 'string') {
chunks = chunks.split('');
}
resp = chunks;
};
return request;
});
jest.mock('axios');
const request: jest.Mock = jest.requireMock('axios').request;
test('downloads the url to the path', async () => {
const BODY = 'abdcefg';
require('request')._setResponse(BODY);
request.mockImplementationOnce(async () => {
return {
data: new ReadableOf(BODY),
};
});
await download('url', TEMP_FILE);
expect(readFileSync(TEMP_FILE, 'utf8')).toEqual(BODY);
@ -56,18 +43,25 @@ test('downloads the url to the path', async () => {
test('returns the md5 hex hash of the http body', async () => {
const BODY = 'foobar';
const HASH = createHash('md5').update(BODY).digest('hex');
require('request')._setResponse(BODY);
const HASH = createHash('md5')
.update(BODY)
.digest('hex');
request.mockImplementationOnce(async () => {
return {
data: new ReadableOf(BODY),
};
});
const returned = await download('url', TEMP_FILE);
expect(returned).toEqual(HASH);
});
test('throws if request emits an error', async () => {
require('request')._setResponse(new Error('foo'));
request.mockImplementationOnce(async () => {
throw new Error('foo');
});
return expect(download('url', TEMP_FILE)).rejects.toThrow('foo');
});
afterEach(async () => (
await del(TEMP_DIR)
));
afterEach(async () => await del(TEMP_DIR));

View file

@ -8,9 +8,9 @@ import { openSync, writeSync, closeSync, mkdirSync } from 'fs';
import { createHash } from 'crypto';
import { dirname } from 'path';
import request from 'request';
import Axios from 'axios';
import { log, readableEnd } from './util';
import { log } from './util';
/**
* Download a url and calculate it's checksum
@ -18,7 +18,7 @@ import { log, readableEnd } from './util';
* @param {String} path
* @return {Promise<String>} checksum of the downloaded file
*/
export async function download(url, path) {
export async function download(url: string, path: string) {
log(`Downloading ${url}`);
const hash = createHash('md5');
@ -27,11 +27,20 @@ export async function download(url, path) {
const handle = openSync(path, 'w');
try {
const readable = request(url).on('data', chunk => {
const resp = await Axios.request({
url,
method: 'GET',
responseType: 'stream',
});
resp.data.on('data', (chunk: Buffer) => {
writeSync(handle, chunk);
hash.update(chunk);
});
await readableEnd(readable);
await new Promise((resolve, reject) => {
resp.data.on('error', reject).on('end', resolve);
});
} finally {
closeSync(handle);
}

View file

@ -7,21 +7,20 @@
import { resolve as resolvePath } from 'path';
import { existsSync } from 'fs';
import { BROWSERS_BY_TYPE } from '../browsers';
import { BROWSERS_BY_TYPE, BrowserType } from '../browsers';
import { md5 } from './checksum';
import { asyncMap } from './util';
import { download } from './download';
import { clean } from './clean';
/**
* Check for the downloaded archive of each requested browser type and
* download them if they are missing or their checksum is invalid
* @param {String} browserType
* @return {Promise<undefined>}
*/
export async function ensureBrowserDownloaded(browserType) {
export async function ensureBrowserDownloaded(browserType: BrowserType) {
await ensureDownloaded([BROWSERS_BY_TYPE[browserType]]);
}
@ -33,7 +32,6 @@ export async function ensureAllBrowsersDownloaded() {
await ensureDownloaded(Object.values(BROWSERS_BY_TYPE));
}
/**
* Clears the unexpected files in the browsers archivesPath
* and ensures that all packages/archives are downloaded and
@ -41,20 +39,29 @@ export async function ensureAllBrowsersDownloaded() {
* @param {BrowserSpec} browsers
* @return {Promise<undefined>}
*/
async function ensureDownloaded(browsers) {
await asyncMap(Object.values(browsers), async (browser) => {
async function ensureDownloaded(
browsers: Array<{
paths: {
archivesPath: string;
baseUrl: string;
packages: Array<{ archiveFilename: string; archiveChecksum: string }>;
};
}>
) {
await asyncMap(browsers, async browser => {
const { archivesPath } = browser.paths;
await clean(archivesPath, browser.paths.packages.map(p => (
resolvePath(archivesPath, p.archiveFilename)
)));
await clean(
archivesPath,
browser.paths.packages.map(p => resolvePath(archivesPath, p.archiveFilename))
);
const invalidChecksums = [];
const invalidChecksums: string[] = [];
await asyncMap(browser.paths.packages, async ({ archiveFilename, archiveChecksum }) => {
const url = `${browser.paths.baseUrl}${archiveFilename}`;
const path = resolvePath(archivesPath, archiveFilename);
if (existsSync(path) && await md5(path) === archiveChecksum) {
if (existsSync(path) && (await md5(path)) === archiveChecksum) {
return;
}
@ -65,7 +72,11 @@ async function ensureDownloaded(browsers) {
});
if (invalidChecksums.length) {
throw new Error(`Error downloading browsers, checksums incorrect for:\n - ${invalidChecksums.join('\n - ')}`);
throw new Error(
`Error downloading browsers, checksums incorrect for:\n - ${invalidChecksums.join(
'\n - '
)}`
);
}
});
}

View file

@ -1,10 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
export {
ensureBrowserDownloaded,
ensureAllBrowsersDownloaded,
} from './ensure_downloaded';

View file

@ -4,6 +4,4 @@
* you may not use this file except in compliance with the Elastic License.
*/
export default function getFlags() {
return process.argv.slice(3);
}
export { ensureBrowserDownloaded, ensureAllBrowsersDownloaded } from './ensure_downloaded';

View file

@ -4,33 +4,30 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { Readable } from 'stream';
/**
* Log a message if the DEBUG environment variable is set
* @param {...any} args
* @return {undefined}
*/
export function log(...args) {
export function log(...args: any[]) {
if (process.env.DEBUG) {
// allow console log since this is off by default and only for debugging
// eslint-disable-next-line no-console
console.log(...args);
}
}
/**
* Iterate an array asynchronously and in parallel
* @param {Array} array
* @param {Function} asyncFn
* @return {Promise}
*/
export function asyncMap(array, asyncFn) {
export function asyncMap<T, T2>(array: T[], asyncFn: (x: T) => T2): Promise<T2[]> {
return Promise.all(array.map(asyncFn));
}
/**
* Wait for a readable stream to end
* @param {Stream.Readable} stream
* @return {Promise<undefined>}
*/
export function readableEnd(stream) {
export function readableEnd(stream: Readable) {
return new Promise((resolve, reject) => {
stream.on('error', reject).on('end', resolve);
});

View file

@ -9,7 +9,7 @@
"kbn:bootstrap": "node legacy/plugins/canvas/scripts/storybook --clean",
"start": "gulp dev",
"build": "gulp build",
"testonly": "gulp testonly",
"testonly": "echo 'Deprecated, use `yarn test`' && gulp test",
"test": "gulp test",
"test:browser:dev": "gulp testbrowser-dev",
"test:browser": "gulp testbrowser",
@ -56,10 +56,13 @@
"@types/d3-time": "^1.0.10",
"@types/d3-time-format": "^2.1.1",
"@types/elasticsearch": "^5.0.33",
"@types/fancy-log": "^1.3.1",
"@types/file-saver": "^2.0.0",
"@types/getos": "^3.0.0",
"@types/git-url-parse": "^9.0.0",
"@types/glob": "^7.1.1",
"@types/graphql": "^0.13.1",
"@types/gulp": "^4.0.6",
"@types/hapi__wreck": "^15.0.1",
"@types/history": "^4.7.3",
"@types/jest": "^24.0.18",
@ -122,7 +125,6 @@
"copy-webpack-plugin": "^5.0.4",
"cypress": "^3.4.1",
"del": "^4.1.1",
"dotenv": "2.0.0",
"enzyme": "^3.10.0",
"enzyme-adapter-react-16": "^1.14.0",
"enzyme-adapter-utils": "^1.12.0",
@ -134,8 +136,8 @@
"graphql-codegen-introspection-template": "^0.13.0",
"graphql-codegen-typescript-resolvers-template": "^0.13.0",
"graphql-codegen-typescript-template": "^0.13.0",
"gulp": "3.9.1",
"gulp-mocha": "^7.0.1",
"gulp": "4.0.2",
"gulp-mocha": "^7.0.2",
"gulp-multi-process": "1.3.1",
"hapi": "^17.5.3",
"jest": "^24.9.0",
@ -162,7 +164,6 @@
"react-testing-library": "^6.0.0",
"redux-test-utils": "0.2.2",
"rsync": "0.6.1",
"run-sequence": "^2.2.1",
"sass-loader": "^7.3.1",
"simple-git": "1.116.0",
"sinon": "^7.4.2",

View file

@ -1,36 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { resolve } from 'path';
import { writeFileSync } from 'fs';
import pluginHelpers from '@kbn/plugin-helpers';
import { ToolingLog } from '@kbn/dev-utils';
import { generateNoticeFromSource } from '../../src/dev';
export default (gulp, { buildTarget }) => {
gulp.task('build', ['clean', 'report', 'prepare:build'], async () => {
await pluginHelpers.run('build', {
skipArchive: true,
buildDestination: buildTarget,
});
const buildRoot = resolve(buildTarget, 'kibana/x-pack');
const log = new ToolingLog({
level: 'info',
writeTo: process.stdout
});
writeFileSync(
resolve(buildRoot, 'NOTICE.txt'),
await generateNoticeFromSource({
productName: 'Kibana X-Pack',
log,
directory: buildRoot
})
);
});
};

70
x-pack/tasks/build.ts Normal file
View file

@ -0,0 +1,70 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { resolve } from 'path';
import { writeFileSync } from 'fs';
import pluginHelpers from '@kbn/plugin-helpers';
import { ToolingLog, REPO_ROOT } from '@kbn/dev-utils';
import gulp from 'gulp';
import del from 'del';
import fancyLog from 'fancy-log';
import chalk from 'chalk';
import { generateNoticeFromSource } from '../../src/dev/notice';
import { prepareTask } from './prepare';
import { gitInfo } from './helpers/git_info';
import { PKG_NAME } from './helpers/pkg';
import { BUILD_VERSION } from './helpers/build_version';
const BUILD_DIR = resolve(REPO_ROOT, 'x-pack/build');
const PLUGIN_BUILD_DIR = resolve(BUILD_DIR, 'plugin');
async function cleanBuildTask() {
fancyLog('Deleting', BUILD_DIR);
await del(BUILD_DIR);
}
async function reportTask() {
const info = await gitInfo();
fancyLog('Package Name', chalk.yellow(PKG_NAME));
fancyLog('Version', chalk.yellow(BUILD_VERSION));
fancyLog('Build Number', chalk.yellow(`${info.number}`));
fancyLog('Build SHA', chalk.yellow(info.sha));
}
async function pluginHelpersBuild() {
await pluginHelpers.run('build', {
skipArchive: true,
buildDestination: PLUGIN_BUILD_DIR,
});
}
async function generateNoticeText() {
const buildRoot = resolve(PLUGIN_BUILD_DIR, 'kibana/x-pack');
const log = new ToolingLog({
level: 'info',
writeTo: process.stdout,
});
writeFileSync(
resolve(buildRoot, 'NOTICE.txt'),
await generateNoticeFromSource({
productName: 'Kibana X-Pack',
log,
directory: buildRoot,
})
);
}
export const buildTask = gulp.series(
cleanBuildTask,
reportTask,
prepareTask,
pluginHelpersBuild,
generateNoticeText
);

View file

@ -1,22 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import del from 'del';
export default (gulp, { coverageDir, buildDir, packageDir, log }) => {
gulp.task('clean-test', () => {
log('Deleting', coverageDir);
return del([coverageDir]);
});
gulp.task('clean', ['clean-test'], () => {
const toDelete = [
buildDir,
packageDir,
];
log('Deleting', toDelete.join(', '));
return del(toDelete);
});
};

View file

@ -5,8 +5,12 @@
*/
import pluginHelpers from '@kbn/plugin-helpers';
import getFlags from './helpers/get_flags';
import gulp from 'gulp';
export default (gulp) => {
gulp.task('dev', ['prepare:dev'], () => pluginHelpers.run('start', { flags: getFlags() }));
};
import { prepareTask } from './prepare';
export const devTask = gulp.series(prepareTask, async function startKibanaServer() {
await pluginHelpers.run('start', {
flags: process.argv.slice(3),
});
});

View file

@ -1,29 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import yargs from 'yargs';
import semver from 'semver';
yargs
.alias('r', 'release').describe('r', 'Create a release build, not a snapshot')
.option('build-qualifier', {
default: null
});
const argv = yargs.argv;
export default function getVersion(pkg) {
const { version } = pkg;
if (!version) {
throw new Error('No version found in package.json');
}
if (!semver.valid(version)) {
throw new Error(`Version is not valid semver: ${version}`);
}
const snapshotText = (argv.release) ? '' : '-SNAPSHOT';
const qualifierText = argv.buildQualifier ? '-' + argv.buildQualifier : '';
return `${version}${qualifierText}${snapshotText}`;
}

View file

@ -0,0 +1,12 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { PKG_VERSION } from './pkg';
import { FLAGS } from './flags';
const snapshotText = FLAGS.release ? '' : '-SNAPSHOT';
const qualifierText = FLAGS.buildQualifier ? '-' + FLAGS.buildQualifier : '';
export const BUILD_VERSION = `${PKG_VERSION}${qualifierText}${snapshotText}`;

View file

@ -0,0 +1,70 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { resolve } from 'path';
import log from 'fancy-log';
import getopts from 'getopts';
import { toArray } from 'rxjs/operators';
// @ts-ignore complicated module doesn't have types yet
import { findPluginSpecs } from '../../../src/legacy/plugin_discovery';
/*
Usage:
Specifying which plugins to run tests can be done with the --plugins flag.
One of more plugins can be specified, and each one should be command separated, like so:
gulp testserver --plugins monitoring,reporting
If using with yarn:
yarn test:server --plugins graph
*/
const opts = Object.freeze(
getopts(process.argv.slice(2), {
alias: {
release: 'r',
},
boolean: ['release', 'flags'],
string: ['build-qualifier', 'plugins'],
})
);
if (opts.flags) {
log(`
X-Pack Gulpfile Flags:
--flags Print this message
--plugins Comma-separated list of plugins
--release, -r Build to a release version
--build-qualifier Qualifier to include in the build version
`);
process.exit(0);
}
export const FLAGS = {
release: !!opts.release,
buildQualifier: opts.buildQualifier as string | undefined,
plugins: opts.plugins
? String(opts.plugins)
.split(',')
.map(id => id.trim())
: undefined,
};
export async function getEnabledPlugins() {
if (FLAGS.plugins) {
return FLAGS.plugins;
}
const { spec$ } = findPluginSpecs({
plugins: {
paths: [resolve(__dirname, '..', '..')],
},
});
const enabledPlugins: Array<{ getId: () => string }> = await spec$.pipe(toArray()).toPromise();
return enabledPlugins.map(spec => spec.getId());
}

View file

@ -1,46 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { resolve } from 'path';
import yargs from 'yargs';
import glob from 'glob';
import { toArray } from 'rxjs/operators';
import { findPluginSpecs } from '../../../src/legacy/plugin_discovery';
/*
Usage:
Specifying which plugins to run tests can be done with the --plugins flag.
One of more plugins can be specified, and each one should be command separated, like so:
gulp testserver --plugins monitoring,reporting
If using with yarn:
yarn test:server --plugins graph
*/
const argv = yargs
.describe('plugins', 'Comma-separated list of plugins')
.argv;
const allPlugins = glob.sync('*', { cwd: resolve(__dirname, '..', '..', 'legacy', 'plugins') });
export function getPlugins() {
const plugins = argv.plugins && argv.plugins.split(',');
if (!Array.isArray(plugins) || plugins.length === 0) {
return allPlugins;
}
return plugins;
}
const { spec$ } = findPluginSpecs({
plugins: { paths: [resolve(__dirname, '..', '..')] }
});
export async function getEnabledPlugins() {
const plugins = argv.plugins && argv.plugins.split(',');
if (!Array.isArray(plugins) || plugins.length === 0) {
const enabledPlugins = await spec$.pipe(toArray()).toPromise();
return enabledPlugins.map(spec => spec.getId());
}
return plugins;
}

View file

@ -5,20 +5,24 @@
*/
import path from 'path';
// @ts-ignore barely used, untyped module
import simpleGit from 'simple-git';
const gitDir = path.resolve(__dirname, '..', '..');
export default function gitInfo() {
export async function gitInfo() {
const git = simpleGit(gitDir);
return new Promise((resolve, reject) => {
git.log((err, log) => {
if (err) return reject(err);
resolve({
number: log.total,
sha: log.latest.hash,
});
return new Promise<{ number: number; sha: string }>((resolve, reject) => {
git.log((err: undefined | Error, log: { total: number; latest: { hash: string } }) => {
if (err) {
reject(err);
} else {
resolve({
number: log.total,
sha: log.latest.hash,
});
}
});
});
}

View file

@ -1,49 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { getPlugins } from './get_plugins';
/*
* Note: The path `plugins / pluginName / ** / __tests__ / ** / *.js` will match
* all public and server tests, so a special var must be used for "index" tests
* paths: `plugins / pluginName / __tests__ / ** / *.js`
*/
function getPluginPaths(plugins, opts = {}) {
const testPath = opts.tests ? '__tests__/**' : '';
return plugins.reduce((paths, pluginName) => {
const plugin = pluginName.trim();
const commonPath = `${plugin}/common`;
const serverPath = `${plugin}/**/server`;
const publicPath = `${plugin}/**/public`;
const indexPaths = `legacy/plugins/${plugin}/${testPath}/*.js`; // index and helpers
const commonPaths = `legacy/plugins/${commonPath}/**/${testPath}/*.js`;
const serverPaths = `legacy/plugins/${serverPath}/**/${testPath}/*.js`;
const publicPaths = `legacy/plugins/${publicPath}/**/${testPath}/*.js`;
paths = paths.concat([indexPaths, commonPaths, serverPaths]);
if (plugin === 'code') {
paths.push(`legacy/plugins/${serverPath}/**/${testPath}/*.ts`);
}
if (opts.browser) {
paths = paths.concat(publicPaths);
}
return paths;
}, []);
}
export function forPlugins() {
const plugins = getPlugins();
return getPluginPaths(plugins, { browser: true });
}
export function forPluginServerTests() {
const plugins = getPlugins();
return getPluginPaths(plugins, { tests: true });
}

View file

@ -0,0 +1,33 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import Fs from 'fs';
import semver from 'semver';
interface PackageJson {
name: string;
version: string;
dependencies: Record<string, string>;
devDependencies: Record<string, string>;
[key: string]: unknown;
}
const PKG_PATH = require.resolve('../../package.json');
export const PKG: PackageJson = JSON.parse(Fs.readFileSync(PKG_PATH, 'utf8'));
export const PKG_VERSION = PKG.version;
export const PKG_NAME = PKG.name;
if (!PKG_VERSION) {
throw new Error('No "version" found in package.json');
}
if (!PKG_NAME) {
throw new Error('No "name" found in package.json');
}
if (!semver.valid(PKG_VERSION)) {
throw new Error(`Version is not valid semver: ${PKG_VERSION}`);
}

View file

@ -1,18 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { ensureAllBrowsersDownloaded } from '../legacy/plugins/reporting/server/browsers';
export default gulp => {
// anything that should always happen before anything else
gulp.task('prepare', () => ensureAllBrowsersDownloaded());
// anything that needs to happen before development
gulp.task('prepare:dev', ['prepare']);
// anything that needs to happen before building
gulp.task('prepare:build', ['prepare']);
};

View file

@ -4,12 +4,8 @@
* you may not use this file except in compliance with the Elastic License.
*/
export class Storage {
get(key) {
return this[key];
}
import { ensureAllBrowsersDownloaded } from '../legacy/plugins/reporting/server/browsers';
set(key, value) {
this[key] = value;
}
}
export const prepareTask = async () => {
await ensureAllBrowsersDownloaded();
};

View file

@ -1,21 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import buildVersion from './helpers/build_version';
import gitInfo from './helpers/git_info';
import chalk from 'chalk';
export default (gulp, { log, pkg }) => {
gulp.task('report', () => {
return gitInfo()
.then(function (info) {
log('Package Name', chalk.yellow(pkg.name));
log('Version', chalk.yellow(buildVersion(pkg)));
log('Build Number', chalk.yellow(info.number));
log('Build SHA', chalk.yellow(info.sha));
});
});
};

View file

@ -1,54 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import runSequence from 'run-sequence';
import pluginHelpers from '@kbn/plugin-helpers';
import { getEnabledPlugins } from './helpers/get_plugins';
import { forPluginServerTests } from './helpers/globs';
import { createAutoJUnitReporter } from '../../src/dev';
const MOCHA_OPTIONS = {
ui: 'bdd',
require: require.resolve('../../src/setup_node_env'),
reporter: createAutoJUnitReporter({
reportName: 'X-Pack Mocha Tests',
}),
};
export default (gulp, { mocha }) => {
gulp.task('test', (cb) => {
const preTasks = ['clean-test'];
runSequence(preTasks, 'testserver', 'testbrowser', cb);
});
gulp.task('testonly', ['testserver', 'testbrowser']);
gulp.task('testserver', () => {
const globs = [
'common/**/__tests__/**/*.js',
'server/**/__tests__/**/*.js',
].concat(forPluginServerTests());
return gulp.src(globs, { read: false })
.pipe(mocha(MOCHA_OPTIONS));
});
gulp.task('testbrowser', () => {
return getEnabledPlugins().then(plugins => {
return pluginHelpers.run('testBrowser', {
plugins: plugins.join(','),
});
});
});
gulp.task('testbrowser-dev', () => {
return getEnabledPlugins().then(plugins => {
return pluginHelpers.run('testBrowser', {
dev: true,
plugins: plugins.join(','),
});
});
});
};

59
x-pack/tasks/test.ts Normal file
View file

@ -0,0 +1,59 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import pluginHelpers from '@kbn/plugin-helpers';
// @ts-ignore no types available
import mocha from 'gulp-mocha';
import gulp from 'gulp';
// @ts-ignore untyped, converted in a different location in master
import { createAutoJUnitReporter } from '../../src/dev/mocha';
import { getEnabledPlugins } from './helpers/flags';
export const testServerTask = async () => {
const pluginIds = await getEnabledPlugins();
const testGlobs = ['common/**/__tests__/**/*.js', 'server/**/__tests__/**/*.js'];
if (pluginIds.includes('code')) {
testGlobs.push(`legacy/plugins/**/server/**/__tests__/**/*.ts`);
}
for (const pluginId of pluginIds) {
testGlobs.push(
`legacy/plugins/${pluginId}/__tests__/**/*.js`,
`legacy/plugins/${pluginId}/common/**/__tests__/**/*.js`,
`legacy/plugins/${pluginId}/**/server/**/__tests__/**/*.js`
);
}
return gulp.src(testGlobs, { read: false }).pipe(
mocha({
ui: 'bdd',
require: require.resolve('../../src/setup_node_env'),
reporter: createAutoJUnitReporter({
reportName: 'X-Pack Mocha Tests',
}),
})
);
};
export const testBrowserTask = async () => {
const plugins = await getEnabledPlugins();
await pluginHelpers.run('testBrowser', {
plugins: plugins.join(','),
});
};
export const testBrowserDevTask = async () => {
const plugins = await getEnabledPlugins();
await pluginHelpers.run('testBrowser', {
dev: true,
plugins: plugins.join(','),
});
};
export const testTask = gulp.series(testServerTask, testBrowserTask);

View file

@ -6,7 +6,8 @@
"legacy/server/**/*",
"legacy/plugins/**/*",
"plugins/**/*",
"test_utils/**/*"
"test_utils/**/*",
"tasks/**/*"
],
"exclude": [
"test/**/*",

847
yarn.lock

File diff suppressed because it is too large Load diff