@stsepelin/checktrail 0.1.0-alpha.3 → 0.1.0-alpha.5
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 +13 -7
- package/dist/src/adapters.js +5 -1
- package/dist/src/architecture.d.ts +1 -1
- package/dist/src/contract-schema.d.ts +1 -1
- package/dist/src/contracts.d.ts +1 -1
- package/dist/src/evidence.js +3 -1
- package/dist/src/finding-policy-schema.d.ts +1 -1
- package/dist/src/go-build.d.ts +27 -0
- package/dist/src/go-build.js +113 -0
- package/dist/src/go-scope-policy.d.ts +11 -0
- package/dist/src/go-scope-policy.js +50 -0
- package/dist/src/go-scope.d.ts +1 -1
- package/dist/src/go-scope.js +42 -5
- package/dist/src/golangci-runner.js +5 -2
- package/dist/src/golangci.js +1 -0
- package/dist/src/output.js +8 -0
- package/dist/src/report-validation.d.ts +11 -0
- package/dist/src/runtime-inventory.d.ts +2 -2
- package/dist/src/schemas.d.ts +28 -0
- package/dist/src/schemas.js +22 -2
- package/dist/src/types.d.ts +7 -1
- package/dist/src/types.js +1 -1
- package/docs/ACCEPTANCE.md +11 -8
- package/docs/CLIENTS.md +6 -4
- package/docs/EXECUTION.md +7 -0
- package/docs/GO-BUILD.md +106 -0
- package/docs/GO-RACE.md +6 -2
- package/docs/GO-SCOPE.md +79 -5
- package/docs/GOLANGCI-LINT.md +5 -2
- package/docs/INSTALLATION.md +5 -4
- package/docs/LANGUAGES.md +11 -2
- package/docs/MCP-COMPATIBILITY.md +6 -0
- package/docs/ONBOARDING.md +3 -2
- package/docs/PUBLIC-ADOPTION.md +9 -5
- package/docs/RELEASE.md +107 -40
- package/docs/SETUP-SCOPES.md +107 -0
- package/docs/STATUS.md +48 -20
- package/docs/TYPESCRIPT.md +2 -2
- package/docs/measurements/go-scope-policy-replay.json +91 -0
- package/docs/measurements/release-alpha3.json +362 -0
- package/docs/measurements/release-alpha4.json +421 -0
- package/package.json +1 -1
- package/schemas/go-build-policy.schema.json +72 -0
- package/schemas/go-scope-policy.schema.json +31 -0
- package/schemas/plan-summary.schema.json +11 -1
- package/schemas/plan.schema.json +51 -0
- package/schemas/report-summary.schema.json +10 -0
- package/schemas/report.schema.json +51 -0
- package/server.json +2 -2
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ Local code validation with a CLI, MCP tools, and evidence of what actually ran.
|
|
|
4
4
|
|
|
5
5
|
Formerly Repo Verifier. See the [rename guide](docs/RENAMING.md) for existing source checkouts.
|
|
6
6
|
|
|
7
|
-
**Published preview: 0.1.0-alpha.
|
|
7
|
+
**Published preview: 0.1.0-alpha.4.** Public source is available at
|
|
8
8
|
[stsepelin/checktrail](https://github.com/stsepelin/checktrail).
|
|
9
9
|
See [implementation status](docs/STATUS.md), the [plan](docs/PLAN.md) and the
|
|
10
10
|
[language matrix](docs/LANGUAGES.md) before relying on an adapter.
|
|
@@ -18,13 +18,16 @@ and MCP configuration generator.
|
|
|
18
18
|
acceptance work; [client checks](docs/CLIENTS.md) record actual application coverage.
|
|
19
19
|
[Public adoption](docs/PUBLIC-ADOPTION.md) records the published package on five
|
|
20
20
|
pinned libraries, including setup friction and compatibility gaps.
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
Alpha.3 fixes the recorded [TypeScript 4.9.5 incompatibility](docs/TYPESCRIPT.md).
|
|
22
|
+
The [setup scope guide](docs/SETUP-SCOPES.md) explains language, documentation and workflow coverage.
|
|
23
|
+
Alpha.4 adds explicit [Go scope exclusions](docs/GO-SCOPE.md) and matching
|
|
24
|
+
race-test package discovery. Its [release record](docs/measurements/release-alpha4.json)
|
|
25
|
+
includes package, client and upgrade/rollback verification.
|
|
26
|
+
|
|
27
|
+
The [hosted matrix](https://github.com/stsepelin/checktrail/actions/runs/35603451711)
|
|
28
|
+
passed at release commit `ebe7f5c` on Linux and macOS. The exact npm tarball and
|
|
26
29
|
fresh CLI/MCP installations were verified. The
|
|
27
|
-
[MCP Registry entry](https://registry.modelcontextprotocol.io/v0.1/servers/io.github.stsepelin%2Fchecktrail/versions/0.1.0-alpha.
|
|
30
|
+
[MCP Registry entry](https://registry.modelcontextprotocol.io/v0.1/servers/io.github.stsepelin%2Fchecktrail/versions/0.1.0-alpha.4)
|
|
28
31
|
is active; execution remains disabled by default.
|
|
29
32
|
|
|
30
33
|
Checktrail discovers projects, plans registered checks, invokes native tools
|
|
@@ -186,6 +189,9 @@ selection with inventoried source; `go.staticcheck` adds explicit all-rule analy
|
|
|
186
189
|
and normalized findings. See [Go scope](docs/GO-SCOPE.md). The constrained
|
|
187
190
|
[`go.golangci-lint` profile](docs/GOLANGCI-LINT.md) accepts explicit native linter
|
|
188
191
|
selection while disabling hidden issue filters and fixes.
|
|
192
|
+
The alpha.5 source candidate adds [Go build-tag profiles](docs/GO-BUILD.md)
|
|
193
|
+
with one explicit configuration per selected native check. Alpha.4 does not
|
|
194
|
+
include this capability; a runnable example is in `examples/go-build`.
|
|
189
195
|
|
|
190
196
|
`php.phpstan` combines per-file analysis accounting with native JSON diagnostics.
|
|
191
197
|
See the [PHPStan contract](docs/PHPSTAN.md).
|
package/dist/src/adapters.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { applyGoBuildPolicy } from "./go-build.js";
|
|
2
|
+
import { applyGoScopePolicy } from "./go-scope-policy.js";
|
|
1
3
|
import { actionlintCheck, workflowRoot } from "./actionlint.js";
|
|
2
4
|
import { clangCheck } from "./clang.js";
|
|
3
5
|
import { javaCheck } from "./java.js";
|
|
@@ -312,7 +314,7 @@ export async function checksFor(source, project, requested) {
|
|
|
312
314
|
...env,
|
|
313
315
|
CGO_ENABLED: "1",
|
|
314
316
|
GORACE: "exitcode=66 log_path=stderr",
|
|
315
|
-
}),
|
|
317
|
+
}, true),
|
|
316
318
|
{
|
|
317
319
|
executable: "go",
|
|
318
320
|
args: ["test", "-race", "-json", "-count=1", "./..."],
|
|
@@ -354,6 +356,8 @@ export async function checksFor(source, project, requested) {
|
|
|
354
356
|
});
|
|
355
357
|
if (explicit)
|
|
356
358
|
checks.push(await golangciCheck(source, project));
|
|
359
|
+
await applyGoScopePolicy(source, project, checks);
|
|
360
|
+
await applyGoBuildPolicy(source, project, checks);
|
|
357
361
|
return checks;
|
|
358
362
|
}
|
|
359
363
|
if (project.adapter === "infrastructure") {
|
|
@@ -78,6 +78,7 @@ export declare const architectureReportSchema: z.ZodObject<{
|
|
|
78
78
|
}, z.core.$strict>;
|
|
79
79
|
export declare const architectureSummarySchema: z.ZodObject<{
|
|
80
80
|
schemaVersion: z.ZodLiteral<1>;
|
|
81
|
+
reason: z.ZodString;
|
|
81
82
|
engineVersion: z.ZodString;
|
|
82
83
|
provenance: z.ZodLiteral<"imported-dependency-graph">;
|
|
83
84
|
outcome: z.ZodEnum<{
|
|
@@ -85,7 +86,6 @@ export declare const architectureSummarySchema: z.ZodObject<{
|
|
|
85
86
|
failed: "failed";
|
|
86
87
|
incomplete: "incomplete";
|
|
87
88
|
}>;
|
|
88
|
-
reason: z.ZodString;
|
|
89
89
|
counts: z.ZodObject<{
|
|
90
90
|
projects: z.ZodNumber;
|
|
91
91
|
verifiedProjects: z.ZodNumber;
|
|
@@ -64,6 +64,7 @@ export declare const contractReportSchema: z.ZodObject<{
|
|
|
64
64
|
export type ContractReport = z.infer<typeof contractReportSchema>;
|
|
65
65
|
export declare const contractSummarySchema: z.ZodObject<{
|
|
66
66
|
schemaVersion: z.ZodLiteral<1>;
|
|
67
|
+
reason: z.ZodString;
|
|
67
68
|
engineVersion: z.ZodString;
|
|
68
69
|
provenance: z.ZodLiteral<"imported-contract-samples">;
|
|
69
70
|
outcome: z.ZodEnum<{
|
|
@@ -71,7 +72,6 @@ export declare const contractSummarySchema: z.ZodObject<{
|
|
|
71
72
|
failed: "failed";
|
|
72
73
|
incomplete: "incomplete";
|
|
73
74
|
}>;
|
|
74
|
-
reason: z.ZodString;
|
|
75
75
|
counts: z.ZodObject<{
|
|
76
76
|
contracts: z.ZodNumber;
|
|
77
77
|
passed: z.ZodNumber;
|
package/dist/src/contracts.d.ts
CHANGED
|
@@ -5,10 +5,10 @@ export declare function validateContracts(input: unknown, options?: {
|
|
|
5
5
|
}): Promise<ContractReport>;
|
|
6
6
|
export declare function projectContractReport(result: ContractReport, detailed: boolean): {
|
|
7
7
|
schemaVersion: 1;
|
|
8
|
+
reason: string;
|
|
8
9
|
engineVersion: string;
|
|
9
10
|
provenance: "imported-contract-samples";
|
|
10
11
|
outcome: "passed" | "failed" | "incomplete";
|
|
11
|
-
reason: string;
|
|
12
12
|
counts: {
|
|
13
13
|
contracts: number;
|
|
14
14
|
passed: number;
|
package/dist/src/evidence.js
CHANGED
|
@@ -172,6 +172,8 @@ function goTests(text, allowPackageFailures = false) {
|
|
|
172
172
|
}
|
|
173
173
|
export function evaluate(check, processes, root) {
|
|
174
174
|
const result = {
|
|
175
|
+
...(check.goScope ? { goScope: check.goScope } : {}),
|
|
176
|
+
...(check.goBuild ? { goBuild: check.goBuild } : {}),
|
|
175
177
|
...(check.external ? { external: check.external } : {}),
|
|
176
178
|
id: check.id,
|
|
177
179
|
adapter: check.adapter,
|
|
@@ -223,7 +225,7 @@ export function evaluate(check, processes, root) {
|
|
|
223
225
|
...(native.tests ? { tests: native.tests } : {}),
|
|
224
226
|
};
|
|
225
227
|
if (!goScopeComplete(check, processes[0], root, check.kind === "test" ? processes[1]?.stdout : undefined))
|
|
226
|
-
return set("inconclusive", "Native Go selection
|
|
228
|
+
return set("inconclusive", "Native Go selection or declared exclusions did not reconcile, a package has no passing test, or scope could not be established.");
|
|
227
229
|
return { ...result, ...(native.tests ? { tests: native.tests } : {}) };
|
|
228
230
|
}
|
|
229
231
|
if (check.parser === "eslint-json")
|
|
@@ -115,6 +115,7 @@ export declare const findingComparisonSchema: z.ZodObject<{
|
|
|
115
115
|
export type FindingComparison = z.infer<typeof findingComparisonSchema>;
|
|
116
116
|
export declare const findingComparisonSummarySchema: z.ZodObject<{
|
|
117
117
|
schemaVersion: z.ZodLiteral<1>;
|
|
118
|
+
reason: z.ZodString;
|
|
118
119
|
engineVersion: z.ZodString;
|
|
119
120
|
provenance: z.ZodLiteral<"finding-comparison">;
|
|
120
121
|
outcome: z.ZodEnum<{
|
|
@@ -122,7 +123,6 @@ export declare const findingComparisonSummarySchema: z.ZodObject<{
|
|
|
122
123
|
failed: "failed";
|
|
123
124
|
incomplete: "incomplete";
|
|
124
125
|
}>;
|
|
125
|
-
reason: z.ZodString;
|
|
126
126
|
counts: z.ZodObject<{
|
|
127
127
|
current: z.ZodNumber;
|
|
128
128
|
new: z.ZodNumber;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { Check, Inventory, Project } from "./types.js";
|
|
3
|
+
export declare const goBuildTagsSchema: z.ZodArray<z.ZodString>;
|
|
4
|
+
export declare const goBuildSelectionSchema: z.ZodObject<{
|
|
5
|
+
profile: z.ZodString;
|
|
6
|
+
tags: z.ZodArray<z.ZodString>;
|
|
7
|
+
}, z.core.$strict>;
|
|
8
|
+
export declare const goBuildPolicySchema: z.ZodObject<{
|
|
9
|
+
schemaVersion: z.ZodLiteral<1>;
|
|
10
|
+
profiles: z.ZodArray<z.ZodObject<{
|
|
11
|
+
name: z.ZodString;
|
|
12
|
+
tags: z.ZodArray<z.ZodString>;
|
|
13
|
+
checks: z.ZodArray<z.ZodEnum<{
|
|
14
|
+
"go.vet": "go.vet";
|
|
15
|
+
"go.test": "go.test";
|
|
16
|
+
"go.test-race": "go.test-race";
|
|
17
|
+
"go.staticcheck": "go.staticcheck";
|
|
18
|
+
"go.golangci-lint": "go.golangci-lint";
|
|
19
|
+
}>>;
|
|
20
|
+
excludedFiles: z.ZodArray<z.ZodObject<{
|
|
21
|
+
path: z.ZodString;
|
|
22
|
+
reason: z.ZodString;
|
|
23
|
+
}, z.core.$strict>>;
|
|
24
|
+
}, z.core.$strict>>;
|
|
25
|
+
}, z.core.$strict>;
|
|
26
|
+
export type GoBuildSelection = z.infer<typeof goBuildSelectionSchema>;
|
|
27
|
+
export declare function applyGoBuildPolicy(source: Inventory, project: Project, checks: Check[]): Promise<void>;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { lstat } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { goScopePolicySchema } from "./go-scope-policy.js";
|
|
5
|
+
import { readProjectFile } from "./inventory.js";
|
|
6
|
+
const nativeCheck = z.enum([
|
|
7
|
+
"go.vet",
|
|
8
|
+
"go.test",
|
|
9
|
+
"go.test-race",
|
|
10
|
+
"go.staticcheck",
|
|
11
|
+
"go.golangci-lint",
|
|
12
|
+
]);
|
|
13
|
+
export const goBuildTagsSchema = z
|
|
14
|
+
.array(z
|
|
15
|
+
.string()
|
|
16
|
+
.max(64)
|
|
17
|
+
.regex(/^[A-Za-z_][A-Za-z0-9_]*$/))
|
|
18
|
+
.max(32);
|
|
19
|
+
export const goBuildSelectionSchema = z.strictObject({
|
|
20
|
+
profile: z
|
|
21
|
+
.string()
|
|
22
|
+
.max(64)
|
|
23
|
+
.regex(/^[A-Za-z][A-Za-z0-9_-]*$/),
|
|
24
|
+
tags: goBuildTagsSchema,
|
|
25
|
+
});
|
|
26
|
+
export const goBuildPolicySchema = z.strictObject({
|
|
27
|
+
schemaVersion: z.literal(1),
|
|
28
|
+
profiles: z
|
|
29
|
+
.array(z.strictObject({
|
|
30
|
+
name: goBuildSelectionSchema.shape.profile,
|
|
31
|
+
tags: goBuildTagsSchema,
|
|
32
|
+
checks: z.array(nativeCheck).min(1).max(5),
|
|
33
|
+
excludedFiles: goScopePolicySchema.shape.excludedFiles,
|
|
34
|
+
}))
|
|
35
|
+
.min(1)
|
|
36
|
+
.max(5),
|
|
37
|
+
});
|
|
38
|
+
export async function applyGoBuildPolicy(source, project, checks) {
|
|
39
|
+
const file = path.posix.join(project.path, "checktrail.go-build.json");
|
|
40
|
+
const scoped = checks.filter((check) => check.id !== "go.format");
|
|
41
|
+
try {
|
|
42
|
+
let entry;
|
|
43
|
+
try {
|
|
44
|
+
entry = await lstat(path.join(source.root, file));
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
if (error.code === "ENOENT")
|
|
48
|
+
return;
|
|
49
|
+
throw error;
|
|
50
|
+
}
|
|
51
|
+
if (!entry.isFile() || !source.files.includes(file))
|
|
52
|
+
throw new Error("Go build policy must be an inventoried regular file");
|
|
53
|
+
try {
|
|
54
|
+
await lstat(path.join(source.root, project.path, "checktrail.go-scope.json"));
|
|
55
|
+
throw new Error("Use either Go build profiles or the module scope policy, not both");
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
if (error.code !== "ENOENT")
|
|
59
|
+
throw error;
|
|
60
|
+
}
|
|
61
|
+
const policy = goBuildPolicySchema.parse(JSON.parse(await readProjectFile(source.root, file)));
|
|
62
|
+
const profiles = new Map();
|
|
63
|
+
const names = new Set();
|
|
64
|
+
for (const profile of policy.profiles) {
|
|
65
|
+
if (names.has(profile.name))
|
|
66
|
+
throw new Error("Duplicate Go build profile name");
|
|
67
|
+
names.add(profile.name);
|
|
68
|
+
if (new Set(profile.tags).size !== profile.tags.length)
|
|
69
|
+
throw new Error("Duplicate Go build tag");
|
|
70
|
+
const paths = profile.excludedFiles.map((item) => item.path);
|
|
71
|
+
if (new Set(paths).size !== paths.length ||
|
|
72
|
+
paths.some((p) => !project.files.includes(p)))
|
|
73
|
+
throw new Error("Go build exclusions must name unique inventoried project files");
|
|
74
|
+
for (const id of profile.checks) {
|
|
75
|
+
if (profiles.has(id))
|
|
76
|
+
throw new Error("A Go check can select only one build profile");
|
|
77
|
+
profiles.set(id, profile);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
for (const check of scoped) {
|
|
81
|
+
const profile = profiles.get(check.id);
|
|
82
|
+
if (!profile) {
|
|
83
|
+
check.unavailableReason = "Selected Go check has no build profile";
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
check.goBuild = { profile: profile.name, tags: [...profile.tags] };
|
|
87
|
+
check.goScope = {
|
|
88
|
+
schemaVersion: 1,
|
|
89
|
+
excludedFiles: profile.excludedFiles,
|
|
90
|
+
};
|
|
91
|
+
for (const command of check.commands) {
|
|
92
|
+
if (command.executable === "go" ||
|
|
93
|
+
command.executable === "staticcheck") {
|
|
94
|
+
const index = command.args.indexOf("./...");
|
|
95
|
+
if (index < 0)
|
|
96
|
+
throw new Error("Unsupported Go build command");
|
|
97
|
+
if (profile.tags.length)
|
|
98
|
+
command.args.splice(index, 0, `-tags=${profile.tags.join(",")}`);
|
|
99
|
+
}
|
|
100
|
+
else if (check.id === "go.golangci-lint") {
|
|
101
|
+
command.args[3] = JSON.stringify(profile.tags);
|
|
102
|
+
}
|
|
103
|
+
else
|
|
104
|
+
throw new Error("Unsupported Go build command");
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
for (const check of scoped)
|
|
110
|
+
check.unavailableReason =
|
|
111
|
+
error instanceof Error ? error.message : "Invalid Go build policy";
|
|
112
|
+
}
|
|
113
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { Check, Inventory, Project } from "./types.js";
|
|
3
|
+
export declare const goScopePolicySchema: z.ZodObject<{
|
|
4
|
+
schemaVersion: z.ZodLiteral<1>;
|
|
5
|
+
excludedFiles: z.ZodArray<z.ZodObject<{
|
|
6
|
+
path: z.ZodString;
|
|
7
|
+
reason: z.ZodString;
|
|
8
|
+
}, z.core.$strict>>;
|
|
9
|
+
}, z.core.$strict>;
|
|
10
|
+
export type GoScopePolicy = z.infer<typeof goScopePolicySchema>;
|
|
11
|
+
export declare function applyGoScopePolicy(source: Inventory, project: Project, checks: Check[]): Promise<void>;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { lstat } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { readProjectFile } from "./inventory.js";
|
|
5
|
+
export const goScopePolicySchema = z.strictObject({
|
|
6
|
+
schemaVersion: z.literal(1),
|
|
7
|
+
excludedFiles: z
|
|
8
|
+
.array(z.strictObject({
|
|
9
|
+
path: z
|
|
10
|
+
.string()
|
|
11
|
+
.max(4096)
|
|
12
|
+
.regex(/^(?!\/)(?!.*(?:^|\/)\.{1,2}(?:\/|$))(?!.*\/\/)(?!.*[\\*?[\]{}])[\u0020-\u007e\u0080-\uffff]+\.go$/),
|
|
13
|
+
reason: z.string().min(1).max(1000).regex(/\S/),
|
|
14
|
+
}))
|
|
15
|
+
.max(1000),
|
|
16
|
+
});
|
|
17
|
+
export async function applyGoScopePolicy(source, project, checks) {
|
|
18
|
+
const file = path.posix.join(project.path, "checktrail.go-scope.json");
|
|
19
|
+
const scoped = checks.filter((check) => check.id !== "go.format");
|
|
20
|
+
try {
|
|
21
|
+
let entry;
|
|
22
|
+
try {
|
|
23
|
+
entry = await lstat(path.join(source.root, file));
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
if (error.code === "ENOENT")
|
|
27
|
+
return;
|
|
28
|
+
throw error;
|
|
29
|
+
}
|
|
30
|
+
if (!entry.isFile() ||
|
|
31
|
+
entry.isSymbolicLink() ||
|
|
32
|
+
source.excluded.includes(file))
|
|
33
|
+
throw new Error("Go scope policy must be an inventoried regular file");
|
|
34
|
+
if (!source.files.includes(file))
|
|
35
|
+
throw new Error("Go scope policy is not inventoried");
|
|
36
|
+
const policy = goScopePolicySchema.parse(JSON.parse(await readProjectFile(source.root, file)));
|
|
37
|
+
const paths = policy.excludedFiles.map((entry) => entry.path);
|
|
38
|
+
if (new Set(paths).size !== paths.length)
|
|
39
|
+
throw new Error("Duplicate Go scope exclusion");
|
|
40
|
+
if (paths.some((file) => !project.files.includes(file)))
|
|
41
|
+
throw new Error("Go scope exclusions must name inventoried project files");
|
|
42
|
+
for (const check of scoped)
|
|
43
|
+
check.goScope = policy;
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
for (const check of scoped)
|
|
47
|
+
check.unavailableReason =
|
|
48
|
+
error instanceof Error ? error.message : "Invalid Go scope policy";
|
|
49
|
+
}
|
|
50
|
+
}
|
package/dist/src/go-scope.d.ts
CHANGED
|
@@ -7,5 +7,5 @@ export declare const goEnvironment: {
|
|
|
7
7
|
GOENV: string;
|
|
8
8
|
GOCACHEPROG: string;
|
|
9
9
|
};
|
|
10
|
-
export declare function goScopeCommand(project: string, env?: Record<string, string
|
|
10
|
+
export declare function goScopeCommand(project: string, env?: Record<string, string>, race?: boolean): Command;
|
|
11
11
|
export declare function goScopeComplete(check: Check, process: ProcessResult | undefined, root: string | undefined, testOutput?: string): boolean;
|
package/dist/src/go-scope.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { goScopePolicySchema } from "./go-scope-policy.js";
|
|
1
2
|
import path from "node:path";
|
|
2
3
|
import { z } from "zod";
|
|
3
4
|
export const goEnvironment = {
|
|
@@ -8,10 +9,10 @@ export const goEnvironment = {
|
|
|
8
9
|
GOENV: "off",
|
|
9
10
|
GOCACHEPROG: "",
|
|
10
11
|
};
|
|
11
|
-
export function goScopeCommand(project, env = goEnvironment) {
|
|
12
|
+
export function goScopeCommand(project, env = goEnvironment, race = false) {
|
|
12
13
|
return {
|
|
13
14
|
executable: "go",
|
|
14
|
-
args: ["list", "-json", "./..."],
|
|
15
|
+
args: ["list", "-json", ...(race ? ["-race"] : []), "./..."],
|
|
15
16
|
cwd: project,
|
|
16
17
|
env,
|
|
17
18
|
};
|
|
@@ -60,6 +61,7 @@ const packageSchema = z.object({
|
|
|
60
61
|
CgoFiles: names,
|
|
61
62
|
TestGoFiles: names,
|
|
62
63
|
XTestGoFiles: names,
|
|
64
|
+
IgnoredGoFiles: names,
|
|
63
65
|
Error: z.unknown().optional(),
|
|
64
66
|
DepsErrors: z.array(z.unknown()).optional(),
|
|
65
67
|
});
|
|
@@ -68,11 +70,26 @@ export function goScopeComplete(check, process, root, testOutput) {
|
|
|
68
70
|
!process ||
|
|
69
71
|
process.exitCode !== 0 ||
|
|
70
72
|
process.stderr.trim() ||
|
|
73
|
+
process.timedOut ||
|
|
74
|
+
process.cancelled ||
|
|
75
|
+
process.truncated ||
|
|
76
|
+
process.signal !== null ||
|
|
77
|
+
process.errorCode !== undefined ||
|
|
71
78
|
!check.scope.length)
|
|
72
79
|
return false;
|
|
73
80
|
try {
|
|
74
81
|
const packages = objects(process.stdout).map((value) => packageSchema.parse(value));
|
|
75
82
|
const expected = new Set(check.scope.map((file) => path.resolve(root, check.project, file)));
|
|
83
|
+
if (expected.size !== check.scope.length)
|
|
84
|
+
return false;
|
|
85
|
+
const policy = check.goScope === undefined
|
|
86
|
+
? undefined
|
|
87
|
+
: goScopePolicySchema.parse(check.goScope);
|
|
88
|
+
const exclusions = new Set((policy?.excludedFiles ?? []).map((entry) => path.resolve(root, check.project, entry.path)));
|
|
89
|
+
if (exclusions.size !== (policy?.excludedFiles.length ?? 0) ||
|
|
90
|
+
[...exclusions].some((file) => !expected.has(file)))
|
|
91
|
+
return false;
|
|
92
|
+
const ignored = new Set();
|
|
76
93
|
const seen = new Set();
|
|
77
94
|
const ids = new Set();
|
|
78
95
|
for (const item of packages) {
|
|
@@ -88,13 +105,30 @@ export function goScopeComplete(check, process, root, testOutput) {
|
|
|
88
105
|
...item.TestGoFiles,
|
|
89
106
|
...item.XTestGoFiles,
|
|
90
107
|
]) {
|
|
91
|
-
if (path.basename(file) !== file ||
|
|
108
|
+
if (path.basename(file) !== file ||
|
|
109
|
+
file.includes("\\") ||
|
|
110
|
+
!file.endsWith(".go"))
|
|
92
111
|
return false;
|
|
93
112
|
const resolved = path.resolve(item.Dir, file);
|
|
94
|
-
if (!expected.has(resolved) ||
|
|
113
|
+
if (!expected.has(resolved) ||
|
|
114
|
+
exclusions.has(resolved) ||
|
|
115
|
+
seen.has(resolved) ||
|
|
116
|
+
ignored.has(resolved))
|
|
95
117
|
return false;
|
|
96
118
|
seen.add(resolved);
|
|
97
119
|
}
|
|
120
|
+
for (const file of item.IgnoredGoFiles) {
|
|
121
|
+
if (path.basename(file) !== file ||
|
|
122
|
+
file.includes("\\") ||
|
|
123
|
+
!file.endsWith(".go"))
|
|
124
|
+
return false;
|
|
125
|
+
const resolved = path.resolve(item.Dir, file);
|
|
126
|
+
if (!exclusions.has(resolved) ||
|
|
127
|
+
ignored.has(resolved) ||
|
|
128
|
+
seen.has(resolved))
|
|
129
|
+
return false;
|
|
130
|
+
ignored.add(resolved);
|
|
131
|
+
}
|
|
98
132
|
}
|
|
99
133
|
if (testOutput !== undefined) {
|
|
100
134
|
const tested = new Set();
|
|
@@ -114,7 +148,10 @@ export function goScopeComplete(check, process, root, testOutput) {
|
|
|
114
148
|
if (tested.size !== ids.size)
|
|
115
149
|
return false;
|
|
116
150
|
}
|
|
117
|
-
return ids.size > 0 &&
|
|
151
|
+
return (ids.size > 0 &&
|
|
152
|
+
seen.size > 0 &&
|
|
153
|
+
ignored.size === exclusions.size &&
|
|
154
|
+
seen.size + ignored.size === expected.size);
|
|
118
155
|
}
|
|
119
156
|
catch {
|
|
120
157
|
return false;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { goBuildTagsSchema } from "./go-build.js";
|
|
1
2
|
import { spawnSync } from "node:child_process";
|
|
2
3
|
import { mkdtemp, writeFile, rm } from "node:fs/promises";
|
|
3
4
|
import { tmpdir } from "node:os";
|
|
@@ -31,9 +32,10 @@ const configuration = z.strictObject({
|
|
|
31
32
|
formatters: z.record(z.string(), z.unknown()).optional(),
|
|
32
33
|
});
|
|
33
34
|
async function main() {
|
|
34
|
-
const [root, configFile, ...files] = process.argv.slice(2);
|
|
35
|
-
if (!root || !configFile || !files.length)
|
|
35
|
+
const [root, configFile, encodedTags, ...files] = process.argv.slice(2);
|
|
36
|
+
if (!root || !configFile || !encodedTags || !files.length)
|
|
36
37
|
throw new Error("Invalid golangci-lint arguments");
|
|
38
|
+
const tags = goBuildTagsSchema.parse(JSON.parse(encodedTags));
|
|
37
39
|
const version = spawnSync("golangci-lint", ["version", "--short"], {
|
|
38
40
|
encoding: "utf8",
|
|
39
41
|
maxBuffer: 8192,
|
|
@@ -63,6 +65,7 @@ async function main() {
|
|
|
63
65
|
version: "2",
|
|
64
66
|
run: {
|
|
65
67
|
tests: true,
|
|
68
|
+
"build-tags": tags,
|
|
66
69
|
"modules-download-mode": "readonly",
|
|
67
70
|
"relative-path-mode": "wd",
|
|
68
71
|
"issues-exit-code": 1,
|
package/dist/src/golangci.js
CHANGED
package/dist/src/output.js
CHANGED
|
@@ -22,6 +22,10 @@ export function projectPlan(plan, detailed) {
|
|
|
22
22
|
excludedCount: plan.excluded.length,
|
|
23
23
|
checks: plan.checks.map((check) => ({
|
|
24
24
|
id: check.id,
|
|
25
|
+
...(check.goBuild ? { goBuildTagCount: check.goBuild.tags.length } : {}),
|
|
26
|
+
...(check.goScope
|
|
27
|
+
? { goExcludedFileCount: check.goScope.excludedFiles.length }
|
|
28
|
+
: {}),
|
|
25
29
|
kind: check.kind,
|
|
26
30
|
ready: !check.unavailableReason,
|
|
27
31
|
})),
|
|
@@ -41,6 +45,10 @@ export function projectReport(report, detailed) {
|
|
|
41
45
|
sourceError: report.sourceError,
|
|
42
46
|
checks: report.checks.map((check) => ({
|
|
43
47
|
id: check.id,
|
|
48
|
+
...(check.goBuild ? { goBuildTagCount: check.goBuild.tags.length } : {}),
|
|
49
|
+
...(check.goScope
|
|
50
|
+
? { goExcludedFileCount: check.goScope.excludedFiles.length }
|
|
51
|
+
: {}),
|
|
44
52
|
status: check.status,
|
|
45
53
|
...(check.tests ? { tests: check.tests } : {}),
|
|
46
54
|
})),
|
|
@@ -39,6 +39,17 @@ export declare function validatedReport(input: unknown): {
|
|
|
39
39
|
source: "adapter-reported";
|
|
40
40
|
}[] | undefined;
|
|
41
41
|
} | undefined;
|
|
42
|
+
goScope?: {
|
|
43
|
+
schemaVersion: 1;
|
|
44
|
+
excludedFiles: {
|
|
45
|
+
path: string;
|
|
46
|
+
reason: string;
|
|
47
|
+
}[];
|
|
48
|
+
} | undefined;
|
|
49
|
+
goBuild?: {
|
|
50
|
+
profile: string;
|
|
51
|
+
tags: string[];
|
|
52
|
+
} | undefined;
|
|
42
53
|
tests?: {
|
|
43
54
|
total: number;
|
|
44
55
|
passed: number;
|
|
@@ -72,6 +72,7 @@ export declare const runtimeComparisonSchema: z.ZodObject<{
|
|
|
72
72
|
}, z.core.$strict>;
|
|
73
73
|
export declare const runtimeComparisonSummarySchema: z.ZodObject<{
|
|
74
74
|
schemaVersion: z.ZodLiteral<1>;
|
|
75
|
+
reason: z.ZodString;
|
|
75
76
|
engineVersion: z.ZodString;
|
|
76
77
|
provenance: z.ZodLiteral<"imported-runtime-comparison">;
|
|
77
78
|
outcome: z.ZodEnum<{
|
|
@@ -79,7 +80,6 @@ export declare const runtimeComparisonSummarySchema: z.ZodObject<{
|
|
|
79
80
|
failed: "failed";
|
|
80
81
|
incomplete: "incomplete";
|
|
81
82
|
}>;
|
|
82
|
-
reason: z.ZodString;
|
|
83
83
|
beforeFingerprint: z.ZodString;
|
|
84
84
|
afterFingerprint: z.ZodString;
|
|
85
85
|
counts: z.ZodObject<{
|
|
@@ -95,10 +95,10 @@ export type RuntimeComparison = z.infer<typeof runtimeComparisonSchema>;
|
|
|
95
95
|
export declare function compareRuntimeInventories(beforeInput: unknown, afterInput: unknown): RuntimeComparison;
|
|
96
96
|
export declare function projectRuntimeComparison(result: RuntimeComparison, detailed: boolean): {
|
|
97
97
|
schemaVersion: 1;
|
|
98
|
+
reason: string;
|
|
98
99
|
engineVersion: string;
|
|
99
100
|
provenance: "imported-runtime-comparison";
|
|
100
101
|
outcome: "passed" | "failed" | "incomplete";
|
|
101
|
-
reason: string;
|
|
102
102
|
beforeFingerprint: string;
|
|
103
103
|
afterFingerprint: string;
|
|
104
104
|
counts: {
|
package/dist/src/schemas.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
export { goBuildPolicySchema } from "./go-build.js";
|
|
2
|
+
export { goScopePolicySchema } from "./go-scope-policy.js";
|
|
1
3
|
export { externalManifestSchema, externalReferenceSchema, externalRequestSchema, externalResultSchema, } from "./external-adapter.js";
|
|
2
4
|
export { actionlintConfigSchema } from "./actionlint.js";
|
|
3
5
|
export { dotnetConfigSchema } from "./dotnet.js";
|
|
@@ -50,6 +52,17 @@ export declare const reportSchema: z.ZodObject<{
|
|
|
50
52
|
adapter: z.ZodString;
|
|
51
53
|
project: z.ZodString;
|
|
52
54
|
scope: z.ZodArray<z.ZodString>;
|
|
55
|
+
goScope: z.ZodOptional<z.ZodObject<{
|
|
56
|
+
schemaVersion: z.ZodLiteral<1>;
|
|
57
|
+
excludedFiles: z.ZodArray<z.ZodObject<{
|
|
58
|
+
path: z.ZodString;
|
|
59
|
+
reason: z.ZodString;
|
|
60
|
+
}, z.core.$strict>>;
|
|
61
|
+
}, z.core.$strict>>;
|
|
62
|
+
goBuild: z.ZodOptional<z.ZodObject<{
|
|
63
|
+
profile: z.ZodString;
|
|
64
|
+
tags: z.ZodArray<z.ZodString>;
|
|
65
|
+
}, z.core.$strict>>;
|
|
53
66
|
status: z.ZodEnum<{
|
|
54
67
|
error: "error";
|
|
55
68
|
passed: "passed";
|
|
@@ -200,6 +213,8 @@ export declare const reportSummarySchema: z.ZodObject<{
|
|
|
200
213
|
failed: z.ZodNumber;
|
|
201
214
|
skipped: z.ZodNumber;
|
|
202
215
|
}, z.core.$strict>>;
|
|
216
|
+
goExcludedFileCount: z.ZodOptional<z.ZodNumber>;
|
|
217
|
+
goBuildTagCount: z.ZodOptional<z.ZodNumber>;
|
|
203
218
|
}, z.core.$strict>>;
|
|
204
219
|
runId: z.ZodString;
|
|
205
220
|
outcome: z.ZodEnum<{
|
|
@@ -256,6 +271,17 @@ export declare const planSchema: z.ZodObject<{
|
|
|
256
271
|
adapter: z.ZodString;
|
|
257
272
|
project: z.ZodString;
|
|
258
273
|
scope: z.ZodArray<z.ZodString>;
|
|
274
|
+
goScope: z.ZodOptional<z.ZodObject<{
|
|
275
|
+
schemaVersion: z.ZodLiteral<1>;
|
|
276
|
+
excludedFiles: z.ZodArray<z.ZodObject<{
|
|
277
|
+
path: z.ZodString;
|
|
278
|
+
reason: z.ZodString;
|
|
279
|
+
}, z.core.$strict>>;
|
|
280
|
+
}, z.core.$strict>>;
|
|
281
|
+
goBuild: z.ZodOptional<z.ZodObject<{
|
|
282
|
+
profile: z.ZodString;
|
|
283
|
+
tags: z.ZodArray<z.ZodString>;
|
|
284
|
+
}, z.core.$strict>>;
|
|
259
285
|
kind: z.ZodEnum<{
|
|
260
286
|
format: "format";
|
|
261
287
|
analysis: "analysis";
|
|
@@ -354,6 +380,8 @@ export declare const planSummarySchema: z.ZodObject<{
|
|
|
354
380
|
unsupported: "unsupported";
|
|
355
381
|
}>;
|
|
356
382
|
ready: z.ZodBoolean;
|
|
383
|
+
goExcludedFileCount: z.ZodOptional<z.ZodNumber>;
|
|
384
|
+
goBuildTagCount: z.ZodOptional<z.ZodNumber>;
|
|
357
385
|
}, z.core.$strict>>;
|
|
358
386
|
schemaVersion: z.ZodLiteral<1>;
|
|
359
387
|
engineVersion: z.ZodString;
|