Using teriac in CI
Install the version each project pins in GitHub Actions, GitLab CI and any other pipeline, cache the store between runs, and test modules against several versions.
In CI, teriac does the same job as on your laptop: it reads the version your project pins and installs exactly that, checksum-verified. Your pipeline then always matches what developers run.
The pattern
Every pipeline follows the same three steps:
npm install -g @marcdomain/teriac
export PATH="$HOME/.teriac/bin:$PATH" # so `terraform` resolves in this job
teriac auto-switch # install + use the pinned versionOn a laptop, restarting the terminal is enough. A CI job is different: it runs in a fresh shell that
never reloads ~/.bashrc, and teriac can't change the PATH of the shell that started it. So add
~/.teriac/bin to PATH in the job yourself. Or skip PATH entirely and use the teriac commands
(teriac plan, teriac exec), which run the managed binary directly.
GitHub Actions
jobs:
plan:
runs-on: ubuntu-latest
defaults:
run:
working-directory: infra
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
- name: Cache teriac versions
uses: actions/cache@v4
with:
path: ~/.teriac/store
key: teriac-${{ runner.os }}-${{ hashFiles('**/.terraform-version', '**/.tool-versions') }}
- name: Set up Terraform with teriac
run: |
npm install -g @marcdomain/teriac
echo "$HOME/.teriac/bin" >> "$GITHUB_PATH"
teriac auto-switch
env:
GITHUB_TOKEN: ${{ github.token }} # raises GitHub's rate limit for OpenTofu/Terragrunt lists
- run: terraform init -input=false
- run: terraform plan -input=falseWriting to $GITHUB_PATH makes terraform available in every later step.
OpenTofu and Terragrunt
- run: |
teriac auto-switch -p tofu
teriac auto-switch -p tgGitLab CI
plan:
image: node:22
variables:
TERIAC_HOME: "$CI_PROJECT_DIR/.teriac" # inside the project, so it can be cached
cache:
key: teriac
paths: [.teriac/store]
before_script:
- npm install -g @marcdomain/teriac
- export PATH="$TERIAC_HOME/bin:$PATH"
- cd infra && teriac auto-switch
script:
- terraform init -input=false
- terraform plan -input=falseTest a module against several versions
exec runs one command with a given version without switching, which suits a matrix:
jobs:
validate:
runs-on: ubuntu-latest
strategy:
matrix:
terraform: ["1.5.7", "1.7.5", "1.9.0"]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 22 }
- run: npm install -g @marcdomain/teriac
- run: teriac install ${{ matrix.terraform }}
- run: teriac exec ${{ matrix.terraform }} -- init -backend=false -input=false
- run: teriac exec ${{ matrix.terraform }} -- validateBehind a firewall
Point teriac at your internal mirror with TERIAC_HASHICORP_MIRROR and TERIAC_GITHUB_MIRROR; see
mirrors.
Tips
- Cache
~/.teriac/store(or$TERIAC_HOME/store), keyed on your version files. A cache hit skips the download;auto-switchjust copies the binary. - Turn on the plugin cache with
teriac plugin-cache onand cache~/.terraform.d/plugin-cacheto skip provider downloads too. - Fail fast with
teriac doctorif a runner image ships its ownterraformthat comes first on PATH. - Want plans in pull requests? That's what teriac server does, with permissions, approvals and locks that a CI job can't give you.