atmos-gitops
Atmos GitOps and CI/CD Integrations
Overview
Atmos provides native CI/CD integration patterns for managing Terraform infrastructure through automated
pipelines. The three primary integration paths are GitHub Actions, Spacelift, and Atlantis. Each approach
leverages Atmos stack configurations and the atmos describe affected command to detect changes between
commits or branches, enabling efficient PR-based plan and merge-based apply workflows.
All integrations follow a common GitOps pattern:
- Detect which stacks and components changed using
atmos describe affected - Run
atmos terraform planfor each affected component/stack pair - Review plan output in the PR or CI/CD UI
- Apply changes on merge (or via manual trigger / label)
Change Detection with atmos describe affected
The atmos describe affected command is the foundation of all CI/CD integrations. It compares two Git
commits to produce a list of affected Atmos components and stacks.
How It Works
The command performs these steps:
- Clone or reference the target branch/commit (the comparison baseline)
- Deep-merge all stack configurations for both the current working branch and the target branch
- Identify changes in component directories (file-level diffs)
- Compare each section of the stack configuration to detect differences
- Output a list of affected components and stacks
When component source directories have changed, all related stacks are marked affected and Atmos skips further configuration comparison for those stacks, streamlining the process.
Command Usage
# Compare current branch against the default branch (main)
atmos describe affected
# Compare against a specific branch
atmos describe affected --ref refs/heads/main
# Compare against a specific commit SHA
atmos describe affected --sha 6a9b2c1
# Use a pre-cloned repo for the target reference
atmos describe affected --repo-path /path/to/cloned/target
# Output as JSON for CI/CD consumption
atmos describe affected --format json
Output Format
The command outputs a JSON array of affected items. Each item contains:
[
{
"component": "vpc",
"component_type": "terraform",
"stack": "plat-ue2-dev",
"stack_slug": "plat-ue2-dev-vpc",
"affected": "stack.vars"
},
{
"component": "eks/cluster",
"component_type": "terraform",
"stack": "plat-ue2-prod",
"stack_slug": "plat-ue2-prod-eks-cluster",
"affected": "component"
}
]
Fields:
component-- The Atmos component namecomponent_type-- Alwaysterraformfor Terraform componentsstack-- The Atmos stack namestack_slug-- A slug combining stack and component (used for matrix grouping)affected-- What changed:component(source files),stack.vars,stack.env,stack.settings, etc.
Filtering and Grouping for CI/CD Matrices
The output can be filtered and grouped for GitHub Actions matrix strategies using jq expressions
configured in atmos.yaml:
# atmos.yaml
integrations:
github:
gitops:
matrix:
sort-by: .stack_slug
group-by: .stack_slug | split("-") | [.[0], .[2]] | join("-")
The group-by expression creates groups for parallel execution, which helps work around the
GitHub Actions 256-job matrix limit.
GitHub Actions Integration
Cloud Posse provides a set of GitHub Actions designed for Atmos-native GitOps workflows. These actions are open source (Apache 2.0 license), require no subscriptions, and use GitHub OIDC for authentication (no hardcoded credentials).
Required Infrastructure
GitHub Actions that manage planfiles require:
- S3 bucket for storing Terraform planfiles
- DynamoDB table for planfile metadata (hash key:
id, GSI:pr-createdAt-index) - Two IAM roles: one for plan/apply operations, one for accessing the S3/DynamoDB state storage
- atmos.yaml configuration with the
integrations.github.gitopssection
atmos.yaml Configuration for GitHub Actions
# atmos.yaml
integrations:
github:
gitops:
terraform-version: 1.5.2
infracost-enabled: false
artifact-storage:
region: us-east-2
bucket: cptest-core-ue2-auto-gitops
table: cptest-core-ue2-auto-gitops-plan-storage
role: arn:aws:iam::xxxxxxxxxxxx:role/cptest-core-ue2-auto-gitops-gha
role:
plan: arn:aws:iam::yyyyyyyyyyyy:role/cptest-core-gbl-identity-gitops
apply: arn:aws:iam::yyyyyyyyyyyy:role/cptest-core-gbl-identity-gitops
matrix:
sort-by: .stack_slug
group-by: .stack_slug | split("-") | [.[0], .[2]] | join("-")
Core GitHub Actions
- setup-atmos -- Installs Atmos in the workflow runner
- atmos-terraform-plan -- Runs
atmos terraform plan, stores planfiles in S3, posts Job Summaries - atmos-terraform-apply -- Retrieves planfiles from S3, runs
atmos terraform apply - affected-stacks -- Runs
atmos describe affectedand outputs a matrix for parallel jobs - atmos-terraform-drift-detection -- Scheduled workflow to detect drift and create GitHub Issues
- atmos-terraform-drift-remediation -- Applies fixes for drifted components via IssueOps
GitOps Workflow Pattern
The standard PR-based workflow:
- Developer opens a PR with infrastructure changes
- The plan workflow triggers:
a.
affected-stacksaction identifies changed components/stacks b. Output feeds into a matrix strategy c.atmos-terraform-planruns for each affected component/stack pair d. Plan summaries appear as GitHub Job Summaries - Team reviews plan output in the PR
- On merge to main, the apply workflow triggers:
a.
atmos-terraform-applyretrieves stored planfiles from S3 b. Applies each affected component/stack pair c. Apply summaries appear as Job Summaries
Drift Detection and Remediation
Drift detection runs on a schedule (cron):
- The drift detection workflow gathers all components and stacks
- Runs
atmos terraform planfor each component/stack pair - If drift is detected, creates a GitHub Issue with plan details
- To remediate, add the
applylabel to the Issue - The drift remediation workflow detects the label, runs
atmos terraform apply, and closes the Issue
The max-opened-issues input (default: 10) limits how many drift Issues are created per run.
256 Matrix Limitation
GitHub Actions supports at most 256 matrix jobs per workflow. For large environments, use a two-level workflow pattern:
- Top-level workflow groups affected stacks using the
group-byjq expression - Each group is dispatched to a reusable workflow
- The reusable workflow runs the actual plan/apply matrix for its group
Spacelift Integration
Atmos natively supports Spacelift through stack configuration settings and a Terraform module that reads YAML stack configs to provision Spacelift resources.
Stack Configuration for Spacelift
Configure Spacelift behavior in the settings.spacelift section of component configurations:
components:
terraform:
my-component:
settings:
spacelift:
workspace_enabled: true
administrative: false
autodeploy: true
before_init: []
component_root: components/terraform/my-component
description: "My component description"
stack_destructor_enabled: false
worker_pool_name: null
policies_enabled: []
administrative_trigger_policy_enabled: false
policies_by_id_enabled:
- my-custom-policy
terraform_workflow_tool: TERRAFORM # or OPEN_TOFU
Key settings:
workspace_enabled-- Whether this component/stack is managed in Spaceliftadministrative-- Whether this is an admin stack that manages other stacksautodeploy-- Automatically apply on merge without manual confirmationcomponent_root-- Path to the Terraform component directorypolicies_by_id_enabled-- List of Spacelift policy IDs to attachterraform_workflow_tool-- UseTERRAFORMorOPEN_TOFU
Spacelift Stack Dependencies
Define component dependencies using settings.depends_on:
components:
terraform:
my-component:
settings:
depends_on:
1:
component: "vpc"
2:
component: "eks/cluster"
tenant: "plat"
environment: "ue2"
stage: "prod"
Each dependency specifies a component (required) and optional context variables
(namespace, tenant, environment, stage) to reference components in other stacks.
OpenTofu Support
To make OpenTofu the default for all Spacelift stacks:
settings:
spacelift:
terraform_workflow_tool: OPEN_TOFU
Or configure per-component to override the global setting.
Atlantis Integration
Atmos supports Atlantis for Terraform Pull Request Automation through three commands:
atmos atlantis generate repo-config-- Generateatlantis.yamlrepo-level configurationatmos terraform generate backends-- Generate backend configuration for all componentsatmos terraform generate varfiles-- Generate deep-merged varfiles for all stacks
Atlantis Configuration in atmos.yaml
integrations:
atlantis:
path: "atlantis.yaml"
config_templates:
config-1:
version: 3
automerge: true
delete_source_branch_on_merge: true
parallel_plan: true
parallel_apply: true
allowed_regexp_prefixes:
- dev/
- staging/
- prod/
project_templates:
project-1:
name: "{tenant}-{environment}-{stage}-{component}"
workspace: "{workspace}"
dir: "{component-path}"
terraform_version: v1.8
delete_source_branch_on_merge: true
autoplan:
enabled: true
when_modified:
- "**/*.tf"
- "varfiles/$PROJECT_NAME.tfvars"
apply_requirements:
- "approved"
workflow_templates:
workflow-1:
plan:
steps:
- run: terraform init -input=false
- run: terraform workspace select $WORKSPACE
- run: terraform plan -input=false -refresh -out $PLANFILE -var-file varfiles/$PROJECT_NAME.tfvars
apply:
steps:
- run: terraform apply $PLANFILE
Generating the Atlantis Configuration
atmos atlantis generate repo-config --config-template config-1 --project-template project-1
This generates an atlantis.yaml file with a project entry for each Atmos component in every stack,
using the specified config and project templates.
Stack-Level Atlantis Configuration
Atlantis settings can also be overridden in stack manifests using settings.atlantis, which deep-merges
with the integrations.atlantis section in atmos.yaml.
Environment Promotion Patterns
Atmos supports environment promotion through its stack inheritance model:
- Catalog-based defaults -- Define common configuration in
stacks/catalog/ - Environment overrides -- Override values per environment in stack manifests
- PR-based promotion -- Use Git branches and PRs to promote changes through environments
- Sequential apply -- Use CI/CD dependencies to apply to dev first, then staging, then prod
Example promotion workflow:
- Changes merged to
mainauto-apply todev - Manual approval (or separate PR) promotes to
staging - Another manual approval promotes to
prod
Best Practices for CI/CD with Atmos
- Use
atmos describe affectedto minimize CI/CD runtime by only planning/applying changed stacks - Store planfiles securely -- Use encrypted S3 buckets with DynamoDB locking for GitHub Actions
- Use GitHub OIDC -- Never hardcode AWS credentials in workflows
- Group matrix jobs -- Use the
group-bysetting to work around the 256-job GitHub Actions limit - Limit drift detection Issues -- Set
max-opened-issuesto keep drift manageable - Use separate IAM roles for plan and apply operations (least privilege)
- Pin Atmos and Terraform versions in CI/CD to ensure reproducibility
- Run
atmos validate stacksearly in CI/CD pipelines to catch configuration errors - Use Job Summaries instead of PR comments to avoid noisy pull requests
- Test infrastructure changes in lower environments before promoting to production
Compatibility Notes
GitHub Actions versions must match the Atmos version:
- Atmos >= 1.63.0: Use v2+ of plan, apply, drift-remediation; v1+ of drift-detection and affected-stacks
- Atmos < 1.63.0: Use older action versions (v1 plan/apply, v0 drift-detection, v2 affected-stacks)
The integrations.github.gitops configuration in atmos.yaml is supported in Atmos >= 1.63.0. Earlier
versions pass the settings directly as GitHub Action inputs.
Additional Resources
- For complete GitHub Actions inputs/outputs, see references/github-actions.md
- For Spacelift stack configuration details, see references/spacelift.md