@intentius/terragucci 0.4.3 → 0.4.5
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 +3 -2
- package/dist/audit.schema.json +3 -3
- package/dist/dora.schema.json +104 -0
- package/dist/estate.schema.json +153 -2
- package/dist/report-index.schema.json +11 -1
- package/dist/report.schema.json +176 -2
- package/dist/run.schema.json +110 -0
- package/dist/state-edges.schema.json +52 -0
- package/dist/state-versions.schema.json +42 -0
- package/dist/terragucci.mjs +878 -444
- package/dist/terragucci.mjs.map +4 -4
- package/dist/terragucci.schema.json +3005 -0
- package/dist/types.d.ts +292 -10
- package/package.json +5 -3
package/dist/types.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { type GenerateSettings } from "./generate-config";
|
|
2
|
+
export { ROOTS_NOT_ATMOS, ROOTS_NOT_TERRAGRUNT, SYNTH_DRIFT_PR, SYNTH_DRIFT_PR_SHORT, SYNTH_GENERATE, SYNTH_ROLLOUTS } from "./refusals";
|
|
1
3
|
export declare const BINARIES: readonly ["terraform", "tofu", "choudoufu"];
|
|
2
4
|
export declare const FORGES: readonly ["github", "gitlab", "forgejo"];
|
|
3
5
|
export declare const GATES: readonly ["always", "on-destroy", "never"];
|
|
@@ -13,6 +15,8 @@ export declare const APPROVALS: readonly ["ledger", "pr-review", "sealed"];
|
|
|
13
15
|
/** Every stage runs on the forge's CI. */
|
|
14
16
|
export declare const RUNTIMES: readonly ["forge"];
|
|
15
17
|
export declare const DEPENDENTS: readonly ["follow", "plan"];
|
|
18
|
+
/** What a pull request does with the dependents of a changed unit when terragrunt.dependents is unset. */
|
|
19
|
+
export declare const DEFAULT_DEPENDENTS: Dependents;
|
|
16
20
|
export declare const POLICY_ENGINES: readonly ["conftest", "opa"];
|
|
17
21
|
export declare const POLICY_INPUTS: readonly ["plan", "hcp"];
|
|
18
22
|
/**
|
|
@@ -57,6 +61,30 @@ export type ApplyWhen = (typeof APPLY_WHEN)[number];
|
|
|
57
61
|
export type Locks = (typeof LOCKS)[number];
|
|
58
62
|
export type ApplyMerge = (typeof APPLY_MERGE)[number];
|
|
59
63
|
export type ApplyRequire = (typeof APPLY_REQUIRES)[number];
|
|
64
|
+
/** The stages a step runs before or after (`steps:`). `drift` is the drift job's refresh-only plan. */
|
|
65
|
+
export declare const STEP_STAGES: readonly ["init", "plan", "apply", "drift"];
|
|
66
|
+
export type StepStage = (typeof STEP_STAGES)[number];
|
|
67
|
+
/** What a step's non-zero exit does: fail the root (the default), or hold its wave for an approval. */
|
|
68
|
+
export declare const STEP_FAILURES: readonly ["fail", "approve"];
|
|
69
|
+
export type StepFailure = (typeof STEP_FAILURES)[number];
|
|
70
|
+
export declare const STEP_KEYS: readonly ["name", "run", "before", "after", "roots", "on_failure"];
|
|
71
|
+
/**
|
|
72
|
+
* One entry of `steps:`. `run` is a shell command, run in the root's
|
|
73
|
+
* directory. Exactly one of `before` and `after` names the stage. `roots`
|
|
74
|
+
* are globs of the roots it runs for (every root when unset).
|
|
75
|
+
* `on_failure: approve` turns a non-zero exit into a hold: the root's wave
|
|
76
|
+
* waits for an approval of its set digest, whatever `gate` says. Only a step
|
|
77
|
+
* that runs before the gate is decided can hold it: one before or after
|
|
78
|
+
* init or plan.
|
|
79
|
+
*/
|
|
80
|
+
export interface StepSettings {
|
|
81
|
+
run: string;
|
|
82
|
+
name?: string;
|
|
83
|
+
before?: StepStage;
|
|
84
|
+
after?: StepStage;
|
|
85
|
+
roots?: string[];
|
|
86
|
+
on_failure?: StepFailure;
|
|
87
|
+
}
|
|
60
88
|
/**
|
|
61
89
|
* `apply:`: when a change applies. `when: merge` (the default) applies the
|
|
62
90
|
* default branch after a merge. `when: pull-request` applies an open pull
|
|
@@ -84,6 +112,14 @@ export interface ApplySettings {
|
|
|
84
112
|
* unset. 5 to 60.
|
|
85
113
|
*/
|
|
86
114
|
resume?: number;
|
|
115
|
+
/**
|
|
116
|
+
* Roots that apply from a branch other than the default: branch name to
|
|
117
|
+
* root globs. A push to a named branch applies only the roots its globs
|
|
118
|
+
* match, in waves behind the same gate; a push to the default branch, and
|
|
119
|
+
* the apply a comment starts from a merge into it, skip every root a glob
|
|
120
|
+
* here matches. Plain roots only, with `when: merge`.
|
|
121
|
+
*/
|
|
122
|
+
branches?: Record<string, string[]>;
|
|
87
123
|
}
|
|
88
124
|
/**
|
|
89
125
|
* Policy as code, off unless set. `tf-plan` runs the engine over each planned
|
|
@@ -120,22 +156,45 @@ export interface PolicySettings {
|
|
|
120
156
|
export interface OidcSettings {
|
|
121
157
|
plan_role?: string;
|
|
122
158
|
apply_role?: string;
|
|
159
|
+
/**
|
|
160
|
+
* AWS roles by root glob (plain roots): a root takes the pair of the first
|
|
161
|
+
* glob it matches, so each environment's roots plan and apply with roles
|
|
162
|
+
* that reach that environment's state alone. A root no glob matches takes
|
|
163
|
+
* `plan_role` and `apply_role`. In a Terragrunt repo, `terragrunt.credentials`
|
|
164
|
+
* does this.
|
|
165
|
+
*/
|
|
166
|
+
roles?: Record<string, RolePair>;
|
|
123
167
|
/** The AWS token's audience. Default `sts.amazonaws.com`. */
|
|
124
168
|
audience?: string;
|
|
125
169
|
/** GCP Workload Identity Federation: the provider's resource name and a service account per stage. */
|
|
126
170
|
gcp?: {
|
|
127
171
|
workload_identity_provider: string;
|
|
128
172
|
plan_service_account: string;
|
|
129
|
-
apply_service_account: string;
|
|
173
|
+
apply_service_account: string;
|
|
174
|
+
/** Default `https://sts.googleapis.com/v1/token`; a regional endpoint such as `https://sts.europe-west3.rep.googleapis.com/v1/token`. */
|
|
130
175
|
token_url?: string;
|
|
176
|
+
/**
|
|
177
|
+
* Service accounts by root glob (plain roots): a root's binary, and what
|
|
178
|
+
* reads its state, impersonate the pair of the first glob it matches, so
|
|
179
|
+
* each environment's roots reach that environment's state alone. A root no
|
|
180
|
+
* glob matches takes plan_service_account and apply_service_account.
|
|
181
|
+
*/
|
|
182
|
+
roles?: Record<string, RolePair>;
|
|
131
183
|
};
|
|
132
184
|
/** An Entra app registration or managed identity per stage, with a federated credential for the forge. */
|
|
133
185
|
azure?: {
|
|
134
186
|
tenant_id: string;
|
|
135
187
|
subscription_id: string;
|
|
136
188
|
plan_client_id: string;
|
|
137
|
-
apply_client_id: string;
|
|
189
|
+
apply_client_id: string;
|
|
190
|
+
/** The token's audience. Default `api://AzureADTokenExchange`; `api://AzureADTokenExchangeUSGov` for Azure US Government, `api://AzureADTokenExchangeChina` for Azure China. */
|
|
138
191
|
audience?: string;
|
|
192
|
+
/**
|
|
193
|
+
* Client ids by root glob (plain roots), as `gcp.roles` gives service
|
|
194
|
+
* accounts; each client needs a federated credential for the forge. A root
|
|
195
|
+
* no glob matches takes plan_client_id and apply_client_id.
|
|
196
|
+
*/
|
|
197
|
+
roles?: Record<string, RolePair>;
|
|
139
198
|
};
|
|
140
199
|
}
|
|
141
200
|
/** A plan role and an apply role, for the units under one path. */
|
|
@@ -154,7 +213,7 @@ export interface TerragruntSettings {
|
|
|
154
213
|
exclude?: string[];
|
|
155
214
|
/** How many units one `run --all` runs at once. Default: from the state backend. */
|
|
156
215
|
parallelism?: number;
|
|
157
|
-
/** Units that depend on a changed unit: `
|
|
216
|
+
/** Units that depend on a changed unit: `plan` (the default) previews them at pull-request time as well as planning them in later waves, `follow` only plans them in later waves. */
|
|
158
217
|
dependents?: Dependents;
|
|
159
218
|
/**
|
|
160
219
|
* Plan and apply roles by unit path glob, assumed over OIDC through a
|
|
@@ -162,6 +221,11 @@ export interface TerragruntSettings {
|
|
|
162
221
|
*/
|
|
163
222
|
credentials?: Record<string, RolePair>;
|
|
164
223
|
}
|
|
224
|
+
/** Atmos settings. Atmos mode is detected (`atmos.yaml` at the repo root); this block only tunes it. */
|
|
225
|
+
export interface AtmosSettings {
|
|
226
|
+
/** The Atmos release every job installs. Default: the one this terragucci release pins. */
|
|
227
|
+
version?: string;
|
|
228
|
+
}
|
|
165
229
|
/**
|
|
166
230
|
* Pipeline events and the responses each takes. The first mode is the
|
|
167
231
|
* default and needs no model. `drift: attribute` also names who changed each drifted attribute (a known-writes
|
|
@@ -243,14 +307,47 @@ export interface AgentCommentSettings {
|
|
|
243
307
|
timeout?: number;
|
|
244
308
|
}
|
|
245
309
|
export declare const AGENT_COMMENT_KEYS: readonly ["command", "key_secret", "max_turns", "timeout"];
|
|
310
|
+
/**
|
|
311
|
+
* `agent.drift`: when the drift job opens the drift issue, a job runs a coding
|
|
312
|
+
* agent on the default branch with the drift report, and a second job opens a
|
|
313
|
+
* pull request with what it changed, with `agent.token_env`'s token. The
|
|
314
|
+
* agent's job holds no forge token and no cloud role. Its settings are
|
|
315
|
+
* `agent.comment`'s (AgentCommentSettings); `true` takes every default.
|
|
316
|
+
*/
|
|
317
|
+
export declare const AGENT_DRIFT_KEYS: readonly ["command", "key_secret", "max_turns", "timeout"];
|
|
318
|
+
/** Why `agent.drift` and `respond.drift: pull-request` do not go together. */
|
|
319
|
+
export declare const AGENT_DRIFT_RESPOND = "agent.drift opens the drift pull request itself, so the codified one would be a second; set respond.drift to attribute or off";
|
|
320
|
+
/**
|
|
321
|
+
* `review`: a model reviews each pull request's intent against its plan
|
|
322
|
+
* (review-agent.ts), off unless `agent` is true. It posts a note and never
|
|
323
|
+
* approves; a `tf-apply` wave's policy reads its risk as `input.review`.
|
|
324
|
+
*/
|
|
325
|
+
export interface ReviewSettings {
|
|
326
|
+
/** Turns the review on. */
|
|
327
|
+
agent?: boolean;
|
|
328
|
+
/** 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). */
|
|
329
|
+
command?: string;
|
|
330
|
+
/** The secret holding the model's API key, mapped into the review command's step alone. Default `ANTHROPIC_API_KEY`. */
|
|
331
|
+
key_secret?: string;
|
|
332
|
+
/** The instructions file, read from the default branch. Default `.terragucci/review.md`. */
|
|
333
|
+
instructions?: string;
|
|
334
|
+
/** Minutes before the review job is stopped. Default 10. */
|
|
335
|
+
timeout?: number;
|
|
336
|
+
}
|
|
337
|
+
export declare const REVIEW_KEYS: readonly ["agent", "command", "key_secret", "instructions", "timeout"];
|
|
246
338
|
/** The settings one project (or one repo) can carry. Every key is optional. */
|
|
247
339
|
export interface ProjectSettings {
|
|
248
340
|
/** Globs of root directories. Detected when absent. */
|
|
249
341
|
roots?: string[];
|
|
250
342
|
/** The binary the pipeline runs. Detected when absent. */
|
|
251
343
|
binary?: Binary;
|
|
252
|
-
/**
|
|
253
|
-
|
|
344
|
+
/**
|
|
345
|
+
* The binary's version. Read from the roots' `required_version` when it pins one. As a map of root
|
|
346
|
+
* glob to release, the version each root it matches runs (tofu and terraform, plain roots only).
|
|
347
|
+
*/
|
|
348
|
+
version?: string | Record<string, string>;
|
|
349
|
+
/** Each plain root's backend, provider and version files, which `terragucci generate` writes; see generate.ts. */
|
|
350
|
+
generate?: GenerateSettings;
|
|
254
351
|
/** The forge, for a host terragucci cannot name. */
|
|
255
352
|
forge?: ForgeName;
|
|
256
353
|
/** Where the project lives, for a forge not on https or the default port. */
|
|
@@ -263,8 +360,14 @@ export interface ProjectSettings {
|
|
|
263
360
|
apply?: ApplySettings;
|
|
264
361
|
/** When a pull request takes its root locks; see LOCKS. */
|
|
265
362
|
locks?: Locks;
|
|
363
|
+
/**
|
|
364
|
+
* `canary`: globs for the wave that applies first. `jobs`: the most jobs one wave's roots or units spread across (GitHub and Forgejo).
|
|
365
|
+
* `after`: plain roots only, for a root or glob the roots or globs it applies after, beside the order its `terraform_remote_state` reads give.
|
|
366
|
+
*/
|
|
266
367
|
waves?: {
|
|
267
368
|
canary?: string[];
|
|
369
|
+
jobs?: number;
|
|
370
|
+
after?: Record<string, string[]>;
|
|
268
371
|
};
|
|
269
372
|
/** A cron schedule for tf-drift, or false. */
|
|
270
373
|
drift?: string | false;
|
|
@@ -274,17 +377,34 @@ export interface ProjectSettings {
|
|
|
274
377
|
* plan, apply and drift jobs, on their own checkout.
|
|
275
378
|
*/
|
|
276
379
|
synth?: string;
|
|
380
|
+
/**
|
|
381
|
+
* Commands run before and after a root's init, plan, apply and drift, in
|
|
382
|
+
* the stage's own job, on its checkout, with its environment less the forge
|
|
383
|
+
* tokens. Read from terragucci.yml at base, never from the change under
|
|
384
|
+
* review (./steps.ts).
|
|
385
|
+
*/
|
|
386
|
+
steps?: StepSettings[];
|
|
387
|
+
/**
|
|
388
|
+
* The image every job runs in, in place of terragucci's: one built FROM
|
|
389
|
+
* the terragucci image for the binary, so the job still has terragucci and
|
|
390
|
+
* the binary, plus what the steps need.
|
|
391
|
+
*/
|
|
392
|
+
image?: string;
|
|
277
393
|
/**
|
|
278
394
|
* Notifications: the names of the secrets holding a Slack or Teams
|
|
279
395
|
* incoming webhook, and a generic webhook's address with the key that
|
|
280
396
|
* signs its body. An apply job whose wave waits, is refused or fails posts
|
|
281
|
-
* to each (notify.ts).
|
|
397
|
+
* to each (notify.ts), and the drift job posts drift to Slack and Teams.
|
|
398
|
+
* `relay` names the customer's relay (relay.ts): a waiting wave's Slack
|
|
399
|
+
* message gets Approve and Decline buttons, its Teams card the reply
|
|
400
|
+
* `@<relay> approve wave-<k> <digest>`.
|
|
282
401
|
*/
|
|
283
402
|
notify?: {
|
|
284
403
|
slack?: string;
|
|
285
404
|
teams?: string;
|
|
286
405
|
webhook?: string;
|
|
287
406
|
webhook_key?: string;
|
|
407
|
+
relay?: string;
|
|
288
408
|
};
|
|
289
409
|
/**
|
|
290
410
|
* Cost estimates per root in the plan note: Infracost on the customer's
|
|
@@ -330,6 +450,21 @@ export interface ProjectSettings {
|
|
|
330
450
|
token_env?: string;
|
|
331
451
|
/** Environment variables every job gets. Values only, never secrets. */
|
|
332
452
|
env?: Record<string, string>;
|
|
453
|
+
/**
|
|
454
|
+
* The runner each generated job runs on: a label, a list of labels the
|
|
455
|
+
* runner must all carry, or on GitHub a runner group; or a map of
|
|
456
|
+
* `default`, `plan`, `apply` and `drift` to one of those. Rendered as
|
|
457
|
+
* `runs-on` on GitHub and Forgejo and as `tags` on GitLab. Unset, the jobs
|
|
458
|
+
* run where they always have.
|
|
459
|
+
*/
|
|
460
|
+
runner?: RunnerSettings;
|
|
461
|
+
/**
|
|
462
|
+
* The names of CI secrets and variables the jobs that plan, apply and check
|
|
463
|
+
* drift get as environment variables of the same name, such as
|
|
464
|
+
* TF_VAR_db_password: never their values. GitHub and Forgejo; GitLab hands
|
|
465
|
+
* every job its CI/CD variables already, so there the key changes nothing.
|
|
466
|
+
*/
|
|
467
|
+
pass?: PassSettings;
|
|
333
468
|
/**
|
|
334
469
|
* The secret holding `OTEL_EXPORTER_OTLP_HEADERS`, such as a collector's API
|
|
335
470
|
* key, and `trace_url`: a link to a run's trace with `{trace_id}` in it
|
|
@@ -351,26 +486,71 @@ export interface ProjectSettings {
|
|
|
351
486
|
parallelism?: number;
|
|
352
487
|
/** Terragrunt settings, for a repo terragucci finds Terragrunt in. */
|
|
353
488
|
terragrunt?: TerragruntSettings;
|
|
489
|
+
/** Atmos settings, for a repo with an `atmos.yaml` at its root. */
|
|
490
|
+
atmos?: AtmosSettings;
|
|
354
491
|
/** Opt-in policy checks over each plan; see PolicySettings. */
|
|
355
492
|
policy?: PolicySettings;
|
|
493
|
+
/**
|
|
494
|
+
* `atlantis plan` and `atlantis apply` comments read as `/terragucci plan`
|
|
495
|
+
* and `/terragucci apply`. Off by default. The alias changes the words
|
|
496
|
+
* only: the same checks decide (comment.ts).
|
|
497
|
+
*/
|
|
498
|
+
atlantis_comments?: boolean;
|
|
356
499
|
/** The response to each pipeline event; see RESPONSES. */
|
|
357
500
|
respond?: Partial<Record<RespondEvent, string>>;
|
|
358
501
|
/**
|
|
359
|
-
* The agent integration behind `agent.comment`. Its token
|
|
360
|
-
* push
|
|
502
|
+
* The agent integration behind `agent.comment` and `agent.drift`. Its token
|
|
503
|
+
* can comment, push a branch and open a pull request; the agent itself never
|
|
504
|
+
* holds it.
|
|
361
505
|
*/
|
|
362
506
|
agent?: {
|
|
363
507
|
via: (typeof AGENT_VIA)[number];
|
|
364
508
|
token_env: string;
|
|
365
509
|
comment?: boolean | AgentCommentSettings;
|
|
510
|
+
drift?: boolean | AgentCommentSettings;
|
|
366
511
|
};
|
|
512
|
+
/** The AI review of a pull request's intent against its plan; see ReviewSettings. Off when absent. */
|
|
513
|
+
review?: ReviewSettings;
|
|
367
514
|
/** The typed-decision service; see DecideSettings. Off when absent. A project's `decide` replaces the defaults' whole. */
|
|
368
515
|
decide?: DecideSettings;
|
|
369
516
|
/** The AWS region whose CloudTrail drift attribution reads. Default: the region the aws CLI already uses. */
|
|
370
517
|
audit_region?: string;
|
|
371
518
|
/** Dashboards and alert rules written next to the pipeline. Off unless set. */
|
|
372
519
|
dashboards?: boolean | DashboardSettings;
|
|
520
|
+
/**
|
|
521
|
+
* Jobs of your own that `init` and `reconcile` write into the generated
|
|
522
|
+
* pipeline as they are: a map of job name to the job, in the forge's own
|
|
523
|
+
* syntax, or the path of a YAML file in the repo that holds that map.
|
|
524
|
+
*/
|
|
525
|
+
own_jobs?: string | Record<string, Record<string, unknown>>;
|
|
526
|
+
/** Roots each pull request gets a copy of, under a state key of its own, destroyed on close or once its TTL passes; see EphemeralSettings. */
|
|
527
|
+
ephemeral?: EphemeralSettings;
|
|
373
528
|
}
|
|
529
|
+
/**
|
|
530
|
+
* Ephemeral environments: each open pull request gets its own copy of the
|
|
531
|
+
* roots `roots` matches, applied from its head under the state key with
|
|
532
|
+
* `-pr-<n>` added (ephemeral.ts). Closing the pull request, or `ttl` passing
|
|
533
|
+
* since its last apply, destroys the copy through a planned destroy that the
|
|
534
|
+
* audit trail lists. A Terragrunt unit's copy takes the suffix through its
|
|
535
|
+
* remote_state key, which reads TERRAGUCCI_EPHEMERAL_SUFFIX; with synth the
|
|
536
|
+
* command writes the roots in the copy's checkout first.
|
|
537
|
+
*/
|
|
538
|
+
export interface EphemeralSettings {
|
|
539
|
+
/** Root globs. */
|
|
540
|
+
roots: string[];
|
|
541
|
+
/** How long a copy lives after the last apply that changed it: `<n>m`, `<n>h` or `<n>d`. Default 24h. */
|
|
542
|
+
ttl?: string;
|
|
543
|
+
/** Minutes between the sweep's runs, which destroy the copies whose TTL passed or whose pull request closed. 5 to 60; default 30. */
|
|
544
|
+
sweep?: number;
|
|
545
|
+
}
|
|
546
|
+
/** `ephemeral.ttl` when unset. */
|
|
547
|
+
export declare const EPHEMERAL_TTL = "24h";
|
|
548
|
+
/** `ephemeral.sweep` when unset. */
|
|
549
|
+
export declare const EPHEMERAL_SWEEP = 30;
|
|
550
|
+
/** A TTL in milliseconds: `<n>m`, `<n>h` or `<n>d`; undefined when it is none of them. */
|
|
551
|
+
export declare function ttlMs(ttl: string): number | undefined;
|
|
552
|
+
/** Why ephemeral environments are refused on GitLab with gitlab.token: protected. */
|
|
553
|
+
export declare const EPHEMERAL_NOT_PROTECTED = "a merge request pipeline applies the copy and records it on chant/lifecycle with the project token, and with gitlab.token: protected no merge request pipeline holds it; leave ephemeral unset or the token unprotected";
|
|
374
554
|
/** The whole file: one repo's settings, or `defaults` and `projects` for many repos. */
|
|
375
555
|
export interface TerragucciConfig extends ProjectSettings {
|
|
376
556
|
defaults?: ProjectSettings;
|
|
@@ -378,10 +558,37 @@ export interface TerragucciConfig extends ProjectSettings {
|
|
|
378
558
|
}
|
|
379
559
|
/** The response a project takes to an event: its setting, or the event's default. */
|
|
380
560
|
export declare function responseTo(settings: ProjectSettings, event: RespondEvent): string;
|
|
561
|
+
/** One runner: a label, every label of a list, or a GitHub runner group with any labels its runners must also carry. */
|
|
562
|
+
export type RunnerSpec = string | string[] | {
|
|
563
|
+
group: string;
|
|
564
|
+
labels?: string[];
|
|
565
|
+
};
|
|
566
|
+
/** `runner`: one runner for every job, or one per stage over a default. */
|
|
567
|
+
export type RunnerSettings = RunnerSpec | Partial<Record<RunnerStage | "default", RunnerSpec>>;
|
|
568
|
+
/** The stages `runner` can name apart; every other job runs on `default`. */
|
|
569
|
+
export declare const JOB_STAGES: readonly ["plan", "apply", "drift"];
|
|
570
|
+
export type RunnerStage = (typeof JOB_STAGES)[number];
|
|
571
|
+
/** `pass`: secret and variable names handed to the jobs as environment variables. */
|
|
572
|
+
export interface PassSettings {
|
|
573
|
+
secrets?: string[];
|
|
574
|
+
vars?: string[];
|
|
575
|
+
}
|
|
576
|
+
/** Whether `runner` is a map of stage to runner, rather than one runner. */
|
|
577
|
+
export declare function runnerByStage(v: RunnerSettings): v is Partial<Record<RunnerStage | "default", RunnerSpec>>;
|
|
578
|
+
export declare const JOB_LABEL: RegExp;
|
|
579
|
+
export declare const JOB_STAGE_KEYS: string[];
|
|
580
|
+
/** The problems with `runner`, for `forge` when it is known. */
|
|
581
|
+
export declare function runnerProblems(v: unknown, where: string, forge?: unknown): string[];
|
|
582
|
+
/** Names `pass` refuses: the forges refuse a secret under these prefixes, and terragucci sets the rest in the jobs itself. */
|
|
583
|
+
export declare const PASS_RESERVED_PREFIXES: string[];
|
|
584
|
+
export declare const PASS_RESERVED: string[];
|
|
585
|
+
/** The problems with `pass`: lists of secret and variable names, each a name a job's environment takes, none listed twice or set by `env` too. */
|
|
586
|
+
export declare function passProblems(v: unknown, where: string, env?: unknown): string[];
|
|
381
587
|
/** `cost: true`, or the secret holding the estimator's key and the command to run instead of Infracost. */
|
|
382
588
|
export type CostSettings = true | {
|
|
383
589
|
key_secret?: string;
|
|
384
590
|
command?: string;
|
|
591
|
+
approve_above?: number;
|
|
385
592
|
};
|
|
386
593
|
/** The secret Infracost's key is read from when `cost.key_secret` is unset; the job gets it as this variable too. */
|
|
387
594
|
export declare const COST_KEY_SECRET = "INFRACOST_API_KEY";
|
|
@@ -405,7 +612,7 @@ export declare const BUILT_IN: ResolvedSettings;
|
|
|
405
612
|
* own clone URL and `rollouts` belongs to a single repo, so `defaults`
|
|
406
613
|
* refuses both.
|
|
407
614
|
*/
|
|
408
|
-
export declare const PROJECT_FILE_KEYS: readonly ["policy", "reports", "approval", "gate", "roots", "waves", "parallelism", "synth", "drift", "cost", "tips", "runtime", "telemetry", "respond", "decide", "audit_region", "modules", "terragrunt", "token_env"];
|
|
615
|
+
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", "ephemeral"];
|
|
409
616
|
export declare class ConfigError extends Error {
|
|
410
617
|
/** Every problem found, when the error is a validation failure. */
|
|
411
618
|
readonly problems?: string[];
|
|
@@ -416,6 +623,24 @@ export declare function checkMode(mode: string): "dry-run" | "apply";
|
|
|
416
623
|
export declare const CONFIG_NAMES: string[];
|
|
417
624
|
/** The config file in `dir`, or undefined. Two of them is an error. */
|
|
418
625
|
export declare function findConfig(dir: string): string | undefined;
|
|
626
|
+
export declare const SETTING_KEYS: Set<string>;
|
|
627
|
+
export declare const TERRAGRUNT_KEYS: string[];
|
|
628
|
+
export declare const RELEASE_VERSION: RegExp;
|
|
629
|
+
/** The settings of `notify`, `policy`, `oidc`, `telemetry`, `gitlab`, `cost`, `pass` and `agent`. */
|
|
630
|
+
export declare const NOTIFY_KEYS: string[];
|
|
631
|
+
export declare const POLICY_KEYS: string[];
|
|
632
|
+
export declare const OIDC_KEYS: string[];
|
|
633
|
+
export declare const TELEMETRY_KEYS: string[];
|
|
634
|
+
export declare const TOKEN_PROTECTION_KEYS: string[];
|
|
635
|
+
export declare const COST_KEYS: string[];
|
|
636
|
+
export declare const PASS_KEYS: string[];
|
|
637
|
+
export declare const AGENT_KEYS: string[];
|
|
638
|
+
export declare const MODULES_KEYS: Set<string>;
|
|
639
|
+
export declare const REGISTRY_KEYS: string[];
|
|
640
|
+
/** A registry namespace or module name, as the Terraform module registry protocol allows them. */
|
|
641
|
+
export declare const REGISTRY_NAME: RegExp;
|
|
642
|
+
/** A registry module's system (its target provider): lower-case letters and digits. */
|
|
643
|
+
export declare const REGISTRY_SYSTEM: RegExp;
|
|
419
644
|
/** A publisher in another repo whose releases `modules.require: attested` checks. */
|
|
420
645
|
export interface TrustedModuleSource {
|
|
421
646
|
/** How the roots' module sources begin: an `oci://` prefix, or the publisher's git URL with or without `git::`. */
|
|
@@ -436,9 +661,38 @@ export interface ModulesSettings {
|
|
|
436
661
|
require?: "attested";
|
|
437
662
|
/** Publishers in other repos whose releases `require` checks. */
|
|
438
663
|
trusted?: TrustedModuleSource[];
|
|
664
|
+
/** Run the binary's `test` on each module before a release of it publishes; a module with no tests, or one that fails them, is refused. */
|
|
665
|
+
test?: boolean;
|
|
666
|
+
/** Write each release as the Terraform module registry protocol, as static files a bucket or a Pages site serves. */
|
|
667
|
+
registry?: RegistrySettings;
|
|
439
668
|
}
|
|
669
|
+
/** `modules.registry`: the module registry protocol as static files. */
|
|
670
|
+
export interface RegistrySettings {
|
|
671
|
+
/** The bucket the files go to: `s3://<bucket>`, `gs://<bucket>` or `az://<account>/<container>`. */
|
|
672
|
+
bucket?: string;
|
|
673
|
+
/** Or a directory in the repo, for a Pages site to serve. */
|
|
674
|
+
dir?: string;
|
|
675
|
+
/** The bucket's API address, for an S3-compatible store. */
|
|
676
|
+
endpoint?: string;
|
|
677
|
+
/** Where the files go in the bucket. The prefix is served as the host's root. */
|
|
678
|
+
prefix?: string;
|
|
679
|
+
/** The https address, with no path, that serves the files; its host is the one module sources name. */
|
|
680
|
+
url: string;
|
|
681
|
+
/** The namespace a module is published under, unless `namespaces` maps its path. */
|
|
682
|
+
namespace: string;
|
|
683
|
+
/** A tag prefix (a path in the repo, such as `platform/`) to the namespace its modules go under. The longest match wins. */
|
|
684
|
+
namespaces?: Record<string, string>;
|
|
685
|
+
/** The system (target provider) in each module's address. Default `generic`. */
|
|
686
|
+
system?: string;
|
|
687
|
+
/** What a version's download points at: a tarball beside it (the default), its git tag, or its OCI artifact. */
|
|
688
|
+
download?: "tarball" | "git-tags" | "oci";
|
|
689
|
+
}
|
|
690
|
+
/** Why a control repo's projects take no `rollouts` job: each project's pipeline sees only its own roots. */
|
|
691
|
+
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";
|
|
440
692
|
/** Why a control repo's projects take no `rollouts` job: each project's pipeline sees only its own roots. */
|
|
441
693
|
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";
|
|
694
|
+
/** The problems `synth` finds in one project's settings: a drift schedule whose response is the pull request, a rollouts schedule, and generate. */
|
|
695
|
+
export declare function synthProblems(s: ProjectSettings, where: string): string[];
|
|
442
696
|
/** Why `comments` is GitLab's alone: the other forges start a job for each comment. */
|
|
443
697
|
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";
|
|
444
698
|
/**
|
|
@@ -459,10 +713,30 @@ export declare const PR_APPLY_NEEDS_ON_GITLAB: {
|
|
|
459
713
|
* job posts it.
|
|
460
714
|
*/
|
|
461
715
|
export declare const PROTECTED_TOKEN_NEEDS_COMMENTS = "protected needs comments: <cron>: a merge request's pipeline then holds no token that may post the plan note, so the comments schedule's job posts it";
|
|
462
|
-
/**
|
|
716
|
+
/**
|
|
717
|
+
* Why `agent.comment` and `review` need `comments:` on GitLab: a merge
|
|
718
|
+
* request note starts no pipeline, and a merge request's own pipeline runs
|
|
719
|
+
* its own pipeline file, so the comments schedule's job starts the agent's and
|
|
720
|
+
* the review's pipelines on the default branch.
|
|
721
|
+
*/
|
|
722
|
+
export declare const NEEDS_COMMENTS_ON_GITLAB: {
|
|
723
|
+
agent: string;
|
|
724
|
+
review: string;
|
|
725
|
+
};
|
|
726
|
+
/** The problems with a GitLab project's `apply.when: pull-request`, `gitlab.token: protected`, `agent.comment` and `review`, when it has any. */
|
|
463
727
|
export declare function gitlabPrApplyProblems(s: Record<string, unknown>, where: string): string[];
|
|
464
728
|
/** Why GitLab has no plan-time locks: no merge request event runs a pipeline from the default branch. */
|
|
465
729
|
export declare const NO_GITLAB_PLAN_LOCKS = "plan is not supported on GitLab, where no merge request event runs a job from the default branch that could hold the lock; leave locks unset, and with apply.when: pull-request a merge request locks its roots on `/terragucci apply` or `/terragucci lock`";
|
|
730
|
+
/** A job name `own_jobs` takes: one every forge's YAML reads as a plain key. */
|
|
731
|
+
export declare const OWN_JOB_NAME: RegExp;
|
|
732
|
+
/** The problems with `own_jobs`: a map of job name to job, or the path of a YAML file in the repo that holds one. */
|
|
733
|
+
export declare function ownJobsProblems(v: unknown, where: string): string[];
|
|
734
|
+
export declare const EPHEMERAL_KEYS: string[];
|
|
735
|
+
export declare const APPLY_KEYS: string[];
|
|
736
|
+
/** A branch name `apply.branches` may name: what a forge's rule and the job's shell both take as it is. */
|
|
737
|
+
export declare const APPLY_BRANCH: RegExp;
|
|
738
|
+
/** Why `apply.branches` is refused with `apply.when: pull-request`. */
|
|
739
|
+
export declare const BRANCHES_NOT_PR_APPLY = "apply.when: pull-request applies an open pull request into the default branch, and a push applies nothing, so no branch could apply its roots; leave apply.branches unset";
|
|
466
740
|
/** Where a shared policy is fetched from: the git URL and the ref. */
|
|
467
741
|
export interface PolicySource {
|
|
468
742
|
url: string;
|
|
@@ -476,6 +750,14 @@ export interface PolicySource {
|
|
|
476
750
|
* Undefined when it is not that shape.
|
|
477
751
|
*/
|
|
478
752
|
export declare function parsePolicySource(source: string): PolicySource | undefined;
|
|
753
|
+
export declare const SECRET_NAME: RegExp;
|
|
754
|
+
export declare const DECIDE_KEYS: string[];
|
|
755
|
+
export declare const DURATION: RegExp;
|
|
756
|
+
export declare const ATMOS_KEYS: string[];
|
|
757
|
+
/** Why a config with both an atmos and a terragrunt block is refused. */
|
|
758
|
+
export declare const ATMOS_NOT_TERRAGRUNT = "terragucci runs an Atmos repo or a Terragrunt repo, not both; keep the block of the one this repo is";
|
|
759
|
+
/** The GCP Workload Identity Federation provider's resource name. */
|
|
760
|
+
export declare const WIF_PROVIDER: RegExp;
|
|
479
761
|
/** Check a parsed config and return it typed, or throw with every problem listed. */
|
|
480
762
|
export declare function validateConfig(raw: unknown, where: string): TerragucciConfig;
|
|
481
763
|
export type ConfigMode = "fold" | "run" | "check";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intentius/terragucci",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.5",
|
|
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",
|
|
@@ -18,7 +18,8 @@
|
|
|
18
18
|
"types": "./dist/types.d.ts"
|
|
19
19
|
},
|
|
20
20
|
"./report.schema.json": "./dist/report.schema.json",
|
|
21
|
-
"./notify.schema.json": "./dist/notify.schema.json"
|
|
21
|
+
"./notify.schema.json": "./dist/notify.schema.json",
|
|
22
|
+
"./terragucci.schema.json": "./dist/terragucci.schema.json"
|
|
22
23
|
},
|
|
23
24
|
"files": [
|
|
24
25
|
"dist",
|
|
@@ -51,6 +52,7 @@
|
|
|
51
52
|
"@intentius/chant-lexicon-github": "0.109.0",
|
|
52
53
|
"@intentius/chant-lexicon-gitlab": "0.109.0",
|
|
53
54
|
"@intentius/chant-lexicon-terraform": "0.109.0",
|
|
54
|
-
"@intentius/tsad-reference": "2.1.0"
|
|
55
|
+
"@intentius/tsad-reference": "2.1.0",
|
|
56
|
+
"@modelcontextprotocol/sdk": "1.30.1"
|
|
55
57
|
}
|
|
56
58
|
}
|