For the complete documentation index, see llms.txt. This page is also available as Markdown.

Filtered Terragrunt Runs (Run Only Changed Units)

Related Guides:

A Terragrunt workspace with Run All enabled runs every unit under its working directory on every trigger. In a repository with dozens of units, a one-line change to a single database configuration still plans everything — slow, noisy, and expensive.

Filtered runs narrow each run to the units your commits actually touched, plus any unit that depends on them. A change to one unit plans one unit. Everything else is skipped.

This is especially useful for:

  • Large unit trees, where a full run --all takes many minutes but a typical change touches one or two units.

  • Shared repositories, where several teams commit to the same Terragrunt root and each wants feedback only on their own units.

  • Pull request reviews, where a plan covering thirty untouched units buries the one plan a reviewer needs to read.

Prerequisites

Requirement
Why

A GitHub or GitLab repository

Firefly works out the commit range from the provider. Bitbucket and Azure DevOps cannot supply one.

A Terragrunt workspace

The feature filters Terragrunt units. It does not apply to plain Terraform or OpenTofu workspaces.

Run All enabled

Filtering narrows a run --all run. With Run All off, the workspace already runs a single unit and there is nothing to filter.

Terragrunt 1.1.1 or newer

Earlier versions cannot expand a filter across the dependency graph. Firefly will not filter a run below this version.

Filtered runs are being rolled out per account. If the Filter Changed Units section does not appear in your workspace settings, contact your Firefly account team to have it enabled.

Supported VCS Providers

Filtered runs are available on GitHub and GitLab.

Provider
Filtered runs

GitHub

Supported

GitLab

Supported

Bitbucket

Not supported

Azure DevOps

Not supported

On Bitbucket and Azure DevOps, Firefly cannot work out the range of commits a run covers, so it has nothing to hand Terragrunt and cannot filter. Leave Run only changed units off on workspaces backed by those providers: a pull request run that asks for a filtered plan will fail rather than quietly planning everything.

Enabling Filtered Runs

You can enable filtering when you create a workspace, or on an existing one.

  1. Open the workspace and go to its General Configuration settings.

  2. Set the IaC type to Terragrunt and choose a Terragrunt version of 1.1.1 or newer.

  3. Enable Run All.

  4. Under Filter Changed Units, turn on Run only changed units.

  5. Save the workspace.

The setting is also available in the Bulk Onboarding wizard, so you can enable it across many workspaces as you onboard them.

Turning Run All off clears Run only changed units — the two settings are saved together, and filtering has no meaning without Run All.

No change to your repository is required. You do not need to add configuration files, annotate your units, or declare which files belong to which unit.

We Use Terragrunt's Own Filtering

Firefly does not calculate the list of units to run, and does not parse your Terragrunt configuration to work out what changed.

Instead, Firefly works out the range of commits your run covers and hands that range to Terragrunt using Terragrunt's own built-in change filter:

Terragrunt reads its own dependency graph and decides which units fall inside that range. The leading ... is what tells Terragrunt to also include units that depend on a changed unit.

This matters for two reasons:

  • The unit selection follows Terragrunt's rules, not ours. If Terragrunt considers a unit affected, it runs. Behavior matches what you would get running the equivalent Terragrunt command yourself.

  • The behavior can change with your Terragrunt version. Because the selection is Terragrunt's, upgrading the Terragrunt version on your workspace may change which units are selected. The examples below were verified against Terragrunt 1.1.1.

How Change Discovery Works

Terragrunt compares the two ends of the commit range, works out which files changed between them, maps those files to the units that own them, and then walks the dependency graph to add every unit that depends on a selected one.

Example

Consider a workspace whose working directory contains three units, where api consumes an output from network:

With Run only changed units enabled:

Your pull request changes
Units that run
Why

database/terragrunt.hcl

database — 1 unit

Nothing depends on database, so the change stops there.

network/terragrunt.hcl

network and api — 2 units

api declares a dependency on network, so it is pulled in automatically.

README.md

none

No unit owns the file. The run completes with nothing to plan.

database/ and api/

database and api — 2 units

Both are touched directly. network is untouched and nothing depends on it changing.

Without filtering, every one of these pull requests would run all three units.

Which Commits Are Compared

The range Firefly sends depends on how the run was triggered:

Trigger
Compared range

Pull request opened or updated

The point where your branch diverged from the target branch, up to the latest commit on the branch

Apply of an approved pull request run

The same range that was planned

Merge of a pull request, or any other push to the workspace's default branch

The commit the branch pointed at before the push, up to the pushed commit

Manual deployment of a non-default branch

The point where the branch diverged from the default branch, up to the commit being deployed

Manual deployment of the default branch

Not filtered — every unit runs

A push and a manual deployment are different triggers even on the same branch. A push carries its own before and after commits, so it can be filtered; a manual deployment names one commit with nothing to compare it against. A push to any other branch does not start a run at all — a workspace only reacts to pushes on its own default branch.

Filtering applies to both the plan and the apply. When you approve a filtered plan, the apply covers the same units, so what you reviewed is what gets applied.

How Filtering Interacts with the Working Directory

Enabling filtering does not change what your working directory is for. Two separate decisions are made, in order, and filtering only affects the second:

  1. Does this workspace run at all? Unchanged. A workspace runs when a changed file falls under its working directory, or matches one of its path configurations. This is how Firefly decides the workspace is affected, with or without filtering.

  2. Which units inside it run? This is what filtering adds. Your working directory is the root Terragrunt runs from, and the filter narrows the units beneath it.

Filtering only ever narrows. It cannot widen a run beyond the working directory, and a change outside the working directory never selects a unit inside it.

A Run Can Be Triggered and Then Select Nothing

The two decisions are made against different things — the first against file paths, the second against Terragrunt's unit graph — so a change can satisfy the first and not the second.

The clearest example is a file that lives under your working directory but belongs to no unit, such as a README.md:

  • The file is under the working directory, so the workspace is marked as changed and a run starts.

  • No unit owns the file, so the filter selects no units and the run finishes without planning anything.

The same change on a workspace without filtering would have planned every unit.

This is easy to mistake for a workspace that did not run. A run that selects no units posts no plan comment on the pull request, so the pull request looks the same as if the workspace had been skipped entirely. The run itself exists — open the workspace in Firefly, where it is recorded as completed with no changes to plan.

Limitations

Branch creation is not filtered. The first push that creates a branch has no earlier commit to compare against, so that run covers every unit.

Manual deployments of the default branch are not filtered. There is no other branch to compare the default branch against, so these runs cover every unit.

Destroy runs are never filtered. A destroy tears down the whole workspace, so every unit runs regardless of this setting.

Only files that Terragrunt attributes to a unit are detected. Terragrunt maps changed files to units through its own configuration graph. A file that a unit reads at runtime but that Terragrunt does not treat as part of that unit — for example a data file loaded by your module — will not cause that unit to be selected. Changes to a module's .tf code are detected. If you depend on external files that Terragrunt cannot see, keep a full run for that workspace.

Runs fall back to a full run when the range cannot be determined. If Firefly cannot work out the comparison range — for example the branch history is unavailable — the run executes every unit rather than silently running too few.

Filtering narrows units within a workspace, not which workspaces run. Deciding whether a workspace is triggered at all is a separate mechanism — see Path Configurations.

Last updated

Was this helpful?