@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/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; /** Default `https://sts.googleapis.com/v1/token`; a regional endpoint such as `https://sts.europe-west3.rep.googleapis.com/v1/token`. */
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; /** The token's audience. Default `api://AzureADTokenExchange`; `api://AzureADTokenExchangeUSGov` for Azure US Government, `api://AzureADTokenExchangeChina` for Azure China. */
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: `follow` plans them in later waves, `plan` also previews them at pull-request time. */
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
- /** The binary's version. Read from the roots' `required_version` when it pins one. */
253
- version?: string;
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 can comment and
360
- * push to a pull request's branch; its role, when named, is read-only.
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
- /** The problems with a GitLab project's `apply.when: pull-request` and `gitlab.token: protected`, when it has any. */
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",
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
  }