Skip to main content

Terraform Workflows

Nine reusable workflows cover the full Terraform lifecycle: format checking, linting, plan comparison, deployment with approval gates, drift detection, and cost estimation.


tf-checks

Full Terraform validation pipeline — runs format check, init, validate, and optionally terraform plan across multiple cloud providers.

View workflow →

When to use: On every pull request to catch Terraform errors before merging.

jobs:
terraform-checks:
uses: clouddrove/github-shared-workflows/.github/workflows/tf-checks.yml@master
with:
working_directory: ./
provider: aws # aws | azure | gcp
terraform_version: latest
enable_plan: true
secrets:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
BUILD_ROLE: ${{ secrets.BUILD_ROLE }}
InputRequiredDefaultDescription
working_directoryNo./Path to Terraform root
providerNoawsCloud provider (aws, azure, gcp)
terraform_versionNolatestTerraform version to install
enable_planNofalseRun terraform plan
aws_regionNous-east-1AWS region
gcp_credentialsNoGCP service account JSON

stf-checks

Terraform min/max version, format, init, validate — a lighter variant of tf-checks focused on version compatibility.

View workflow →

jobs:
stf-checks:
uses: clouddrove/github-shared-workflows/.github/workflows/stf-checks.yml@master
with:
working_directory: ./
provider: aws
secrets:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

tf-lint

Lint Terraform with TFLint — catches common errors and enforces best practices beyond what terraform validate checks.

View workflow →

jobs:
lint:
uses: clouddrove/github-shared-workflows/.github/workflows/tf-lint.yml@master
secrets:
GITHUB: ${{ secrets.GITHUB_TOKEN }}

tf-pr-checks

Terraform plan comparison on PRs — generates a plan for the PR branch and compares it against the target branch plan, posting a diff as a PR comment.

View workflow →

When to use: On pull requests to show reviewers exactly what infrastructure will change.

jobs:
tf-pr-checks:
uses: clouddrove/github-shared-workflows/.github/workflows/tf-pr-checks.yml@master
with:
terraform_directory: ./infra
target_branch: main
provider: aws
aws_region: us-east-1
secrets:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
BUILD_ROLE: ${{ secrets.BUILD_ROLE }}
InputRequiredDescription
terraform_directoryYesPath to Terraform code
target_branchYesBranch to compare against
providerYesaws, azure, or gcp

tf-workflow

Terraform deploy with plan approval gates and targeted resource management — runs plan, waits for human approval, then applies. Supports terraform destroy and -target flags.

View workflow →

When to use: Production deployments that require a human to review the plan before apply.

jobs:
deploy:
uses: clouddrove/github-shared-workflows/.github/workflows/tf-workflow.yml@master
with:
working_directory: ./infra/production
provider: aws
approvers: alice,bob # GitHub usernames who can approve
timeout: 30 # minutes to wait for approval
destroy: false
secrets:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
BUILD_ROLE: ${{ secrets.BUILD_ROLE }}
InputRequiredDefaultDescription
working_directoryYesPath to Terraform root
providerYesaws, azure, or gcp
approversNoGitHub usernames who can approve
timeoutNo30Minutes to wait for approval
destroyNofalseRun terraform destroy instead of apply
targetNoSpecific resource to target
plan_onlyNofalseStop after plan, do not apply

tf-smurf

Multi-cloud Terraform orchestration with approval gates — similar to tf-workflow but adds SSH key support for modules pulled from private repos.

View workflow →

jobs:
deploy:
uses: clouddrove/github-shared-workflows/.github/workflows/tf-smurf.yml@master
with:
working_directory: ./
provider: gcp
approvers: alice
secrets:
GCP_CREDENTIALS: ${{ secrets.GCP_CREDENTIALS }}
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}

tf-drift

Detect infrastructure configuration drift — runs terraform plan on a schedule and creates or updates a GitHub Issue when drift is found.

View workflow →

When to use: Schedule nightly or weekly to catch manual changes made outside Terraform.

on:
schedule:
- cron: '0 6 * * *' # every day at 6 AM UTC

jobs:
drift:
uses: clouddrove/github-shared-workflows/.github/workflows/tf-drift.yml@master
with:
working_directory: ./infra
provider: aws
aws_region: us-east-1
secrets:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
GITHUB: ${{ secrets.GITHUB_TOKEN }}
InputRequiredDescription
working_directoryYesPath to Terraform root
providerYesaws, azure, or gcp
var_fileNoPath to .tfvars file

tf-monorepo-tag-release

Auto-detect module changes and bump versions in monorepos — detects which Terraform module directories changed, bumps the patch/minor/major version, and creates a new git tag.

View workflow →

When to use: Monorepos containing multiple Terraform modules where each module needs its own versioned release.

on:
push:
branches: [master]

jobs:
tag-release:
uses: clouddrove/github-shared-workflows/.github/workflows/tf-monorepo-tag-release.yml@master
with:
module_prefix: terraform-aws- # prefix used in tag names

infracost

Terraform infrastructure cost estimation — runs Infracost to calculate the monthly cost of your Terraform plan and posts a breakdown comment on the pull request.

View workflow →

When to use: On pull requests that change infrastructure, so reviewers can see the cost impact before merging.

jobs:
cost:
uses: clouddrove/github-shared-workflows/.github/workflows/infracost.yml@master
with:
working-directory: ./infra
slack_notification: true
secrets:
INFRACOST_API_KEY: ${{ secrets.INFRACOST_API_KEY }}
GITHUB: ${{ secrets.GITHUB_TOKEN }}
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
Get an Infracost API key

Sign up free at infracost.io to get your INFRACOST_API_KEY.


sst_workflow

Deploy Serverless Stack (SST) applications to AWS — builds and deploys SST v2/v3 apps with support for preview environments and self-hosted runners.

View workflow →

jobs:
deploy:
uses: clouddrove/github-shared-workflows/.github/workflows/sst_workflow.yml@master
with:
app-env: production
working-directory: ./
deploy: true
preview: false
secrets:
token: ${{ secrets.GITHUB_TOKEN }}
build-role: ${{ secrets.BUILD_ROLE }}
env-vars: |
DATABASE_URL=${{ secrets.DATABASE_URL }}
InputRequiredDefaultDescription
app-envYesEnvironment name (production, staging)
previewNofalseCreate a preview environment on PRs
working-directoryNo./App root directory
deployNotrueRun sst deploy