@codyswann/lisa 4.81.9 → 4.82.0
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/dist/cli/lisa-test-run-jest-merge.d.ts +11 -0
- package/dist/cli/lisa-test-run-jest-merge.d.ts.map +1 -0
- package/dist/cli/lisa-test-run-jest-merge.js +152 -0
- package/dist/cli/lisa-test-run-jest-merge.js.map +1 -0
- package/dist/cli/lisa-test-run-shard.d.ts +123 -0
- package/dist/cli/lisa-test-run-shard.d.ts.map +1 -0
- package/dist/cli/lisa-test-run-shard.js +333 -0
- package/dist/cli/lisa-test-run-shard.js.map +1 -0
- package/dist/cli/lisa-test-run.d.ts.map +1 -1
- package/dist/cli/lisa-test-run.js +38 -1
- package/dist/cli/lisa-test-run.js.map +1 -1
- package/dist/core/nightly-e2e-guard-behavior-certificate.js +2 -2
- package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
- package/dist/core/upstream-evidence-manifest.js +11 -1
- package/dist/core/upstream-evidence-manifest.js.map +1 -1
- package/package.json +4 -4
- package/plugins/lisa/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-agy/plugin.json +1 -1
- package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-devin/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-devin/.devin-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-devin/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-devin/.devin-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-agy/plugin.json +1 -1
- package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-devin/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-devin/.devin-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-devin/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-devin/.devin-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-agy/plugin.json +1 -1
- package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-devin/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-devin/.devin-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-agy/plugin.json +1 -1
- package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-devin/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-devin/.devin-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-agy/plugin.json +1 -1
- package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-devin/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-devin/.devin-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-agy/plugin.json +1 -1
- package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-devin/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-devin/.devin-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-agy/plugin.json +1 -1
- package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-devin/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-devin/.devin-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-agy/plugin.json +1 -1
- package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-devin/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-devin/.devin-plugin/plugin.json +1 -1
- package/scripts/two-channel-couplings.json +1 -1
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type ShardReceipt } from "./lisa-test-run-shard.js";
|
|
2
|
+
/**
|
|
3
|
+
* Merge every shard's Jest coverage, write the configured reports, and check
|
|
4
|
+
* the project's `coverageThreshold` once over the merged map.
|
|
5
|
+
* @param argv - Payload argv the gate task handed `lisa-test-run`
|
|
6
|
+
* @param receipts - Every shard's receipt, complete and consistent
|
|
7
|
+
* @param cwd - Project directory
|
|
8
|
+
* @returns Process exit code: 0 when every floor holds
|
|
9
|
+
*/
|
|
10
|
+
export declare function mergeJestShards(argv: readonly [string, ...string[]], receipts: readonly ShardReceipt[], cwd?: string): number;
|
|
11
|
+
//# sourceMappingURL=lisa-test-run-jest-merge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lisa-test-run-jest-merge.d.ts","sourceRoot":"","sources":["../../src/cli/lisa-test-run-jest-merge.ts"],"names":[],"mappings":"AAuBA,OAAO,EAKL,KAAK,YAAY,EAClB,MAAM,0BAA0B,CAAC;AA2IlC;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,SAAS,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,EACpC,QAAQ,EAAE,SAAS,YAAY,EAAE,EACjC,GAAG,GAAE,MAAsB,GAC1B,MAAM,CA4CR"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Merge Jest shard coverage and enforce the project floor once (#4479).
|
|
3
|
+
*
|
|
4
|
+
* Jest has no counterpart to `vitest --merge-reports`, so the merge is done
|
|
5
|
+
* here with the istanbul libraries Jest itself reports through. They are
|
|
6
|
+
* resolved from the project's own Jest install, not bundled with Lisa, so the
|
|
7
|
+
* coverage maps are read and written by the same library versions that
|
|
8
|
+
* produced them.
|
|
9
|
+
*
|
|
10
|
+
* Nothing about the project's coverage configuration is restated. `jest
|
|
11
|
+
* --showConfig` over the very argv the gate task ran resolves
|
|
12
|
+
* `coverageThreshold`, `coverageReporters` and `coverageDirectory` under the
|
|
13
|
+
* same environment — so `LISA_COVERAGE_SCOPE=unit` still selects the unit
|
|
14
|
+
* floor — and the merge writes the reporters the project configured, into the
|
|
15
|
+
* directory it configured, which is where the SonarCloud hand-off looks.
|
|
16
|
+
* @module cli/lisa-test-run-jest-merge
|
|
17
|
+
*/
|
|
18
|
+
import { spawnSync } from "node:child_process";
|
|
19
|
+
import * as fs from "node:fs";
|
|
20
|
+
import { createRequire } from "node:module";
|
|
21
|
+
import * as path from "node:path";
|
|
22
|
+
import { env } from "node:process";
|
|
23
|
+
import { checkJestThresholds, runnerEntry, } from "./lisa-test-run-shard.js";
|
|
24
|
+
/** Largest `--showConfig` document accepted, in bytes. */
|
|
25
|
+
const SHOW_CONFIG_LIMIT = 64 * 1024 * 1024;
|
|
26
|
+
/**
|
|
27
|
+
* Resolve Jest's global coverage configuration for this exact command.
|
|
28
|
+
* @param argv - Payload argv the gate task handed `lisa-test-run`
|
|
29
|
+
* @param cwd - Project directory
|
|
30
|
+
* @returns Resolved coverage configuration
|
|
31
|
+
*/
|
|
32
|
+
function showJestConfig(argv, cwd) {
|
|
33
|
+
const [command, ...args] = argv;
|
|
34
|
+
const shown = spawnSync(command, [...args, "--showConfig"], {
|
|
35
|
+
cwd,
|
|
36
|
+
encoding: "utf8",
|
|
37
|
+
maxBuffer: SHOW_CONFIG_LIMIT,
|
|
38
|
+
});
|
|
39
|
+
if (shown.status !== 0) {
|
|
40
|
+
throw new Error(`jest --showConfig exited ${shown.status ?? shown.signal}: ${shown.stderr}`);
|
|
41
|
+
}
|
|
42
|
+
return JSON.parse(shown.stdout)
|
|
43
|
+
.globalConfig;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* The file a bare command name runs, found on PATH.
|
|
47
|
+
* @param command - Executable name or path
|
|
48
|
+
* @returns Real path of the executable, or undefined
|
|
49
|
+
*/
|
|
50
|
+
function executablePath(command) {
|
|
51
|
+
const candidates = command.includes(path.sep)
|
|
52
|
+
? [command]
|
|
53
|
+
: (env.PATH ?? "")
|
|
54
|
+
.split(path.delimiter)
|
|
55
|
+
.map(directory => path.join(directory, command));
|
|
56
|
+
const found = candidates.find(candidate => fs.existsSync(candidate));
|
|
57
|
+
return found === undefined ? undefined : fs.realpathSync(found);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Resolve one istanbul library from the project, falling back to the copy
|
|
61
|
+
* reachable from the Jest executable the gate task actually runs.
|
|
62
|
+
* @param name - Package name
|
|
63
|
+
* @param bases - Files to resolve from, in order
|
|
64
|
+
* @returns The loaded module
|
|
65
|
+
*/
|
|
66
|
+
function load(name, bases) {
|
|
67
|
+
for (const base of bases) {
|
|
68
|
+
try {
|
|
69
|
+
return createRequire(base)(name);
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
// Next base: package managers that isolate dependencies hoist none.
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
throw new Error(`${name} is not resolvable from the project or its jest install; the shard merge needs the istanbul libraries jest reports with.`);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Every file the istanbul libraries may be resolved from.
|
|
79
|
+
* @param argv - Payload argv
|
|
80
|
+
* @param cwd - Project directory
|
|
81
|
+
* @returns Resolution bases in the order they are tried: the project, then
|
|
82
|
+
* `@jest/reporters` (which depends on istanbul directly) back up to Jest
|
|
83
|
+
*/
|
|
84
|
+
function resolutionBases(argv, cwd) {
|
|
85
|
+
const entry = runnerEntry(argv);
|
|
86
|
+
const jest = entry === undefined ? undefined : executablePath(entry);
|
|
87
|
+
const chain = ["@jest/core", "@jest/reporters"].reduce((resolved, dependency) => {
|
|
88
|
+
const from = resolved.at(-1);
|
|
89
|
+
const next = from === undefined ? undefined : manifestFrom(from, dependency);
|
|
90
|
+
return next === undefined ? resolved : [...resolved, next];
|
|
91
|
+
}, jest === undefined ? [] : [jest]);
|
|
92
|
+
return [path.join(cwd, "package.json"), ...[...chain].reverse()];
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Resolve one package's manifest from a file, or undefined when unreachable.
|
|
96
|
+
* @param from - File to resolve from
|
|
97
|
+
* @param dependency - Package name
|
|
98
|
+
* @returns The manifest path, or undefined
|
|
99
|
+
*/
|
|
100
|
+
function manifestFrom(from, dependency) {
|
|
101
|
+
try {
|
|
102
|
+
return createRequire(from).resolve(`${dependency}/package.json`);
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
return undefined;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Merge every shard's Jest coverage, write the configured reports, and check
|
|
110
|
+
* the project's `coverageThreshold` once over the merged map.
|
|
111
|
+
* @param argv - Payload argv the gate task handed `lisa-test-run`
|
|
112
|
+
* @param receipts - Every shard's receipt, complete and consistent
|
|
113
|
+
* @param cwd - Project directory
|
|
114
|
+
* @returns Process exit code: 0 when every floor holds
|
|
115
|
+
*/
|
|
116
|
+
export function mergeJestShards(argv, receipts, cwd = process.cwd()) {
|
|
117
|
+
// Decided from the RESOLVED config, not the receipts' command-line flag: a
|
|
118
|
+
// project with `collectCoverage: true` collects in every shard without
|
|
119
|
+
// passing --coverage, and its floor must still be enforced here.
|
|
120
|
+
const config = showJestConfig(argv, cwd);
|
|
121
|
+
if (!config.collectCoverage) {
|
|
122
|
+
process.stdout.write("lisa-test-run: the test command collects no coverage, so there is nothing to merge.\n");
|
|
123
|
+
return 0;
|
|
124
|
+
}
|
|
125
|
+
const bases = resolutionBases(argv, cwd);
|
|
126
|
+
const istanbul = {
|
|
127
|
+
coverage: load("istanbul-lib-coverage", bases),
|
|
128
|
+
report: load("istanbul-lib-report", bases),
|
|
129
|
+
reports: load("istanbul-reports", bases),
|
|
130
|
+
};
|
|
131
|
+
const map = istanbul.coverage.createCoverageMap({});
|
|
132
|
+
for (const receipt of receipts) {
|
|
133
|
+
const file = path.join(receipt.directory, "coverage", "coverage-final.json");
|
|
134
|
+
if (!fs.existsSync(file))
|
|
135
|
+
throw new Error(`shard ${receipt.index} left no coverage (${file}).`);
|
|
136
|
+
map.merge(JSON.parse(fs.readFileSync(file, "utf8")));
|
|
137
|
+
}
|
|
138
|
+
const context = istanbul.report.createContext({
|
|
139
|
+
dir: config.coverageDirectory,
|
|
140
|
+
coverageMap: map,
|
|
141
|
+
defaultSummarizer: "nested",
|
|
142
|
+
});
|
|
143
|
+
for (const reporter of config.coverageReporters) {
|
|
144
|
+
const [name, options] = typeof reporter === "string" ? [reporter, {}] : reporter;
|
|
145
|
+
istanbul.reports.create(name, options).execute(context);
|
|
146
|
+
}
|
|
147
|
+
const failures = checkJestThresholds(config.coverageThreshold, map.getCoverageSummary().toJSON());
|
|
148
|
+
for (const failure of failures)
|
|
149
|
+
process.stderr.write(`${failure}\n`);
|
|
150
|
+
return failures.length === 0 ? 0 : 1;
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=lisa-test-run-jest-merge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lisa-test-run-jest-merge.js","sourceRoot":"","sources":["../../src/cli/lisa-test-run-jest-merge.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/** `<index>/<total>` for one shard leg, e.g. `2/4`. */
|
|
2
|
+
export declare const SHARD_ENV = "LISA_TEST_SHARD";
|
|
3
|
+
/** Directory a shard leg writes its receipt and results into. */
|
|
4
|
+
export declare const SHARD_OUTPUT_ENV = "LISA_TEST_SHARD_OUTPUT";
|
|
5
|
+
/** Directory the merge leg downloaded every shard's results into. */
|
|
6
|
+
export declare const SHARD_MERGE_ENV = "LISA_TEST_SHARD_MERGE";
|
|
7
|
+
/** How many shards the merge leg must find. */
|
|
8
|
+
export declare const SHARD_TOTAL_ENV = "LISA_TEST_SHARD_TOTAL";
|
|
9
|
+
/** Every variable above, for stripping before the payload starts. */
|
|
10
|
+
export declare const SHARD_ENV_NAMES: readonly ["LISA_TEST_SHARD", "LISA_TEST_SHARD_OUTPUT", "LISA_TEST_SHARD_MERGE", "LISA_TEST_SHARD_TOTAL"];
|
|
11
|
+
/** File a shard leg leaves in its output directory. */
|
|
12
|
+
export declare const SHARD_RECEIPT = "lisa-shard-receipt.json";
|
|
13
|
+
/** The test runners this wrapper knows how to shard. */
|
|
14
|
+
export type ShardRunner = "jest" | "vitest";
|
|
15
|
+
/** One shard leg. */
|
|
16
|
+
export interface ShardLeg {
|
|
17
|
+
readonly kind: "shard";
|
|
18
|
+
readonly index: number;
|
|
19
|
+
readonly total: number;
|
|
20
|
+
readonly output: string;
|
|
21
|
+
}
|
|
22
|
+
/** The merge leg. */
|
|
23
|
+
export interface ShardMerge {
|
|
24
|
+
readonly kind: "merge";
|
|
25
|
+
readonly directory: string;
|
|
26
|
+
readonly total: number;
|
|
27
|
+
}
|
|
28
|
+
/** What this process was asked to be. */
|
|
29
|
+
export type ShardPlan = {
|
|
30
|
+
readonly kind: "none";
|
|
31
|
+
} | ShardLeg | ShardMerge;
|
|
32
|
+
/** One shard's receipt as read back by the merge. */
|
|
33
|
+
export interface ShardReceipt {
|
|
34
|
+
readonly index: number;
|
|
35
|
+
readonly total: number;
|
|
36
|
+
readonly runner: ShardRunner;
|
|
37
|
+
readonly coverage: boolean;
|
|
38
|
+
/** Directory the receipt was found in — the shard's own results. */
|
|
39
|
+
readonly directory: string;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Decide whether this process is a shard leg, the merge, or neither.
|
|
43
|
+
* @param env - Process environment
|
|
44
|
+
* @returns The plan; `none` when no shard variable is set
|
|
45
|
+
*/
|
|
46
|
+
export declare function shardPlanFrom(env: Readonly<Record<string, string | undefined>>): ShardPlan;
|
|
47
|
+
/**
|
|
48
|
+
* The file a payload argv actually starts: the command itself, or — when the
|
|
49
|
+
* command is `node` — the first argument that is not a Node flag, so
|
|
50
|
+
* `node --max-old-space-size=6144 node_modules/jest/bin/jest.js` names Jest.
|
|
51
|
+
* A flag that takes its value as a separate argument is not special-cased;
|
|
52
|
+
* its value is taken for the entry, names no runner, and is refused loudly.
|
|
53
|
+
* @param argv - Payload argv
|
|
54
|
+
* @returns The entry, or undefined when `node` is given no script
|
|
55
|
+
*/
|
|
56
|
+
export declare function runnerEntry(argv: readonly string[]): string | undefined;
|
|
57
|
+
/**
|
|
58
|
+
* Name the runner a payload argv starts, refusing anything else.
|
|
59
|
+
* @param argv - Payload argv
|
|
60
|
+
* @returns The runner
|
|
61
|
+
*/
|
|
62
|
+
export declare function shardRunnerOf(argv: readonly string[]): ShardRunner;
|
|
63
|
+
/**
|
|
64
|
+
* Rewrite one payload argv into a single shard of itself.
|
|
65
|
+
* @param argv - Payload argv
|
|
66
|
+
* @param runner - Runner the argv starts
|
|
67
|
+
* @param leg - This shard leg
|
|
68
|
+
* @returns The shard's argv
|
|
69
|
+
*/
|
|
70
|
+
export declare function shardArgv(argv: readonly [string, ...string[]], runner: ShardRunner, leg: ShardLeg): [string, ...string[]];
|
|
71
|
+
/**
|
|
72
|
+
* Leave the receipt that proves this leg ran only its slice.
|
|
73
|
+
* @param leg - This shard leg
|
|
74
|
+
* @param runner - Runner the leg starts
|
|
75
|
+
* @param argv - The payload argv before sharding
|
|
76
|
+
*/
|
|
77
|
+
export declare function writeShardReceipt(leg: ShardLeg, runner: ShardRunner, argv: readonly string[]): void;
|
|
78
|
+
/**
|
|
79
|
+
* Read every shard's receipt, refusing an incomplete or inconsistent set.
|
|
80
|
+
* @param directory - Merge directory
|
|
81
|
+
* @param total - Expected shard count
|
|
82
|
+
* @returns Receipts in shard order
|
|
83
|
+
*/
|
|
84
|
+
export declare function readShardReceipts(directory: string, total: number): readonly ShardReceipt[];
|
|
85
|
+
/**
|
|
86
|
+
* Turn the payload argv into Vitest's report merge over the gathered blobs.
|
|
87
|
+
* @param argv - Payload argv
|
|
88
|
+
* @param blobs - Directory holding every shard's blob
|
|
89
|
+
* @returns Merge argv
|
|
90
|
+
*/
|
|
91
|
+
export declare function vitestMergeArgv(argv: readonly [string, ...string[]], blobs: string): [string, ...string[]];
|
|
92
|
+
/**
|
|
93
|
+
* Copy every shard's blob into one flat directory, which is the only layout
|
|
94
|
+
* `vitest --merge-reports` reads.
|
|
95
|
+
* @param receipts - Every shard's receipt
|
|
96
|
+
* @param into - Destination directory
|
|
97
|
+
*/
|
|
98
|
+
export declare function gatherVitestBlobs(receipts: readonly ShardReceipt[], into: string): void;
|
|
99
|
+
/** One coverage metric's totals, as istanbul summarises it. */
|
|
100
|
+
export interface CoverageMetric {
|
|
101
|
+
readonly total: number;
|
|
102
|
+
readonly covered: number;
|
|
103
|
+
readonly pct: number;
|
|
104
|
+
}
|
|
105
|
+
/** Istanbul's summary of a coverage map. */
|
|
106
|
+
export type CoverageSummary = Readonly<Record<"lines" | "statements" | "functions" | "branches", CoverageMetric>>;
|
|
107
|
+
/** A Jest `coverageThreshold` object. */
|
|
108
|
+
export type JestThresholds = Readonly<Record<string, Readonly<Record<string, number>>>>;
|
|
109
|
+
/**
|
|
110
|
+
* Check merged coverage against the project's Jest `coverageThreshold`, with
|
|
111
|
+
* Jest's own semantics and wording: a positive number is a percentage floor, a
|
|
112
|
+
* negative one a ceiling on uncovered entities.
|
|
113
|
+
*
|
|
114
|
+
* Only the `global` key is supported. Path and glob keys select files by
|
|
115
|
+
* Jest's own matching, and reimplementing that here would be a second
|
|
116
|
+
* definition free to drift from the first, so a sharded run refuses them by
|
|
117
|
+
* name instead of approximating them.
|
|
118
|
+
* @param thresholds - Resolved `coverageThreshold`, or undefined
|
|
119
|
+
* @param summary - Merged coverage summary
|
|
120
|
+
* @returns Jest-worded failures; empty when every floor holds
|
|
121
|
+
*/
|
|
122
|
+
export declare function checkJestThresholds(thresholds: JestThresholds | undefined, summary: CoverageSummary): readonly string[];
|
|
123
|
+
//# sourceMappingURL=lisa-test-run-shard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lisa-test-run-shard.d.ts","sourceRoot":"","sources":["../../src/cli/lisa-test-run-shard.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shard and merge planning for `lisa-test-run` (CodySwannGT/lisa#4479).
|
|
3
|
+
*
|
|
4
|
+
* `quality.yml` shards the unit suite by ENVIRONMENT, never by appending
|
|
5
|
+
* arguments to the project's gate task. The task is a package script whose
|
|
6
|
+
* shape Lisa does not know — `bun run test:cov` may reach the runner through
|
|
7
|
+
* two `$npm_execpath run` hops, and npm, yarn and bun each forward trailing
|
|
8
|
+
* arguments differently. The playwright workflow hit exactly that wall and
|
|
9
|
+
* stopped sharding declared tasks altogether. An environment variable survives
|
|
10
|
+
* every hop, and this wrapper is the one place that knows which runner it is
|
|
11
|
+
* about to start, so the runner-specific spelling lives here.
|
|
12
|
+
*
|
|
13
|
+
* A shard leg writes a receipt BEFORE its runner starts. The workflow refuses a
|
|
14
|
+
* leg that left none: a consumer still on a Lisa without this module, or a
|
|
15
|
+
* gate task that bypasses `lisa-test-run`, would otherwise run the WHOLE suite
|
|
16
|
+
* in every leg and report green N times — the sharded run would look healthy
|
|
17
|
+
* while proving nothing about the speed-up it was adopted for.
|
|
18
|
+
*
|
|
19
|
+
* Per-shard coverage floors are switched off, because a shard measures a slice
|
|
20
|
+
* of the suite against the whole source and fails any project-wide floor. The
|
|
21
|
+
* floor is enforced once, by the merge, over the union of every shard. Vitest
|
|
22
|
+
* enforces every threshold form its config declares at that merge; the Jest
|
|
23
|
+
* merge supports the `global` key only and refuses the rest by name.
|
|
24
|
+
* @module cli/lisa-test-run-shard
|
|
25
|
+
*/
|
|
26
|
+
import * as fs from "node:fs";
|
|
27
|
+
import * as path from "node:path";
|
|
28
|
+
/** `<index>/<total>` for one shard leg, e.g. `2/4`. */
|
|
29
|
+
export const SHARD_ENV = "LISA_TEST_SHARD";
|
|
30
|
+
/** Directory a shard leg writes its receipt and results into. */
|
|
31
|
+
export const SHARD_OUTPUT_ENV = "LISA_TEST_SHARD_OUTPUT";
|
|
32
|
+
/** Directory the merge leg downloaded every shard's results into. */
|
|
33
|
+
export const SHARD_MERGE_ENV = "LISA_TEST_SHARD_MERGE";
|
|
34
|
+
/** How many shards the merge leg must find. */
|
|
35
|
+
export const SHARD_TOTAL_ENV = "LISA_TEST_SHARD_TOTAL";
|
|
36
|
+
/** Every variable above, for stripping before the payload starts. */
|
|
37
|
+
export const SHARD_ENV_NAMES = [
|
|
38
|
+
SHARD_ENV,
|
|
39
|
+
SHARD_OUTPUT_ENV,
|
|
40
|
+
SHARD_MERGE_ENV,
|
|
41
|
+
SHARD_TOTAL_ENV,
|
|
42
|
+
];
|
|
43
|
+
/** File a shard leg leaves in its output directory. */
|
|
44
|
+
export const SHARD_RECEIPT = "lisa-shard-receipt.json";
|
|
45
|
+
const WHOLE_NUMBER = /^[1-9]\d*$/;
|
|
46
|
+
/**
|
|
47
|
+
* Read a variable, treating an empty value as unset.
|
|
48
|
+
* @param env - Process environment
|
|
49
|
+
* @param name - Variable name
|
|
50
|
+
* @returns The value, or undefined when unset or empty
|
|
51
|
+
*/
|
|
52
|
+
function setting(env, name) {
|
|
53
|
+
const value = env[name];
|
|
54
|
+
return value === undefined || value === "" ? undefined : value;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Parse one shard leg's `<index>/<total>`.
|
|
58
|
+
* @param value - Raw `LISA_TEST_SHARD`
|
|
59
|
+
* @param output - Raw `LISA_TEST_SHARD_OUTPUT`
|
|
60
|
+
* @returns The shard leg
|
|
61
|
+
*/
|
|
62
|
+
function shardLeg(value, output) {
|
|
63
|
+
const [index, total, ...rest] = value.split("/");
|
|
64
|
+
if (rest.length > 0 ||
|
|
65
|
+
index === undefined ||
|
|
66
|
+
total === undefined ||
|
|
67
|
+
!WHOLE_NUMBER.test(index) ||
|
|
68
|
+
!WHOLE_NUMBER.test(total) ||
|
|
69
|
+
Number(index) > Number(total)) {
|
|
70
|
+
throw new Error(`${SHARD_ENV} is ${JSON.stringify(value)}; it must be <index>/<total> with 1 <= index <= total.`);
|
|
71
|
+
}
|
|
72
|
+
if (output === undefined) {
|
|
73
|
+
throw new Error(`${SHARD_ENV} is set but ${SHARD_OUTPUT_ENV} is not, so this shard has nowhere to leave its receipt.`);
|
|
74
|
+
}
|
|
75
|
+
return { kind: "shard", index: Number(index), total: Number(total), output };
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Decide whether this process is a shard leg, the merge, or neither.
|
|
79
|
+
* @param env - Process environment
|
|
80
|
+
* @returns The plan; `none` when no shard variable is set
|
|
81
|
+
*/
|
|
82
|
+
export function shardPlanFrom(env) {
|
|
83
|
+
const shard = setting(env, SHARD_ENV);
|
|
84
|
+
const merge = setting(env, SHARD_MERGE_ENV);
|
|
85
|
+
if (shard !== undefined && merge !== undefined) {
|
|
86
|
+
throw new Error(`${SHARD_ENV} and ${SHARD_MERGE_ENV} are both set; a run is one shard or the merge, never both.`);
|
|
87
|
+
}
|
|
88
|
+
if (shard !== undefined)
|
|
89
|
+
return shardLeg(shard, setting(env, SHARD_OUTPUT_ENV));
|
|
90
|
+
if (merge === undefined)
|
|
91
|
+
return { kind: "none" };
|
|
92
|
+
const total = env[SHARD_TOTAL_ENV] ?? "";
|
|
93
|
+
if (!WHOLE_NUMBER.test(total)) {
|
|
94
|
+
throw new Error(`${SHARD_TOTAL_ENV} is ${JSON.stringify(total)}; the merge must be told how many shards to expect.`);
|
|
95
|
+
}
|
|
96
|
+
return { kind: "merge", directory: merge, total: Number(total) };
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Whether one argv entry names a runner's executable or entry script.
|
|
100
|
+
* @param entry - argv entry
|
|
101
|
+
* @param runner - Runner name
|
|
102
|
+
* @returns True when the entry starts that runner
|
|
103
|
+
*/
|
|
104
|
+
function names(entry, runner) {
|
|
105
|
+
if (entry === undefined)
|
|
106
|
+
return false;
|
|
107
|
+
const base = path.basename(entry);
|
|
108
|
+
return (base === runner ||
|
|
109
|
+
base === `${runner}.js` ||
|
|
110
|
+
base === `${runner}.mjs` ||
|
|
111
|
+
entry.includes(`node_modules/${runner}/`));
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* The file a payload argv actually starts: the command itself, or — when the
|
|
115
|
+
* command is `node` — the first argument that is not a Node flag, so
|
|
116
|
+
* `node --max-old-space-size=6144 node_modules/jest/bin/jest.js` names Jest.
|
|
117
|
+
* A flag that takes its value as a separate argument is not special-cased;
|
|
118
|
+
* its value is taken for the entry, names no runner, and is refused loudly.
|
|
119
|
+
* @param argv - Payload argv
|
|
120
|
+
* @returns The entry, or undefined when `node` is given no script
|
|
121
|
+
*/
|
|
122
|
+
export function runnerEntry(argv) {
|
|
123
|
+
if (path.basename(argv[0] ?? "") !== "node")
|
|
124
|
+
return argv[0];
|
|
125
|
+
return argv.slice(1).find(arg => !arg.startsWith("-"));
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Name the runner a payload argv starts, refusing anything else.
|
|
129
|
+
* @param argv - Payload argv
|
|
130
|
+
* @returns The runner
|
|
131
|
+
*/
|
|
132
|
+
export function shardRunnerOf(argv) {
|
|
133
|
+
const entry = runnerEntry(argv);
|
|
134
|
+
const runner = ["jest", "vitest"].find(candidate => names(entry, candidate));
|
|
135
|
+
if (runner === undefined) {
|
|
136
|
+
throw new Error(`lisa-test-run cannot shard "${argv.join(" ")}": only jest and vitest commands can be sharded.`);
|
|
137
|
+
}
|
|
138
|
+
return runner;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Whether the payload collects coverage at all.
|
|
142
|
+
* @param argv - Payload argv
|
|
143
|
+
* @returns True when a coverage flag is present
|
|
144
|
+
*/
|
|
145
|
+
function collectsCoverage(argv) {
|
|
146
|
+
return argv.some(arg => arg === "--coverage" ||
|
|
147
|
+
arg === "--coverage=true" ||
|
|
148
|
+
arg === "--collectCoverage" ||
|
|
149
|
+
arg === "--collectCoverage=true");
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Rewrite one payload argv into a single shard of itself.
|
|
153
|
+
* @param argv - Payload argv
|
|
154
|
+
* @param runner - Runner the argv starts
|
|
155
|
+
* @param leg - This shard leg
|
|
156
|
+
* @returns The shard's argv
|
|
157
|
+
*/
|
|
158
|
+
export function shardArgv(argv, runner, leg) {
|
|
159
|
+
const shard = `--shard=${leg.index}/${leg.total}`;
|
|
160
|
+
if (runner === "jest") {
|
|
161
|
+
return [
|
|
162
|
+
...argv,
|
|
163
|
+
shard,
|
|
164
|
+
"--coverageReporters=json",
|
|
165
|
+
"--coverageThreshold={}",
|
|
166
|
+
`--coverageDirectory=${path.join(leg.output, "coverage")}`,
|
|
167
|
+
];
|
|
168
|
+
}
|
|
169
|
+
return [
|
|
170
|
+
...argv,
|
|
171
|
+
shard,
|
|
172
|
+
"--reporter=blob",
|
|
173
|
+
`--outputFile.blob=${path.join(leg.output, `blob-${leg.index}-${leg.total}.json`)}`,
|
|
174
|
+
// Every threshold off, not four zeroed metrics: glob, `perFile` and
|
|
175
|
+
// `100: true` thresholds survive zeroes and fail a partial shard. The
|
|
176
|
+
// merge (`--merge-reports`) still enforces the config's thresholds.
|
|
177
|
+
"--coverage.thresholds=false",
|
|
178
|
+
];
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Leave the receipt that proves this leg ran only its slice.
|
|
182
|
+
* @param leg - This shard leg
|
|
183
|
+
* @param runner - Runner the leg starts
|
|
184
|
+
* @param argv - The payload argv before sharding
|
|
185
|
+
*/
|
|
186
|
+
export function writeShardReceipt(leg, runner, argv) {
|
|
187
|
+
fs.mkdirSync(leg.output, { recursive: true });
|
|
188
|
+
fs.writeFileSync(path.join(leg.output, SHARD_RECEIPT), `${JSON.stringify({
|
|
189
|
+
schema: 1,
|
|
190
|
+
index: leg.index,
|
|
191
|
+
total: leg.total,
|
|
192
|
+
runner,
|
|
193
|
+
coverage: collectsCoverage(argv),
|
|
194
|
+
})}\n`);
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Find every receipt directly in, or one level under, the merge directory —
|
|
198
|
+
* which is where `download-artifact` puts one artifact per subdirectory.
|
|
199
|
+
* @param directory - Merge directory
|
|
200
|
+
* @returns Receipt paths
|
|
201
|
+
*/
|
|
202
|
+
function receiptPaths(directory) {
|
|
203
|
+
const candidates = [
|
|
204
|
+
directory,
|
|
205
|
+
...fs
|
|
206
|
+
.readdirSync(directory, { withFileTypes: true })
|
|
207
|
+
.filter(entry => entry.isDirectory())
|
|
208
|
+
.map(entry => path.join(directory, entry.name)),
|
|
209
|
+
].map(candidate => path.join(candidate, SHARD_RECEIPT));
|
|
210
|
+
return candidates.filter(candidate => fs.existsSync(candidate));
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Read one receipt file.
|
|
214
|
+
* @param file - Receipt path
|
|
215
|
+
* @returns The receipt
|
|
216
|
+
*/
|
|
217
|
+
function readReceipt(file) {
|
|
218
|
+
const raw = JSON.parse(fs.readFileSync(file, "utf8"));
|
|
219
|
+
if (typeof raw.index !== "number" ||
|
|
220
|
+
typeof raw.total !== "number" ||
|
|
221
|
+
(raw.runner !== "jest" && raw.runner !== "vitest") ||
|
|
222
|
+
typeof raw.coverage !== "boolean") {
|
|
223
|
+
throw new Error(`${file} is not a unit-test shard receipt.`);
|
|
224
|
+
}
|
|
225
|
+
return {
|
|
226
|
+
index: raw.index,
|
|
227
|
+
total: raw.total,
|
|
228
|
+
runner: raw.runner,
|
|
229
|
+
coverage: raw.coverage,
|
|
230
|
+
directory: path.dirname(file),
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Refuse a set of receipts that is not exactly shards 1..total of one run.
|
|
235
|
+
* @param receipts - Every receipt found
|
|
236
|
+
* @param total - Expected shard count
|
|
237
|
+
*/
|
|
238
|
+
function assertCompleteShardSet(receipts, total) {
|
|
239
|
+
const foreign = receipts.find(receipt => receipt.total !== total);
|
|
240
|
+
if (foreign !== undefined) {
|
|
241
|
+
throw new Error(`shard ${foreign.index}/${foreign.total} belongs to a different layout; expected ${total} shards.`);
|
|
242
|
+
}
|
|
243
|
+
const indices = receipts.map(receipt => receipt.index);
|
|
244
|
+
const repeated = indices.find((index, position) => indices.indexOf(index) !== position);
|
|
245
|
+
if (repeated !== undefined)
|
|
246
|
+
throw new Error(`shard ${repeated} reported twice.`);
|
|
247
|
+
const seen = new Set(indices);
|
|
248
|
+
const missing = Array.from({ length: total }, (_, i) => i + 1).filter(index => !seen.has(index));
|
|
249
|
+
if (missing.length > 0) {
|
|
250
|
+
throw new Error(`expected ${total} unit-test shards but found ${seen.size}: missing shard ${missing.join(", ")}.`);
|
|
251
|
+
}
|
|
252
|
+
const runners = [...new Set(receipts.map(receipt => receipt.runner))];
|
|
253
|
+
if (runners.length > 1) {
|
|
254
|
+
throw new Error(`the shards ran different test runners (${runners.join(", ")}); they cannot be merged.`);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Read every shard's receipt, refusing an incomplete or inconsistent set.
|
|
259
|
+
* @param directory - Merge directory
|
|
260
|
+
* @param total - Expected shard count
|
|
261
|
+
* @returns Receipts in shard order
|
|
262
|
+
*/
|
|
263
|
+
export function readShardReceipts(directory, total) {
|
|
264
|
+
const receipts = receiptPaths(directory).map(readReceipt);
|
|
265
|
+
assertCompleteShardSet(receipts, total);
|
|
266
|
+
return [...receipts].sort((left, right) => left.index - right.index);
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Turn the payload argv into Vitest's report merge over the gathered blobs.
|
|
270
|
+
* @param argv - Payload argv
|
|
271
|
+
* @param blobs - Directory holding every shard's blob
|
|
272
|
+
* @returns Merge argv
|
|
273
|
+
*/
|
|
274
|
+
export function vitestMergeArgv(argv, blobs) {
|
|
275
|
+
return [...argv, `--merge-reports=${blobs}`];
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Copy every shard's blob into one flat directory, which is the only layout
|
|
279
|
+
* `vitest --merge-reports` reads.
|
|
280
|
+
* @param receipts - Every shard's receipt
|
|
281
|
+
* @param into - Destination directory
|
|
282
|
+
*/
|
|
283
|
+
export function gatherVitestBlobs(receipts, into) {
|
|
284
|
+
fs.mkdirSync(into, { recursive: true });
|
|
285
|
+
for (const receipt of receipts) {
|
|
286
|
+
const blob = `blob-${receipt.index}-${receipt.total}.json`;
|
|
287
|
+
const source = path.join(receipt.directory, blob);
|
|
288
|
+
if (!fs.existsSync(source))
|
|
289
|
+
throw new Error(`shard ${receipt.index} left no vitest blob (${blob}).`);
|
|
290
|
+
fs.copyFileSync(source, path.join(into, blob));
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Check merged coverage against the project's Jest `coverageThreshold`, with
|
|
295
|
+
* Jest's own semantics and wording: a positive number is a percentage floor, a
|
|
296
|
+
* negative one a ceiling on uncovered entities.
|
|
297
|
+
*
|
|
298
|
+
* Only the `global` key is supported. Path and glob keys select files by
|
|
299
|
+
* Jest's own matching, and reimplementing that here would be a second
|
|
300
|
+
* definition free to drift from the first, so a sharded run refuses them by
|
|
301
|
+
* name instead of approximating them.
|
|
302
|
+
* @param thresholds - Resolved `coverageThreshold`, or undefined
|
|
303
|
+
* @param summary - Merged coverage summary
|
|
304
|
+
* @returns Jest-worded failures; empty when every floor holds
|
|
305
|
+
*/
|
|
306
|
+
export function checkJestThresholds(thresholds, summary) {
|
|
307
|
+
const keys = Object.keys(thresholds ?? {});
|
|
308
|
+
const unsupported = keys.find(key => key !== "global");
|
|
309
|
+
if (unsupported !== undefined) {
|
|
310
|
+
throw new Error(`coverageThreshold key ${JSON.stringify(unsupported)} cannot be checked across shards; only "global" thresholds are supported when unit_test_shards > 1.`);
|
|
311
|
+
}
|
|
312
|
+
const global = thresholds?.global ?? {};
|
|
313
|
+
return ["statements", "branches", "lines", "functions"].flatMap(metric => {
|
|
314
|
+
const threshold = global[metric];
|
|
315
|
+
if (threshold === undefined)
|
|
316
|
+
return [];
|
|
317
|
+
const actual = summary[metric];
|
|
318
|
+
if (threshold < 0) {
|
|
319
|
+
const uncovered = actual.total - actual.covered;
|
|
320
|
+
return -threshold < uncovered
|
|
321
|
+
? [
|
|
322
|
+
`Jest: Uncovered count for ${metric} (${uncovered}) exceeds global threshold (${-threshold})`,
|
|
323
|
+
]
|
|
324
|
+
: [];
|
|
325
|
+
}
|
|
326
|
+
return actual.pct < threshold
|
|
327
|
+
? [
|
|
328
|
+
`Jest: "global" coverage threshold for ${metric} (${threshold}%) not met: ${actual.pct}%`,
|
|
329
|
+
]
|
|
330
|
+
: [];
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
//# sourceMappingURL=lisa-test-run-shard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lisa-test-run-shard.js","sourceRoot":"","sources":["../../src/cli/lisa-test-run-shard.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lisa-test-run.d.ts","sourceRoot":"","sources":["../../src/cli/lisa-test-run.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"lisa-test-run.d.ts","sourceRoot":"","sources":["../../src/cli/lisa-test-run.ts"],"names":[],"mappings":";AA6BA,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC"}
|