@intentius/chant-lexicon-terraform 0.124.50 → 0.124.52

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.
@@ -22,5 +22,10 @@ export declare function parsePinRolloutArgs(rawArgs: string[]): {
22
22
  };
23
23
  /** Exit status for a rollout's status. */
24
24
  export declare function pinRolloutExitCode(status: string): number;
25
+ /** Parse `chant terraform report`'s flags. Throws on an unknown flag, a missing value or a missing required flag. */
26
+ export declare function parseReportArgs(rawArgs: string[]): {
27
+ values: Map<string, string>;
28
+ json: boolean;
29
+ };
25
30
  export declare const terraformCommands: CommandGroup;
26
31
  //# sourceMappingURL=commands.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAuB,MAAM,oCAAoC,CAAC;AAE5F,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AAW3E,qGAAqG;AACrG,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG;IAAE,IAAI,EAAE,uBAAuB,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,CAiDvG;AAED,0CAA0C;AAC1C,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAIzD;AAqBD,eAAO,MAAM,iBAAiB,EAAE,YAI/B,CAAC"}
1
+ {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAuB,MAAM,oCAAoC,CAAC;AAE5F,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AAW3E,qGAAqG;AACrG,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG;IAAE,IAAI,EAAE,uBAAuB,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,CAiDvG;AAED,0CAA0C;AAC1C,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAIzD;AA4BD,qHAAqH;AACrH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG;IAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,CAqBjG;AA+CD,eAAO,MAAM,iBAAiB,EAAE,YAO/B,CAAC"}
package/dist/commands.js CHANGED
@@ -99,8 +99,90 @@ async function runPinRolloutVerb(ctx) {
99
99
  return 1;
100
100
  }
101
101
  }
