headlamp 0.1.9 → 0.1.10
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 +32 -0
- package/dist/cli.cjs +65 -2
- package/dist/cli.cjs.map +3 -3
- package/dist/index.js +65 -2
- package/dist/index.js.map +3 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -69,11 +69,43 @@ npx headlamp --onlyFailures
|
|
|
69
69
|
npx headlamp --changed --onlyFailures
|
|
70
70
|
```
|
|
71
71
|
|
|
72
|
+
## Changed-file selection
|
|
73
|
+
|
|
74
|
+
- `--changed[=mode]` selects tests by files changed in your working tree or branch.
|
|
75
|
+
- Modes:
|
|
76
|
+
- `all` (default when `--changed` is passed without a value): includes staged + unstaged + untracked files.
|
|
77
|
+
- `staged`: only staged changes.
|
|
78
|
+
- `unstaged`: only unstaged + untracked files.
|
|
79
|
+
- `branch`: union of
|
|
80
|
+
- files changed on the current branch relative to the default branch (via merge-base), and
|
|
81
|
+
- your current uncommitted changes (staged, unstaged tracked, and untracked files).
|
|
82
|
+
- Default branch is resolved via `origin/HEAD` when available, falling back to `origin/main` or `origin/master`.
|
|
83
|
+
- Effects:
|
|
84
|
+
- Uses changed production files as seeds to discover related tests by import-graph.
|
|
85
|
+
- Coverage tables prioritize and annotate files related to selection/changed files.
|
|
86
|
+
|
|
87
|
+
Examples:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
# Staged changes only
|
|
91
|
+
npx headlamp --changed=staged
|
|
92
|
+
|
|
93
|
+
# All working tree changes
|
|
94
|
+
npx headlamp --changed
|
|
95
|
+
|
|
96
|
+
# Diff current branch against default branch (merge-base)
|
|
97
|
+
npx headlamp --changed=branch
|
|
98
|
+
|
|
99
|
+
# Combine with coverage
|
|
100
|
+
npx headlamp --coverage --changed=branch
|
|
101
|
+
```
|
|
102
|
+
|
|
72
103
|
## Coverage flags
|
|
73
104
|
|
|
74
105
|
- `--coverage`: enables coverage collection and prints merged coverage output after test execution. Uses your project's Jest/Vitest setup and reads coverage JSON from Jest.
|
|
75
106
|
- Prints a compact per-file table with hotspots and optionally detailed per-file breakdowns.
|
|
76
107
|
- Honors file selection and include/exclude globs when rendering coverage tables.
|
|
108
|
+
- When `--changed` is specified, coverage views factor in those changed files as selection seeds, influencing relevancy ordering and the “changed-related” highlighting.
|
|
77
109
|
- `--coverage.abortOnFailure`: if tests fail, exit immediately with the test exit code and skip coverage printing. Useful in CI when failures should short-circuit.
|
|
78
110
|
- `--coverage.ui=jest|both`:
|
|
79
111
|
- `jest`: write Istanbul text report to `coverage/merged/coverage.txt` only.
|
package/dist/cli.cjs
CHANGED
|
@@ -478,12 +478,12 @@ var init_args = __esm({
|
|
|
478
478
|
rule.eq("--changed", () => step([ActionBuilders.changed("all")])),
|
|
479
479
|
rule.startsWith("--changed=", (value) => {
|
|
480
480
|
const raw = (value.split("=")[1] ?? "").trim().toLowerCase();
|
|
481
|
-
const mode = raw === "staged" ? "staged" : raw === "unstaged" ? "unstaged" : "all";
|
|
481
|
+
const mode = raw === "staged" ? "staged" : raw === "unstaged" ? "unstaged" : raw === "branch" ? "branch" : "all";
|
|
482
482
|
return step([ActionBuilders.changed(mode)]);
|
|
483
483
|
}),
|
|
484
484
|
rule.withLookahead("--changed", (_flag, lookahead) => {
|
|
485
485
|
const raw = String(lookahead).trim().toLowerCase();
|
|
486
|
-
const mode = raw === "staged" ? "staged" : raw === "unstaged" ? "unstaged" : "all";
|
|
486
|
+
const mode = raw === "staged" ? "staged" : raw === "unstaged" ? "unstaged" : raw === "branch" ? "branch" : "all";
|
|
487
487
|
return step([ActionBuilders.changed(mode)], true);
|
|
488
488
|
}),
|
|
489
489
|
rule.withLookahead(
|
|
@@ -5347,6 +5347,52 @@ var program = async () => {
|
|
|
5347
5347
|
return [];
|
|
5348
5348
|
}
|
|
5349
5349
|
};
|
|
5350
|
+
if (mode === "branch") {
|
|
5351
|
+
const resolveDefaultBranch = async () => {
|
|
5352
|
+
const candidates = [];
|
|
5353
|
+
try {
|
|
5354
|
+
const sym = await collect("git", ["symbolic-ref", "refs/remotes/origin/HEAD"]);
|
|
5355
|
+
const headRef = sym.find((ln) => ln.includes("refs/remotes/origin/"));
|
|
5356
|
+
if (headRef) {
|
|
5357
|
+
const m = /refs\/remotes\/(.+)/.exec(headRef);
|
|
5358
|
+
if (m && m[1]) {
|
|
5359
|
+
candidates.push(m[1]);
|
|
5360
|
+
}
|
|
5361
|
+
}
|
|
5362
|
+
} catch {
|
|
5363
|
+
}
|
|
5364
|
+
candidates.push("origin/main", "origin/master");
|
|
5365
|
+
for (const cand of candidates) {
|
|
5366
|
+
const exists = await collect("git", ["rev-parse", "--verify", cand]);
|
|
5367
|
+
if (exists.length > 0) {
|
|
5368
|
+
return cand;
|
|
5369
|
+
}
|
|
5370
|
+
}
|
|
5371
|
+
return void 0;
|
|
5372
|
+
};
|
|
5373
|
+
const defaultBranch = await resolveDefaultBranch();
|
|
5374
|
+
const mergeBase = defaultBranch ? (await collect("git", ["merge-base", "HEAD", defaultBranch]))[0] : void 0;
|
|
5375
|
+
const diffBase = mergeBase ?? "HEAD^";
|
|
5376
|
+
const branchDiff = await collect("git", [
|
|
5377
|
+
"diff",
|
|
5378
|
+
"--name-only",
|
|
5379
|
+
"--diff-filter=ACMRTUXB",
|
|
5380
|
+
diffBase,
|
|
5381
|
+
"HEAD"
|
|
5382
|
+
]);
|
|
5383
|
+
const stagedNow = await collect("git", [
|
|
5384
|
+
"diff",
|
|
5385
|
+
"--name-only",
|
|
5386
|
+
"--diff-filter=ACMRTUXB",
|
|
5387
|
+
"--cached"
|
|
5388
|
+
]);
|
|
5389
|
+
const unstagedNow = await collect("git", ["diff", "--name-only", "--diff-filter=ACMRTUXB"]);
|
|
5390
|
+
const untrackedNow = await collect("git", ["ls-files", "--others", "--exclude-standard"]);
|
|
5391
|
+
const rels2 = Array.from(
|
|
5392
|
+
/* @__PURE__ */ new Set([...branchDiff, ...stagedNow, ...unstagedNow, ...untrackedNow])
|
|
5393
|
+
);
|
|
5394
|
+
return rels2.map((rel) => path10.resolve(cwd, rel).replace(/\\/g, "/")).filter((abs) => !abs.includes("/node_modules/") && !abs.includes("/coverage/"));
|
|
5395
|
+
}
|
|
5350
5396
|
const staged = mode === "staged" || mode === "all" ? await collect("git", ["diff", "--name-only", "--diff-filter=ACMRTUXB", "--cached"]) : [];
|
|
5351
5397
|
const unstagedTracked = mode === "unstaged" || mode === "all" ? await collect("git", ["diff", "--name-only", "--diff-filter=ACMRTUXB"]) : [];
|
|
5352
5398
|
const untracked = mode === "unstaged" || mode === "all" ? await collect("git", ["ls-files", "--others", "--exclude-standard"]) : [];
|
|
@@ -5658,6 +5704,23 @@ var program = async () => {
|
|
|
5658
5704
|
}
|
|
5659
5705
|
if (effectiveJestFiles.length === 0) {
|
|
5660
5706
|
const repoRoot = repoRootForRefinement;
|
|
5707
|
+
if (jestFiles.length === 0) {
|
|
5708
|
+
try {
|
|
5709
|
+
const allAcross = [];
|
|
5710
|
+
for (const cfg of projectConfigs) {
|
|
5711
|
+
const cfgCwd = path10.dirname(cfg);
|
|
5712
|
+
const listed = await discoverJestResilient([...jestDiscoveryArgs, "--config", cfg], {
|
|
5713
|
+
cwd: cfgCwd
|
|
5714
|
+
});
|
|
5715
|
+
allAcross.push(...listed);
|
|
5716
|
+
}
|
|
5717
|
+
const uniqAll = Array.from(new Set(allAcross.map((p) => p.replace(/\\/g, "/"))));
|
|
5718
|
+
if (uniqAll.length > 0) {
|
|
5719
|
+
jestFiles = uniqAll;
|
|
5720
|
+
}
|
|
5721
|
+
} catch {
|
|
5722
|
+
}
|
|
5723
|
+
}
|
|
5661
5724
|
const seeds = prodSelections.map(
|
|
5662
5725
|
(abs) => path10.relative(repoRoot, abs).replace(/\\/g, "/").replace(/\.(m?[tj]sx?)$/i, "")
|
|
5663
5726
|
).flatMap((rel) => {
|