@diffci.com/diffci 0.1.6 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
|
|
7
7
|
**Find test-selection opportunities in your CI before changing what it runs.** DiffCI analyzes a
|
|
8
8
|
commit's changes and dependency graph, then reports which test files it would select, why it falls
|
|
9
|
-
back to a full run, and whether it can propose a test command. The
|
|
9
|
+
back to a full run, and whether it can propose a test command. The `observe` command and Action are observation-only;
|
|
10
|
+
the opt-in `pilot` and `verify-savings` commands execute tests.
|
|
10
11
|
|
|
11
12
|
From an existing repository checkout, with Node.js 22.5+ and Git installed:
|
|
12
13
|
|
|
@@ -26,8 +27,10 @@ On Windows PowerShell, quote the package name:
|
|
|
26
27
|
npx '@diffci.com/diffci@latest' pilot --full "npm test"
|
|
27
28
|
```
|
|
28
29
|
|
|
29
|
-
This writes `diffci-observe.json`,
|
|
30
|
-
`diffci-
|
|
30
|
+
This executes the full and selected commands sequentially, and writes `diffci-observe.json`,
|
|
31
|
+
`diffci-savings.json`, and `diffci-savings.md` to a sibling `diffci-output` folder outside the checkout.
|
|
32
|
+
The commands you supply may create files or otherwise change the checkout. One paired run is preliminary
|
|
33
|
+
timing evidence; repeat comparisons and account for cache effects before claiming savings.
|
|
31
34
|
|
|
32
35
|
**Upgrade from 0.1.3:** tests excluded by a source-only `tsconfig.json` could be discovered without
|
|
33
36
|
their dependency edges, producing an incomplete selection. This is fixed in **0.1.4**. Revalidate
|
|
@@ -393,8 +393,15 @@ async function main() {
|
|
|
393
393
|
}
|
|
394
394
|
}
|
|
395
395
|
main().catch((error) => {
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
396
|
+
const command = process.argv[2];
|
|
397
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
398
|
+
if (command === "observe") {
|
|
399
|
+
// Reaching here means a defect outside observe()'s own guard. It still must not take a build down:
|
|
400
|
+
// the failure is printed, and the exit code stays 0 unless the caller asked otherwise.
|
|
401
|
+
console.error(`DiffCI observer failed: ${message}`);
|
|
402
|
+
process.exitCode = process.argv.includes("--fail-on-error") ? 1 : 0;
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
console.error(`DiffCI ${command ?? "command"} failed: ${message}`);
|
|
406
|
+
process.exitCode = 1;
|
|
400
407
|
});
|
|
@@ -11,11 +11,11 @@ function readSelectionFromObservation(path) {
|
|
|
11
11
|
const parsed = JSON.parse(readFileSync(absolutePath, "utf8"));
|
|
12
12
|
if (parsed.status !== "OBSERVED")
|
|
13
13
|
throw new Error(`--selected-from-report requires an OBSERVED report; got ${String(parsed.status)}`);
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
const commands = parsed.result?.proposedCommands;
|
|
15
|
+
if (!Array.isArray(commands) || commands.length !== 1 || typeof commands[0] !== "string" || !commands[0].trim()) {
|
|
16
|
+
throw new Error("--selected-from-report requires exactly one non-empty proposed command; use --selected with an explicit command covering the complete selection for multi-command plans");
|
|
17
|
+
}
|
|
18
|
+
const command = commands[0];
|
|
19
19
|
const selectedTests = Array.isArray(parsed.result?.selectedTests) ? parsed.result.selectedTests : undefined;
|
|
20
20
|
return {
|
|
21
21
|
command,
|
|
@@ -122,7 +122,9 @@ export function renderVerifySavingsMarkdown(report) {
|
|
|
122
122
|
const title = report.label ? `# DiffCI Verify Savings: ${report.label}` : "# DiffCI Verify Savings";
|
|
123
123
|
const warning = report.comparison.missedFailureSignal
|
|
124
124
|
? "\n> WARNING: Full failed while selected passed. Do not treat this selected command as safe until the full-run failure is understood.\n"
|
|
125
|
-
:
|
|
125
|
+
: !report.comparison.fullCommandSucceeded || !report.comparison.selectedCommandSucceeded
|
|
126
|
+
? "\n> WARNING: One or both commands failed. This comparison is invalid as savings evidence; timings below are diagnostic only.\n"
|
|
127
|
+
: "";
|
|
126
128
|
const selectionCounts = report.selectedTestCount !== undefined && report.totalTestCount !== undefined
|
|
127
129
|
? `\nSelected tests: ${report.selectedTestCount} of ${report.totalTestCount}\n`
|
|
128
130
|
: "";
|
|
@@ -137,6 +139,7 @@ This report compares a full command with a selected command on the same checkout
|
|
|
137
139
|
|
|
138
140
|
## Result
|
|
139
141
|
|
|
142
|
+
${!report.comparison.fullCommandSucceeded || !report.comparison.selectedCommandSucceeded ? "Comparison invalid: command failure. Do not interpret the timing difference as savings.\n" : ""}
|
|
140
143
|
| Measure | Value |
|
|
141
144
|
| --- | ---: |
|
|
142
145
|
| Full runtime | ${formatMs(report.comparison.fullWallMs)} |
|
|
@@ -183,6 +186,10 @@ export function writeVerifySavingsReport(report, paths) {
|
|
|
183
186
|
writeText(paths.markdown, renderVerifySavingsMarkdown(report));
|
|
184
187
|
}
|
|
185
188
|
export function formatVerifySavingsSummary(report) {
|
|
189
|
+
if (!report.comparison.fullCommandSucceeded || !report.comparison.selectedCommandSucceeded) {
|
|
190
|
+
return "DiffCI verify-savings: comparison invalid because one or both commands failed" +
|
|
191
|
+
(report.comparison.missedFailureSignal ? "\n warning: full failed while selected passed; inspect outputs before claiming safety" : "");
|
|
192
|
+
}
|
|
186
193
|
const lines = [
|
|
187
194
|
`DiffCI verify-savings: ${report.comparison.deltaMs >= 0 ? "faster" : "slower"} by ${formatMs(Math.abs(report.comparison.deltaMs))}`,
|
|
188
195
|
];
|
package/docs/npm-adoption.md
CHANGED
|
@@ -62,7 +62,7 @@ This is a paired local measurement, not a production-savings claim.
|
|
|
62
62
|
Step 1: create an observation report without sending it anywhere.
|
|
63
63
|
|
|
64
64
|
```bash
|
|
65
|
-
npx @diffci.com/diffci@latest observe --no-send --out
|
|
65
|
+
npx @diffci.com/diffci@latest observe --no-send --out ../diffci-output/diffci-observation.json
|
|
66
66
|
```
|
|
67
67
|
|
|
68
68
|
Step 2: run the paired pilot.
|
|
@@ -72,13 +72,17 @@ npx @diffci.com/diffci@latest verify-savings \
|
|
|
72
72
|
--label owner/repo \
|
|
73
73
|
--repo /path/to/their/repo \
|
|
74
74
|
--full "npm test" \
|
|
75
|
-
--selected-from-report /
|
|
76
|
-
--out
|
|
77
|
-
--markdown
|
|
75
|
+
--selected-from-report ../diffci-output/diffci-observation.json \
|
|
76
|
+
--out ../diffci-output/diffci-verify-savings.json \
|
|
77
|
+
--markdown ../diffci-output/diffci-verify-savings.md
|
|
78
78
|
```
|
|
79
79
|
|
|
80
80
|
What the report means:
|
|
81
81
|
|
|
82
|
+
Run both steps from the same repository root with the same checked-out revision. These commands
|
|
83
|
+
execute repository code. The full run can warm caches for the selected run, so repeat comparisons
|
|
84
|
+
with controlled cache state before drawing conclusions. A passing pair does not establish selection safety.
|
|
85
|
+
|
|
82
86
|
- Full runtime is measured from `--full`.
|
|
83
87
|
- Selected runtime is measured from DiffCI's proposed command in the observation report.
|
|
84
88
|
- DiffCI analysis overhead is imported from `timings.totalMs` in the observation report unless
|