Skip to content

Commit 31ffd5e

Browse files
committed
fix(core): audit metadata looked up in plugin config, not expected in output
1 parent 3e88ffc commit 31ffd5e

File tree

6 files changed

+72
-58
lines changed

6 files changed

+72
-58
lines changed
+3-10
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,18 @@
1-
import { name, version } from '../../package.json';
2-
3-
import { pluginOutputSchema, Report } from '@code-pushup/models';
1+
import { pluginReportSchema } from '@code-pushup/models';
42
import { collect, CollectOptions } from './commands/collect';
53
import { logPersistedResults, persistReport } from './implementation/persist';
64

75
export async function collectAndPersistReports(
86
config: CollectOptions,
97
): Promise<void> {
10-
const collectReport = await collect(config);
11-
const report: Report = {
12-
...collectReport,
13-
packageName: name,
14-
version: version,
15-
};
8+
const report = await collect(config);
169

1710
const persistResults = await persistReport(report, config);
1811
logPersistedResults(persistResults);
1912

2013
// validate report and throw if invalid
2114
report.plugins.forEach(plugin => {
2215
// Running checks after persisting helps while debugging as you can check the invalid output after the error is thrown
23-
pluginOutputSchema.parse(plugin);
16+
pluginReportSchema.parse(plugin);
2417
});
2518
}

packages/core/src/lib/commands/collect.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Report } from '@code-pushup/models';
2-
import { executePlugins } from '../implementation/execute-plugin';
32
import { calcDuration } from '@code-pushup/utils';
3+
import { executePlugins } from '../implementation/execute-plugin';
44
import { CommandBaseOptions } from '../implementation/model';
55

66
/**

packages/core/src/lib/implementation/execute-plugin.ts

+28-10
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {
22
PluginConfig,
3-
PluginOutput,
3+
PluginReport,
44
auditOutputsSchema,
55
} from '@code-pushup/models';
66
import { ProcessObserver, executeProcess } from '@code-pushup/utils';
@@ -13,7 +13,7 @@ import { join } from 'path';
1313
export class PluginOutputError extends Error {
1414
constructor(pluginSlug: string, error?: Error) {
1515
super(
16-
`Plugin output of plugin with slug ${pluginSlug} is invalid. \n Zod Error: ${error?.message}`,
16+
`Plugin output of plugin with slug ${pluginSlug} is invalid. \n Error: ${error?.message}`,
1717
);
1818
if (error) {
1919
this.name = error.name;
@@ -47,7 +47,7 @@ export class PluginOutputError extends Error {
4747
export async function executePlugin(
4848
pluginConfig: PluginConfig,
4949
observer?: ProcessObserver,
50-
): Promise<PluginOutput> {
50+
): Promise<PluginReport> {
5151
const { slug, title, icon, description, docsUrl, version, packageName } =
5252
pluginConfig;
5353
const { args, command } = pluginConfig.runner;
@@ -64,10 +64,28 @@ export async function executePlugin(
6464
pluginConfig.runner.outputPath,
6565
);
6666
// read process output from file system and parse it
67-
const audits = auditOutputsSchema.parse(
67+
const auditOutputs = auditOutputsSchema.parse(
6868
JSON.parse((await readFile(processOutputPath)).toString()),
6969
);
7070

71+
const audits = auditOutputs.map(auditOutput => {
72+
const auditMetadata = pluginConfig.audits.find(
73+
audit => audit.slug === auditOutput.slug,
74+
);
75+
if (!auditMetadata) {
76+
throw new PluginOutputError(
77+
slug,
78+
new Error(
79+
`Audit metadata not found for slug ${auditOutput.slug} from runner output`,
80+
),
81+
);
82+
}
83+
return {
84+
...auditOutput,
85+
...auditMetadata,
86+
};
87+
});
88+
7189
return {
7290
version,
7391
packageName,
@@ -89,8 +107,8 @@ export async function executePlugin(
89107
/**
90108
* Execute multiple plugins and aggregates their output.
91109
* @public
92-
* @param plugins - array of {@link PluginConfig} objects
93-
* @returns {Promise<AuditOutput[]>} - runner output
110+
* @param plugins array of {@link PluginConfig} objects
111+
* @returns {Promise<PluginReport[]>} plugin report
94112
*
95113
* @example
96114
* // plugin execution
@@ -107,10 +125,10 @@ export async function executePlugin(
107125
*/
108126
export async function executePlugins(
109127
plugins: PluginConfig[],
110-
): Promise<PluginOutput[]> {
128+
): Promise<PluginReport[]> {
111129
return await plugins.reduce(async (acc, pluginCfg) => {
112130
const outputs = await acc;
113-
const pluginOutput = await executePlugin(pluginCfg);
114-
return outputs.concat(pluginOutput);
115-
}, Promise.resolve([] as PluginOutput[]));
131+
const pluginReport = await executePlugin(pluginCfg);
132+
return outputs.concat(pluginReport);
133+
}, Promise.resolve([] as PluginReport[]));
116134
}

