Skip to content

Commit d9d0076

Browse files
mshustovspalger
andcommitted
Add script to identify plugin dependencies for TS project references migration (#80463)
* move kbn-dev-utils plugin helpers under a dedicated folder * use getPluginSearchPaths in kbn-config & kbn-optimizer * add a script to find plugin dependencies not migrated to TS project refs * update docs * add a script reporting all circular deps between plugins based on kibana.json declaration, so it doesn't provide all the cases * fix optimizer scan logic. removed by mistake * revert changes. fails on CI * remove prod depenedency on kbn/dev-utils * remove last export * only run plugin discovery once to speed up circular dep detection * address comments * address comments * update fixtures Co-authored-by: spalger <spalger@users.noreply.github.com>
1 parent fd5e8cf commit d9d0076

24 files changed

Lines changed: 508 additions & 44 deletions

File tree

docs/developer/best-practices/typescript.asciidoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ This architecture imposes several limitations to which we must comply:
2828
[discrete]
2929
==== Prerequisites
3030
Since project refs rely on generated `d.ts` files, the migration order does matter. You can migrate your plugin only when all the plugin dependencies already have migrated. It creates a situation where commonly used plugins (such as `data` or `kibana_react`) have to migrate first.
31-
https://github.com/elastic/kibana/issues/79343 is going to provide a tool for identifying a plugin dependency tree.
31+
Run `node scripts/find_plugins_without_ts_refs.js --id your_plugin_id` to get a list of plugins that should be switched to TS project refs to unblock your plugin migration.
3232

3333
[discrete]
3434
==== Implementation

packages/kbn-config/src/env.ts

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import { resolve, join } from 'path';
2121
import loadJsonFile from 'load-json-file';
22+
import { getPluginSearchPaths } from './plugins';
2223
import { PackageInfo, EnvironmentMode } from './types';
2324

2425
/** @internal */
@@ -114,21 +115,11 @@ export class Env {
114115
this.binDir = resolve(this.homeDir, 'bin');
115116
this.logDir = resolve(this.homeDir, 'log');
116117

117-
/**
118-
* BEWARE: this needs to stay roughly synchronized with the @kbn/optimizer
119-
* `packages/kbn-optimizer/src/optimizer_config.ts` determines the paths
120-
* that should be searched for plugins to build
121-
*/
122-
this.pluginSearchPaths = [
123-
resolve(this.homeDir, 'src', 'plugins'),
124-
...(options.cliArgs.oss ? [] : [resolve(this.homeDir, 'x-pack', 'plugins')]),
125-
resolve(this.homeDir, 'plugins'),
126-
...(options.cliArgs.runExamples ? [resolve(this.homeDir, 'examples')] : []),
127-
...(options.cliArgs.runExamples && !options.cliArgs.oss
128-
? [resolve(this.homeDir, 'x-pack', 'examples')]
129-
: []),
130-
resolve(this.homeDir, '..', 'kibana-extra'),
131-
];
118+
this.pluginSearchPaths = getPluginSearchPaths({
119+
rootDir: this.homeDir,
120+
oss: options.cliArgs.oss,
121+
examples: options.cliArgs.runExamples,
122+
});
132123

133124
this.cliArgs = Object.freeze(options.cliArgs);
134125
this.configs = Object.freeze(options.configs);

packages/kbn-config/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,4 @@ export { ObjectToConfigAdapter } from './object_to_config_adapter';
3535
export { CliArgs, Env, RawPackageInfo } from './env';
3636
export { EnvironmentMode, PackageInfo } from './types';
3737
export { LegacyObjectToConfigAdapter, LegacyLoggingConfig } from './legacy';
38+
export { getPluginSearchPaths } from './plugins';
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*
2+
* Licensed to Elasticsearch B.V. under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch B.V. licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
export { getPluginSearchPaths } from './plugin_search_paths';
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Licensed to Elasticsearch B.V. under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch B.V. licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
import { resolve } from 'path';
20+
21+
interface SearchOptions {
22+
rootDir: string;
23+
oss: boolean;
24+
examples: boolean;
25+
}
26+
27+
export function getPluginSearchPaths({ rootDir, oss, examples }: SearchOptions) {
28+
return [
29+
resolve(rootDir, 'src', 'plugins'),
30+
...(oss ? [] : [resolve(rootDir, 'x-pack', 'plugins')]),
31+
resolve(rootDir, 'plugins'),
32+
...(examples ? [resolve(rootDir, 'examples')] : []),
33+
...(examples && !oss ? [resolve(rootDir, 'x-pack', 'examples')] : []),
34+
resolve(rootDir, '..', 'kibana-extra'),
35+
];
36+
}

packages/kbn-dev-utils/src/index.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ export * from './axios';
4040
export * from './stdio';
4141
export * from './ci_stats_reporter';
4242
export * from './plugin_list';
43-
export * from './simple_kibana_platform_plugin_discovery';
43+
export * from './plugins';
4444
export * from './streams';
4545
export * from './babel';
46-
export * from './parse_kibana_platform_plugin';

packages/kbn-dev-utils/src/plugin_list/discover_plugins.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import MarkdownIt from 'markdown-it';
2424
import cheerio from 'cheerio';
2525
import { REPO_ROOT } from '@kbn/utils';
2626

27-
import { simpleKibanaPlatformPluginDiscovery } from '../simple_kibana_platform_plugin_discovery';
27+
import { simpleKibanaPlatformPluginDiscovery } from '../plugins';
2828
import { extractAsciidocInfo } from './extract_asciidoc_info';
2929

3030
export interface Plugin {
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
* Licensed to Elasticsearch B.V. under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch B.V. licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
export * from './parse_kibana_platform_plugin';
21+
export * from './simple_kibana_platform_plugin_discovery';

packages/kbn-dev-utils/src/parse_kibana_platform_plugin.ts renamed to packages/kbn-dev-utils/src/plugins/parse_kibana_platform_plugin.ts

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,20 +23,35 @@ import loadJsonFile from 'load-json-file';
2323
export interface KibanaPlatformPlugin {
2424
readonly directory: string;
2525
readonly manifestPath: string;
26-
readonly manifest: {
27-
id: string;
28-
ui: boolean;
29-
server: boolean;
30-
[key: string]: unknown;
31-
};
26+
readonly manifest: Manifest;
27+
}
28+
29+
function isValidDepsDeclaration(input: unknown, type: string): string[] {
30+
if (typeof input === 'undefined') return [];
31+
if (Array.isArray(input) && input.every((i) => typeof i === 'string')) {
32+
return input;
33+
}
34+
throw new TypeError(`The "${type}" in plugin manifest should be an array of strings.`);
35+
}
36+
37+
interface Manifest {
38+
id: string;
39+
ui: boolean;
40+
server: boolean;
41+
kibanaVersion: string;
42+
version: string;
43+
requiredPlugins: readonly string[];
44+
optionalPlugins: readonly string[];
45+
requiredBundles: readonly string[];
46+
extraPublicDirs: readonly string[];
3247
}
3348

3449
export function parseKibanaPlatformPlugin(manifestPath: string): KibanaPlatformPlugin {
3550
if (!Path.isAbsolute(manifestPath)) {
3651
throw new TypeError('expected new platform manifest path to be absolute');
3752
}
3853

39-
const manifest = loadJsonFile.sync(manifestPath);
54+
const manifest: Partial<Manifest> = loadJsonFile.sync(manifestPath);
4055
if (!manifest || typeof manifest !== 'object' || Array.isArray(manifest)) {
4156
throw new TypeError('expected new platform plugin manifest to be a JSON encoded object');
4257
}
@@ -45,6 +60,10 @@ export function parseKibanaPlatformPlugin(manifestPath: string): KibanaPlatformP
4560
throw new TypeError('expected new platform plugin manifest to have a string id');
4661
}
4762

63+
if (typeof manifest.version !== 'string') {
64+
throw new TypeError('expected new platform plugin manifest to have a string version');
65+
}
66+
4867
return {
4968
directory: Path.dirname(manifestPath),
5069
manifestPath,
@@ -54,6 +73,12 @@ export function parseKibanaPlatformPlugin(manifestPath: string): KibanaPlatformP
5473
ui: !!manifest.ui,
5574
server: !!manifest.server,
5675
id: manifest.id,
76+
version: manifest.version,
77+
kibanaVersion: manifest.kibanaVersion || manifest.version,
78+
requiredPlugins: isValidDepsDeclaration(manifest.requiredPlugins, 'requiredPlugins'),
79+
optionalPlugins: isValidDepsDeclaration(manifest.optionalPlugins, 'optionalPlugins'),
80+
requiredBundles: isValidDepsDeclaration(manifest.requiredBundles, 'requiredBundles'),
81+
extraPublicDirs: isValidDepsDeclaration(manifest.extraPublicDirs, 'extraPublicDirs'),
5782
},
5883
};
5984
}

packages/kbn-dev-utils/src/simple_kibana_platform_plugin_discovery.ts renamed to packages/kbn-dev-utils/src/plugins/simple_kibana_platform_plugin_discovery.ts

File renamed without changes.

0 commit comments

Comments
 (0)