CI Perf Lint

cache-terraform-providers

Detects jobs that run terraform init without caching the downloaded provider plugins.

Why it matters

Terraform provider downloads are the slowest part of terraform init, especially with large providers:

Without caching, every CI run downloads the same providers from the Terraform registry. With a warm provider cache, terraform init typically drops from minutes to under 30 seconds.

Detected patterns

The rule fires when a job runs terraform init (in a run step, action, or step name) but has no matching actions/cache step for:

TL;DR: TF_PLUGIN_CACHE_DIR + actions/cache

- name: Configure Terraform plugin cache
  run: |
    echo "TF_PLUGIN_CACHE_DIR=$HOME/.terraform.d/plugin-cache" >>"$GITHUB_ENV"
    mkdir --parents "$HOME/.terraform.d/plugin-cache"
- name: Cache Terraform providers
  uses: actions/cache@v4
  with:
    path: |
      ~/.terraform.d/plugin-cache
    key: terraform-${{ runner.os }}-${{ hashFiles('**/.terraform.lock.hcl') }}
    restore-keys: |
      terraform-${{ runner.os }}-
- run: terraform init

This approach:

Simpler alternative: cache .terraform/providers

- uses: actions/cache@v4
  with:
    path: .terraform/providers
    key: terraform-${{ runner.os }}-${{ hashFiles('**/.terraform.lock.hcl') }}
    restore-keys: |
      terraform-${{ runner.os }}-
- run: terraform init

This works without TF_PLUGIN_CACHE_DIR but only caches the provider directory after the first terraform init.

Cache key strategy

ScopeKey
Single terraform directoryhashFiles('.terraform.lock.hcl')
Monorepo (multiple terraform directories)hashFiles('**/.terraform.lock.hcl')
Per-directory in monorepohashFiles('path/to/terraform/.terraform.lock.hcl')

Choosing between monorepo-wide and per-directory keys:

Prerequisites

  1. Commit .terraform.lock.hcl to version control

  2. Ensure the lock file includes hashes for the CI runner platform. Run locally or in CI:

    terraform providers lock -platform=linux_amd64 -platform=linux_arm64

    Without the correct platform hashes, Terraform will re-download providers even when a matching version is cached.

    This is especially important when developers work on macOS/Windows but CI runs on Linux. Running terraform providers lock adds the required platform-specific hashes so that CI can verify the cached provider binary against a matching hash.

Caveats