@intentius/chant 0.124.33 → 0.124.34
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/handlers/promote.d.ts.map +1 -1
- package/dist/cli/handlers/promote.js +261 -73
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/main.js +18 -1
- package/dist/cli/parse-args.d.ts.map +1 -1
- package/dist/cli/parse-args.js +7 -0
- package/dist/cli/registry.d.ts +3 -1
- package/dist/cli/registry.d.ts.map +1 -1
- package/dist/components/promote-rounds.d.ts +102 -0
- package/dist/components/promote-rounds.d.ts.map +1 -0
- package/dist/components/promote-rounds.js +174 -0
- package/dist/components/release-gate.d.ts +30 -0
- package/dist/components/release-gate.d.ts.map +1 -1
- package/dist/components/release-gate.js +92 -42
- package/dist/graph-declared.d.ts +4 -0
- package/dist/graph-declared.d.ts.map +1 -1
- package/dist/graph-declared.js +11 -1
- package/dist/wave-runtime.mjs +39 -39
- package/dist/workspace/__fixtures__/contract-repo.d.ts.map +1 -1
- package/dist/workspace/__fixtures__/contract-repo.js +13 -2
- package/dist/workspace/check.schema.json +20 -2
- package/dist/workspace/checks/ci-workflow.d.ts +17 -0
- package/dist/workspace/checks/ci-workflow.d.ts.map +1 -0
- package/dist/workspace/checks/ci-workflow.js +123 -0
- package/dist/workspace/checks/security.d.ts +16 -1
- package/dist/workspace/checks/security.d.ts.map +1 -1
- package/dist/workspace/checks/security.js +4 -4
- package/dist/workspace/checks.d.ts +1 -1
- package/dist/workspace/checks.d.ts.map +1 -1
- package/dist/workspace/checks.js +4 -1
- package/dist/workspace/ci-init.d.ts +100 -0
- package/dist/workspace/ci-init.d.ts.map +1 -0
- package/dist/workspace/ci-init.js +434 -0
- package/dist/workspace/ci-workflow.d.ts +91 -0
- package/dist/workspace/ci-workflow.d.ts.map +1 -0
- package/dist/workspace/ci-workflow.js +33 -0
- package/dist/workspace/declaration.d.ts +18 -0
- package/dist/workspace/declaration.d.ts.map +1 -1
- package/dist/workspace/declaration.js +9 -2
- package/dist/workspace/declaration.schema.json +28 -0
- package/dist/workspace/init.js +2 -2
- package/dist/workspace/reason-codes.d.ts +9 -0
- package/dist/workspace/reason-codes.d.ts.map +1 -1
- package/dist/workspace/reason-codes.js +10 -0
- package/dist/workspace/release-workflow.d.ts +31 -0
- package/dist/workspace/release-workflow.d.ts.map +1 -0
- package/dist/workspace/release-workflow.js +150 -0
- package/package.json +1 -1
- package/src/cli/handlers/promote.ts +280 -83
- package/src/cli/main.ts +18 -1
- package/src/cli/parse-args.ts +5 -0
- package/src/cli/registry.ts +3 -1
- package/src/components/promote-rounds.test.ts +220 -0
- package/src/components/promote-rounds.ts +232 -0
- package/src/components/release-gate.test.ts +47 -0
- package/src/components/release-gate.ts +111 -46
- package/src/graph-declared-exports.test.ts +40 -0
- package/src/graph-declared.ts +9 -1
- package/src/workspace/__fixtures__/contract-repo.ts +11 -2
- package/src/workspace/check-contract.test.ts +3 -2
- package/src/workspace/check.schema.json +20 -2
- package/src/workspace/checks/ci-workflow.test.ts +150 -0
- package/src/workspace/checks/ci-workflow.ts +129 -0
- package/src/workspace/checks/security.ts +4 -4
- package/src/workspace/checks.ts +4 -1
- package/src/workspace/ci-init.test.ts +159 -0
- package/src/workspace/ci-init.ts +445 -0
- package/src/workspace/ci-report-url.test.ts +6 -1
- package/src/workspace/ci-workflow.ts +71 -0
- package/src/workspace/declaration.schema.json +28 -0
- package/src/workspace/declaration.ts +32 -3
- package/src/workspace/init.ts +2 -2
- package/src/workspace/reason-codes.test.ts +2 -0
- package/src/workspace/reason-codes.ts +10 -0
- package/src/workspace/release-workflow.ts +167 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contract-repo.d.ts","sourceRoot":"","sources":["../../../src/workspace/__fixtures__/contract-repo.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,OAAO,MAAM,eAAe,CAAC;AAGpC,6CAA6C;AAC7C,eAAO,MAAM,IAAI,QAAwE,CAAC;AAI1F,gGAAgG;AAChG,wBAAgB,YAAY,IAAI,IAAI,CAEnC;AAED,wBAAgB,UAAU,CAAC,MAAM,SAAoB,GAAG,MAAM,CAI7D;AAED,wBAAgB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAM1D;AAED,iFAAiF;AACjF,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,IAAI,CAO7G;AAED,uFAAuF;AACvF,wBAAgB,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,EAAE,MAAM,UAAQ,GAAG,MAAM,CAS3G;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,MAAM,EAAE,MAAM,SAAyB,GAAG,MAAM,MAAM,
|
|
1
|
+
{"version":3,"file":"contract-repo.d.ts","sourceRoot":"","sources":["../../../src/workspace/__fixtures__/contract-repo.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,OAAO,MAAM,eAAe,CAAC;AAGpC,6CAA6C;AAC7C,eAAO,MAAM,IAAI,QAAwE,CAAC;AAI1F,gGAAgG;AAChG,wBAAgB,YAAY,IAAI,IAAI,CAEnC;AAED,wBAAgB,UAAU,CAAC,MAAM,SAAoB,GAAG,MAAM,CAI7D;AAED,wBAAgB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAM1D;AAED,iFAAiF;AACjF,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,IAAI,CAO7G;AAED,uFAAuF;AACvF,wBAAgB,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,EAAE,MAAM,UAAQ,GAAG,MAAM,CAS3G;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,MAAM,EAAE,MAAM,SAAyB,GAAG,MAAM,MAAM,CAiB9F;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,SAAS,GAAG,MAAM,CAIhE;AAED,QAAA,MAAM,GAAG,SAAiD,CAAC;AAE3D,4EAA4E;AAC5E,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,QAAQ,EAAE,UAAU,CAAC,OAAO,GAAG,CAAC,OAAO,CAAC,CAAC;IAAC,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAAA;CAAE,CAStH;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEnD;AAED,eAAO,MAAM,WAAW,YAAa,OAAO,EAAE,UAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,WACL,CAAC;AAE1E;;;GAGG;AACH,eAAO,MAAM,gBAAgB,6XAU5B,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,sZASjC,CAAC"}
|
|
@@ -22,7 +22,7 @@ export function scratchDir(prefix = "chant-contract-") {
|
|
|
22
22
|
return d;
|
|
23
23
|
}
|
|
24
24
|
export function git(cwd, ...args) {
|
|
25
|
-
return execFileSync("git", ["-c", "user.name=t", "-c", "user.email=t@example.com", "-c", "commit.gpgsign=false", ...args], {
|
|
25
|
+
return execFileSync("git", ["-c", "user.name=t", "-c", "user.email=t@example.com", "-c", "commit.gpgsign=false", "-c", "gc.auto=0", "-c", "maintenance.auto=false", ...args], {
|
|
26
26
|
cwd,
|
|
27
27
|
encoding: "utf-8",
|
|
28
28
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -61,7 +61,18 @@ export function repoFixture(build, prefix = "chant-contract-copy-") {
|
|
|
61
61
|
if (template === undefined || !existsSync(template))
|
|
62
62
|
template = build();
|
|
63
63
|
const root = scratchDir(prefix);
|
|
64
|
-
|
|
64
|
+
// A commit can leave a detached `git gc --auto` or maintenance run moving
|
|
65
|
+
// the template's objects, and a copy that meets it fails with ENOENT on
|
|
66
|
+
// .git/objects. Copy once more after it settles.
|
|
67
|
+
try {
|
|
68
|
+
cpSync(template, root, { recursive: true });
|
|
69
|
+
}
|
|
70
|
+
catch (err) {
|
|
71
|
+
if (err.code !== "ENOENT")
|
|
72
|
+
throw err;
|
|
73
|
+
rmSync(root, { recursive: true, force: true });
|
|
74
|
+
cpSync(template, root, { recursive: true });
|
|
75
|
+
}
|
|
65
76
|
return root;
|
|
66
77
|
};
|
|
67
78
|
}
|
|
@@ -332,7 +332,16 @@
|
|
|
332
332
|
|
|
333
333
|
"security-runner-start-no-role",
|
|
334
334
|
|
|
335
|
-
"security-trust-unreadable"
|
|
335
|
+
"security-trust-unreadable",
|
|
336
|
+
"ci-workflow-green-undeclared",
|
|
337
|
+
"ci-workflow-no-pre-merge",
|
|
338
|
+
"ci-workflow-apply-in-green",
|
|
339
|
+
"ci-workflow-no-components",
|
|
340
|
+
"ci-workflow-no-environments",
|
|
341
|
+
"ci-workflow-ungated-env",
|
|
342
|
+
"ci-workflow-pipeline-missing",
|
|
343
|
+
"ci-workflow-pipeline-differs",
|
|
344
|
+
"ci-workflow-publish-missing"
|
|
336
345
|
],
|
|
337
346
|
"description": "For WSP001: why the declaration can't be read. For WSP121 to WSP127, the box finding (#2726, #2727, #2780, #2850). For WSP117, work-acceptance-unmet (#2772). For WSP118, flag-stale (#4024). For WSP131 to WSP133, the diagram finding (#2764)."
|
|
338
347
|
}
|
|
@@ -445,7 +454,16 @@
|
|
|
445
454
|
|
|
446
455
|
"security-runner-start-no-role",
|
|
447
456
|
|
|
448
|
-
"security-trust-unreadable"
|
|
457
|
+
"security-trust-unreadable",
|
|
458
|
+
"ci-workflow-green-undeclared",
|
|
459
|
+
"ci-workflow-no-pre-merge",
|
|
460
|
+
"ci-workflow-apply-in-green",
|
|
461
|
+
"ci-workflow-no-components",
|
|
462
|
+
"ci-workflow-no-environments",
|
|
463
|
+
"ci-workflow-ungated-env",
|
|
464
|
+
"ci-workflow-pipeline-missing",
|
|
465
|
+
"ci-workflow-pipeline-differs",
|
|
466
|
+
"ci-workflow-publish-missing"
|
|
449
467
|
],
|
|
450
468
|
"description": "For WSP001: why the declaration can't be read. For WSP121 to WSP127, the box finding (#2726, #2727, #2780, #2850). For WSP117, work-acceptance-unmet (#2772). For WSP118, flag-stale (#4024). For WSP131 to WSP133, the diagram finding (#2764)."
|
|
451
469
|
},
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WSP151 (#4168 step 6): what a member under `ci.workflow` still lacks.
|
|
3
|
+
*
|
|
4
|
+
* A declaration that names no workflow gets no finding from this file. The
|
|
5
|
+
* requirements and their codes are {@link CI_WORKFLOW_REQUIREMENTS}
|
|
6
|
+
* (../ci-workflow.ts). Like the security checklists (./security.ts), the
|
|
7
|
+
* check reads files and never runs them: `chant.config.ts` for the
|
|
8
|
+
* environments (its literal `environments`, as `workspace status` reads it),
|
|
9
|
+
* `*.component.ts` for components and gates, and the forge pipeline files for
|
|
10
|
+
* the jobs. A generated file that differs from what its generator writes is
|
|
11
|
+
* WSP101 to WSP106's to report; this check asks only whether the jobs the
|
|
12
|
+
* workflow needs are there.
|
|
13
|
+
*/
|
|
14
|
+
import type { WorkspaceCheck } from "../checks.js";
|
|
15
|
+
export declare const WSP_CI_WORKFLOW = "WSP151";
|
|
16
|
+
export declare const CI_WORKFLOW_CHECKS: readonly WorkspaceCheck[];
|
|
17
|
+
//# sourceMappingURL=ci-workflow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ci-workflow.d.ts","sourceRoot":"","sources":["../../../src/workspace/checks/ci-workflow.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAuB,MAAM,WAAW,CAAC;AAQrE,eAAO,MAAM,eAAe,WAAW,CAAC;AAaxC,eAAO,MAAM,kBAAkB,EAAE,SAAS,cAAc,EA6FvD,CAAC"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WSP151 (#4168 step 6): what a member under `ci.workflow` still lacks.
|
|
3
|
+
*
|
|
4
|
+
* A declaration that names no workflow gets no finding from this file. The
|
|
5
|
+
* requirements and their codes are {@link CI_WORKFLOW_REQUIREMENTS}
|
|
6
|
+
* (../ci-workflow.ts). Like the security checklists (./security.ts), the
|
|
7
|
+
* check reads files and never runs them: `chant.config.ts` for the
|
|
8
|
+
* environments (its literal `environments`, as `workspace status` reads it),
|
|
9
|
+
* `*.component.ts` for components and gates, and the forge pipeline files for
|
|
10
|
+
* the jobs. A generated file that differs from what its generator writes is
|
|
11
|
+
* WSP101 to WSP106's to report; this check asks only whether the jobs the
|
|
12
|
+
* workflow needs are there.
|
|
13
|
+
*/
|
|
14
|
+
import { appliesOnMerge, STUB_MARKER, workflowOf } from "../ci-workflow.js";
|
|
15
|
+
import { matchesCheckRun } from "../ci-green.js";
|
|
16
|
+
import { staticPromotionOrder } from "../promotion-order.js";
|
|
17
|
+
import { joinPath } from "../tree.js";
|
|
18
|
+
import { allPipelineFiles, commandLines, componentFiles, read } from "./security.js";
|
|
19
|
+
export const WSP_CI_WORKFLOW = "WSP151";
|
|
20
|
+
const memberDir = (dir) => (dir === "." ? "" : dir);
|
|
21
|
+
const PLAN = /\bci\s+run\s+plan\b|\bcomponents\s+pr-plan\b/;
|
|
22
|
+
const RECORD = /\bci\s+run\s+record\b|\bcomponents\s+pr-record\b/;
|
|
23
|
+
const APPLY = /\bci\s+run\s+apply\b|\bcomponents\s+pr-apply\b/;
|
|
24
|
+
const TICK = /\bci\s+tick\b/;
|
|
25
|
+
const PUBLISH = /\brelease\s+publish\b/;
|
|
26
|
+
/** The apply job names a required phase could match. */
|
|
27
|
+
const APPLY_JOB_NAMES = ["apply", "pr-apply"];
|
|
28
|
+
export const CI_WORKFLOW_CHECKS = [
|
|
29
|
+
{
|
|
30
|
+
id: WSP_CI_WORKFLOW,
|
|
31
|
+
name: "ci-workflow",
|
|
32
|
+
description: "Under ci.workflow: ci.green with pre-merge phases and no apply job required, each member with a component, environments and a gate on each component, and pipeline files that plan, record (or apply under apply on merge), tick and publish.",
|
|
33
|
+
severity: "warning",
|
|
34
|
+
configurable: true,
|
|
35
|
+
check(ctx) {
|
|
36
|
+
const d = ctx.declaration;
|
|
37
|
+
const under = d.members
|
|
38
|
+
.map((m) => ({ member: m, workflow: workflowOf(d, m) }))
|
|
39
|
+
.filter((u) => u.workflow !== null)
|
|
40
|
+
// The top level's workflow covers the members that build with chant; a member that names one itself is held to it.
|
|
41
|
+
.filter((u) => u.member.ciWorkflow !== null || ctx.tree.stat(joinPath(memberDir(u.member.dir), "chant.config.ts")) === "file");
|
|
42
|
+
if (under.length === 0 && !d.ci?.workflow)
|
|
43
|
+
return [];
|
|
44
|
+
const pointer = d.ci?.workflow ? "/ci/workflow" : `${under[0].member.pointer}/ci/workflow`;
|
|
45
|
+
const out = [];
|
|
46
|
+
const finding = (code, message, at = {}) => {
|
|
47
|
+
out.push({
|
|
48
|
+
checkId: this.id,
|
|
49
|
+
severity: this.severity,
|
|
50
|
+
code,
|
|
51
|
+
message: `${code}: ${message}`,
|
|
52
|
+
pointer: at.pointer ?? pointer,
|
|
53
|
+
...(at.entity !== undefined ? { entity: at.entity } : {}),
|
|
54
|
+
...(at.treeFile !== undefined ? { treeFile: at.treeFile, line: at.line ?? 1, column: 1 } : {}),
|
|
55
|
+
});
|
|
56
|
+
};
|
|
57
|
+
const green = d.ci?.green ?? null;
|
|
58
|
+
if (!green) {
|
|
59
|
+
finding("ci-workflow-green-undeclared", "the workspace follows a ci.workflow and declares no ci.green, so no commit gets a verdict and no release can be cut; run chant ci init or add a ci.green block");
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
if ((green.preMerge ?? []).length === 0) {
|
|
63
|
+
finding("ci-workflow-no-pre-merge", "ci.green.preMerge names no phase, so nothing says which checks run before the branch moves; name the quick ones", { pointer: green.pointer });
|
|
64
|
+
}
|
|
65
|
+
for (const name of green.require) {
|
|
66
|
+
const phase = green.phases.find((p) => p.name === name);
|
|
67
|
+
const hit = phase?.runs.find((pattern) => APPLY_JOB_NAMES.some((job) => matchesCheckRun(pattern, job)));
|
|
68
|
+
if (phase && hit) {
|
|
69
|
+
finding("ci-workflow-apply-in-green", `the required phase ${name} matches the apply job with ${JSON.stringify(hit)}, so an apply that waits for a green commit would wait on itself; drop the pattern`, { pointer: phase.pointer });
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
for (const { member } of under) {
|
|
74
|
+
const dir = memberDir(member.dir);
|
|
75
|
+
const components = componentFiles(ctx.tree, dir);
|
|
76
|
+
if (components.length === 0) {
|
|
77
|
+
finding("ci-workflow-no-components", `member ${member.name} declares no component, so nothing of it can be cut or promoted; chant ci init writes a stub`, { pointer: member.pointer, entity: member.name });
|
|
78
|
+
}
|
|
79
|
+
else if (components.every((f) => (read(ctx.tree, f) ?? "").includes(STUB_MARKER))) {
|
|
80
|
+
finding("ci-workflow-no-components", `member ${member.name}'s only component is the stub chant ci init wrote (${components[0]}); say how it is built and deployed, then delete its ${STUB_MARKER} line`, { pointer: member.pointer, entity: member.name, treeFile: components[0] });
|
|
81
|
+
}
|
|
82
|
+
const configPath = joinPath(dir, "chant.config.ts");
|
|
83
|
+
const config = read(ctx.tree, configPath);
|
|
84
|
+
// A config whose environments aren't literals can't be read without running it; say nothing rather than guess.
|
|
85
|
+
const order = config === null ? [] : staticPromotionOrder(config);
|
|
86
|
+
if (order !== undefined && order.length === 0) {
|
|
87
|
+
finding("ci-workflow-no-environments", `member ${member.name}'s chant.config.ts declares no environments, so a release has nowhere to be promoted to`, { pointer: member.pointer, entity: member.name, ...(config !== null ? { treeFile: configPath } : {}) });
|
|
88
|
+
}
|
|
89
|
+
for (const file of components) {
|
|
90
|
+
const text = read(ctx.tree, file) ?? "";
|
|
91
|
+
if (/\bgate\s*\(|kind\s*:\s*["']gate["']/.test(text))
|
|
92
|
+
continue;
|
|
93
|
+
const last = order && order.length > 0 ? order[order.length - 1].name : "the last environment";
|
|
94
|
+
finding("ci-workflow-ungated-env", `${file} has no gate, so a promote to ${last} waits on no approval; add a gate() step`, { pointer: member.pointer, entity: member.name, treeFile: file });
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
const files = allPipelineFiles(ctx);
|
|
98
|
+
const has = (re) => files.some((f) => f.lines.some((l) => re.test(l)));
|
|
99
|
+
const applyOnMerge = under.some((u) => appliesOnMerge(u.workflow)) || (d.ci?.workflow ? appliesOnMerge(d.ci.workflow) : false);
|
|
100
|
+
const missing = [
|
|
101
|
+
...(has(PLAN) ? [] : ["a plan job (ci run plan)"]),
|
|
102
|
+
...(has(RECORD) || has(APPLY) ? [] : [applyOnMerge ? "an apply job (ci run apply)" : "a record job (ci run record)"]),
|
|
103
|
+
...(has(TICK) ? [] : ["chant ci tick"]),
|
|
104
|
+
];
|
|
105
|
+
if (missing.length > 0) {
|
|
106
|
+
finding("ci-workflow-pipeline-missing", `no pipeline file runs ${missing.join(", ")}; generate them with chant build --components --generate <forge> --pr-loop and chant ci workflow`);
|
|
107
|
+
}
|
|
108
|
+
if (!applyOnMerge) {
|
|
109
|
+
for (const l of commandLines(ctx, APPLY)) {
|
|
110
|
+
finding("ci-workflow-pipeline-differs", `${l.path} applies on merge, and the workflow is trunk-curated, where a merge records the plan and deploys nothing; regenerate without --apply-on-merge, or set ci.workflow to trunk-curated+apply-on-merge`, { treeFile: l.path, line: l.line });
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
else if (!has(APPLY) && has(RECORD)) {
|
|
114
|
+
const l = commandLines(ctx, RECORD)[0];
|
|
115
|
+
finding("ci-workflow-pipeline-differs", `${l.path} records on merge, and the workflow is trunk-curated+apply-on-merge; regenerate with --apply-on-merge`, { treeFile: l.path, line: l.line });
|
|
116
|
+
}
|
|
117
|
+
if (!has(PUBLISH)) {
|
|
118
|
+
finding("ci-workflow-publish-missing", "no pipeline file runs chant release publish, so a cut release is never published; generate one with chant release workflow");
|
|
119
|
+
}
|
|
120
|
+
return out;
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
];
|
|
@@ -23,7 +23,8 @@
|
|
|
23
23
|
* pipeline file that runs `chant release publish`, `chant ci tick` or
|
|
24
24
|
* `chant components pr-apply`.
|
|
25
25
|
*/
|
|
26
|
-
import type { WorkspaceCheck } from "../checks.js";
|
|
26
|
+
import type { WorkspaceCheck, WorkspaceCheckContext } from "../checks.js";
|
|
27
|
+
import { type WorkspaceTree } from "../tree.js";
|
|
27
28
|
/** The read contract's codes for the security findings, carried as `code` on each. */
|
|
28
29
|
export declare const SECURITY_FINDING_CODES: readonly ["security-signers-missing", "security-release-gate-missing", "security-publish-allows-unsigned", "security-sbom-disabled", "security-sbom-unsourced", "security-publish-no-provenance", "security-component-no-sbom", "security-component-no-verify", "security-signed-since-unset", "security-runner-untrusted", "security-tick-no-key", "security-review-not-required", "security-attribution-any", "security-gate-unsigned", "security-runner-start-no-key", "security-runner-start-no-role", "security-trust-unreadable"];
|
|
29
30
|
export declare const WSP_SECURITY_VERIFIED_RELEASES = "WSP161";
|
|
@@ -31,5 +32,19 @@ export declare const WSP_SECURITY_SUPPLY_CHAIN = "WSP162";
|
|
|
31
32
|
export declare const WSP_SECURITY_WHO_RAN_IT = "WSP163";
|
|
32
33
|
export declare const WSP_SECURITY_REVIEW_RULES = "WSP164";
|
|
33
34
|
export declare const WSP_SECURITY_ISOLATED_RUNNERS = "WSP165";
|
|
35
|
+
export declare function read(tree: WorkspaceTree, path: string): string | null;
|
|
36
|
+
/** Every pipeline file of the workspace: its root's, and each member's. */
|
|
37
|
+
export declare function allPipelineFiles(ctx: WorkspaceCheckContext): {
|
|
38
|
+
path: string;
|
|
39
|
+
lines: string[];
|
|
40
|
+
}[];
|
|
41
|
+
/** The lines of the pipeline files that run a chant command, `command` naming it, such as `release publish`. */
|
|
42
|
+
export declare function commandLines(ctx: WorkspaceCheckContext, command: RegExp): {
|
|
43
|
+
path: string;
|
|
44
|
+
line: number;
|
|
45
|
+
text: string;
|
|
46
|
+
}[];
|
|
47
|
+
/** The member's `*.component.ts` files, walked a few levels down, past node_modules and build output. */
|
|
48
|
+
export declare function componentFiles(tree: WorkspaceTree, dir: string, depth?: number): string[];
|
|
34
49
|
export declare const SECURITY_CHECKS: readonly WorkspaceCheck[];
|
|
35
50
|
//# sourceMappingURL=security.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"security.d.ts","sourceRoot":"","sources":["../../../src/workspace/checks/security.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,KAAK,EAAE,cAAc,
|
|
1
|
+
{"version":3,"file":"security.d.ts","sourceRoot":"","sources":["../../../src/workspace/checks/security.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,qBAAqB,EAAuB,MAAM,WAAW,CAAC;AAI5F,OAAO,EAAY,KAAK,aAAa,EAAE,MAAM,SAAS,CAAC;AAMvD,sFAAsF;AACtF,eAAO,MAAM,sBAAsB,ygBAkBO,CAAC;AAI3C,eAAO,MAAM,8BAA8B,WAAW,CAAC;AACvD,eAAO,MAAM,yBAAyB,WAAW,CAAC;AAClD,eAAO,MAAM,uBAAuB,WAAW,CAAC;AAChD,eAAO,MAAM,yBAAyB,WAAW,CAAC;AAClD,eAAO,MAAM,6BAA6B,WAAW,CAAC;AAsBtD,wBAAgB,IAAI,CAAC,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAOrE;AAkBD,2EAA2E;AAC3E,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,qBAAqB,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,EAAE,CAGhG;AAED,gHAAgH;AAChH,wBAAgB,YAAY,CAAC,GAAG,EAAE,qBAAqB,EAAE,OAAO,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,CAExH;AAED,yGAAyG;AACzG,wBAAgB,cAAc,CAAC,IAAI,EAAE,aAAa,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,SAAI,GAAG,MAAM,EAAE,CAQpF;AAuCD,eAAO,MAAM,eAAe,EAAE,SAAS,cAAc,EAuIpD,CAAC"}
|
|
@@ -70,7 +70,7 @@ function groupPointer(declaration, group) {
|
|
|
70
70
|
const m = declaration.members.find((e) => e.security.includes(group));
|
|
71
71
|
return m ? `${m.pointer}/security/${m.security.indexOf(group)}` : "/security";
|
|
72
72
|
}
|
|
73
|
-
function read(tree, path) {
|
|
73
|
+
export function read(tree, path) {
|
|
74
74
|
if (tree.stat(path) !== "file")
|
|
75
75
|
return null;
|
|
76
76
|
try {
|
|
@@ -99,16 +99,16 @@ function pipelineFiles(tree, dir) {
|
|
|
99
99
|
return out;
|
|
100
100
|
}
|
|
101
101
|
/** Every pipeline file of the workspace: its root's, and each member's. */
|
|
102
|
-
function allPipelineFiles(ctx) {
|
|
102
|
+
export function allPipelineFiles(ctx) {
|
|
103
103
|
const dirs = new Set(["", ...ctx.declaration.members.map((m) => memberDir(m.dir))]);
|
|
104
104
|
return [...dirs].flatMap((d) => pipelineFiles(ctx.tree, d));
|
|
105
105
|
}
|
|
106
106
|
/** The lines of the pipeline files that run a chant command, `command` naming it, such as `release publish`. */
|
|
107
|
-
function commandLines(ctx, command) {
|
|
107
|
+
export function commandLines(ctx, command) {
|
|
108
108
|
return allPipelineFiles(ctx).flatMap((f) => f.lines.flatMap((text, i) => (command.test(text) ? [{ path: f.path, line: i + 1, text }] : [])));
|
|
109
109
|
}
|
|
110
110
|
/** The member's `*.component.ts` files, walked a few levels down, past node_modules and build output. */
|
|
111
|
-
function componentFiles(tree, dir, depth = 4) {
|
|
111
|
+
export function componentFiles(tree, dir, depth = 4) {
|
|
112
112
|
const out = [];
|
|
113
113
|
for (const e of tree.list(dir) ?? []) {
|
|
114
114
|
if (e.type === "dir") {
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
* | WSP126, WSP127 | box intent: the decision record a box names exists, and constrains a member or path of this workspace (#2850, #2857) |
|
|
38
38
|
* | WSP141, WSP142 | member links resolved against a live read, with `--live` (#2549) |
|
|
39
39
|
* | WSP131 to WSP133 | diagram artifacts: source and render exist, a recorded source hash still matches (#2764) |
|
|
40
|
-
* | WSP151 |
|
|
40
|
+
* | WSP151 | what a member under `ci.workflow` still lacks (#4168 step 6) |
|
|
41
41
|
* | WSP161 to WSP165 | the security groups the declaration opts into: what each still lacks (#4168 step 7) |
|
|
42
42
|
*/
|
|
43
43
|
import type { LintDiagnostic, LintRule, Severity } from "../lint/rule.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checks.d.ts","sourceRoot":"","sources":["../../src/workspace/checks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACvE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAsD,KAAK,WAAW,EAAkC,KAAK,aAAa,EAAE,MAAM,eAAe,CAAC;AACzJ,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEjD,OAAO,EAAiE,KAAK,eAAe,EAAE,KAAK,YAAY,EAAE,MAAM,SAAS,CAAC;AACjI,OAAO,EAA6D,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpH,OAAO,EAAuB,KAAK,aAAa,EAAE,MAAM,QAAQ,CAAC;AAEjE,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACrD,OAAO,EAA0C,KAAK,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACrG,OAAO,EAAoC,KAAK,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC5F,OAAO,EAAwC,KAAK,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACpG,OAAO,EAAoC,KAAK,aAAa,EAAE,MAAM,eAAe,CAAC;AACrF,OAAO,EAAiB,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"checks.d.ts","sourceRoot":"","sources":["../../src/workspace/checks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACvE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAsD,KAAK,WAAW,EAAkC,KAAK,aAAa,EAAE,MAAM,eAAe,CAAC;AACzJ,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEjD,OAAO,EAAiE,KAAK,eAAe,EAAE,KAAK,YAAY,EAAE,MAAM,SAAS,CAAC;AACjI,OAAO,EAA6D,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpH,OAAO,EAAuB,KAAK,aAAa,EAAE,MAAM,QAAQ,CAAC;AAEjE,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACrD,OAAO,EAA0C,KAAK,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACrG,OAAO,EAAoC,KAAK,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC5F,OAAO,EAAwC,KAAK,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACpG,OAAO,EAAoC,KAAK,aAAa,EAAE,MAAM,eAAe,CAAC;AACrF,OAAO,EAAiB,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAKnE,OAAO,EAAqB,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACxE,OAAO,EAAqB,KAAK,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACzE,OAAO,EAAwB,KAAK,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAEpF;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B,6EAA6E;IAC7E,OAAO,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;IACvC,+EAA+E;IAC/E,SAAS,CAAC,EAAE,SAAS,mBAAmB,EAAE,CAAC;IAC3C,kFAAkF;IAClF,SAAS,CAAC,EAAE,SAAS,kBAAkB,EAAE,CAAC;IAC1C,oFAAoF;IACpF,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,oGAAoG;IACpG,aAAa,CAAC,EAAE,SAAS,YAAY,EAAE,CAAC;IACxC,8EAA8E;IAC9E,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,uFAAuF;IACvF,UAAU,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAC1C,kHAAkH;IAClH,cAAc,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC;CAC5D;AAED,0CAA0C;AAC1C,MAAM,WAAW,qBAAqB;IACpC,WAAW,EAAE,WAAW,CAAC;IACzB,IAAI,EAAE,aAAa,CAAC;IACpB,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,KAAK,EAAE,YAAY,CAAC;IACpB,+CAA+C;IAC/C,YAAY,EAAE,eAAe,EAAE,CAAC;IAChC,yGAAyG;IACzG,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,mEAAmE;IACnE,aAAa,CAAC,EAAE,eAAe,EAAE,CAAC;IAClC,gDAAgD;IAChD,KAAK,CAAC,EAAE,cAAc,CAAC;CACxB;AAED;;;;GAIG;AACH,MAAM,WAAW,mBAAoB,SAAQ,mBAAmB;IAC9D,2CAA2C;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,2IAA2I;IAC3I,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,mJAAmJ;IACnJ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yEAAyE;IACzE,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,mDAAmD;IACnD,EAAE,EAAE,MAAM,CAAC;IACX,kCAAkC;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,QAAQ,CAAC;IACnB,kFAAkF;IAClF,YAAY,EAAE,OAAO,CAAC;IACtB,KAAK,CAAC,GAAG,EAAE,qBAAqB,GAAG,mBAAmB,EAAE,CAAC;CAC1D;AAED,2EAA2E;AAC3E,MAAM,WAAW,gBAAiB,SAAQ,cAAc;IACtD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mJAAmJ;IACnJ,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB;AAED,MAAM,WAAW,iBAAkB,SAAQ,gBAAgB;IACzD,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,sBAAsB;IACrC,+EAA+E;IAC/E,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,gBAAgB,EAAE,CAAC;IAChC,UAAU,EAAE,iBAAiB,EAAE,CAAC;IAChC,8EAA8E;IAC9E,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,0FAA0F;IAC1F,IAAI,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,EAAE,CAAA;KAAE,CAAC;IACzC,mDAAmD;IACnD,EAAE,EAAE,OAAO,CAAC;CACb;AAqBD,iHAAiH;AACjH,eAAO,MAAM,mBAAmB,WAAW,CAAC;AAE5C,eAAO,MAAM,gBAAgB,EAAE,SAAS,cAAc,EAqMrD,CAAC;AAWF;;;GAGG;AACH,wBAAgB,mBAAmB,IAAI,QAAQ,EAAE,CAShD;AAED,qFAAqF;AACrF,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,qBAAqB,GAAG,mBAAmB,EAAE,CAEpF;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,WAAW,EACxB,QAAQ,EAAE,mBAAmB,EAAE,GAC9B;IAAE,MAAM,EAAE,mBAAmB,EAAE,CAAC;IAAC,UAAU,EAAE,CAAC,mBAAmB,GAAG;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,EAAE,CAAA;CAAE,CAkB7F;AAED,MAAM,WAAW,uBAAuB;IACtC;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,sHAAsH;IACtH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,8FAA8F;IAC9F,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB;;;;;OAKG;IACH,IAAI,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;KAAE,CAAC;CAC3D;AAED;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,OAAO,GAAE;IAAE,aAAa,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,OAAO,CAAC,cAAc,CAAC,CASrJ;AAUD;;;;;;;;GAQG;AACH,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAiB,EAC5C,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,sBAAsB,CAAC,CAqEjC"}
|
package/dist/workspace/checks.js
CHANGED
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
* | WSP126, WSP127 | box intent: the decision record a box names exists, and constrains a member or path of this workspace (#2850, #2857) |
|
|
38
38
|
* | WSP141, WSP142 | member links resolved against a live read, with `--live` (#2549) |
|
|
39
39
|
* | WSP131 to WSP133 | diagram artifacts: source and render exist, a recorded source hash still matches (#2764) |
|
|
40
|
-
* | WSP151 |
|
|
40
|
+
* | WSP151 | what a member under `ci.workflow` still lacks (#4168 step 6) |
|
|
41
41
|
* | WSP161 to WSP165 | the security groups the declaration opts into: what each still lacks (#4168 step 7) |
|
|
42
42
|
*/
|
|
43
43
|
import { realpathSync } from "node:fs";
|
|
@@ -56,6 +56,7 @@ import { RECORD_CHECKS } from "./checks/records.js";
|
|
|
56
56
|
import { BOX_CHECKS } from "./checks/boxes.js";
|
|
57
57
|
import { DIAGRAM_CHECKS } from "./checks/diagrams.js";
|
|
58
58
|
import { SECURITY_CHECKS } from "./checks/security.js";
|
|
59
|
+
import { CI_WORKFLOW_CHECKS } from "./checks/ci-workflow.js";
|
|
59
60
|
import { loadDeclaredKinds } from "./declared-kinds.js";
|
|
60
61
|
import { resolveBoxIntents } from "./box-intent.js";
|
|
61
62
|
import { gatherLexiconOutputs } from "./lexicon-outputs.js";
|
|
@@ -273,6 +274,8 @@ export const WORKSPACE_CHECKS = [
|
|
|
273
274
|
...DIAGRAM_CHECKS,
|
|
274
275
|
// Links resolved against a live read, with --live (#2549), WSP141 and WSP142.
|
|
275
276
|
...LIVE_CHECKS,
|
|
277
|
+
// What a member under ci.workflow still lacks (#4168 step 6), WSP151.
|
|
278
|
+
...CI_WORKFLOW_CHECKS,
|
|
276
279
|
// The security groups the declaration opts into (#4168 step 7), WSP161 to WSP165.
|
|
277
280
|
...SECURITY_CHECKS,
|
|
278
281
|
];
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `chant ci init --workflow <name> [--forge <forge>] [--security <group>]...
|
|
3
|
+
* [--yes]` (#4168 step 6, section 9): set a workspace up for a prescribed
|
|
4
|
+
* delivery workflow (../ci-workflow.ts).
|
|
5
|
+
*
|
|
6
|
+
* It proposes, prints the proposal as a diff, and writes only on `--yes` or a
|
|
7
|
+
* yes at the prompt. What it proposes comes from what `workspace check`'s
|
|
8
|
+
* WSP151 reports for the workspace as it would be with `ci.workflow` set, so
|
|
9
|
+
* a second run proposes only what is still missing, and nothing once the
|
|
10
|
+
* workspace has it all.
|
|
11
|
+
*
|
|
12
|
+
* - The declaration gains `ci.workflow`, a `ci.green` block when it has none
|
|
13
|
+
* (one phase per GitHub workflow, its jobs as the check runs, and the
|
|
14
|
+
* workflows a pull request runs as `preMerge`), and `preMerge` when the
|
|
15
|
+
* block has none. `--security` adds groups to the top-level `security`;
|
|
16
|
+
* without it no group is turned on, and the groups are listed.
|
|
17
|
+
* - A member that builds with chant and declares no component gets a
|
|
18
|
+
* `<member>.component.ts` stub with a gate and a TODO line, which WSP151
|
|
19
|
+
* keeps reporting until someone fills the stub in. A `chant.config.ts`
|
|
20
|
+
* that declares no environments gains `environments: ["staging", "prod"]`
|
|
21
|
+
* when its default export is a plain object literal.
|
|
22
|
+
* - The generated files are written by the generators that own them, run
|
|
23
|
+
* after the edits: `chant build --components --generate <forge> --pr-loop`
|
|
24
|
+
* in each member, `chant ci workflow` for the tick, and `chant release
|
|
25
|
+
* workflow` for the publish job. Each is named in the proposal before it
|
|
26
|
+
* runs.
|
|
27
|
+
*
|
|
28
|
+
* It never edits a file the diff did not show, and never overwrites a file
|
|
29
|
+
* it proposed to create that appeared in the meantime.
|
|
30
|
+
*/
|
|
31
|
+
import type { CommandContext } from "../cli/registry.js";
|
|
32
|
+
import type { WorkspaceDiagnostic } from "./checks.js";
|
|
33
|
+
import { STUB_MARKER } from "./ci-workflow.js";
|
|
34
|
+
export { STUB_MARKER };
|
|
35
|
+
import { type CiWorkflow } from "./declaration.js";
|
|
36
|
+
import { type SecurityGroup } from "./security.js";
|
|
37
|
+
import { type ReleaseWorkflowForge } from "./release-workflow.js";
|
|
38
|
+
/** The environments a config with none is given. */
|
|
39
|
+
export declare const DEFAULT_ENVIRONMENTS: readonly ["staging", "prod"];
|
|
40
|
+
/** One file the proposal writes: created when `before` is null. */
|
|
41
|
+
export interface ProposedFile {
|
|
42
|
+
path: string;
|
|
43
|
+
before: string | null;
|
|
44
|
+
after: string;
|
|
45
|
+
}
|
|
46
|
+
/** A generator the proposal runs after the edits, in `cwd` (relative to the workspace root). */
|
|
47
|
+
export interface ProposedCommand {
|
|
48
|
+
cwd: string;
|
|
49
|
+
args: string[];
|
|
50
|
+
why: string;
|
|
51
|
+
}
|
|
52
|
+
export interface CiInitProposal {
|
|
53
|
+
files: ProposedFile[];
|
|
54
|
+
commands: ProposedCommand[];
|
|
55
|
+
/** What the proposal leaves to a person, such as a component with no gate. */
|
|
56
|
+
notes: string[];
|
|
57
|
+
/** The WSP151 findings the proposal answers. */
|
|
58
|
+
findings: WorkspaceDiagnostic[];
|
|
59
|
+
}
|
|
60
|
+
export interface CiInitOptions {
|
|
61
|
+
workflow: CiWorkflow;
|
|
62
|
+
forge?: ReleaseWorkflowForge;
|
|
63
|
+
security?: readonly SecurityGroup[];
|
|
64
|
+
}
|
|
65
|
+
/** The forge whose pipeline files the repository has, or null. */
|
|
66
|
+
export declare function inferForge(repoRoot: string): ReleaseWorkflowForge | null;
|
|
67
|
+
/** The branch `origin/HEAD` names, else `main`. */
|
|
68
|
+
export declare function inferTrunk(repoRoot: string): string;
|
|
69
|
+
/**
|
|
70
|
+
* A `ci.green` block from the repository's GitHub workflows: a phase per
|
|
71
|
+
* workflow holding its jobs' check runs, all required, and those a pull
|
|
72
|
+
* request runs as `preMerge`. chant's own generated workflows are left out.
|
|
73
|
+
*/
|
|
74
|
+
export declare function inferGreen(repoRoot: string): {
|
|
75
|
+
branch: string;
|
|
76
|
+
phases: Record<string, string[]>;
|
|
77
|
+
require: string[];
|
|
78
|
+
preMerge: string[];
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* The declaration's text with `next`'s top-level keys. A key the file lacks
|
|
82
|
+
* is added as text before the closing brace, so the rest keeps its layout; a
|
|
83
|
+
* key it has whose value changes rewrites the file, two-space indented.
|
|
84
|
+
*/
|
|
85
|
+
export declare function editDeclarationText(text: string, raw: Record<string, unknown>, next: Record<string, unknown>): string;
|
|
86
|
+
/** The component stub for a member that declares none: a gate and a TODO, so WSP151 keeps asking until it is filled in. */
|
|
87
|
+
export declare function componentStub(member: string, lastEnvironment: string): string;
|
|
88
|
+
/** The config with `environments` added after `export default {`, or null when its default export is not a plain object literal. */
|
|
89
|
+
export declare function withEnvironments(config: string, environments?: readonly string[]): string | null;
|
|
90
|
+
/**
|
|
91
|
+
* What `chant ci init` would write for the workspace at `root`, and the
|
|
92
|
+
* generators it would run. Reads only; {@link applyCiInit} writes.
|
|
93
|
+
*/
|
|
94
|
+
export declare function proposeCiInit(root: string, options: CiInitOptions): CiInitProposal;
|
|
95
|
+
/** A unified-style diff of two texts, for the proposal. Line-based, from their longest common subsequence. */
|
|
96
|
+
export declare function lineDiff(path: string, before: string | null, after: string): string;
|
|
97
|
+
/** Write the proposal's files. A file it would create that now exists is refused, and nothing is written. */
|
|
98
|
+
export declare function applyCiInit(root: string, proposal: CiInitProposal): string[];
|
|
99
|
+
export declare function runCiInit(ctx: CommandContext): Promise<number>;
|
|
100
|
+
//# sourceMappingURL=ci-init.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ci-init.d.ts","sourceRoot":"","sources":["../../src/workspace/ci-init.ts"],"names":[],"mappings":"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"}
|