packages/models/src/index.ts

+16-12
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,35 @@
11
export { CategoryConfig, categoryConfigSchema } from './lib/category-config';
2-
export { GlobalOptions, globalOptionsSchema } from './lib/global-options';
32
export {
43
CoreConfig,
54
coreConfigSchema,
65
refineCoreConfig,
76
unrefinedCoreConfigSchema,
87
} from './lib/core-config';
8+
export { GlobalOptions, globalOptionsSchema } from './lib/global-options';
99
export {
10+
Format,
1011
PersistConfig,
11-
persistConfigSchema,
1212
formatSchema,
13-
Format,
13+
persistConfigSchema,
1414
} from './lib/persist-config';
15-
export { UploadConfig, uploadConfigSchema } from './lib/upload-config';
1615
export {
17-
AuditGroup,
1816
Audit,
17+
AuditGroup,
1918
AuditOutput,
19+
AuditOutputs,
20+
Issue,
2021
PluginConfig,
21-
PluginOutput,
22-
pluginOutputSchema,
2322
auditGroupSchema,
23+
auditOutputsSchema,
2424
auditSchema,
25-
pluginConfigSchema,
26-
Issue,
27-
AuditOutputs,
2825
issueSchema,
29-
auditOutputsSchema,
26+
pluginConfigSchema,
3027
} from './lib/plugin-config';
31-
export { PluginReport, AuditReport, Report, reportSchema } from './lib/report';
28+
export {
29+
AuditReport,
30+
PluginReport,
31+
Report,
32+
pluginReportSchema,
33+
reportSchema,
34+
} from './lib/report';
35+
export { UploadConfig, uploadConfigSchema } from './lib/upload-config';

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

+24-24
Original file line numberDiff line numberDiff line change
@@ -193,31 +193,31 @@ export const issueSchema = z.object(
193193
);
194194
export type Issue = z.infer<typeof issueSchema>;
195195

196-
export const auditOutputSchema = auditSchema.merge(
197-
z.object(
198-
{
199-
displayValue: z
200-
.string({ description: "Formatted value (e.g. '0.9 s', '2.1 MB')" })
201-
.optional(),
202-
value: positiveIntSchema('Raw numeric value'),
203-
score: z
204-
.number({
205-
description: 'Value between 0 and 1',
206-
})
207-
.min(0)
208-
.max(1),
209-
details: z
210-
.object(
211-
{
212-
issues: z.array(issueSchema, { description: 'List of findings' }),
213-
},
214-
{ description: 'Detailed information' },
215-
)
216-
.optional(),
217-
},
218-
{ description: 'Audit information' },
219-
),
196+
export const auditOutputSchema = z.object(
197+
{
198+
slug: slugSchema('Reference to audit'),
199+
displayValue: z
200+
.string({ description: "Formatted value (e.g. '0.9 s', '2.1 MB')" })
201+
.optional(),
202+
value: positiveIntSchema('Raw numeric value'),
203+
score: z
204+
.number({
205+
description: 'Value between 0 and 1',
206+
})
207+
.min(0)
208+
.max(1),
209+
details: z
210+
.object(
211+
{
212+
issues: z.array(issueSchema, { description: 'List of findings' }),
213+
},
214+
{ description: 'Detailed information' },
215+
)
216+
.optional(),
217+
},
218+
{ description: 'Audit information' },
220219
);
220+
221221
export type AuditOutput = z.infer<typeof auditOutputSchema>;
222222

223223
export const auditOutputsSchema = z

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

-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ export function lighthousePlugin(_: LighthousePluginConfig): PluginConfig {
2323
`require('fs').writeFileSync('tmp/out.json', '${JSON.stringify([
2424
{
2525
slug: 'largest-contentful-paint',
26-
title: 'Largest Contentful Paint',
2726
value: 0,
2827
score: 0,
2928
},

0 commit comments

Comments
 (0)