@intentius/chant 0.59.0 → 0.60.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.
Files changed (42) hide show
  1. package/dist/build-params.d.ts +2 -2
  2. package/dist/cli/commands/lint.d.ts.map +1 -1
  3. package/dist/cli/handlers/lint.d.ts.map +1 -1
  4. package/dist/components/pilots/alb-ecs.pilot.d.ts +2 -2
  5. package/dist/config.d.ts +4 -4
  6. package/dist/lexicon.d.ts +48 -5
  7. package/dist/lexicon.d.ts.map +1 -1
  8. package/dist/lifecycle/observe.d.ts +4 -4
  9. package/dist/op/activities/index.d.ts +1 -1
  10. package/dist/op/activities/index.d.ts.map +1 -1
  11. package/dist/op/activities/reconcile.d.ts +79 -7
  12. package/dist/op/activities/reconcile.d.ts.map +1 -1
  13. package/dist/op/gate-summary.d.ts +16 -4
  14. package/dist/op/gate-summary.d.ts.map +1 -1
  15. package/dist/params.d.ts +1 -1
  16. package/dist/project-root.d.ts +2 -2
  17. package/package.json +1 -1
  18. package/src/build-params.ts +2 -2
  19. package/src/cli/commands/build.ts +8 -8
  20. package/src/cli/commands/lint.test.ts +151 -0
  21. package/src/cli/commands/lint.ts +37 -4
  22. package/src/cli/handlers/graph.test.ts +4 -4
  23. package/src/cli/handlers/graph.ts +11 -11
  24. package/src/cli/handlers/lint.test.ts +107 -0
  25. package/src/cli/handlers/lint.ts +30 -0
  26. package/src/components/SPRAWL-VALIDATION.md +5 -5
  27. package/src/components/pilots/README.md +1 -1
  28. package/src/components/pilots/alb-ecs.pilot.ts +2 -2
  29. package/src/config.ts +4 -4
  30. package/src/discovery/fold-import.test.ts +1 -1
  31. package/src/discovery/fold-import.ts +3 -3
  32. package/src/lexicon.ts +49 -5
  33. package/src/lifecycle/observe.test.ts +2 -2
  34. package/src/lifecycle/observe.ts +8 -8
  35. package/src/lifecycle/release-ledger.test.ts +2 -2
  36. package/src/op/activities/index.ts +8 -1
  37. package/src/op/activities/reconcile.test.ts +238 -0
  38. package/src/op/activities/reconcile.ts +267 -13
  39. package/src/op/gate-summary.test.ts +62 -0
  40. package/src/op/gate-summary.ts +17 -5
  41. package/src/params.ts +1 -1
  42. package/src/project-root.ts +2 -2
@@ -0,0 +1,62 @@
1
+ /**
2
+ * The pending-gate block a CI run leaves where people actually look (#2243),
3
+ * and the second surface GitLab needs for it (#2256).
4
+ *
5
+ * GitHub Actions, Forgejo Actions and Gitea all hand a step a markdown
6
+ * scratchpad through `GITHUB_STEP_SUMMARY`. GitLab CI has no equivalent at
7
+ * all — a job's surfaces are its log and its artifacts — so `CHANT_GATE_SUMMARY`
8
+ * names a path the generated GitLab job also declares under `artifacts:`. One
9
+ * more environment variable, the same block, still no API call and no token.
10
+ */
11
+
12
+ import { mkdtempSync, readFileSync, existsSync } from "node:fs";
13
+ import { tmpdir } from "node:os";
14
+ import { join } from "node:path";
15
+ import { describe, test, expect } from "vitest";
16
+ import { gatedRunSummaryMarkdown, writeGatedRunSummary } from "./gate-summary";
17
+
18
+ const summary = { op: "app-apply", gate: "approve-app-apply", expiresAt: "2026-09-08T00:00:00Z" };
19
+
20
+ function tempPath(name: string): string {
21
+ return join(mkdtempSync(join(tmpdir(), "chant-gate-")), name);
22
+ }
23
+
24
+ describe("gatedRunSummaryMarkdown (#2243)", () => {
25
+ test("names the gate, the exact approve command and the ledger path", () => {
26
+ const md = gatedRunSummaryMarkdown(summary);
27
+ expect(md).toContain("Waiting on gate `approve-app-apply`");
28
+ expect(md).toContain("chant approve app-apply approve-app-apply --approver <you>");
29
+ expect(md).toContain("_gates/app-apply.jsonl");
30
+ });
31
+ });
32
+
33
+ describe("writeGatedRunSummary surfaces (#2243, #2256)", () => {
34
+ test("writes to GITHUB_STEP_SUMMARY where the forge sets one", () => {
35
+ const path = tempPath("step-summary.md");
36
+ expect(writeGatedRunSummary(summary, { GITHUB_STEP_SUMMARY: path })).toBe(path);
37
+ expect(readFileSync(path, "utf8")).toContain("approve-app-apply");
38
+ });
39
+
40
+ test("writes to CHANT_GATE_SUMMARY where the forge sets none — GitLab's artifact path", () => {
41
+ const path = tempPath("chant-gate-app-apply.md");
42
+ expect(writeGatedRunSummary(summary, { CHANT_GATE_SUMMARY: path })).toBe(path);
43
+ expect(readFileSync(path, "utf8")).toContain("chant approve app-apply approve-app-apply");
44
+ });
45
+
46
+ test("the forge's own variable wins when both are set", () => {
47
+ const forge = tempPath("step-summary.md");
48
+ const artifact = tempPath("chant-gate-app-apply.md");
49
+ expect(
50
+ writeGatedRunSummary(summary, { GITHUB_STEP_SUMMARY: forge, CHANT_GATE_SUMMARY: artifact }),
51
+ ).toBe(forge);
52
+ expect(existsSync(artifact)).toBe(false);
53
+ });
54
+
55
+ test("a run with neither variable writes nothing and reports nothing", () => {
56
+ expect(writeGatedRunSummary(summary, {})).toBeUndefined();
57
+ });
58
+
59
+ test("an unwritable path is swallowed: a decided run does not change outcome over a scratchpad", () => {
60
+ expect(writeGatedRunSummary(summary, { CHANT_GATE_SUMMARY: "/no/such/dir/gate.md" })).toBeUndefined();
61
+ });
62
+ });
@@ -8,9 +8,14 @@
8
8
  * markdown scratchpad through `GITHUB_STEP_SUMMARY`, rendered at the top of
