What gets planned
How teriac server finds affected projects, picks tool versions, watches extra files with teriac:watch, and handles Terragrunt dependencies and mock outputs.
teriac finds Terraform, Terragrunt and OpenTofu projects on its own and plans the ones a pull request affects. Most repos need no config at all.
Project detection
A project is planned when a PR changes:
- the project's own files;
- modules it uses, and the modules those use;
- Terragrunt includes (such as
_envcommon),dependencyunits,read_terragrunt_config(...),file(...), and hook scripts; - parent
root.hcl,env.hcland version pins.
Paths built with Terragrunt functions (get_repo_root(), get_terragrunt_dir(),
find_in_parent_folders()) and with locals are resolved too.
Example
modules/
network/ ← changed in this PR
envs/
dev/main.tf module "net" { source = "../../modules/network" } → planned
prod/main.tf module "net" { source = "../../modules/network" } → planned
sandbox/main.tf no reference to modules/network → not plannedAnd in a Terragrunt repo:
_envcommon/vpc.hcl ← changed in this PR
live/
root.hcl
dev/vpc/terragrunt.hcl include "envcommon" { path = ".../_envcommon/vpc.hcl" } → planned
prod/vpc/terragrunt.hcl include "envcommon" { path = ".../_envcommon/vpc.hcl" } → planned
prod/app/terragrunt.hcl dependency "vpc" { config_path = "../vpc" } → plannedTool versions
Each project is planned with the exact tool version it pins, read the same way as the
CLI's auto-switch: .terraform-version,
.opentofu-version, .terragrunt-version, .tool-versions, terragrunt.hcl constraints and
required_version. When it pins none, teriac uses TERIAC_DEFAULT_VERSION (latest by default).
Binaries are downloaded on demand, checksum-verified, and kept on the server's volume. Warm the
cache at start-up with TERIAC_PREINSTALL, for example terraform@1.9.8,tofu@1.8.5.
Naming projects yourself
Detection covers most repos. To give projects names, set workspaces or tools, or turn autoplan off
for one, list them in the repo's teriac.yaml:
# teriac.yaml
projects:
- name: prod-network
dir: live/prod/network
workspace: default
engine: opentofu # terraform | opentofu | terragrunt
version: 1.8.5
- name: orders
dir: stacks/orders
autoplan: false # plan only on `teriac plan -p orders`
autodiscover: true # keep finding the other projects too (default)All keys are in the teriac.yaml reference.
Watch extra files: teriac:watch
For a file no config mentions, such as source code that a build step packages, add a watch. Globs work, a folder means everything inside it, and watches add to automatic detection; they never replace it.
In any .tf, .tofu or .hcl file:
# teriac:watch /lambda/orders/**/*.py scripts/build.shIn Terragrunt, with its functions:
locals {
teriac_watch = ["${get_repo_root()}/schemas/*.json"]
}Or in the repo's teriac.yaml:
projects:
- dir: stacks/orders
watch: ["/lambda/orders/**"]Paths are relative to the project folder; a leading / means the repo root.
When plans run
| Event | What happens |
|---|---|
| PR opened, or new commits pushed | Affected projects are planned (unless autoplan: false) |
| Draft PR | Skipped, unless the repo sets plan_drafts: true |
teriac plan comment |
The projects you name, or every affected project |
| A newer commit arrives mid-run | Waiting plans for the old commit are skipped |
| PR merged or closed | Locks released, plans and checkouts deleted |
Plans and applies share TERIAC_PARALLELISM slots (4 by default). One PR gets at most
TERIAC_PR_PARALLELISM (one less than the total), so a big PR never blocks everyone else.
Terragrunt dependencies
teriac never applies a dependency for you, and never applies a plan built on wrong outputs.
- Mock outputs. A unit planned with a dependency's
mock_outputs(because the dependency isn't applied yet) is flagged in the PR and can't be applied, not even with--override. teriac tells you to apply the dependency first, for exampleteriac apply -p live/prod/vpc. - Re-plans. When you apply a dependency, teriac re-plans the units that depend on it with the real outputs. That's a plan only, for you to review and apply.
- Outdated plans. A plan made before one of its dependencies was applied is refused with "re-plan first".
- Order. Several units applied in one command go in dependency order, and independent ones run in parallel.
Example
teriac plan # vpc and app are planned; app uses vpc's mock_outputs
teriac apply -p live/prod/app # refused: app was planned with mock outputs
teriac apply -p live/prod/vpc # applies vpc; teriac re-plans app with the real outputs
teriac apply -p live/prod/app # applies app once you've reviewed the new planThe run environment
Plans and applies run with your server's environment (so cloud credentials just work), minus every
TERIAC_* variable, plus:
| Variable | Value |
|---|---|
TF_IN_AUTOMATION, TF_INPUT=0 |
Non-interactive Terraform |
TG_NON_INTERACTIVE, TG_NO_COLOR |
Non-interactive Terragrunt |
CHECKPOINT_DISABLE=1 |
No HashiCorp update checks |
TF_PLUGIN_CACHE_DIR |
A provider cache shared by all runs |
TERIAC_REPO, TERIAC_PR_NUMBER, TERIAC_HEAD_SHA |
The PR being planned |
TERIAC_PROJECT, TERIAC_WORKSPACE |
The project being planned |
TERIAC_USER |
Who started the run |
TERIAC_BRANCH |
The branch (drift checks) |
Use them in hooks or scripts, for example to tag resources with the PR that created them. Each run
times out after TERIAC_RUN_TIMEOUT_SECONDS (an hour by default).