Terraform CI/CD: Atlantis, Cloud, GitOps Prompt
Choose and configure Terraform CI/CD — Atlantis, Terraform Cloud, Spacelift, custom CI; plan/apply workflows, approvals.
- Target user
- Platform engineers automating Terraform
- Difficulty
- Intermediate
- Tools
- Claude, ChatGPT
The prompt
You are a senior platform engineer who has set up Terraform CI/CD across many tools — Atlantis, Terraform Cloud, custom pipelines. I will provide: - Team size + workflow - Tool preference - Goal (setup / migrate / harden) Your job: 1. **Tool comparison**: - **Atlantis** — open source; runs in your infra; PR comment driven - **Terraform Cloud** — managed; rich features; per-run cost - **Spacelift** — managed; flexible workflows - **env0** — managed; alt option - **Custom CI** (GitLab/GitHub) — full control; more work 2. **For Atlantis**: - GitHub/GitLab webhooks - `atlantis plan` / `atlantis apply` comments - Locks at PR level - Server runs in your cloud 3. **For Terraform Cloud**: - Workspace per state - VCS integration - Plan + apply UI - Variables, runs, policy 4. **For custom CI**: - GitLab `resource_group` for serialization - GitHub Actions matrix - Manual approval for apply 5. **For plan/apply workflow**: - Plan on every PR - Plan posted as comment - Apply on merge OR via comment - Approval gate 6. **For policy**: - Sentinel (TFC) - OPA / Checkov / tfsec - Pre-apply policy check 7. **For state locking**: - Backend handles; orchestrator respects - Don't bypass 8. **For drift detection**: - Scheduled runs - Alert on drift Mark DESTRUCTIVE: auto-apply without review, broad webhook permissions, atlantis with admin role to many accounts. --- Team + workflow: [DESCRIBE] Tool preference: [DESCRIBE] Goal: [DESCRIBE]
Why this prompt works
CI/CD for Terraform varies widely. This prompt walks options.
How to use it
- Pick tool matching team.
- Plan on PR.
- Apply with approval.
- Policy in pipeline.
Patterns
Atlantis
# atlantis.yaml (in repo)
version: 3
projects:
- name: prod-network
dir: envs/prod/network
workflow: prod
- name: prod-compute
dir: envs/prod/compute
workflow: prod
- name: staging-network
dir: envs/staging/network
workflow: staging
workflows:
prod:
plan:
steps:
- init
- plan
apply:
steps:
- apply
staging:
plan:
steps:
- init
- plan
apply:
steps:
- apply
Workflow:
- Open PR
- Atlantis comments
atlantis planautomatically - Review plan output in PR comment
- Comment
atlantis applyto apply - Merge after success
Terraform Cloud workspace
terraform {
cloud {
organization = "myorg"
workspaces {
tags = ["env:production", "team:platform"]
}
}
}
TFC features:
- Plans on PR via VCS integration
- Apply via UI or auto
- Variables stored encrypted
- Run history
- Sentinel policy
Custom GitLab CI
stages: [plan, apply]
.tf-job: &tf-job
image: hashicorp/terraform:1.9
variables:
TF_VAR_env: $CI_ENVIRONMENT_NAME
before_script:
- cd envs/$CI_ENVIRONMENT_NAME
- terraform init
plan:
<<: *tf-job
stage: plan
script:
- terraform plan -out=tfplan
- terraform show -no-color tfplan > plan.txt
artifacts:
paths: [envs/$CI_ENVIRONMENT_NAME/tfplan, envs/$CI_ENVIRONMENT_NAME/plan.txt]
expire_in: 1 week
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
apply:
<<: *tf-job
stage: apply
resource_group: terraform-$CI_ENVIRONMENT_NAME
script:
- terraform apply -auto-approve tfplan
needs: [plan]
environment:
name: $CI_ENVIRONMENT_NAME
rules:
- if: $CI_COMMIT_BRANCH == "main"
when: manual
MR comment with plan output (custom CI)
# In CI script
PLAN_OUTPUT=$(terraform show -no-color tfplan)
PLAN_BODY=$(jq -Rs '.' <<<"$PLAN_OUTPUT")
curl -X POST \
-H "PRIVATE-TOKEN: $GITLAB_API_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"body\":\"### Terraform Plan\n\n\`\`\`\n$PLAN_OUTPUT\n\`\`\`\"}" \
"https://gitlab.example.com/api/v4/projects/$CI_PROJECT_ID/merge_requests/$CI_MERGE_REQUEST_IID/notes"
Drift detection (scheduled)
drift-check:
stage: plan
script:
- cd envs/prod
- terraform init
- terraform plan -detailed-exitcode -out=tfplan
# Exit codes: 0=no changes, 1=error, 2=changes
rules:
- if: $CI_PIPELINE_SOURCE == "schedule"
allow_failure:
exit_codes:
- 2 # drift detected: warn
after_script:
- |
if [ $TF_EXIT_CODE -eq 2 ]; then
# Alert
curl -X POST -d '{"text":"Drift detected in prod"}' $SLACK_WEBHOOK
fi
Comparison
| Aspect | Atlantis | TFC | Custom CI |
|---|---|---|---|
| Cost | Self-hosted | Per-run | Self-hosted CI |
| Setup | Moderate | Easy | Custom |
| Features | PR comments | Rich UI | Whatever you build |
| Policy | OPA via integrations | Sentinel built-in | Custom |
| Audit | Logs | UI | CI logs |
| Best for | Open source teams | Enterprise | Specialized needs |
Common findings this catches
- No plan posted on PR → reviewers blind.
- Auto-apply on main without approval → safety.
- Webhook secret exposed → rotate.
- Atlantis admin to all clouds → scope.
- TFC variables with prod credentials → mark sensitive.
- No drift detection → schedule.
- Custom CI without state locking respect → race.
When to escalate
- Tool migration — staged.
- Multi-team Atlantis sharing — coordinate.
- Cost vs feature tradeoffs — discuss.
Related prompts
-
Terraform Plan Review Checklist Prompt
Review Terraform plan output — read 'destroy', 'replace', 'create', identify dangerous changes, automate review.
-
Terraform Policy-as-Code (Sentinel / OPA / Checkov) Prompt
Implement policy-as-code for Terraform — Sentinel (TFC), OPA/Conftest, Checkov, tfsec, enforce security and compliance.
-
Terraform State Backend Design Prompt
Design Terraform state backend — S3+DynamoDB, GCS, Azure Blob, encryption, locking, versioning, cross-account access.