@avi2dg/checks 0.26.0 → 0.28.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/CHANGELOG.md +25 -0
- package/README.md +7 -6
- package/dist/data-shape/index.js +428 -0
- package/dist/templates/reference.md +1 -1
- package/docs/configs/commit-messages.md +1 -1
- package/docs/configs/dependency-rules.md +7 -1
- package/docs/configs/effect-rules.md +10 -0
- package/docs/configs/native-settings.md +8 -30
- package/docs/configs/typescript-rules.md +43 -1
- package/docs/design.md +232 -104
- package/docs/gates/checks-advisories.md +128 -0
- package/docs/gates/checks-changelog.md +8 -5
- package/docs/gates/checks-ci-wiring.md +2 -2
- package/docs/gates/checks-comment-gate.md +3 -4
- package/docs/gates/checks-commit-identity.md +3 -3
- package/docs/gates/checks-docs.md +56 -36
- package/docs/gates/checks-exports.md +4 -4
- package/docs/gates/checks-flake.md +3 -3
- package/docs/gates/checks-lint-coverage.md +17 -9
- package/docs/gates/checks-lint.md +9 -4
- package/docs/gates/checks-mutation-compare.md +3 -3
- package/docs/gates/checks-quarantine-clock.md +3 -5
- package/docs/gates/checks-release-notes.md +4 -4
- package/docs/gates/checks-release-report.md +3 -3
- package/docs/gates/checks-repetition.md +2 -1
- package/docs/gates/checks-subsumed-tests.md +3 -3
- package/docs/gates/checks-suppressions-ratchet.md +3 -4
- package/docs/gates/checks-test-layout.md +4 -4
- package/docs/gates/checks-test.md +3 -2
- package/docs/gates/checks-unused.md +4 -4
- package/docs/gates/checks-vendor.md +3 -3
- package/oxlintrc.json +22 -2
- package/package.json +16 -6
- package/src/complexity/exports.ts +8 -16
- package/src/complexity/knip.ts +1 -1
- package/src/core/gates.ts +3 -0
- package/src/core/git.ts +10 -0
- package/src/delivery/ci-wiring.ts +1 -1
- package/src/dependencies/advisories.ts +115 -0
- package/src/dependencies/advisory-rules.ts +206 -0
- package/src/dependencies/cache-root.ts +15 -0
- package/src/dependencies/osv-scanner.ts +176 -0
- package/src/dependencies/vendor.ts +1 -10
- package/src/docs/doc-names.ts +128 -0
- package/src/docs/doc-templates.ts +1 -1
- package/src/docs/docs.ts +17 -14
- package/src/docs/prose-matchers.ts +11 -1
- package/src/quality/lint-coverage.sh +35 -2
- package/src/quality/presets/effect.language-service.json +3 -1
- package/src/testing/mutation-compare.ts +51 -45
- package/src/testing/quarantine-clock.ts +2 -11
- package/src/testing/test-layout.ts +1 -1
- package/ts-reset.d.ts +2 -0
- package/tsconfig.effect.json +3 -0
|
@@ -2,27 +2,43 @@
|
|
|
2
2
|
import { Console, Effect, FileSystem, Schema } from "effect";
|
|
3
3
|
import { runMain, Usage } from "../core/main.ts";
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
const PositionSchema = Schema.Struct({ line: Schema.Finite, column: Schema.Finite });
|
|
6
|
+
const LocationSchema = Schema.Struct({ start: PositionSchema, end: PositionSchema });
|
|
7
|
+
|
|
8
|
+
export type Location = typeof LocationSchema.Type;
|
|
9
|
+
|
|
10
|
+
const MutantStatusSchema = Schema.Literals([
|
|
11
|
+
"Killed",
|
|
12
|
+
"Survived",
|
|
13
|
+
"Timeout",
|
|
14
|
+
"NoCoverage",
|
|
15
|
+
"Ignored",
|
|
16
|
+
"CompileError",
|
|
17
|
+
"RuntimeError",
|
|
18
|
+
"Pending",
|
|
19
|
+
]);
|
|
20
|
+
|
|
21
|
+
export type MutantStatus = typeof MutantStatusSchema.Type;
|
|
22
|
+
|
|
23
|
+
const MutantSchema = Schema.Struct({
|
|
24
|
+
status: MutantStatusSchema,
|
|
25
|
+
mutatorName: Schema.String,
|
|
26
|
+
replacement: Schema.String,
|
|
27
|
+
killedBy: Schema.optionalKey(Schema.Array(Schema.String)),
|
|
28
|
+
location: LocationSchema,
|
|
29
|
+
});
|
|
9
30
|
|
|
10
|
-
export type Mutant =
|
|
11
|
-
readonly status: string;
|
|
12
|
-
readonly mutatorName: string;
|
|
13
|
-
readonly replacement: string;
|
|
14
|
-
readonly killedBy?: readonly string[];
|
|
15
|
-
readonly location: Location;
|
|
16
|
-
};
|
|
31
|
+
export type Mutant = typeof MutantSchema.Type;
|
|
17
32
|
|
|
18
|
-
|
|
19
|
-
readonly source: string;
|
|
20
|
-
readonly mutants: readonly Mutant[];
|
|
21
|
-
};
|
|
33
|
+
const ReportFileSchema = Schema.Struct({ source: Schema.String, mutants: Schema.Array(MutantSchema) });
|
|
22
34
|
|
|
23
|
-
export type
|
|
24
|
-
|
|
25
|
-
|
|
35
|
+
export type ReportFile = typeof ReportFileSchema.Type;
|
|
36
|
+
|
|
37
|
+
const TestFileSchema = Schema.Struct({
|
|
38
|
+
tests: Schema.Array(Schema.Struct({ id: Schema.String, name: Schema.String })),
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
export type TestFile = typeof TestFileSchema.Type;
|
|
26
42
|
|
|
27
43
|
export type KillRun = {
|
|
28
44
|
readonly files: ReadonlyMap<string, ReportFile>;
|
|
@@ -35,8 +51,8 @@ export type MutantChange = {
|
|
|
35
51
|
readonly location: Location;
|
|
36
52
|
readonly mutatorName: string;
|
|
37
53
|
readonly replacement: string;
|
|
38
|
-
readonly from:
|
|
39
|
-
readonly to:
|
|
54
|
+
readonly from: MutantStatus;
|
|
55
|
+
readonly to: MutantStatus;
|
|
40
56
|
};
|
|
41
57
|
|
|
42
58
|
export type UnmatchedMutant = {
|
|
@@ -44,7 +60,7 @@ export type UnmatchedMutant = {
|
|
|
44
60
|
readonly location: Location;
|
|
45
61
|
readonly mutatorName: string;
|
|
46
62
|
readonly replacement: string;
|
|
47
|
-
readonly status:
|
|
63
|
+
readonly status: MutantStatus;
|
|
48
64
|
};
|
|
49
65
|
|
|
50
66
|
export type Comparison = {
|
|
@@ -65,35 +81,25 @@ export class ReportError extends Schema.TaggedError<ReportError>()("ReportError"
|
|
|
65
81
|
message: Schema.String,
|
|
66
82
|
}) {}
|
|
67
83
|
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
84
|
+
const OUTCOME = {
|
|
85
|
+
Killed: "detected",
|
|
86
|
+
Timeout: "detected",
|
|
87
|
+
Survived: "undetected",
|
|
88
|
+
NoCoverage: "undetected",
|
|
89
|
+
CompileError: "leaves-score",
|
|
90
|
+
RuntimeError: "leaves-score",
|
|
91
|
+
Ignored: "leaves-score",
|
|
92
|
+
Pending: "leaves-score",
|
|
93
|
+
} as const satisfies Record<MutantStatus, "detected" | "undetected" | "leaves-score">;
|
|
71
94
|
const USAGE = "usage: mutation-compare.ts [--advisory] <base-report> <head-report>";
|
|
72
95
|
|
|
73
|
-
const Files = Schema.Record(
|
|
74
|
-
Schema.String,
|
|
75
|
-
Schema.Struct({
|
|
76
|
-
source: Schema.String,
|
|
77
|
-
mutants: Schema.Array(
|
|
78
|
-
Schema.Struct({
|
|
79
|
-
status: Schema.String,
|
|
80
|
-
mutatorName: Schema.String,
|
|
81
|
-
replacement: Schema.String,
|
|
82
|
-
killedBy: Schema.optionalKey(Schema.Array(Schema.String)),
|
|
83
|
-
location: Schema.Struct({
|
|
84
|
-
start: Schema.Struct({ line: Schema.Finite, column: Schema.Finite }),
|
|
85
|
-
end: Schema.Struct({ line: Schema.Finite, column: Schema.Finite }),
|
|
86
|
-
}),
|
|
87
|
-
}),
|
|
88
|
-
),
|
|
89
|
-
}),
|
|
90
|
-
);
|
|
96
|
+
const Files = Schema.Record(Schema.String, ReportFileSchema);
|
|
91
97
|
const decodeReport = Schema.decodeUnknownEffect(Schema.fromJsonString(Schema.Struct({ files: Files })));
|
|
92
98
|
const decodeKillRun = Schema.decodeUnknownEffect(
|
|
93
99
|
Schema.fromJsonString(
|
|
94
100
|
Schema.Struct({
|
|
95
101
|
files: Files,
|
|
96
|
-
testFiles: Schema.Record(Schema.String,
|
|
102
|
+
testFiles: Schema.Record(Schema.String, TestFileSchema),
|
|
97
103
|
config: Schema.optionalKey(Schema.Struct({ disableBail: Schema.optionalKey(Schema.Boolean) })),
|
|
98
104
|
}),
|
|
99
105
|
),
|
|
@@ -211,9 +217,9 @@ function judgeMatch(path: string, mutant: UnmatchedMutant, counterpart: Unmatche
|
|
|
211
217
|
from: mutant.status,
|
|
212
218
|
to: counterpart.status,
|
|
213
219
|
};
|
|
214
|
-
if (mutant.status !== counterpart.status && (
|
|
220
|
+
if (mutant.status !== counterpart.status && (OUTCOME[mutant.status] === "leaves-score" || OUTCOME[counterpart.status] === "leaves-score")) {
|
|
215
221
|
findings.moves.push(change);
|
|
216
|
-
} else if (
|
|
222
|
+
} else if (OUTCOME[mutant.status] === "detected" && OUTCOME[counterpart.status] === "undetected") {
|
|
217
223
|
findings.regressions.push(change);
|
|
218
224
|
}
|
|
219
225
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
import { Console, Effect, Schema } from "effect";
|
|
3
|
-
import { commitOf, git, isShallowBoundary, refArgs } from "../core/git.ts";
|
|
3
|
+
import { commitOf, git, isShallowBoundary, refArgs, writtenAt } from "../core/git.ts";
|
|
4
4
|
import { runMain } from "../core/main.ts";
|
|
5
5
|
import { TEST_FILE } from "./test-layout.ts";
|
|
6
6
|
|
|
@@ -125,19 +125,10 @@ const entryAt = Effect.fn("entryAt")(function* (root: string, head: string, file
|
|
|
125
125
|
return { file, at: entry.at, day: entry.day };
|
|
126
126
|
});
|
|
127
127
|
|
|
128
|
-
const headAt = Effect.fn("headAt")(function* (root: string, head: string) {
|
|
129
|
-
const shown = yield* git(["show", "-s", "--format=%at %ct", head], root);
|
|
130
|
-
const dates = shown.trim().split(" ").map(Number);
|
|
131
|
-
if (dates.length !== 2 || !dates.every(Number.isInteger)) {
|
|
132
|
-
return yield* new QuarantineError({ message: `cannot read when ${head} was written` });
|
|
133
|
-
}
|
|
134
|
-
return Math.max(...dates);
|
|
135
|
-
});
|
|
136
|
-
|
|
137
128
|
export const runHead = Effect.fn("runHead")(function* (root: string, head: string) {
|
|
138
129
|
const files = yield* filesAt(root, head);
|
|
139
130
|
const entries = yield* Effect.forEach(files, (file) => entryAt(root, head, file));
|
|
140
|
-
return { checked: files.length, overdue: overdueOf(entries, yield*
|
|
131
|
+
return { checked: files.length, overdue: overdueOf(entries, yield* writtenAt(head, root)) } satisfies ClockResult;
|
|
141
132
|
});
|
|
142
133
|
|
|
143
134
|
const clock = Effect.gen(function* () {
|
|
@@ -177,7 +177,7 @@ function callUse(node: Record<string, unknown>): string | undefined {
|
|
|
177
177
|
const callee = node["callee"];
|
|
178
178
|
const calleeName = identifierName(callee);
|
|
179
179
|
if (calleeName !== undefined && BANNED_GLOBAL_CALLS.includes(calleeName)) return `calls ${calleeName}`;
|
|
180
|
-
const argument = Array.isArray(node["arguments"]) ? node["arguments"][0] : undefined;
|
|
180
|
+
const argument: unknown = Array.isArray(node["arguments"]) ? node["arguments"][0] : undefined;
|
|
181
181
|
const specifier = isRecord(argument) ? stringValue(argument["expression"]) : undefined;
|
|
182
182
|
const banned = specifier === undefined ? undefined : bannedModule(specifier);
|
|
183
183
|
if (banned === undefined) return undefined;
|
package/ts-reset.d.ts
ADDED
package/tsconfig.effect.json
CHANGED