@blzsky/variant 0.2.0 → 0.2.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 +197 -146
- package/dist/{build-2LO7GD2S.js → build-3DSBMMI3.js} +9 -9
- package/dist/{check-ZTKGGF4M.js → check-SIQJU6Z2.js} +8 -8
- package/dist/{chunk-RGD422OM.js → chunk-26DHEXGS.js} +1 -1
- package/dist/{chunk-LXKLCLL6.js → chunk-43VLELTL.js} +1 -1
- package/dist/{chunk-XUBWCTJZ.js → chunk-6BXSZPHC.js} +18 -0
- package/dist/{chunk-MZZOE7L4.js → chunk-7OPTWU6E.js} +1 -1
- package/dist/{chunk-V22IPJ7A.js → chunk-EISTWXDW.js} +5 -1
- package/dist/{chunk-4LLK2S4R.js → chunk-FA64KWJ2.js} +8 -8
- package/dist/{chunk-LJDDS4RR.js → chunk-FZEXZBXB.js} +16 -2
- package/dist/{chunk-NSNZOH5P.js → chunk-Q7RLUZSN.js} +2 -2
- package/dist/{chunk-ISRF5F3Q.js → chunk-QRPI6TJE.js} +1 -1
- package/dist/{chunk-O4LZKXNZ.js → chunk-RC23JQKI.js} +50 -1
- package/dist/{chunk-VTJ67TT5.js → chunk-TCISS2AS.js} +4 -4
- package/dist/{chunk-RVXUCJYA.js → chunk-VYWPQKMS.js} +7 -0
- package/dist/{chunk-SWPVR2DF.js → chunk-ZH2PQUNL.js} +7 -7
- package/dist/cli.js +30 -26
- package/dist/{diff-GFI6RAEA.js → diff-HSJBZFMC.js} +9 -5
- package/dist/{doctor-GH4RZVEH.js → doctor-B7MHFIYJ.js} +3 -3
- package/dist/{env-QORDD6FQ.js → env-I7JZRWDN.js} +7 -7
- package/dist/{impact-AF453PLK.js → impact-PRZ6HEP5.js} +54 -21
- package/dist/index.js +2 -2
- package/dist/{init-KJIUNGAN.js → init-O2BY3FOY.js} +3 -3
- package/dist/{insight-DZ5NQY6D.js → insight-JQLTGFYB.js} +8 -8
- package/dist/{pr-UFZRZX6S.js → pr-Y724QAHE.js} +19 -6
- package/dist/{run-6PNH4QRA.js → run-C6VAQOVM.js} +9 -9
- package/dist/{symbol-graph-YYUEMZGR.js → symbol-graph-E5GXKDFZ.js} +3 -3
- package/dist/{workspace-X5FUBTY3.js → workspace-HRTFGWKN.js} +4 -4
- package/package.json +3 -3
|
@@ -276,6 +276,7 @@ function inferTypeText(get) {
|
|
|
276
276
|
}
|
|
277
277
|
function significantText(src, tsm) {
|
|
278
278
|
if (src.trim() === "") return "";
|
|
279
|
+
const { SyntaxKind } = tsm.ts;
|
|
279
280
|
const scanner = tsm.ts.createScanner(
|
|
280
281
|
tsm.ts.ScriptTarget.Latest,
|
|
281
282
|
/* skipTrivia */
|
|
@@ -284,13 +285,61 @@ function significantText(src, tsm) {
|
|
|
284
285
|
src
|
|
285
286
|
);
|
|
286
287
|
const parts = [];
|
|
288
|
+
const substitutionBraces = [];
|
|
289
|
+
let previous = SyntaxKind.Unknown;
|
|
287
290
|
let kind = scanner.scan();
|
|
288
|
-
while (kind !==
|
|
291
|
+
while (kind !== SyntaxKind.EndOfFileToken) {
|
|
292
|
+
if (kind === SyntaxKind.CloseBraceToken && substitutionBraces.at(-1) === 0) {
|
|
293
|
+
substitutionBraces.pop();
|
|
294
|
+
kind = scanner.reScanTemplateToken(
|
|
295
|
+
/* isTaggedTemplate */
|
|
296
|
+
false
|
|
297
|
+
);
|
|
298
|
+
} else if (kind === SyntaxKind.OpenBraceToken || kind === SyntaxKind.CloseBraceToken) {
|
|
299
|
+
const depth = substitutionBraces.pop();
|
|
300
|
+
if (depth !== void 0) {
|
|
301
|
+
substitutionBraces.push(
|
|
302
|
+
kind === SyntaxKind.OpenBraceToken ? depth + 1 : depth - 1
|
|
303
|
+
);
|
|
304
|
+
}
|
|
305
|
+
} else if ((kind === SyntaxKind.SlashToken || kind === SyntaxKind.SlashEqualsToken) && !endsOperand(previous, tsm)) {
|
|
306
|
+
kind = scanner.reScanSlashToken();
|
|
307
|
+
}
|
|
308
|
+
if (kind === SyntaxKind.TemplateHead || kind === SyntaxKind.TemplateMiddle) {
|
|
309
|
+
substitutionBraces.push(0);
|
|
310
|
+
}
|
|
289
311
|
parts.push(scanner.getTokenText());
|
|
312
|
+
previous = kind;
|
|
290
313
|
kind = scanner.scan();
|
|
291
314
|
}
|
|
292
315
|
return parts.join(" ");
|
|
293
316
|
}
|
|
317
|
+
function endsOperand(kind, tsm) {
|
|
318
|
+
const { SyntaxKind } = tsm.ts;
|
|
319
|
+
switch (kind) {
|
|
320
|
+
case SyntaxKind.Identifier:
|
|
321
|
+
case SyntaxKind.PrivateIdentifier:
|
|
322
|
+
case SyntaxKind.NumericLiteral:
|
|
323
|
+
case SyntaxKind.BigIntLiteral:
|
|
324
|
+
case SyntaxKind.StringLiteral:
|
|
325
|
+
case SyntaxKind.NoSubstitutionTemplateLiteral:
|
|
326
|
+
case SyntaxKind.TemplateTail:
|
|
327
|
+
case SyntaxKind.RegularExpressionLiteral:
|
|
328
|
+
case SyntaxKind.CloseParenToken:
|
|
329
|
+
case SyntaxKind.CloseBracketToken:
|
|
330
|
+
case SyntaxKind.CloseBraceToken:
|
|
331
|
+
case SyntaxKind.PlusPlusToken:
|
|
332
|
+
case SyntaxKind.MinusMinusToken:
|
|
333
|
+
case SyntaxKind.ThisKeyword:
|
|
334
|
+
case SyntaxKind.SuperKeyword:
|
|
335
|
+
case SyntaxKind.TrueKeyword:
|
|
336
|
+
case SyntaxKind.FalseKeyword:
|
|
337
|
+
case SyntaxKind.NullKeyword:
|
|
338
|
+
return true;
|
|
339
|
+
default:
|
|
340
|
+
return false;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
294
343
|
function normalize(text) {
|
|
295
344
|
return text.replace(/\s+/g, " ").trim();
|
|
296
345
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
GraphError
|
|
3
|
-
} from "./chunk-RVXUCJYA.js";
|
|
4
1
|
import {
|
|
5
2
|
collectExportedSurface
|
|
6
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-RC23JQKI.js";
|
|
4
|
+
import {
|
|
5
|
+
GraphError
|
|
6
|
+
} from "./chunk-VYWPQKMS.js";
|
|
7
7
|
|
|
8
8
|
// src/core/semantic/symbol-graph.ts
|
|
9
9
|
import { createHash } from "crypto";
|
|
@@ -56,6 +56,12 @@ var GraphError = class extends VariantError {
|
|
|
56
56
|
this.hint = "Delete `.variant/graph/` and retry.";
|
|
57
57
|
}
|
|
58
58
|
};
|
|
59
|
+
var GitRefError = class extends VariantError {
|
|
60
|
+
constructor(message) {
|
|
61
|
+
super("GIT_REF_ERROR", message);
|
|
62
|
+
this.hint = "Check the ref with `git rev-parse --verify <ref>`. In CI, check out with `fetch-depth: 0` and pass a remote-tracking ref such as `origin/main`.";
|
|
63
|
+
}
|
|
64
|
+
};
|
|
59
65
|
var ImpactReportError = class extends VariantError {
|
|
60
66
|
constructor(message) {
|
|
61
67
|
super("IMPACT_REPORT_ERROR", `Could not read the test report: ${message}`);
|
|
@@ -76,6 +82,7 @@ export {
|
|
|
76
82
|
TaskExecutionError,
|
|
77
83
|
CacheError,
|
|
78
84
|
GraphError,
|
|
85
|
+
GitRefError,
|
|
79
86
|
ImpactReportError,
|
|
80
87
|
CliUsageError
|
|
81
88
|
};
|
|
@@ -7,29 +7,29 @@ import {
|
|
|
7
7
|
} from "./chunk-V5CTGXMM.js";
|
|
8
8
|
import {
|
|
9
9
|
loadConfig
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-26DHEXGS.js";
|
|
11
11
|
import {
|
|
12
12
|
getColors
|
|
13
13
|
} from "./chunk-YYGCSKIQ.js";
|
|
14
14
|
import {
|
|
15
15
|
changedFilesToPackages,
|
|
16
16
|
getChangedFiles
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-7OPTWU6E.js";
|
|
18
18
|
import {
|
|
19
19
|
computeAffectedPackages,
|
|
20
20
|
loadPackageGraph,
|
|
21
21
|
tasksFromPackageGraph
|
|
22
22
|
} from "./chunk-3E5LBU3O.js";
|
|
23
|
-
import {
|
|
24
|
-
ConfigError,
|
|
25
|
-
CycleError
|
|
26
|
-
} from "./chunk-RVXUCJYA.js";
|
|
27
23
|
import {
|
|
28
24
|
errorLines
|
|
29
25
|
} from "./chunk-6J4XDG44.js";
|
|
30
26
|
import {
|
|
31
27
|
getPrinter
|
|
32
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-EISTWXDW.js";
|
|
29
|
+
import {
|
|
30
|
+
ConfigError,
|
|
31
|
+
CycleError
|
|
32
|
+
} from "./chunk-VYWPQKMS.js";
|
|
33
33
|
|
|
34
34
|
// src/adapters/frameworks/plugin.ts
|
|
35
35
|
var wrapFrameworkAsPlugin = (a) => ({
|
package/dist/cli.js
CHANGED
|
@@ -4,14 +4,14 @@ import {
|
|
|
4
4
|
resolveColorChoice,
|
|
5
5
|
writeGlobalColorChoice
|
|
6
6
|
} from "./chunk-YYGCSKIQ.js";
|
|
7
|
-
import {
|
|
8
|
-
CliUsageError,
|
|
9
|
-
VariantError
|
|
10
|
-
} from "./chunk-RVXUCJYA.js";
|
|
11
7
|
import {
|
|
12
8
|
Printer,
|
|
13
9
|
setGlobalPrinter
|
|
14
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-EISTWXDW.js";
|
|
11
|
+
import {
|
|
12
|
+
CliUsageError,
|
|
13
|
+
VariantError
|
|
14
|
+
} from "./chunk-VYWPQKMS.js";
|
|
15
15
|
|
|
16
16
|
// src/cli/index.ts
|
|
17
17
|
import { readFileSync } from "fs";
|
|
@@ -121,7 +121,7 @@ var program = new Command().name("variant").description(
|
|
|
121
121
|
var impactCmd = program.command("impact").description(
|
|
122
122
|
"Predict which tests a change requires \u2014 report-only; the full suite should still run"
|
|
123
123
|
).option("--base <ref>", "git ref to compare against", "HEAD~1").option("--json", "output the report as JSON").action(async (opts) => {
|
|
124
|
-
const { registerImpactAction } = await import("./impact-
|
|
124
|
+
const { registerImpactAction } = await import("./impact-PRZ6HEP5.js");
|
|
125
125
|
await registerImpactAction({
|
|
126
126
|
base: opts.base,
|
|
127
127
|
...opts.json === true && { json: true }
|
|
@@ -129,26 +129,25 @@ var impactCmd = program.command("impact").description(
|
|
|
129
129
|
});
|
|
130
130
|
impactCmd.command("verify <report>").description(
|
|
131
131
|
"Reconcile a logged prediction against a Vitest/Jest JSON report \u2014 reports false skips"
|
|
132
|
-
).option("--head-sha <sha>", "reconcile the prediction made at this commit").option("--json", "output the reconciliation as JSON").action(
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
);
|
|
132
|
+
).option("--head-sha <sha>", "reconcile the prediction made at this commit").option("--json", "output the reconciliation as JSON").action(async (report, _opts, command) => {
|
|
133
|
+
const { registerImpactVerifyAction } = await import("./impact-PRZ6HEP5.js");
|
|
134
|
+
const opts = command.optsWithGlobals();
|
|
135
|
+
await registerImpactVerifyAction(report, {
|
|
136
|
+
...opts.headSha !== void 0 && { headSha: opts.headSha },
|
|
137
|
+
...opts.json === true && { json: true }
|
|
138
|
+
});
|
|
139
|
+
});
|
|
141
140
|
program.command("diff <file>").description(
|
|
142
141
|
"Classify a TypeScript file change as non-impacting / internal / breaking"
|
|
143
142
|
).option("--base <ref>", "git ref to compare against", "HEAD~1").action(async (file, opts) => {
|
|
144
|
-
const { registerDiffAction } = await import("./diff-
|
|
143
|
+
const { registerDiffAction } = await import("./diff-HSJBZFMC.js");
|
|
145
144
|
await registerDiffAction(file, { base: opts.base });
|
|
146
145
|
});
|
|
147
146
|
var workspaceCmd = program.command("workspace").description("Workspace-level analysis commands");
|
|
148
147
|
workspaceCmd.command("check").description(
|
|
149
148
|
"Detect packages importing dependencies they do not declare (CI gate: exits 1 on violations)"
|
|
150
149
|
).option("--json", "output the result as JSON").action(async (opts) => {
|
|
151
|
-
const { registerWorkspaceCheckAction } = await import("./workspace-
|
|
150
|
+
const { registerWorkspaceCheckAction } = await import("./workspace-HRTFGWKN.js");
|
|
152
151
|
await registerWorkspaceCheckAction({
|
|
153
152
|
...opts.json === true && { json: true }
|
|
154
153
|
});
|
|
@@ -157,12 +156,12 @@ var prCmd = program.command("pr").description("PR-aware analysis commands");
|
|
|
157
156
|
prCmd.command("check").description(
|
|
158
157
|
"Classify all TypeScript changes in this PR and report a build verdict"
|
|
159
158
|
).option("--base <ref>", "base branch or ref for the PR diff", "main").action(async (opts) => {
|
|
160
|
-
const { registerPrCheckAction } = await import("./pr-
|
|
159
|
+
const { registerPrCheckAction } = await import("./pr-Y724QAHE.js");
|
|
161
160
|
await registerPrCheckAction({ base: opts.base });
|
|
162
161
|
});
|
|
163
162
|
prCmd.command("report").description("Render `pr check` as a structured JSON or markdown report").option("--base <ref>", "base branch or ref for the PR diff", "main").option("--markdown", "output a markdown summary instead of JSON").option("--output <file>", "write report to file instead of stdout").action(
|
|
164
163
|
async (opts) => {
|
|
165
|
-
const { registerPrReportAction } = await import("./pr-
|
|
164
|
+
const { registerPrReportAction } = await import("./pr-Y724QAHE.js");
|
|
166
165
|
await registerPrReportAction(opts);
|
|
167
166
|
}
|
|
168
167
|
);
|
|
@@ -171,7 +170,7 @@ program.command("build").description("Run the build task").option("-c, --concurr
|
|
|
171
170
|
"run only packages affected by changes since baseRef (includes cascade dependents)"
|
|
172
171
|
).option("--dry-run", "print the task plan without executing").action(
|
|
173
172
|
async (opts) => {
|
|
174
|
-
const { registerBuildAction } = await import("./build-
|
|
173
|
+
const { registerBuildAction } = await import("./build-3DSBMMI3.js");
|
|
175
174
|
const concurrency = parseConcurrency(opts);
|
|
176
175
|
await registerBuildAction({
|
|
177
176
|
...concurrency !== void 0 && { concurrency },
|
|
@@ -185,7 +184,7 @@ program.command("run <task>").description("Run a named task").option(
|
|
|
185
184
|
"max tasks to run concurrently per DAG level"
|
|
186
185
|
).option("--dry-run", "print the task plan without executing").action(
|
|
187
186
|
async (taskName, opts) => {
|
|
188
|
-
const { registerRunAction } = await import("./run-
|
|
187
|
+
const { registerRunAction } = await import("./run-C6VAQOVM.js");
|
|
189
188
|
const concurrency = parseConcurrency(opts);
|
|
190
189
|
await registerRunAction(taskName, {
|
|
191
190
|
...concurrency !== void 0 && { concurrency },
|
|
@@ -194,27 +193,32 @@ program.command("run <task>").description("Run a named task").option(
|
|
|
194
193
|
}
|
|
195
194
|
);
|
|
196
195
|
program.command("init").description("Scaffold variant.config.ts in the current directory").action(async () => {
|
|
197
|
-
const { registerInitAction } = await import("./init-
|
|
196
|
+
const { registerInitAction } = await import("./init-O2BY3FOY.js");
|
|
198
197
|
await registerInitAction();
|
|
199
198
|
});
|
|
200
199
|
program.command("doctor").description("Validate config and diagnose common issues").action(async () => {
|
|
201
|
-
const { registerDoctorAction } = await import("./doctor-
|
|
200
|
+
const { registerDoctorAction } = await import("./doctor-B7MHFIYJ.js");
|
|
202
201
|
await registerDoctorAction();
|
|
203
202
|
});
|
|
204
203
|
program.command("insight").description("Show task timing and cache hit stats").action(async () => {
|
|
205
|
-
const { registerInsightAction } = await import("./insight-
|
|
204
|
+
const { registerInsightAction } = await import("./insight-JQLTGFYB.js");
|
|
206
205
|
await registerInsightAction();
|
|
207
206
|
});
|
|
208
207
|
program.command("env").description(
|
|
209
208
|
"Show detected environment (runtime, package manager, framework)"
|
|
210
209
|
).action(async () => {
|
|
211
|
-
const { registerEnvAction } = await import("./env-
|
|
210
|
+
const { registerEnvAction } = await import("./env-I7JZRWDN.js");
|
|
212
211
|
await registerEnvAction();
|
|
213
212
|
});
|
|
214
213
|
program.command("check").description("Validate config and task graph (no execution)").action(async () => {
|
|
215
|
-
const { registerCheckAction } = await import("./check-
|
|
214
|
+
const { registerCheckAction } = await import("./check-SIQJU6Z2.js");
|
|
216
215
|
await registerCheckAction();
|
|
217
216
|
});
|
|
217
|
+
for (const stream of [process.stdout, process.stderr]) {
|
|
218
|
+
stream.on("error", (error) => {
|
|
219
|
+
if (error.code !== "EPIPE" && error.code !== "EOF") throw error;
|
|
220
|
+
});
|
|
221
|
+
}
|
|
218
222
|
program.parseAsync(process.argv).catch((err) => {
|
|
219
223
|
if (err instanceof VariantError) {
|
|
220
224
|
renderError(err);
|
|
@@ -2,16 +2,19 @@ import {
|
|
|
2
2
|
DEFAULT_DIFF_BASE_REF,
|
|
3
3
|
classifyFileAgainstRef,
|
|
4
4
|
toWorkspaceRelative
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import
|
|
7
|
-
|
|
5
|
+
} from "./chunk-Q7RLUZSN.js";
|
|
6
|
+
import {
|
|
7
|
+
assertBaseRef
|
|
8
|
+
} from "./chunk-FZEXZBXB.js";
|
|
9
|
+
import "./chunk-6BXSZPHC.js";
|
|
8
10
|
import {
|
|
9
11
|
lines
|
|
10
12
|
} from "./chunk-6J4XDG44.js";
|
|
11
13
|
import {
|
|
12
14
|
getPrinter
|
|
13
|
-
} from "./chunk-
|
|
14
|
-
import "./chunk-
|
|
15
|
+
} from "./chunk-EISTWXDW.js";
|
|
16
|
+
import "./chunk-RC23JQKI.js";
|
|
17
|
+
import "./chunk-VYWPQKMS.js";
|
|
15
18
|
|
|
16
19
|
// src/cli/render/diff.ts
|
|
17
20
|
var CLASS_MEANING = {
|
|
@@ -50,6 +53,7 @@ async function registerDiffAction(filePath, opts = {}) {
|
|
|
50
53
|
const cwd = process.cwd();
|
|
51
54
|
const baseRef = opts.base ?? DEFAULT_DIFF_BASE_REF;
|
|
52
55
|
const relPath = toWorkspaceRelative(cwd, filePath);
|
|
56
|
+
await assertBaseRef(cwd, baseRef);
|
|
53
57
|
renderClassification(
|
|
54
58
|
await classifyFileAgainstRef(cwd, relPath, baseRef),
|
|
55
59
|
baseRef
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
2
|
findVariantConfigPath,
|
|
3
3
|
loadConfig
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-26DHEXGS.js";
|
|
5
5
|
import {
|
|
6
6
|
getColors
|
|
7
7
|
} from "./chunk-YYGCSKIQ.js";
|
|
8
|
-
import "./chunk-RVXUCJYA.js";
|
|
9
8
|
import {
|
|
10
9
|
lines
|
|
11
10
|
} from "./chunk-6J4XDG44.js";
|
|
12
11
|
import {
|
|
13
12
|
getPrinter
|
|
14
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-EISTWXDW.js";
|
|
14
|
+
import "./chunk-VYWPQKMS.js";
|
|
15
15
|
|
|
16
16
|
// src/core/doctor/diagnostics.ts
|
|
17
17
|
import { readdir, stat } from "fs/promises";
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import {
|
|
2
2
|
renderEnv
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-QRPI6TJE.js";
|
|
4
4
|
import {
|
|
5
5
|
createContext
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-ZH2PQUNL.js";
|
|
7
7
|
import "./chunk-V5CTGXMM.js";
|
|
8
|
-
import "./chunk-
|
|
8
|
+
import "./chunk-26DHEXGS.js";
|
|
9
9
|
import "./chunk-YYGCSKIQ.js";
|
|
10
|
-
import "./chunk-
|
|
10
|
+
import "./chunk-7OPTWU6E.js";
|
|
11
11
|
import "./chunk-3E5LBU3O.js";
|
|
12
|
-
import "./chunk-
|
|
13
|
-
import "./chunk-XUBWCTJZ.js";
|
|
12
|
+
import "./chunk-6BXSZPHC.js";
|
|
14
13
|
import "./chunk-6J4XDG44.js";
|
|
15
|
-
import "./chunk-
|
|
14
|
+
import "./chunk-EISTWXDW.js";
|
|
15
|
+
import "./chunk-VYWPQKMS.js";
|
|
16
16
|
|
|
17
17
|
// src/cli/commands/env.ts
|
|
18
18
|
async function registerEnvAction() {
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
} from "./chunk-GDSZFIHM.js";
|
|
4
4
|
import {
|
|
5
5
|
getChangedFiles
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-7OPTWU6E.js";
|
|
7
7
|
import {
|
|
8
8
|
buildImportGraph,
|
|
9
9
|
computeAffectedFiles
|
|
@@ -16,22 +16,20 @@ import {
|
|
|
16
16
|
} from "./chunk-KSHWC2XN.js";
|
|
17
17
|
import {
|
|
18
18
|
updateSymbolGraph
|
|
19
|
-
} from "./chunk-
|
|
20
|
-
import {
|
|
21
|
-
ImpactReportError
|
|
22
|
-
} from "./chunk-RVXUCJYA.js";
|
|
19
|
+
} from "./chunk-TCISS2AS.js";
|
|
23
20
|
import {
|
|
24
21
|
deriveVerdict,
|
|
25
22
|
verdictText
|
|
26
23
|
} from "./chunk-DRMASVYN.js";
|
|
27
24
|
import {
|
|
25
|
+
assertBaseRef,
|
|
28
26
|
createClassifier
|
|
29
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-FZEXZBXB.js";
|
|
30
28
|
import {
|
|
31
29
|
readFileAtRef,
|
|
32
30
|
readFilesAtRef,
|
|
33
31
|
readHeadSha
|
|
34
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-6BXSZPHC.js";
|
|
35
33
|
import {
|
|
36
34
|
classificationLabel,
|
|
37
35
|
plural
|
|
@@ -41,8 +39,12 @@ import {
|
|
|
41
39
|
} from "./chunk-6J4XDG44.js";
|
|
42
40
|
import {
|
|
43
41
|
getPrinter
|
|
44
|
-
} from "./chunk-
|
|
45
|
-
import "./chunk-
|
|
42
|
+
} from "./chunk-EISTWXDW.js";
|
|
43
|
+
import "./chunk-RC23JQKI.js";
|
|
44
|
+
import {
|
|
45
|
+
GitRefError,
|
|
46
|
+
ImpactReportError
|
|
47
|
+
} from "./chunk-VYWPQKMS.js";
|
|
46
48
|
|
|
47
49
|
// src/core/history/impact-log.ts
|
|
48
50
|
import { mkdir, readFile, writeFile } from "fs/promises";
|
|
@@ -293,6 +295,10 @@ function defaultIsTestFile(file) {
|
|
|
293
295
|
return /(^|\/)__tests__\//.test(file) || /\.(test|spec)\.(ts|tsx|mts|cts)$/.test(file);
|
|
294
296
|
}
|
|
295
297
|
var TEST_CONFIG_FILE = /(^|\/)(package\.json|pnpm-lock\.yaml|package-lock\.json|yarn\.lock|tsconfig[^/]*\.json|(vitest|jest|playwright|vite)\.config\.[^/.]+(\.[^/]+)?)$/;
|
|
298
|
+
var TEST_SETUP_FILE = /(^|\/)((vitest|jest)\.setup|setup-?tests|global-?(setup|teardown)|tests?\/setup)\.[cm]?[jt]sx?$/i;
|
|
299
|
+
function invalidatesAllTests(filePath) {
|
|
300
|
+
return TEST_CONFIG_FILE.test(filePath) || TEST_SETUP_FILE.test(filePath);
|
|
301
|
+
}
|
|
296
302
|
function buildTestTrace(graph, options = {}) {
|
|
297
303
|
const isTest = options.isTestFile ?? defaultIsTestFile;
|
|
298
304
|
const closures = /* @__PURE__ */ new Map();
|
|
@@ -322,7 +328,7 @@ function computeTestImpact(radius, graph, options = {}) {
|
|
|
322
328
|
const notes = /* @__PURE__ */ new Set();
|
|
323
329
|
let selectAll = false;
|
|
324
330
|
for (const impact of radius.changed) {
|
|
325
|
-
if (
|
|
331
|
+
if (invalidatesAllTests(impact.filePath)) {
|
|
326
332
|
selectAll = true;
|
|
327
333
|
notes.add(
|
|
328
334
|
`${impact.filePath}: build/test configuration changed \u2014 running all tests`
|
|
@@ -418,6 +424,7 @@ function closureOf(start, graph) {
|
|
|
418
424
|
var DEFAULT_IMPACT_BASE_REF = "HEAD~1";
|
|
419
425
|
async function predictImpact(cwd, options = {}) {
|
|
420
426
|
const baseRef = options.base ?? DEFAULT_IMPACT_BASE_REF;
|
|
427
|
+
if (options.changedFiles === void 0) await assertBaseRef(cwd, baseRef);
|
|
421
428
|
const packageGraph = await loadPackageGraph(cwd).catch(() => void 0);
|
|
422
429
|
const result = await traceTestImpact(cwd, {
|
|
423
430
|
baseRef,
|
|
@@ -427,7 +434,11 @@ async function predictImpact(cwd, options = {}) {
|
|
|
427
434
|
},
|
|
428
435
|
...options.readBefore !== void 0 && { readBefore: options.readBefore }
|
|
429
436
|
});
|
|
430
|
-
if (result === null)
|
|
437
|
+
if (result === null) {
|
|
438
|
+
throw new GitRefError(
|
|
439
|
+
`Could not list the files changed since "${baseRef}"`
|
|
440
|
+
);
|
|
441
|
+
}
|
|
431
442
|
const verdict = deriveVerdict(
|
|
432
443
|
result.radius.changed.map((change) => change.classification),
|
|
433
444
|
{ forceBuild: result.tests.selectAll }
|
|
@@ -451,13 +462,30 @@ async function predictImpact(cwd, options = {}) {
|
|
|
451
462
|
}
|
|
452
463
|
|
|
453
464
|
// src/core/impact/verify.ts
|
|
465
|
+
import { realpathSync } from "fs";
|
|
454
466
|
import { readFile as readFile3 } from "fs/promises";
|
|
455
467
|
import path3 from "path";
|
|
456
|
-
function
|
|
457
|
-
|
|
468
|
+
function realpathOrSelf(target) {
|
|
469
|
+
try {
|
|
470
|
+
return realpathSync.native(target);
|
|
471
|
+
} catch {
|
|
472
|
+
return target;
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
function escapes(relative) {
|
|
476
|
+
return relative === ".." || relative.startsWith(`..${path3.sep}`) || path3.isAbsolute(relative);
|
|
477
|
+
}
|
|
478
|
+
function toRelativePosix(cwd, testPath, realpath) {
|
|
479
|
+
let relative = testPath;
|
|
480
|
+
if (path3.isAbsolute(testPath)) {
|
|
481
|
+
relative = path3.relative(cwd, testPath);
|
|
482
|
+
if (escapes(relative)) {
|
|
483
|
+
relative = path3.relative(realpath(cwd), realpath(testPath));
|
|
484
|
+
}
|
|
485
|
+
}
|
|
458
486
|
return relative.replace(/\\/g, "/");
|
|
459
487
|
}
|
|
460
|
-
function parseFailedTests(cwd, raw) {
|
|
488
|
+
function parseFailedTests(cwd, raw, realpath = realpathOrSelf) {
|
|
461
489
|
let parsed;
|
|
462
490
|
try {
|
|
463
491
|
parsed = JSON.parse(raw);
|
|
@@ -476,7 +504,7 @@ function parseFailedTests(cwd, raw) {
|
|
|
476
504
|
if (typeof entry !== "object" || entry === null) continue;
|
|
477
505
|
const { name, status } = entry;
|
|
478
506
|
if (status !== "failed" || typeof name !== "string") continue;
|
|
479
|
-
failed.push(toRelativePosix(cwd, name));
|
|
507
|
+
failed.push(toRelativePosix(cwd, name, realpath));
|
|
480
508
|
}
|
|
481
509
|
return [...new Set(failed)].sort();
|
|
482
510
|
}
|
|
@@ -507,12 +535,22 @@ function selectPrediction(predictions, headSha) {
|
|
|
507
535
|
const latest = predictions[predictions.length - 1];
|
|
508
536
|
return latest === void 0 ? null : { prediction: latest, matchedBy: "most-recent" };
|
|
509
537
|
}
|
|
538
|
+
async function readReport(cwd, reportPath) {
|
|
539
|
+
try {
|
|
540
|
+
return await readFile3(path3.resolve(cwd, reportPath), "utf8");
|
|
541
|
+
} catch (error) {
|
|
542
|
+
const code = error instanceof Error && "code" in error ? String(error.code) : "";
|
|
543
|
+
throw new ImpactReportError(
|
|
544
|
+
code === "ENOENT" ? `no file at ${reportPath}` : `${reportPath} could not be read${code === "" ? "" : ` (${code})`}`
|
|
545
|
+
);
|
|
546
|
+
}
|
|
547
|
+
}
|
|
510
548
|
async function verifyImpact(cwd, reportPath, options = {}) {
|
|
511
549
|
const historyDir = defaultHistoryDir(cwd);
|
|
512
550
|
const predictions = options.predictions ?? await readImpactPredictions(historyDir);
|
|
513
551
|
const match = selectPrediction(predictions, options.headSha);
|
|
514
552
|
if (match === null) return null;
|
|
515
|
-
const raw = await
|
|
553
|
+
const raw = await readReport(cwd, reportPath);
|
|
516
554
|
const failedTests = parseFailedTests(cwd, raw);
|
|
517
555
|
const { caught, falseSkips, falseSkipRate } = reconcile(
|
|
518
556
|
match.prediction,
|
|
@@ -543,7 +581,6 @@ async function verifyImpact(cwd, reportPath, options = {}) {
|
|
|
543
581
|
var MAX_LISTED_FILES = 20;
|
|
544
582
|
var count = (value) => value.toLocaleString("en-US");
|
|
545
583
|
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.";
|
|
546
|
-
var NO_CHANGED_FILES_MESSAGE = "impact: could not determine changed files (is this a git repository with at least one prior commit?). Pass --base <ref> against a valid ref.";
|
|
547
584
|
function renderImpactJson(report, printer = getPrinter()) {
|
|
548
585
|
const { result, ...rest } = report;
|
|
549
586
|
lines(
|
|
@@ -672,10 +709,6 @@ function renderImpactVerify(result, printer = getPrinter()) {
|
|
|
672
709
|
// src/cli/commands/impact.ts
|
|
673
710
|
async function registerImpactAction(opts = {}) {
|
|
674
711
|
const report = await predictImpact(process.cwd(), opts);
|
|
675
|
-
if (report === null) {
|
|
676
|
-
lines(getPrinter(), NO_CHANGED_FILES_MESSAGE);
|
|
677
|
-
return;
|
|
678
|
-
}
|
|
679
712
|
if (opts.json === true) {
|
|
680
713
|
renderImpactJson(report);
|
|
681
714
|
return;
|
package/dist/index.js
CHANGED
|
@@ -3,14 +3,14 @@ import {
|
|
|
3
3
|
} from "./chunk-V5CTGXMM.js";
|
|
4
4
|
import {
|
|
5
5
|
findVariantConfigPath
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-RVXUCJYA.js";
|
|
6
|
+
} from "./chunk-26DHEXGS.js";
|
|
8
7
|
import {
|
|
9
8
|
lines
|
|
10
9
|
} from "./chunk-6J4XDG44.js";
|
|
11
10
|
import {
|
|
12
11
|
getPrinter
|
|
13
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-EISTWXDW.js";
|
|
13
|
+
import "./chunk-VYWPQKMS.js";
|
|
14
14
|
|
|
15
15
|
// src/cli/commands/init.ts
|
|
16
16
|
import { writeFile } from "fs/promises";
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
import {
|
|
2
2
|
computeInsights,
|
|
3
3
|
readCache
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-43VLELTL.js";
|
|
5
5
|
import {
|
|
6
6
|
renderInsights
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-QRPI6TJE.js";
|
|
8
8
|
import {
|
|
9
9
|
createContext
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-ZH2PQUNL.js";
|
|
11
11
|
import "./chunk-V5CTGXMM.js";
|
|
12
|
-
import "./chunk-
|
|
12
|
+
import "./chunk-26DHEXGS.js";
|
|
13
13
|
import "./chunk-YYGCSKIQ.js";
|
|
14
|
-
import "./chunk-
|
|
14
|
+
import "./chunk-7OPTWU6E.js";
|
|
15
15
|
import "./chunk-3E5LBU3O.js";
|
|
16
|
-
import "./chunk-
|
|
17
|
-
import "./chunk-XUBWCTJZ.js";
|
|
16
|
+
import "./chunk-6BXSZPHC.js";
|
|
18
17
|
import "./chunk-6J4XDG44.js";
|
|
19
|
-
import "./chunk-
|
|
18
|
+
import "./chunk-EISTWXDW.js";
|
|
19
|
+
import "./chunk-VYWPQKMS.js";
|
|
20
20
|
|
|
21
21
|
// src/cli/commands/insight.ts
|
|
22
22
|
async function registerInsightAction() {
|
|
@@ -4,11 +4,13 @@ import {
|
|
|
4
4
|
} from "./chunk-DRMASVYN.js";
|
|
5
5
|
import {
|
|
6
6
|
classifyFileAgainstRef
|
|
7
|
-
} from "./chunk-
|
|
8
|
-
import
|
|
7
|
+
} from "./chunk-Q7RLUZSN.js";
|
|
8
|
+
import {
|
|
9
|
+
assertBaseRef
|
|
10
|
+
} from "./chunk-FZEXZBXB.js";
|
|
9
11
|
import {
|
|
10
12
|
listChangedFilesSinceMergeBase
|
|
11
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-6BXSZPHC.js";
|
|
12
14
|
import {
|
|
13
15
|
classificationLabel
|
|
14
16
|
} from "./chunk-CXNXZLDG.js";
|
|
@@ -17,8 +19,11 @@ import {
|
|
|
17
19
|
} from "./chunk-6J4XDG44.js";
|
|
18
20
|
import {
|
|
19
21
|
getPrinter
|
|
20
|
-
} from "./chunk-
|
|
21
|
-
import "./chunk-
|
|
22
|
+
} from "./chunk-EISTWXDW.js";
|
|
23
|
+
import "./chunk-RC23JQKI.js";
|
|
24
|
+
import {
|
|
25
|
+
GitRefError
|
|
26
|
+
} from "./chunk-VYWPQKMS.js";
|
|
22
27
|
|
|
23
28
|
// src/cli/commands/pr.ts
|
|
24
29
|
import { writeFile } from "fs/promises";
|
|
@@ -27,9 +32,17 @@ import path from "path";
|
|
|
27
32
|
// src/core/pr/check.ts
|
|
28
33
|
var DEFAULT_PR_BASE_REF = "main";
|
|
29
34
|
var TS_FILE = /\.tsx?$/;
|
|
35
|
+
async function listBranchChanges(cwd, baseRef) {
|
|
36
|
+
await assertBaseRef(cwd, baseRef);
|
|
37
|
+
const changed = await listChangedFilesSinceMergeBase(cwd, baseRef);
|
|
38
|
+
if (changed === null) {
|
|
39
|
+
throw new GitRefError(`"${baseRef}" has no merge base with HEAD`);
|
|
40
|
+
}
|
|
41
|
+
return changed;
|
|
42
|
+
}
|
|
30
43
|
async function runPrCheck(cwd, options = {}) {
|
|
31
44
|
const baseRef = options.base ?? DEFAULT_PR_BASE_REF;
|
|
32
|
-
const changed = options.changedFiles ?? await
|
|
45
|
+
const changed = options.changedFiles ?? await listBranchChanges(cwd, baseRef);
|
|
33
46
|
const tsFiles = changed.filter((file) => TS_FILE.test(file));
|
|
34
47
|
const files = [];
|
|
35
48
|
for (const relPath of tsFiles) {
|