Skip to main content

Atmos Terraform Plan

The Cloud Posse GitHub Action for "Atmos Terraform Plan" simplifies provisioning Terraform from within GitHub using workflows. Understand precisely what to expect from running a terraform plan from directly within the GitHub UI for any Pull Request.

Given any component and stack in an Atmos supported infrastructure environment, github-action-atmos-terraform-plan will run atmos terraform plan, generate a Terraform planfile, store this planfile in an S3 Bucket with metadata in DynamodDB, and finally format the Terraform Plan result as part of a GitHub Workflow Job Summary.

This action is intended to be used together with Atmos Terraform Apply and Atmos Affected Stacks.


This GitHub Action incorporates superior GitOps support for Terraform by utilizing the capabilities of Atmos, enabling efficient management of large enterprise-scale environments.

  • Implements Native GitOps with Atmos and Terraform
  • No hardcoded credentials. Use GitHub OIDC to assume roles.
  • Compatible with GitHub Cloud & Self-hosted Runners for maximum flexibility.
  • Beautiful Job Summaries don't clutter up pull requests with noisy GitHub comments
  • 100% Open Source with Permissive APACHE2 License means you have no expensive subscriptions or long-term commitments.


The following screenshot showcases a successful "plan" Job Summary report. The report effectively utilizes badges to clearly indicate success or failure. Furthermore, it specifically highlights any potentially destructive operations, mitigating the risk of unintentional destructive actions. A diff-style format is employed to illustrate the creation, recreation, destruction, or modification of resources. Unnecessary details are neatly hidden behind a collapsible <details/> block, ensuring a streamlined view. Additionally, developers are provided with a direct link to access the job run, eliminating the need for manual searching to gather information about any potential issues.

Example Image

By expanding the "Terraform Plan Summary" block (clicking on the <details/> block), the full details of the plan are visible.

Example Image Expanded

Usage Example

In this example, the action is triggered when certain events occur, such as a manual workflow dispatch or the opening, synchronization, or reopening of a pull request, specifically on the main branch. It specifies specific permissions related to assuming roles in AWS. Within the "plan" job, the "component" and "stack" are hardcoded. In practice, these are usually derived from another action.

name: "atmos-terraform-plan"

- opened
- synchronize
- reopened
- main

# These permissions are required for GitHub to assume roles in AWS
id-token: write
contents: read

runs-on: ubuntu-latest
- name: Plan Atmos Component
uses: cloudposse/github-action-atmos-terraform-plan@v1
component: "foobar"
stack: "plat-ue2-sandbox"
component-path: "components/terraform/s3-bucket"
terraform-plan-role: "arn:aws:iam::111111111111:role/acme-core-gbl-identity-gitops"
terraform-state-bucket: "acme-core-ue2-auto-gitops"
terraform-state-role: "arn:aws:iam::999999999999:role/acme-core-ue2-auto-gitops-gha"
terraform-state-table: "acme-core-ue2-auto-gitops"
aws-region: "us-east-2"

Please note that in practice, we recommend combining this action with the affected-stacks GitHub Action inside a matrix to plan all affected stacks in parallel.


This GitHub Action depends on a few resources:

  • S3 bucket for storing planfiles
  • DynamoDB table for retrieving metadata about planfiles
  • 2x IAM roles for "planning" and accessing the "state" bucket

S3 Bucket

This action can use any S3 Bucket to keep track of your planfiles. Just ensure the bucket is properly locked down since planfiles may contain secrets.

For example, vendor in the s3-component, then using an Atmos stack configuration, define a bucket using the s3-bucket component with this catalog configuration:

- catalog/s3-bucket/defaults

# S3 Bucket for storing Terraform Plans
component: s3-bucket
- s3-bucket/defaults
name: gitops-plan-storage
allow_encrypted_uploads_only: false

Assign this S3 Bucket ARN to the terraform-plan-bucket input.

DynamoDB Table

Similarly, a simple DynamoDB table can be provisioned using our dynamodb component. Set the Hash Key and create a Global Secondary Index as follows:

- catalog/dynamodb/defaults

# DynamoDB table used to store metadata for Terraform Plans
component: dynamodb
- dynamodb/defaults
name: gitops-plan-storage
# This key (case-sensitive) is required for the cloudposse/github-action-terraform-plan-storage action
hash_key: id
range_key: ""
# Only these 2 attributes are required for creating the GSI,
# but there will be several other attributes on the table itself
- name: 'createdAt'
type: 'S'
- name: 'pr'
type: 'N'
# This GSI is used to Query the latest plan file for a given PR.
- name: pr-createdAt-index
hash_key: pr
range_key: createdAt
projection_type: ALL
non_key_attributes: []
read_capacity: null
write_capacity: null
# Auto delete old entries
ttl_enabled: true
ttl_attribute: ttl

Pass the ARN of this table as the input to the terraform-plan-table of the cloudposse/github-action-atmos-terraform-plan GitHub Action.

IAM Access Roles

First create an access role for storing and retrieving planfiles from the S3 Bucket and DynamoDB table. We deploy this role using the gitops component. Assign this role ARN to the terraform-state-role input.

Next, create a role for GitHub workflows to use to plan and apply Terraform. We typically create an "AWS Team" with our aws-teams component, and then allow this team to assume terraform in the delegated accounts with our aws-team-roles component. Assign this role ARN to the terraform-plan-role input