You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
As a developer I want to be able to cache as much as possible with Nx and leverage affected
Why Commit Info Breaks Caching
To get reliable caching in tools like Nx, task inputs must stay stable across commits — unless the output truly depends on them.
Example ESLint:
ESLint can be cached effectively when its inputs are:
The ESLint version
Source files of the project
Dependency .d.ts files
In this setup, even if you're on a different commit or branch, ESLint won’t re-run unless something relevant changes. This allows maximum cache reuse.
Note
Using Commit SHA as Input
If you include the commit SHA in:
Task inputs
Generated files
Plugin outputs
Then every commit creates a unique input hash, and ESLint (or any task) loses its cache — even when the code hasn’t changed.
Suggestion
Legend:
🐳 Owned by Nx — Nx or other external caching solutions
🔌 Owned by plugin creator — depends on code changes
☑️ Owned by CodePushup — depends on code changes
🔧 Code-related — depends on code changes
⛓️ Commit-related — depends on commit (includes code changes)
⚡ Fast — fast enough to optionally skip caching
💾 Cached — slow or expensive, should be cached
🚫 No Cache — intentionally avoids caching
New CLI options for command collect
Option
Type
Default
Description
--persist.report
boolean
true
Will not produce report.json. Normally in combination with --cache
--cache.write
boolean
false
If true it will generate a {persist.outputDir}/<plugin-slug>/audit-outputs.json file containing the audit output data of a plugin
--cache.read
boolean
false
If true it will try to read the plugins audit outputs for file system. If not available it will run the plugin to get the audit outputs on the fly. If
IF--cache.write is given it will write the audit outputs data to {persist.outputDir}/<plugin-slug>/audit-outputs.json (💾☑️).
This is done in executePlugin after the execution.
After the plugins are run
IF--no-report is set, no final report persist.outputDir/report.json is created. (☑️)
IF--cache.read is given the CLI checks for existing plugin audit outputs under persist.outputDir/<plugin-slug>/audit-outputs.json and if given it will take the data instead of executing the plugin runner.
This is done in executePlugin before the execution.
ELSE:
IFgenerateArtifactsCommand is defined
→ Run the command e.g., npx nx run-many ... to produce the raw artifacts (🐳)
Optional Generate plugin artifacts (💾 🔧 🔌)
Generate the plugin report and persist it to persist.outputDir/<plugin-slug>/audit-outputs.json (💾 🔧 ☑️)
In executePlugin we save the plugin report as AuditOutputs.
After all plugins are processed, the CLI will combine reports into the final report persist.outputDir/report.json (⛓️ ⚡ 🚫 🔧 ☑️)
User story
As a developer I want to be able to cache as much as possible with Nx and leverage
affectedWhy Commit Info Breaks Caching
To get reliable caching in tools like Nx, task inputs must stay stable across commits — unless the output truly depends on them.
Example ESLint:
ESLint can be cached effectively when its inputs are:
In this setup, even if you're on a different commit or branch, ESLint won’t re-run unless something relevant changes. This allows maximum cache reuse.
Note
Using Commit SHA as Input
If you include the commit SHA in:
Then every commit creates a unique input hash, and ESLint (or any task) loses its cache — even when the code hasn’t changed.
Suggestion
Legend:
New CLI options for command
collect--persist.reportbooleantruereport.json. Normally in combination with--cache--cache.writebooleanfalsetrueit will generate a{persist.outputDir}/<plugin-slug>/audit-outputs.jsonfile containing the audit output data of a plugin--cache.readbooleanfalsetrueit will try to read the plugins audit outputs for file system. If not available it will run the plugin to get the audit outputs on the fly. IfCollect Flow - Generation Phase
Command:
npx @code-pushup/cli collect --cache.write --no-report --onlyPlugins eslintFor each plugin listed in
--onlyPlugins:IF
--cache.writeis given it will write the audit outputs data to{persist.outputDir}/<plugin-slug>/audit-outputs.json(💾☑️).This is done in executePlugin after the execution.
After the plugins are run
IF
--no-reportis set, no final reportpersist.outputDir/report.jsonis created. (☑️)Collect Flow - Aggregation Phase
Command:
npx @code-pushup/cli collect --cache.readIF
--cache.readis given the CLI checks for existing plugin audit outputs underpersist.outputDir/<plugin-slug>/audit-outputs.jsonand if given it will take the data instead of executing the plugin runner.This is done in executePlugin before the execution.
ELSE:
IF
generateArtifactsCommandis defined→ Run the command e.g.,
npx nx run-many ...to produce the raw artifacts (🐳)Optional Generate plugin artifacts (💾 🔧 🔌)
Generate the plugin report and persist it to
persist.outputDir/<plugin-slug>/audit-outputs.json(💾 🔧 ☑️)In executePlugin we save the plugin report as AuditOutputs.
persist.outputDir/report.json(⛓️ ⚡ 🚫 🔧 ☑️)Code Pushup Config
Targets
{ "name": "lib-a", "targets": { "int-test": { "cache": true, "outputs": ["{options.coverage.reportsDirectory}"], "executor": "@nx/vite:test", "options": { "configFile": "packages/lib-a/vitest.int.config.ts", "coverage.reportsDirectory": "{projectRoot}/coverage/int-test" } }, "unit-test": { "cache": true, "outputs": ["{options.coverage.reportsDirectory}"], "executor": "@nx/vite:test", "options": { "configFile": "packages/lib-a/vitest.unit.config.ts", "coverage.reportsDirectory": "{projectRoot}/coverage/unit-test" } }, "code-pushup:coverage": { "dependsOn": ["unit-test", "int-test"], "cache": true, "inputs": ["{coverage-speciftic-globs}"], "outputs": ["{options.outputPath}"], "executor": "@code-pushup/nx-plugin:cli", "options": { "report": false, "cache.write": true, "onlyPlugins": "coverage", "persist.outputDir": "{projectRoot}/.code-pushup/coverage", "outputPath": "{projectRoot}/.code-pushup/coverage/<plugin-slug>/plugin-report.json", } }, "//":"This target could be completely skipped as we d not cache anything here", "code-pushup:nx-perf": { "cache": false, "executor": "@code-pushup/nx-plugin:cli", "options": { "report": false, "onlyPlugins": "nx-perf" "persist.outputDir": "{projectRoot}/.code-pushup/nx-perf" } }, "code-pushup": { "dependsOn": ["code-pushup:coverage", "code-pushup:nx-perf"], "cache": false, "outputs": ["{options.outputPath}"], "executor": "@code-pushup/nx-plugin:cli", "options": { "cache.read": true, "persist.outputDir": "{projectRoot}/.code-pushup", "outputPath": "{projectRoot}/.code-pushup/report.*", } } } }Nx Task Graph
Acceptance criteria
--report- feat: add report option to cli #1058{persist.outputDir}/<plugin-slug>/runner-output.json--cache.writeand--cache.readfeat: add audit output caching for execute plugin #1057Implementation details
No response