@blzsky/variant 0.2.1 → 0.3.0-canary.1
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 +222 -85
- package/dist/{build-3DSBMMI3.js → build-GCUFPPIB.js} +11 -10
- package/dist/check-AKYABBIV.js +1459 -0
- package/dist/{chunk-43VLELTL.js → chunk-2UVLKBLV.js} +1 -1
- package/dist/chunk-34VGKPEM.js +59 -0
- package/dist/chunk-BNACT47L.js +590 -0
- package/dist/chunk-C3NZIFW6.js +174 -0
- package/dist/{chunk-ZH2PQUNL.js → chunk-EFCMBBBT.js} +72 -110
- package/dist/chunk-H55GYSQ6.js +102 -0
- package/dist/chunk-HL65IPEQ.js +167 -0
- package/dist/chunk-IHXJ72XA.js +31 -0
- package/dist/{chunk-FZEXZBXB.js → chunk-JEJRXPCU.js} +41 -9
- package/dist/chunk-LUTP2TVU.js +94 -0
- package/dist/{chunk-7OPTWU6E.js → chunk-MKUYZIXF.js} +1 -1
- package/dist/chunk-MNYKLWRC.js +377 -0
- package/dist/{chunk-Q7RLUZSN.js → chunk-NJSTAWDM.js} +10 -3
- package/dist/{chunk-26DHEXGS.js → chunk-NOC53Z5Q.js} +1 -1
- package/dist/chunk-O6FCFZDF.js +127 -0
- package/dist/{chunk-6BXSZPHC.js → chunk-OON6O4S5.js} +99 -6
- package/dist/{chunk-FA64KWJ2.js → chunk-TPMHY4L6.js} +16 -31
- package/dist/chunk-TRUK3TJF.js +575 -0
- package/dist/chunk-WTXWEEI2.js +21 -0
- package/dist/{chunk-RC23JQKI.js → chunk-WULBOSG5.js} +15 -2
- package/dist/chunk-X3VVGTEV.js +268 -0
- package/dist/{chunk-TCISS2AS.js → chunk-XXMD4NC5.js} +120 -25
- package/dist/cli.js +89 -30
- package/dist/{diff-HSJBZFMC.js → diff-ST5KHT7P.js} +5 -5
- package/dist/{doctor-B7MHFIYJ.js → doctor-OEIY4Y5X.js} +41 -8
- package/dist/{env-I7JZRWDN.js → env-EQAOZCFR.js} +8 -9
- package/dist/git-VGHUF2SY.js +30 -0
- package/dist/impact-AXLZTLVT.js +266 -0
- package/dist/index.js +2 -2
- package/dist/init-QCOZWLOO.js +793 -0
- package/dist/{insight-JQLTGFYB.js → insight-KRWT6Z47.js} +9 -10
- package/dist/pr-7JXUC5BQ.js +710 -0
- package/dist/{run-C6VAQOVM.js → run-UOPS5FRU.js} +11 -10
- package/dist/stryker-host.d.ts +2 -0
- package/dist/stryker-host.js +135 -0
- package/dist/stryker-plugins.d.ts +33 -0
- package/dist/stryker-plugins.js +142 -0
- package/dist/{symbol-graph-E5GXKDFZ.js → symbol-graph-GYOI4GU4.js} +3 -3
- package/dist/{tsconfig-paths-E3UEDGXZ.js → tsconfig-paths-SV3PULCW.js} +3 -1
- package/dist/vitest.cjs +629 -0
- package/dist/vitest.d.cts +181 -0
- package/dist/vitest.d.ts +181 -0
- package/dist/vitest.js +358 -0
- package/dist/workspace-IQFLR3RY.js +65 -0
- package/package.json +17 -3
- package/dist/check-SIQJU6Z2.js +0 -44
- package/dist/chunk-DRMASVYN.js +0 -25
- package/dist/chunk-KSHWC2XN.js +0 -78
- package/dist/chunk-QRPI6TJE.js +0 -68
- package/dist/chunk-VYWPQKMS.js +0 -88
- package/dist/chunk-XTYVVUWW.js +0 -279
- package/dist/impact-PRZ6HEP5.js +0 -735
- package/dist/init-O2BY3FOY.js +0 -158
- package/dist/pr-Y724QAHE.js +0 -165
- package/dist/workspace-HRTFGWKN.js +0 -186
|
@@ -2,19 +2,19 @@ import {
|
|
|
2
2
|
DEFAULT_DIFF_BASE_REF,
|
|
3
3
|
classifyFileAgainstRef,
|
|
4
4
|
toWorkspaceRelative
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-NJSTAWDM.js";
|
|
6
6
|
import {
|
|
7
7
|
assertBaseRef
|
|
8
|
-
} from "./chunk-
|
|
9
|
-
import "./chunk-6BXSZPHC.js";
|
|
8
|
+
} from "./chunk-JEJRXPCU.js";
|
|
10
9
|
import {
|
|
11
10
|
lines
|
|
12
11
|
} from "./chunk-6J4XDG44.js";
|
|
13
12
|
import {
|
|
14
13
|
getPrinter
|
|
15
14
|
} from "./chunk-EISTWXDW.js";
|
|
16
|
-
import "./chunk-
|
|
17
|
-
import "./chunk-
|
|
15
|
+
import "./chunk-OON6O4S5.js";
|
|
16
|
+
import "./chunk-WULBOSG5.js";
|
|
17
|
+
import "./chunk-C3NZIFW6.js";
|
|
18
18
|
|
|
19
19
|
// src/cli/render/diff.ts
|
|
20
20
|
var CLASS_MEANING = {
|
|
@@ -1,22 +1,45 @@
|
|
|
1
|
+
import {
|
|
2
|
+
buildGraph
|
|
3
|
+
} from "./chunk-H55GYSQ6.js";
|
|
4
|
+
import {
|
|
5
|
+
lines
|
|
6
|
+
} from "./chunk-6J4XDG44.js";
|
|
1
7
|
import {
|
|
2
8
|
findVariantConfigPath,
|
|
3
9
|
loadConfig
|
|
4
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-NOC53Z5Q.js";
|
|
5
11
|
import {
|
|
6
12
|
getColors
|
|
7
13
|
} from "./chunk-YYGCSKIQ.js";
|
|
8
|
-
import {
|
|
9
|
-
lines
|
|
10
|
-
} from "./chunk-6J4XDG44.js";
|
|
11
14
|
import {
|
|
12
15
|
getPrinter
|
|
13
16
|
} from "./chunk-EISTWXDW.js";
|
|
14
|
-
import
|
|
17
|
+
import {
|
|
18
|
+
ConfigError
|
|
19
|
+
} from "./chunk-C3NZIFW6.js";
|
|
15
20
|
|
|
16
21
|
// src/core/doctor/diagnostics.ts
|
|
17
22
|
import { readdir, stat } from "fs/promises";
|
|
18
23
|
import path from "path";
|
|
19
|
-
|
|
24
|
+
|
|
25
|
+
// src/core/graph/validation.ts
|
|
26
|
+
function validateTaskGraph(tasks, graph) {
|
|
27
|
+
for (const [name, task] of Object.entries(tasks)) {
|
|
28
|
+
for (const dependency of task.dependsOn ?? []) {
|
|
29
|
+
if (!(dependency in tasks)) {
|
|
30
|
+
throw new ConfigError(
|
|
31
|
+
`Task "${name}" depends on unknown task "${dependency}"`
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
for (const name of Object.keys(tasks)) {
|
|
37
|
+
graph.toLevels(name);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// src/core/doctor/diagnostics.ts
|
|
42
|
+
var MINIMUM_NODE_MAJOR = 22;
|
|
20
43
|
var CACHE_WARN_MB = 500;
|
|
21
44
|
function checkNodeVersion(version = process.version) {
|
|
22
45
|
const match = version.match(/^v(\d+)/);
|
|
@@ -71,9 +94,9 @@ async function checkConfig(cwd) {
|
|
|
71
94
|
if (!configPath) {
|
|
72
95
|
return [
|
|
73
96
|
{
|
|
74
|
-
level: "
|
|
97
|
+
level: "warn",
|
|
75
98
|
label: "No variant.config.ts found",
|
|
76
|
-
detail: "
|
|
99
|
+
detail: "`impact`, `diff`, `pr` and `workspace check` work without one. `build` and `run` need it: `variant init --tasks` creates one."
|
|
77
100
|
}
|
|
78
101
|
];
|
|
79
102
|
}
|
|
@@ -92,6 +115,16 @@ async function checkConfig(cwd) {
|
|
|
92
115
|
return diagnostics;
|
|
93
116
|
}
|
|
94
117
|
diagnostics.push({ level: "ok", label: "Config is valid" });
|
|
118
|
+
try {
|
|
119
|
+
validateTaskGraph(config.tasks, buildGraph(config));
|
|
120
|
+
diagnostics.push({ level: "ok", label: "Task graph is valid" });
|
|
121
|
+
} catch (err) {
|
|
122
|
+
diagnostics.push({
|
|
123
|
+
level: "error",
|
|
124
|
+
label: "Task graph is invalid",
|
|
125
|
+
detail: err instanceof Error ? err.message : String(err)
|
|
126
|
+
});
|
|
127
|
+
}
|
|
95
128
|
diagnostics.push(await checkCacheSize(cwd, config.cache.directory));
|
|
96
129
|
return diagnostics;
|
|
97
130
|
}
|
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
|
+
createContext,
|
|
2
3
|
renderEnv
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
} from "./chunk-ZH2PQUNL.js";
|
|
4
|
+
} from "./chunk-EFCMBBBT.js";
|
|
5
|
+
import "./chunk-H55GYSQ6.js";
|
|
6
|
+
import "./chunk-MKUYZIXF.js";
|
|
7
7
|
import "./chunk-V5CTGXMM.js";
|
|
8
|
-
import "./chunk-26DHEXGS.js";
|
|
9
|
-
import "./chunk-YYGCSKIQ.js";
|
|
10
|
-
import "./chunk-7OPTWU6E.js";
|
|
11
8
|
import "./chunk-3E5LBU3O.js";
|
|
12
|
-
import "./chunk-6BXSZPHC.js";
|
|
13
9
|
import "./chunk-6J4XDG44.js";
|
|
10
|
+
import "./chunk-NOC53Z5Q.js";
|
|
11
|
+
import "./chunk-YYGCSKIQ.js";
|
|
14
12
|
import "./chunk-EISTWXDW.js";
|
|
15
|
-
import "./chunk-
|
|
13
|
+
import "./chunk-OON6O4S5.js";
|
|
14
|
+
import "./chunk-C3NZIFW6.js";
|
|
16
15
|
|
|
17
16
|
// src/cli/commands/env.ts
|
|
18
17
|
async function registerEnvAction() {
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import {
|
|
2
|
+
defaultBranchRef,
|
|
3
|
+
hasLocalChanges,
|
|
4
|
+
listChangedFiles,
|
|
5
|
+
listChangedFilesSinceMergeBase,
|
|
6
|
+
listRepositoryFiles,
|
|
7
|
+
listUntrackedFiles,
|
|
8
|
+
mergeBase,
|
|
9
|
+
readFileAtRef,
|
|
10
|
+
readFilesAtRef,
|
|
11
|
+
readHeadSha,
|
|
12
|
+
readZeroContextDiff,
|
|
13
|
+
repositoryRoot,
|
|
14
|
+
resolveCommit
|
|
15
|
+
} from "./chunk-OON6O4S5.js";
|
|
16
|
+
export {
|
|
17
|
+
defaultBranchRef,
|
|
18
|
+
hasLocalChanges,
|
|
19
|
+
listChangedFiles,
|
|
20
|
+
listChangedFilesSinceMergeBase,
|
|
21
|
+
listRepositoryFiles,
|
|
22
|
+
listUntrackedFiles,
|
|
23
|
+
mergeBase,
|
|
24
|
+
readFileAtRef,
|
|
25
|
+
readFilesAtRef,
|
|
26
|
+
readHeadSha,
|
|
27
|
+
readZeroContextDiff,
|
|
28
|
+
repositoryRoot,
|
|
29
|
+
resolveCommit
|
|
30
|
+
};
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
import {
|
|
2
|
+
predictImpact
|
|
3
|
+
} from "./chunk-LUTP2TVU.js";
|
|
4
|
+
import {
|
|
5
|
+
verdictText
|
|
6
|
+
} from "./chunk-BNACT47L.js";
|
|
7
|
+
import "./chunk-JEJRXPCU.js";
|
|
8
|
+
import "./chunk-TRUK3TJF.js";
|
|
9
|
+
import "./chunk-GDSZFIHM.js";
|
|
10
|
+
import "./chunk-MKUYZIXF.js";
|
|
11
|
+
import {
|
|
12
|
+
classificationLabel,
|
|
13
|
+
plural
|
|
14
|
+
} from "./chunk-CXNXZLDG.js";
|
|
15
|
+
import "./chunk-3E5LBU3O.js";
|
|
16
|
+
import {
|
|
17
|
+
lines
|
|
18
|
+
} from "./chunk-6J4XDG44.js";
|
|
19
|
+
import {
|
|
20
|
+
getColors
|
|
21
|
+
} from "./chunk-YYGCSKIQ.js";
|
|
22
|
+
import {
|
|
23
|
+
getPrinter
|
|
24
|
+
} from "./chunk-EISTWXDW.js";
|
|
25
|
+
import {
|
|
26
|
+
verifyImpact
|
|
27
|
+
} from "./chunk-HL65IPEQ.js";
|
|
28
|
+
import "./chunk-34VGKPEM.js";
|
|
29
|
+
import {
|
|
30
|
+
changeBaseDeps,
|
|
31
|
+
detectHeadSha
|
|
32
|
+
} from "./chunk-O6FCFZDF.js";
|
|
33
|
+
import "./chunk-X3VVGTEV.js";
|
|
34
|
+
import "./chunk-OON6O4S5.js";
|
|
35
|
+
import "./chunk-XXMD4NC5.js";
|
|
36
|
+
import "./chunk-WULBOSG5.js";
|
|
37
|
+
import {
|
|
38
|
+
NoBaseCommitError
|
|
39
|
+
} from "./chunk-C3NZIFW6.js";
|
|
40
|
+
|
|
41
|
+
// src/cli/render/impact.ts
|
|
42
|
+
var MAX_LISTED_FILES = 20;
|
|
43
|
+
var count = (value) => value.toLocaleString("en-US");
|
|
44
|
+
var NO_PREDICTION_MESSAGE = "impact verify: no logged prediction to reconcile against. Run `variant impact` before the test run, or pass --head-sha for a specific commit.";
|
|
45
|
+
function shortRef(ref) {
|
|
46
|
+
return /^[0-9a-f]{40}$/.test(ref) ? ref.slice(0, 12) : ref;
|
|
47
|
+
}
|
|
48
|
+
function renderNoBaseCommit(reason, json, printer = getPrinter()) {
|
|
49
|
+
lines(
|
|
50
|
+
printer,
|
|
51
|
+
json ? JSON.stringify(
|
|
52
|
+
{ prediction: null, code: "NO_BASE_COMMIT", reason },
|
|
53
|
+
null,
|
|
54
|
+
2
|
|
55
|
+
) : `impact: ${reason}; no prediction was made.`
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
function renderImpactJson(report, printer = getPrinter()) {
|
|
59
|
+
const { result, ...rest } = report;
|
|
60
|
+
lines(
|
|
61
|
+
printer,
|
|
62
|
+
JSON.stringify(
|
|
63
|
+
{ ...rest, radius: result.radius, tests: result.tests },
|
|
64
|
+
null,
|
|
65
|
+
2
|
|
66
|
+
)
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
function renderImpact(report, printer = getPrinter()) {
|
|
70
|
+
const { radius, tests } = report.result;
|
|
71
|
+
lines(
|
|
72
|
+
printer,
|
|
73
|
+
"",
|
|
74
|
+
`Base ref: ${shortRef(report.baseRef)}${report.baseLabel === report.baseRef ? "" : ` (${report.baseLabel})`}`,
|
|
75
|
+
`Workspace: ${report.packagesFound === 0 ? "no workspace packages found" : plural(report.packagesFound, "package")}`,
|
|
76
|
+
"",
|
|
77
|
+
`You changed ${plural(radius.changed.length, "file")}.`
|
|
78
|
+
);
|
|
79
|
+
for (const impact of radius.changed.slice(0, MAX_LISTED_FILES)) {
|
|
80
|
+
const symbols = impact.impactedSymbols.length > 0 ? ` (${impact.impactedSymbols.join(", ")})` : "";
|
|
81
|
+
lines(
|
|
82
|
+
printer,
|
|
83
|
+
` ${classificationLabel(impact.classification)} ${impact.filePath}${symbols}`
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
if (radius.changed.length > MAX_LISTED_FILES) {
|
|
87
|
+
lines(
|
|
88
|
+
printer,
|
|
89
|
+
` \u2026 and ${count(radius.changed.length - MAX_LISTED_FILES)} more`
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
const packages = radius.affectedPackages.length > 0 ? `, ${plural(radius.affectedPackages.length, "package")} (${radius.affectedPackages.join(", ")})` : "";
|
|
93
|
+
lines(
|
|
94
|
+
printer,
|
|
95
|
+
"",
|
|
96
|
+
`Impact: ${plural(radius.affectedFiles.length, "file")}${packages}`
|
|
97
|
+
);
|
|
98
|
+
const skipped = tests.totalTests - tests.affectedTests.length;
|
|
99
|
+
lines(
|
|
100
|
+
printer,
|
|
101
|
+
"",
|
|
102
|
+
`Run: ${plural(tests.affectedTests.length, "test file")}`,
|
|
103
|
+
`Skip: ${plural(skipped, "test file")} (of ${count(tests.totalTests)} total)`
|
|
104
|
+
);
|
|
105
|
+
if (tests.unreached.length > 0) {
|
|
106
|
+
const listed = tests.unreached.slice(0, MAX_LISTED_FILES).join(", ");
|
|
107
|
+
const more = tests.unreached.length > MAX_LISTED_FILES ? `, \u2026 ${count(tests.unreached.length - MAX_LISTED_FILES)} more` : "";
|
|
108
|
+
const one = tests.unreached.length === 1;
|
|
109
|
+
lines(
|
|
110
|
+
printer,
|
|
111
|
+
"",
|
|
112
|
+
`${getColors().yellow("Unreached:")} ${plural(tests.unreached.length, "changed file")} no test reaches (${listed}${more}). No test is selected for ${one ? "it: it is" : "them: they are"} untested, or used in a way variant cannot follow.`
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
if (tests.unselectedTests.length > 0) {
|
|
116
|
+
const listed = tests.unselectedTests.slice(0, MAX_LISTED_FILES).join(", ");
|
|
117
|
+
const more = tests.unselectedTests.length > MAX_LISTED_FILES ? `, \u2026 ${count(tests.unselectedTests.length - MAX_LISTED_FILES)} more` : "";
|
|
118
|
+
const one = tests.unselectedTests.length === 1;
|
|
119
|
+
lines(
|
|
120
|
+
printer,
|
|
121
|
+
"",
|
|
122
|
+
`${getColors().yellow("Not selected:")} ${plural(tests.unselectedTests.length, "changed test file")} ${one ? "is" : "are"} JavaScript (${listed}${more}). variant does not index JavaScript tests, so it cannot select them; run them yourself.`
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
const nothingAnalyzed = !tests.selectAll && radius.changed.length > 0 && radius.changed.every((impact) => impact.classification === "unanalyzed");
|
|
126
|
+
if (nothingAnalyzed) {
|
|
127
|
+
lines(
|
|
128
|
+
printer,
|
|
129
|
+
"",
|
|
130
|
+
"Nothing in this change was analyzed: none of the changed files is TypeScript that variant indexes."
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
lines(
|
|
134
|
+
printer,
|
|
135
|
+
"",
|
|
136
|
+
`Verdict: ${verdictText(report.verdict)}`,
|
|
137
|
+
`Confidence: ${tests.resolution} (${Math.round(tests.confidence * 100)}%) (report-only \u2014 run the full suite; skipping unlocks after shadow-mode validation)`
|
|
138
|
+
);
|
|
139
|
+
const notes = [...radius.notes, ...tests.notes];
|
|
140
|
+
if (notes.length > 0) {
|
|
141
|
+
lines(printer, "", "Notes:");
|
|
142
|
+
for (const note of notes) lines(printer, ` - ${note}`);
|
|
143
|
+
}
|
|
144
|
+
const standing = [...radius.repositoryNotes, ...tests.repositoryNotes];
|
|
145
|
+
if (standing.length > 0 && printer.mode === "verbose") {
|
|
146
|
+
lines(printer, "", "Repository (the same whatever changed):");
|
|
147
|
+
for (const note of standing) lines(printer, ` - ${note}`);
|
|
148
|
+
} else if (standing.length > 0) {
|
|
149
|
+
lines(
|
|
150
|
+
printer,
|
|
151
|
+
"",
|
|
152
|
+
`Repository: ${plural(standing.length, "standing note")}, the same whatever changed (-v lists them)`
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
if (!report.historyLogged) {
|
|
156
|
+
lines(
|
|
157
|
+
printer,
|
|
158
|
+
"",
|
|
159
|
+
"(warning: could not write .variant/history/impact.jsonl \u2014 shadow-mode logging skipped)"
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
function renderImpactVerifyJson(result, printer = getPrinter()) {
|
|
164
|
+
const { prediction, ...rest } = result;
|
|
165
|
+
lines(
|
|
166
|
+
printer,
|
|
167
|
+
JSON.stringify(
|
|
168
|
+
{ ...rest, predictedAt: prediction.at, baseRef: prediction.baseRef },
|
|
169
|
+
null,
|
|
170
|
+
2
|
|
171
|
+
)
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
function renderImpactVerify(result, printer = getPrinter()) {
|
|
175
|
+
const { prediction } = result;
|
|
176
|
+
lines(
|
|
177
|
+
printer,
|
|
178
|
+
"",
|
|
179
|
+
`Prediction: ${prediction.at} (${prediction.headSha ?? "no commit recorded"})`,
|
|
180
|
+
`Matched by: ${result.matchedBy === "head-sha" ? "head SHA" : "most recent \u2014 verify this is the right run"}`,
|
|
181
|
+
"",
|
|
182
|
+
`Predicted: ${count(prediction.affectedTests.length)} of ${count(prediction.totalTests)} test files${prediction.selectAll ? " (selected all)" : ""}`,
|
|
183
|
+
`Ran: ${plural(result.ranTests, "test file")}, ${count(result.predictedRan)} of them predicted`,
|
|
184
|
+
`Failed: ${plural(result.failedTests.length, "test file")}`
|
|
185
|
+
);
|
|
186
|
+
if (result.failedTests.length === 0) {
|
|
187
|
+
lines(
|
|
188
|
+
printer,
|
|
189
|
+
"",
|
|
190
|
+
"No failures in this run, so it neither confirms nor refutes the prediction."
|
|
191
|
+
);
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
lines(
|
|
195
|
+
printer,
|
|
196
|
+
"",
|
|
197
|
+
`Caught: ${count(result.caught.length)} (inside the predicted set)`,
|
|
198
|
+
`False skips: ${count(result.falseSkips.length)} (would have been missed)`
|
|
199
|
+
);
|
|
200
|
+
if (result.falseSkips.length > 0) {
|
|
201
|
+
lines(printer, "", "False skips:");
|
|
202
|
+
for (const test of result.falseSkips.slice(0, MAX_LISTED_FILES)) {
|
|
203
|
+
lines(printer, ` ${test}`);
|
|
204
|
+
}
|
|
205
|
+
if (result.falseSkips.length > MAX_LISTED_FILES) {
|
|
206
|
+
lines(
|
|
207
|
+
printer,
|
|
208
|
+
` \u2026 and ${count(result.falseSkips.length - MAX_LISTED_FILES)} more`
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
lines(
|
|
213
|
+
printer,
|
|
214
|
+
"",
|
|
215
|
+
`False-skip rate this run: ${(result.falseSkipRate * 100).toFixed(1)}%`,
|
|
216
|
+
"One run is not a rate. Reconcile many before reading anything into it."
|
|
217
|
+
);
|
|
218
|
+
if (!result.historyLogged) {
|
|
219
|
+
lines(
|
|
220
|
+
printer,
|
|
221
|
+
"",
|
|
222
|
+
"(warning: could not write .variant/history/reconciliation.jsonl)"
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// src/cli/commands/impact.ts
|
|
228
|
+
async function registerImpactAction(opts = {}) {
|
|
229
|
+
let report;
|
|
230
|
+
try {
|
|
231
|
+
report = await predictImpact(process.cwd(), opts);
|
|
232
|
+
} catch (error) {
|
|
233
|
+
if (!(error instanceof NoBaseCommitError)) throw error;
|
|
234
|
+
renderNoBaseCommit(error.message, opts.json === true);
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
if (opts.json === true) {
|
|
238
|
+
renderImpactJson(report);
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
renderImpact(report);
|
|
242
|
+
}
|
|
243
|
+
async function registerImpactVerifyAction(reportPaths, opts = {}) {
|
|
244
|
+
const cwd = process.cwd();
|
|
245
|
+
const detected = opts.headSha === void 0 ? await detectHeadSha(changeBaseDeps(cwd)) : void 0;
|
|
246
|
+
const headSha = opts.headSha ?? detected;
|
|
247
|
+
let result = await verifyImpact(cwd, reportPaths, {
|
|
248
|
+
...headSha !== void 0 && { headSha }
|
|
249
|
+
});
|
|
250
|
+
if (result === null && opts.headSha === void 0 && detected !== void 0) {
|
|
251
|
+
result = await verifyImpact(cwd, reportPaths);
|
|
252
|
+
}
|
|
253
|
+
if (result === null) {
|
|
254
|
+
lines(getPrinter(), NO_PREDICTION_MESSAGE);
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
if (opts.json === true) {
|
|
258
|
+
renderImpactVerifyJson(result);
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
renderImpactVerify(result);
|
|
262
|
+
}
|
|
263
|
+
export {
|
|
264
|
+
registerImpactAction,
|
|
265
|
+
registerImpactVerifyAction
|
|
266
|
+
};
|