diff --git a/packages/plugin-coverage/package.json b/packages/plugin-coverage/package.json index 65be3a008..86c6bfef2 100644 --- a/packages/plugin-coverage/package.json +++ b/packages/plugin-coverage/package.json @@ -37,7 +37,6 @@ "@code-pushup/models": "0.96.1", "@code-pushup/utils": "0.96.1", "parse-lcov": "^1.0.4", - "yargs": "^17.7.2", "zod": "^4.0.5" }, "peerDependencies": { diff --git a/packages/plugin-coverage/src/bin.ts b/packages/plugin-coverage/src/bin.ts deleted file mode 100644 index fc625dd73..000000000 --- a/packages/plugin-coverage/src/bin.ts +++ /dev/null @@ -1,7 +0,0 @@ -import process from 'node:process'; -import { Parser } from 'yargs/helpers'; -import { executeRunner } from './lib/runner/index.js'; - -const { runnerConfigPath, runnerOutputPath } = Parser(process.argv); - -await executeRunner({ runnerConfigPath, runnerOutputPath }); diff --git a/packages/plugin-coverage/src/lib/coverage-plugin.ts b/packages/plugin-coverage/src/lib/coverage-plugin.ts index 93a94b4c6..f8f727749 100644 --- a/packages/plugin-coverage/src/lib/coverage-plugin.ts +++ b/packages/plugin-coverage/src/lib/coverage-plugin.ts @@ -1,6 +1,4 @@ import { createRequire } from 'node:module'; -import path from 'node:path'; -import { fileURLToPath } from 'node:url'; import { type Audit, type Group, @@ -13,7 +11,7 @@ import { type CoverageType, coveragePluginConfigSchema, } from './config.js'; -import { createRunnerConfig } from './runner/index.js'; +import { createRunnerFunction } from './runner/index.js'; import { coverageDescription, coverageTypeWeightMapper } from './utils.js'; /** @@ -60,12 +58,6 @@ export async function coveragePlugin( })), }; - const runnerScriptPath = path.join( - fileURLToPath(path.dirname(import.meta.url)), - '..', - 'bin.js', - ); - const packageJson = createRequire(import.meta.url)( '../../package.json', ) as typeof import('../../package.json'); @@ -82,7 +74,7 @@ export async function coveragePlugin( version: packageJson.version, audits, groups: [group], - runner: await createRunnerConfig(runnerScriptPath, coverageConfig), + runner: createRunnerFunction(coverageConfig), ...(scoreTargets && { scoreTargets }), }; } diff --git a/packages/plugin-coverage/src/lib/coverage-plugin.unit.test.ts b/packages/plugin-coverage/src/lib/coverage-plugin.unit.test.ts index 6967a58f1..9cbe5c973 100644 --- a/packages/plugin-coverage/src/lib/coverage-plugin.unit.test.ts +++ b/packages/plugin-coverage/src/lib/coverage-plugin.unit.test.ts @@ -1,15 +1,8 @@ import path from 'node:path'; import { describe, expect, it } from 'vitest'; -import { type RunnerConfig, pluginConfigSchema } from '@code-pushup/models'; +import { pluginConfigSchema } from '@code-pushup/models'; import { coveragePlugin } from './coverage-plugin.js'; -vi.mock('./runner/index.ts', () => ({ - createRunnerConfig: vi.fn().mockReturnValue({ - command: 'node', - outputFile: 'runner-output.json', - } satisfies RunnerConfig), -})); - describe('coveragePlugin', () => { const LCOV_PATH = path.join( 'packages', @@ -30,7 +23,7 @@ describe('coveragePlugin', () => { title: 'Code coverage', audits: expect.any(Array), groups: expect.any(Array), - runner: expect.any(Object), + runner: expect.any(Function), }), ); }); diff --git a/packages/plugin-coverage/src/lib/runner/index.ts b/packages/plugin-coverage/src/lib/runner/index.ts index 34801d8cb..09d988a78 100644 --- a/packages/plugin-coverage/src/lib/runner/index.ts +++ b/packages/plugin-coverage/src/lib/runner/index.ts @@ -1,62 +1,34 @@ -import { writeFile } from 'node:fs/promises'; -import path from 'node:path'; -import type { RunnerConfig, RunnerFilesPaths } from '@code-pushup/models'; -import { - createRunnerFiles, - ensureDirectoryExists, - executeProcess, - filePathToCliArg, - objectToCliArgs, - readJsonFile, -} from '@code-pushup/utils'; +import type { RunnerFunction } from '@code-pushup/models'; +import { executeProcess } from '@code-pushup/utils'; import type { FinalCoveragePluginConfig } from '../config.js'; import { lcovResultsToAuditOutputs } from './lcov/lcov-runner.js'; -export async function executeRunner({ - runnerConfigPath, - runnerOutputPath, -}: RunnerFilesPaths): Promise { - const { reports, coverageToolCommand, continueOnCommandFail, coverageTypes } = - await readJsonFile(runnerConfigPath); +export function createRunnerFunction( + config: FinalCoveragePluginConfig, +): RunnerFunction { + return async () => { + const { + reports, + coverageToolCommand, + continueOnCommandFail, + coverageTypes, + } = config; - // Run coverage tool if provided - if (coverageToolCommand != null) { - const { command, args } = coverageToolCommand; - try { - await executeProcess({ command, args }); - } catch { - if (!continueOnCommandFail) { - throw new Error( - 'Coverage plugin: Running coverage tool failed. Make sure all your provided tests are passing.', - ); + // Run coverage tool if provided + if (coverageToolCommand != null) { + const { command, args } = coverageToolCommand; + try { + await executeProcess({ command, args }); + } catch { + if (!continueOnCommandFail) { + throw new Error( + 'Coverage plugin: Running coverage tool failed. Make sure all your provided tests are passing.', + ); + } } } - } - - // Calculate coverage from LCOV results - const auditOutputs = await lcovResultsToAuditOutputs(reports, coverageTypes); - - await ensureDirectoryExists(path.dirname(runnerOutputPath)); - await writeFile(runnerOutputPath, JSON.stringify(auditOutputs)); -} - -export async function createRunnerConfig( - scriptPath: string, - config: FinalCoveragePluginConfig, -): Promise { - // Create JSON config for executeRunner - const { runnerConfigPath, runnerOutputPath } = await createRunnerFiles( - 'coverage', - JSON.stringify(config), - ); - return { - command: 'node', - args: [ - filePathToCliArg(scriptPath), - ...objectToCliArgs({ runnerConfigPath, runnerOutputPath }), - ], - configFile: runnerConfigPath, - outputFile: runnerOutputPath, + // Calculate coverage from LCOV results + return lcovResultsToAuditOutputs(reports, coverageTypes); }; } diff --git a/packages/plugin-coverage/src/lib/runner/runner.int.test.ts b/packages/plugin-coverage/src/lib/runner/runner.int.test.ts index 91c2579b7..4d135a992 100644 --- a/packages/plugin-coverage/src/lib/runner/runner.int.test.ts +++ b/packages/plugin-coverage/src/lib/runner/runner.int.test.ts @@ -1,54 +1,12 @@ import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { expect } from 'vitest'; -import type { AuditOutputs, RunnerConfig } from '@code-pushup/models'; -import { createRunnerFiles, readJsonFile } from '@code-pushup/utils'; -import type { FinalCoveragePluginConfig } from '../config.js'; -import { createRunnerConfig, executeRunner } from './index.js'; +import { type AuditOutputs, DEFAULT_PERSIST_CONFIG } from '@code-pushup/models'; +import { createRunnerFunction } from './index.js'; -describe('createRunnerConfig', () => { - it('should create a valid runner config', async () => { - const runnerConfig = await createRunnerConfig('executeRunner.ts', { - reports: ['coverage/lcov.info'], - coverageTypes: ['branch'], - scoreTargets: 0.85, - continueOnCommandFail: true, - }); - expect(runnerConfig).toStrictEqual({ - command: 'node', - args: [ - '"executeRunner.ts"', - expect.stringContaining('plugin-config.json'), - expect.stringContaining('runner-output.json'), - ], - outputFile: expect.stringContaining('runner-output.json'), - configFile: expect.stringContaining('plugin-config.json'), - }); - }); - - it('should provide plugin config to runner in JSON file', async () => { - const pluginConfig: FinalCoveragePluginConfig = { - coverageTypes: ['line'], - reports: ['coverage/lcov.info'], - coverageToolCommand: { command: 'npm', args: ['run', 'test'] }, - scoreTargets: 0.85, - continueOnCommandFail: true, - }; - - const { configFile } = await createRunnerConfig( - 'executeRunner.ts', - pluginConfig, - ); - - expect(configFile).toMatch(/.*plugin-config\.json$/); - const config = await readJsonFile(configFile!); - expect(config).toStrictEqual(pluginConfig); - }); -}); - -describe('executeRunner', () => { +describe('createRunnerFunction', () => { it('should successfully execute runner', async () => { - const config: FinalCoveragePluginConfig = { + const runner = createRunnerFunction({ reports: [ path.join( fileURLToPath(path.dirname(import.meta.url)), @@ -61,18 +19,11 @@ describe('executeRunner', () => { ], coverageTypes: ['line'], continueOnCommandFail: true, - }; - - const runnerFiles = await createRunnerFiles( - 'coverage', - JSON.stringify(config), - ); - await executeRunner(runnerFiles); + }); - const results = await readJsonFile( - runnerFiles.runnerOutputPath, - ); - expect(results).toStrictEqual([ + await expect( + runner({ persist: DEFAULT_PERSIST_CONFIG }), + ).resolves.toStrictEqual([ { slug: 'line-coverage', score: 0.7, @@ -112,6 +63,6 @@ describe('executeRunner', () => { ], }, }, - ]); + ] satisfies AuditOutputs); }); }); diff --git a/packages/plugin-js-packages/package.json b/packages/plugin-js-packages/package.json index f1df17065..bd7354a69 100644 --- a/packages/plugin-js-packages/package.json +++ b/packages/plugin-js-packages/package.json @@ -41,7 +41,6 @@ "@code-pushup/utils": "0.96.1", "build-md": "^0.4.1", "semver": "^7.6.0", - "yargs": "^17.7.2", "zod": "^4.0.5" }, "files": [ diff --git a/packages/plugin-js-packages/project.json b/packages/plugin-js-packages/project.json index 5ef4c7cf1..208cc4668 100644 --- a/packages/plugin-js-packages/project.json +++ b/packages/plugin-js-packages/project.json @@ -7,7 +7,6 @@ "build": {}, "lint": {}, "unit-test": {}, - "int-test": {}, "code-pushup": {}, "code-pushup-eslint": {}, "code-pushup-coverage": {}, diff --git a/packages/plugin-js-packages/src/bin.ts b/packages/plugin-js-packages/src/bin.ts deleted file mode 100644 index fc625dd73..000000000 --- a/packages/plugin-js-packages/src/bin.ts +++ /dev/null @@ -1,7 +0,0 @@ -import process from 'node:process'; -import { Parser } from 'yargs/helpers'; -import { executeRunner } from './lib/runner/index.js'; - -const { runnerConfigPath, runnerOutputPath } = Parser(process.argv); - -await executeRunner({ runnerConfigPath, runnerOutputPath }); diff --git a/packages/plugin-js-packages/src/lib/js-packages-plugin.ts b/packages/plugin-js-packages/src/lib/js-packages-plugin.ts index 8fe2491cd..d2754e30b 100644 --- a/packages/plugin-js-packages/src/lib/js-packages-plugin.ts +++ b/packages/plugin-js-packages/src/lib/js-packages-plugin.ts @@ -1,6 +1,4 @@ import { createRequire } from 'node:module'; -import path from 'node:path'; -import { fileURLToPath } from 'node:url'; import type { Audit, Group, PluginConfig } from '@code-pushup/models'; import { type DependencyGroup, @@ -11,7 +9,7 @@ import { } from './config.js'; import { dependencyDocs, dependencyGroupWeights } from './constants.js'; import { packageManagers } from './package-managers/package-managers.js'; -import { createRunnerConfig } from './runner/index.js'; +import { createRunnerFunction } from './runner/index.js'; import { normalizeConfig } from './utils.js'; /** @@ -42,12 +40,6 @@ export async function jsPackagesPlugin( ...jsPackagesPluginConfigRest } = await normalizeConfig(config); - const runnerScriptPath = path.join( - fileURLToPath(path.dirname(import.meta.url)), - '..', - 'bin.js', - ); - const packageJson = createRequire(import.meta.url)( '../../package.json', ) as typeof import('../../package.json'); @@ -63,7 +55,7 @@ export async function jsPackagesPlugin( version: packageJson.version, audits: createAudits(packageManager.slug, checks, depGroups), groups: createGroups(packageManager.slug, checks, depGroups), - runner: await createRunnerConfig(runnerScriptPath, { + runner: createRunnerFunction({ ...jsPackagesPluginConfigRest, checks, packageManager: packageManager.slug, diff --git a/packages/plugin-js-packages/src/lib/js-packages-plugin.unit.test.ts b/packages/plugin-js-packages/src/lib/js-packages-plugin.unit.test.ts index 2b8b90dcb..66a4551ec 100644 --- a/packages/plugin-js-packages/src/lib/js-packages-plugin.unit.test.ts +++ b/packages/plugin-js-packages/src/lib/js-packages-plugin.unit.test.ts @@ -3,19 +3,11 @@ import { describe, expect, it } from 'vitest'; import { type Group, type PluginConfig, - type RunnerConfig, pluginConfigSchema, } from '@code-pushup/models'; import { MEMFS_VOLUME } from '@code-pushup/test-utils'; import { jsPackagesPlugin } from './js-packages-plugin.js'; -vi.mock('./runner/index.ts', () => ({ - createRunnerConfig: vi.fn().mockReturnValue({ - command: 'node', - outputFile: 'runner-output.json', - } satisfies RunnerConfig), -})); - describe('jsPackagesPlugin', () => { it('should initialise the plugin without a given config for NPM', async () => { vol.fromJSON( @@ -60,7 +52,7 @@ describe('jsPackagesPlugin', () => { title: 'JS Packages', audits: expect.any(Array), groups: expect.any(Array), - runner: expect.any(Object), + runner: expect.any(Function), }), ); }); diff --git a/packages/plugin-js-packages/src/lib/runner/index.ts b/packages/plugin-js-packages/src/lib/runner/index.ts index a4921ff75..04b9338dd 100644 --- a/packages/plugin-js-packages/src/lib/runner/index.ts +++ b/packages/plugin-js-packages/src/lib/runner/index.ts @@ -1,15 +1,9 @@ -import { writeFile } from 'node:fs/promises'; import path from 'node:path'; -import type { RunnerConfig, RunnerFilesPaths } from '@code-pushup/models'; +import type { RunnerFunction } from '@code-pushup/models'; import { asyncSequential, - createRunnerFiles, - ensureDirectoryExists, executeProcess, - filePathToCliArg, objectFromEntries, - objectToCliArgs, - readJsonFile, } from '@code-pushup/utils'; import { type AuditSeverity, @@ -26,54 +20,33 @@ import type { AuditResult } from './audit/types.js'; import { outdatedResultToAuditOutput } from './outdated/transform.js'; import { getTotalDependencies } from './utils.js'; -export async function createRunnerConfig( - scriptPath: string, +export function createRunnerFunction( config: FinalJSPackagesPluginConfig, -): Promise { - const { runnerConfigPath, runnerOutputPath } = await createRunnerFiles( - 'js-packages', - JSON.stringify(config), - ); - - return { - command: 'node', - args: [ - filePathToCliArg(scriptPath), - ...objectToCliArgs({ runnerConfigPath, runnerOutputPath }), - ], - configFile: runnerConfigPath, - outputFile: runnerOutputPath, - }; -} - -export async function executeRunner({ - runnerConfigPath, - runnerOutputPath, -}: RunnerFilesPaths): Promise { - const { - packageManager, - checks, - auditLevelMapping, - packageJsonPath, - dependencyGroups: depGroups, - } = await readJsonFile(runnerConfigPath); +): RunnerFunction { + return async () => { + const { + packageManager, + checks, + auditLevelMapping, + packageJsonPath, + dependencyGroups: depGroups, + } = config; - const auditResults = checks.includes('audit') - ? await processAudit( - packageManager, - depGroups, - auditLevelMapping, - packageJsonPath, - ) - : []; + const auditResults = checks.includes('audit') + ? await processAudit( + packageManager, + depGroups, + auditLevelMapping, + packageJsonPath, + ) + : []; - const outdatedResults = checks.includes('outdated') - ? await processOutdated(packageManager, depGroups, packageJsonPath) - : []; - const checkResults = [...auditResults, ...outdatedResults]; + const outdatedResults = checks.includes('outdated') + ? await processOutdated(packageManager, depGroups, packageJsonPath) + : []; - await ensureDirectoryExists(path.dirname(runnerOutputPath)); - await writeFile(runnerOutputPath, JSON.stringify(checkResults)); + return [...auditResults, ...outdatedResults]; + }; } async function processOutdated( diff --git a/packages/plugin-js-packages/src/lib/runner/runner.int.test.ts b/packages/plugin-js-packages/src/lib/runner/runner.int.test.ts deleted file mode 100644 index c61af31fc..000000000 --- a/packages/plugin-js-packages/src/lib/runner/runner.int.test.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { describe, expect, it } from 'vitest'; -import type { RunnerConfig } from '@code-pushup/models'; -import { readJsonFile } from '@code-pushup/utils'; -import type { FinalJSPackagesPluginConfig } from '../config.js'; -import { defaultAuditLevelMapping } from '../constants.js'; -import { createRunnerConfig } from './index.js'; - -describe('createRunnerConfig', () => { - it('should create a valid runner config', async () => { - const runnerConfig = await createRunnerConfig('executeRunner.ts', { - packageManager: 'npm', - checks: ['audit'], - auditLevelMapping: defaultAuditLevelMapping, - dependencyGroups: ['prod', 'dev'], - packageJsonPath: 'package.json', - }); - expect(runnerConfig).toStrictEqual({ - command: 'node', - args: [ - '"executeRunner.ts"', - expect.stringContaining('plugin-config.json'), - expect.stringContaining('runner-output.json'), - ], - outputFile: expect.stringContaining('runner-output.json'), - configFile: expect.stringContaining('plugin-config.json'), - }); - }); - - it('should provide plugin config to runner in JSON file', async () => { - const pluginConfig: FinalJSPackagesPluginConfig = { - packageManager: 'yarn-classic', - checks: ['outdated'], - dependencyGroups: ['prod', 'dev'], - auditLevelMapping: { ...defaultAuditLevelMapping, moderate: 'error' }, - packageJsonPath: 'package.json', - }; - const { configFile } = await createRunnerConfig( - 'executeRunner.ts', - pluginConfig, - ); - expect(configFile).toMatch(/.*plugin-config\.json$/); - const config = await readJsonFile(configFile!); - expect(config).toStrictEqual(pluginConfig); - }); -});