mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
## Summary Dealing with circular dependencies between plugins has become a sharp pain point for anyone developing plugins in Kibana. ### Providing dependencies to a plugin First, a plugin defines its dependencies in its `kibana.jsonc` file as one of three types: - `required` - the dependency must be present and enabled -- will be guaranteed in the lifecycle - `optional` - the dependency can be missing or disabled -- will be `undefined` in the lifecycle - `requiredBundle` - the dependency is required as static code only -- will not be present in the lifecycle Missing or circular dependencies are detected by the Kibana platform when it starts. ### Providing dependencies in code Our plugins are written in and type-checked by Typescript. As such, each plugin needs to maintain Typescript types defining what the platform is providing. This is done manually, and there is no enforcement mechanism between that and the plugin Typescript types. If these dependency definitions are inconsistent or stale, it can lead to host of issues: - optional plugins typed as required that are disabled crash the plugin at runtime; - plugins that are no longer used still included in dependency checks; - plugins marked as required or optional that are actually required bundles. - etc. ### Dependencies with side-effects One of the interesting things that has come out of this has been identifying plugins that provide dependent logic through side-effects, rather than lifecycles. As an example, `licensing` provides a lifecycle contracts, but also a [route handler context](https://github.com/elastic/kibana/blob/main/x-pack/plugins/licensing/server/licensing_route_handler_context.ts) as middleware for a dependent plugin. Unfortunately, while this dependency can be stated as `required` in a dependent plugin's `kibana.jsonc`, the fact that this is a side-effect makes it incredible difficult to understand the dependency without searching the code. <img width="735" alt="Screenshot 2023-12-13 at 10 08 00 AM" src="b4201c86
-4811-4506-b2d0-be5bf8c372b0"> So the side-effect is more or less hidden from developers. This is likely why we see other plugins using the lifecycle [logic](https://github.com/elastic/kibana/blob/main/src/plugins/maps_ems/public/kibana_services.ts#L33-L37), or copy-pasting licensing check code [[1](https://github.com/elastic/kibana/blob/main/x-pack/plugins/actions/server/lib/license_state.ts), [2](https://github.com/elastic/kibana/blob/main/x-pack/plugins/alerting/server/lib/license_state.ts)], or relying on the route context side-effect. ## Proposed (initial) solution This script is an initial attempt to both identify these problems and surface a plugin's dependencies in a useful way. In addition, the script will warn if the classes aren't typed well, not typed at all, or even don't extend the `core` `Plugin` class. <img width="1426" alt="Screenshot 2023-12-13 at 12 37 25 AM" src="e044afb7
-26f5-4d96-92db-d2eb0a3dfc6e"> <img width="1413" alt="Screenshot 2023-12-13 at 12 38 07 AM" src="69217a34
-9840-4d32-98de-eeeb863d4a50"> <img width="1071" alt="Screenshot 2023-12-13 at 12 38 35 AM" src="57736027
-2d10-44bf-8230-29fdb8b77cb2"> For side-effects, identifying them is key, and then refactoring the plugins to provide appropriate logic in the `start` or `setup` contracts. ## Next steps - [x] refine the logic - [ ] write tests - [ ] add `--fix` option I'm also considering (in another PR), outputting a consistent type definition file-- perhaps `kibana.d.ts`-- to the plugin from which the implementing classes could `Omit<>` or `Pick<>` the relevant contracts.
10 lines
439 B
JavaScript
10 lines
439 B
JavaScript
/*
|
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
|
* or more contributor license agreements. Licensed under the Elastic License
|
|
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
|
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
|
* Side Public License, v 1.
|
|
*/
|
|
|
|
require('../src/setup_node_env');
|
|
require('@kbn/plugin-check').runPluginCheckCli();
|