- Description
- Inputs
- Outputs
- Usage
- Permissions
- Usage Examples
- Contributing
This action will validate, plan and apply your OpenTofu configuration.
Workflow summaries are automatically updated from each stage, making it easier to see validation issues, planned changes, and apply results. Pull requests are decorated with concise sticky comments so reruns update in place instead of spamming the thread.
| name | description | required | default |
|---|---|---|---|
version |
Exact OpenTofu version to install. |
false |
1.12.5 |
tofu-checksums |
Optional newline-delimited SHA256 checksums for a custom OpenTofu version. Required when overriding |
false |
"" |
workdir |
Path to the OpenTofu configuration directory, relative to the repository root. |
false |
. |
env |
Logical deployment label used for sticky comment scoping, artifact naming, and plan/apply correlation. |
false |
"" |
steps |
Comma or newline separated steps to run. Allowed values are |
false |
validate,plan |
tfvar-files |
Comma or newline separated list of tfvar files to include. |
false |
"" |
tfvars |
Newline-delimited |
false |
"" |
backend-config-var-files |
Comma or newline separated list of backend config files to include. |
false |
"" |
backend-config-vars |
Newline-delimited |
false |
"" |
test-dir |
Directory containing OpenTofu tests, relative to |
false |
tests |
test-tfvar-files |
Comma or newline separated list of tfvar files to include for tests. Defaults to |
false |
"" |
test-tfvars |
Newline-delimited |
false |
"" |
tflint-version |
Exact TFLint version to install. |
false |
0.55.1 |
tflint-checksums |
Optional newline-delimited SHA256 checksums for a custom TFLint version. Required when overriding |
false |
"" |
trivy-version |
Exact Trivy version to install. Defaults to the post-incident safe |
false |
0.69.3 |
trivy-checksums |
Optional newline-delimited SHA256 checksums for a custom Trivy version. Required when overriding |
false |
"" |
checkov-version |
Exact Checkov version to install. The bundled lock file currently supports |
false |
3.2.497 |
trivy-scan-type |
Trivy scan type. Allowed values are |
false |
config |
checkov-skip-checks |
Comma or newline separated list of Checkov checks to skip. |
false |
"" |
lock-timeout |
State lock timeout for plan/apply, for example |
false |
"" |
parallelism |
Parallelism for plan/apply. |
false |
"" |
refresh |
Refresh behavior for plan/apply. Allowed values are |
false |
"" |
targets |
Comma or newline separated list of target resources for plan/apply. |
false |
"" |
artifact-retention-days |
Retention days for uploaded plan artifacts, from 1 to 90. Empty uses the repository default. |
false |
"" |
skip-plan-upload |
Skip uploading the generated plan artifact. Defaults to false so follow-up apply jobs can download it. |
false |
false |
summary-mode |
Summary mode for validate, lint, trivy, checkov, test, plan, and apply. Allowed values are |
false |
redacted |
comment-mode |
PR comment mode. Use |
false |
sticky |
comment-identifier |
Identifier used to find and update sticky PR comments. |
false |
tf-github-action |
The action exposes per-step status outputs such as validate_status, plan_status, apply_status, lint_status, trivy_status, checkov_status, and test_status.
The most useful orchestration outputs are:
has_failures:truewhen any selected step failed.has_changes:truewhen the plan detected changes.create_count,update_count,destroy_count: plan change counts.added,changed,destroyed,imported,forgotten: apply change counts.plan_artifact_name: uploaded plan artifact name.plan_artifact_sha256: SHA256 digest for the generated plan artifact.env_slug: sanitized environment label used for sticky comment scoping and artifact naming.
- uses: coresolutionsltd/tofu-github-action@main
with:
version:
# Exact OpenTofu version to install.
#
# Required: false
# Default: 1.12.5
tofu-checksums:
# Optional newline-delimited SHA256 checksums for a custom OpenTofu version. Required when overriding `version`.
#
# Required: false
# Default: ""
workdir:
# Path to the OpenTofu configuration directory, relative to the repository root.
#
# Required: false
# Default: .
env:
# Logical deployment label used for sticky comment scoping, artifact naming, and plan/apply correlation.
#
# Required: false
# Default: ""
steps:
# Comma or newline separated steps to run. Allowed values are `validate`, `plan`, `apply`, `test`, `lint`, `trivy`, and `checkov`.
#
# Required: false
# Default: validate,plan
tfvar-files:
# Comma or newline separated list of tfvar files to include.
#
# Required: false
# Default: ""
tfvars:
# Newline-delimited `key=value` pairs for Terraform variables.
#
# Required: false
# Default: ""
backend-config-var-files:
# Comma or newline separated list of backend config files to include.
#
# Required: false
# Default: ""
backend-config-vars:
# Newline-delimited `key=value` pairs for backend configuration.
#
# Required: false
# Default: ""
test-dir:
# Directory containing OpenTofu tests, relative to `workdir`.
#
# Required: false
# Default: tests
test-tfvar-files:
# Comma or newline separated list of tfvar files to include for tests. Defaults to `tfvar-files`.
#
# Required: false
# Default: ""
test-tfvars:
# Newline-delimited `key=value` pairs for test variables. Defaults to `tfvars`.
#
# Required: false
# Default: ""
tflint-version:
# Exact TFLint version to install
#
# Required: false
# Default: 0.55.1
tflint-checksums:
# Optional newline-delimited SHA256 checksums for a custom TFLint version. Required when overriding `tflint-version`.
#
# Required: false
# Default: ""
trivy-version:
# Exact Trivy version to install. Defaults to the post-incident safe `0.69.3` release.
#
# Required: false
# Default: 0.69.3
trivy-checksums:
# Optional newline-delimited SHA256 checksums for a custom Trivy version. Required when overriding `trivy-version`.
#
# Required: false
# Default: ""
checkov-version:
# Exact Checkov version to install. The bundled lock file currently supports `3.2.497`.
#
# Required: false
# Default: 3.2.497
trivy-scan-type:
# Trivy scan type. Allowed values are `config` and `fs`.
#
# Required: false
# Default: config
checkov-skip-checks:
# Comma or newline separated list of Checkov checks to skip.
#
# Required: false
# Default: ""
lock-timeout:
# State lock timeout for plan/apply, for example `5m`.
#
# Required: false
# Default: ""
parallelism:
# Parallelism for plan/apply.
#
# Required: false
# Default: ""
refresh:
# Refresh behavior for plan/apply. Allowed values are `true` and `false`.
#
# Required: false
# Default: ""
targets:
# Comma or newline separated list of target resources for plan/apply.
#
# Required: false
# Default: ""
artifact-retention-days:
# Retention days for uploaded plan artifacts, from 1 to 90. Empty uses the repository default.
#
# Required: false
# Default: ""
skip-plan-upload:
# Skip uploading the generated plan artifact.
#
# Required: false
# Default: true
summary-mode:
# Summary mode for validate, lint, trivy, checkov, test, plan, and apply. Allowed values are `full`, `redacted`, and `off`.
#
# Required: false
# Default: redacted
comment-mode:
# PR comment mode. Use `sticky` to update a single comment or `off` to disable comments.
#
# Required: false
# Default: sticky
comment-identifier:
# Identifier used to find and update sticky PR comments.
#
# Required: false
# Default: tf-github-actionThe action can post PR comments and publish releases. Ensure your workflow grants the required permissions.
For PR comments:
permissions:
contents: read
pull-requests: writeFor semantic-release publishing:
permissions:
contents: write
issues: write
pull-requests: writeThis action now pins third-party actions to commit SHAs, verifies OpenTofu, TFLint, and Trivy downloads against pinned SHA256 checksums, and installs Checkov from a hash-locked requirements file.
This section provides examples of how to use the Tofu GitHub Action in various scenarios, from simple validation to multi-environment deployments with approval gates.
Perfect for pull requests to ensure OpenTofu configuration is valid without making any changes.
name: Validate Only
on:
pull_request:
branches:
- main
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
- name: Validate Configuration
uses: coresolutionsltd/tofu-github-action@main
with:
workdir: ./infra
steps: validateGenerate and review execution plans without applying changes. Useful for code review and change approval processes.
name: Plan Only
on:
pull_request:
branches:
- main
jobs:
plan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
- name: Plan Changes
uses: coresolutionsltd/tofu-github-action@main
with:
workdir: ./infra
steps: planComplete workflow that validates, plans, and applies changes. Best for automated deployments to development environments.
name: Deploy to Development
on:
pull_request:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
- name: Deploy to Development Environment
uses: coresolutionsltd/tofu-github-action@main
with:
workdir: ./infra
env: dev
steps: validate,plan,applyLoad multiple variable files to configure your infrastructure with shared and environment-specific settings.
- name: Deploy with Multiple Variable Files
uses: coresolutionsltd/tofu-github-action@main
with:
workdir: ./infra
env: dev
tfvar-files: common.tfvars, prod.tfvars
steps: validate,plan,apply
tfvar-filescan be comma or newline separated.
Pass variables directly in the workflow for simple configurations or dynamic values.
- name: Deploy with Inline Variables
uses: coresolutionsltd/tofu-github-action@main
with:
workdir: ./infra
env: dev
tfvars: |
environment=development
region=us-west-2
instance_count=2
steps: validate,plan,applyCombine variable files and inline variables for maximum flexibility.
- name: Deploy with Mixed Variable Sources
uses: coresolutionsltd/tofu-github-action@main
with:
workdir: ./infra
env: dev
tfvar-files: base.tfvars, dev.tfvars
tfvars: |
build_number=${{ github.run_number }}
commit_sha=${{ github.sha }}
deployed_by=${{ github.actor }}
deployment_time=${{ github.event.head_commit.timestamp }}
steps: validate,plan,applyUse configuration files to manage remote state across different environments.
- name: Initialize with Backend Configuration Files
uses: coresolutionsltd/tofu-github-action@main
with:
workdir: ./infra
env: staging
backend-config-var-files: backend-base.conf, backend-staging.conf
steps: planConfigure remote state directly in the workflow for dynamic setups.
- name: Configure Remote State Inline
uses: coresolutionsltd/tofu-github-action@main
with:
workdir: ./infra
backend-config-vars: |
bucket=my-terraform-state-${{ github.repository_owner }}
key=${{ github.repository }}/terraform.tfstate
region=us-west-2
encrypt=true
steps: validate,plan,applyPublic and Enterprise private GitHub repositories can apply deployment protection rules. These can require people or teams to approve a workflow before using a specific environment. Deployment protection rules are an excellent way to require approval before applying changes - we simply separate our plan and apply steps, with the apply step running in a protected environment.
This pattern separates planning from applying, allowing for review and approval between steps.
name: Infrastructure Deployment with Approval
on:
push:
branches:
- main
workflow_dispatch:
jobs:
plan:
name: Plan Infrastructure Changes
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
- name: Plan Production Changes
uses: coresolutionsltd/tofu-github-action@main
with:
workdir: ./infra
env: prod
tfvar-files: base.tfvars, prod.tfvars
tfvars: build_number=${{ github.run_number }}
steps: validate,plan
apply:
name: Apply Infrastructure Changes
runs-on: ubuntu-latest
needs: plan
environment: prod # This environment can have protection rules
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
- name: Apply Production Changes
uses: coresolutionsltd/tofu-github-action@main
with:
workdir: ./infra
env: prod # env must match what is planned
steps: apply # Only apply, plan artifact is downloaded automaticallyNote
Apply-only runs require a plan artifact from a previous job or run. Leave skip-plan-upload as false when you intend to apply later.
Control PR comments and redact plan/apply output in summaries.
- name: Plan with redacted summaries and no PR comment
uses: coresolutionsltd/tofu-github-action@main
with:
workdir: ./infra
steps: plan
summary-mode: redacted
comment-mode: off
artifact-retention-days: 7Use comment-identifier if you want separate sticky comments per workflow or environment.
Linting runs tflint against workdir. Configuration resolution is:
.tflint.hclinworkdir.tflint.hclin the repository root- The default
.tflint.hclbundled with this action
- name: Lint with TFLint
uses: coresolutionsltd/tofu-github-action@main
with:
workdir: ./infra
steps: lint
### Security Scanning
Trivy and Checkov scans use config files with sensible defaults bundled in this action. You can override them by placing a config file in your repo.
The security tooling is installed in a hardened way by default:
- OpenTofu is downloaded only when its release archive matches a pinned SHA256 checksum.
- TFLint is downloaded only when its release archive matches a pinned SHA256 checksum.
- Trivy defaults to the safe `0.69.3` release and is downloaded only when its archive matches a pinned SHA256 checksum.
- Checkov is installed from a hash-locked Python requirements file instead of an unpinned `pip install`.
### Maintainer Updates
To bump the pinned toolchain safely, run:
```bash
npm run update:security-assets -- \
--tofu-version 1.12.5 \
--tflint-version 0.55.1 \
--trivy-version 0.69.3 \
--checkov-version 3.2.497That script refreshes:
- vendored checksum manifests for OpenTofu, TFLint, and Trivy
- the hash-locked Checkov requirements file
- version defaults referenced in the action, source, tests, and README
CI runs npm run validate:security-assets to catch drift between defaults and the vendored security assets.
Config resolution (highest precedence first):
workdir(the directory you pass to the action where your Tofu config lives)- Repository root (local repo)
- Default config bundled with this action
Use .trivy.yaml and .checkov.yaml in your repo to override the defaults.
Trivy scans IaC configuration using .trivy.yaml and steps: trivy. The default installer uses the post-incident safe 0.69.3 release. If you override trivy-version, you should also provide matching trivy-checksums. Use trivy-scan-type if you need fs instead of config.
- name: Trivy scan
uses: coresolutionsltd/tofu-github-action@main
with:
workdir: ./infra
steps: trivyCheckov scans IaC configuration using .checkov.yaml and steps: checkov. Use checkov-skip-checks for quick exclusions, with additional settings in .checkov.yaml. The bundled install path is hash-locked to checkov==3.2.497.
- name: Checkov scan
uses: coresolutionsltd/tofu-github-action@main
with:
workdir: ./infra
steps: checkov
checkov-skip-checks: CKV_AWS_20,CKV_AWS_21
### Testing
OpenTofu tests run via `tofu test`. Unit tests typically use `command = plan` (no changes applied), while integration tests use `command = apply` to exercise full deployments.
Recommended structure:
. ├── main.tf └── tests/ ├── unit/ │ └── validations.tftest.hcl # Contains command = plan └── integration/ └── deploy_aws.tftest.hcl # Contains command = apply
To run both unit and integration tests, invoke the action twice with `steps: test` and point `test-dir` at the directory you want to execute. `test-tfvars` and `test-tfvar-files` default to `tfvars`/`tfvar-files` unless explicitly set.
If the test directory is missing or contains no `.tftest.hcl` files, the action emits a warning and skips tests.
```yaml
- name: Run unit tests
uses: coresolutionsltd/tofu-github-action@main
with:
workdir: ./infra
steps: test
test-dir: tests/unit
- name: Run integration tests
uses: coresolutionsltd/tofu-github-action@main
with:
workdir: ./infra
steps: test
test-dir: tests/integration
These examples are meant to give you the building blocks for putting together a complete infrastructure deployment workflow. You can mix and match them to create pipelines that validate, plan, and apply your configuration, while also adding steps for review and approval where it makes sense.
Use these patterns as starting points and adapt them to fit the way your team works.
If something doesn’t quite work for you, or there’s a use case we haven’t covered yet, please open an issue and we’ll look into adding it.
We welcome contributions to improve our GitHub Action!
-
Issues
- Before starting work, please open an issue to discuss bugs, features, or improvements.
-
Fork & Branch
- Fork the repository and create a feature branch from
main. - Use descriptive branch names (e.g.,
feat/extend-plan-summaryorfix/validation-error).
- Fork the repository and create a feature branch from
-
Commits
- We use Conventional Commits to ensure automated versioning with semantic release.
- Examples:
feat: add x capability to validatefix: resolve y validation issuedocs: update z usage example
-
Pre-commit Hooks
- Install and enable pre-commit before committing.
- Run
pre-commit installonce after cloning to enforce linting, formatting, and checks locally.
-
Pull Requests
- Ensure your PR references the related issue (e.g.,
Closes #42). - Include tests if adding functionality.
- Update documentation where relevant.
- Keep PRs focused and small where possible.
- Ensure your PR references the related issue (e.g.,
- Open an issue to propose a change.
- Fork the repo and create a feature branch.
- Make changes, following commit and pre-commit guidelines.
- Push your branch and open a Pull Request.
- The maintainers will review, request changes if needed, and merge once approved.