@intentius/chant 0.116.0 → 0.118.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/build.d.ts +1 -1
- package/dist/build.d.ts.map +1 -1
- package/dist/cli/commands/build.d.ts.map +1 -1
- package/dist/cli/handlers/gate-resume.d.ts +44 -0
- package/dist/cli/handlers/gate-resume.d.ts.map +1 -0
- package/dist/cli/handlers/operator.d.ts +1 -0
- package/dist/cli/handlers/operator.d.ts.map +1 -1
- package/dist/cli/handlers/run-wave.d.ts.map +1 -1
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/registry.d.ts +8 -0
- package/dist/cli/registry.d.ts.map +1 -1
- package/dist/discovery/files.d.ts +8 -0
- package/dist/discovery/files.d.ts.map +1 -1
- package/dist/lexicon.d.ts +10 -1
- package/dist/lexicon.d.ts.map +1 -1
- package/dist/lifecycle/gate-ledger.d.ts +18 -0
- package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
- package/dist/op/gate-resume.d.ts +104 -0
- package/dist/op/gate-resume.d.ts.map +1 -0
- package/dist/op/gate-review.d.ts +113 -0
- package/dist/op/gate-review.d.ts.map +1 -0
- package/dist/op/gate.d.ts.map +1 -1
- package/dist/op/op-waves-run.d.ts +47 -1
- package/dist/op/op-waves-run.d.ts.map +1 -1
- package/dist/op/op-waves.d.ts +39 -0
- package/dist/op/op-waves.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/build.ts +13 -2
- package/src/cli/commands/build.ts +2 -1
- package/src/cli/handlers/gate-resume.test.ts +51 -0
- package/src/cli/handlers/gate-resume.ts +166 -0
- package/src/cli/handlers/operator.ts +8 -2
- package/src/cli/handlers/run-wave.ts +13 -1
- package/src/cli/main.ts +21 -3
- package/src/cli/plugins.ts +1 -1
- package/src/cli/registry.ts +8 -0
- package/src/discovery/files.ts +18 -0
- package/src/lexicon.ts +10 -1
- package/src/lifecycle/gate-ledger.ts +14 -0
- package/src/op/gate-resume.e2e.test.ts +135 -0
- package/src/op/gate-resume.test.ts +177 -0
- package/src/op/gate-resume.ts +267 -0
- package/src/op/gate-review.test.ts +225 -0
- package/src/op/gate-review.ts +339 -0
- package/src/op/gate.ts +4 -0
- package/src/op/op-waves-run.ts +191 -13
- package/src/op/op-waves.ts +51 -0
package/src/op/op-waves.ts
CHANGED
|
@@ -27,6 +27,12 @@
|
|
|
27
27
|
* the same digest a component fan-out's wave binds). Whether it waits at all
|
|
28
28
|
* is the wave's gate policy, read from the base commit's copy of the spec
|
|
29
29
|
* file, so a change cannot loosen the rule that gates its own merge.
|
|
30
|
+
*
|
|
31
|
+
* So is which approvals count (#3684), the wave's `approval`: `ledger` (any
|
|
32
|
+
* `chant approve` of the digest), `sealed` (only one whose seal verifies
|
|
33
|
+
* against the signers file at base) or `pr-review` (also the merged pull
|
|
34
|
+
* request's review of its head, by a writer other than its author, when the
|
|
35
|
+
* head planned the same digest). See `./gate-review.ts`.
|
|
30
36
|
*/
|
|
31
37
|
|
|
32
38
|
import type { OpEnvironment, OpSetupStep } from "../lexicon";
|
|
@@ -42,6 +48,17 @@ export type OpWaveGatePolicy =
|
|
|
42
48
|
|
|
43
49
|
export const OP_WAVE_GATE_POLICIES: readonly OpWaveGatePolicy[] = ["always", "on-destructive", "never"];
|
|
44
50
|
|
|
51
|
+
/** Which approvals of a gate's digest count (#3684). See `./gate-review.ts`. */
|
|
52
|
+
export type GateApprovalSource =
|
|
53
|
+
/** Any resolution on `chant/lifecycle` that names the digest. */
|
|
54
|
+
| "ledger"
|
|
55
|
+
/** As `ledger`, and the merged pull request's review of its head, by a writer other than its author. */
|
|
56
|
+
| "pr-review"
|
|
57
|
+
/** Only a resolution sealed by a key the signers file at base lists for its approver. */
|
|
58
|
+
| "sealed";
|
|
59
|
+
|
|
60
|
+
export const GATE_APPROVAL_SOURCES: readonly GateApprovalSource[] = ["ledger", "pr-review", "sealed"];
|
|
61
|
+
|
|
45
62
|
/** One Op run in a wave: an Op applied to one target (an environment, a database, a tenant). */
|
|
46
63
|
export interface OpWaveRun {
|
|
47
64
|
/** What the run applies to. Unique within its wave; it names the run in the set digest. */
|
|
@@ -60,6 +77,11 @@ export interface OpWave {
|
|
|
60
77
|
* spec file at the base commit, never from the change being applied.
|
|
61
78
|
*/
|
|
62
79
|
gate?: OpWaveGatePolicy;
|
|
80
|
+
/**
|
|
81
|
+
* Which approvals of the wave's digest count (#3684). Default `"ledger"`.
|
|
82
|
+
* Like `gate`, the runner reads it from the spec file at the base commit.
|
|
83
|
+
*/
|
|
84
|
+
approval?: GateApprovalSource;
|
|
63
85
|
/**
|
|
64
86
|
* Split the wave into a deciding job and this many share jobs, each
|
|
65
87
|
* applying a slice of the runs. Default 1: one job plans, decides and
|
|
@@ -103,6 +125,29 @@ export interface OpWavesSpec {
|
|
|
103
125
|
/** Apply one run whose plan is at `{plan}`. Default `chant run {op} --env {target}`. */
|
|
104
126
|
apply?: string[];
|
|
105
127
|
waves: OpWave[];
|
|
128
|
+
/**
|
|
129
|
+
* A scheduled job that starts again a wave job whose approval has arrived
|
|
130
|
+
* (#3683): it runs `chant run resume --op <name>`, which re-runs the
|
|
131
|
+
* GitHub run, retries the GitLab job or dispatches the Forgejo workflow.
|
|
132
|
+
* It approves nothing. Absent, no such job is rendered and an approval is
|
|
133
|
+
* followed by `chant approve --resume` or a re-run by hand.
|
|
134
|
+
*/
|
|
135
|
+
resume?: OpWavesResume;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/** The scheduled resume job of an Op waves pipeline (#3683). */
|
|
139
|
+
export interface OpWavesResume {
|
|
140
|
+
/**
|
|
141
|
+
* Five-field cron, such as `"*\/10 * * * *"`. GitHub and Forgejo put it
|
|
142
|
+
* in the workflow; GitLab runs the job in a pipeline schedule you create,
|
|
143
|
+
* which sets the cron.
|
|
144
|
+
*/
|
|
145
|
+
schedule: string;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/** The command a resume job runs. */
|
|
149
|
+
export function opWavesResumeCommand(spec: Pick<OpWavesSpec, "name">): string[] {
|
|
150
|
+
return ["chant", "run", "resume", "--op", spec.name];
|
|
106
151
|
}
|
|
107
152
|
|
|
108
153
|
/** The default apply command. */
|
|
@@ -146,6 +191,9 @@ export function assertOpWavesSpec(spec: OpWavesSpec): void {
|
|
|
146
191
|
throw new Error(`${where}: the \`plan\` command never names {plan}, the file it writes the plan digest to.`);
|
|
147
192
|
}
|
|
148
193
|
if (spec.waves.length === 0) throw new Error(`${where} has no waves.`);
|
|
194
|
+
if (spec.resume !== undefined && (typeof spec.resume.schedule !== "string" || spec.resume.schedule.trim().split(/\s+/).length !== 5)) {
|
|
195
|
+
throw new Error(`${where}: resume.schedule must be a five-field cron expression, such as "*/10 * * * *".`);
|
|
196
|
+
}
|
|
149
197
|
const names = new Set<string>();
|
|
150
198
|
for (const wave of spec.waves) {
|
|
151
199
|
if (!NAME.test(wave.name)) {
|
|
@@ -156,6 +204,9 @@ export function assertOpWavesSpec(spec: OpWavesSpec): void {
|
|
|
156
204
|
if (wave.gate !== undefined && !OP_WAVE_GATE_POLICIES.includes(wave.gate)) {
|
|
157
205
|
throw new Error(`${where}: wave "${wave.name}" has gate "${wave.gate}"; use ${OP_WAVE_GATE_POLICIES.join(", ")}.`);
|
|
158
206
|
}
|
|
207
|
+
if (wave.approval !== undefined && !GATE_APPROVAL_SOURCES.includes(wave.approval)) {
|
|
208
|
+
throw new Error(`${where}: wave "${wave.name}" has approval "${wave.approval}"; use ${GATE_APPROVAL_SOURCES.join(", ")}.`);
|
|
209
|
+
}
|
|
159
210
|
if (wave.runs.length === 0) throw new Error(`${where}: wave "${wave.name}" has no runs.`);
|
|
160
211
|
const targets = new Set<string>();
|
|
161
212
|
for (const run of wave.runs) {
|