Set up Terraform or Terragrunt with version management, caching, and optional AWS or Google Cloud authentication. The action can also run configured Terraform or Terragrunt commands.
- Installs Terraform, OpenTofu, and Terragrunt via tenv
- Detects tool versions from
.terraform-version,.opentofu-version,.terragrunt-version, and.tool-versions - Caches installed tools, Terraform providers, and Terragrunt downloads
- Supports AWS OIDC and Google Cloud Workload Identity authentication
- Optionally runs Terraform or Terragrunt commands through the
commandsinput - Provides a companion action for publishing Terraform plans as pull request comments
- Configures Terragrunt to use Terraform by default, while honoring an explicit
TG_TF_PATH=tofuortofu-versioninput
Note: As of October 2025, this composite action uses tofuutils/tenv under the hood to install Terraform, OpenTofu, and Terragrunt binaries (replacing the previous
hashicorp/setup-terraformandautero1/action-terragruntactions). Specifyterraform-version,tofu-version, andterragrunt-versionas needed. Set the TENV_GITHUB_TOKEN environment variable to ${{ github.token }} for tenv API calls to GitHub (e.g. to avoid rate limits).
Leave terraform-version blank to let tenv auto-detect the version from .terraform-version or .tool-versions. Terraform can then be used in a following workflow step.
name: Terraform Plan (no terragrunt)
on:
pull_request:
paths:
- 'terraform/**'
- '.terraform-version'
permissions: {}
jobs:
terraform-plan:
runs-on: ubuntu-24.04
permissions:
id-token: write # for OIDC auth
contents: read
pull-requests: write # for PR commenter
steps:
- uses: actions/checkout@v6
- name: install terraform
uses: datadrivers/terragrunt-action@v4
env:
TENV_GITHUB_TOKEN: ${{ github.token }} # optional but avoids API rate limits when calling github API for tools installation
with:
terraform-version: ""
use-aws-auth: "true"
aws-region: ${{ vars.AWS_REGION }}
aws-role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
- name: run terraform
working-directory: "terraform/"
run: |
terraform planTo use OpenTofu instead, set tofu-version:
- uses: datadrivers/terragrunt-action@v4
with:
tofu-version: ""
terragrunt-version: ""name: Terraform Validate dev
on:
pull_request:
paths:
- ".terra*-version"
- "terraform/**"
branches:
- develop
defaults:
run:
shell: bash
# Use ENV vars to configure parameters for steps
env:
AWS_REGION: "eu-central-1"
ACCOUNT: project-dev
TERRAGRUNT_PARALLELISM: 4 # limit CPU usage
permissions: {}
jobs:
terraform-validate:
name: TF code in project-dev
runs-on: ubuntu-24.04
permissions:
id-token: write # for OIDC auth
contents: read
pull-requests: write # for PR commenter
steps:
- uses: actions/checkout@v6
- name: Set terra*_version variables from files
run: |
TF_VER=$(cat .terraform-version)
TG_VER=$(cat .terragrunt-version)
echo "TERRAFORM_VERSION=$TF_VER" >> $GITHUB_ENV
echo "TERRAGRUNT_VERSION=$TG_VER" >> $GITHUB_ENV
- name: run terraform
uses: datadrivers/terragrunt-action@v4
env:
TENV_GITHUB_TOKEN: ${{ github.token }} # optional but avoids API rate limits when calling github API for tools installation
with:
terraform-version: ${{ env.TERRAFORM_VERSION }}
terragrunt-version: ${{ env.TERRAGRUNT_VERSION }}
use-aws-auth: "true"
aws-region: ${{ env.AWS_REGION }}
aws-role-to-assume: ${{ secrets.AWS_ROLE_TERRAFORM }}
terragrunt-download: "$HOME/.terragrunt-cache/${{ env.ACCOUNT }}"
skip-caches: "false"
commands: |
terragrunt run --all -- init
terragrunt run --all -- plan -out terraform.tfplan - name: run terraform
uses: datadrivers/terragrunt-action@v4
env:
TENV_GITHUB_TOKEN: ${{ github.token }} # optional but avoids API rate limits when calling github API for tools installation
with:
terraform-version: ""
terragrunt-version: ""
use-aws-auth: "true"
aws-region: ${{ env.AWS_REGION }}
aws-role-to-assume: ${{ env.AWS_ROLE_TO_ASSUME }}
skip-caches: "false"
commands: |
terragrunt run --all -- validate
terragrunt run --all -- plan - name: run terraform
uses: datadrivers/terragrunt-action@v4
env:
TENV_GITHUB_TOKEN: ${{ github.token }} # optional but avoids API rate limits when calling github API for tools installation
with:
terraform-version: ""
terragrunt-version: ""
use-gcloud-auth: "true"
gcp-workload-identity-provider: "projects/123456789/locations/global/workloadIdentityPools/my-pool/providers/my-provider"
gcp-service-account-email: "automation-github@project-id.iam.gserviceaccount.com"
gcp-project-id: "123456789"
skip-caches: "false"
commands: |
terragrunt run --all -- planTerraform commands must create a plan file (e.g. terraform.tfplan) for the PR commenter action to pick up and convert to JSON for the comment:
jobs:
terraform-plan:
runs-on: ubuntu-24.04
permissions:
id-token: write # for OIDC auth
contents: read
pull-requests: write # for PR commenter
steps:
- uses: actions/checkout@v6
- name: install terraform
uses: datadrivers/terragrunt-action@v4
env:
TENV_GITHUB_TOKEN: ${{ github.token }}
with:
terraform-version: ""
- name: run terraform
working-directory: examples/my-module
run: |
terraform init
terraform plan -out terraform.tfplan
- name: add PR comment for terraform plan
if: ${{ github.event_name == 'pull_request' }}
uses: datadrivers/terragrunt-action/terraform-pr-commenter@v4
with:
terraform-plan-filename: terraform.tfplan # default
pr-commenter-comment-header: "Terraform Plan Changes" # default
pr-commenter-comment-footer: "Review plan above"
github-token: ${{ secrets.PAT_TOKEN }} # optional, uses GITHUB_TOKEN by defaultTo avoid downloading the same Terraform / Terragrunt / OpenTofu versions on every workflow run you can enable caching of tenv managed tool directories. This is on by default.
Input: cache-tenv-tools (default true). Set to false to skip caching.
What is cached:
~/.tenv/Terraform/{tool version}
~/.tenv/Terragrunt/{tool version}
~/.tenv/OpenTofu
Cache key components:
- OS (
runner.os) - Hash of local version indicator files (
.terraform-version,.terragrunt-version,.opentofu-version,terragrunt.hcl,root.hcl) - Explicit input versions (
terraform-version,terragrunt-version,tenv-version)
Force a cache refresh by:
- Bumping any of the version files or input version values
- Adding a dummy change to e.g.
root.hclwhen using constraint based detection
Disable all caches (plugin, terragrunt download dir, tenv tool versions) via skip-caches: "true" or enable them with skip-caches: "false" (default).
Problem: When TF_PLUGIN_CACHE_DIR points to a single shared directory, restoring a cache and then downloading new providers causes the directory to accumulate provider versions over time. Subsequent cache saves include both old and new providers, leading to large cache entries.
Mitigation implemented in this action:
-
The plugin cache directory is now scoped per lockfile hash. Internally, the action computes a hash of all
**/.terraform.lock.hcland**/versions.tffiles and sets:TF_PLUGIN_CACHE_DIR=$HOME/.terraform.d/plugin-cache/<LOCK_HASH>
-
The cache path targets this hashed subdirectory, and the cache key includes the same
<LOCK_HASH>. This ensures each distinct dependency set has its own isolated cache, preventing old providers from being bundled with new ones.
Notes:
- If no lockfile is present, the action uses a fallback scope
no-lock. - We removed broad restore-keys for the plugin cache to avoid restoring mismatched provider sets into the current scope.
- For self-hosted runners, you can periodically prune older hashed subdirectories under
~/.terraform.d/plugin-cache/if disk usage is a concern (safe to delete non-current hashes; they will be rehydrated from cache when needed).