coverage-check 0.2.1 → 0.2.2
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 +9 -5
- package/bin/coverage-check.mjs +4 -0
- package/dist/src/cli.d.mts +1 -0
- package/dist/src/cli.mjs +14 -0
- package/dist/src/commands/check-args.d.mts +20 -0
- package/dist/src/commands/check-args.mjs +89 -0
- package/dist/src/commands/check.d.mts +4 -0
- package/dist/src/commands/check.mjs +128 -0
- package/dist/src/commands/store-put.d.mts +11 -0
- package/dist/src/commands/store-put.mjs +104 -0
- package/{src/coverage-check.mts → dist/src/coverage-check.d.mts} +1 -9
- package/dist/src/coverage-check.mjs +4 -0
- package/dist/src/diff-parser.d.mts +17 -0
- package/dist/src/diff-parser.mjs +127 -0
- package/dist/src/github-comment.d.mts +9 -0
- package/dist/src/github-comment.mjs +66 -0
- package/dist/src/lcov-merge.d.mts +5 -0
- package/dist/src/lcov-merge.mjs +29 -0
- package/dist/src/lcov-parser.d.mts +8 -0
- package/dist/src/lcov-parser.mjs +44 -0
- package/dist/src/load-artifacts.d.mts +9 -0
- package/dist/src/load-artifacts.mjs +41 -0
- package/dist/src/patch-coverage.d.mts +5 -0
- package/dist/src/patch-coverage.mjs +65 -0
- package/dist/src/report.d.mts +4 -0
- package/dist/src/report.mjs +65 -0
- package/dist/src/rules.d.mts +4 -0
- package/dist/src/rules.mjs +30 -0
- package/dist/src/s3-suite-store.d.mts +28 -0
- package/dist/src/s3-suite-store.mjs +147 -0
- package/dist/src/s3-utils.d.mts +2 -0
- package/dist/src/s3-utils.mjs +14 -0
- package/dist/src/step-summary.d.mts +9 -0
- package/dist/src/step-summary.mjs +70 -0
- package/dist/src/store-factory.d.mts +11 -0
- package/dist/src/store-factory.mjs +23 -0
- package/dist/src/suite-store.d.mts +51 -0
- package/dist/src/suite-store.mjs +154 -0
- package/dist/src/types.d.mts +36 -0
- package/dist/src/types.mjs +1 -0
- package/package.json +19 -5
- package/bin/coverage-check.mts +0 -6
- package/src/cli.mts +0 -15
- package/src/cli.test.mts +0 -45
- package/src/commands/check-args.mts +0 -110
- package/src/commands/check.mts +0 -147
- package/src/commands/check.test.mts +0 -870
- package/src/commands/store-put.mts +0 -115
- package/src/commands/store-put.test.mts +0 -248
- package/src/diff-parser.mts +0 -127
- package/src/diff-parser.test.mts +0 -178
- package/src/github-comment.mts +0 -79
- package/src/github-comment.test.mts +0 -63
- package/src/lcov-merge.mts +0 -34
- package/src/lcov-merge.test.mts +0 -57
- package/src/lcov-parser.mts +0 -46
- package/src/lcov-parser.test.mts +0 -86
- package/src/load-artifacts.mts +0 -42
- package/src/load-artifacts.test.mts +0 -115
- package/src/patch-coverage.mts +0 -82
- package/src/patch-coverage.test.mts +0 -91
- package/src/report.mts +0 -78
- package/src/report.test.mts +0 -142
- package/src/rules.mts +0 -34
- package/src/rules.test.mts +0 -98
- package/src/s3-suite-store.mts +0 -138
- package/src/s3-suite-store.test.mts +0 -308
- package/src/step-summary.mts +0 -89
- package/src/step-summary.test.mts +0 -189
- package/src/store-factory.mts +0 -23
- package/src/store-factory.test.mts +0 -67
- package/src/suite-store.mts +0 -112
- package/src/suite-store.test.mts +0 -209
- package/src/types.mts +0 -43
package/src/suite-store.mts
DELETED
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import { mkdirSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
-
import { join } from "node:path";
|
|
3
|
-
import type { SuiteMeta } from "./types.mts";
|
|
4
|
-
|
|
5
|
-
export function assertSafePathComponent(value: string, label: string): void {
|
|
6
|
-
if (
|
|
7
|
-
typeof value !== "string" ||
|
|
8
|
-
value.length === 0 ||
|
|
9
|
-
value === "." ||
|
|
10
|
-
value === ".." ||
|
|
11
|
-
value.includes("/") ||
|
|
12
|
-
value.includes("\\")
|
|
13
|
-
) {
|
|
14
|
-
throw new Error(`invalid ${label}: ${JSON.stringify(value)}`);
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export type { SuiteMeta };
|
|
19
|
-
|
|
20
|
-
export interface SuiteStore {
|
|
21
|
-
/** Returns all suite names currently in the store. */
|
|
22
|
-
list(): Promise<string[]>;
|
|
23
|
-
/**
|
|
24
|
-
* Returns the merged LCOV bytes for a suite, or null if absent.
|
|
25
|
-
* Resolves by sha if opts.sha is set; otherwise follows the branch pointer
|
|
26
|
-
* (opts.branch, defaulting to "main").
|
|
27
|
-
*/
|
|
28
|
-
get(suite: string, opts?: { sha?: string; branch?: string }): Promise<Buffer | null>;
|
|
29
|
-
/** Stores the merged LCOV bytes for a suite. sha and branch are required. */
|
|
30
|
-
put(
|
|
31
|
-
suite: string,
|
|
32
|
-
lcov: Buffer,
|
|
33
|
-
meta: SuiteMeta & { sha: string; branch: string },
|
|
34
|
-
): Promise<void>;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Filesystem-backed SuiteStore.
|
|
39
|
-
*
|
|
40
|
-
* Layout:
|
|
41
|
-
* <root>/<suite>/sha/<sha>/lcov.info — LCOV payload
|
|
42
|
-
* <root>/<suite>/branch/<branch>/latest.json — { sha, timestamp }
|
|
43
|
-
*
|
|
44
|
-
* Transport is the caller's responsibility (e.g. S3 sync, git orphan branch).
|
|
45
|
-
*/
|
|
46
|
-
export class FileSystemSuiteStore implements SuiteStore {
|
|
47
|
-
private readonly root: string;
|
|
48
|
-
constructor(root: string) {
|
|
49
|
-
this.root = root;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
async list(): Promise<string[]> {
|
|
53
|
-
try {
|
|
54
|
-
return readdirSync(this.root, { withFileTypes: true })
|
|
55
|
-
.filter((e) => e.isDirectory())
|
|
56
|
-
.map((e) => e.name);
|
|
57
|
-
} catch (err) {
|
|
58
|
-
if ((err as NodeJS.ErrnoException).code === "ENOENT") return [];
|
|
59
|
-
throw err;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
async get(suite: string, opts?: { sha?: string; branch?: string }): Promise<Buffer | null> {
|
|
64
|
-
assertSafePathComponent(suite, "suite");
|
|
65
|
-
if (opts?.sha !== undefined) assertSafePathComponent(opts.sha, "sha");
|
|
66
|
-
let sha = opts?.sha;
|
|
67
|
-
if (!sha) {
|
|
68
|
-
const branch = opts?.branch ?? "main";
|
|
69
|
-
assertSafePathComponent(branch, "branch");
|
|
70
|
-
const pointerPath = join(this.root, suite, "branch", branch, "latest.json");
|
|
71
|
-
try {
|
|
72
|
-
const pointer = JSON.parse(readFileSync(pointerPath, "utf8")) as { sha: string };
|
|
73
|
-
assertSafePathComponent(pointer.sha, "sha");
|
|
74
|
-
sha = pointer.sha;
|
|
75
|
-
} catch (err) {
|
|
76
|
-
if ((err as NodeJS.ErrnoException).code === "ENOENT") return null;
|
|
77
|
-
throw err;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
const lcovPath = join(this.root, suite, "sha", sha, "lcov.info");
|
|
81
|
-
try {
|
|
82
|
-
return readFileSync(lcovPath);
|
|
83
|
-
} catch (err) {
|
|
84
|
-
if ((err as NodeJS.ErrnoException).code === "ENOENT") return null;
|
|
85
|
-
throw err;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
async put(
|
|
90
|
-
suite: string,
|
|
91
|
-
lcov: Buffer,
|
|
92
|
-
meta: SuiteMeta & { sha: string; branch: string },
|
|
93
|
-
): Promise<void> {
|
|
94
|
-
assertSafePathComponent(suite, "suite");
|
|
95
|
-
assertSafePathComponent(meta.sha, "sha");
|
|
96
|
-
assertSafePathComponent(meta.branch, "branch");
|
|
97
|
-
const shaDir = join(this.root, suite, "sha", meta.sha);
|
|
98
|
-
mkdirSync(shaDir, { recursive: true });
|
|
99
|
-
writeFileSync(join(shaDir, "lcov.info"), lcov);
|
|
100
|
-
|
|
101
|
-
const branchDir = join(this.root, suite, "branch", meta.branch);
|
|
102
|
-
mkdirSync(branchDir, { recursive: true });
|
|
103
|
-
writeFileSync(
|
|
104
|
-
join(branchDir, "latest.json"),
|
|
105
|
-
JSON.stringify(
|
|
106
|
-
{ sha: meta.sha, timestamp: meta.timestamp ?? new Date().toISOString() },
|
|
107
|
-
null,
|
|
108
|
-
2,
|
|
109
|
-
),
|
|
110
|
-
);
|
|
111
|
-
}
|
|
112
|
-
}
|
package/src/suite-store.test.mts
DELETED
|
@@ -1,209 +0,0 @@
|
|
|
1
|
-
import { mkdtempSync, readFileSync, rmSync } from "node:fs";
|
|
2
|
-
import { join } from "node:path";
|
|
3
|
-
import { tmpdir } from "node:os";
|
|
4
|
-
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
5
|
-
import { assertSafePathComponent, FileSystemSuiteStore } from "./suite-store.mts";
|
|
6
|
-
|
|
7
|
-
describe("FileSystemSuiteStore", () => {
|
|
8
|
-
let tmpDir: string;
|
|
9
|
-
let store: FileSystemSuiteStore;
|
|
10
|
-
|
|
11
|
-
beforeEach(() => {
|
|
12
|
-
tmpDir = mkdtempSync(join(tmpdir(), "suite-store-"));
|
|
13
|
-
store = new FileSystemSuiteStore(tmpDir);
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
afterEach(() => {
|
|
17
|
-
rmSync(tmpDir, { recursive: true, force: true });
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
describe("list()", () => {
|
|
21
|
-
it("returns empty array when store root does not exist", async () => {
|
|
22
|
-
const missing = new FileSystemSuiteStore(join(tmpDir, "nonexistent"));
|
|
23
|
-
expect(await missing.list()).toEqual([]);
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it("returns empty array for an empty store", async () => {
|
|
27
|
-
expect(await store.list()).toEqual([]);
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
it("returns suite names after putting suites", async () => {
|
|
31
|
-
await store.put("backend", Buffer.from("SF:foo\nend_of_record\n"), {
|
|
32
|
-
sha: "abc",
|
|
33
|
-
branch: "main",
|
|
34
|
-
});
|
|
35
|
-
await store.put("frontend", Buffer.from("SF:bar\nend_of_record\n"), {
|
|
36
|
-
sha: "def",
|
|
37
|
-
branch: "main",
|
|
38
|
-
});
|
|
39
|
-
const suites = await store.list();
|
|
40
|
-
expect(suites).toContain("backend");
|
|
41
|
-
expect(suites).toContain("frontend");
|
|
42
|
-
expect(suites).toHaveLength(2);
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
it("ignores non-directory entries in the root", async () => {
|
|
46
|
-
await store.put("backend", Buffer.from("SF:foo\nend_of_record\n"), {
|
|
47
|
-
sha: "abc",
|
|
48
|
-
branch: "main",
|
|
49
|
-
});
|
|
50
|
-
const suites = await store.list();
|
|
51
|
-
expect(suites).not.toContain("lcov.info");
|
|
52
|
-
expect(suites).not.toContain("meta.json");
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
it("rethrows non-ENOENT errors", async () => {
|
|
56
|
-
const badStore = new FileSystemSuiteStore("\0invalid");
|
|
57
|
-
await expect(badStore.list()).rejects.toThrow();
|
|
58
|
-
});
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
describe("get()", () => {
|
|
62
|
-
it("returns null for a missing suite (no pointer file)", async () => {
|
|
63
|
-
expect(await store.get("nonexistent")).toBeNull();
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
it("returns null when get() is called with explicit sha that has no lcov file", async () => {
|
|
67
|
-
// Pointer exists (from a different sha), but requested sha is absent
|
|
68
|
-
await store.put("backend", Buffer.from("SF:backend/foo.mts\nDA:1,1\nend_of_record\n"), {
|
|
69
|
-
sha: "abc",
|
|
70
|
-
branch: "main",
|
|
71
|
-
});
|
|
72
|
-
expect(await store.get("backend", { sha: "nonexistent-sha" })).toBeNull();
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
it("returns the LCOV buffer after put() via branch pointer", async () => {
|
|
76
|
-
const lcov = Buffer.from("SF:backend/foo.mts\nDA:1,1\nend_of_record\n");
|
|
77
|
-
await store.put("backend", lcov, { sha: "abc123", branch: "main" });
|
|
78
|
-
const result = await store.get("backend");
|
|
79
|
-
expect(result).not.toBeNull();
|
|
80
|
-
expect(result!.toString()).toBe(lcov.toString());
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
it("returns the LCOV buffer when get() is called with explicit sha", async () => {
|
|
84
|
-
const lcov = Buffer.from("SF:backend/foo.mts\nDA:1,1\nend_of_record\n");
|
|
85
|
-
await store.put("backend", lcov, { sha: "abc123", branch: "main" });
|
|
86
|
-
const result = await store.get("backend", { sha: "abc123" });
|
|
87
|
-
expect(result).not.toBeNull();
|
|
88
|
-
expect(result!.toString()).toBe(lcov.toString());
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
it("resolves the correct sha via the branch pointer", async () => {
|
|
92
|
-
const lcovV1 = Buffer.from("SF:backend/v1.mts\nDA:1,1\nend_of_record\n");
|
|
93
|
-
const lcovV2 = Buffer.from("SF:backend/v2.mts\nDA:2,1\nend_of_record\n");
|
|
94
|
-
await store.put("backend", lcovV1, { sha: "sha1", branch: "main" });
|
|
95
|
-
await store.put("backend", lcovV2, { sha: "sha2", branch: "main" });
|
|
96
|
-
// Branch pointer now points to sha2; sha1 still exists on disk
|
|
97
|
-
const result = await store.get("backend", { branch: "main" });
|
|
98
|
-
expect(result!.toString()).toBe(lcovV2.toString());
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
it("rethrows non-ENOENT errors from pointer readFileSync", async () => {
|
|
102
|
-
const badStore = new FileSystemSuiteStore("\0invalid");
|
|
103
|
-
await expect(badStore.get("suite")).rejects.toThrow();
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
it("rethrows non-ENOENT errors from lcov readFileSync when sha is explicit", async () => {
|
|
107
|
-
const badStore = new FileSystemSuiteStore("\0invalid");
|
|
108
|
-
await expect(badStore.get("suite", { sha: "abc" })).rejects.toThrow();
|
|
109
|
-
});
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
describe("put()", () => {
|
|
113
|
-
it("writes lcov.info under sha/ and latest.json under branch/", async () => {
|
|
114
|
-
const lcov = Buffer.from("SF:foo.mts\nDA:1,5\nend_of_record\n");
|
|
115
|
-
await store.put("backend", lcov, { sha: "abc123", branch: "main" });
|
|
116
|
-
|
|
117
|
-
const lcovPath = join(tmpDir, "backend", "sha", "abc123", "lcov.info");
|
|
118
|
-
const pointerPath = join(tmpDir, "backend", "branch", "main", "latest.json");
|
|
119
|
-
expect(readFileSync(lcovPath).toString()).toBe(lcov.toString());
|
|
120
|
-
|
|
121
|
-
const pointer = JSON.parse(readFileSync(pointerPath, "utf8"));
|
|
122
|
-
expect(pointer.sha).toBe("abc123");
|
|
123
|
-
expect(typeof pointer.timestamp).toBe("string");
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
it("uses the provided timestamp", async () => {
|
|
127
|
-
await store.put("backend", Buffer.from(""), {
|
|
128
|
-
sha: "abc",
|
|
129
|
-
branch: "main",
|
|
130
|
-
timestamp: "2026-01-01T00:00:00.000Z",
|
|
131
|
-
});
|
|
132
|
-
const pointer = JSON.parse(
|
|
133
|
-
readFileSync(join(tmpDir, "backend", "branch", "main", "latest.json"), "utf8"),
|
|
134
|
-
);
|
|
135
|
-
expect(pointer.timestamp).toBe("2026-01-01T00:00:00.000Z");
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
it("creates a default timestamp when none is provided", async () => {
|
|
139
|
-
const before = new Date().toISOString();
|
|
140
|
-
await store.put("backend", Buffer.from(""), { sha: "abc", branch: "main" });
|
|
141
|
-
const after = new Date().toISOString();
|
|
142
|
-
const pointer = JSON.parse(
|
|
143
|
-
readFileSync(join(tmpDir, "backend", "branch", "main", "latest.json"), "utf8"),
|
|
144
|
-
);
|
|
145
|
-
expect(pointer.timestamp >= before).toBe(true);
|
|
146
|
-
expect(pointer.timestamp <= after).toBe(true);
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
it("creates parent directories recursively", async () => {
|
|
150
|
-
const nested = new FileSystemSuiteStore(join(tmpDir, "deep", "nested", "store"));
|
|
151
|
-
await nested.put("backend", Buffer.from("SF:foo\nend_of_record\n"), {
|
|
152
|
-
sha: "abc",
|
|
153
|
-
branch: "main",
|
|
154
|
-
});
|
|
155
|
-
expect(await nested.list()).toContain("backend");
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
it("overwrites an existing suite when same sha is used", async () => {
|
|
159
|
-
await store.put("backend", Buffer.from("v1"), { sha: "abc", branch: "main" });
|
|
160
|
-
await store.put("backend", Buffer.from("v2"), { sha: "abc", branch: "main" });
|
|
161
|
-
const result = await store.get("backend", { sha: "abc" });
|
|
162
|
-
expect(result!.toString()).toBe("v2");
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
it("keeps multiple sha entries independently", async () => {
|
|
166
|
-
await store.put("backend", Buffer.from("v1"), { sha: "sha1", branch: "main" });
|
|
167
|
-
await store.put("backend", Buffer.from("v2"), { sha: "sha2", branch: "main" });
|
|
168
|
-
expect((await store.get("backend", { sha: "sha1" }))!.toString()).toBe("v1");
|
|
169
|
-
expect((await store.get("backend", { sha: "sha2" }))!.toString()).toBe("v2");
|
|
170
|
-
});
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
describe("path traversal protection", () => {
|
|
174
|
-
const invalid = ["", ".", "..", "a/b", "a\\b"];
|
|
175
|
-
for (const val of invalid) {
|
|
176
|
-
it(`get() rejects suite=${JSON.stringify(val)}`, async () => {
|
|
177
|
-
await expect(store.get(val)).rejects.toThrow("invalid suite");
|
|
178
|
-
});
|
|
179
|
-
it(`get() rejects branch=${JSON.stringify(val)}`, async () => {
|
|
180
|
-
await expect(store.get("backend", { branch: val })).rejects.toThrow("invalid branch");
|
|
181
|
-
});
|
|
182
|
-
it(`get() rejects sha=${JSON.stringify(val)}`, async () => {
|
|
183
|
-
await expect(store.get("backend", { sha: val })).rejects.toThrow("invalid sha");
|
|
184
|
-
});
|
|
185
|
-
it(`put() rejects suite=${JSON.stringify(val)}`, async () => {
|
|
186
|
-
await expect(
|
|
187
|
-
store.put(val, Buffer.from(""), { sha: "abc", branch: "main" }),
|
|
188
|
-
).rejects.toThrow("invalid suite");
|
|
189
|
-
});
|
|
190
|
-
it(`put() rejects sha=${JSON.stringify(val)}`, async () => {
|
|
191
|
-
await expect(
|
|
192
|
-
store.put("backend", Buffer.from(""), { sha: val, branch: "main" }),
|
|
193
|
-
).rejects.toThrow("invalid sha");
|
|
194
|
-
});
|
|
195
|
-
it(`put() rejects branch=${JSON.stringify(val)}`, async () => {
|
|
196
|
-
await expect(
|
|
197
|
-
store.put("backend", Buffer.from(""), { sha: "abc", branch: val }),
|
|
198
|
-
).rejects.toThrow("invalid branch");
|
|
199
|
-
});
|
|
200
|
-
}
|
|
201
|
-
});
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
describe("assertSafePathComponent", () => {
|
|
205
|
-
it("rejects non-string values at runtime (e.g. from JSON.parse)", () => {
|
|
206
|
-
expect(() => assertSafePathComponent(123 as unknown as string, "sha")).toThrow("invalid sha");
|
|
207
|
-
expect(() => assertSafePathComponent(null as unknown as string, "sha")).toThrow("invalid sha");
|
|
208
|
-
});
|
|
209
|
-
});
|
package/src/types.mts
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
export type CoverageRule = {
|
|
2
|
-
paths: string;
|
|
3
|
-
patch_coverage_min: number;
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
export type CoverageRules = {
|
|
7
|
-
rules: CoverageRule[];
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
/** Map from repo-root-relative file path to map of line number → hit count. */
|
|
11
|
-
export type LcovData = Map<string, Map<number, number>>;
|
|
12
|
-
|
|
13
|
-
/** Map from repo-root-relative file path to set of added/modified line numbers. */
|
|
14
|
-
export type DiffLines = Map<string, Set<number>>;
|
|
15
|
-
|
|
16
|
-
export type FileCoverageResult = {
|
|
17
|
-
file: string;
|
|
18
|
-
coverable: number;
|
|
19
|
-
hit: number;
|
|
20
|
-
uncoveredLines: number[];
|
|
21
|
-
rule: string | null;
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
export type BucketResult = {
|
|
25
|
-
rule: string;
|
|
26
|
-
threshold: number;
|
|
27
|
-
coverable: number;
|
|
28
|
-
hit: number;
|
|
29
|
-
files: FileCoverageResult[];
|
|
30
|
-
passed: boolean;
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
export type CoverageCheckResult = {
|
|
34
|
-
buckets: BucketResult[];
|
|
35
|
-
informational: FileCoverageResult[];
|
|
36
|
-
passed: boolean;
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
export type SuiteMeta = {
|
|
40
|
-
sha?: string;
|
|
41
|
-
branch?: string;
|
|
42
|
-
timestamp?: string;
|
|
43
|
-
};
|