Make owner attribute required on kibana.json (#108231)

* make owner attribute required

* Add owner properties in more places

* add test for owner attribute

* add error check too in the test

* Fix tests

* fix tests and update docs

* wip

* More test fixes

* Fix All The Errorz

* Adding more owner attributes

* Update x-pack/test/saved_object_api_integration/common/fixtures/saved_object_test_plugin/kibana.json

Co-authored-by: Larry Gregory <lgregorydev@gmail.com>

* Update x-pack/test/ui_capabilities/common/fixtures/plugins/foo_plugin/kibana.json

Co-authored-by: Larry Gregory <lgregorydev@gmail.com>

* commeeeooonnnn

* Update docs

* soooo many kibanajsons

* adjust plugin generator to add an owner

* Add owner to the plugin generator scripts

* update snapshot

* Fix snapshot

* review updates

Co-authored-by: Larry Gregory <lgregorydev@gmail.com>
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Stacey Gammon 2021-08-24 10:02:32 -04:00 committed by GitHub
parent 9857cac494
commit 52ee65b8d5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
98 changed files with 506 additions and 108 deletions

View file

@ -75,7 +75,7 @@ plugins/
- preboot plugins are bootstrapped to prepare the environment before Kibana starts.
- standard plugins define Kibana functionality while Kibana is running.
`owner` - [Required] Help users of your plugin know who manages this plugin and how to get in touch. This is required for internal plugins. `Owner.name` should be the name of the team that manages this plugin. This should match the team that owns this code in the [CODEOWNERS](https://github.com/elastic/kibana/blob/master/.github/CODEOWNERS) file (however, this is not currently enforced). Internal teams should also use a [GitHub team alias](https://github.com/orgs/elastic/teams) for `owner.githubTeam`. While many teams can contribute to a plugin, only a single team should be the primary owner.
`owner` - [Required] Help users of your plugin know who manages this plugin and how to get in touch. For internal developers, `Owner.name` should be the name of the team that manages this plugin. This should match the team that owns this code in the [CODEOWNERS](https://github.com/elastic/kibana/blob/master/.github/CODEOWNERS) file (however, this is not currently enforced). Internal teams should also use a [GitHub team alias](https://github.com/orgs/elastic/teams) for `owner.githubTeam`. This value is used to create a link to `https://github.com/orgs/elastic/teams/${githubTeam}`, so leave the `elastic/` prefix should be left out. While many teams can contribute to a plugin, only a single team should be the primary owner.
`description` - [Required] Give your plugin a description to help other developers understand what it does. This is required for internal plugins.

View file

@ -26,7 +26,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. |
| [owner](./kibana-plugin-core-server.pluginmanifest.owner.md) | <code>{</code><br/><code> readonly name: string;</code><br/><code> readonly githubTeam?: string;</code><br/><code> }</code> | TODO: make required once all internal plugins have this specified. |
| [owner](./kibana-plugin-core-server.pluginmanifest.owner.md) | <code>{</code><br/><code> readonly name: string;</code><br/><code> readonly githubTeam?: string;</code><br/><code> }</code> | |
| [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. |

View file

@ -4,12 +4,10 @@
## PluginManifest.owner property
TODO: make required once all internal plugins have this specified.
<b>Signature:</b>
```typescript
readonly owner?: {
readonly owner: {
readonly name: string;
readonly githubTeam?: string;
};

View file

@ -29,8 +29,7 @@ interface Manifest {
server: boolean;
kibanaVersion: string;
version: string;
// TODO: make this required.
owner?: {
owner: {
// Internally, this should be a team name.
name: string;
// All internally owned plugins should have a github team specified that can be pinged in issues, or used to look up
@ -64,6 +63,12 @@ export function parseKibanaPlatformPlugin(manifestPath: string): KibanaPlatformP
throw new TypeError('expected new platform plugin manifest to have a string version');
}
if (!manifest.owner || typeof manifest.owner.name !== 'string') {
throw new TypeError(
`Expected plugin ${manifest.id} manifest to have an owner with name specified (${manifestPath})`
);
}
return {
directory: Path.dirname(manifestPath),
manifestPath,

View file

@ -86,8 +86,8 @@ import ${json} from './${fileName}.json';
${plugin.manifest.description ?? ''}
${
plugin.manifest.owner?.githubTeam && name
? `Contact [${name}](https://github.com/orgs/elastic/teams/${plugin.manifest.owner?.githubTeam}) for questions regarding this plugin.`
plugin.manifest.owner.githubTeam && name
? `Contact [${name}](https://github.com/orgs/elastic/teams/${plugin.manifest.owner.githubTeam}) for questions regarding this plugin.`
: name
? `Contact ${name} for questions regarding this plugin.`
: ''

View file

@ -1,7 +1,7 @@
{
"id": "pluginA",
"summary": "This an example plugin for testing the api documentation system",
"version": "kibana",
"serviceFolders": ["foo"]
}
"id": "pluginA",
"owner": { "name": "Kibana Tech Leads" },
"summary": "This an example plugin for testing the api documentation system",
"version": "kibana",
"serviceFolders": ["foo"]
}

View file

@ -1,5 +1,6 @@
{
"id": "pluginB",
"owner": { "name": "Kibana Tech Leads" },
"summary": "This an example plugin for testing the api documentation system",
"version": "kibana"
}

View file

@ -18,6 +18,9 @@ export function getKibanaPlatformPlugin(id: string, dir?: string): KibanaPlatfor
server: true,
kibanaVersion: '1',
version: '1',
owner: {
name: 'Kibana Core',
},
serviceFolders: [],
requiredPlugins: [],
requiredBundles: [],

View file

@ -2,5 +2,8 @@
"id": "bar",
"ui": true,
"requiredBundles": ["foo"],
"version": "8.0.0"
"version": "8.0.0",
"owner": {
"name": "Operations"
}
}

View file

@ -1,5 +1,8 @@
{
"id": "foo",
"owner": {
"name": "Operations"
},
"ui": true,
"version": "8.0.0"
}

View file

@ -1,4 +1,7 @@
{
"id": "baz",
"owner": {
"name": "Operations"
},
"version": "8.0.0"
}

View file

@ -1,4 +1,7 @@
{
"id": "test_baz",
"owner": {
"name": "Operations"
},
"version": "8.0.0"
}

View file

@ -1,5 +1,6 @@
{
"id": "baz",
"owner": { "name": "Operations", "githubTeam": "kibana-operations" },
"ui": true,
"version": "8.0.0"
}

View file

@ -17,6 +17,9 @@ export interface Answers {
internalLocation: string;
ui: boolean;
server: boolean;
githubTeam?: string;
ownerName: string;
description?: string;
}
export const INTERNAL_PLUGIN_LOCATIONS: Array<{ name: string; value: string }> = [
@ -49,6 +52,11 @@ export const QUESTIONS = [
default: undefined,
validate: (name: string) => (!name ? 'name is required' : true),
},
{
name: 'description',
message: 'Provide a description for your plugin.',
default: undefined,
},
{
name: 'internal',
type: 'confirm',
@ -63,6 +71,24 @@ export const QUESTIONS = [
default: INTERNAL_PLUGIN_LOCATIONS[0].value,
when: ({ internal }: Answers) => internal,
},
{
name: 'ownerName',
message: 'Who is developing and maintaining this plugin?',
default: undefined,
when: ({ internal }: Answers) => !internal,
},
{
name: 'ownerName',
message: 'What team will maintain this plugin?',
default: undefined,
when: ({ internal }: Answers) => internal,
},
{
name: 'githubTeam',
message: 'What is your gitHub team alias?',
default: undefined,
when: ({ internal }: Answers) => internal,
},
{
name: 'ui',
type: 'confirm',

View file

@ -64,6 +64,10 @@ export async function renderTemplates({
hasServer: !!answers.server,
hasUi: !!answers.ui,
ownerName: answers.ownerName,
githubTeam: answers.githubTeam,
description: answers.description,
camelCase,
snakeCase,
upperCamelCase,

View file

@ -2,6 +2,11 @@
"id": "<%= camelCase(name) %>",
"version": "1.0.0",
"kibanaVersion": "kibana",
"owner": {
"name": "<%= ownerName %>",
"githubTeam": "<%= githubTeam %>"
},
"description": "<%= description %>",
"server": <%= hasServer %>,
"ui": <%= hasUi %>,
"requiredPlugins": ["navigation"],

View file

@ -101,9 +101,14 @@ it('builds a generated plugin into a viable archive', async () => {
expect(loadJsonFile.sync(Path.resolve(TMP_DIR, 'kibana', 'fooTestPlugin', 'kibana.json')))
.toMatchInlineSnapshot(`
Object {
"description": "",
"id": "fooTestPlugin",
"kibanaVersion": "7.5.0",
"optionalPlugins": Array [],
"owner": Object {
"githubTeam": "",
"name": "",
},
"requiredPlugins": Array [
"navigation",
],

View file

@ -24,6 +24,9 @@ function createManifest(
requiredPlugins: required,
optionalPlugins: optional,
requiredBundles: [],
owner: {
name: 'foo',
},
} as DiscoveredPlugin;
}

View file

@ -64,6 +64,10 @@ function createManifest(
requiredPlugins: required,
optionalPlugins: optional,
requiredBundles: [],
owner: {
name: 'Core',
githubTeam: 'kibana-core',
},
};
}

View file

@ -65,7 +65,7 @@ test('return error when manifest content is not a valid JSON', async () => {
test('return error when plugin id is missing', async () => {
mockReadFile.mockImplementation((path, cb) => {
cb(null, Buffer.from(JSON.stringify({ version: 'some-version' })));
cb(null, Buffer.from(JSON.stringify({ version: 'some-version', owner: { name: 'foo' } })));
});
await expect(parseManifest(pluginPath, packageInfo)).rejects.toMatchObject({
@ -77,7 +77,12 @@ test('return error when plugin id is missing', async () => {
test('return error when plugin id includes `.` characters', async () => {
mockReadFile.mockImplementation((path, cb) => {
cb(null, Buffer.from(JSON.stringify({ id: 'some.name', version: 'some-version' })));
cb(
null,
Buffer.from(
JSON.stringify({ id: 'some.name', version: 'some-version', owner: { name: 'foo' } })
)
);
});
await expect(parseManifest(pluginPath, packageInfo)).rejects.toMatchObject({
@ -90,7 +95,12 @@ test('return error when plugin id includes `.` characters', async () => {
test('return error when pluginId is not in camelCase format', async () => {
expect.assertions(1);
mockReadFile.mockImplementation((path, cb) => {
cb(null, Buffer.from(JSON.stringify({ id: 'some_name', version: 'kibana', server: true })));
cb(
null,
Buffer.from(
JSON.stringify({ id: 'some_name', version: 'kibana', server: true, owner: { name: 'foo' } })
)
);
});
await expect(parseManifest(pluginPath, packageInfo)).rejects.toMatchObject({
@ -102,7 +112,7 @@ test('return error when pluginId is not in camelCase format', async () => {
test('return error when plugin version is missing', async () => {
mockReadFile.mockImplementation((path, cb) => {
cb(null, Buffer.from(JSON.stringify({ id: 'someId' })));
cb(null, Buffer.from(JSON.stringify({ id: 'someId', owner: { name: 'foo' } })));
});
await expect(parseManifest(pluginPath, packageInfo)).rejects.toMatchObject({
@ -114,7 +124,10 @@ test('return error when plugin version is missing', async () => {
test('return error when plugin expected Kibana version is lower than actual version', async () => {
mockReadFile.mockImplementation((path, cb) => {
cb(null, Buffer.from(JSON.stringify({ id: 'someId', version: '6.4.2' })));
cb(
null,
Buffer.from(JSON.stringify({ id: 'someId', version: '6.4.2', owner: { name: 'foo' } }))
);
});
await expect(parseManifest(pluginPath, packageInfo)).rejects.toMatchObject({
@ -128,7 +141,14 @@ test('return error when plugin expected Kibana version cannot be interpreted as
mockReadFile.mockImplementation((path, cb) => {
cb(
null,
Buffer.from(JSON.stringify({ id: 'someId', version: '1.0.0', kibanaVersion: 'non-sem-ver' }))
Buffer.from(
JSON.stringify({
id: 'someId',
version: '1.0.0',
kibanaVersion: 'non-sem-ver',
owner: { name: 'foo' },
})
)
);
});
@ -141,7 +161,12 @@ test('return error when plugin expected Kibana version cannot be interpreted as
test('return error when plugin config path is not a string', async () => {
mockReadFile.mockImplementation((path, cb) => {
cb(null, Buffer.from(JSON.stringify({ id: 'someId', version: '7.0.0', configPath: 2 })));
cb(
null,
Buffer.from(
JSON.stringify({ id: 'someId', version: '7.0.0', configPath: 2, owner: { name: 'foo' } })
)
);
});
await expect(parseManifest(pluginPath, packageInfo)).rejects.toMatchObject({
@ -155,7 +180,14 @@ test('return error when plugin config path is an array that contains non-string
mockReadFile.mockImplementation((path, cb) => {
cb(
null,
Buffer.from(JSON.stringify({ id: 'someId', version: '7.0.0', configPath: ['config', 2] }))
Buffer.from(
JSON.stringify({
id: 'someId',
version: '7.0.0',
configPath: ['config', 2],
owner: { name: 'foo' },
})
)
);
});
@ -168,7 +200,10 @@ test('return error when plugin config path is an array that contains non-string
test('return error when plugin expected Kibana version is higher than actual version', async () => {
mockReadFile.mockImplementation((path, cb) => {
cb(null, Buffer.from(JSON.stringify({ id: 'someId', version: '7.0.1' })));
cb(
null,
Buffer.from(JSON.stringify({ id: 'someId', version: '7.0.1', owner: { name: 'foo' } }))
);
});
await expect(parseManifest(pluginPath, packageInfo)).rejects.toMatchObject({
@ -180,7 +215,10 @@ test('return error when plugin expected Kibana version is higher than actual ver
test('return error when both `server` and `ui` are set to `false` or missing', async () => {
mockReadFile.mockImplementation((path, cb) => {
cb(null, Buffer.from(JSON.stringify({ id: 'someId', version: '7.0.0' })));
cb(
null,
Buffer.from(JSON.stringify({ id: 'someId', version: '7.0.0', owner: { name: 'foo' } }))
);
});
await expect(parseManifest(pluginPath, packageInfo)).rejects.toMatchObject({
@ -192,7 +230,15 @@ test('return error when both `server` and `ui` are set to `false` or missing', a
mockReadFile.mockImplementation((path, cb) => {
cb(
null,
Buffer.from(JSON.stringify({ id: 'someId', version: '7.0.0', server: false, ui: false }))
Buffer.from(
JSON.stringify({
id: 'someId',
version: '7.0.0',
server: false,
ui: false,
owner: { name: 'foo' },
})
)
);
});
@ -214,6 +260,7 @@ test('return error when manifest contains unrecognized properties', async () =>
server: true,
unknownOne: 'one',
unknownTwo: true,
owner: { name: 'foo' },
})
)
);
@ -237,6 +284,7 @@ test('returns error when manifest contains unrecognized `type`', async () => {
kibanaVersion: '7.0.0',
type: 'unknown',
server: true,
owner: { name: 'foo' },
})
)
);
@ -252,7 +300,12 @@ test('returns error when manifest contains unrecognized `type`', async () => {
describe('configPath', () => {
test('falls back to plugin id if not specified', async () => {
mockReadFile.mockImplementation((path, cb) => {
cb(null, Buffer.from(JSON.stringify({ id: 'plugin', version: '7.0.0', server: true })));
cb(
null,
Buffer.from(
JSON.stringify({ id: 'plugin', version: '7.0.0', server: true, owner: { name: 'foo' } })
)
);
});
const manifest = await parseManifest(pluginPath, packageInfo);
@ -261,7 +314,12 @@ describe('configPath', () => {
test('falls back to plugin id in snakeCase format', async () => {
mockReadFile.mockImplementation((path, cb) => {
cb(null, Buffer.from(JSON.stringify({ id: 'someId', version: '7.0.0', server: true })));
cb(
null,
Buffer.from(
JSON.stringify({ id: 'someId', version: '7.0.0', server: true, owner: { name: 'foo' } })
)
);
});
const manifest = await parseManifest(pluginPath, packageInfo);
@ -273,7 +331,13 @@ describe('configPath', () => {
cb(
null,
Buffer.from(
JSON.stringify({ id: 'someId', configPath: 'somePath', version: '7.0.0', server: true })
JSON.stringify({
id: 'someId',
configPath: 'somePath',
version: '7.0.0',
server: true,
owner: { name: 'foo' },
})
)
);
});
@ -287,7 +351,13 @@ describe('configPath', () => {
cb(
null,
Buffer.from(
JSON.stringify({ id: 'someId', configPath: ['somePath'], version: '7.0.0', server: true })
JSON.stringify({
id: 'someId',
configPath: ['somePath'],
version: '7.0.0',
server: true,
owner: { name: 'foo' },
})
)
);
});
@ -299,7 +369,12 @@ describe('configPath', () => {
test('set defaults for all missing optional fields', async () => {
mockReadFile.mockImplementation((path, cb) => {
cb(null, Buffer.from(JSON.stringify({ id: 'someId', version: '7.0.0', server: true })));
cb(
null,
Buffer.from(
JSON.stringify({ id: 'someId', version: '7.0.0', server: true, owner: { name: 'foo' } })
)
);
});
await expect(parseManifest(pluginPath, packageInfo)).resolves.toEqual({
@ -313,6 +388,7 @@ test('set defaults for all missing optional fields', async () => {
requiredBundles: [],
server: true,
ui: false,
owner: { name: 'foo' },
});
});
@ -330,6 +406,7 @@ test('return all set optional fields as they are in manifest', async () => {
requiredPlugins: ['some-required-plugin', 'some-required-plugin-2'],
optionalPlugins: ['some-optional-plugin'],
ui: true,
owner: { name: 'foo' },
})
)
);
@ -346,6 +423,7 @@ test('return all set optional fields as they are in manifest', async () => {
requiredPlugins: ['some-required-plugin', 'some-required-plugin-2'],
server: false,
ui: true,
owner: { name: 'foo' },
});
});
@ -361,6 +439,7 @@ test('return manifest when plugin expected Kibana version matches actual version
kibanaVersion: '7.0.0-alpha2',
requiredPlugins: ['some-required-plugin'],
server: true,
owner: { name: 'foo' },
})
)
);
@ -377,6 +456,7 @@ test('return manifest when plugin expected Kibana version matches actual version
requiredBundles: [],
server: true,
ui: false,
owner: { name: 'foo' },
});
});
@ -392,6 +472,7 @@ test('return manifest when plugin expected Kibana version is `kibana`', async ()
requiredPlugins: ['some-required-plugin'],
server: true,
ui: true,
owner: { name: 'foo' },
})
)
);
@ -408,5 +489,6 @@ test('return manifest when plugin expected Kibana version is `kibana`', async ()
requiredBundles: [],
server: true,
ui: true,
owner: { name: 'foo' },
});
});

View file

@ -121,6 +121,15 @@ export async function parseManifest(
);
}
if (!manifest.owner || !manifest.owner.name || typeof manifest.owner.name !== 'string') {
throw PluginDiscoveryError.invalidManifest(
manifestPath,
new Error(
`Plugin manifest for "${manifest.id}" must contain an "owner" property, which includes a nested "name" property.`
)
);
}
if (manifest.configPath !== undefined && !isConfigPath(manifest.configPath)) {
throw PluginDiscoveryError.invalidManifest(
manifestPath,
@ -201,7 +210,7 @@ export async function parseManifest(
ui: includesUiPlugin,
server: includesServerPlugin,
extraPublicDirs: manifest.extraPublicDirs,
owner: manifest.owner,
owner: manifest.owner!,
description: manifest.description,
};
}

View file

@ -30,10 +30,23 @@ const Plugins = {
'kibana.json': 'not-json',
}),
incomplete: () => ({
'kibana.json': JSON.stringify({ version: '1' }),
'kibana.json': JSON.stringify({
version: '1',
owner: {
name: 'foo',
githubTeam: 'foo',
},
}),
}),
incompatible: () => ({
'kibana.json': JSON.stringify({ id: 'plugin', version: '1' }),
'kibana.json': JSON.stringify({
id: 'plugin',
version: '1',
owner: {
name: 'foo',
githubTeam: 'foo',
},
}),
}),
incompatibleType: (id: string) => ({
'kibana.json': JSON.stringify({
@ -42,6 +55,10 @@ const Plugins = {
kibanaVersion: '1.2.3',
type: 'evenEarlierThanPreboot',
server: true,
owner: {
name: 'foo',
githubTeam: 'foo',
},
}),
}),
missingManifest: () => ({}),
@ -51,6 +68,17 @@ const Plugins = {
content: JSON.stringify({ id: 'plugin', version: '1' }),
}),
}),
missingOwnerAttribute: () => ({
'kibana.json': JSON.stringify({
id: 'foo',
configPath: ['plugins', 'foo'],
version: '1',
kibanaVersion: '1.2.3',
requiredPlugins: [],
optionalPlugins: [],
server: true,
}),
}),
valid: (id: string) => ({
'kibana.json': JSON.stringify({
id,
@ -60,6 +88,10 @@ const Plugins = {
requiredPlugins: [],
optionalPlugins: [],
server: true,
owner: {
name: 'foo',
githubTeam: 'foo',
},
}),
}),
validPreboot: (id: string) => ({
@ -72,6 +104,10 @@ const Plugins = {
requiredPlugins: [],
optionalPlugins: [],
server: true,
owner: {
name: 'foo',
githubTeam: 'foo',
},
}),
}),
};
@ -182,6 +218,7 @@ describe('plugins discovery system', () => {
[`${KIBANA_ROOT}/src/plugins/plugin_c`]: Plugins.incompatible(),
[`${KIBANA_ROOT}/src/plugins/plugin_d`]: Plugins.incompatibleType('pluginD'),
[`${KIBANA_ROOT}/src/plugins/plugin_ad`]: Plugins.missingManifest(),
[`${KIBANA_ROOT}/src/plugins/plugin_e`]: Plugins.missingOwnerAttribute(),
},
{ createCwd: false }
);
@ -196,21 +233,40 @@ describe('plugins discovery system', () => {
)
.toPromise();
expect(errors).toEqual(
expect.arrayContaining([
`Error: Unexpected token o in JSON at position 1 (invalid-manifest, ${manifestPath(
'plugin_a'
)})`,
`Error: Plugin manifest must contain an "id" property. (invalid-manifest, ${manifestPath(
'plugin_b'
)})`,
`Error: Plugin "plugin" is only compatible with Kibana version "1", but used Kibana version is "1.2.3". (incompatible-version, ${manifestPath(
'plugin_c'
)})`,
`Error: The "type" in manifest for plugin "pluginD" is set to "evenEarlierThanPreboot", but it should either be "standard" or "preboot". (invalid-manifest, ${manifestPath(
'plugin_d'
)})`,
])
expect(errors).toContain(
`Error: Unexpected token o in JSON at position 1 (invalid-manifest, ${manifestPath(
'plugin_a'
)})`
);
expect(errors).toContain(
`Error: Plugin manifest must contain an "id" property. (invalid-manifest, ${manifestPath(
'plugin_b'
)})`
);
expect(errors).toContain(
`Error: Plugin "plugin" is only compatible with Kibana version "1", but used Kibana version is "1.2.3". (incompatible-version, ${manifestPath(
'plugin_c'
)})`
);
expect(errors).toContain(
`Error: The "type" in manifest for plugin "pluginD" is set to "evenEarlierThanPreboot", but it should either be "standard" or "preboot". (invalid-manifest, ${manifestPath(
'plugin_d'
)})`
);
expect(errors).toContain(
`Error: The "type" in manifest for plugin "pluginD" is set to "evenEarlierThanPreboot", but it should either be "standard" or "preboot". (invalid-manifest, ${manifestPath(
'plugin_d'
)})`
);
expect(errors).toContain(
`Error: Plugin manifest for "foo" must contain an "owner" property, which includes a nested "name" property. (invalid-manifest, ${manifestPath(
'plugin_e'
)})`
);
});

View file

@ -42,6 +42,7 @@ describe('PluginsService', () => {
configPath = [path],
server = true,
ui = true,
owner = { name: 'foo' },
}: {
path?: string;
disabled?: boolean;
@ -54,6 +55,7 @@ describe('PluginsService', () => {
configPath?: ConfigPath;
server?: boolean;
ui?: boolean;
owner?: { name: string };
}
): PluginWrapper => {
return new PluginWrapper({
@ -69,6 +71,7 @@ describe('PluginsService', () => {
optionalPlugins,
server,
ui,
owner,
},
opaqueId: Symbol(id),
initializerContext: { logger } as any,

View file

@ -56,6 +56,7 @@ function createPluginManifest(manifestProps: Partial<PluginManifest> = {}): Plug
requiredBundles: [],
server: true,
ui: true,
owner: { name: 'Core' },
...manifestProps,
};
}

View file

@ -38,6 +38,10 @@ function createPluginManifest(manifestProps: Partial<PluginManifest> = {}): Plug
optionalPlugins: ['some-optional-dep'],
server: true,
ui: true,
owner: {
name: 'Core',
githubTeam: 'kibana-core',
},
...manifestProps,
};
}

View file

@ -101,6 +101,10 @@ const createPlugin = (
requiredBundles,
optionalPlugins,
server,
owner: {
name: 'Core',
githubTeam: 'kibana-core',
},
ui,
},
opaqueId: Symbol(id),

View file

@ -55,6 +55,7 @@ function createPlugin(
requiredBundles: [],
server,
ui,
owner: { name: 'foo' },
},
opaqueId: Symbol(id),
initializerContext: { logger } as any,

View file

@ -226,10 +226,7 @@ export interface PluginManifest {
*/
readonly serviceFolders?: readonly string[];
/**
* TODO: make required once all internal plugins have this specified.
*/
readonly owner?: {
readonly owner: {
/**
* The name of the team that currently owns this plugin.
*/

View file

@ -1530,7 +1530,8 @@ export interface PluginManifest {
readonly id: PluginName;
readonly kibanaVersion: string;
readonly optionalPlugins: readonly PluginName[];
readonly owner?: {
// (undocumented)
readonly owner: {
readonly name: string;
readonly githubTeam?: string;
};
@ -2918,9 +2919,9 @@ export const validBodyOutput: readonly ["data", "stream"];
//
// src/core/server/elasticsearch/client/types.ts:94:7 - (ae-forgotten-export) The symbol "Explanation" needs to be exported by the entry point index.d.ts
// src/core/server/http/router/response.ts:301:3 - (ae-forgotten-export) The symbol "KibanaResponse" needs to be exported by the entry point index.d.ts
// src/core/server/plugins/types.ts:380:3 - (ae-forgotten-export) The symbol "KibanaConfigType" needs to be exported by the entry point index.d.ts
// src/core/server/plugins/types.ts:380:3 - (ae-forgotten-export) The symbol "SharedGlobalConfigKeys" needs to be exported by the entry point index.d.ts
// src/core/server/plugins/types.ts:383:3 - (ae-forgotten-export) The symbol "SavedObjectsConfigType" needs to be exported by the entry point index.d.ts
// src/core/server/plugins/types.ts:489:5 - (ae-unresolved-link) The @link reference could not be resolved: The package "kibana" does not have an export "create"
// src/core/server/plugins/types.ts:377:3 - (ae-forgotten-export) The symbol "KibanaConfigType" needs to be exported by the entry point index.d.ts
// src/core/server/plugins/types.ts:377:3 - (ae-forgotten-export) The symbol "SharedGlobalConfigKeys" needs to be exported by the entry point index.d.ts
// src/core/server/plugins/types.ts:380:3 - (ae-forgotten-export) The symbol "SavedObjectsConfigType" needs to be exported by the entry point index.d.ts
// src/core/server/plugins/types.ts:486:5 - (ae-unresolved-link) The @link reference could not be resolved: The package "kibana" does not have an export "create"
```

View file

@ -1,5 +1,9 @@
{
"id": "codeCoverageTestPlugin",
"owner": {
"name": "Core",
"githubTeam": "kibana-core"
},
"version": "kibana",
"server": true,
"ui": false

View file

@ -1,6 +1,8 @@
{
"id": "coverageFixtures",
"owner": { "name": "Kibana Operations", "githubTeam": "kibana-operations" },
"version": "kibana",
"server": false,
"ui": true
}
}

View file

@ -1,5 +1,9 @@
{
"id": "newsfeedFixtures",
"owner": {
"name": "Core",
"githubTeam": "kibana-core"
},
"version": "kibana",
"server": true,
"ui": false

View file

@ -1,16 +1,13 @@
{
"id": "kbnTpRunPipeline",
"owner": {
"name": "Core",
"githubTeam": "kibana-core"
},
"version": "0.0.1",
"kibanaVersion": "kibana",
"requiredPlugins": [
"data",
"savedObjects",
"kibanaUtils",
"expressions"
],
"requiredPlugins": ["data", "savedObjects", "kibanaUtils", "expressions"],
"server": true,
"ui": true,
"requiredBundles": [
"inspector"
]
"requiredBundles": ["inspector"]
}

View file

@ -1,5 +1,9 @@
{
"id": "appLinkTest",
"owner": {
"name": "Core",
"githubTeam": "kibana-core"
},
"version": "0.0.1",
"kibanaVersion": "kibana",
"server": false,

View file

@ -1,5 +1,9 @@
{
"id": "coreAppStatus",
"owner": {
"name": "Core",
"githubTeam": "kibana-core"
},
"version": "0.0.1",
"kibanaVersion": "kibana",
"configPath": ["core_app_status"],

View file

@ -1,5 +1,9 @@
{
"id": "coreHistoryBlock",
"owner": {
"name": "Core",
"githubTeam": "kibana-core"
},
"version": "0.0.1",
"kibanaVersion": "kibana",
"server": false,

View file

@ -1,6 +1,10 @@
{
"id": "coreHttp",
"version": "0.0.1",
"owner": {
"name": "Core",
"githubTeam": "kibana-core"
},
"kibanaVersion": "kibana",
"configPath": ["core_http"],
"server": true,

View file

@ -2,6 +2,10 @@
"id": "corePluginA",
"version": "0.0.1",
"kibanaVersion": "kibana",
"owner": {
"name": "Core",
"githubTeam": "kibana-core"
},
"configPath": ["core_plugin_a"],
"server": true,
"ui": true

View file

@ -1,6 +1,10 @@
{
"id": "corePluginAppleave",
"version": "0.0.1",
"owner": {
"name": "Core",
"githubTeam": "kibana-core"
},
"kibanaVersion": "kibana",
"configPath": ["core_plugin_appleave"],
"server": false,

View file

@ -2,6 +2,10 @@
"id": "corePluginB",
"version": "0.0.1",
"kibanaVersion": "kibana",
"owner": {
"name": "Core",
"githubTeam": "kibana-core"
},
"configPath": ["core_plugin_b"],
"server": true,
"ui": true,

View file

@ -1,5 +1,9 @@
{
"id": "corePluginChromeless",
"owner": {
"name": "Core",
"githubTeam": "kibana-core"
},
"version": "0.0.1",
"kibanaVersion": "kibana",
"configPath": ["core_plugin_chromeless"],

View file

@ -1,5 +1,9 @@
{
"id": "corePluginDeepLinks",
"owner": {
"name": "Core",
"githubTeam": "kibana-core"
},
"version": "0.0.1",
"kibanaVersion": "kibana",
"configPath": ["core_plugin_deep_links"],

View file

@ -1,6 +1,10 @@
{
"id": "corePluginDeprecations",
"version": "0.0.1",
"owner": {
"name": "Core",
"githubTeam": "kibana-core"
},
"kibanaVersion": "kibana",
"configPath": ["corePluginDeprecations"],
"server": true,

View file

@ -1,5 +1,9 @@
{
"id": "corePluginExecutionContext",
"owner": {
"name": "Core",
"githubTeam": "kibana-core"
},
"version": "0.0.1",
"kibanaVersion": "kibana",
"configPath": ["core_plugin_execution_context"],

View file

@ -1,5 +1,9 @@
{
"id": "corePluginHelpmenu",
"owner": {
"name": "Core",
"githubTeam": "kibana-core"
},
"version": "0.0.1",
"kibanaVersion": "kibana",
"configPath": ["core_plugin_helpmenu"],

View file

@ -1,5 +1,9 @@
{
"id": "corePluginRouteTimeouts",
"owner": {
"name": "Core",
"githubTeam": "kibana-core"
},
"version": "0.0.1",
"kibanaVersion": "kibana",
"configPath": ["core_plugin_route_timeouts"],

View file

@ -1,5 +1,9 @@
{
"id": "corePluginStaticAssets",
"owner": {
"name": "Core",
"githubTeam": "kibana-core"
},
"version": "0.0.1",
"kibanaVersion": "kibana",
"server": false,

View file

@ -1,14 +1,12 @@
{
"id": "coreProviderPlugin",
"owner": {
"name": "Core",
"githubTeam": "kibana-core"
},
"version": "0.0.1",
"kibanaVersion": "kibana",
"optionalPlugins": [
"corePluginA",
"corePluginB",
"coreHttp",
"licensing",
"globalSearchTest"
],
"optionalPlugins": ["corePluginA", "corePluginB", "coreHttp", "licensing", "globalSearchTest"],
"server": false,
"ui": true
}

View file

@ -1,5 +1,9 @@
{
"id": "dataSearchPlugin",
"owner": {
"name": "App Services",
"githubTeam": "kibana-app-services"
},
"version": "0.0.1",
"kibanaVersion": "kibana",
"configPath": ["data_search_test_plugin"],

View file

@ -1,5 +1,9 @@
{
"id": "elasticsearchClientPlugin",
"owner": {
"name": "Core",
"githubTeam": "kibana-core"
},
"version": "0.0.1",
"kibanaVersion": "kibana",
"server": true,

View file

@ -1,5 +1,9 @@
{
"id": "kbnSamplePanelAction",
"owner": {
"name": "App Services",
"githubTeam": "kibana-app-services"
},
"version": "0.0.1",
"kibanaVersion": "kibana",
"configPath": ["kbn_sample_panel_action"],

View file

@ -1,5 +1,9 @@
{
"id": "kbnTopNav",
"owner": {
"name": "Core",
"githubTeam": "kibana-core"
},
"version": "0.0.1",
"kibanaVersion": "kibana",
"configPath": ["kbn_top_nav"],

View file

@ -1,11 +1,12 @@
{
"id": "kbnTpCustomVisualizations",
"owner": {
"name": "Kibana App",
"githubTeam": "kibana-app"
},
"version": "0.0.1",
"kibanaVersion": "kibana",
"requiredPlugins": [
"expressions",
"visualizations"
],
"requiredPlugins": ["expressions", "visualizations"],
"server": false,
"ui": true
}

View file

@ -1,5 +1,9 @@
{
"id": "managementTestPlugin",
"owner": {
"name": "App Services",
"githubTeam": "kibana-app-services"
},
"version": "0.0.1",
"kibanaVersion": "kibana",
"configPath": ["management_test_plugin"],

View file

@ -1,5 +1,9 @@
{
"id": "renderingPlugin",
"owner": {
"name": "Core",
"githubTeam": "kibana-core"
},
"version": "0.0.1",
"kibanaVersion": "kibana",
"configPath": ["rendering_plugin"],

View file

@ -1,5 +1,9 @@
{
"id": "savedObjectExportTransforms",
"owner": {
"name": "Core",
"githubTeam": "kibana-core"
},
"version": "0.0.1",
"kibanaVersion": "kibana",
"configPath": ["saved_object_export_transforms"],

View file

@ -1,5 +1,9 @@
{
"id": "savedObjectImportWarnings",
"owner": {
"name": "Core",
"githubTeam": "kibana-core"
},
"version": "0.0.1",
"kibanaVersion": "kibana",
"configPath": ["saved_object_import_warnings"],

View file

@ -1,5 +1,9 @@
{
"id": "savedObjectsHiddenType",
"owner": {
"name": "Core",
"githubTeam": "kibana-core"
},
"version": "0.0.1",
"kibanaVersion": "kibana",
"configPath": ["saved_objects_hidden_type"],

View file

@ -1,5 +1,9 @@
{
"id": "sessionNotifications",
"owner": {
"name": "Core",
"githubTeam": "kibana-core"
},
"version": "0.0.1",
"kibanaVersion": "kibana",
"configPath": ["session_notifications"],

View file

@ -1,5 +1,9 @@
{
"id": "telemetryTestPlugin",
"owner": {
"name": "Core",
"githubTeam": "kibana-core"
},
"version": "0.0.1",
"kibanaVersion": "kibana",
"configPath": ["telemetryTestPlugin"],

View file

@ -1,5 +1,9 @@
{
"id": "uiSettingsPlugin",
"owner": {
"name": "Core",
"githubTeam": "kibana-core"
},
"version": "0.0.1",
"kibanaVersion": "kibana",
"configPath": ["ui_settings_plugin"],

View file

@ -1,5 +1,9 @@
{
"id": "usageCollectionTestPlugin",
"owner": {
"name": "Core",
"githubTeam": "kibana-core"
},
"version": "0.0.1",
"kibanaVersion": "kibana",
"configPath": ["usageCollectionTestPlugin"],

View file

@ -1,5 +1,6 @@
{
"id": "statusPluginA",
"owner": { "name": "Core", "githubTeam": "kibana-core" },
"version": "0.0.1",
"kibanaVersion": "kibana",
"server": true,

View file

@ -1,5 +1,6 @@
{
"id": "statusPluginB",
"owner": { "name": "Core", "githubTeam": "kibana-core" },
"version": "0.0.1",
"kibanaVersion": "kibana",
"server": true,

View file

@ -1,23 +1,13 @@
{
"id": "dashboardEnhanced",
"owner": {
"name": "App Services",
"githubTeam": "kibana-app-services"
},
"version": "kibana",
"server": true,
"ui": true,
"configPath": [
"xpack",
"dashboardEnhanced"
],
"requiredPlugins": [
"dashboard",
"data",
"embeddable",
"share",
"uiActionsEnhanced"
],
"requiredBundles": [
"embeddable",
"embeddableEnhanced",
"kibanaReact",
"kibanaUtils"
]
"configPath": ["xpack", "dashboardEnhanced"],
"requiredPlugins": ["dashboard", "data", "embeddable", "share", "uiActionsEnhanced"],
"requiredBundles": ["embeddable", "embeddableEnhanced", "kibanaReact", "kibanaUtils"]
}

View file

@ -3,7 +3,7 @@
"version": "8.0.0",
"kibanaVersion": "kibana",
"owner": {
"owner": "Stack Monitoring",
"name": "Stack Monitoring",
"githubTeam": "stack-monitoring-ui"
},
"configPath": ["monitoring"],

View file

@ -1,5 +1,9 @@
{
"id": "ruleRegistry",
"owner": {
"name": "RAC",
"githubTeam": "rac"
},
"version": "8.0.0",
"kibanaVersion": "kibana",
"configPath": ["xpack", "ruleRegistry"],

View file

@ -1,5 +1,9 @@
{
"id": "aadFixtures",
"owner": {
"name": "Alerting Services",
"githubTeam": "kibana-alerting-services"
},
"version": "1.0.0",
"kibanaVersion": "kibana",
"configPath": ["xpack"],

View file

@ -1,5 +1,9 @@
{
"id": "actionsSimulators",
"owner": {
"name": "Alerting Services",
"githubTeam": "kibana-alerting-services"
},
"version": "1.0.0",
"kibanaVersion": "kibana",
"configPath": ["xpack"],

View file

@ -1,10 +1,14 @@
{
"id": "alertsFixtures",
"owner": {
"name": "Alerting Services",
"githubTeam": "kibana-alerting-services"
},
"version": "1.0.0",
"kibanaVersion": "kibana",
"configPath": ["xpack"],
"requiredPlugins": ["taskManager", "features", "actions", "alerting", "encryptedSavedObjects"],
"optionalPlugins": ["security", "spaces"],
"optionalPlugins": ["security", "spaces"],
"server": true,
"ui": false
}

View file

@ -1,5 +1,9 @@
{
"id": "alertsRestrictedFixtures",
"owner": {
"name": "Alerting Services",
"githubTeam": "kibana-alerting-services"
},
"version": "1.0.0",
"kibanaVersion": "kibana",
"configPath": ["xpack"],

View file

@ -1,5 +1,9 @@
{
"id": "taskManagerFixture",
"owner": {
"name": "Alerting Services",
"githubTeam": "kibana-alerting-services"
},
"version": "1.0.0",
"kibanaVersion": "kibana",
"configPath": ["xpack"],

View file

@ -1,10 +1,14 @@
{
"id": "casesClientUserFixture",
"owner": {
"githubTeam": "security-threat-hunting",
"name": "Security Solution Threat Hunting"
},
"version": "1.0.0",
"kibanaVersion": "kibana",
"configPath": ["xpack"],
"requiredPlugins": ["features", "cases"],
"optionalPlugins": ["security", "spaces"],
"optionalPlugins": ["security", "spaces"],
"server": true,
"ui": false
}

View file

@ -1,10 +1,14 @@
{
"id": "observabilityFixtures",
"owner": {
"githubTeam": "security-threat-hunting",
"name": "Security Solution Threat Hunting"
},
"version": "1.0.0",
"kibanaVersion": "kibana",
"configPath": ["xpack"],
"requiredPlugins": ["features", "cases"],
"optionalPlugins": ["security", "spaces"],
"optionalPlugins": ["security", "spaces"],
"server": true,
"ui": false
}

View file

@ -1,10 +1,14 @@
{
"id": "securitySolutionFixtures",
"owner": {
"githubTeam": "security-threat-hunting",
"name": "Security Solution Threat Hunting"
},
"version": "1.0.0",
"kibanaVersion": "kibana",
"configPath": ["xpack"],
"requiredPlugins": ["features", "cases"],
"optionalPlugins": ["security", "spaces"],
"optionalPlugins": ["security", "spaces"],
"server": true,
"ui": false
}

View file

@ -1,5 +1,6 @@
{
"id": "samlProviderPlugin",
"owner": { "name": "Core", "githubTeam": "kibana-core" },
"version": "8.0.0",
"kibanaVersion": "kibana",
"server": true,

View file

@ -1,5 +1,6 @@
{
"id": "eso",
"owner": { "name": "Platform Security", "githubTeam": "kibana-security" },
"version": "8.0.0",
"kibanaVersion": "kibana",
"requiredPlugins": ["encryptedSavedObjects", "spaces"],

View file

@ -1,5 +1,6 @@
{
"id": "kibanaCorsTest",
"owner": { "name": "Platform Security", "githubTeam": "kibana-security" },
"version": "1.0.0",
"kibanaVersion": "kibana",
"configPath": ["test", "cors"],

View file

@ -1,5 +1,6 @@
{
"id": "iframeEmbedded",
"owner": { "name": "Core", "githubTeam": "kibana-core" },
"version": "1.0.0",
"kibanaVersion": "kibana",
"server": true,

View file

@ -1,5 +1,6 @@
{
"id": "alertingFixture",
"owner": { "name": "Alerting Services", "githubTeam": "kibana-alerting-services" },
"version": "1.0.0",
"kibanaVersion": "kibana",
"configPath": ["xpack"],

View file

@ -1,5 +1,6 @@
{
"id": "testFeatureUsage",
"owner": { "name": "Platform Security", "githubTeam": "kibana-security" },
"version": "kibana",
"server": false,
"ui": true,

View file

@ -1,5 +1,6 @@
{
"id": "elasticsearchClientXpack",
"owner": { "name": "Core", "githubTeam": "kibana-core" },
"version": "1.0.0",
"kibanaVersion": "kibana",
"server": true,

View file

@ -1,5 +1,9 @@
{
"id": "eventLogFixture",
"owner": {
"name": "Kibana Alerting",
"githubTeam": "kibana-alerting-services"
},
"version": "1.0.0",
"kibanaVersion": "kibana",
"configPath": ["xpack"],

View file

@ -1,5 +1,9 @@
{
"id": "featureUsageTest",
"owner": {
"name": "Platform Security",
"githubTeam": "kibana-security"
},
"version": "1.0.0",
"kibanaVersion": "kibana",
"configPath": ["xpack", "feature_usage_test"],

View file

@ -1,5 +1,9 @@
{
"id": "sampleTaskPlugin",
"owner": {
"name": "Alerting Services",
"githubTeam": "kibana-alerting-services"
},
"version": "1.0.0",
"kibanaVersion": "kibana",
"configPath": ["xpack"],

View file

@ -1,5 +1,6 @@
{
"id": "taskManagerPerformance",
"owner": { "name": "Alerting Services", "githubTeam": "kibana-alerting-services" },
"version": "1.0.0",
"kibanaVersion": "kibana",
"configPath": ["xpack"],

View file

@ -1,5 +1,6 @@
{
"id": "globalSearchTest",
"owner": { "name": "Core", "githubTeam": "kibana-core" },
"version": "1.0.0",
"kibanaVersion": "kibana",
"configPath": ["xpack", "global_search_test"],

View file

@ -1,14 +1,14 @@
{
"id": "resolverTest",
"owner": {
"githubTeam": "security-threat-hunting",
"name": "Security Solution Threat Hunting"
},
"version": "1.0.0",
"kibanaVersion": "kibana",
"configPath": ["xpack", "resolverTest"],
"requiredPlugins": [
"securitySolution"
],
"requiredBundles": [
"kibanaReact"
],
"requiredPlugins": ["securitySolution"],
"requiredBundles": ["kibanaReact"],
"server": false,
"ui": true
}

View file

@ -1,5 +1,6 @@
{
"id": "timelinesTest",
"owner": { "name": "Security solution", "githubTeam": "security-solution" },
"version": "1.0.0",
"kibanaVersion": "kibana",
"configPath": ["xpack", "timelinesTest"],

View file

@ -1,5 +1,6 @@
{
"id": "savedObjectTestPlugin",
"owner": { "name": "Platform Security", "githubTeam": "kibana-security" },
"version": "kibana",
"server": true,
"ui": false

View file

@ -1,5 +1,6 @@
{
"id": "auditLog",
"owner": { "name": "Platform Security", "githubTeam": "kibana-security" },
"version": "1.0.0",
"kibanaVersion": "kibana",
"configPath": [],

View file

@ -1,5 +1,6 @@
{
"id": "oidcProviderPlugin",
"owner": { "name": "Platform Security", "githubTeam": "kibana-security" },
"version": "8.0.0",
"kibanaVersion": "kibana",
"server": true,

View file

@ -1,5 +1,6 @@
{
"id": "samlProviderPlugin",
"owner": { "name": "Core", "githubTeam": "kibana-core" },
"version": "8.0.0",
"kibanaVersion": "kibana",
"server": true,

View file

@ -1,5 +1,6 @@
{
"id": "securityTestEndpoints",
"owner": { "name": "Platform Security", "githubTeam": "kibana-security" },
"version": "8.0.0",
"kibanaVersion": "kibana",
"server": true,

View file

@ -1,5 +1,6 @@
{
"id": "spacesTestPlugin",
"owner": { "name": "Platform Security", "githubTeam": "kibana-security" },
"version": "kibana",
"server": true,
"ui": false

View file

@ -1,5 +1,6 @@
{
"id": "fooPlugin",
"owner": { "name": "Platform Security", "githubTeam": "kibana-security" },
"version": "1.0.0",
"kibanaVersion": "kibana",
"requiredPlugins": ["features"],

View file

@ -1,5 +1,6 @@
{
"id": "applicationUsageTest",
"owner": { "name": "Core", "githubTeam": "kibana-core" },
"version": "1.0.0",
"kibanaVersion": "kibana",
"configPath": ["xpack", "applicationUsageTest"],

View file

@ -1,5 +1,6 @@
{
"id": "stackManagementUsageTest",
"owner": { "name": "Kibana Stack Management", "githubTeam": "kibana-stack-management" },
"version": "1.0.0",
"kibanaVersion": "kibana",
"configPath": ["xpack", "stackManagementUsageTest"],