Run a Deployment in GitHub Actions
The following workflows are blueprints and need some adjustments to work for you.
Search for CHANGEME
to adjust needed credentials details for AWS, Google Cloud, and Azure examples.
Terramate Cloud support
When synchronizing deployments to Terramate Cloud, it is recommended to run a drift check right after the deployment. This drift check will be used to validate the integrity of the deployment. Consider the following two scenarios:
- If a deployment succeeds, an immediate drift check will help detect if resources drift right away.
- If a deployment fails, an immediate drift will help to detect and understand partially applied plans.
Deployment Blueprints
Create the following GitHub Actions configuration at .github/workflows/deploy.yml
Please select the tab that fits your use case. Currently available use cases are:
- Terraform + Terramate Cloud
- OpenTofu + Terramate Cloud
- Terragrunt + Terramate Cloud
- Terraform
- OpenTofu
- Terragrunt
yml
name: Terraform Deployment
on:
push:
branches:
- main
jobs:
deploy:
name: Deploy Terraform changes in changed Terramate stacks
permissions:
id-token: write
contents: read
pull-requests: read
checks: read
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ github.head_ref }}
fetch-depth: 0
- name: Install Terramate
uses: terramate-io/terramate-action@v2
- name: Install Terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: 1.7.4
terraform_wrapper: false
- name: List changed stacks
id: list
run: terramate list --changed
## Comment this step out if not using AWS
- name: Configure AWS credentials via OIDC
if: steps.list.outputs.stdout
id: auth
uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: CHANGEME_AWS_REGION
role-to-assume: CHANGEME_IAM_ROLE_ARN
## Uncomment this if using Google Cloud
# - name: Authenticate to Google Cloud
# if: steps.list.outputs.stdout
# id: auth
# uses: google-github-actions/auth@v2
# with:
# workload_identity_provider: CHANGEME_WORKLOAD_IDENTITY_PROVIDER
# service_account: CHANGEME_SERVICE_ACCOUNT_EMAIL
## Uncomment this if using Microsoft Azure
# - name: Configure Azure credentials
# if: steps.list.outputs.stdout
# id: auth
# uses: azure/login@v2
# with:
# client-id: CHANGEME_AZURE_CLIENT_ID
# tenant-id: CHANGEME_AZURE_TENANT_ID
# subscription-id: CHANGEME_AZURE_SUBSCRIPTION_ID
- name: Run Terraform init in each changed stacks
if: steps.list.outputs.stdout
id: init
run: |
terramate run \
--parallel 1 \
--changed \
-- \
terraform init
- name: Create Terraform plan on changed stacks
if: steps.list.outputs.stdout
id: plan
run: |
terramate run \
--parallel 5 \
--changed \
-- \
terraform plan -lock-timeout=5m -out out.tfplan
- name: Apply planned changes on changed stacks
if: steps.list.outputs.stdout
id: apply
run: |
terramate run \
--parallel 5 \
--changed \
--sync-deployment \
--terraform-plan-file=out.tfplan \
-- \
terraform apply -input=false -auto-approve -lock-timeout=5m out.tfplan
env:
GITHUB_TOKEN: ${{ github.token }}
- name: Run drift detection
if: steps.list.outputs.stdout && ! cancelled() && steps.apply.outcome != 'skipped'
id: drift
run: |
terramate run \
--parallel 5 \
--changed \
--continue-on-error \
--sync-drift-status \
--terraform-plan-file=drift.tfplan \
-- \
terraform plan -out drift.tfplan -detailed-exitcode
env:
GITHUB_TOKEN: ${{ github.token }}
yml
name: OpenTofu Deployment
on:
push:
branches:
- main
jobs:
deploy:
name: Deploy OpenTofu changes in changed Terramate stacks
permissions:
id-token: write
contents: read
pull-requests: read
checks: read
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ github.head_ref }}
fetch-depth: 0
- name: Install Terramate
uses: terramate-io/terramate-action@v2
- name: Install OpenTofu
uses: opentofu/setup-opentofu@v1
with:
tofu_version: 1.9.0
tofu_wrapper: false
- name: List changed stacks
id: list
run: terramate list --changed
## Comment this step out if not using AWS
- name: Configure AWS credentials via OIDC
if: steps.list.outputs.stdout
id: auth
uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: CHANGEME_AWS_REGION
role-to-assume: CHANGEME_IAM_ROLE_ARN
## Uncomment this if using Google Cloud
# - name: Authenticate to Google Cloud
# if: steps.list.outputs.stdout
# id: auth
# uses: google-github-actions/auth@v2
# with:
# workload_identity_provider: CHANGEME_WORKLOAD_IDENTITY_PROVIDER
# service_account: CHANGEME_SERVICE_ACCOUNT_EMAIL
## Uncomment this if using Microsoft Azure
# - name: Configure Azure credentials
# if: steps.list.outputs.stdout
# id: auth
# uses: azure/login@v2
# with:
# client-id: CHANGEME_AZURE_CLIENT_ID
# tenant-id: CHANGEME_AZURE_TENANT_ID
# subscription-id: CHANGEME_AZURE_SUBSCRIPTION_ID
- name: Run OpenTofu init on changed stacks
if: steps.list.outputs.stdout
id: init
run: |
terramate run \
--parallel 1 \
--changed \
-- \
tofu init
- name: Create OpenTofu plan on changed stacks
if: steps.list.outputs.stdout
id: plan
run: |
terramate run \
--parallel 5 \
--changed \
-- \
tofu plan -lock-timeout=5m -out out.otplan
- name: Apply planned changes on changed stacks
if: steps.list.outputs.stdout
id: apply
run: |
terramate run \
--parallel 5 \
--changed \
--sync-deployment \
--tofu-plan-file=out.otplan \
-- \
tofu apply -input=false -auto-approve -lock-timeout=5m out.otplan
env:
GITHUB_TOKEN: ${{ github.token }}
- name: Run drift detection
if: steps.list.outputs.stdout && ! cancelled() && steps.apply.outcome != 'skipped'
id: drift
run: |
terramate run \
--parallel 5 \
--changed \
--continue-on-error \
--sync-drift-status \
--tofu-plan-file=drift.otplan \
-- \
tofu plan -out drift.otplan -detailed-exitcode
env:
GITHUB_TOKEN: ${{ github.token }}
yml
name: Terragrunt Deployment
on:
push:
branches:
- main
jobs:
deploy:
name: Deploy Terragrunt changes in changed Terramate stacks
permissions:
id-token: write
contents: read
pull-requests: read
checks: read
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ github.head_ref }}
fetch-depth: 0
- name: Install Terramate
uses: terramate-io/terramate-action@v2
- name: Setup Terragrunt
uses: autero1/action-terragrunt@v3
with:
terragrunt-version: 0.72.6
token: ${{ github.token }}
- name: List changed stacks
id: list
run: terramate list --changed
## Comment this step out if not using AWS
- name: Configure AWS credentials via OIDC
if: steps.list.outputs.stdout
id: auth
uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: CHANGEME_AWS_REGION
role-to-assume: CHANGEME_IAM_ROLE_ARN
## Uncomment this if using Google Cloud
# - name: Authenticate to Google Cloud
# if: steps.list.outputs.stdout
# id: auth
# uses: google-github-actions/auth@v2
# with:
# workload_identity_provider: CHANGEME_WORKLOAD_IDENTITY_PROVIDER
# service_account: CHANGEME_SERVICE_ACCOUNT_EMAIL
## Uncomment this if using Microsoft Azure
# - name: Configure Azure credentials
# if: steps.list.outputs.stdout
# id: auth
# uses: azure/login@v2
# with:
# client-id: CHANGEME_AZURE_CLIENT_ID
# tenant-id: CHANGEME_AZURE_TENANT_ID
# subscription-id: CHANGEME_AZURE_SUBSCRIPTION_ID
- name: Run Terragrunt init in each changed stacks
if: steps.list.outputs.stdout
id: init
run: |
terramate run \
--parallel 1 \
--changed \
-- \
terragrunt init
- name: Create Terragrunt plan on changed stacks
if: steps.list.outputs.stdout
id: plan
run: |
terramate run \
--parallel 5 \
--changed \
-- \
terragrunt plan -lock-timeout=5m -out out.tfplan
- name: Apply planned changes on changed stacks
if: steps.list.outputs.stdout
id: apply
run: |
terramate run \
--parallel 5 \
--changed \
--sync-deployment \
--terraform-plan-file=out.tfplan \
--terragrunt \
-- \
terragrunt apply -input=false -auto-approve -lock-timeout=5m out.tfplan
env:
GITHUB_TOKEN: ${{ github.token }}
- name: Run drift detection
if: steps.list.outputs.stdout && ! cancelled() && steps.apply.outcome != 'skipped'
id: drift
run: |
terramate run \
--parallel 5 \
--changed \
--sync-drift-status \
--continue-on-error \
--terraform-plan-file=drift.tfplan \
--terragrunt \
-- \
terragrunt plan -out drift.tfplan -detailed-exitcode
env:
GITHUB_TOKEN: ${{ github.token }}
yml
name: Terraform Deployment
on:
push:
branches:
- main
jobs:
deploy:
name: Deploy Terraform changes in changed Terramate stacks
permissions:
id-token: write
contents: read
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ github.head_ref }}
fetch-depth: 0
- name: Install Terramate
uses: terramate-io/terramate-action@v2
- name: Install Terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: 1.7.4
terraform_wrapper: false
- name: List changed stacks
id: list
run: terramate list --changed
## Comment this step out if not using AWS
- name: Configure AWS credentials via OIDC
if: steps.list.outputs.stdout
id: auth
uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: CHANGEME_AWS_REGION
role-to-assume: CHANGEME_IAM_ROLE_ARN
## Uncomment this if using Google Cloud
# - name: Authenticate to Google Cloud
# if: steps.list.outputs.stdout
# id: auth
# uses: google-github-actions/auth@v2
# with:
# workload_identity_provider: CHANGEME_WORKLOAD_IDENTITY_PROVIDER
# service_account: CHANGEME_SERVICE_ACCOUNT_EMAIL
## Uncomment this if using Microsoft Azure
# - name: Configure Azure credentials
# if: steps.list.outputs.stdout
# id: auth
# uses: azure/login@v2
# with:
# client-id: CHANGEME_AZURE_CLIENT_ID
# tenant-id: CHANGEME_AZURE_TENANT_ID
# subscription-id: CHANGEME_AZURE_SUBSCRIPTION_ID
- name: Run Terraform init in each changed stacks
if: steps.list.outputs.stdout
id: init
run: |
terramate run \
--parallel 1 \
--changed \
-- \
terraform init
- name: Apply planned changes on changed stacks
if: steps.list.outputs.stdout
id: apply
run: |
terramate run \
--parallel 5 \
--changed \
-- \
terraform apply -input=false -auto-approve -lock-timeout=5m
yml
name: OpenTofu Deployment
on:
push:
branches:
- main
jobs:
deploy:
name: Deploy OpenTofu changes in changed Terramate stacks
permissions:
id-token: write
contents: read
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ github.head_ref }}
fetch-depth: 0
- name: Install Terramate
uses: terramate-io/terramate-action@v2
- name: Install OpenTofu
uses: opentofu/setup-opentofu@v1
with:
tofu_version: 1.9.0
tofu_wrapper: false
- name: List changed stacks
id: list
run: terramate list --changed
## Comment this step out if not using AWS
- name: Configure AWS credentials via OIDC
if: steps.list.outputs.stdout
id: auth
uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: CHANGEME_AWS_REGION
role-to-assume: CHANGEME_IAM_ROLE_ARN
## Uncomment this if using Google Cloud
# - name: Authenticate to Google Cloud
# if: steps.list.outputs.stdout
# id: auth
# uses: google-github-actions/auth@v2
# with:
# workload_identity_provider: CHANGEME_WORKLOAD_IDENTITY_PROVIDER
# service_account: CHANGEME_SERVICE_ACCOUNT_EMAIL
## Uncomment this if using Microsoft Azure
# - name: Configure Azure credentials
# if: steps.list.outputs.stdout
# id: auth
# uses: azure/login@v2
# with:
# client-id: CHANGEME_AZURE_CLIENT_ID
# tenant-id: CHANGEME_AZURE_TENANT_ID
# subscription-id: CHANGEME_AZURE_SUBSCRIPTION_ID
- name: Run OpenTofu init on changed stacks
if: steps.list.outputs.stdout
id: init
run: |
terramate run \
--parallel 1 \
--changed \
-- \
tofu init
- name: Apply planned changes on changed stacks
if: steps.list.outputs.stdout
id: apply
run: |
terramate run \
--parallel 5 \
--changed \
-- \
tofu apply -input=false -auto-approve -lock-timeout=5m
yml
name: Terragrunt Deployment
on:
push:
branches:
- main
jobs:
deploy:
name: Deploy Terragrunt changes in changed Terramate stacks
permissions:
id-token: write
contents: read
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ github.head_ref }}
fetch-depth: 0
- name: Install Terramate
uses: terramate-io/terramate-action@v2
- name: Setup Terragrunt
uses: autero1/action-terragrunt@v3
with:
terragrunt-version: 0.72.6
token: ${{ github.token }}
- name: List changed stacks
id: list
run: terramate list --changed
## Comment this step out if not using AWS
- name: Configure AWS credentials via OIDC
if: steps.list.outputs.stdout
id: auth
uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: CHANGEME_AWS_REGION
role-to-assume: CHANGEME_IAM_ROLE_ARN
## Uncomment this if using Google Cloud
# - name: Authenticate to Google Cloud
# if: steps.list.outputs.stdout
# id: auth
# uses: google-github-actions/auth@v2
# with:
# workload_identity_provider: CHANGEME_WORKLOAD_IDENTITY_PROVIDER
# service_account: CHANGEME_SERVICE_ACCOUNT_EMAIL
## Uncomment this if using Microsoft Azure
# - name: Configure Azure credentials
# if: steps.list.outputs.stdout
# id: auth
# uses: azure/login@v2
# with:
# client-id: CHANGEME_AZURE_CLIENT_ID
# tenant-id: CHANGEME_AZURE_TENANT_ID
# subscription-id: CHANGEME_AZURE_SUBSCRIPTION_ID
- name: Run Terragrunt init in each changed stacks
if: steps.list.outputs.stdout
id: init
run: |
terramate run \
--parallel 1 \
--changed \
-- \
terragrunt init
- name: Apply planned changes on changed stacks
if: steps.list.outputs.stdout
id: apply
run: |
terramate run \
--parallel 5 \
--changed \
-- \
terragrunt apply -input=false -auto-approve -lock-timeout=5m