Merge branch 'master' into data/allow-custom-formatting
This commit is contained in:
commit
fc9ff7be61
|
@ -46,7 +46,7 @@ echo "Creating bootstrap_cache archive"
|
|||
# archive cacheable directories
|
||||
mkdir -p "$HOME/.kibana/bootstrap_cache"
|
||||
tar -cf "$HOME/.kibana/bootstrap_cache/$branch.tar" \
|
||||
x-pack/plugins/reporting/.chromium \
|
||||
.chromium \
|
||||
.es \
|
||||
.chromedriver \
|
||||
.geckodriver;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
**/*.js.snap
|
||||
**/graphql/types.ts
|
||||
/.es
|
||||
/.chromium
|
||||
/build
|
||||
/built_assets
|
||||
/config/apm.dev.js
|
||||
|
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -2,6 +2,7 @@
|
|||
.signing-config.json
|
||||
.ackrc
|
||||
/.es
|
||||
/.chromium
|
||||
.DS_Store
|
||||
.node_binaries
|
||||
.native_modules
|
||||
|
|
|
@ -398,7 +398,7 @@ include::api.asciidoc[tag=using-the-APIs]
|
|||
[%collapsible%open]
|
||||
======
|
||||
`version` :::
|
||||
(required, string) Name of service.
|
||||
(required, string) Version of service.
|
||||
|
||||
`environment` :::
|
||||
(optional, string) Environment of service.
|
||||
|
|
|
@ -19,5 +19,6 @@ export interface DiscoveredPlugin
|
|||
| [configPath](./kibana-plugin-core-server.discoveredplugin.configpath.md) | <code>ConfigPath</code> | Root configuration path used by the plugin, defaults to "id" in snake\_case format. |
|
||||
| [id](./kibana-plugin-core-server.discoveredplugin.id.md) | <code>PluginName</code> | Identifier of the plugin. |
|
||||
| [optionalPlugins](./kibana-plugin-core-server.discoveredplugin.optionalplugins.md) | <code>readonly PluginName[]</code> | An optional list of the other plugins that if installed and enabled \*\*may be\*\* leveraged by this plugin for some additional functionality but otherwise are not required for this plugin to work properly. |
|
||||
| [requiredBundles](./kibana-plugin-core-server.discoveredplugin.requiredbundles.md) | <code>readonly PluginName[]</code> | List of plugin ids that this plugin's UI code imports modules from that are not in <code>requiredPlugins</code>. |
|
||||
| [requiredPlugins](./kibana-plugin-core-server.discoveredplugin.requiredplugins.md) | <code>readonly PluginName[]</code> | An optional list of the other plugins that \*\*must be\*\* installed and enabled for this plugin to function properly. |
|
||||
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [DiscoveredPlugin](./kibana-plugin-core-server.discoveredplugin.md) > [requiredBundles](./kibana-plugin-core-server.discoveredplugin.requiredbundles.md)
|
||||
|
||||
## DiscoveredPlugin.requiredBundles property
|
||||
|
||||
List of plugin ids that this plugin's UI code imports modules from that are not in `requiredPlugins`<!-- -->.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
readonly requiredBundles: readonly PluginName[];
|
||||
```
|
||||
|
||||
## Remarks
|
||||
|
||||
The plugins listed here will be loaded in the browser, even if the plugin is disabled. Required by `@kbn/optimizer` to support cross-plugin imports. "core" and plugins already listed in `requiredPlugins` do not need to be duplicated here.
|
||||
|
|
@ -25,6 +25,7 @@ Should never be used in code outside of Core but is exported for documentation p
|
|||
| [id](./kibana-plugin-core-server.pluginmanifest.id.md) | <code>PluginName</code> | Identifier of the plugin. Must be a string in camelCase. Part of a plugin public contract. Other plugins leverage it to access plugin API, navigate to the plugin, etc. |
|
||||
| [kibanaVersion](./kibana-plugin-core-server.pluginmanifest.kibanaversion.md) | <code>string</code> | The version of Kibana the plugin is compatible with, defaults to "version". |
|
||||
| [optionalPlugins](./kibana-plugin-core-server.pluginmanifest.optionalplugins.md) | <code>readonly PluginName[]</code> | An optional list of the other plugins that if installed and enabled \*\*may be\*\* leveraged by this plugin for some additional functionality but otherwise are not required for this plugin to work properly. |
|
||||
| [requiredBundles](./kibana-plugin-core-server.pluginmanifest.requiredbundles.md) | <code>readonly string[]</code> | List of plugin ids that this plugin's UI code imports modules from that are not in <code>requiredPlugins</code>. |
|
||||
| [requiredPlugins](./kibana-plugin-core-server.pluginmanifest.requiredplugins.md) | <code>readonly PluginName[]</code> | An optional list of the other plugins that \*\*must be\*\* installed and enabled for this plugin to function properly. |
|
||||
| [server](./kibana-plugin-core-server.pluginmanifest.server.md) | <code>boolean</code> | Specifies whether plugin includes some server-side specific functionality. |
|
||||
| [ui](./kibana-plugin-core-server.pluginmanifest.ui.md) | <code>boolean</code> | Specifies whether plugin includes some client/browser specific functionality that should be included into client bundle via <code>public/ui_plugin.js</code> file. |
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [PluginManifest](./kibana-plugin-core-server.pluginmanifest.md) > [requiredBundles](./kibana-plugin-core-server.pluginmanifest.requiredbundles.md)
|
||||
|
||||
## PluginManifest.requiredBundles property
|
||||
|
||||
List of plugin ids that this plugin's UI code imports modules from that are not in `requiredPlugins`<!-- -->.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
readonly requiredBundles: readonly string[];
|
||||
```
|
||||
|
||||
## Remarks
|
||||
|
||||
The plugins listed here will be loaded in the browser, even if the plugin is disabled. Required by `@kbn/optimizer` to support cross-plugin imports. "core" and plugins already listed in `requiredPlugins` do not need to be duplicated here.
|
||||
|
|
@ -19,7 +19,7 @@ image::user/reporting/images/share-button.png["Share"]
|
|||
[float]
|
||||
== Setup
|
||||
|
||||
{reporting} is automatically enabled in {kib}. The first time {kib} runs, it extracts a custom build for the Chromium web browser, which
|
||||
{reporting} is automatically enabled in {kib}. It runs a custom build of the Chromium web browser, which
|
||||
runs on the server in headless mode to load {kib} and capture the rendered {kib} charts as images.
|
||||
|
||||
Chromium is an open-source project not related to Elastic, but the Chromium binary for {kib} has been custom-built by Elastic to ensure it
|
||||
|
|
|
@ -5,5 +5,6 @@
|
|||
"server": true,
|
||||
"ui": true,
|
||||
"requiredPlugins": ["bfetch", "developerExamples"],
|
||||
"optionalPlugins": []
|
||||
"optionalPlugins": [],
|
||||
"requiredBundles": ["kibanaReact"]
|
||||
}
|
||||
|
|
|
@ -5,5 +5,6 @@
|
|||
"server": false,
|
||||
"ui": true,
|
||||
"requiredPlugins": ["embeddable", "embeddableExamples", "dashboard", "developerExamples"],
|
||||
"optionalPlugins": []
|
||||
"optionalPlugins": [],
|
||||
"requiredBundles": ["esUiShared"]
|
||||
}
|
||||
|
|
|
@ -6,5 +6,6 @@
|
|||
"ui": true,
|
||||
"requiredPlugins": ["embeddable", "uiActions"],
|
||||
"optionalPlugins": [],
|
||||
"extraPublicDirs": ["public/todo", "public/hello_world", "public/todo/todo_ref_embeddable"]
|
||||
"extraPublicDirs": ["public/todo", "public/hello_world", "public/todo/todo_ref_embeddable"],
|
||||
"requiredBundles": ["kibanaReact"]
|
||||
}
|
||||
|
|
|
@ -5,5 +5,6 @@
|
|||
"server": true,
|
||||
"ui": true,
|
||||
"requiredPlugins": ["navigation", "data", "developerExamples"],
|
||||
"optionalPlugins": []
|
||||
"optionalPlugins": [],
|
||||
"requiredBundles": ["kibanaUtils", "kibanaReact"]
|
||||
}
|
||||
|
|
|
@ -5,5 +5,6 @@
|
|||
"server": false,
|
||||
"ui": true,
|
||||
"requiredPlugins": ["uiActions"],
|
||||
"optionalPlugins": []
|
||||
"optionalPlugins": [],
|
||||
"requiredBundles": ["kibanaReact"]
|
||||
}
|
||||
|
|
|
@ -5,5 +5,6 @@
|
|||
"server": false,
|
||||
"ui": true,
|
||||
"requiredPlugins": ["uiActions", "uiActionsExamples", "developerExamples"],
|
||||
"optionalPlugins": []
|
||||
"optionalPlugins": [],
|
||||
"requiredBundles": ["kibanaReact"]
|
||||
}
|
||||
|
|
|
@ -127,7 +127,7 @@
|
|||
"@elastic/datemath": "5.0.3",
|
||||
"@elastic/elasticsearch": "7.8.0",
|
||||
"@elastic/ems-client": "7.9.3",
|
||||
"@elastic/eui": "24.1.0",
|
||||
"@elastic/eui": "26.3.1",
|
||||
"@elastic/filesaver": "1.1.2",
|
||||
"@elastic/good": "8.1.1-kibana2",
|
||||
"@elastic/numeral": "^2.5.0",
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"id": "bar",
|
||||
"ui": true
|
||||
"ui": true,
|
||||
"requiredBundles": ["foo"]
|
||||
}
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
p {
|
||||
background-color: rebeccapurple;
|
||||
}
|
|
@ -1,3 +1,5 @@
|
|||
@import "./other_styles.scss";
|
||||
|
||||
body {
|
||||
width: $globalStyleConstant;
|
||||
background-image: url("ui/icon.svg");
|
||||
|
|
|
@ -87,6 +87,11 @@ run(
|
|||
throw createFlagError('expected --report-stats to have no value');
|
||||
}
|
||||
|
||||
const filter = typeof flags.filter === 'string' ? [flags.filter] : flags.filter;
|
||||
if (!Array.isArray(filter) || !filter.every((f) => typeof f === 'string')) {
|
||||
throw createFlagError('expected --filter to be one or more strings');
|
||||
}
|
||||
|
||||
const config = OptimizerConfig.create({
|
||||
repoRoot: REPO_ROOT,
|
||||
watch,
|
||||
|
@ -99,6 +104,7 @@ run(
|
|||
extraPluginScanDirs,
|
||||
inspectWorkers,
|
||||
includeCoreBundle,
|
||||
filter,
|
||||
});
|
||||
|
||||
let update$ = runOptimizer(config);
|
||||
|
@ -128,12 +134,13 @@ run(
|
|||
'inspect-workers',
|
||||
'report-stats',
|
||||
],
|
||||
string: ['workers', 'scan-dir'],
|
||||
string: ['workers', 'scan-dir', 'filter'],
|
||||
default: {
|
||||
core: true,
|
||||
examples: true,
|
||||
cache: true,
|
||||
'inspect-workers': true,
|
||||
filter: [],
|
||||
},
|
||||
help: `
|
||||
--watch run the optimizer in watch mode
|
||||
|
@ -142,6 +149,7 @@ run(
|
|||
--profile profile the webpack builds and write stats.json files to build outputs
|
||||
--no-core disable generating the core bundle
|
||||
--no-cache disable the cache
|
||||
--filter comma-separated list of bundle id filters, results from multiple flags are merged, * and ! are supported
|
||||
--no-examples don't build the example plugins
|
||||
--dist create bundles that are suitable for inclusion in the Kibana distributable
|
||||
--scan-dir add a directory to the list of directories scanned for plugins (specify as many times as necessary)
|
||||
|
|
|
@ -50,6 +50,7 @@ it('creates cache keys', () => {
|
|||
"spec": Object {
|
||||
"contextDir": "/foo/bar",
|
||||
"id": "bar",
|
||||
"manifestPath": undefined,
|
||||
"outputDir": "/foo/bar/target",
|
||||
"publicDirNames": Array [
|
||||
"public",
|
||||
|
@ -85,6 +86,7 @@ it('parses bundles from JSON specs', () => {
|
|||
},
|
||||
"contextDir": "/foo/bar",
|
||||
"id": "bar",
|
||||
"manifestPath": undefined,
|
||||
"outputDir": "/foo/bar/target",
|
||||
"publicDirNames": Array [
|
||||
"public",
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
|
||||
import Path from 'path';
|
||||
import Fs from 'fs';
|
||||
|
||||
import { BundleCache } from './bundle_cache';
|
||||
import { UnknownVals } from './ts_helpers';
|
||||
|
@ -25,6 +26,11 @@ import { includes, ascending, entriesToObject } from './array_helpers';
|
|||
|
||||
const VALID_BUNDLE_TYPES = ['plugin' as const, 'entry' as const];
|
||||
|
||||
const DEFAULT_IMPLICIT_BUNDLE_DEPS = ['core'];
|
||||
|
||||
const isStringArray = (input: any): input is string[] =>
|
||||
Array.isArray(input) && input.every((x) => typeof x === 'string');
|
||||
|
||||
export interface BundleSpec {
|
||||
readonly type: typeof VALID_BUNDLE_TYPES[0];
|
||||
/** Unique id for this bundle */
|
||||
|
@ -37,6 +43,8 @@ export interface BundleSpec {
|
|||
readonly sourceRoot: string;
|
||||
/** Absolute path to the directory where output should be written */
|
||||
readonly outputDir: string;
|
||||
/** Absolute path to a kibana.json manifest file, if omitted we assume there are not dependenices */
|
||||
readonly manifestPath?: string;
|
||||
}
|
||||
|
||||
export class Bundle {
|
||||
|
@ -56,6 +64,12 @@ export class Bundle {
|
|||
public readonly sourceRoot: BundleSpec['sourceRoot'];
|
||||
/** Absolute path to the output directory for this bundle */
|
||||
public readonly outputDir: BundleSpec['outputDir'];
|
||||
/**
|
||||
* Absolute path to a manifest file with "requiredBundles" which will be
|
||||
* used to allow bundleRefs from this bundle to the exports of another bundle.
|
||||
* Every bundle mentioned in the `requiredBundles` must be built together.
|
||||
*/
|
||||
public readonly manifestPath: BundleSpec['manifestPath'];
|
||||
|
||||
public readonly cache: BundleCache;
|
||||
|
||||
|
@ -66,6 +80,7 @@ export class Bundle {
|
|||
this.contextDir = spec.contextDir;
|
||||
this.sourceRoot = spec.sourceRoot;
|
||||
this.outputDir = spec.outputDir;
|
||||
this.manifestPath = spec.manifestPath;
|
||||
|
||||
this.cache = new BundleCache(Path.resolve(this.outputDir, '.kbn-optimizer-cache'));
|
||||
}
|
||||
|
@ -96,8 +111,54 @@ export class Bundle {
|
|||
contextDir: this.contextDir,
|
||||
sourceRoot: this.sourceRoot,
|
||||
outputDir: this.outputDir,
|
||||
manifestPath: this.manifestPath,
|
||||
};
|
||||
}
|
||||
|
||||
readBundleDeps(): { implicit: string[]; explicit: string[] } {
|
||||
if (!this.manifestPath) {
|
||||
return {
|
||||
implicit: [...DEFAULT_IMPLICIT_BUNDLE_DEPS],
|
||||
explicit: [],
|
||||
};
|
||||
}
|
||||
|
||||
let json: string;
|
||||
try {
|
||||
json = Fs.readFileSync(this.manifestPath, 'utf8');
|
||||
} catch (error) {
|
||||
if (error.code !== 'ENOENT') {
|
||||
throw error;
|
||||
}
|
||||
|
||||
json = '{}';
|
||||
}
|
||||
|
||||
let parsedManifest: { requiredPlugins?: string[]; requiredBundles?: string[] };
|
||||
try {
|
||||
parsedManifest = JSON.parse(json);
|
||||
} catch (error) {
|
||||
throw new Error(
|
||||
`unable to parse manifest at [${this.manifestPath}], error: [${error.message}]`
|
||||
);
|
||||
}
|
||||
|
||||
if (typeof parsedManifest === 'object' && parsedManifest) {
|
||||
const explicit = parsedManifest.requiredBundles || [];
|
||||
const implicit = [...DEFAULT_IMPLICIT_BUNDLE_DEPS, ...(parsedManifest.requiredPlugins || [])];
|
||||
|
||||
if (isStringArray(explicit) && isStringArray(implicit)) {
|
||||
return {
|
||||
explicit,
|
||||
implicit,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
`Expected "requiredBundles" and "requiredPlugins" in manifest file [${this.manifestPath}] to be arrays of strings`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -152,6 +213,13 @@ export function parseBundles(json: string) {
|
|||
throw new Error('`bundles[]` must have an absolute path `outputDir` property');
|
||||
}
|
||||
|
||||
const { manifestPath } = spec;
|
||||
if (manifestPath !== undefined) {
|
||||
if (!(typeof manifestPath === 'string' && Path.isAbsolute(manifestPath))) {
|
||||
throw new Error('`bundles[]` must have an absolute path `manifestPath` property');
|
||||
}
|
||||
}
|
||||
|
||||
return new Bundle({
|
||||
type,
|
||||
id,
|
||||
|
@ -159,6 +227,7 @@ export function parseBundles(json: string) {
|
|||
contextDir,
|
||||
sourceRoot,
|
||||
outputDir,
|
||||
manifestPath,
|
||||
});
|
||||
}
|
||||
);
|
||||
|
|
|
@ -24,6 +24,7 @@ export interface State {
|
|||
optimizerCacheKey?: unknown;
|
||||
cacheKey?: unknown;
|
||||
moduleCount?: number;
|
||||
workUnits?: number;
|
||||
files?: string[];
|
||||
bundleRefExportIds?: string[];
|
||||
}
|
||||
|
@ -96,6 +97,10 @@ export class BundleCache {
|
|||
return this.get().cacheKey;
|
||||
}
|
||||
|
||||
public getWorkUnits() {
|
||||
return this.get().workUnits;
|
||||
}
|
||||
|
||||
public getOptimizerCacheKey() {
|
||||
return this.get().optimizerCacheKey;
|
||||
}
|
||||
|
|
|
@ -114,6 +114,10 @@ export class BundleRefs {
|
|||
|
||||
constructor(private readonly refs: BundleRef[]) {}
|
||||
|
||||
public forBundleIds(bundleIds: string[]) {
|
||||
return this.refs.filter((r) => bundleIds.includes(r.bundleId));
|
||||
}
|
||||
|
||||
public filterByExportIds(exportIds: string[]) {
|
||||
return this.refs.filter((r) => exportIds.includes(r.exportId));
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -139,6 +139,7 @@ it('builds expected bundles, saves bundle counts to metadata', async () => {
|
|||
expect(foo.cache.getModuleCount()).toBe(6);
|
||||
expect(foo.cache.getReferencedFiles()).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
<absolute path>/packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/plugins/foo/kibana.json,
|
||||
<absolute path>/packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/plugins/foo/public/async_import.ts,
|
||||
<absolute path>/packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/plugins/foo/public/ext.ts,
|
||||
<absolute path>/packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/plugins/foo/public/index.ts,
|
||||
|
@ -160,12 +161,17 @@ it('builds expected bundles, saves bundle counts to metadata', async () => {
|
|||
Array [
|
||||
<absolute path>/node_modules/css-loader/package.json,
|
||||
<absolute path>/node_modules/style-loader/package.json,
|
||||
<absolute path>/packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/plugins/bar/kibana.json,
|
||||
<absolute path>/packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/plugins/bar/public/index.scss,
|
||||
<absolute path>/packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/plugins/bar/public/index.ts,
|
||||
<absolute path>/packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/plugins/bar/public/legacy/_other_styles.scss,
|
||||
<absolute path>/packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/plugins/bar/public/legacy/styles.scss,
|
||||
<absolute path>/packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/plugins/bar/public/lib.ts,
|
||||
<absolute path>/packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/src/legacy/ui/public/icon.svg,
|
||||
<absolute path>/packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/src/legacy/ui/public/styles/_globals_v7dark.scss,
|
||||
<absolute path>/packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/src/legacy/ui/public/styles/_globals_v7light.scss,
|
||||
<absolute path>/packages/kbn-optimizer/target/worker/entry_point_creator.js,
|
||||
<absolute path>/packages/kbn-optimizer/target/worker/postcss.config.js,
|
||||
<absolute path>/packages/kbn-ui-shared-deps/public_path_module_creator.js,
|
||||
]
|
||||
`);
|
||||
|
|
|
@ -54,12 +54,18 @@ export function logOptimizerState(log: ToolingLog, config: OptimizerConfig) {
|
|||
|
||||
if (event?.type === 'worker started') {
|
||||
let moduleCount = 0;
|
||||
let workUnits = 0;
|
||||
for (const bundle of event.bundles) {
|
||||
moduleCount += bundle.cache.getModuleCount() ?? NaN;
|
||||
workUnits += bundle.cache.getWorkUnits() ?? NaN;
|
||||
}
|
||||
const mcString = isFinite(moduleCount) ? String(moduleCount) : '?';
|
||||
const bcString = String(event.bundles.length);
|
||||
log.info(`starting worker [${bcString} bundles, ${mcString} modules]`);
|
||||
|
||||
log.info(
|
||||
`starting worker [${event.bundles.length} ${
|
||||
event.bundles.length === 1 ? 'bundle' : 'bundles'
|
||||
}]`
|
||||
);
|
||||
log.debug(`modules [${moduleCount}] work units [${workUnits}]`);
|
||||
}
|
||||
|
||||
if (state.phase === 'reallocating') {
|
||||
|
|
|
@ -23,11 +23,11 @@ import { Bundle } from '../common';
|
|||
|
||||
import { assignBundlesToWorkers, Assignments } from './assign_bundles_to_workers';
|
||||
|
||||
const hasModuleCount = (b: Bundle) => b.cache.getModuleCount() !== undefined;
|
||||
const noModuleCount = (b: Bundle) => b.cache.getModuleCount() === undefined;
|
||||
const hasWorkUnits = (b: Bundle) => b.cache.getWorkUnits() !== undefined;
|
||||
const noWorkUnits = (b: Bundle) => b.cache.getWorkUnits() === undefined;
|
||||
const summarizeBundles = (w: Assignments) =>
|
||||
[
|
||||
w.moduleCount ? `${w.moduleCount} known modules` : '',
|
||||
w.workUnits ? `${w.workUnits} work units` : '',
|
||||
w.newBundles ? `${w.newBundles} new bundles` : '',
|
||||
]
|
||||
.filter(Boolean)
|
||||
|
@ -42,15 +42,15 @@ const assertReturnVal = (workers: Assignments[]) => {
|
|||
expect(workers).toBeInstanceOf(Array);
|
||||
for (const worker of workers) {
|
||||
expect(worker).toEqual({
|
||||
moduleCount: expect.any(Number),
|
||||
workUnits: expect.any(Number),
|
||||
newBundles: expect.any(Number),
|
||||
bundles: expect.any(Array),
|
||||
});
|
||||
|
||||
expect(worker.bundles.filter(noModuleCount).length).toBe(worker.newBundles);
|
||||
expect(worker.bundles.filter(noWorkUnits).length).toBe(worker.newBundles);
|
||||
expect(
|
||||
worker.bundles.filter(hasModuleCount).reduce((sum, b) => sum + b.cache.getModuleCount()!, 0)
|
||||
).toBe(worker.moduleCount);
|
||||
worker.bundles.filter(hasWorkUnits).reduce((sum, b) => sum + b.cache.getWorkUnits()!, 0)
|
||||
).toBe(worker.workUnits);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -76,7 +76,7 @@ const getBundles = ({
|
|||
for (let i = 1; i <= withCounts; i++) {
|
||||
const id = `foo${i}`;
|
||||
const bundle = testBundle(id);
|
||||
bundle.cache.set({ moduleCount: i % 5 === 0 ? i * 10 : i });
|
||||
bundle.cache.set({ workUnits: i % 5 === 0 ? i * 10 : i });
|
||||
bundles.push(bundle);
|
||||
}
|
||||
|
||||
|
@ -95,8 +95,8 @@ it('creates less workers if maxWorkersCount is larger than bundle count', () =>
|
|||
expect(workers.length).toBe(2);
|
||||
expect(readConfigs(workers)).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"worker 0 (1 known modules) => foo1",
|
||||
"worker 1 (2 known modules) => foo2",
|
||||
"worker 0 (1 work units) => foo1",
|
||||
"worker 1 (2 work units) => foo2",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
@ -121,10 +121,10 @@ it('distributes bundles without module counts evenly after assigning modules wit
|
|||
assertReturnVal(workers);
|
||||
expect(readConfigs(workers)).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"worker 0 (78 known modules, 3 new bundles) => foo5,foo11,foo8,foo6,foo2,foo1,bar9,bar5,bar1",
|
||||
"worker 1 (78 known modules, 3 new bundles) => foo16,foo14,foo13,foo12,foo9,foo7,foo4,foo3,bar8,bar4,bar0",
|
||||
"worker 2 (100 known modules, 2 new bundles) => foo10,bar7,bar3",
|
||||
"worker 3 (150 known modules, 2 new bundles) => foo15,bar6,bar2",
|
||||
"worker 0 (78 work units, 3 new bundles) => foo5,foo11,foo8,foo6,foo2,foo1,bar9,bar5,bar1",
|
||||
"worker 1 (78 work units, 3 new bundles) => foo16,foo14,foo13,foo12,foo9,foo7,foo4,foo3,bar8,bar4,bar0",
|
||||
"worker 2 (100 work units, 2 new bundles) => foo10,bar7,bar3",
|
||||
"worker 3 (150 work units, 2 new bundles) => foo15,bar6,bar2",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
@ -135,8 +135,8 @@ it('distributes 2 bundles to workers evenly', () => {
|
|||
assertReturnVal(workers);
|
||||
expect(readConfigs(workers)).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"worker 0 (1 known modules) => foo1",
|
||||
"worker 1 (2 known modules) => foo2",
|
||||
"worker 0 (1 work units) => foo1",
|
||||
"worker 1 (2 work units) => foo2",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
@ -147,10 +147,10 @@ it('distributes 5 bundles to workers evenly', () => {
|
|||
assertReturnVal(workers);
|
||||
expect(readConfigs(workers)).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"worker 0 (3 known modules) => foo2,foo1",
|
||||
"worker 1 (3 known modules) => foo3",
|
||||
"worker 2 (4 known modules) => foo4",
|
||||
"worker 3 (50 known modules) => foo5",
|
||||
"worker 0 (3 work units) => foo2,foo1",
|
||||
"worker 1 (3 work units) => foo3",
|
||||
"worker 2 (4 work units) => foo4",
|
||||
"worker 3 (50 work units) => foo5",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
@ -161,10 +161,10 @@ it('distributes 10 bundles to workers evenly', () => {
|
|||
assertReturnVal(workers);
|
||||
expect(readConfigs(workers)).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"worker 0 (20 known modules) => foo9,foo6,foo4,foo1",
|
||||
"worker 1 (20 known modules) => foo8,foo7,foo3,foo2",
|
||||
"worker 2 (50 known modules) => foo5",
|
||||
"worker 3 (100 known modules) => foo10",
|
||||
"worker 0 (20 work units) => foo9,foo6,foo4,foo1",
|
||||
"worker 1 (20 work units) => foo8,foo7,foo3,foo2",
|
||||
"worker 2 (50 work units) => foo5",
|
||||
"worker 3 (100 work units) => foo10",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
@ -175,10 +175,10 @@ it('distributes 15 bundles to workers evenly', () => {
|
|||
assertReturnVal(workers);
|
||||
expect(readConfigs(workers)).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"worker 0 (70 known modules) => foo14,foo13,foo12,foo11,foo9,foo6,foo4,foo1",
|
||||
"worker 1 (70 known modules) => foo5,foo8,foo7,foo3,foo2",
|
||||
"worker 2 (100 known modules) => foo10",
|
||||
"worker 3 (150 known modules) => foo15",
|
||||
"worker 0 (70 work units) => foo14,foo13,foo12,foo11,foo9,foo6,foo4,foo1",
|
||||
"worker 1 (70 work units) => foo5,foo8,foo7,foo3,foo2",
|
||||
"worker 2 (100 work units) => foo10",
|
||||
"worker 3 (150 work units) => foo15",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
@ -189,10 +189,10 @@ it('distributes 20 bundles to workers evenly', () => {
|
|||
assertReturnVal(workers);
|
||||
expect(readConfigs(workers)).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"worker 0 (153 known modules) => foo15,foo3",
|
||||
"worker 1 (153 known modules) => foo10,foo16,foo13,foo11,foo7,foo6",
|
||||
"worker 2 (154 known modules) => foo5,foo19,foo18,foo17,foo14,foo12,foo9,foo8,foo4,foo2,foo1",
|
||||
"worker 3 (200 known modules) => foo20",
|
||||
"worker 0 (153 work units) => foo15,foo3",
|
||||
"worker 1 (153 work units) => foo10,foo16,foo13,foo11,foo7,foo6",
|
||||
"worker 2 (154 work units) => foo5,foo19,foo18,foo17,foo14,foo12,foo9,foo8,foo4,foo2,foo1",
|
||||
"worker 3 (200 work units) => foo20",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
@ -203,10 +203,10 @@ it('distributes 25 bundles to workers evenly', () => {
|
|||
assertReturnVal(workers);
|
||||
expect(readConfigs(workers)).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"worker 0 (250 known modules) => foo20,foo17,foo13,foo9,foo8,foo2,foo1",
|
||||
"worker 1 (250 known modules) => foo15,foo23,foo22,foo18,foo16,foo11,foo7,foo3",
|
||||
"worker 2 (250 known modules) => foo10,foo5,foo24,foo21,foo19,foo14,foo12,foo6,foo4",
|
||||
"worker 3 (250 known modules) => foo25",
|
||||
"worker 0 (250 work units) => foo20,foo17,foo13,foo9,foo8,foo2,foo1",
|
||||
"worker 1 (250 work units) => foo15,foo23,foo22,foo18,foo16,foo11,foo7,foo3",
|
||||
"worker 2 (250 work units) => foo10,foo5,foo24,foo21,foo19,foo14,foo12,foo6,foo4",
|
||||
"worker 3 (250 work units) => foo25",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
@ -217,10 +217,10 @@ it('distributes 30 bundles to workers evenly', () => {
|
|||
assertReturnVal(workers);
|
||||
expect(readConfigs(workers)).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"worker 0 (352 known modules) => foo30,foo22,foo14,foo11,foo4,foo1",
|
||||
"worker 1 (352 known modules) => foo15,foo10,foo28,foo24,foo19,foo16,foo9,foo6",
|
||||
"worker 2 (353 known modules) => foo20,foo5,foo29,foo23,foo21,foo13,foo12,foo3,foo2",
|
||||
"worker 3 (353 known modules) => foo25,foo27,foo26,foo18,foo17,foo8,foo7",
|
||||
"worker 0 (352 work units) => foo30,foo22,foo14,foo11,foo4,foo1",
|
||||
"worker 1 (352 work units) => foo15,foo10,foo28,foo24,foo19,foo16,foo9,foo6",
|
||||
"worker 2 (353 work units) => foo20,foo5,foo29,foo23,foo21,foo13,foo12,foo3,foo2",
|
||||
"worker 3 (353 work units) => foo25,foo27,foo26,foo18,foo17,foo8,foo7",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
|
|
@ -20,19 +20,18 @@
|
|||
import { Bundle, descending, ascending } from '../common';
|
||||
|
||||
// helper types used inside getWorkerConfigs so we don't have
|
||||
// to calculate moduleCounts over and over
|
||||
|
||||
// to calculate workUnits over and over
|
||||
export interface Assignments {
|
||||
moduleCount: number;
|
||||
workUnits: number;
|
||||
newBundles: number;
|
||||
bundles: Bundle[];
|
||||
}
|
||||
|
||||
/** assign a wrapped bundle to a worker */
|
||||
const assignBundle = (worker: Assignments, bundle: Bundle) => {
|
||||
const moduleCount = bundle.cache.getModuleCount();
|
||||
if (moduleCount !== undefined) {
|
||||
worker.moduleCount += moduleCount;
|
||||
const workUnits = bundle.cache.getWorkUnits();
|
||||
if (workUnits !== undefined) {
|
||||
worker.workUnits += workUnits;
|
||||
} else {
|
||||
worker.newBundles += 1;
|
||||
}
|
||||
|
@ -59,7 +58,7 @@ export function assignBundlesToWorkers(bundles: Bundle[], maxWorkerCount: number
|
|||
const workers: Assignments[] = [];
|
||||
for (let i = 0; i < workerCount; i++) {
|
||||
workers.push({
|
||||
moduleCount: 0,
|
||||
workUnits: 0,
|
||||
newBundles: 0,
|
||||
bundles: [],
|
||||
});
|
||||
|
@ -67,18 +66,18 @@ export function assignBundlesToWorkers(bundles: Bundle[], maxWorkerCount: number
|
|||
|
||||
/**
|
||||
* separate the bundles which do and don't have module
|
||||
* counts and sort them by [moduleCount, id]
|
||||
* counts and sort them by [workUnits, id]
|
||||
*/
|
||||
const bundlesWithCountsDesc = bundles
|
||||
.filter((b) => b.cache.getModuleCount() !== undefined)
|
||||
.filter((b) => b.cache.getWorkUnits() !== undefined)
|
||||
.sort(
|
||||
descending(
|
||||
(b) => b.cache.getModuleCount(),
|
||||
(b) => b.cache.getWorkUnits(),
|
||||
(b) => b.id
|
||||
)
|
||||
);
|
||||
const bundlesWithoutModuleCounts = bundles
|
||||
.filter((b) => b.cache.getModuleCount() === undefined)
|
||||
.filter((b) => b.cache.getWorkUnits() === undefined)
|
||||
.sort(descending((b) => b.id));
|
||||
|
||||
/**
|
||||
|
@ -87,9 +86,9 @@ export function assignBundlesToWorkers(bundles: Bundle[], maxWorkerCount: number
|
|||
* with module counts are assigned
|
||||
*/
|
||||
while (bundlesWithCountsDesc.length) {
|
||||
const [smallestWorker, nextSmallestWorker] = workers.sort(ascending((w) => w.moduleCount));
|
||||
const [smallestWorker, nextSmallestWorker] = workers.sort(ascending((w) => w.workUnits));
|
||||
|
||||
while (!nextSmallestWorker || smallestWorker.moduleCount <= nextSmallestWorker.moduleCount) {
|
||||
while (!nextSmallestWorker || smallestWorker.workUnits <= nextSmallestWorker.workUnits) {
|
||||
const bundle = bundlesWithCountsDesc.shift();
|
||||
|
||||
if (!bundle) {
|
||||
|
@ -104,7 +103,7 @@ export function assignBundlesToWorkers(bundles: Bundle[], maxWorkerCount: number
|
|||
* assign bundles without module counts to workers round-robin
|
||||
* starting with the smallest workers
|
||||
*/
|
||||
workers.sort(ascending((w) => w.moduleCount));
|
||||
workers.sort(ascending((w) => w.workUnits));
|
||||
while (bundlesWithoutModuleCounts.length) {
|
||||
for (const worker of workers) {
|
||||
const bundle = bundlesWithoutModuleCounts.shift();
|
||||
|
|
72
packages/kbn-optimizer/src/optimizer/filter_by_id.test.ts
Normal file
72
packages/kbn-optimizer/src/optimizer/filter_by_id.test.ts
Normal file
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import { filterById, HasId } from './filter_by_id';
|
||||
|
||||
const bundles: HasId[] = [
|
||||
{ id: 'foo' },
|
||||
{ id: 'bar' },
|
||||
{ id: 'abc' },
|
||||
{ id: 'abcd' },
|
||||
{ id: 'abcde' },
|
||||
{ id: 'example_a' },
|
||||
];
|
||||
|
||||
const print = (result: HasId[]) =>
|
||||
result
|
||||
.map((b) => b.id)
|
||||
.sort((a, b) => a.localeCompare(b))
|
||||
.join(', ');
|
||||
|
||||
it('[] matches everything', () => {
|
||||
expect(print(filterById([], bundles))).toMatchInlineSnapshot(
|
||||
`"abc, abcd, abcde, bar, example_a, foo"`
|
||||
);
|
||||
});
|
||||
|
||||
it('* matches everything', () => {
|
||||
expect(print(filterById(['*'], bundles))).toMatchInlineSnapshot(
|
||||
`"abc, abcd, abcde, bar, example_a, foo"`
|
||||
);
|
||||
});
|
||||
|
||||
it('combines mutliple filters to select any bundle which is matched', () => {
|
||||
expect(print(filterById(['foo', 'bar'], bundles))).toMatchInlineSnapshot(`"bar, foo"`);
|
||||
expect(print(filterById(['bar', 'abc*'], bundles))).toMatchInlineSnapshot(
|
||||
`"abc, abcd, abcde, bar"`
|
||||
);
|
||||
});
|
||||
|
||||
it('matches everything if any filter is *', () => {
|
||||
expect(print(filterById(['*', '!abc*'], bundles))).toMatchInlineSnapshot(
|
||||
`"abc, abcd, abcde, bar, example_a, foo"`
|
||||
);
|
||||
});
|
||||
|
||||
it('only matches bundles which are matched by an entire single filter', () => {
|
||||
expect(print(filterById(['*,!abc*'], bundles))).toMatchInlineSnapshot(`"bar, example_a, foo"`);
|
||||
});
|
||||
|
||||
it('handles purely positive filters', () => {
|
||||
expect(print(filterById(['abc*'], bundles))).toMatchInlineSnapshot(`"abc, abcd, abcde"`);
|
||||
});
|
||||
|
||||
it('handles purely negative filters', () => {
|
||||
expect(print(filterById(['!abc*'], bundles))).toMatchInlineSnapshot(`"bar, example_a, foo"`);
|
||||
});
|
48
packages/kbn-optimizer/src/optimizer/filter_by_id.ts
Normal file
48
packages/kbn-optimizer/src/optimizer/filter_by_id.ts
Normal file
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* 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 interface HasId {
|
||||
id: string;
|
||||
}
|
||||
|
||||
function parseFilter(filter: string) {
|
||||
const positive: RegExp[] = [];
|
||||
const negative: RegExp[] = [];
|
||||
|
||||
for (const segment of filter.split(',')) {
|
||||
let trimmed = segment.trim();
|
||||
let list = positive;
|
||||
|
||||
if (trimmed.startsWith('!')) {
|
||||
trimmed = trimmed.slice(1);
|
||||
list = negative;
|
||||
}
|
||||
|
||||
list.push(new RegExp(`^${trimmed.split('*').join('.*')}$`));
|
||||
}
|
||||
|
||||
return (bundle: HasId) =>
|
||||
(!positive.length || positive.some((p) => p.test(bundle.id))) &&
|
||||
(!negative.length || !negative.some((p) => p.test(bundle.id)));
|
||||
}
|
||||
|
||||
export function filterById<T extends HasId>(filterStrings: string[], bundles: T[]) {
|
||||
const filters = filterStrings.map(parseFilter);
|
||||
return bundles.filter((b) => !filters.length || filters.some((f) => f(b)));
|
||||
}
|
|
@ -32,18 +32,21 @@ it('returns a bundle for core and each plugin', () => {
|
|||
id: 'foo',
|
||||
isUiPlugin: true,
|
||||
extraPublicDirs: [],
|
||||
manifestPath: '/repo/plugins/foo/kibana.json',
|
||||
},
|
||||
{
|
||||
directory: '/repo/plugins/bar',
|
||||
id: 'bar',
|
||||
isUiPlugin: false,
|
||||
extraPublicDirs: [],
|
||||
manifestPath: '/repo/plugins/bar/kibana.json',
|
||||
},
|
||||
{
|
||||
directory: '/outside/of/repo/plugins/baz',
|
||||
id: 'baz',
|
||||
isUiPlugin: true,
|
||||
extraPublicDirs: [],
|
||||
manifestPath: '/outside/of/repo/plugins/baz/kibana.json',
|
||||
},
|
||||
],
|
||||
'/repo'
|
||||
|
@ -53,6 +56,7 @@ it('returns a bundle for core and each plugin', () => {
|
|||
Object {
|
||||
"contextDir": <absolute path>/plugins/foo,
|
||||
"id": "foo",
|
||||
"manifestPath": <absolute path>/plugins/foo/kibana.json,
|
||||
"outputDir": <absolute path>/plugins/foo/target/public,
|
||||
"publicDirNames": Array [
|
||||
"public",
|
||||
|
@ -63,6 +67,7 @@ it('returns a bundle for core and each plugin', () => {
|
|||
Object {
|
||||
"contextDir": "/outside/of/repo/plugins/baz",
|
||||
"id": "baz",
|
||||
"manifestPath": "/outside/of/repo/plugins/baz/kibana.json",
|
||||
"outputDir": "/outside/of/repo/plugins/baz/target/public",
|
||||
"publicDirNames": Array [
|
||||
"public",
|
||||
|
|
|
@ -35,6 +35,7 @@ export function getPluginBundles(plugins: KibanaPlatformPlugin[], repoRoot: stri
|
|||
sourceRoot: repoRoot,
|
||||
contextDir: p.directory,
|
||||
outputDir: Path.resolve(p.directory, 'target/public'),
|
||||
manifestPath: p.manifestPath,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
|
|
@ -40,24 +40,28 @@ it('parses kibana.json files of plugins found in pluginDirs', () => {
|
|||
"extraPublicDirs": Array [],
|
||||
"id": "bar",
|
||||
"isUiPlugin": true,
|
||||
"manifestPath": <absolute path>/packages/kbn-optimizer/src/__fixtures__/mock_repo/plugins/bar/kibana.json,
|
||||
},
|
||||
Object {
|
||||
"directory": <absolute path>/packages/kbn-optimizer/src/__fixtures__/mock_repo/plugins/foo,
|
||||
"extraPublicDirs": Array [],
|
||||
"id": "foo",
|
||||
"isUiPlugin": true,
|
||||
"manifestPath": <absolute path>/packages/kbn-optimizer/src/__fixtures__/mock_repo/plugins/foo/kibana.json,
|
||||
},
|
||||
Object {
|
||||
"directory": <absolute path>/packages/kbn-optimizer/src/__fixtures__/mock_repo/plugins/nested/baz,
|
||||
"extraPublicDirs": Array [],
|
||||
"id": "baz",
|
||||
"isUiPlugin": false,
|
||||
"manifestPath": <absolute path>/packages/kbn-optimizer/src/__fixtures__/mock_repo/plugins/nested/baz/kibana.json,
|
||||
},
|
||||
Object {
|
||||
"directory": <absolute path>/packages/kbn-optimizer/src/__fixtures__/mock_repo/test_plugins/test_baz,
|
||||
"extraPublicDirs": Array [],
|
||||
"id": "test_baz",
|
||||
"isUiPlugin": false,
|
||||
"manifestPath": <absolute path>/packages/kbn-optimizer/src/__fixtures__/mock_repo/test_plugins/test_baz/kibana.json,
|
||||
},
|
||||
]
|
||||
`);
|
||||
|
|
|
@ -24,6 +24,7 @@ import loadJsonFile from 'load-json-file';
|
|||
|
||||
export interface KibanaPlatformPlugin {
|
||||
readonly directory: string;
|
||||
readonly manifestPath: string;
|
||||
readonly id: string;
|
||||
readonly isUiPlugin: boolean;
|
||||
readonly extraPublicDirs: string[];
|
||||
|
@ -92,6 +93,7 @@ function readKibanaPlatformPlugin(manifestPath: string): KibanaPlatformPlugin {
|
|||
|
||||
return {
|
||||
directory: Path.dirname(manifestPath),
|
||||
manifestPath,
|
||||
id: manifest.id,
|
||||
isUiPlugin: !!manifest.ui,
|
||||
extraPublicDirs: extraPublicDirs || [],
|
||||
|
|
|
@ -21,6 +21,7 @@ jest.mock('./assign_bundles_to_workers.ts');
|
|||
jest.mock('./kibana_platform_plugins.ts');
|
||||
jest.mock('./get_plugin_bundles.ts');
|
||||
jest.mock('../common/theme_tags.ts');
|
||||
jest.mock('./filter_by_id.ts');
|
||||
|
||||
import Path from 'path';
|
||||
import Os from 'os';
|
||||
|
@ -113,6 +114,7 @@ describe('OptimizerConfig::parseOptions()', () => {
|
|||
Object {
|
||||
"cache": true,
|
||||
"dist": false,
|
||||
"filters": Array [],
|
||||
"includeCoreBundle": false,
|
||||
"inspectWorkers": false,
|
||||
"maxWorkerCount": 2,
|
||||
|
@ -139,6 +141,7 @@ describe('OptimizerConfig::parseOptions()', () => {
|
|||
Object {
|
||||
"cache": false,
|
||||
"dist": false,
|
||||
"filters": Array [],
|
||||
"includeCoreBundle": false,
|
||||
"inspectWorkers": false,
|
||||
"maxWorkerCount": 2,
|
||||
|
@ -165,6 +168,7 @@ describe('OptimizerConfig::parseOptions()', () => {
|
|||
Object {
|
||||
"cache": true,
|
||||
"dist": false,
|
||||
"filters": Array [],
|
||||
"includeCoreBundle": false,
|
||||
"inspectWorkers": false,
|
||||
"maxWorkerCount": 2,
|
||||
|
@ -193,6 +197,7 @@ describe('OptimizerConfig::parseOptions()', () => {
|
|||
Object {
|
||||
"cache": true,
|
||||
"dist": false,
|
||||
"filters": Array [],
|
||||
"includeCoreBundle": false,
|
||||
"inspectWorkers": false,
|
||||
"maxWorkerCount": 2,
|
||||
|
@ -218,6 +223,7 @@ describe('OptimizerConfig::parseOptions()', () => {
|
|||
Object {
|
||||
"cache": true,
|
||||
"dist": false,
|
||||
"filters": Array [],
|
||||
"includeCoreBundle": false,
|
||||
"inspectWorkers": false,
|
||||
"maxWorkerCount": 2,
|
||||
|
@ -243,6 +249,7 @@ describe('OptimizerConfig::parseOptions()', () => {
|
|||
Object {
|
||||
"cache": true,
|
||||
"dist": false,
|
||||
"filters": Array [],
|
||||
"includeCoreBundle": false,
|
||||
"inspectWorkers": false,
|
||||
"maxWorkerCount": 100,
|
||||
|
@ -265,6 +272,7 @@ describe('OptimizerConfig::parseOptions()', () => {
|
|||
Object {
|
||||
"cache": false,
|
||||
"dist": false,
|
||||
"filters": Array [],
|
||||
"includeCoreBundle": false,
|
||||
"inspectWorkers": false,
|
||||
"maxWorkerCount": 100,
|
||||
|
@ -287,6 +295,7 @@ describe('OptimizerConfig::parseOptions()', () => {
|
|||
Object {
|
||||
"cache": false,
|
||||
"dist": false,
|
||||
"filters": Array [],
|
||||
"includeCoreBundle": false,
|
||||
"inspectWorkers": false,
|
||||
"maxWorkerCount": 100,
|
||||
|
@ -310,6 +319,7 @@ describe('OptimizerConfig::parseOptions()', () => {
|
|||
Object {
|
||||
"cache": false,
|
||||
"dist": false,
|
||||
"filters": Array [],
|
||||
"includeCoreBundle": false,
|
||||
"inspectWorkers": false,
|
||||
"maxWorkerCount": 100,
|
||||
|
@ -333,6 +343,7 @@ describe('OptimizerConfig::parseOptions()', () => {
|
|||
Object {
|
||||
"cache": true,
|
||||
"dist": false,
|
||||
"filters": Array [],
|
||||
"includeCoreBundle": false,
|
||||
"inspectWorkers": false,
|
||||
"maxWorkerCount": 100,
|
||||
|
@ -358,6 +369,7 @@ describe('OptimizerConfig::create()', () => {
|
|||
const findKibanaPlatformPlugins: jest.Mock = jest.requireMock('./kibana_platform_plugins.ts')
|
||||
.findKibanaPlatformPlugins;
|
||||
const getPluginBundles: jest.Mock = jest.requireMock('./get_plugin_bundles.ts').getPluginBundles;
|
||||
const filterById: jest.Mock = jest.requireMock('./filter_by_id.ts').filterById;
|
||||
|
||||
beforeEach(() => {
|
||||
if ('mock' in OptimizerConfig.parseOptions) {
|
||||
|
@ -370,6 +382,7 @@ describe('OptimizerConfig::create()', () => {
|
|||
]);
|
||||
findKibanaPlatformPlugins.mockReturnValue(Symbol('new platform plugins'));
|
||||
getPluginBundles.mockReturnValue([Symbol('bundle1'), Symbol('bundle2')]);
|
||||
filterById.mockReturnValue(Symbol('filtered bundles'));
|
||||
|
||||
jest.spyOn(OptimizerConfig, 'parseOptions').mockImplementation((): any => ({
|
||||
cache: Symbol('parsed cache'),
|
||||
|
@ -382,6 +395,7 @@ describe('OptimizerConfig::create()', () => {
|
|||
themeTags: Symbol('theme tags'),
|
||||
inspectWorkers: Symbol('parsed inspect workers'),
|
||||
profileWebpack: Symbol('parsed profile webpack'),
|
||||
filters: [],
|
||||
}));
|
||||
});
|
||||
|
||||
|
@ -392,10 +406,7 @@ describe('OptimizerConfig::create()', () => {
|
|||
|
||||
expect(config).toMatchInlineSnapshot(`
|
||||
OptimizerConfig {
|
||||
"bundles": Array [
|
||||
Symbol(bundle1),
|
||||
Symbol(bundle2),
|
||||
],
|
||||
"bundles": Symbol(filtered bundles),
|
||||
"cache": Symbol(parsed cache),
|
||||
"dist": Symbol(parsed dist),
|
||||
"inspectWorkers": Symbol(parsed inspect workers),
|
||||
|
@ -431,6 +442,32 @@ describe('OptimizerConfig::create()', () => {
|
|||
}
|
||||
`);
|
||||
|
||||
expect(filterById.mock).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"calls": Array [
|
||||
Array [
|
||||
Array [],
|
||||
Array [
|
||||
Symbol(bundle1),
|
||||
Symbol(bundle2),
|
||||
],
|
||||
],
|
||||
],
|
||||
"instances": Array [
|
||||
[Window],
|
||||
],
|
||||
"invocationCallOrder": Array [
|
||||
23,
|
||||
],
|
||||
"results": Array [
|
||||
Object {
|
||||
"type": "return",
|
||||
"value": Symbol(filtered bundles),
|
||||
},
|
||||
],
|
||||
}
|
||||
`);
|
||||
|
||||
expect(getPluginBundles.mock).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"calls": Array [
|
||||
|
|
|
@ -31,6 +31,7 @@ import {
|
|||
|
||||
import { findKibanaPlatformPlugins, KibanaPlatformPlugin } from './kibana_platform_plugins';
|
||||
import { getPluginBundles } from './get_plugin_bundles';
|
||||
import { filterById } from './filter_by_id';
|
||||
|
||||
function pickMaxWorkerCount(dist: boolean) {
|
||||
// don't break if cpus() returns nothing, or an empty array
|
||||
|
@ -77,6 +78,18 @@ interface Options {
|
|||
pluginScanDirs?: string[];
|
||||
/** absolute paths that should be added to the default scan dirs */
|
||||
extraPluginScanDirs?: string[];
|
||||
/**
|
||||
* array of comma separated patterns that will be matched against bundle ids.
|
||||
* bundles will only be built if they match one of the specified patterns.
|
||||
* `*` can exist anywhere in each pattern and will match anything, `!` inverts the pattern
|
||||
*
|
||||
* examples:
|
||||
* --filter foo --filter bar # [foo, bar], excludes [foobar]
|
||||
* --filter foo,bar # [foo, bar], excludes [foobar]
|
||||
* --filter foo* # [foo, foobar], excludes [bar]
|
||||
* --filter f*r # [foobar], excludes [foo, bar]
|
||||
*/
|
||||
filter?: string[];
|
||||
|
||||
/** flag that causes the core bundle to be built along with plugins */
|
||||
includeCoreBundle?: boolean;
|
||||
|
@ -103,6 +116,7 @@ interface ParsedOptions {
|
|||
dist: boolean;
|
||||
pluginPaths: string[];
|
||||
pluginScanDirs: string[];
|
||||
filters: string[];
|
||||
inspectWorkers: boolean;
|
||||
includeCoreBundle: boolean;
|
||||
themeTags: ThemeTags;
|
||||
|
@ -118,6 +132,7 @@ export class OptimizerConfig {
|
|||
const inspectWorkers = !!options.inspectWorkers;
|
||||
const cache = options.cache !== false && !process.env.KBN_OPTIMIZER_NO_CACHE;
|
||||
const includeCoreBundle = !!options.includeCoreBundle;
|
||||
const filters = options.filter || [];
|
||||
|
||||
const repoRoot = options.repoRoot;
|
||||
if (!Path.isAbsolute(repoRoot)) {
|
||||
|
@ -172,6 +187,7 @@ export class OptimizerConfig {
|
|||
cache,
|
||||
pluginScanDirs,
|
||||
pluginPaths,
|
||||
filters,
|
||||
inspectWorkers,
|
||||
includeCoreBundle,
|
||||
themeTags,
|
||||
|
@ -198,7 +214,7 @@ export class OptimizerConfig {
|
|||
];
|
||||
|
||||
return new OptimizerConfig(
|
||||
bundles,
|
||||
filterById(options.filters, bundles),
|
||||
options.cache,
|
||||
options.watch,
|
||||
options.inspectWorkers,
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
// @ts-ignore not typed by @types/webpack
|
||||
import Module from 'webpack/lib/Module';
|
||||
import { BundleRef } from '../common';
|
||||
|
||||
export class BundleRefModule extends Module {
|
||||
public built = false;
|
||||
|
@ -17,12 +18,12 @@ export class BundleRefModule extends Module {
|
|||
public buildInfo?: any;
|
||||
public exportsArgument = '__webpack_exports__';
|
||||
|
||||
constructor(public readonly exportId: string) {
|
||||
constructor(public readonly ref: BundleRef) {
|
||||
super('kbn/bundleRef', null);
|
||||
}
|
||||
|
||||
libIdent() {
|
||||
return this.exportId;
|
||||
return this.ref.exportId;
|
||||
}
|
||||
|
||||
chunkCondition(chunk: any) {
|
||||
|
@ -30,7 +31,7 @@ export class BundleRefModule extends Module {
|
|||
}
|
||||
|
||||
identifier() {
|
||||
return '@kbn/bundleRef ' + JSON.stringify(this.exportId);
|
||||
return '@kbn/bundleRef ' + JSON.stringify(this.ref.exportId);
|
||||
}
|
||||
|
||||
readableIdentifier() {
|
||||
|
@ -51,7 +52,7 @@ export class BundleRefModule extends Module {
|
|||
source() {
|
||||
return `
|
||||
__webpack_require__.r(__webpack_exports__);
|
||||
var ns = __kbnBundles__.get('${this.exportId}');
|
||||
var ns = __kbnBundles__.get('${this.ref.exportId}');
|
||||
Object.defineProperties(__webpack_exports__, Object.getOwnPropertyDescriptors(ns))
|
||||
`;
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ export class BundleRefsPlugin {
|
|||
private readonly resolvedRefEntryCache = new Map<BundleRef, Promise<string>>();
|
||||
private readonly resolvedRequestCache = new Map<string, Promise<string | undefined>>();
|
||||
private readonly ignorePrefix = Path.resolve(this.bundle.contextDir) + Path.sep;
|
||||
private allowedBundleIds = new Set<string>();
|
||||
|
||||
constructor(private readonly bundle: Bundle, private readonly bundleRefs: BundleRefs) {}
|
||||
|
||||
|
@ -81,6 +82,45 @@ export class BundleRefsPlugin {
|
|||
}
|
||||
);
|
||||
});
|
||||
|
||||
compiler.hooks.compilation.tap('BundleRefsPlugin/getRequiredBundles', (compilation) => {
|
||||
this.allowedBundleIds.clear();
|
||||
|
||||
const manifestPath = this.bundle.manifestPath;
|
||||
if (!manifestPath) {
|
||||
return;
|
||||
}
|
||||
|
||||
const deps = this.bundle.readBundleDeps();
|
||||
for (const ref of this.bundleRefs.forBundleIds([...deps.explicit, ...deps.implicit])) {
|
||||
this.allowedBundleIds.add(ref.bundleId);
|
||||
}
|
||||
|
||||
compilation.hooks.additionalAssets.tap('BundleRefsPlugin/watchManifest', () => {
|
||||
compilation.fileDependencies.add(manifestPath);
|
||||
});
|
||||
|
||||
compilation.hooks.finishModules.tapPromise(
|
||||
'BundleRefsPlugin/finishModules',
|
||||
async (modules) => {
|
||||
const usedBundleIds = (modules as any[])
|
||||
.filter((m: any): m is BundleRefModule => m instanceof BundleRefModule)
|
||||
.map((m) => m.ref.bundleId);
|
||||
|
||||
const unusedBundleIds = deps.explicit
|
||||
.filter((id) => !usedBundleIds.includes(id))
|
||||
.join(', ');
|
||||
|
||||
if (unusedBundleIds) {
|
||||
const error = new Error(
|
||||
`Bundle for [${this.bundle.id}] lists [${unusedBundleIds}] as a required bundle, but does not use it. Please remove it.`
|
||||
);
|
||||
(error as any).file = manifestPath;
|
||||
compilation.errors.push(error);
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
private cachedResolveRefEntry(ref: BundleRef) {
|
||||
|
@ -170,21 +210,29 @@ export class BundleRefsPlugin {
|
|||
return;
|
||||
}
|
||||
|
||||
const eligibleRefs = this.bundleRefs.filterByContextPrefix(this.bundle, resolved);
|
||||
if (!eligibleRefs.length) {
|
||||
const possibleRefs = this.bundleRefs.filterByContextPrefix(this.bundle, resolved);
|
||||
if (!possibleRefs.length) {
|
||||
// import doesn't match a bundle context
|
||||
return;
|
||||
}
|
||||
|
||||
for (const ref of eligibleRefs) {
|
||||
for (const ref of possibleRefs) {
|
||||
const resolvedEntry = await this.cachedResolveRefEntry(ref);
|
||||
if (resolved === resolvedEntry) {
|
||||
return new BundleRefModule(ref.exportId);
|
||||
if (resolved !== resolvedEntry) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!this.allowedBundleIds.has(ref.bundleId)) {
|
||||
throw new Error(
|
||||
`import [${request}] references a public export of the [${ref.bundleId}] bundle, but that bundle is not in the "requiredPlugins" or "requiredBundles" list in the plugin manifest [${this.bundle.manifestPath}]`
|
||||
);
|
||||
}
|
||||
|
||||
return new BundleRefModule(ref);
|
||||
}
|
||||
|
||||
const bundleId = Array.from(new Set(eligibleRefs.map((r) => r.bundleId))).join(', ');
|
||||
const publicDir = eligibleRefs.map((r) => r.entry).join(', ');
|
||||
const bundleId = Array.from(new Set(possibleRefs.map((r) => r.bundleId))).join(', ');
|
||||
const publicDir = possibleRefs.map((r) => r.entry).join(', ');
|
||||
throw new Error(
|
||||
`import [${request}] references a non-public export of the [${bundleId}] bundle and must point to one of the public directories: [${publicDir}]`
|
||||
);
|
||||
|
|
|
@ -50,6 +50,15 @@ import {
|
|||
|
||||
const PLUGIN_NAME = '@kbn/optimizer';
|
||||
|
||||
/**
|
||||
* sass-loader creates about a 40% overhead on the overall optimizer runtime, and
|
||||
* so this constant is used to indicate to assignBundlesToWorkers() that there is
|
||||
* extra work done in a bundle that has a lot of scss imports. The value is
|
||||
* arbitrary and just intended to weigh the bundles so that they are distributed
|
||||
* across mulitple workers on machines with lots of cores.
|
||||
*/
|
||||
const EXTRA_SCSS_WORK_UNITS = 100;
|
||||
|
||||
/**
|
||||
* Create an Observable<CompilerMsg> for a specific child compiler + bundle
|
||||
*/
|
||||
|
@ -102,6 +111,11 @@ const observeCompiler = (
|
|||
const bundleRefExportIds: string[] = [];
|
||||
const referencedFiles = new Set<string>();
|
||||
let normalModuleCount = 0;
|
||||
let workUnits = stats.compilation.fileDependencies.size;
|
||||
|
||||
if (bundle.manifestPath) {
|
||||
referencedFiles.add(bundle.manifestPath);
|
||||
}
|
||||
|
||||
for (const module of stats.compilation.modules) {
|
||||
if (isNormalModule(module)) {
|
||||
|
@ -111,6 +125,15 @@ const observeCompiler = (
|
|||
|
||||
if (!parsedPath.dirs.includes('node_modules')) {
|
||||
referencedFiles.add(path);
|
||||
|
||||
if (path.endsWith('.scss')) {
|
||||
workUnits += EXTRA_SCSS_WORK_UNITS;
|
||||
|
||||
for (const depPath of module.buildInfo.fileDependencies) {
|
||||
referencedFiles.add(depPath);
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -127,7 +150,7 @@ const observeCompiler = (
|
|||
}
|
||||
|
||||
if (module instanceof BundleRefModule) {
|
||||
bundleRefExportIds.push(module.exportId);
|
||||
bundleRefExportIds.push(module.ref.exportId);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -158,6 +181,7 @@ const observeCompiler = (
|
|||
optimizerCacheKey: workerConfig.optimizerCacheKey,
|
||||
cacheKey: bundle.createCacheKey(files, mtimes),
|
||||
moduleCount: normalModuleCount,
|
||||
workUnits,
|
||||
files,
|
||||
});
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@elastic/charts": "19.8.1",
|
||||
"@elastic/eui": "24.1.0",
|
||||
"@elastic/eui": "26.3.1",
|
||||
"@elastic/numeral": "^2.5.0",
|
||||
"@kbn/i18n": "1.0.0",
|
||||
"@kbn/monaco": "1.0.0",
|
||||
|
|
|
@ -261,7 +261,7 @@ export class ClusterManager {
|
|||
/debug\.log$/,
|
||||
...pluginInternalDirsIgnore,
|
||||
fromRoot('src/legacy/server/sass/__tmp__'),
|
||||
fromRoot('x-pack/plugins/reporting/.chromium'),
|
||||
fromRoot('x-pack/plugins/reporting/chromium'),
|
||||
fromRoot('x-pack/plugins/security_solution/cypress'),
|
||||
fromRoot('x-pack/plugins/apm/e2e'),
|
||||
fromRoot('x-pack/plugins/apm/scripts'),
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { Breadcrumb as EuiBreadcrumb, IconType } from '@elastic/eui';
|
||||
import { EuiBreadcrumb, IconType } from '@elastic/eui';
|
||||
import React from 'react';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import { BehaviorSubject, combineLatest, merge, Observable, of, ReplaySubject } from 'rxjs';
|
||||
|
|
|
@ -372,12 +372,13 @@ exports[`CollapsibleNav renders links grouped by category 1`] = `
|
|||
handler={[Function]}
|
||||
/>
|
||||
<EuiOverlayMask
|
||||
headerZindexLocation="below"
|
||||
onClick={[Function]}
|
||||
>
|
||||
<Portal
|
||||
containerInfo={
|
||||
<div
|
||||
class="euiOverlayMask"
|
||||
class="euiOverlayMask euiOverlayMask--belowHeader"
|
||||
/>
|
||||
}
|
||||
/>
|
||||
|
@ -3908,16 +3909,9 @@ exports[`CollapsibleNav renders the default nav 2`] = `
|
|||
handler={[Function]}
|
||||
/>
|
||||
<EuiOverlayMask
|
||||
headerZindexLocation="below"
|
||||
onClick={[Function]}
|
||||
>
|
||||
<Portal
|
||||
containerInfo={
|
||||
<div
|
||||
class="euiOverlayMask"
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</EuiOverlayMask>
|
||||
/>
|
||||
<EuiFocusTrap
|
||||
clickOutsideDisables={true}
|
||||
disabled={false}
|
||||
|
|
|
@ -2703,7 +2703,7 @@ exports[`Header renders 2`] = `
|
|||
>
|
||||
<nav
|
||||
aria-label="breadcrumb"
|
||||
className="euiBreadcrumbs euiHeaderBreadcrumbs euiBreadcrumbs--truncate euiBreadcrumbs--responsive"
|
||||
className="euiBreadcrumbs euiHeaderBreadcrumbs euiBreadcrumbs--truncate"
|
||||
data-test-subj="breadcrumbs"
|
||||
>
|
||||
<EuiInnerText>
|
||||
|
@ -6914,7 +6914,7 @@ exports[`Header renders 3`] = `
|
|||
>
|
||||
<nav
|
||||
aria-label="breadcrumb"
|
||||
className="euiBreadcrumbs euiHeaderBreadcrumbs euiBreadcrumbs--truncate euiBreadcrumbs--responsive"
|
||||
className="euiBreadcrumbs euiHeaderBreadcrumbs euiBreadcrumbs--truncate"
|
||||
data-test-subj="breadcrumbs"
|
||||
>
|
||||
<EuiInnerText>
|
||||
|
@ -12347,7 +12347,7 @@ exports[`Header renders 4`] = `
|
|||
>
|
||||
<nav
|
||||
aria-label="breadcrumb"
|
||||
className="euiBreadcrumbs euiHeaderBreadcrumbs euiBreadcrumbs--truncate euiBreadcrumbs--responsive"
|
||||
className="euiBreadcrumbs euiHeaderBreadcrumbs euiBreadcrumbs--truncate"
|
||||
data-test-subj="breadcrumbs"
|
||||
>
|
||||
<EuiInnerText>
|
||||
|
|
|
@ -13,29 +13,14 @@ exports[`HeaderBreadcrumbs renders updates to the breadcrumbs$ observable 1`] =
|
|||
|
||||
exports[`HeaderBreadcrumbs renders updates to the breadcrumbs$ observable 2`] = `
|
||||
Array [
|
||||
<EuiLink
|
||||
<span
|
||||
aria-current="false"
|
||||
className="euiBreadcrumb"
|
||||
color="subdued"
|
||||
data-test-subj="breadcrumb first"
|
||||
title="First"
|
||||
>
|
||||
<button
|
||||
className="euiLink euiLink--subdued euiBreadcrumb"
|
||||
data-test-subj="breadcrumb first"
|
||||
title="First"
|
||||
type="button"
|
||||
>
|
||||
First
|
||||
</button>
|
||||
</EuiLink>,
|
||||
<button
|
||||
className="euiLink euiLink--subdued euiBreadcrumb"
|
||||
data-test-subj="breadcrumb first"
|
||||
title="First"
|
||||
type="button"
|
||||
>
|
||||
First
|
||||
</button>,
|
||||
</span>,
|
||||
<span
|
||||
aria-current="page"
|
||||
className="euiBreadcrumb euiBreadcrumb--last"
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
@include euiHeaderAffordForFixed;
|
||||
|
||||
// TODO #64541
|
||||
// Delete this block
|
||||
.chrHeaderWrapper:not(.headerWrapper) {
|
||||
|
|
|
@ -4,6 +4,7 @@ exports[`renders matching snapshot 1`] = `
|
|||
<EuiGlobalToastList
|
||||
data-test-subj="globalToastList"
|
||||
dismissToast={[Function]}
|
||||
side="right"
|
||||
toastLifeTimeMs={Infinity}
|
||||
toasts={Array []}
|
||||
/>
|
||||
|
|
|
@ -32,6 +32,7 @@ function createManifest(
|
|||
configPath: ['path'],
|
||||
requiredPlugins: required,
|
||||
optionalPlugins: optional,
|
||||
requiredBundles: [],
|
||||
} as DiscoveredPlugin;
|
||||
}
|
||||
|
||||
|
|
|
@ -73,6 +73,7 @@ function createManifest(
|
|||
configPath: ['path'],
|
||||
requiredPlugins: required,
|
||||
optionalPlugins: optional,
|
||||
requiredBundles: [],
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
import { Action } from 'history';
|
||||
import Boom from 'boom';
|
||||
import { Breadcrumb } from '@elastic/eui';
|
||||
import { BulkIndexDocumentsParams } from 'elasticsearch';
|
||||
import { CatAliasesParams } from 'elasticsearch';
|
||||
import { CatAllocationParams } from 'elasticsearch';
|
||||
|
@ -37,6 +36,7 @@ import { DeleteDocumentByQueryParams } from 'elasticsearch';
|
|||
import { DeleteDocumentParams } from 'elasticsearch';
|
||||
import { DeleteScriptParams } from 'elasticsearch';
|
||||
import { DeleteTemplateParams } from 'elasticsearch';
|
||||
import { EuiBreadcrumb } from '@elastic/eui';
|
||||
import { EuiButtonEmptyProps } from '@elastic/eui';
|
||||
import { EuiConfirmModalProps } from '@elastic/eui';
|
||||
import { EuiGlobalToastListToast } from '@elastic/eui';
|
||||
|
@ -334,7 +334,7 @@ export interface ChromeBrand {
|
|||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export type ChromeBreadcrumb = Breadcrumb;
|
||||
export type ChromeBreadcrumb = EuiBreadcrumb;
|
||||
|
||||
// @public
|
||||
export interface ChromeDocTitle {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@import '@elastic/eui/src/components/header/variables';
|
||||
@import '@elastic/eui/src/global_styling/variables/header';
|
||||
@import '@elastic/eui/src/components/nav_drawer/variables';
|
||||
|
||||
/**
|
||||
|
|
|
@ -109,6 +109,7 @@ beforeEach(() => {
|
|||
[
|
||||
'plugin-id',
|
||||
{
|
||||
requiredBundles: [],
|
||||
publicTargetDir: 'path/to/target/public',
|
||||
publicAssetsDir: '/plugins/name/assets/',
|
||||
},
|
||||
|
|
|
@ -302,6 +302,7 @@ test('set defaults for all missing optional fields', async () => {
|
|||
kibanaVersion: '7.0.0',
|
||||
optionalPlugins: [],
|
||||
requiredPlugins: [],
|
||||
requiredBundles: [],
|
||||
server: true,
|
||||
ui: false,
|
||||
});
|
||||
|
@ -331,6 +332,7 @@ test('return all set optional fields as they are in manifest', async () => {
|
|||
version: 'some-version',
|
||||
kibanaVersion: '7.0.0',
|
||||
optionalPlugins: ['some-optional-plugin'],
|
||||
requiredBundles: [],
|
||||
requiredPlugins: ['some-required-plugin', 'some-required-plugin-2'],
|
||||
server: false,
|
||||
ui: true,
|
||||
|
@ -361,6 +363,7 @@ test('return manifest when plugin expected Kibana version matches actual version
|
|||
kibanaVersion: '7.0.0-alpha2',
|
||||
optionalPlugins: [],
|
||||
requiredPlugins: ['some-required-plugin'],
|
||||
requiredBundles: [],
|
||||
server: true,
|
||||
ui: false,
|
||||
});
|
||||
|
@ -390,6 +393,7 @@ test('return manifest when plugin expected Kibana version is `kibana`', async ()
|
|||
kibanaVersion: 'kibana',
|
||||
optionalPlugins: [],
|
||||
requiredPlugins: ['some-required-plugin'],
|
||||
requiredBundles: [],
|
||||
server: true,
|
||||
ui: true,
|
||||
});
|
||||
|
|
|
@ -58,6 +58,7 @@ const KNOWN_MANIFEST_FIELDS = (() => {
|
|||
ui: true,
|
||||
server: true,
|
||||
extraPublicDirs: true,
|
||||
requiredBundles: true,
|
||||
};
|
||||
|
||||
return new Set(Object.keys(manifestFields));
|
||||
|
@ -191,6 +192,7 @@ export async function parseManifest(
|
|||
configPath: manifest.configPath || snakeCase(manifest.id),
|
||||
requiredPlugins: Array.isArray(manifest.requiredPlugins) ? manifest.requiredPlugins : [],
|
||||
optionalPlugins: Array.isArray(manifest.optionalPlugins) ? manifest.optionalPlugins : [],
|
||||
requiredBundles: Array.isArray(manifest.requiredBundles) ? manifest.requiredBundles : [],
|
||||
ui: includesUiPlugin,
|
||||
server: includesServerPlugin,
|
||||
extraPublicDirs: manifest.extraPublicDirs,
|
||||
|
|
|
@ -43,6 +43,7 @@ describe('PluginsService', () => {
|
|||
disabled = false,
|
||||
version = 'some-version',
|
||||
requiredPlugins = [],
|
||||
requiredBundles = [],
|
||||
optionalPlugins = [],
|
||||
kibanaVersion = '7.0.0',
|
||||
configPath = [path],
|
||||
|
@ -53,6 +54,7 @@ describe('PluginsService', () => {
|
|||
disabled?: boolean;
|
||||
version?: string;
|
||||
requiredPlugins?: string[];
|
||||
requiredBundles?: string[];
|
||||
optionalPlugins?: string[];
|
||||
kibanaVersion?: string;
|
||||
configPath?: ConfigPath;
|
||||
|
@ -68,6 +70,7 @@ describe('PluginsService', () => {
|
|||
configPath: `${configPath}${disabled ? '-disabled' : ''}`,
|
||||
kibanaVersion,
|
||||
requiredPlugins,
|
||||
requiredBundles,
|
||||
optionalPlugins,
|
||||
server,
|
||||
ui,
|
||||
|
|
|
@ -54,6 +54,7 @@ function createPluginManifest(manifestProps: Partial<PluginManifest> = {}): Plug
|
|||
kibanaVersion: '7.0.0',
|
||||
requiredPlugins: ['some-required-dep'],
|
||||
optionalPlugins: ['some-optional-dep'],
|
||||
requiredBundles: [],
|
||||
server: true,
|
||||
ui: true,
|
||||
...manifestProps,
|
||||
|
|
|
@ -53,6 +53,7 @@ export class PluginWrapper<
|
|||
public readonly configPath: PluginManifest['configPath'];
|
||||
public readonly requiredPlugins: PluginManifest['requiredPlugins'];
|
||||
public readonly optionalPlugins: PluginManifest['optionalPlugins'];
|
||||
public readonly requiredBundles: PluginManifest['requiredBundles'];
|
||||
public readonly includesServerPlugin: PluginManifest['server'];
|
||||
public readonly includesUiPlugin: PluginManifest['ui'];
|
||||
|
||||
|
@ -81,6 +82,7 @@ export class PluginWrapper<
|
|||
this.configPath = params.manifest.configPath;
|
||||
this.requiredPlugins = params.manifest.requiredPlugins;
|
||||
this.optionalPlugins = params.manifest.optionalPlugins;
|
||||
this.requiredBundles = params.manifest.requiredBundles;
|
||||
this.includesServerPlugin = params.manifest.server;
|
||||
this.includesUiPlugin = params.manifest.ui;
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@ function createPluginManifest(manifestProps: Partial<PluginManifest> = {}): Plug
|
|||
configPath: 'path',
|
||||
kibanaVersion: '7.0.0',
|
||||
requiredPlugins: ['some-required-dep'],
|
||||
requiredBundles: [],
|
||||
optionalPlugins: ['some-optional-dep'],
|
||||
server: true,
|
||||
ui: true,
|
||||
|
|
|
@ -64,6 +64,7 @@ const createPlugin = (
|
|||
disabled = false,
|
||||
version = 'some-version',
|
||||
requiredPlugins = [],
|
||||
requiredBundles = [],
|
||||
optionalPlugins = [],
|
||||
kibanaVersion = '7.0.0',
|
||||
configPath = [path],
|
||||
|
@ -74,6 +75,7 @@ const createPlugin = (
|
|||
disabled?: boolean;
|
||||
version?: string;
|
||||
requiredPlugins?: string[];
|
||||
requiredBundles?: string[];
|
||||
optionalPlugins?: string[];
|
||||
kibanaVersion?: string;
|
||||
configPath?: ConfigPath;
|
||||
|
@ -89,6 +91,7 @@ const createPlugin = (
|
|||
configPath: `${configPath}${disabled ? '-disabled' : ''}`,
|
||||
kibanaVersion,
|
||||
requiredPlugins,
|
||||
requiredBundles,
|
||||
optionalPlugins,
|
||||
server,
|
||||
ui,
|
||||
|
@ -460,6 +463,7 @@ describe('PluginsService', () => {
|
|||
id: plugin.name,
|
||||
configPath: plugin.manifest.configPath,
|
||||
requiredPlugins: [],
|
||||
requiredBundles: [],
|
||||
optionalPlugins: [],
|
||||
},
|
||||
];
|
||||
|
@ -563,10 +567,12 @@ describe('PluginsService', () => {
|
|||
"plugin-1" => Object {
|
||||
"publicAssetsDir": <absolute path>/path-1/public/assets,
|
||||
"publicTargetDir": <absolute path>/path-1/target/public,
|
||||
"requiredBundles": Array [],
|
||||
},
|
||||
"plugin-2" => Object {
|
||||
"publicAssetsDir": <absolute path>/path-2/public/assets,
|
||||
"publicTargetDir": <absolute path>/path-2/target/public,
|
||||
"requiredBundles": Array [],
|
||||
},
|
||||
}
|
||||
`);
|
||||
|
|
|
@ -228,6 +228,7 @@ export class PluginsService implements CoreService<PluginsServiceSetup, PluginsS
|
|||
|
||||
if (plugin.includesUiPlugin) {
|
||||
this.uiPluginInternalInfo.set(plugin.name, {
|
||||
requiredBundles: plugin.requiredBundles,
|
||||
publicTargetDir: Path.resolve(plugin.path, 'target/public'),
|
||||
publicAssetsDir: Path.resolve(plugin.path, 'public/assets'),
|
||||
});
|
||||
|
@ -239,6 +240,21 @@ export class PluginsService implements CoreService<PluginsServiceSetup, PluginsS
|
|||
.toPromise();
|
||||
|
||||
for (const [pluginName, { plugin, isEnabled }] of pluginEnableStatuses) {
|
||||
// validate that `requiredBundles` ids point to a discovered plugin which `includesUiPlugin`
|
||||
for (const requiredBundleId of plugin.requiredBundles) {
|
||||
if (!pluginEnableStatuses.has(requiredBundleId)) {
|
||||
throw new Error(
|
||||
`Plugin bundle with id "${requiredBundleId}" is required by plugin "${pluginName}" but it is missing.`
|
||||
);
|
||||
}
|
||||
|
||||
if (!pluginEnableStatuses.get(requiredBundleId)!.plugin.includesUiPlugin) {
|
||||
throw new Error(
|
||||
`Plugin bundle with id "${requiredBundleId}" is required by plugin "${pluginName}" but it doesn't have a UI bundle.`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const pluginEnablement = this.shouldEnablePlugin(pluginName, pluginEnableStatuses);
|
||||
|
||||
if (pluginEnablement.enabled) {
|
||||
|
|
|
@ -55,6 +55,7 @@ function createPlugin(
|
|||
kibanaVersion: '7.0.0',
|
||||
requiredPlugins: required,
|
||||
optionalPlugins: optional,
|
||||
requiredBundles: [],
|
||||
server,
|
||||
ui,
|
||||
},
|
||||
|
|
|
@ -178,6 +178,7 @@ export class PluginsSystem {
|
|||
optionalPlugins: plugin.manifest.optionalPlugins.filter((p) =>
|
||||
uiPluginNames.includes(p)
|
||||
),
|
||||
requiredBundles: plugin.manifest.requiredBundles,
|
||||
},
|
||||
];
|
||||
})
|
||||
|
|
|
@ -136,6 +136,18 @@ export interface PluginManifest {
|
|||
*/
|
||||
readonly requiredPlugins: readonly PluginName[];
|
||||
|
||||
/**
|
||||
* List of plugin ids that this plugin's UI code imports modules from that are
|
||||
* not in `requiredPlugins`.
|
||||
*
|
||||
* @remarks
|
||||
* The plugins listed here will be loaded in the browser, even if the plugin is
|
||||
* disabled. Required by `@kbn/optimizer` to support cross-plugin imports.
|
||||
* "core" and plugins already listed in `requiredPlugins` do not need to be
|
||||
* duplicated here.
|
||||
*/
|
||||
readonly requiredBundles: readonly string[];
|
||||
|
||||
/**
|
||||
* An optional list of the other plugins that if installed and enabled **may be**
|
||||
* leveraged by this plugin for some additional functionality but otherwise are
|
||||
|
@ -191,12 +203,28 @@ export interface DiscoveredPlugin {
|
|||
* not required for this plugin to work properly.
|
||||
*/
|
||||
readonly optionalPlugins: readonly PluginName[];
|
||||
|
||||
/**
|
||||
* List of plugin ids that this plugin's UI code imports modules from that are
|
||||
* not in `requiredPlugins`.
|
||||
*
|
||||
* @remarks
|
||||
* The plugins listed here will be loaded in the browser, even if the plugin is
|
||||
* disabled. Required by `@kbn/optimizer` to support cross-plugin imports.
|
||||
* "core" and plugins already listed in `requiredPlugins` do not need to be
|
||||
* duplicated here.
|
||||
*/
|
||||
readonly requiredBundles: readonly PluginName[];
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export interface InternalPluginInfo {
|
||||
/**
|
||||
* Bundles that must be loaded for this plugoin
|
||||
*/
|
||||
readonly requiredBundles: readonly string[];
|
||||
/**
|
||||
* Path to the target/public directory of the plugin which should be
|
||||
* served
|
||||
|
|
|
@ -637,6 +637,7 @@ export interface DiscoveredPlugin {
|
|||
readonly configPath: ConfigPath;
|
||||
readonly id: PluginName;
|
||||
readonly optionalPlugins: readonly PluginName[];
|
||||
readonly requiredBundles: readonly PluginName[];
|
||||
readonly requiredPlugins: readonly PluginName[];
|
||||
}
|
||||
|
||||
|
@ -1684,6 +1685,7 @@ export interface PluginManifest {
|
|||
readonly id: PluginName;
|
||||
readonly kibanaVersion: string;
|
||||
readonly optionalPlugins: readonly PluginName[];
|
||||
readonly requiredBundles: readonly string[];
|
||||
readonly requiredPlugins: readonly PluginName[];
|
||||
readonly server: boolean;
|
||||
readonly ui: boolean;
|
||||
|
@ -2706,8 +2708,8 @@ export const validBodyOutput: readonly ["data", "stream"];
|
|||
// src/core/server/legacy/types.ts:165:3 - (ae-forgotten-export) The symbol "LegacyNavLinkSpec" needs to be exported by the entry point index.d.ts
|
||||
// src/core/server/legacy/types.ts:166:3 - (ae-forgotten-export) The symbol "LegacyAppSpec" needs to be exported by the entry point index.d.ts
|
||||
// src/core/server/legacy/types.ts:167:16 - (ae-forgotten-export) The symbol "LegacyPluginSpec" needs to be exported by the entry point index.d.ts
|
||||
// src/core/server/plugins/types.ts:238:3 - (ae-forgotten-export) The symbol "KibanaConfigType" needs to be exported by the entry point index.d.ts
|
||||
// src/core/server/plugins/types.ts:238:3 - (ae-forgotten-export) The symbol "SharedGlobalConfigKeys" needs to be exported by the entry point index.d.ts
|
||||
// src/core/server/plugins/types.ts:240:3 - (ae-forgotten-export) The symbol "PathConfigType" needs to be exported by the entry point index.d.ts
|
||||
// src/core/server/plugins/types.ts:266:3 - (ae-forgotten-export) The symbol "KibanaConfigType" needs to be exported by the entry point index.d.ts
|
||||
// src/core/server/plugins/types.ts:266:3 - (ae-forgotten-export) The symbol "SharedGlobalConfigKeys" needs to be exported by the entry point index.d.ts
|
||||
// src/core/server/plugins/types.ts:268:3 - (ae-forgotten-export) The symbol "PathConfigType" needs to be exported by the entry point index.d.ts
|
||||
|
||||
```
|
||||
|
|
|
@ -24,7 +24,7 @@ The majority of this logic is extracted from the grunt build that has existed fo
|
|||
|
||||
**Config**: [lib/config.js] defines the config used to execute tasks. It is mostly used to determine absolute paths to specific locations, and to get access to the Platforms.
|
||||
|
||||
**Platform**: [lib/platform.js] defines the Platform objects, which define the different platforms we build for. Use `config.getTargetPlatforms()` to get the list of platforms we are targeting in this build, `config.getNodePlatforms()` to get the list of platform we will download node for, or `config.getLinux/Windows/MacPlatform()` to get a specific platform.
|
||||
**Platform**: [lib/platform.js] defines the Platform objects, which define the different platforms we build for. Use `config.getTargetPlatforms()` to get the list of platforms we are targeting in this build, `config.getNodePlatforms()` to get the list of platform we will download node for, or `config.getPlatform` to get a specific platform and architecture.
|
||||
|
||||
**Log**: We uses the `ToolingLog` defined in [../tooling_log/tooling_log.js]
|
||||
|
||||
|
|
|
@ -20,16 +20,16 @@
|
|||
import { getConfig, createRunner } from './lib';
|
||||
|
||||
import {
|
||||
BuildKibanaPlatformPluginsTask,
|
||||
BuildPackagesTask,
|
||||
CleanClientModulesOnDLLTask,
|
||||
CleanEmptyFoldersTask,
|
||||
CleanExtraBinScriptsTask,
|
||||
CleanExtraBrowsersTask,
|
||||
CleanExtraFilesFromModulesTask,
|
||||
CleanPackagesTask,
|
||||
CleanTypescriptTask,
|
||||
CleanNodeBuildsTask,
|
||||
CleanPackagesTask,
|
||||
CleanTask,
|
||||
CleanTypescriptTask,
|
||||
CopyBinScriptsTask,
|
||||
CopySourceTask,
|
||||
CreateArchivesSourcesTask,
|
||||
|
@ -44,20 +44,20 @@ import {
|
|||
CreateRpmPackageTask,
|
||||
DownloadNodeBuildsTask,
|
||||
ExtractNodeBuildsTask,
|
||||
InstallChromiumTask,
|
||||
InstallDependenciesTask,
|
||||
BuildKibanaPlatformPluginsTask,
|
||||
OptimizeBuildTask,
|
||||
PatchNativeModulesTask,
|
||||
PathLengthTask,
|
||||
RemovePackageJsonDepsTask,
|
||||
RemoveWorkspacesTask,
|
||||
TranspileBabelTask,
|
||||
TranspileScssTask,
|
||||
UpdateLicenseFileTask,
|
||||
UuidVerificationTask,
|
||||
VerifyEnvTask,
|
||||
VerifyExistingNodeBuildsTask,
|
||||
PathLengthTask,
|
||||
WriteShaSumsTask,
|
||||
UuidVerificationTask,
|
||||
} from './tasks';
|
||||
|
||||
export async function buildDistributables(options) {
|
||||
|
@ -134,12 +134,12 @@ export async function buildDistributables(options) {
|
|||
|
||||
/**
|
||||
* copy generic build outputs into platform-specific build
|
||||
* directories and perform platform-specific steps
|
||||
* directories and perform platform/architecture-specific steps
|
||||
*/
|
||||
await run(CreateArchivesSourcesTask);
|
||||
await run(PatchNativeModulesTask);
|
||||
await run(InstallChromiumTask);
|
||||
await run(CleanExtraBinScriptsTask);
|
||||
await run(CleanExtraBrowsersTask);
|
||||
await run(CleanNodeBuildsTask);
|
||||
|
||||
await run(PathLengthTask);
|
||||
|
|
|
@ -72,15 +72,31 @@ describe('dev/build/lib/config', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('#getPlatform()', () => {
|
||||
it('throws error when platform does not exist', async () => {
|
||||
const { config } = await setup();
|
||||
const fn = () => config.getPlatform('foo', 'x64');
|
||||
|
||||
expect(fn).to.throwException(/Unable to find platform/);
|
||||
});
|
||||
|
||||
it('throws error when architecture does not exist', async () => {
|
||||
const { config } = await setup();
|
||||
const fn = () => config.getPlatform('linux', 'foo');
|
||||
|
||||
expect(fn).to.throwException(/Unable to find platform/);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getTargetPlatforms()', () => {
|
||||
it('returns an array of all platform objects', async () => {
|
||||
const { config } = await setup();
|
||||
expect(
|
||||
config
|
||||
.getTargetPlatforms()
|
||||
.map((p) => p.getName())
|
||||
.map((p) => p.getNodeArch())
|
||||
.sort()
|
||||
).to.eql(['darwin', 'linux', 'windows']);
|
||||
).to.eql(['darwin-x64', 'linux-arm64', 'linux-x64', 'win32-x64']);
|
||||
});
|
||||
|
||||
it('returns just this platform when targetAllPlatforms = false', async () => {
|
||||
|
@ -99,9 +115,9 @@ describe('dev/build/lib/config', () => {
|
|||
expect(
|
||||
config
|
||||
.getTargetPlatforms()
|
||||
.map((p) => p.getName())
|
||||
.map((p) => p.getNodeArch())
|
||||
.sort()
|
||||
).to.eql(['darwin', 'linux', 'windows']);
|
||||
).to.eql(['darwin-x64', 'linux-arm64', 'linux-x64', 'win32-x64']);
|
||||
});
|
||||
|
||||
it('returns this platform and linux, when targetAllPlatforms = false', async () => {
|
||||
|
@ -111,39 +127,20 @@ describe('dev/build/lib/config', () => {
|
|||
if (process.platform !== 'linux') {
|
||||
expect(platforms).to.have.length(2);
|
||||
expect(platforms[0]).to.be(config.getPlatformForThisOs());
|
||||
expect(platforms[1]).to.be(config.getLinuxPlatform());
|
||||
expect(platforms[1]).to.be(config.getPlatform('linux', 'x64'));
|
||||
} else {
|
||||
expect(platforms).to.have.length(1);
|
||||
expect(platforms[0]).to.be(config.getLinuxPlatform());
|
||||
expect(platforms[0]).to.be(config.getPlatform('linux', 'x64'));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getLinuxPlatform()', () => {
|
||||
it('returns the linux platform', async () => {
|
||||
const { config } = await setup();
|
||||
expect(config.getLinuxPlatform().getName()).to.be('linux');
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getWindowsPlatform()', () => {
|
||||
it('returns the windows platform', async () => {
|
||||
const { config } = await setup();
|
||||
expect(config.getWindowsPlatform().getName()).to.be('windows');
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getMacPlatform()', () => {
|
||||
it('returns the mac platform', async () => {
|
||||
const { config } = await setup();
|
||||
expect(config.getMacPlatform().getName()).to.be('darwin');
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getPlatformForThisOs()', () => {
|
||||
it('returns the platform that matches the arch of this machine', async () => {
|
||||
const { config } = await setup();
|
||||
expect(config.getPlatformForThisOs().getName()).to.be(process.platform);
|
||||
const currentPlatform = config.getPlatformForThisOs();
|
||||
expect(currentPlatform.getName()).to.be(process.platform);
|
||||
expect(currentPlatform.getArchitecture()).to.be(process.arch);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -30,37 +30,39 @@ describe('src/dev/build/lib/platform', () => {
|
|||
|
||||
describe('getNodeArch()', () => {
|
||||
it('returns the node arch for the passed name', () => {
|
||||
expect(createPlatform('windows').getNodeArch()).to.be('windows-x64');
|
||||
expect(createPlatform('win32', 'x64').getNodeArch()).to.be('win32-x64');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getBuildName()', () => {
|
||||
it('returns the build name for the passed name', () => {
|
||||
expect(createPlatform('windows').getBuildName()).to.be('windows-x86_64');
|
||||
expect(createPlatform('linux', 'arm64', 'linux-aarch64').getBuildName()).to.be(
|
||||
'linux-aarch64'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isWindows()', () => {
|
||||
it('returns true if name is windows', () => {
|
||||
expect(createPlatform('windows').isWindows()).to.be(true);
|
||||
expect(createPlatform('linux').isWindows()).to.be(false);
|
||||
expect(createPlatform('darwin').isWindows()).to.be(false);
|
||||
it('returns true if name is win32', () => {
|
||||
expect(createPlatform('win32', 'x64').isWindows()).to.be(true);
|
||||
expect(createPlatform('linux', 'x64').isWindows()).to.be(false);
|
||||
expect(createPlatform('darwin', 'x64').isWindows()).to.be(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isLinux()', () => {
|
||||
it('returns true if name is linux', () => {
|
||||
expect(createPlatform('windows').isLinux()).to.be(false);
|
||||
expect(createPlatform('linux').isLinux()).to.be(true);
|
||||
expect(createPlatform('darwin').isLinux()).to.be(false);
|
||||
expect(createPlatform('win32', 'x64').isLinux()).to.be(false);
|
||||
expect(createPlatform('linux', 'x64').isLinux()).to.be(true);
|
||||
expect(createPlatform('darwin', 'x64').isLinux()).to.be(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isMac()', () => {
|
||||
it('returns true if name is darwin', () => {
|
||||
expect(createPlatform('windows').isMac()).to.be(false);
|
||||
expect(createPlatform('linux').isMac()).to.be(false);
|
||||
expect(createPlatform('darwin').isMac()).to.be(true);
|
||||
expect(createPlatform('win32', 'x64').isMac()).to.be(false);
|
||||
expect(createPlatform('linux', 'x64').isMac()).to.be(false);
|
||||
expect(createPlatform('darwin', 'x64').isMac()).to.be(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
*/
|
||||
|
||||
import { dirname, resolve, relative } from 'path';
|
||||
import { platform as getOsPlatform } from 'os';
|
||||
import os from 'os';
|
||||
|
||||
import { getVersionInfo } from './version_info';
|
||||
import { createPlatform } from './platform';
|
||||
|
@ -29,7 +29,12 @@ export async function getConfig({ isRelease, targetAllPlatforms, versionQualifie
|
|||
const repoRoot = dirname(pkgPath);
|
||||
const nodeVersion = pkg.engines.node;
|
||||
|
||||
const platforms = ['darwin', 'linux', 'windows'].map(createPlatform);
|
||||
const platforms = [
|
||||
createPlatform('linux', 'x64', 'linux-x86_64'),
|
||||
createPlatform('linux', 'arm64', 'linux-aarch64'),
|
||||
createPlatform('darwin', 'x64', 'darwin-x86_64'),
|
||||
createPlatform('win32', 'x64', 'windows-x86_64'),
|
||||
];
|
||||
|
||||
const versionInfo = await getVersionInfo({
|
||||
isRelease,
|
||||
|
@ -101,34 +106,22 @@ export async function getConfig({ isRelease, targetAllPlatforms, versionQualifie
|
|||
}
|
||||
|
||||
if (process.platform === 'linux') {
|
||||
return [this.getLinuxPlatform()];
|
||||
return [this.getPlatform('linux', 'x64')];
|
||||
}
|
||||
|
||||
return [this.getPlatformForThisOs(), this.getLinuxPlatform()];
|
||||
return [this.getPlatformForThisOs(), this.getPlatform('linux', 'x64')];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the linux platform object
|
||||
* @return {Platform}
|
||||
*/
|
||||
getLinuxPlatform() {
|
||||
return platforms.find((p) => p.isLinux());
|
||||
}
|
||||
getPlatform(name, arch) {
|
||||
const selected = platforms.find((p) => {
|
||||
return name === p.getName() && arch === p.getArchitecture();
|
||||
});
|
||||
|
||||
/**
|
||||
* Get the windows platform object
|
||||
* @return {Platform}
|
||||
*/
|
||||
getWindowsPlatform() {
|
||||
return platforms.find((p) => p.isWindows());
|
||||
}
|
||||
if (!selected) {
|
||||
throw new Error(`Unable to find platform (${name}) with architecture (${arch})`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mac platform object
|
||||
* @return {Platform}
|
||||
*/
|
||||
getMacPlatform() {
|
||||
return platforms.find((p) => p.isMac());
|
||||
return selected;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -136,16 +129,7 @@ export async function getConfig({ isRelease, targetAllPlatforms, versionQualifie
|
|||
* @return {Platform}
|
||||
*/
|
||||
getPlatformForThisOs() {
|
||||
switch (getOsPlatform()) {
|
||||
case 'darwin':
|
||||
return this.getMacPlatform();
|
||||
case 'win32':
|
||||
return this.getWindowsPlatform();
|
||||
case 'linux':
|
||||
return this.getLinuxPlatform();
|
||||
default:
|
||||
throw new Error(`Unable to find platform for this os`);
|
||||
}
|
||||
return this.getPlatform(os.platform(), os.arch());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -17,22 +17,26 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
export function createPlatform(name) {
|
||||
export function createPlatform(name, architecture, buildName) {
|
||||
return new (class Platform {
|
||||
getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
getNodeArch() {
|
||||
return `${name}-x64`;
|
||||
getArchitecture() {
|
||||
return architecture;
|
||||
}
|
||||
|
||||
getBuildName() {
|
||||
return `${name}-x86_64`;
|
||||
return buildName;
|
||||
}
|
||||
|
||||
getNodeArch() {
|
||||
return `${name}-${architecture}`;
|
||||
}
|
||||
|
||||
isWindows() {
|
||||
return name === 'windows';
|
||||
return name === 'win32';
|
||||
}
|
||||
|
||||
isMac() {
|
||||
|
|
|
@ -201,45 +201,6 @@ export const CleanExtraBinScriptsTask = {
|
|||
},
|
||||
};
|
||||
|
||||
export const CleanExtraBrowsersTask = {
|
||||
description: 'Cleaning extra browsers from platform-specific builds',
|
||||
|
||||
async run(config, log, build) {
|
||||
const getBrowserPathsForPlatform = (platform) => {
|
||||
const reportingDir = 'x-pack/plugins/reporting';
|
||||
const chromiumDir = '.chromium';
|
||||
const chromiumPath = (p) =>
|
||||
build.resolvePathForPlatform(platform, reportingDir, chromiumDir, p);
|
||||
return (platforms) => {
|
||||
const paths = [];
|
||||
if (platforms.windows) {
|
||||
paths.push(chromiumPath('chromium-*-win32.zip'));
|
||||
paths.push(chromiumPath('chromium-*-windows.zip'));
|
||||
}
|
||||
|
||||
if (platforms.darwin) {
|
||||
paths.push(chromiumPath('chromium-*-darwin.zip'));
|
||||
}
|
||||
|
||||
if (platforms.linux) {
|
||||
paths.push(chromiumPath('chromium-*-linux.zip'));
|
||||
}
|
||||
return paths;
|
||||
};
|
||||
};
|
||||
for (const platform of config.getNodePlatforms()) {
|
||||
const getBrowserPaths = getBrowserPathsForPlatform(platform);
|
||||
if (platform.isWindows()) {
|
||||
await deleteAll(getBrowserPaths({ linux: true, darwin: true }), log);
|
||||
} else if (platform.isMac()) {
|
||||
await deleteAll(getBrowserPaths({ linux: true, windows: true }), log);
|
||||
} else if (platform.isLinux()) {
|
||||
await deleteAll(getBrowserPaths({ windows: true, darwin: true }), log);
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export const CleanEmptyFoldersTask = {
|
||||
description: 'Cleaning all empty folders recursively',
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ export const CreateArchivesSourcesTask = {
|
|||
|
||||
log.debug(
|
||||
'Generic build source copied into',
|
||||
platform.getName(),
|
||||
platform.getNodeArch(),
|
||||
'specific build directory'
|
||||
);
|
||||
|
||||
|
@ -43,7 +43,7 @@ export const CreateArchivesSourcesTask = {
|
|||
destination: build.resolvePathForPlatform(platform, 'node'),
|
||||
});
|
||||
|
||||
log.debug('Node.js copied into', platform.getName(), 'specific build directory');
|
||||
log.debug('Node.js copied into', platform.getNodeArch(), 'specific build directory');
|
||||
})
|
||||
);
|
||||
},
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
|
||||
export * from './bin';
|
||||
export * from './build_kibana_platform_plugins';
|
||||
export * from './build_packages_task';
|
||||
export * from './clean_tasks';
|
||||
export * from './copy_source_task';
|
||||
|
@ -26,18 +27,18 @@ export * from './create_archives_task';
|
|||
export * from './create_empty_dirs_and_files_task';
|
||||
export * from './create_package_json_task';
|
||||
export * from './create_readme_task';
|
||||
export * from './install_chromium';
|
||||
export * from './install_dependencies_task';
|
||||
export * from './license_file_task';
|
||||
export * from './nodejs';
|
||||
export * from './nodejs_modules';
|
||||
export * from './nodejs';
|
||||
export * from './notice_file_task';
|
||||
export * from './optimize_task';
|
||||
export * from './os_packages';
|
||||
export * from './patch_native_modules_task';
|
||||
export * from './path_length_task';
|
||||
export * from './transpile_babel_task';
|
||||
export * from './transpile_scss_task';
|
||||
export * from './uuid_verification_task';
|
||||
export * from './verify_env_task';
|
||||
export * from './write_sha_sums_task';
|
||||
export * from './path_length_task';
|
||||
export * from './build_kibana_platform_plugins';
|
||||
export * from './uuid_verification_task';
|
||||
|
|
44
src/dev/build/tasks/install_chromium.js
Normal file
44
src/dev/build/tasks/install_chromium.js
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
|
||||
import { installBrowser } from '../../../../x-pack/plugins/reporting/server/browsers/install';
|
||||
import { first } from 'rxjs/operators';
|
||||
|
||||
export const InstallChromiumTask = {
|
||||
description: 'Installing Chromium',
|
||||
|
||||
async run(config, log, build) {
|
||||
if (build.isOss()) {
|
||||
return;
|
||||
} else {
|
||||
for (const platform of config.getNodePlatforms()) {
|
||||
log.info(`Installing Chromium for ${platform.getName()}-${platform.getArchitecture()}`);
|
||||
|
||||
const { binaryPath$ } = installBrowser(
|
||||
log,
|
||||
build.resolvePathForPlatform(platform, 'x-pack/plugins/reporting/chromium'),
|
||||
platform.getName(),
|
||||
platform.getArchitecture()
|
||||
);
|
||||
await binaryPath$.pipe(first()).toPromise();
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
|
@ -47,7 +47,7 @@ export const CreateNoticeFileTask = {
|
|||
log.info('Generating build notice');
|
||||
const { extractDir: nodeDir, version: nodeVersion } = getNodeDownloadInfo(
|
||||
config,
|
||||
config.getLinuxPlatform()
|
||||
config.getPlatform('linux', 'x64')
|
||||
);
|
||||
|
||||
const notice = await generateBuildNoticeText({
|
||||
|
|
|
@ -22,7 +22,7 @@ import { resolve } from 'path';
|
|||
import { exec } from '../../lib';
|
||||
|
||||
export async function runFpm(config, log, build, type, pkgSpecificFlags) {
|
||||
const linux = config.getLinuxPlatform();
|
||||
const linux = config.getPlatform('linux', 'x64');
|
||||
const version = config.getBuildVersion();
|
||||
|
||||
const resolveWithTrailingSlash = (...paths) => `${resolve(...paths)}/`;
|
||||
|
|
|
@ -38,7 +38,7 @@ const packages = [
|
|||
url: 'https://github.com/uhop/node-re2/releases/download/1.14.0/linux-x64-64.gz',
|
||||
sha256: 'f54f059035e71a7ccb3fa201080e260c41d228d13a8247974b4bb157691b6757',
|
||||
},
|
||||
windows: {
|
||||
win32: {
|
||||
url: 'https://github.com/uhop/node-re2/releases/download/1.14.0/win32-x64-64.gz',
|
||||
sha256: 'de708446a8b802f4634c2cfef097c2625a2811fdcd8133dfd7b7c485f966caa9',
|
||||
},
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@import '@elastic/eui/src/components/header/variables';
|
||||
@import '@elastic/eui/src/global_styling/variables/header';
|
||||
|
||||
.timApp {
|
||||
position: relative;
|
||||
|
|
|
@ -51,7 +51,7 @@ import {
|
|||
suggest,
|
||||
insertAtLocation,
|
||||
} from './timelion_expression_input_helpers';
|
||||
import { comboBoxKeyCodes } from '@elastic/eui';
|
||||
import { comboBoxKeys } from '@elastic/eui';
|
||||
import { npStart } from 'ui/new_platform';
|
||||
|
||||
const Parser = PEG.generate(grammar);
|
||||
|
@ -178,9 +178,9 @@ export function TimelionExpInput($http, $timeout) {
|
|||
});
|
||||
}
|
||||
|
||||
function isNavigationalKey(keyCode) {
|
||||
const keyCodes = _.values(comboBoxKeyCodes);
|
||||
return keyCodes.includes(keyCode);
|
||||
function isNavigationalKey(key) {
|
||||
const keyCodes = _.values(comboBoxKeys);
|
||||
return keyCodes.includes(key);
|
||||
}
|
||||
|
||||
scope.onFocusInput = () => {
|
||||
|
@ -196,12 +196,12 @@ export function TimelionExpInput($http, $timeout) {
|
|||
scope.onKeyDownInput = (e) => {
|
||||
// If we've pressed any non-navigational keys, then the user has typed something and we
|
||||
// can exit early without doing any navigation. The keyup handler will pull up suggestions.
|
||||
if (!isNavigationalKey(e.keyCode)) {
|
||||
if (!isNavigationalKey(e.key)) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (e.keyCode) {
|
||||
case comboBoxKeyCodes.UP:
|
||||
case comboBoxKeys.ARROW_UP:
|
||||
if (scope.suggestions.isVisible) {
|
||||
// Up and down keys navigate through suggestions.
|
||||
e.preventDefault();
|
||||
|
@ -210,7 +210,7 @@ export function TimelionExpInput($http, $timeout) {
|
|||
}
|
||||
break;
|
||||
|
||||
case comboBoxKeyCodes.DOWN:
|
||||
case comboBoxKeys.ARROW_DOWN:
|
||||
if (scope.suggestions.isVisible) {
|
||||
// Up and down keys navigate through suggestions.
|
||||
e.preventDefault();
|
||||
|
@ -219,7 +219,7 @@ export function TimelionExpInput($http, $timeout) {
|
|||
}
|
||||
break;
|
||||
|
||||
case comboBoxKeyCodes.TAB:
|
||||
case comboBoxKeys.TAB:
|
||||
// If there are no suggestions or none is selected, the user tabs to the next input.
|
||||
if (scope.suggestions.isEmpty() || scope.suggestions.index < 0) {
|
||||
// Before letting the tab be handled to focus the next element
|
||||
|
@ -234,7 +234,7 @@ export function TimelionExpInput($http, $timeout) {
|
|||
insertSuggestionIntoExpression(scope.suggestions.index);
|
||||
break;
|
||||
|
||||
case comboBoxKeyCodes.ENTER:
|
||||
case comboBoxKeys.ENTER:
|
||||
if (e.metaKey || e.ctrlKey) {
|
||||
// Re-render the chart when the user hits CMD+ENTER.
|
||||
e.preventDefault();
|
||||
|
@ -246,7 +246,7 @@ export function TimelionExpInput($http, $timeout) {
|
|||
}
|
||||
break;
|
||||
|
||||
case comboBoxKeyCodes.ESCAPE:
|
||||
case comboBoxKeys.ESCAPE:
|
||||
e.preventDefault();
|
||||
scope.suggestions.hide();
|
||||
break;
|
||||
|
@ -255,7 +255,7 @@ export function TimelionExpInput($http, $timeout) {
|
|||
|
||||
scope.onKeyUpInput = (e) => {
|
||||
// If the user isn't navigating, then we should update the suggestions based on their input.
|
||||
if (!isNavigationalKey(e.keyCode)) {
|
||||
if (!isNavigationalKey(e.key)) {
|
||||
getSuggestions();
|
||||
}
|
||||
};
|
||||
|
|
|
@ -22,7 +22,7 @@ import sinon from 'sinon';
|
|||
import expect from '@kbn/expect';
|
||||
import ngMock from 'ng_mock';
|
||||
import '../kbn_accessible_click';
|
||||
import { keyCodes } from '@elastic/eui';
|
||||
import { keys } from '@elastic/eui';
|
||||
|
||||
describe('kbnAccessibleClick directive', () => {
|
||||
let $compile;
|
||||
|
@ -112,14 +112,14 @@ describe('kbnAccessibleClick directive', () => {
|
|||
|
||||
it(`on ENTER keyup`, () => {
|
||||
const e = angular.element.Event('keyup'); // eslint-disable-line new-cap
|
||||
e.keyCode = keyCodes.ENTER;
|
||||
e.key = keys.ENTER;
|
||||
element.trigger(e);
|
||||
sinon.assert.calledOnce(scope.handleClick);
|
||||
});
|
||||
|
||||
it(`on SPACE keyup`, () => {
|
||||
const e = angular.element.Event('keyup'); // eslint-disable-line new-cap
|
||||
e.keyCode = keyCodes.SPACE;
|
||||
e.key = keys.SPACE;
|
||||
element.trigger(e);
|
||||
sinon.assert.calledOnce(scope.handleClick);
|
||||
});
|
||||
|
|
|
@ -22,7 +22,7 @@ import sinon from 'sinon';
|
|||
import expect from '@kbn/expect';
|
||||
import ngMock from 'ng_mock';
|
||||
import '../kbn_ui_ace_keyboard_mode';
|
||||
import { keyCodes } from '@elastic/eui';
|
||||
import { keys } from '@elastic/eui';
|
||||
|
||||
describe('kbnUiAceKeyboardMode directive', () => {
|
||||
let element;
|
||||
|
@ -48,7 +48,7 @@ describe('kbnUiAceKeyboardMode directive', () => {
|
|||
const textarea = element.find('textarea');
|
||||
sinon.spy(textarea[0], 'focus');
|
||||
const ev = angular.element.Event('keydown'); // eslint-disable-line new-cap
|
||||
ev.keyCode = keyCodes.ENTER;
|
||||
ev.key = keys.ENTER;
|
||||
element.find('.kbnUiAceKeyboardHint').trigger(ev);
|
||||
expect(textarea[0].focus.called).to.be(true);
|
||||
expect(
|
||||
|
@ -61,7 +61,7 @@ describe('kbnUiAceKeyboardMode directive', () => {
|
|||
const hint = element.find('.kbnUiAceKeyboardHint');
|
||||
sinon.spy(hint[0], 'focus');
|
||||
const ev = angular.element.Event('keydown'); // eslint-disable-line new-cap
|
||||
ev.keyCode = keyCodes.ESCAPE;
|
||||
ev.key = keys.ESCAPE;
|
||||
textarea.trigger(ev);
|
||||
expect(hint[0].focus.called).to.be(true);
|
||||
expect(hint.hasClass('kbnUiAceKeyboardHint-isInactive')).to.be(false);
|
||||
|
@ -101,7 +101,7 @@ describe('kbnUiAceKeyboardModeService', () => {
|
|||
const textarea = element.find('textarea');
|
||||
sinon.spy(textarea[0], 'focus');
|
||||
const ev = angular.element.Event('keydown'); // eslint-disable-line new-cap
|
||||
ev.keyCode = keyCodes.ENTER;
|
||||
ev.key = keys.ENTER;
|
||||
element.find('.kbnUiAceKeyboardHint').trigger(ev);
|
||||
expect(textarea[0].focus.called).to.be(true);
|
||||
expect(
|
||||
|
@ -114,7 +114,7 @@ describe('kbnUiAceKeyboardModeService', () => {
|
|||
const hint = element.find('.kbnUiAceKeyboardHint');
|
||||
sinon.spy(hint[0], 'focus');
|
||||
const ev = angular.element.Event('keydown'); // eslint-disable-line new-cap
|
||||
ev.keyCode = keyCodes.ESCAPE;
|
||||
ev.key = keys.ESCAPE;
|
||||
textarea.trigger(ev);
|
||||
expect(hint[0].focus.called).to.be(true);
|
||||
expect(hint.hasClass('kbnUiAceKeyboardHint-isInactive')).to.be(false);
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
|
||||
import angular from 'angular';
|
||||
import { uiModules } from '../modules';
|
||||
import { keyCodes } from '@elastic/eui';
|
||||
import { keys } from '@elastic/eui';
|
||||
|
||||
let aceKeyboardModeId = 0;
|
||||
|
||||
|
@ -72,7 +72,7 @@ uiModules
|
|||
}
|
||||
|
||||
hint.keydown((ev) => {
|
||||
if (ev.keyCode === keyCodes.ENTER) {
|
||||
if (ev.key === keys.ENTER) {
|
||||
ev.preventDefault();
|
||||
startEditing();
|
||||
}
|
||||
|
@ -103,7 +103,7 @@ uiModules
|
|||
);
|
||||
|
||||
uiAceTextbox.keydown((ev) => {
|
||||
if (ev.keyCode === keyCodes.ESCAPE) {
|
||||
if (ev.key === keys.ESCAPE) {
|
||||
// If the autocompletion context menu is open then we want to let ESC close it but
|
||||
// **not** exit out of editing mode.
|
||||
if (!isAutoCompleterOpen) {
|
||||
|
|
|
@ -33,7 +33,7 @@ import chrome from 'ui/chrome';
|
|||
|
||||
import { ExitFullScreenButton } from './exit_full_screen_button';
|
||||
|
||||
import { keyCodes } from '@elastic/eui';
|
||||
import { keys } from '@elastic/eui';
|
||||
|
||||
test('is rendered', () => {
|
||||
const component = renderWithIntl(<ExitFullScreenButton onExitFullScreenMode={() => {}} />);
|
||||
|
@ -57,7 +57,7 @@ describe('onExitFullScreenMode', () => {
|
|||
|
||||
mountWithIntl(<ExitFullScreenButton onExitFullScreenMode={onExitHandler} />);
|
||||
|
||||
const escapeKeyEvent = new KeyboardEvent('keydown', { keyCode: keyCodes.ESCAPE });
|
||||
const escapeKeyEvent = new KeyboardEvent('keydown', { key: keys.ESCAPE });
|
||||
document.dispatchEvent(escapeKeyEvent);
|
||||
|
||||
sinon.assert.calledOnce(onExitHandler);
|
||||
|
|
|
@ -150,7 +150,23 @@ export function uiRenderMixin(kbnServer, server, config) {
|
|||
]),
|
||||
];
|
||||
|
||||
const kpPluginIds = Array.from(kbnServer.newPlatform.__internals.uiPlugins.public.keys());
|
||||
const kpUiPlugins = kbnServer.newPlatform.__internals.uiPlugins;
|
||||
const kpPluginPublicPaths = new Map();
|
||||
const kpPluginBundlePaths = new Set();
|
||||
|
||||
// recursively iterate over the kpUiPlugin ids and their required bundles
|
||||
// to populate kpPluginPublicPaths and kpPluginBundlePaths
|
||||
(function readKpPlugins(ids) {
|
||||
for (const id of ids) {
|
||||
if (kpPluginPublicPaths.has(id)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
kpPluginPublicPaths.set(id, `${regularBundlePath}/plugin/${id}/`);
|
||||
kpPluginBundlePaths.add(`${regularBundlePath}/plugin/${id}/${id}.plugin.js`);
|
||||
readKpPlugins(kpUiPlugins.internal.get(id).requiredBundles);
|
||||
}
|
||||
})(kpUiPlugins.public.keys());
|
||||
|
||||
const jsDependencyPaths = [
|
||||
...UiSharedDeps.jsDepFilenames.map(
|
||||
|
@ -160,9 +176,7 @@ export function uiRenderMixin(kbnServer, server, config) {
|
|||
...(isCore ? [] : [`${dllBundlePath}/vendors_runtime.bundle.dll.js`, ...dllJsChunks]),
|
||||
|
||||
`${regularBundlePath}/core/core.entry.js`,
|
||||
...kpPluginIds.map(
|
||||
(pluginId) => `${regularBundlePath}/plugin/${pluginId}/${pluginId}.plugin.js`
|
||||
),
|
||||
...kpPluginBundlePaths,
|
||||
];
|
||||
|
||||
// These paths should align with the bundle routes configured in
|
||||
|
@ -170,13 +184,7 @@ export function uiRenderMixin(kbnServer, server, config) {
|
|||
const publicPathMap = JSON.stringify({
|
||||
core: `${regularBundlePath}/core/`,
|
||||
'kbn-ui-shared-deps': `${regularBundlePath}/kbn-ui-shared-deps/`,
|
||||
...kpPluginIds.reduce(
|
||||
(acc, pluginId) => ({
|
||||
...acc,
|
||||
[pluginId]: `${regularBundlePath}/plugin/${pluginId}/`,
|
||||
}),
|
||||
{}
|
||||
),
|
||||
...Object.fromEntries(kpPluginPublicPaths),
|
||||
});
|
||||
|
||||
const bootstrap = new AppBootstrap({
|
||||
|
|
|
@ -3,5 +3,6 @@
|
|||
"version": "kibana",
|
||||
"server": true,
|
||||
"ui": true,
|
||||
"requiredPlugins": ["management"]
|
||||
"requiredPlugins": ["management"],
|
||||
"requiredBundles": ["kibanaReact"]
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@import '@elastic/eui/src/components/header/variables';
|
||||
@import '@elastic/eui/src/global_styling/variables/header';
|
||||
@import '@elastic/eui/src/components/nav_drawer/variables';
|
||||
|
||||
// TODO #64541
|
||||
|
|
|
@ -2,5 +2,6 @@
|
|||
"id": "bfetch",
|
||||
"version": "kibana",
|
||||
"server": true,
|
||||
"ui": true
|
||||
"ui": true,
|
||||
"requiredBundles": ["kibanaUtils"]
|
||||
}
|
||||
|
|
|
@ -2,5 +2,6 @@
|
|||
"id": "charts",
|
||||
"version": "kibana",
|
||||
"server": true,
|
||||
"ui": true
|
||||
"ui": true,
|
||||
"requiredBundles": ["kibanaUtils", "kibanaReact", "data"]
|
||||
}
|
||||
|
|
|
@ -4,5 +4,6 @@
|
|||
"server": true,
|
||||
"ui": true,
|
||||
"requiredPlugins": ["devTools", "home"],
|
||||
"optionalPlugins": ["usageCollection"]
|
||||
"optionalPlugins": ["usageCollection"],
|
||||
"requiredBundles": ["esUiShared", "kibanaReact", "kibanaUtils"]
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ import { i18n } from '@kbn/i18n';
|
|||
import { memoize } from 'lodash';
|
||||
import moment from 'moment';
|
||||
import {
|
||||
keyCodes,
|
||||
keys,
|
||||
EuiSpacer,
|
||||
EuiIcon,
|
||||
EuiTitle,
|
||||
|
@ -125,17 +125,17 @@ export function ConsoleHistory({ close }: Props) {
|
|||
<ul
|
||||
ref={listRef}
|
||||
onKeyDown={(ev: React.KeyboardEvent) => {
|
||||
if (ev.keyCode === keyCodes.ENTER) {
|
||||
if (ev.key === keys.ENTER) {
|
||||
restoreRequestFromHistory(selectedReq.current);
|
||||
return;
|
||||
}
|
||||
|
||||
let currentIdx = selectedIndex;
|
||||
|
||||
if (ev.keyCode === keyCodes.UP) {
|
||||
if (ev.key === keys.ARROW_UP) {
|
||||
ev.preventDefault();
|
||||
--currentIdx;
|
||||
} else if (ev.keyCode === keyCodes.DOWN) {
|
||||
} else if (ev.key === keys.ARROW_DOWN) {
|
||||
ev.preventDefault();
|
||||
++currentIdx;
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ import { i18n } from '@kbn/i18n';
|
|||
import { debounce } from 'lodash';
|
||||
import { parse } from 'query-string';
|
||||
import React, { CSSProperties, useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { useUIAceKeyboardMode } from '../../../../../../../es_ui_shared/public';
|
||||
import { ace } from '../../../../../../../es_ui_shared/public';
|
||||
// @ts-ignore
|
||||
import { retrieveAutoCompleteInfo, clearSubscriptions } from '../../../../../lib/mappings/mappings';
|
||||
import { ConsoleMenu } from '../../../../components';
|
||||
|
@ -38,6 +38,8 @@ import { subscribeResizeChecker } from '../subscribe_console_resize_checker';
|
|||
import { applyCurrentSettings } from './apply_editor_settings';
|
||||
import { registerCommands } from './keyboard_shortcuts';
|
||||
|
||||
const { useUIAceKeyboardMode } = ace;
|
||||
|
||||
export interface EditorProps {
|
||||
initialTextValue: string;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// TODO: Move all of the styles here (should be modularised by, e.g., CSS-in-JS or CSS modules).
|
||||
@import '@elastic/eui/src/components/header/variables';
|
||||
@import '@elastic/eui/src/global_styling/variables/header';
|
||||
|
||||
// This value is calculated to static value using SCSS because calc in calc has issues in IE11
|
||||
$headerHeightOffset: $euiHeaderHeightCompensation * 2;
|
||||
|
|
|
@ -12,5 +12,6 @@
|
|||
],
|
||||
"optionalPlugins": ["home", "share", "usageCollection"],
|
||||
"server": true,
|
||||
"ui": true
|
||||
"ui": true,
|
||||
"requiredBundles": ["kibanaUtils", "kibanaReact", "home"]
|
||||
}
|
||||
|
|
|
@ -8,5 +8,11 @@
|
|||
"uiActions"
|
||||
],
|
||||
"optionalPlugins": ["usageCollection"],
|
||||
"extraPublicDirs": ["common", "common/utils/abort_utils"]
|
||||
"extraPublicDirs": ["common", "common/utils/abort_utils"],
|
||||
"requiredBundles": [
|
||||
"kibanaUtils",
|
||||
"kibanaReact",
|
||||
"kibanaLegacy",
|
||||
"inspector"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ import { ApplicationStart } from 'kibana/public';
|
|||
import { Assign } from '@kbn/utility-types';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import Boom from 'boom';
|
||||
import { Breadcrumb } from '@elastic/eui';
|
||||
import { BulkIndexDocumentsParams } from 'elasticsearch';
|
||||
import { CatAliasesParams } from 'elasticsearch';
|
||||
import { CatAllocationParams } from 'elasticsearch';
|
||||
|
@ -48,6 +47,7 @@ import { DeleteScriptParams } from 'elasticsearch';
|
|||
import { DeleteTemplateParams } from 'elasticsearch';
|
||||
import { Ensure } from '@kbn/utility-types';
|
||||
import { ErrorToastOptions } from 'src/core/public/notifications';
|
||||
import { EuiBreadcrumb } from '@elastic/eui';
|
||||
import { EuiButtonEmptyProps } from '@elastic/eui';
|
||||
import { EuiComboBoxProps } from '@elastic/eui';
|
||||
import { EuiConfirmModalProps } from '@elastic/eui';
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
{
|
||||
"id": "discover",
|
||||
"version": "kibana",
|
||||
"optionalPlugins": ["share"],
|
||||
"server": true,
|
||||
"ui": true,
|
||||
"requiredPlugins": [
|
||||
|
@ -14,5 +13,11 @@
|
|||
"uiActions",
|
||||
"visualizations"
|
||||
],
|
||||
"optionalPlugins": ["home", "share"]
|
||||
"optionalPlugins": ["home", "share"],
|
||||
"requiredBundles": [
|
||||
"kibanaUtils",
|
||||
"home",
|
||||
"savedObjects",
|
||||
"kibanaReact"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -10,5 +10,9 @@
|
|||
],
|
||||
"extraPublicDirs": [
|
||||
"public/lib/test_samples"
|
||||
],
|
||||
"requiredBundles": [
|
||||
"savedObjects",
|
||||
"kibanaReact"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
.kbnUiAceKeyboardHint {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
background: transparentize($euiColorEmptyShade, 0.3);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
opacity: 0;
|
||||
|
||||
&:focus {
|
||||
opacity: 1;
|
||||
border: 2px solid $euiColorPrimary;
|
||||
z-index: $euiZLevel1;
|
||||
}
|
||||
|
||||
&.kbnUiAceKeyboardHint-isInactive {
|
||||
display: none;
|
||||
}
|
||||
}
|
|
@ -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 { useUIAceKeyboardMode } from './use_ui_ace_keyboard_mode';
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue