@intentius/terragucci 0.4.2 → 0.4.4
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/README.md +1 -0
- package/dist/audit.schema.json +34 -0
- package/dist/changes.schema.json +33 -0
- package/dist/dora.schema.json +104 -0
- package/dist/estate.schema.json +250 -0
- package/dist/history.schema.json +49 -0
- package/dist/inventory.schema.json +38 -0
- package/dist/notify.schema.json +66 -0
- package/dist/report-index.schema.json +67 -0
- package/dist/report.schema.json +137 -2
- package/dist/run.schema.json +88 -0
- package/dist/state-versions.schema.json +42 -0
- package/dist/terragucci.mjs +639 -393
- package/dist/terragucci.mjs.map +4 -4
- package/dist/types.d.ts +150 -9
- package/package.json +3 -2
package/dist/types.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type GenerateSettings } from "./generate-config";
|
|
1
2
|
export declare const BINARIES: readonly ["terraform", "tofu", "choudoufu"];
|
|
2
3
|
export declare const FORGES: readonly ["github", "gitlab", "forgejo"];
|
|
3
4
|
export declare const GATES: readonly ["always", "on-destroy", "never"];
|
|
@@ -57,6 +58,30 @@ export type ApplyWhen = (typeof APPLY_WHEN)[number];
|
|
|
57
58
|
export type Locks = (typeof LOCKS)[number];
|
|
58
59
|
export type ApplyMerge = (typeof APPLY_MERGE)[number];
|
|
59
60
|
export type ApplyRequire = (typeof APPLY_REQUIRES)[number];
|
|
61
|
+
/** The stages a step runs before or after (`steps:`). `drift` is the drift job's refresh-only plan. */
|
|
62
|
+
export declare const STEP_STAGES: readonly ["init", "plan", "apply", "drift"];
|
|
63
|
+
export type StepStage = (typeof STEP_STAGES)[number];
|
|
64
|
+
/** What a step's non-zero exit does: fail the root (the default), or hold its wave for an approval. */
|
|
65
|
+
export declare const STEP_FAILURES: readonly ["fail", "approve"];
|
|
66
|
+
export type StepFailure = (typeof STEP_FAILURES)[number];
|
|
67
|
+
export declare const STEP_KEYS: readonly ["name", "run", "before", "after", "roots", "on_failure"];
|
|
68
|
+
/**
|
|
69
|
+
* One entry of `steps:`. `run` is a shell command, run in the root's
|
|
70
|
+
* directory. Exactly one of `before` and `after` names the stage. `roots`
|
|
71
|
+
* are globs of the roots it runs for (every root when unset).
|
|
72
|
+
* `on_failure: approve` turns a non-zero exit into a hold: the root's wave
|
|
73
|
+
* waits for an approval of its set digest, whatever `gate` says. Only a step
|
|
74
|
+
* that runs before the gate is decided can hold it: one before or after
|
|
75
|
+
* init or plan.
|
|
76
|
+
*/
|
|
77
|
+
export interface StepSettings {
|
|
78
|
+
run: string;
|
|
79
|
+
name?: string;
|
|
80
|
+
before?: StepStage;
|
|
81
|
+
after?: StepStage;
|
|
82
|
+
roots?: string[];
|
|
83
|
+
on_failure?: StepFailure;
|
|
84
|
+
}
|
|
60
85
|
/**
|
|
61
86
|
* `apply:`: when a change applies. `when: merge` (the default) applies the
|
|
62
87
|
* default branch after a merge. `when: pull-request` applies an open pull
|
|
@@ -78,6 +103,12 @@ export interface ApplySettings {
|
|
|
78
103
|
merge?: ApplyMerge;
|
|
79
104
|
merge_token_env?: string;
|
|
80
105
|
requires?: ApplyRequire[];
|
|
106
|
+
/**
|
|
107
|
+
* Minutes between runs of the resume job, which applies a waiting wave once
|
|
108
|
+
* an approval of its digest is on chant/lifecycle (resume.ts). Off when
|
|
109
|
+
* unset. 5 to 60.
|
|
110
|
+
*/
|
|
111
|
+
resume?: number;
|
|
81
112
|
}
|
|
82
113
|
/**
|
|
83
114
|
* Policy as code, off unless set. `tf-plan` runs the engine over each planned
|
|
@@ -169,6 +200,7 @@ export declare const RESPONSES: {
|
|
|
169
200
|
readonly tips: readonly ["pull-request", "off"];
|
|
170
201
|
readonly fmt: readonly ["commit", "off"];
|
|
171
202
|
readonly publish: readonly ["notes", "off"];
|
|
203
|
+
/** next-wave: with `rollouts:` set, init writes a job that runs `respond rollout` on that schedule, so a merged and applied wave's next one opens within one interval. off leaves the job out. */
|
|
172
204
|
readonly rollout: readonly ["next-wave", "off"];
|
|
173
205
|
readonly "version-bump": readonly ["off", "suggest"];
|
|
174
206
|
/** terragucci#30: a typed decision flags a pull request whose description leaves out what its plan destroys or replaces. Needs `decide:`. */
|
|
@@ -236,14 +268,37 @@ export interface AgentCommentSettings {
|
|
|
236
268
|
timeout?: number;
|
|
237
269
|
}
|
|
238
270
|
export declare const AGENT_COMMENT_KEYS: readonly ["command", "key_secret", "max_turns", "timeout"];
|
|
271
|
+
/**
|
|
272
|
+
* `review`: a model reviews each pull request's intent against its plan
|
|
273
|
+
* (review-agent.ts), off unless `agent` is true. It posts a note and never
|
|
274
|
+
* approves; a `tf-apply` wave's policy reads its risk as `input.review`.
|
|
275
|
+
*/
|
|
276
|
+
export interface ReviewSettings {
|
|
277
|
+
/** Turns the review on. */
|
|
278
|
+
agent?: boolean;
|
|
279
|
+
/** The command line, run with the prompt on stdin; it prints the review. Default: Claude Code in print mode with no tools (REVIEW_COMMAND in review-agent.ts). */
|
|
280
|
+
command?: string;
|
|
281
|
+
/** The secret holding the model's API key, mapped into the review command's step alone. Default `ANTHROPIC_API_KEY`. */
|
|
282
|
+
key_secret?: string;
|
|
283
|
+
/** The instructions file, read from the default branch. Default `.terragucci/review.md`. */
|
|
284
|
+
instructions?: string;
|
|
285
|
+
/** Minutes before the review job is stopped. Default 10. */
|
|
286
|
+
timeout?: number;
|
|
287
|
+
}
|
|
288
|
+
export declare const REVIEW_KEYS: readonly ["agent", "command", "key_secret", "instructions", "timeout"];
|
|
239
289
|
/** The settings one project (or one repo) can carry. Every key is optional. */
|
|
240
290
|
export interface ProjectSettings {
|
|
241
291
|
/** Globs of root directories. Detected when absent. */
|
|
242
292
|
roots?: string[];
|
|
243
293
|
/** The binary the pipeline runs. Detected when absent. */
|
|
244
294
|
binary?: Binary;
|
|
245
|
-
/**
|
|
246
|
-
|
|
295
|
+
/**
|
|
296
|
+
* The binary's version. Read from the roots' `required_version` when it pins one. As a map of root
|
|
297
|
+
* glob to release, the version each root it matches runs (tofu and terraform, plain roots only).
|
|
298
|
+
*/
|
|
299
|
+
version?: string | Record<string, string>;
|
|
300
|
+
/** Each plain root's backend, provider and version files, which `terragucci generate` writes; see generate.ts. */
|
|
301
|
+
generate?: GenerateSettings;
|
|
247
302
|
/** The forge, for a host terragucci cannot name. */
|
|
248
303
|
forge?: ForgeName;
|
|
249
304
|
/** Where the project lives, for a forge not on https or the default port. */
|
|
@@ -256,8 +311,10 @@ export interface ProjectSettings {
|
|
|
256
311
|
apply?: ApplySettings;
|
|
257
312
|
/** When a pull request takes its root locks; see LOCKS. */
|
|
258
313
|
locks?: Locks;
|
|
314
|
+
/** `canary`: globs for the wave that applies first. `jobs`: the most jobs one wave's roots spread across (plain roots, GitHub and Forgejo). */
|
|
259
315
|
waves?: {
|
|
260
316
|
canary?: string[];
|
|
317
|
+
jobs?: number;
|
|
261
318
|
};
|
|
262
319
|
/** A cron schedule for tf-drift, or false. */
|
|
263
320
|
drift?: string | false;
|
|
@@ -268,13 +325,33 @@ export interface ProjectSettings {
|
|
|
268
325
|
*/
|
|
269
326
|
synth?: string;
|
|
270
327
|
/**
|
|
271
|
-
*
|
|
272
|
-
*
|
|
273
|
-
*
|
|
328
|
+
* Commands run before and after a root's init, plan, apply and drift, in
|
|
329
|
+
* the stage's own job, on its checkout, with its environment less the forge
|
|
330
|
+
* tokens. Read from terragucci.yml at base, never from the change under
|
|
331
|
+
* review (./steps.ts).
|
|
332
|
+
*/
|
|
333
|
+
steps?: StepSettings[];
|
|
334
|
+
/**
|
|
335
|
+
* The image every job runs in, in place of terragucci's: one built FROM
|
|
336
|
+
* the terragucci image for the binary, so the job still has terragucci and
|
|
337
|
+
* the binary, plus what the steps need.
|
|
338
|
+
*/
|
|
339
|
+
image?: string;
|
|
340
|
+
/**
|
|
341
|
+
* Notifications: the names of the secrets holding a Slack or Teams
|
|
342
|
+
* incoming webhook, and a generic webhook's address with the key that
|
|
343
|
+
* signs its body. An apply job whose wave waits, is refused or fails posts
|
|
344
|
+
* to each (notify.ts), and the drift job posts drift to Slack and Teams.
|
|
345
|
+
* `relay` names the customer's relay (relay.ts): a waiting wave's Slack
|
|
346
|
+
* message gets Approve and Decline buttons, its Teams card the reply
|
|
347
|
+
* `@<relay> approve wave-<k> <digest>`.
|
|
274
348
|
*/
|
|
275
349
|
notify?: {
|
|
276
350
|
slack?: string;
|
|
277
351
|
teams?: string;
|
|
352
|
+
webhook?: string;
|
|
353
|
+
webhook_key?: string;
|
|
354
|
+
relay?: string;
|
|
278
355
|
};
|
|
279
356
|
/**
|
|
280
357
|
* Cost estimates per root in the plan note: Infracost on the customer's
|
|
@@ -288,6 +365,14 @@ export interface ProjectSettings {
|
|
|
288
365
|
* schedule (comment-gitlab.ts), since GitLab starts no pipeline for a note.
|
|
289
366
|
*/
|
|
290
367
|
comments?: string | false;
|
|
368
|
+
/**
|
|
369
|
+
* A cron schedule, or false: init writes a job that runs `terragucci respond
|
|
370
|
+
* rollout --mode apply` on it, which opens the next wave of every rollout in
|
|
371
|
+
* flight once the last one merged and applied. A single repo's key: a
|
|
372
|
+
* control repo's rollout spans its projects, so it is continued from the
|
|
373
|
+
* control repo. `respond.rollout: off` leaves the job out.
|
|
374
|
+
*/
|
|
375
|
+
rollouts?: string | false;
|
|
291
376
|
/** GitLab only: how the project keeps its forge token; see TOKEN_PROTECTIONS. */
|
|
292
377
|
gitlab?: {
|
|
293
378
|
token?: GitLabToken;
|
|
@@ -322,10 +407,7 @@ export interface ProjectSettings {
|
|
|
322
407
|
trace_url?: string;
|
|
323
408
|
};
|
|
324
409
|
tips?: boolean;
|
|
325
|
-
modules?:
|
|
326
|
-
path?: string;
|
|
327
|
-
publish?: string | string[];
|
|
328
|
-
};
|
|
410
|
+
modules?: ModulesSettings;
|
|
329
411
|
/**
|
|
330
412
|
* Cloud identities the pipeline takes over OIDC, so no long-lived keys sit in CI.
|
|
331
413
|
* Plan runs pull-request code and gets the read-only identity; apply gets the
|
|
@@ -338,6 +420,12 @@ export interface ProjectSettings {
|
|
|
338
420
|
terragrunt?: TerragruntSettings;
|
|
339
421
|
/** Opt-in policy checks over each plan; see PolicySettings. */
|
|
340
422
|
policy?: PolicySettings;
|
|
423
|
+
/**
|
|
424
|
+
* `atlantis plan` and `atlantis apply` comments read as `/terragucci plan`
|
|
425
|
+
* and `/terragucci apply`. Off by default. The alias changes the words
|
|
426
|
+
* only: the same checks decide (comment.ts).
|
|
427
|
+
*/
|
|
428
|
+
atlantis_comments?: boolean;
|
|
341
429
|
/** The response to each pipeline event; see RESPONSES. */
|
|
342
430
|
respond?: Partial<Record<RespondEvent, string>>;
|
|
343
431
|
/**
|
|
@@ -349,6 +437,8 @@ export interface ProjectSettings {
|
|
|
349
437
|
token_env: string;
|
|
350
438
|
comment?: boolean | AgentCommentSettings;
|
|
351
439
|
};
|
|
440
|
+
/** The AI review of a pull request's intent against its plan; see ReviewSettings. Off when absent. */
|
|
441
|
+
review?: ReviewSettings;
|
|
352
442
|
/** The typed-decision service; see DecideSettings. Off when absent. A project's `decide` replaces the defaults' whole. */
|
|
353
443
|
decide?: DecideSettings;
|
|
354
444
|
/** The AWS region whose CloudTrail drift attribution reads. Default: the region the aws CLI already uses. */
|
|
@@ -367,6 +457,7 @@ export declare function responseTo(settings: ProjectSettings, event: RespondEven
|
|
|
367
457
|
export type CostSettings = true | {
|
|
368
458
|
key_secret?: string;
|
|
369
459
|
command?: string;
|
|
460
|
+
approve_above?: number;
|
|
370
461
|
};
|
|
371
462
|
/** The secret Infracost's key is read from when `cost.key_secret` is unset; the job gets it as this variable too. */
|
|
372
463
|
export declare const COST_KEY_SECRET = "INFRACOST_API_KEY";
|
|
@@ -379,6 +470,18 @@ export interface ResolvedSettings extends ProjectSettings {
|
|
|
379
470
|
env: Record<string, string>;
|
|
380
471
|
}
|
|
381
472
|
export declare const BUILT_IN: ResolvedSettings;
|
|
473
|
+
/**
|
|
474
|
+
* The keys a project's jobs read from the project's own terragucci.yml: the
|
|
475
|
+
* plan and apply stages, `respond`, `approve` and `check-policy` read them
|
|
476
|
+
* there, and no pipeline flag carries them. A control repo's `reconcile`
|
|
477
|
+
* writes each one its settings give the project, other than the built-in
|
|
478
|
+
* value, into that file (init.ts). Every other key reaches a project through
|
|
479
|
+
* the pipeline init writes (flags, the job's environment, its steps and
|
|
480
|
+
* files, such as `apply.resume` and `notify.webhook`). `url` is the project's
|
|
481
|
+
* own clone URL and `rollouts` belongs to a single repo, so `defaults`
|
|
482
|
+
* refuses both.
|
|
483
|
+
*/
|
|
484
|
+
export declare const PROJECT_FILE_KEYS: readonly ["policy", "reports", "approval", "gate", "roots", "waves", "parallelism", "synth", "steps", "drift", "cost", "tips", "runtime", "telemetry", "respond", "review", "decide", "audit_region", "modules", "terragrunt", "token_env", "generate"];
|
|
382
485
|
export declare class ConfigError extends Error {
|
|
383
486
|
/** Every problem found, when the error is a validation failure. */
|
|
384
487
|
readonly problems?: string[];
|
|
@@ -389,6 +492,44 @@ export declare function checkMode(mode: string): "dry-run" | "apply";
|
|
|
389
492
|
export declare const CONFIG_NAMES: string[];
|
|
390
493
|
/** The config file in `dir`, or undefined. Two of them is an error. */
|
|
391
494
|
export declare function findConfig(dir: string): string | undefined;
|
|
495
|
+
/** A publisher in another repo whose releases `modules.require: attested` checks. */
|
|
496
|
+
export interface TrustedModuleSource {
|
|
497
|
+
/** How the roots' module sources begin: an `oci://` prefix, or the publisher's git URL with or without `git::`. */
|
|
498
|
+
source: string;
|
|
499
|
+
/** The publisher's cosign public key, a path in this repo. */
|
|
500
|
+
key: string;
|
|
501
|
+
/** The git repository whose `chant/lifecycle` branch holds the publisher's release ledger. */
|
|
502
|
+
ledger: string;
|
|
503
|
+
}
|
|
504
|
+
export interface ModulesSettings {
|
|
505
|
+
path?: string;
|
|
506
|
+
publish?: string | string[];
|
|
507
|
+
/** Sign each release, write its provenance and SBOM, and record it in the release ledger. `true` reads the key at cosign.pub. */
|
|
508
|
+
attest?: boolean | {
|
|
509
|
+
key?: string;
|
|
510
|
+
};
|
|
511
|
+
/** `attested`: tf-check and tf-plan refuse a root that pins a release of a checked source unless it verifies. */
|
|
512
|
+
require?: "attested";
|
|
513
|
+
/** Publishers in other repos whose releases `require` checks. */
|
|
514
|
+
trusted?: TrustedModuleSource[];
|
|
515
|
+
}
|
|
516
|
+
/** Why a control repo's projects take no `rollouts` job: each project's pipeline sees only its own roots. */
|
|
517
|
+
/** Why `waves.jobs` is refused on GitLab: a split wave's shares hold one apply lock between them on GitHub and Forgejo, and GitLab's apply jobs take a resource group one job at a time. */
|
|
518
|
+
export declare const WAVE_JOBS_NOT_GITLAB = "a wave splits across jobs on GitHub and Forgejo; GitLab runs one apply job at a time in its resource group, so leave waves.jobs unset there";
|
|
519
|
+
export declare const WAVE_JOBS_NOT_PR_APPLY = "apply.when: pull-request applies every wave in the one job a comment starts, so a wave has no jobs to spread across; leave waves.jobs unset";
|
|
520
|
+
export declare const WAVE_JOBS_NOT_TERRAGRUNT = "a Terragrunt wave applies its units with one run --all in one job; waves.jobs splits a wave of plain roots, so leave it unset";
|
|
521
|
+
export declare const ROLLOUTS_SINGLE_REPO = "a control repo's rollout plans its waves across every project, and a project's pipeline sees only its own roots; leave rollouts unset and run terragucci respond rollout --mode apply on a schedule in the control repo";
|
|
522
|
+
/**
|
|
523
|
+
* What `synth` rules out, each because it would edit the roots the synth
|
|
524
|
+
* command writes. Those files are output, not in git: a change to them is
|
|
525
|
+
* lost at the next synth, and their source is the app's code (a CDK Terrain
|
|
526
|
+
* app's TypeScript), which terragucci does not edit.
|
|
527
|
+
*/
|
|
528
|
+
export declare const SYNTH_DRIFT_PR_SHORT = "synth writes the roots, so a live value belongs in the app that writes them, which terragucci does not edit";
|
|
529
|
+
export declare const SYNTH_DRIFT_PR = "the drift pull request writes each live value into a root's own files, and with synth the command writes those files and git does not hold them, so the value belongs in the app that writes them, which terragucci does not edit; set respond.drift to attribute, which names who changed each value in the drift issue, or to off";
|
|
530
|
+
export declare const SYNTH_ROLLOUTS = "a rollout moves a pin in each root's files or its lock file, and with synth the command writes those files and git does not hold them, so the pin is in the app that writes them; move it there";
|
|
531
|
+
/** The problems `synth` finds in one project's settings: a drift schedule whose response is the pull request, and a rollouts schedule. */
|
|
532
|
+
export declare function synthProblems(s: ProjectSettings, where: string): string[];
|
|
392
533
|
/** Why `comments` is GitLab's alone: the other forges start a job for each comment. */
|
|
393
534
|
export declare const COMMENTS_GITLAB_ONLY = "comments is for GitLab, which starts no pipeline for a merge request note; GitHub and Forgejo start the comment jobs from the comment itself, so leave comments unset";
|
|
394
535
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intentius/terragucci",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.4",
|
|
4
4
|
"description": "The whole Terraform lifecycle, handled: one config file, generated pipelines for GitHub, GitLab and Forgejo.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
".": {
|
|
18
18
|
"types": "./dist/types.d.ts"
|
|
19
19
|
},
|
|
20
|
-
"./report.schema.json": "./dist/report.schema.json"
|
|
20
|
+
"./report.schema.json": "./dist/report.schema.json",
|
|
21
|
+
"./notify.schema.json": "./dist/notify.schema.json"
|
|
21
22
|
},
|
|
22
23
|
"files": [
|
|
23
24
|
"dist",
|