mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[scout] fix playwright configs discovery script and add save
flag for CI (#213147)
## Summary This PR fixes the search logic to look for playwright configs in all possible & expected locations (`src/*` was not working), matching one of 3 regexp: ``` /(x-pack\/platform\/plugins\/(?:private|shared|[^\/]+)\/([^\/]+))\/ui_tests\//, /(x-pack\/solutions\/[^\/]+\/plugins\/([^\/]+))\/ui_tests\//, /(src\/platform\/plugins\/(?:private|shared)?\/?([^\/]+))\/ui_tests\//, ``` For each plugin we also have `usesParallelWorkers` prop (`true` if at least 1 config runs with concurrent workers) to decide later, if we need worker with 4 or 8 VCPUs. The idea is to run `node scripts/scout discover-playwright-configs --save` on CI and use generated json as source to build test run pipeline. Current output: ``` { "discover_enhanced": { "group": "platform", "pluginPath": "x-pack/platform/plugins/private/discover_enhanced", "configs": [ "x-pack/platform/plugins/private/discover_enhanced/ui_tests/parallel.playwright.config.ts", "x-pack/platform/plugins/private/discover_enhanced/ui_tests/playwright.config.ts" ], "usesParallelWorkers": true }, "maps": { "group": "platform", "pluginPath": "x-pack/platform/plugins/shared/maps", "configs": [ "x-pack/platform/plugins/shared/maps/ui_tests/playwright.config.ts" ], "usesParallelWorkers": false }, "observability_onboarding": { "group": "observability", "pluginPath": "x-pack/solutions/observability/plugins/observability_onboarding", "configs": [ "x-pack/solutions/observability/plugins/observability_onboarding/ui_tests/parallel.playwright.config.ts", "x-pack/solutions/observability/plugins/observability_onboarding/ui_tests/playwright.config.ts" ], "usesParallelWorkers": true } } ```
This commit is contained in:
parent
75f9c6113d
commit
1e3bb05734
3 changed files with 107 additions and 34 deletions
|
@ -7,7 +7,10 @@
|
|||
* License v3.0 only", or the "Server Side Public License, v 1".
|
||||
*/
|
||||
|
||||
import fs from 'fs';
|
||||
import { Command } from '@kbn/dev-cli-runner';
|
||||
import { SCOUT_OUTPUT_ROOT } from '@kbn/scout-info';
|
||||
import { resolve } from 'path';
|
||||
import { getScoutPlaywrightConfigs, DEFAULT_TEST_PATH_PATTERNS } from '../config';
|
||||
import { measurePerformance } from '../common';
|
||||
|
||||
|
@ -21,29 +24,41 @@ export const discoverPlaywrightConfigs: Command<void> = {
|
|||
|
||||
Common usage:
|
||||
node scripts/scout discover-playwright-configs --searchPaths <search_paths>
|
||||
node scripts/scout discover-playwright-configs --save
|
||||
node scripts/scout discover-playwright-configs
|
||||
`,
|
||||
flags: {
|
||||
string: ['searchPaths'],
|
||||
default: { searchPaths: DEFAULT_TEST_PATH_PATTERNS },
|
||||
boolean: ['save'],
|
||||
default: { searchPaths: DEFAULT_TEST_PATH_PATTERNS, save: false },
|
||||
},
|
||||
run: ({ flagsReader, log }) => {
|
||||
const searchPaths = flagsReader.arrayOfStrings('searchPaths')!;
|
||||
|
||||
const plugins = measurePerformance(log, 'Discovering playwright config files', () => {
|
||||
const pluginsMap = measurePerformance(log, 'Discovering playwright config files', () => {
|
||||
return getScoutPlaywrightConfigs(searchPaths, log);
|
||||
});
|
||||
|
||||
const finalMessage =
|
||||
plugins.size === 0
|
||||
? 'No playwright config files found'
|
||||
: `Found playwright config files in '${plugins.size}' plugins`;
|
||||
pluginsMap.size === 0
|
||||
? 'No Playwright config files found'
|
||||
: `Found Playwright config files in '${pluginsMap.size}' plugins`;
|
||||
|
||||
if (pluginsMap.size > 0 && flagsReader.boolean('save')) {
|
||||
const scoutConfigsFilePath = resolve(SCOUT_OUTPUT_ROOT, 'scout_playwright_configs.json');
|
||||
fs.writeFileSync(
|
||||
scoutConfigsFilePath,
|
||||
JSON.stringify(Object.fromEntries(pluginsMap), null, 2)
|
||||
);
|
||||
log.info(`${finalMessage}. Saved to '${scoutConfigsFilePath}'`);
|
||||
return;
|
||||
}
|
||||
|
||||
log.info(finalMessage);
|
||||
|
||||
plugins.forEach((files, plugin) => {
|
||||
log.info(`[${plugin}] plugin:`);
|
||||
files.forEach((file) => {
|
||||
pluginsMap.forEach((data, plugin) => {
|
||||
log.info(`${data.group} / [${plugin}] plugin:`);
|
||||
data.configs.map((file) => {
|
||||
log.info(`- ${file}`);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -35,21 +35,36 @@ describe('getScoutPlaywrightConfigs', () => {
|
|||
|
||||
it('should correctly extract plugin names and group config files', () => {
|
||||
(fastGlob.sync as jest.Mock).mockReturnValue([
|
||||
'x-pack/platform/plugins/plugin_a/ui_tests/playwright.config.ts',
|
||||
'x-pack/platform/plugins/plugin_a/ui_tests/parallel.playwright.config.ts',
|
||||
'x-pack/platform/plugins/private/plugin_a/ui_tests/playwright.config.ts',
|
||||
'x-pack/platform/plugins/private/plugin_a/ui_tests/parallel.playwright.config.ts',
|
||||
'x-pack/solutions/security/plugins/plugin_b/ui_tests/playwright.config.ts',
|
||||
'src/platform/plugins/shared/plugin_c/ui_tests/playwright.config.ts',
|
||||
]);
|
||||
|
||||
const plugins = getScoutPlaywrightConfigs(['x-pack/'], mockLog);
|
||||
const plugins = getScoutPlaywrightConfigs(['x-pack/', 'src/'], mockLog);
|
||||
|
||||
expect(plugins.size).toBe(2);
|
||||
expect(plugins.get('plugin_a')).toEqual([
|
||||
'x-pack/platform/plugins/plugin_a/ui_tests/playwright.config.ts',
|
||||
'x-pack/platform/plugins/plugin_a/ui_tests/parallel.playwright.config.ts',
|
||||
]);
|
||||
expect(plugins.get('plugin_b')).toEqual([
|
||||
'x-pack/solutions/security/plugins/plugin_b/ui_tests/playwright.config.ts',
|
||||
]);
|
||||
expect(plugins.size).toBe(3);
|
||||
expect(plugins.get('plugin_a')).toEqual({
|
||||
configs: [
|
||||
'x-pack/platform/plugins/private/plugin_a/ui_tests/playwright.config.ts',
|
||||
'x-pack/platform/plugins/private/plugin_a/ui_tests/parallel.playwright.config.ts',
|
||||
],
|
||||
usesParallelWorkers: true,
|
||||
group: 'platform',
|
||||
pluginPath: 'x-pack/platform/plugins/private/plugin_a',
|
||||
});
|
||||
expect(plugins.get('plugin_b')).toEqual({
|
||||
configs: ['x-pack/solutions/security/plugins/plugin_b/ui_tests/playwright.config.ts'],
|
||||
usesParallelWorkers: false,
|
||||
group: 'security',
|
||||
pluginPath: 'x-pack/solutions/security/plugins/plugin_b',
|
||||
});
|
||||
expect(plugins.get('plugin_c')).toEqual({
|
||||
configs: ['src/platform/plugins/shared/plugin_c/ui_tests/playwright.config.ts'],
|
||||
usesParallelWorkers: false,
|
||||
group: 'platform',
|
||||
pluginPath: 'src/platform/plugins/shared/plugin_c',
|
||||
});
|
||||
});
|
||||
|
||||
it('should log a warning if a file path does not match the expected pattern', () => {
|
||||
|
|
|
@ -13,35 +13,78 @@ import { ToolingLog } from '@kbn/tooling-log';
|
|||
|
||||
export const DEFAULT_TEST_PATH_PATTERNS = ['src/platform/plugins', 'x-pack/**/plugins'];
|
||||
|
||||
interface PluginScoutConfig {
|
||||
group: string;
|
||||
pluginPath: string;
|
||||
usesParallelWorkers: boolean;
|
||||
configs: string[];
|
||||
}
|
||||
|
||||
export const getScoutPlaywrightConfigs = (searchPaths: string[], log: ToolingLog) => {
|
||||
const patterns = searchPaths.map((basePath) =>
|
||||
path.join(basePath, '**/ui_tests/{playwright.config.ts,parallel.playwright.config.ts}')
|
||||
);
|
||||
|
||||
log.info('Searching for playwright config files in the following paths:');
|
||||
log.info('Searching for Playwright config files in the following paths:');
|
||||
patterns.forEach((pattern) => log.info(`- ${pattern}`));
|
||||
log.info(''); // Add a newline for better readability
|
||||
|
||||
const files = patterns.flatMap((pattern) => fastGlob.sync(pattern, { onlyFiles: true }));
|
||||
|
||||
// Group config files by plugin
|
||||
const plugins = files.reduce((acc: Map<string, string[]>, filePath: string) => {
|
||||
const match = filePath.match(
|
||||
/(?:src\/platform\/plugins|x-pack\/.*?\/plugins)\/(?:.*?\/)?([^\/]+)\/ui_tests\//
|
||||
);
|
||||
const pluginName = match ? match[1] : null;
|
||||
const typeMappings: Record<string, string> = {
|
||||
'x-pack/solutions/security': 'security',
|
||||
'x-pack/solutions/search': 'search',
|
||||
'x-pack/solutions/observability': 'observability',
|
||||
'x-pack/platform/plugins': 'platform',
|
||||
'src/platform/plugins': 'platform',
|
||||
};
|
||||
|
||||
if (pluginName) {
|
||||
if (!acc.has(pluginName)) {
|
||||
acc.set(pluginName, []);
|
||||
const matchPluginPath = (filePath: string): { pluginPath: string; pluginName: string } | null => {
|
||||
const regexes = [
|
||||
/(x-pack\/platform\/plugins\/(?:private|shared|[^\/]+)\/([^\/]+))\/ui_tests\//,
|
||||
/(x-pack\/solutions\/[^\/]+\/plugins\/([^\/]+))\/ui_tests\//,
|
||||
/(src\/platform\/plugins\/(?:private|shared)?\/?([^\/]+))\/ui_tests\//,
|
||||
];
|
||||
|
||||
for (const regex of regexes) {
|
||||
const match = filePath.match(regex);
|
||||
if (match) {
|
||||
return { pluginPath: match[1], pluginName: match[2] };
|
||||
}
|
||||
acc.get(pluginName)!.push(filePath);
|
||||
} else {
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const pluginsWithConfigs = new Map<string, PluginScoutConfig>();
|
||||
|
||||
files.forEach((filePath) => {
|
||||
const matchResult = matchPluginPath(filePath);
|
||||
if (!matchResult) {
|
||||
log.warning(`Unable to extract plugin name from path: ${filePath}`);
|
||||
return;
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, new Map<string, string[]>());
|
||||
const { pluginPath, pluginName } = matchResult;
|
||||
const group =
|
||||
Object.entries(typeMappings).find(([key]) => filePath.includes(key))?.[1] || 'unknown';
|
||||
|
||||
return plugins;
|
||||
if (!pluginsWithConfigs.has(pluginName)) {
|
||||
pluginsWithConfigs.set(pluginName, {
|
||||
group,
|
||||
pluginPath,
|
||||
configs: [],
|
||||
usesParallelWorkers: false,
|
||||
});
|
||||
}
|
||||
|
||||
const pluginData = pluginsWithConfigs.get(pluginName)!;
|
||||
if (!pluginData.configs.includes(filePath)) {
|
||||
pluginData.configs.push(filePath);
|
||||
if (filePath.endsWith('parallel.playwright.config.ts')) {
|
||||
pluginData.usesParallelWorkers = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return pluginsWithConfigs;
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue