diff --git a/code-pushup.config.ts b/code-pushup.config.ts index a5f2189e..04870241 100644 --- a/code-pushup.config.ts +++ b/code-pushup.config.ts @@ -1,6 +1,14 @@ import { CoreConfig } from '@code-pushup/models'; -import nxPerformancePlugin from './tooling/measures/nx-performance/nx-performance.plugin'; +import nxPerformancePlugin, { + nxPerformanceCategoryRefs, + type OnlyAudit, +} from './tooling/measures/nx-performance/nx-performance.plugin'; +const onlyAudits: OnlyAudit[] = [ + 'project-graph-performance', + 'task-time', + 'cache-size', +]; const taskTimeTasks = [ 'cli-e2e:e2e', 'core-e2e:e2e', @@ -20,6 +28,20 @@ export default { nxPerformancePlugin({ taskTimeTasks, cacheSizeTasks, + onlyAudits, }), ], + categories: [ + { + slug: 'performance', + title: 'Performance', + refs: [ + ...nxPerformanceCategoryRefs({ + taskTimeTasks, + cacheSizeTasks, + onlyAudits, + }), + ], + }, + ], } satisfies CoreConfig; diff --git a/tooling/measures/nx-performance/audit/cache-size.audit.ts b/tooling/measures/nx-performance/audit/cache-size.audit.ts index 9f69587f..1dde6272 100644 --- a/tooling/measures/nx-performance/audit/cache-size.audit.ts +++ b/tooling/measures/nx-performance/audit/cache-size.audit.ts @@ -11,13 +11,15 @@ import { DEFAULT_PLUGIN_OUTPUT } from '../constant'; export const DEFAULT_MAX_PROJECT_TARGET_CACHE_SIZE = 3000; -export function getAuditSlug(task: string): string { - return `nx-${slugify(task)}-cache-size`; +export const CACHE_SIZE_AUDIT_POSTFIX = 'cache-size'; + +export function getCacheSizeAuditSlug(task: string): string { + return `nx-${slugify(task)}-${CACHE_SIZE_AUDIT_POSTFIX}`; } export const getCacheSizeAudits = (tasks: string[]): Audit[] => { return tasks.map((task) => ({ - slug: getAuditSlug(task), // Unique slug for each task + slug: getCacheSizeAuditSlug(task), // Unique slug for each task title: `Cache size ${task}`, description: 'An audit to check cache size of the Nx task.', })); @@ -53,7 +55,7 @@ export async function cacheSizeAudits( ]; }) .map(([task, duration]) => ({ - slug: getAuditSlug(task), // Unique slug for each task + slug: getCacheSizeAuditSlug(task), // Unique slug for each task score: scoreProjectTaskCacheSize(duration, maxCacheSize), value: duration, displayValue: formatBytes(duration), diff --git a/tooling/measures/nx-performance/audit/project-graph.audit.ts b/tooling/measures/nx-performance/audit/project-graph.audit.ts index 8a409dfb..1552c14a 100644 --- a/tooling/measures/nx-performance/audit/project-graph.audit.ts +++ b/tooling/measures/nx-performance/audit/project-graph.audit.ts @@ -1,13 +1,14 @@ -import {AuditOutput, PluginReport} from '@code-pushup/models'; -import {execFile} from 'node:child_process'; -import {join} from "node:path"; -import {DEFAULT_PLUGIN_OUTPUT} from "../constant"; -import {executeProcess, slugify} from "@code-pushup/utils"; +import { AuditOutput, PluginReport } from '@code-pushup/models'; +import { execFile } from 'node:child_process'; +import { join } from 'node:path'; +import { DEFAULT_PLUGIN_OUTPUT } from '../constant'; +import { executeProcess, slugify } from '@code-pushup/utils'; export const DEFAULT_MAX_PROJECT_GRAPH_TIME = 300; +export const PROJECT_GRAPH_PERFORMANCE_AUDIT_SLUG = 'project-graph-performance'; export const PROJECT_GRAPH_PERFORMANCE_AUDIT = { - slug: 'project-graph-performance', + slug: PROJECT_GRAPH_PERFORMANCE_AUDIT_SLUG, title: 'Project graph performance', description: 'An audit to check performance of the Nx project graph', }; @@ -19,9 +20,9 @@ export type ProjectGraphAuditOptions = { export async function projectGraphAudit( options?: ProjectGraphAuditOptions ): Promise { - const {maxProjectGraphTime = DEFAULT_MAX_PROJECT_GRAPH_TIME} = - options ?? {}; - const {duration} = await projectGraphTiming(); + const { maxProjectGraphTime = DEFAULT_MAX_PROJECT_GRAPH_TIME } = + options ?? {}; + const { duration } = await projectGraphTiming(); return { slug: 'project-graph-performance', @@ -58,7 +59,9 @@ export async function projectGraphTiming(): Promise<{ duration: number }> { } })*/ const start = performance.now(); - execFile('NX_DAEMON=true NX_CACHE_PROJECT_GRAPH=false NX_ISOLATE_PLUGINS=true npx nx show projects'); + execFile( + 'NX_DAEMON=true NX_CACHE_PROJECT_GRAPH=false NX_ISOLATE_PLUGINS=true npx nx show projects' + ); const execFileDuration = Number((performance.now() - start).toFixed(3)); - return {duration: Number(execFileDuration.toFixed(3))}; + return { duration: Number(execFileDuration.toFixed(3)) }; } diff --git a/tooling/measures/nx-performance/audit/project-task.audit.ts b/tooling/measures/nx-performance/audit/project-task.audit.ts index c5308d10..0ba5bcca 100644 --- a/tooling/measures/nx-performance/audit/project-task.audit.ts +++ b/tooling/measures/nx-performance/audit/project-task.audit.ts @@ -6,13 +6,15 @@ import { join } from 'node:path'; export const DEFAULT_MAX_PROJECT_TARGET_TIME = 300; -export function getAuditSlug(task: string): string { - return `nx-${slugify(task)}-performance`; +export const TASK_TIME_AUDIT_POSTFIX = 'task-time'; + +export function getTaskTimeAuditSlug(task: string): string { + return `nx-${slugify(task)}-${TASK_TIME_AUDIT_POSTFIX}`; } -export const getTaskPerformanceAudits = (tasks: string[]): Audit[] => { +export const getTaskTimeAudits = (tasks: string[]): Audit[] => { return tasks.map((task) => ({ - slug: getAuditSlug(task), // Unique slug for each task + slug: getTaskTimeAuditSlug(task), // Unique slug for each task title: `Task time ${task}`, description: 'An audit to check performance of the Nx task.', })); @@ -46,7 +48,7 @@ export async function taskTimeAudits( ]; }) .map(([task, duration]) => ({ - slug: getAuditSlug(task), // Unique slug for each task + slug: getTaskTimeAuditSlug(task), // Unique slug for each task score: scoreProjectTaskDuration(duration, maxTaskTime), value: duration, displayValue: formatDuration(duration), diff --git a/tooling/measures/nx-performance/index.ts b/tooling/measures/nx-performance/index.ts index d15483f1..4f2cbeae 100644 --- a/tooling/measures/nx-performance/index.ts +++ b/tooling/measures/nx-performance/index.ts @@ -1 +1,6 @@ -export {nxPerformanceAudits, nxPerformancePlugin, nxPerformanceCategoryRefs} from './nx-performance.plugin'; +export { + type OnlyAudit, + nxPerformanceAudits, + nxPerformancePlugin, + nxPerformanceCategoryRefs, +} from './nx-performance.plugin'; diff --git a/tooling/measures/nx-performance/nx-performance.plugin.ts b/tooling/measures/nx-performance/nx-performance.plugin.ts index dec21a06..c0d4c014 100644 --- a/tooling/measures/nx-performance/nx-performance.plugin.ts +++ b/tooling/measures/nx-performance/nx-performance.plugin.ts @@ -1,16 +1,24 @@ -import { PluginConfig, AuditOutputs, CategoryRef } from '@code-pushup/models'; +import { + Audit, + AuditOutputs, + CategoryRef, + PluginConfig, +} from '@code-pushup/models'; import { PLUGIN_SLUG } from './constant'; import { PROJECT_GRAPH_PERFORMANCE_AUDIT, + PROJECT_GRAPH_PERFORMANCE_AUDIT_SLUG, projectGraphAudit, ProjectGraphAuditOptions, } from './audit/project-graph.audit'; import { - getTaskPerformanceAudits, + getTaskTimeAudits, ProjectTaskAuditOptions, + TASK_TIME_AUDIT_POSTFIX, taskTimeAudits, } from './audit/project-task.audit'; import { + CACHE_SIZE_AUDIT_POSTFIX, CacheSizeAuditOptions, cacheSizeAudits, getCacheSizeAudits, @@ -21,53 +29,102 @@ export const nxPerformanceAudits = ({ cacheSizeTasks, }: NxPerfPluginConfig) => [ PROJECT_GRAPH_PERFORMANCE_AUDIT, - ...(taskTimeTasks ? getTaskPerformanceAudits(taskTimeTasks) : []), + ...(taskTimeTasks ? getTaskTimeAudits(taskTimeTasks) : []), ...(cacheSizeTasks ? getCacheSizeAudits(cacheSizeTasks) : []), ]; export const nxPerformanceCategoryRefs = ( options: NxPerfRunnerOptions -): CategoryRef[] => - nxPerformanceAudits(options).map(({ slug }) => ({ +): CategoryRef[] => { + const allAudits = nxPerformanceAudits(options); + const audits = options?.onlyAudits + ? filterOnlyAudits(allAudits, options.onlyAudits) + : allAudits; + return audits.map(({ slug }) => ({ type: 'audit', plugin: PLUGIN_SLUG, slug, weight: 1, })); +}; -export type NxPerfPluginConfig = ProjectGraphAuditOptions & +export type OnlyAudit = + | typeof CACHE_SIZE_AUDIT_POSTFIX + | typeof PROJECT_GRAPH_PERFORMANCE_AUDIT_SLUG + | typeof TASK_TIME_AUDIT_POSTFIX; +export type NxPerfPluginConfig = { + onlyAudits?: OnlyAudit[]; +} & ProjectGraphAuditOptions & ProjectTaskAuditOptions & CacheSizeAuditOptions; export function nxPerformancePlugin( options?: NxPerfPluginConfig ): PluginConfig { + const allAudits = nxPerformanceAudits(options); return { slug: PLUGIN_SLUG, title: 'Nx Performance Checks', icon: 'flash', description: 'A plugin to measure and assert performance of Nx workspace.', runner: () => runnerFunction(options), - audits: nxPerformanceAudits(options), + audits: options?.onlyAudits + ? filterOnlyAudits(allAudits, options.onlyAudits) + : allAudits, }; } export default nxPerformancePlugin; export type NxPerfRunnerOptions = NxPerfPluginConfig; + +export function filterOnlyAudits( + audits: Audit[], + onlyAudits: OnlyAudit[] +): Audit[] { + const onlyAuditsSet = new Set(onlyAudits); + return audits.filter(({ slug }) => { + if ( + onlyAuditsSet.has(CACHE_SIZE_AUDIT_POSTFIX) && + slug.endsWith(CACHE_SIZE_AUDIT_POSTFIX) + ) { + return true; + } + if ( + onlyAuditsSet.has(TASK_TIME_AUDIT_POSTFIX) && + slug.endsWith(TASK_TIME_AUDIT_POSTFIX) + ) { + return true; + } + return onlyAuditsSet.has(slug as OnlyAudit); + }); +} + export async function runnerFunction( options: NxPerfRunnerOptions ): Promise { const { + onlyAudits = [ + PROJECT_GRAPH_PERFORMANCE_AUDIT_SLUG, + CACHE_SIZE_AUDIT_POSTFIX, + TASK_TIME_AUDIT_POSTFIX, + ], taskTimeTasks, maxTaskTime, maxCacheSize, cacheSizeTasks, maxProjectGraphTime, } = options; + const onlyAuditsSet = new Set(onlyAudits); return [ - await projectGraphAudit({ maxProjectGraphTime }), - // ...(await cacheSizeAudits({ maxCacheSize, cacheSizeTasks })), - // ...(await taskTimeAudits({ taskTimeTasks, maxTaskTime })), + ...(onlyAuditsSet.has(PROJECT_GRAPH_PERFORMANCE_AUDIT_SLUG) + ? [await projectGraphAudit({ maxProjectGraphTime })] + : []), + ...(onlyAuditsSet.has(CACHE_SIZE_AUDIT_POSTFIX) + ? await cacheSizeAudits({ maxCacheSize, cacheSizeTasks }) + : []), + ...(onlyAuditsSet.has(TASK_TIME_AUDIT_POSTFIX) + ? await taskTimeAudits({ maxTaskTime, taskTimeTasks }) + : []), ]; }