9
9
  * the run page; anything else that sets the variable gets the same block.
10
10
  *
11
- * That is the whole forge coupling: one environment variable, appended to
12
- * when it is set, and nothing at all when it is not. No API call, no token,
13
- * no flag to turn it on.
11
+ * GitLab CI sets no such variable and has no step summary at all: a job's
12
+ * surfaces are its log and its artifacts (#2256). So `CHANT_GATE_SUMMARY`
13
+ * names a second path, which the generated GitLab job sets to a file it also
14
+ * declares under `artifacts:`. Same block, same rule, one more variable.
15
+ *
16
+ * That is the whole forge coupling: two environment variables, appended to
17
+ * whichever is set, and nothing at all when neither is. No API call, no
18
+ * token, no flag to turn it on.
14
19
  */
15
20
 
16
21
  import { appendFileSync } from "node:fs";
@@ -63,7 +68,14 @@ export function gatedRunSummaryMarkdown(summary: GatedRunSummary): string {
63
68
 
64
69
  /**
65
70
  * Append {@link gatedRunSummaryMarkdown} to the file `GITHUB_STEP_SUMMARY`
66
- * names, when the variable is set and the file can be written.
71
+ * names, or, where the forge sets no such variable, the one
72
+ * `CHANT_GATE_SUMMARY` names (#2256) — when it is set and the file can be
73
+ * written.
74
+ *
75
+ * The forge's own variable wins where both are set: a step summary is
76
+ * rendered on the run page, an artifact has to be downloaded, and writing
77
+ * both would put the same block in two places on a forge that already shows
78
+ * one of them.
67
79
  *
68
80
  * Returns the path written, or `undefined` when there was nothing to write to.
69
81
  * A write that fails is swallowed: a run that already decided its outcome must
@@ -73,7 +85,7 @@ export function writeGatedRunSummary(
73
85
  summary: GatedRunSummary,
74
86
  env: NodeJS.ProcessEnv = process.env,
75
87
  ): string | undefined {
76
- const path = env.GITHUB_STEP_SUMMARY;
88
+ const path = env.GITHUB_STEP_SUMMARY || env.CHANT_GATE_SUMMARY;
77
89
  if (!path) return undefined;
78
90
  try {
79
91
  appendFileSync(path, gatedRunSummaryMarkdown(summary));
package/src/params.ts CHANGED
@@ -6,7 +6,7 @@
6
6
  * is a deploy-time CloudFormation parameter: it emits a `Parameters:` block and
7
7
  * resolves when the STACK deploys. A build-time parameter resolves before the
8
8
  * template is even synthesized — its value can change WHICH resources are
9
- * produced at all (loomster's `LOOM_TIER` selecting `light` vs `production` vs
9
+ * produced at all (a `tier` parameter selecting `light` vs `production` vs
10
10
  * `production-ha`), which a deploy-time `Parameter` structurally cannot do.
11
11
  *
12
12
  * Project source never reads `process.env` directly to vary a build — that
@@ -12,8 +12,8 @@ import { dirname, join, resolve } from "path";
12
12
  * `src/<stack>` layout — `chant build src/<stack>` two or more levels below
13
13
  * the project root — silently never found the root config: `buildParams`'
14
14
  * declared `env:` mappings went inert, `ownership`/`lint.policies`/etc quietly
15
- * fell back to defaults, and nothing warned (loomster#162: `LOOM_TIER`/
16
- * `LOOM_ENV` inert under every `npm run synth:*` for two releases).
15
+ * fell back to defaults, and nothing warned. That failure ran under every
16
+ * `npm run synth:*` of one project for two releases before anyone noticed it.
17
17
  *
18
18
  * `findProjectConfig` is the one walk every config-discovery call site now
19
19
  * shares. It stops at the first of: