diff --git a/packages/core/src/lib/implementation/execute-plugin.ts b/packages/core/src/lib/implementation/execute-plugin.ts index c84efd6ad..d61b8f17d 100644 --- a/packages/core/src/lib/implementation/execute-plugin.ts +++ b/packages/core/src/lib/implementation/execute-plugin.ts @@ -68,8 +68,8 @@ export async function executePlugin( ? // IF not null, take the result from cache ((await readRunnerResults(pluginMeta.slug, outputDir)) ?? // ELSE execute the plugin runner - (await executePluginRunner(pluginConfig))) - : await executePluginRunner(pluginConfig); + (await executePluginRunner(pluginConfig, persist))) + : await executePluginRunner(pluginConfig, persist); if (cacheWrite) { await writeRunnerResults(pluginMeta.slug, outputDir, { diff --git a/packages/core/src/lib/implementation/execute-plugin.unit.test.ts b/packages/core/src/lib/implementation/execute-plugin.unit.test.ts index e3c1ab929..191e2f995 100644 --- a/packages/core/src/lib/implementation/execute-plugin.unit.test.ts +++ b/packages/core/src/lib/implementation/execute-plugin.unit.test.ts @@ -18,7 +18,12 @@ describe('executePlugin', () => { vi.restoreAllMocks(); }); - it('should execute a valid plugin config', async () => { + it('should execute a valid plugin config and pass runner params', async () => { + const executePluginRunnerSpy = vi.spyOn( + runnerModule, + 'executePluginRunner', + ); + await expect( executePlugin(MINIMAL_PLUGIN_CONFIG_MOCK, { persist: { outputDir: '' }, @@ -39,6 +44,11 @@ describe('executePlugin', () => { }), ]), }); + + expect(executePluginRunnerSpy).toHaveBeenCalledWith( + MINIMAL_PLUGIN_CONFIG_MOCK, + { outputDir: '' }, + ); }); it('should try to read cache if cache.read is true', async () => { @@ -102,7 +112,7 @@ describe('executePlugin', () => { await expect( executePlugin(MINIMAL_PLUGIN_CONFIG_MOCK, { - persist: { outputDir: 'dummy-path-result-is-mocked' }, + persist: { outputDir: MEMFS_VOLUME }, cache: { read: true, write: false }, }), ).resolves.toStrictEqual({ @@ -122,6 +132,7 @@ describe('executePlugin', () => { expect(executePluginRunnerSpy).toHaveBeenCalledWith( MINIMAL_PLUGIN_CONFIG_MOCK, + { outputDir: MEMFS_VOLUME }, ); }); @@ -383,8 +394,8 @@ describe('executePlugins', () => { { ...MINIMAL_PLUGIN_CONFIG_MOCK, runner: { - command: 'node', - args: ['-v'], + command: 'echo', + args: ['16'], outputFile: 'output.json', outputTransform: (outputs: unknown): Promise => Promise.resolve([ @@ -398,7 +409,7 @@ describe('executePlugins', () => { }, }, ], - persist: { outputDir: '.code-pushup' }, + persist: { outputDir: MEMFS_VOLUME }, cache: { read: false, write: false }, }, { progress: false }, diff --git a/packages/core/src/lib/implementation/runner.ts b/packages/core/src/lib/implementation/runner.ts index afdf17546..0bec5a3b4 100644 --- a/packages/core/src/lib/implementation/runner.ts +++ b/packages/core/src/lib/implementation/runner.ts @@ -3,6 +3,7 @@ import { writeFile } from 'node:fs/promises'; import path from 'node:path'; import { type AuditOutputs, + type PersistConfig, type PluginConfig, type RunnerConfig, type RunnerFunction, @@ -14,6 +15,7 @@ import { executeProcess, fileExists, isVerbose, + objectToCliArgs, readJsonFile, removeDirectoryIfExists, ui, @@ -32,12 +34,13 @@ export type ValidatedRunnerResult = Omit & { export async function executeRunnerConfig( cfg: RunnerConfig, + config: Required>, ): Promise { const { args, command, outputFile, outputTransform } = cfg; const { duration, date } = await executeProcess({ command, - args, + args: [...(args ?? []), ...objectToCliArgs(config)], observer: { onStdout: stdout => { if (isVerbose()) { @@ -66,12 +69,13 @@ export async function executeRunnerConfig( export async function executeRunnerFunction( runner: RunnerFunction, + config: PersistConfig, ): Promise { const date = new Date().toISOString(); const start = performance.now(); // execute plugin runner - const audits = await runner(); + const audits = await runner(config); // create runner result return { @@ -96,12 +100,13 @@ export class AuditOutputsMissingAuditError extends Error { export async function executePluginRunner( pluginConfig: Pick, + persist: Required>, ): Promise & { audits: AuditOutputs }> { const { audits: pluginConfigAudits, runner } = pluginConfig; const runnerResult: RunnerResult = typeof runner === 'object' - ? await executeRunnerConfig(runner) - : await executeRunnerFunction(runner); + ? await executeRunnerConfig(runner, persist) + : await executeRunnerFunction(runner, persist); const { audits: unvalidatedAuditOutputs, ...executionMeta } = runnerResult; const result = auditOutputsSchema.safeParse(unvalidatedAuditOutputs); diff --git a/packages/models/docs/models-reference.md b/packages/models/docs/models-reference.md index f11d358f8..246c75edc 100644 --- a/packages/models/docs/models-reference.md +++ b/packages/models/docs/models-reference.md @@ -1421,7 +1421,7 @@ _Function._ _Parameters:_ -- _none_ +1. [PersistConfig](#persistconfig) _Returns:_ diff --git a/packages/models/src/lib/runner-config.ts b/packages/models/src/lib/runner-config.ts index a40a0b983..422b39639 100644 --- a/packages/models/src/lib/runner-config.ts +++ b/packages/models/src/lib/runner-config.ts @@ -2,6 +2,7 @@ import { z } from 'zod/v4'; import { auditOutputsSchema } from './audit-output.js'; import { convertAsyncZodFunctionToSchema } from './implementation/function.js'; import { filePathSchema } from './implementation/schemas.js'; +import { persistConfigSchema } from './persist-config.js'; export const outputTransformSchema = convertAsyncZodFunctionToSchema( z.function({ @@ -25,6 +26,7 @@ export type RunnerConfig = z.infer; export const runnerFunctionSchema = convertAsyncZodFunctionToSchema( z.function({ + input: [persistConfigSchema], output: z.union([auditOutputsSchema, z.promise(auditOutputsSchema)]), }), ); diff --git a/packages/plugin-eslint/src/index.ts b/packages/plugin-eslint/src/index.ts index 8e33e0c18..c10a009ea 100644 --- a/packages/plugin-eslint/src/index.ts +++ b/packages/plugin-eslint/src/index.ts @@ -3,6 +3,7 @@ import { eslintPlugin } from './lib/eslint-plugin.js'; export default eslintPlugin; export type { ESLintPluginConfig } from './lib/config.js'; +export { ESLINT_PLUGIN_SLUG } from './lib/constants.js'; export { eslintConfigFromAllNxProjects, diff --git a/packages/plugin-eslint/src/lib/constants.ts b/packages/plugin-eslint/src/lib/constants.ts new file mode 100644 index 000000000..8f4ec0403 --- /dev/null +++ b/packages/plugin-eslint/src/lib/constants.ts @@ -0,0 +1 @@ +export const ESLINT_PLUGIN_SLUG = 'eslint'; diff --git a/packages/plugin-eslint/src/lib/eslint-plugin.ts b/packages/plugin-eslint/src/lib/eslint-plugin.ts index 285a39e50..2b8b36246 100644 --- a/packages/plugin-eslint/src/lib/eslint-plugin.ts +++ b/packages/plugin-eslint/src/lib/eslint-plugin.ts @@ -9,6 +9,7 @@ import { eslintPluginConfigSchema, eslintPluginOptionsSchema, } from './config.js'; +import { ESLINT_PLUGIN_SLUG } from './constants.js'; import { listAuditsAndGroups } from './meta/index.js'; import { createRunnerConfig } from './runner/index.js'; @@ -60,7 +61,7 @@ export async function eslintPlugin( ) as typeof import('../../package.json'); return { - slug: 'eslint', + slug: ESLINT_PLUGIN_SLUG, title: 'ESLint', icon: 'eslint', description: 'Official Code PushUp ESLint plugin',