@intentius/chant 0.68.0 → 0.68.1
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.
|
@@ -66,6 +66,16 @@ export declare const sanitizeOneLine: typeof sanitizeLedgerText;
|
|
|
66
66
|
* The gate a gated `chant run` stopped at, read off its JSON result (#2119) —
|
|
67
67
|
* pure, unit-tested directly rather than only through `dispatchOp`'s
|
|
68
68
|
* subprocess plumbing. `undefined` when the output says nothing about a gate.
|
|
69
|
+
*
|
|
70
|
+
* Reads `gate.name`, matching a real `OpRunStatus`/`OpRunRecord`
|
|
71
|
+
* (`../runtime.ts`'s own `gate?: { name: string; since: string }`) — a gated
|
|
72
|
+
* run's record never carries a nested field literally named `gate`. Checking
|
|
73
|
+
* `gate.gate` instead (chant#2396) is `typeof undefined === "string"`, always
|
|
74
|
+
* false, so every gated dispatch fell through to the regex below, which also
|
|
75
|
+
* never matches a `--json` result: the phrase it looks for belongs to the
|
|
76
|
+
* human-readable render `--json` mode suppresses. The regex stays as the
|
|
77
|
+
* fallback for exactly that human-mode case, where the caller's output is
|
|
78
|
+
* prose rather than JSON.
|
|
69
79
|
*/
|
|
70
80
|
export declare function classifyDispatchFailure(raw: string): {
|
|
71
81
|
gateName: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"converge.d.ts","sourceRoot":"","sources":["../../../src/op/activities/converge.ts"],"names":[],"mappings":"AAkCA,OAAO,EAEL,KAAK,YAAY,EAGlB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAuB,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEzE,OAAO,EAAkB,KAAK,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAChF,OAAO,EAKL,kBAAkB,EAClB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACxB,MAAM,iCAAiC,CAAC;AAQzC,+JAA+J;AAC/J,MAAM,MAAM,sBAAsB,GAAG,YAAY,CAAC,eAAe,CAAC,CAAC;AAEnE,MAAM,WAAW,gBAAgB;IAC/B,mFAAmF;IACnF,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ;;;;;;;;;;;OAWG;IACH,IAAI,EAAE,SAAS,GAAG,WAAW,GAAG,OAAO,CAAC;IACxC,mHAAmH;IACnH,MAAM,EAAE,MAAM,CAAC;IACf,yCAAyC;IACzC,KAAK,EAAE,sBAAsB,EAAE,CAAC;IAChC;;;;;OAKG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,kBAAkB;IACjC,gIAAgI;IAChI,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,kGAAkG;IAClG,KAAK,EAAE,MAAM,CAAC;IACd,8DAA8D;IAC9D,GAAG,EAAE,MAAM,CAAC;CACb;AAMD;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,eAAe,2BAAqB,CAAC;AA0BlD
|
|
1
|
+
{"version":3,"file":"converge.d.ts","sourceRoot":"","sources":["../../../src/op/activities/converge.ts"],"names":[],"mappings":"AAkCA,OAAO,EAEL,KAAK,YAAY,EAGlB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAuB,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEzE,OAAO,EAAkB,KAAK,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAChF,OAAO,EAKL,kBAAkB,EAClB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACxB,MAAM,iCAAiC,CAAC;AAQzC,+JAA+J;AAC/J,MAAM,MAAM,sBAAsB,GAAG,YAAY,CAAC,eAAe,CAAC,CAAC;AAEnE,MAAM,WAAW,gBAAgB;IAC/B,mFAAmF;IACnF,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ;;;;;;;;;;;OAWG;IACH,IAAI,EAAE,SAAS,GAAG,WAAW,GAAG,OAAO,CAAC;IACxC,mHAAmH;IACnH,MAAM,EAAE,MAAM,CAAC;IACf,yCAAyC;IACzC,KAAK,EAAE,sBAAsB,EAAE,CAAC;IAChC;;;;;OAKG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,kBAAkB;IACjC,gIAAgI;IAChI,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,kGAAkG;IAClG,KAAK,EAAE,MAAM,CAAC;IACd,8DAA8D;IAC9D,GAAG,EAAE,MAAM,CAAC;CACb;AAMD;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,eAAe,2BAAqB,CAAC;AA0BlD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAerF;AA0CD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,gBAAgB,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,WAAW,GAAG,SAAS,GAAG,OAAO,CAKtH;AAED;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,mBAAmB,EAC5B,IAAI,EAAE,gBAAgB,CAAC,MAAM,CAAC,EAC9B,SAAS,EAAE,WAAW,GAAG,SAAS,GACjC,mBAAmB,CAWrB;AAaD;;;;;;;GAOG;AACH,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,QAAQ,EAAE,mBAAmB,EAAE,CAAC;CACjC;AAED,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,eAAe,EACxB,KAAK,EAAE,sBAAsB,EAAE,EAC/B,YAAY,EAAE,kBAAkB,EAAE,EAClC,IAAI,EAAE,gBAAgB,CAAC,MAAM,CAAC,EAC9B,MAAM,EAAE,MAAM,GACb,gBAAgB,CAmDlB;AAoBD,wBAAsB,YAAY,CAAC,IAAI,EAAE,gBAAgB,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAyF5G"}
|
package/package.json
CHANGED
|
@@ -307,12 +307,38 @@ describe("classifyDispatchFailure", () => {
|
|
|
307
307
|
const raw = JSON.stringify({
|
|
308
308
|
op: "fountain-apply",
|
|
309
309
|
status: "gated",
|
|
310
|
-
gate: {
|
|
310
|
+
gate: { name: "rollout-gate", since: "t2" },
|
|
311
311
|
records: [],
|
|
312
312
|
});
|
|
313
313
|
expect(classifyDispatchFailure(raw)).toEqual({ gateName: "rollout-gate" });
|
|
314
314
|
});
|
|
315
315
|
|
|
316
|
+
// chant#2396: a real gated `OpRunRecord` (`../runtime.ts`'s own
|
|
317
|
+
// `gate?: { name: string; since: string }`) never carries a nested field
|
|
318
|
+
// literally named `gate` — `parsed.gate?.gate` is always `undefined`, so
|
|
319
|
+
// this used to fall through to a regex that never matches `--json` output
|
|
320
|
+
// either, and a `ConvergeOp` tick recorded every gated dispatch as an
|
|
321
|
+
// ordinary "reported" failure. This is the exact record shape
|
|
322
|
+
// `TerraformApplyOp`'s own `chant run dev-apply --json` printed while
|
|
323
|
+
// building `examples/converge-operator` against a live floci.
|
|
324
|
+
test("reads the gate off a real gated Op run record — gate.name, not gate.gate (#2396)", () => {
|
|
325
|
+
const raw = JSON.stringify({
|
|
326
|
+
version: 1,
|
|
327
|
+
id: "local-abc123",
|
|
328
|
+
op: "dev-apply",
|
|
329
|
+
env: "dev",
|
|
330
|
+
started: "2026-09-11T05:39:16.000Z",
|
|
331
|
+
ended: "2026-09-11T05:39:16.058Z",
|
|
332
|
+
status: "gated",
|
|
333
|
+
labels: {},
|
|
334
|
+
outcomes: {},
|
|
335
|
+
phases: [],
|
|
336
|
+
gate: { name: "approve-dev-apply", since: "2026-09-11T05:39:16.058Z" },
|
|
337
|
+
approve: "chant approve dev-apply approve-dev-apply",
|
|
338
|
+
});
|
|
339
|
+
expect(classifyDispatchFailure(raw)).toEqual({ gateName: "approve-dev-apply" });
|
|
340
|
+
});
|
|
341
|
+
|
|
316
342
|
test("falls back to the human summary line, wherever it appears in the output", () => {
|
|
317
343
|
const raw = 'some earlier noise\nOp "prod-apply" is gated on "prod-approval" after 0.3s\n approve : chant approve prod-apply prod-approval';
|
|
318
344
|
expect(classifyDispatchFailure(raw)).toEqual({ gateName: "prod-approval" });
|
|
@@ -153,15 +153,25 @@ const GATED_EXIT_CODE = 3;
|
|
|
153
153
|
* The gate a gated `chant run` stopped at, read off its JSON result (#2119) —
|
|
154
154
|
* pure, unit-tested directly rather than only through `dispatchOp`'s
|
|
155
155
|
* subprocess plumbing. `undefined` when the output says nothing about a gate.
|
|
156
|
+
*
|
|
157
|
+
* Reads `gate.name`, matching a real `OpRunStatus`/`OpRunRecord`
|
|
158
|
+
* (`../runtime.ts`'s own `gate?: { name: string; since: string }`) — a gated
|
|
159
|
+
* run's record never carries a nested field literally named `gate`. Checking
|
|
160
|
+
* `gate.gate` instead (chant#2396) is `typeof undefined === "string"`, always
|
|
161
|
+
* false, so every gated dispatch fell through to the regex below, which also
|
|
162
|
+
* never matches a `--json` result: the phrase it looks for belongs to the
|
|
163
|
+
* human-readable render `--json` mode suppresses. The regex stays as the
|
|
164
|
+
* fallback for exactly that human-mode case, where the caller's output is
|
|
165
|
+
* prose rather than JSON.
|
|
156
166
|
*/
|
|
157
167
|
export function classifyDispatchFailure(raw: string): { gateName: string } | undefined {
|
|
158
168
|
for (const line of raw.split("\n")) {
|
|
159
169
|
const trimmed = line.trim();
|
|
160
170
|
if (!trimmed.startsWith("{")) continue;
|
|
161
171
|
try {
|
|
162
|
-
const parsed = JSON.parse(trimmed) as { status?: string; gate?: {
|
|
163
|
-
if (parsed.status === "gated" && typeof parsed.gate?.
|
|
164
|
-
return { gateName: parsed.gate.
|
|
172
|
+
const parsed = JSON.parse(trimmed) as { status?: string; gate?: { name?: string } };
|
|
173
|
+
if (parsed.status === "gated" && typeof parsed.gate?.name === "string") {
|
|
174
|
+
return { gateName: parsed.gate.name };
|
|
165
175
|
}
|
|
166
176
|
} catch {
|
|
167
177
|
// Not this line's JSON — keep looking.
|