102
+ const REPORT_USAGE = "usage: chant terraform report --stage tf-plan|tf-apply --plan <show.json> [--applied <show-after-apply.json>] (--out <dir> | --to <url>) " +
103
+ "[--project <host/path>] [--commit <sha>] [--pull-request <n>] [--binary <name>] [--binary-version <v>] [--root-dir <dir>] [--self-root <dir>] [--repo <dir>] " +
104
+ "[--started <iso>] [--finished <iso>] [--json]";
105
+ const REPORT_VALUE_FLAGS = new Set(["--stage", "--plan", "--applied", "--out", "--to", "--project", "--commit", "--pull-request", "--binary", "--binary-version", "--root-dir", "--self-root", "--repo", "--started", "--finished"]);
106
+ /** Parse `chant terraform report`'s flags. Throws on an unknown flag, a missing value or a missing required flag. */
107
+ export function parseReportArgs(rawArgs) {
108
+ const tokens = splitJoinedFlags(rawArgs, new Set(["--json"]));
109
+ const values = new Map();
110
+ let json = false;
111
+ for (let i = 0; i < tokens.length; i++) {
112
+ const t = tokens[i];
113
+ if (t === "--json") {
114
+ json = true;
115
+ continue;
116
+ }
117
+ if (!REPORT_VALUE_FLAGS.has(t))
118
+ throw t.startsWith("-") ? unknownFlagError(t, REPORT_USAGE) : new Error(`unexpected argument "${t}"\n${REPORT_USAGE}`);
119
+ const v = tokens[++i];
120
+ if (v === undefined || v.startsWith("--"))
121
+ throw new Error(`${t} needs a value\n${REPORT_USAGE}`);
122
+ values.set(t, v);
123
+ }
124
+ const stage = values.get("--stage");
125
+ if (stage !== "tf-plan" && stage !== "tf-apply")
126
+ throw new Error(`--stage is tf-plan or tf-apply\n${REPORT_USAGE}`);
127
+ if (!values.has("--plan"))
128
+ throw new Error(`--plan is required\n${REPORT_USAGE}`);
129
+ if (stage === "tf-apply" && !values.has("--applied"))
130
+ throw new Error(`--stage tf-apply needs --applied, the show -json of a plan made after the apply\n${REPORT_USAGE}`);
131
+ if (values.has("--out") === values.has("--to"))
132
+ throw new Error(`give one of --out <dir> and --to <url>\n${REPORT_USAGE}`);
133
+ return { values, json };
134
+ }
135
+ async function runReportVerb(ctx) {
136
+ try {
137
+ const { values, json } = parseReportArgs(ctx.rawArgs);
138
+ const { readFileSync } = await import("node:fs");
139
+ const { runFactsFromEnv, terraformReport, writeReport, httpStore, dirStore, moduleEstates, atmosStackReads, topModule } = await import("./report.js");
140
+ const read = (flag) => {
141
+ const file = values.get(flag);
142
+ try {
143
+ return JSON.parse(readFileSync(file, "utf8"));
144
+ }
145
+ catch (err) {
146
+ throw new Error(`${flag} ${file}: ${err instanceof Error ? err.message : String(err)}`);
147
+ }
148
+ };
149
+ const run = runFactsFromEnv(process.env, { pullRequest: values.get("--pull-request"), project: values.get("--project"), commit: values.get("--commit") });
150
+ const plan = read("--plan");
151
+ // The plan holds no `live` block: each module's estate is read from its directory, <repo>/<root-dir>/<module>.
152
+ const repo = values.get("--repo") ?? process.env.GITHUB_WORKSPACE ?? process.cwd();
153
+ const modules = [...new Set((plan.resource_changes ?? []).map((r) => topModule(String(r.module_address ?? r.address ?? ""))).filter((m) => m !== undefined))];
154
+ const estates = moduleEstates(repo, values.get("--root-dir") ?? "", modules);
155
+ // An Atmos repo wires its components with !terraform.output in the stack manifests, which the plan does not keep.
156
+ const componentReads = atmosStackReads(repo);
157
+ const result = terraformReport({
158
+ stage: values.get("--stage"),
159
+ plan,
160
+ ...(Object.keys(estates).length > 0 ? { estates } : {}),
161
+ ...(Object.keys(componentReads).length > 0 ? { componentReads } : {}),
162
+ ...(values.has("--applied") ? { applied: read("--applied") } : {}),
163
+ run,
164
+ ...(values.has("--binary") ? { binary: values.get("--binary") } : {}),
165
+ ...(values.has("--binary-version") ? { binaryVersion: values.get("--binary-version") } : {}),
166
+ ...(values.has("--root-dir") ? { rootDir: values.get("--root-dir") } : {}),
167
+ ...(values.has("--self-root") ? { selfRoot: values.get("--self-root") } : {}),
168
+ ...(values.has("--started") ? { started: values.get("--started") } : {}),
169
+ finished: values.get("--finished") ?? new Date().toISOString().replace(/\.\d+Z$/, "Z"),
170
+ });
171
+ const store = values.has("--out") ? dirStore(values.get("--out")) : httpStore(values.get("--to"));
172
+ const keys = await writeReport(store, result);
173
+ console.log(json ? JSON.stringify({ path: result.path, keys, row: result.row }, null, 2) : `wrote ${keys.join(", ")}`);
174
+ return 0;
175
+ }
176
+ catch (err) {
177
+ console.error(err instanceof Error ? err.message : String(err));
178
+ return 1;
179
+ }
180
+ }
102
181
  export const terraformCommands = {
103
182
  name: "terraform",
104
- description: "Terraform and OpenTofu roots: roll a module version out as one pin-bump PR per wave",
105
- commands: [{ name: "pin-rollout", description: "Read a pin-bump rollout's state and open the next wave's PR when it is due", handler: runPinRolloutVerb }],
183
+ description: "Terraform and OpenTofu roots: roll a module version out as one pin-bump PR per wave; write a run report from a saved plan",
184
+ commands: [
185
+ { name: "pin-rollout", description: "Read a pin-bump rollout's state and open the next wave's PR when it is due", handler: runPinRolloutVerb },
186
+ { name: "report", description: "Write a terragucci.report/v1 run report and its index row from show -json of a composed plan", handler: runReportVerb },
187
+ ],
106
188
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "algorithm": "sha256",
3
3
  "artifacts": {
4
- "manifest.json": "190cb359f0a343d9ce668c4541eb19a65eb82a6b8f1357359738a838e5c92de5",
4
+ "manifest.json": "2b3f8b18903d43627d811f5ccfb418ddbcf2ce8aecde7fe38eafd28a6a593559",
5
5
  "meta.json": "ca3d163bab055381827226140568f3bef7eaac187cebd76878e0b63e9e442356",
6
6
  "types/index.d.ts": "022927e6a7b351cc4cf52d5f973f60ccd140e5810e17b32fb8868965aa1db161",
7
7
  "rules/plan-before-apply.ts": "7c10245b2c3335253b48ee7d8b075d89f43116bde20313a5d1031b343fef1282",
@@ -56,5 +56,5 @@
56
56
  "rules/tf045.ts": "760b1f4f385fbe7a86897efe3078fdeac11bcc9bfb806285d63db50488174b7b",
57
57
  "skills/chant-terraform.md": "d9ca7b7c28aed0038ce775a3491150298492eed2858fd3651ed9bfca0e577ae8"
58
58
  },
59
- "composite": "aee256d820fc55f9f0f31c59c3067dcaa999264bb603df28933c8612eab1863c"
59
+ "composite": "acd11f24f4546441f7084748e2617792a690dedbd9677aa19333461e23c47a0d"
60
60
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "terraform",
3
- "version": "0.124.50",
3
+ "version": "0.124.52",
4
4
  "chantVersion": ">=0.1.0",
5
5
  "namespace": "Terraform"
6
6
  }
