Skip to content

Commit 1209ed2

Browse files
ASAS
authored andcommitted
feat: add artifaction options to plugin-eslint
1 parent ed01057 commit 1209ed2

File tree

5 files changed

+87
-12
lines changed

5 files changed

+87
-12
lines changed

packages/models/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,3 +138,4 @@ export {
138138
artifactGenerationCommandSchema,
139139
pluginArtifactOptionsSchema,
140140
} from './lib/configuration.js';
141+
export type { PluginArtifactOptions } from './lib/configuration.js';

packages/plugin-eslint/src/lib/config.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { z } from 'zod';
2+
import { pluginArtifactOptionsSchema } from '@code-pushup/models';
23
import { toArray } from '@code-pushup/utils';
34

45
const patternsSchema = z.union([z.string(), z.array(z.string()).min(1)], {
@@ -64,5 +65,6 @@ export type CustomGroup = z.infer<typeof customGroupSchema>;
6465

6566
export const eslintPluginOptionsSchema = z.object({
6667
groups: z.array(customGroupSchema).optional(),
68+
artifacts: pluginArtifactOptionsSchema.optional(),
6769
});
6870
export type ESLintPluginOptions = z.infer<typeof eslintPluginOptionsSchema>;

packages/plugin-eslint/src/lib/eslint-plugin.int.test.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,4 +160,30 @@ describe('eslintPlugin', () => {
160160
eslintPlugin({ eslintrc: '.eslintrc.yml', patterns: '**/*.js' }),
161161
).rejects.toThrow(/Failed to load url .*\.eslintrc.yml/);
162162
});
163+
164+
it('should initialize with artifact options', async () => {
165+
cwdSpy.mockReturnValue(path.join(fixturesDir, 'todos-app'));
166+
const plugin = await eslintPlugin(
167+
{
168+
eslintrc: 'eslint.config.js',
169+
patterns: ['src/**/*.js'],
170+
},
171+
{
172+
artifacts: {
173+
artifactsPaths: './artifacts/eslint-output.json',
174+
generateArtifactsCommand: 'echo "Generating artifacts"',
175+
},
176+
},
177+
);
178+
179+
expect(typeof plugin.runner).toBe('object');
180+
const runnerConfig = plugin.runner as {
181+
command: string;
182+
args?: string[];
183+
outputFile: string;
184+
};
185+
expect(runnerConfig.command).toBe('node');
186+
expect(runnerConfig.args).toContain('echo "Generating artifacts"');
187+
expect(runnerConfig.outputFile).toBe('./artifacts/eslint-output.json');
188+
});
163189
});

packages/plugin-eslint/src/lib/eslint-plugin.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,14 @@ export async function eslintPlugin(
4141
schemaType: 'ESLint plugin config',
4242
});
4343

44-
const customGroups = options
44+
const parsedOptions = options
4545
? parseSchema(eslintPluginOptionsSchema, options, {
4646
schemaType: 'ESLint plugin options',
47-
}).groups
47+
})
4848
: undefined;
4949

50+
const customGroups = parsedOptions?.groups;
51+
5052
const { audits, groups } = await listAuditsAndGroups(targets, customGroups);
5153

5254
const runnerScriptPath = path.join(
@@ -71,6 +73,11 @@ export async function eslintPlugin(
7173
audits,
7274
groups,
7375

74-
runner: await createRunnerConfig(runnerScriptPath, audits, targets),
76+
runner: await createRunnerConfig(
77+
runnerScriptPath,
78+
audits,
79+
targets,
80+
parsedOptions?.artifacts,
81+
),
7582
};
7683
}

packages/plugin-eslint/src/lib/runner/index.ts

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@ import path from 'node:path';
33
import type {
44
Audit,
55
AuditOutput,
6+
PluginArtifactOptions,
67
RunnerConfig,
78
RunnerFilesPaths,
89
} from '@code-pushup/models';
10+
import { pluginArtifactOptionsSchema } from '@code-pushup/models';
911
import {
1012
asyncSequential,
1113
createRunnerFiles,
@@ -51,23 +53,60 @@ export async function createRunnerConfig(
5153
scriptPath: string,
5254
audits: Audit[],
5355
targets: ESLintTarget[],
56+
artifactOptions?: PluginArtifactOptions,
5457
): Promise<RunnerConfig> {
58+
const parsedOptions = artifactOptions
59+
? pluginArtifactOptionsSchema.parse(artifactOptions)
60+
: undefined;
61+
5562
const config: ESLintPluginRunnerConfig = {
5663
targets,
57-
slugs: audits.map(audit => audit.slug),
64+
slugs: audits.map(a => a.slug),
5865
};
59-
const { runnerConfigPath, runnerOutputPath } = await createRunnerFiles(
60-
'eslint',
61-
JSON.stringify(config),
62-
);
66+
67+
const { runnerConfigPath, runnerOutputPath } = parsedOptions
68+
? await createCustomRunnerPaths(parsedOptions, config)
69+
: await createRunnerFiles('eslint', JSON.stringify(config));
70+
71+
const args = [
72+
filePathToCliArg(scriptPath),
73+
...objectToCliArgs({ runnerConfigPath, runnerOutputPath }),
74+
...resolveCommandArgs(parsedOptions?.generateArtifactsCommand),
75+
];
6376

6477
return {
6578
command: 'node',
66-
args: [
67-
filePathToCliArg(scriptPath),
68-
...objectToCliArgs({ runnerConfigPath, runnerOutputPath }),
69-
],
79+
args,
7080
configFile: runnerConfigPath,
7181
outputFile: runnerOutputPath,
7282
};
7383
}
84+
85+
async function createCustomRunnerPaths(
86+
options: PluginArtifactOptions,
87+
config: ESLintPluginRunnerConfig,
88+
): Promise<RunnerFilesPaths> {
89+
const artifactPaths = Array.isArray(options.artifactsPaths)
90+
? options.artifactsPaths
91+
: [options.artifactsPaths];
92+
93+
const runnerOutputPath = artifactPaths[0] ?? '';
94+
const runnerConfigPath = path.join(
95+
path.dirname(runnerOutputPath),
96+
'plugin-config.json',
97+
);
98+
99+
await ensureDirectoryExists(path.dirname(runnerConfigPath));
100+
await writeFile(runnerConfigPath, JSON.stringify(config));
101+
102+
return { runnerConfigPath, runnerOutputPath };
103+
}
104+
105+
function resolveCommandArgs(
106+
command?: string | { command: string; args?: string[] },
107+
): string[] {
108+
if (!command) return [];
109+
return typeof command === 'string'
110+
? [command]
111+
: [command.command, ...(command.args ?? [])];
112+
}

0 commit comments

Comments
 (0)