@@ -0,0 +1,207 @@
1
+ /**
2
+ * `chant terraform report`: a run report from `show -json` of a saved plan, in
3
+ * the `terragucci.report/v1` shape that behold's kiosk reads, for pipelines
4
+ * that run plain `terraform`, `terragrunt`, `atmos` or `choudoufu` and have no
5
+ * terragucci in them.
6
+ *
7
+ * It covers one composed run: a root whose only content is `module` calls
8
+ * (choudoufu's composed root, chant#4419), planned and applied as one. Each
9
+ * top-level module becomes one root of the report, with its part of the plan
10
+ * taken as if it had planned alone (`module.<m>.` off every address), the way
11
+ * terragucci's own composed run reports it.
12
+ *
13
+ * What it writes is the part of the v1 contract a reader needs to draw the
14
+ * run: roots, their changes with before and after values, "known after
15
+ * apply" for values the plan cannot know, one composed wave, the totals,
16
+ * groups and named destroys, the index row, and each root's `reads`: the
17
+ * `data "terraform_estate_outputs"` blocks that read another module's estate,
18
+ * and, in an Atmos repo, the `!terraform.output` calls in its stack manifests,
19
+ * which behold draws as the lines between roots. The estate of each module
20
+ * comes from the `live` block in its directory (`<repo>/<root-dir>/<module>`),
21
+ * since the plan holds none. After an apply, a second
22
+ * `show -json` (of a plan made once the apply finished, whose `prior_state`
23
+ * holds the state) fills in the values the plan left unknown. It writes no
24
+ * report.html, no plan files, no policy, cost or approval fields.
25
+ *
26
+ * The change set is {@link terraformChangeSetPart}'s, and the grouping is
27
+ * chant's `groupChangeSet`, so a report here and one from terragucci agree on
28
+ * what changed.
29
+ */
30
+ type Json = Record<string, unknown>;
31
+ export declare const REPORT_SCHEMA = "terragucci.report/v1";
32
+ export declare const INDEX_SCHEMA = "terragucci.report-index/v1";
33
+ /** The minor of the v1 contract the report is written to: `compose.estate` is minor 48. */
34
+ export declare const REPORT_MINOR = 48;
35
+ /** What terragucci puts in place of a redacted value; the report carries no values it would need to redact. */
36
+ export declare const REDACTED = "(sensitive, redacted by terragucci)";
37
+ export type ReportStage = "tf-plan" | "tf-apply";
38
+ export interface RunFacts {
39
+ /** `<host>/<path>` of the repo, as terragucci names a project. */
40
+ project: string;
41
+ commit: string;
42
+ job_url?: string;
43
+ commit_url?: string;
44
+ pull_request?: string;
45
+ pull_request_url?: string;
46
+ }
47
+ /**
48
+ * The run's facts from a Forgejo, Gitea or GitHub Actions environment
49
+ * (`GITHUB_REPOSITORY`, `GITHUB_SERVER_URL`, `GITHUB_SHA`, `GITHUB_RUN_ID`,
50
+ * which Forgejo sets too). `project` and `commit` override it; `pullRequest`
51
+ * is the number, when the run has one.
52
+ */
53
+ export declare function runFactsFromEnv(env: NodeJS.ProcessEnv, over?: {
54
+ pullRequest?: string;
55
+ project?: string;
56
+ commit?: string;
57
+ }): RunFacts;
58
+ export interface TerraformReportInput {
59
+ stage: ReportStage;
60
+ /** `show -json` of the saved plan. */
61
+ plan: unknown;
62
+ /** tf-apply: `show -json` of a plan made after the apply. Its `prior_state` holds the applied values. */
63
+ applied?: unknown;
64
+ run: RunFacts;
65
+ /** The binary that planned, by name or path. Default `terraform`. */
66
+ binary?: string;
67
+ /** The binary's version, when known. */
68
+ binaryVersion?: string;
69
+ /** Where each root lives in the repo: the root of module `network` is `<rootDir>/network`. Default: the module's name. */
70
+ rootDir?: string;
71
+ /** The path of the composed root itself, which holds any resource declared outside a module. Default: `rootDir`, else `.`. */
72
+ selfRoot?: string;
73
+ /**
74
+ * The estate each module's directory names in its `live` block, by module:
75
+ * what ties a `terraform_estate_outputs` read to the module that owns the
76
+ * estate. The plan carries no `live` block, so {@link moduleEstates} reads it
77
+ * from the directories. A read of an estate none of these names has no edge.
78
+ */
79
+ estates?: Record<string, string>;
80
+ /**
81
+ * What each module reads off the others' outputs through the stack that
82
+ * wires them, by module: Atmos's `!terraform.output` ({@link atmosStackReads}).
83
+ * Atmos resolves those into plain variables before the plan, so the plan
84
+ * holds no trace of them. A module already read through an estate data
85
+ * block is not read twice.
86
+ */
87
+ componentReads?: ComponentReads;
88
+ started?: string;
89
+ finished: string;
90
+ runtime?: string;
91
+ }
92
+ export interface IndexRow {
93
+ project: string;
94
+ commit: string;
95
+ stage: ReportStage;
96
+ finished: string;
97
+ path: string;
98
+ roots: number;
99
+ groups: number;
100
+ totals: {
101
+ create: number;
102
+ update: number;
103
+ replace: number;
104
+ delete: number;
105
+ };
106
+ refused: number;
107
+ failed: number;
108
+ changed: number;
109
+ destroys: string[];
110
+ applied?: string;
111
+ commit_url?: string;
112
+ pull_request?: string;
113
+ pull_request_url?: string;
114
+ job_url?: string;
115
+ }
116
+ /** The top-level module an address or module address is in, or undefined for the composed root's own. */
117
+ export declare function topModule(address: string): string | undefined;
118
+ /** The plan's `resource_changes` that belong to module `m` (undefined: the root's own), each with the module taken off its address. */
119
+ export declare function slicePlan(plan: unknown, m: string | undefined): Json;
120
+ /** One `read` of the report schema's `reads`, as a composed run writes it. */
121
+ export interface ReportRead {
122
+ upstream: string;
123
+ data: string;
124
+ outputs: "planned";
125
+ unknown?: string[];
126
+ /** Why the read is there, when no data block names it: Atmos's `!terraform.output` and the outputs it reads. */
127
+ why?: string;
128
+ composed: true;
129
+ }
130
+ /** The estate named by the first `live { estate = "..." }` block in a directory's `.tf` files, or undefined. */
131
+ export declare function estateOfDir(dir: string): string | undefined;
132
+ /** Each module's estate, read from `<repo>/<rootDir>/<module>`. A module whose directory has no `live` block is left out. */
133
+ export declare function moduleEstates(repo: string, rootDir: string, modules: readonly string[]): Record<string, string>;
134
+ /**
135
+ * Module `m`'s reads of another module's estate, as terragucci writes them for
136
+ * a composed run: `{ upstream, data, outputs: "planned", unknown?, composed }`.
137
+ * `unknown` names the outputs it reads that the plan cannot know. A read of an
138
+ * estate no other module owns has no edge and is left out.
139
+ */
140
+ export declare function estateReads(plan: Json, m: string, estates: Readonly<Record<string, string>>, rootOf: (m: string | undefined) => string): ReportRead[];
141
+ /** What each component reads off another with `!terraform.output`: reader -> upstream -> output names. */
142
+ export type ComponentReads = Record<string, Record<string, string[]>>;
143
+ /**
144
+ * Each component's `!terraform.output <component> [<stack>] <output>` reads in
145
+ * one Atmos stack manifest. The components are the keys under
146
+ * `components.terraform`, named by their `metadata.component` when they set
147
+ * one. A line scan, not a YAML parser: Atmos writes the function as a tagged
148
+ * scalar, one per line, which is all this reads.
149
+ */
150
+ export declare function atmosOutputReads(yaml: string): ComponentReads;
151
+ /**
152
+ * The `!terraform.output` reads of every stack manifest in an Atmos repo: the
153
+ * `.yaml`/`.yml` files under `stacks.base_path` of `<repo>/atmos.yaml`
154
+ * (`stacks` when it names none), joined. Empty when the repo has no atmos.yaml.
155
+ */
156
+ export declare function atmosStackReads(repo: string): ComponentReads;
157
+ /**
158
+ * Module `m`'s reads of the other modules' outputs that the stack wires in
159
+ * (`componentReads`, from Atmos's `!terraform.output`): one per upstream that
160
+ * is a module of this run, planned and composed, as {@link estateReads} writes
161
+ * them. Under choudoufu the reader is planned on the upstream's planned
162
+ * outputs, so `unknown` names the ones read that the plan cannot know.
163
+ */
164
+ export declare function componentOutputReads(plan: Json, m: string, componentReads: ComponentReads, modules: readonly string[], rootOf: (m: string | undefined) => string): ReportRead[];
165
+ export interface TerraformReport {
166
+ report: Json;
167
+ /** The run's directory, relative to the project's own index: `yyyy/mm/<commit>/<stage>`. */
168
+ path: string;
169
+ row: IndexRow;
170
+ }
171
+ /** Where a run's report lives under its project: `yyyy/mm/<commit>/<stage>`, by the day it finished. */
172
+ export declare function runPath(commit: string, stage: ReportStage, finished: string): string;
173
+ /** The report for one composed run, and its index row. Pure. */
174
+ export declare function terraformReport(input: TerraformReportInput): TerraformReport;
175
+ /** How many rows an index keeps. */
176
+ export declare const INDEX_ROWS = 500;
177
+ /**
178
+ * `existing` index text with `row` added: a row at the same path is replaced,
179
+ * newest first, an unreadable index starts again from this row.
180
+ */
181
+ export declare function addToIndex(existing: string | undefined, row: IndexRow): {
182
+ schema: string;
183
+ reports: IndexRow[];
184
+ };
185
+ /** A place the report's files go: a key is `project/...` under the reports prefix. */
186
+ export interface ReportStore {
187
+ read(key: string): Promise<string | undefined>;
188
+ put(key: string, body: string): Promise<void>;
189
+ }
190
+ /**
191
+ * Write the run's `report.json` and add its row to the project's index
192
+ * (`<project>/index.json`, paths relative to it) and to the prefix's
193
+ * (`index.json`, paths starting at the project), the two places terragucci
194
+ * writes. Returns the keys written.
195
+ */
196
+ export declare function writeReport(store: ReportStore, r: TerraformReport): Promise<string[]>;
197
+ /** A store under a local directory: what the tests and a job that uploads itself use. */
198
+ export declare function dirStore(dir: string): ReportStore;
199
+ /**
200
+ * A store behind an HTTP address that takes unsigned `GET` and `PUT` of
201
+ * `<base>/<key>`: the demo's floci bucket, `http://floci:4566/<bucket>/<prefix>`.
202
+ * It signs nothing, so it does not write to AWS S3 or another store that asks
203
+ * for credentials. A 404 on read is no object.
204
+ */
205
+ export declare function httpStore(base: string, fetcher?: typeof fetch): ReportStore;
206
+ export {};
207
+ //# sourceMappingURL=report.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"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"}