Automated Apply #
Automated apply adalah tujuan akhir dari Terraform CI/CD yang matang — perubahan konfigurasi yang sudah di-review dan di-merge secara otomatis diterapkan ke infrastruktur tanpa perlu seseorang yang menjalankan perintah secara manual. Ini menghilangkan bottleneck “tunggu si A yang punya akses untuk apply”, memastikan konsistensi antara kode dan infrastruktur, dan memungkinkan tim bergerak lebih cepat. Tapi “otomatis” bukan berarti “tanpa kontrol” — justru automated apply yang baik memiliki lebih banyak safeguard dibanding apply manual.
Prasyarat Automated Apply yang Aman #
Automated apply tanpa prasyarat yang tepat lebih berbahaya dari apply manual. Berikut apa yang harus ada sebelum mengaktifkan automated apply.
PRASYARAT AUTOMATED APPLY:
REVIEW PROCESS:
✓ Semua perubahan melalui PR / merge request
✓ Minimal 1 reviewer yang approve sebelum merge
✓ Plan output tampil di PR agar reviewer melihat DAMPAK, bukan hanya kode
STATE MANAGEMENT:
✓ Remote state dengan locking (S3 + DynamoDB atau Terraform Cloud)
✓ State tidak bisa diakses atau dimodifikasi langsung oleh siapapun selain pipeline
CREDENTIALS:
✓ CI/CD mendapatkan credentials via OIDC (bukan stored secrets)
✓ Credentials berbeda untuk plan dan apply (plan: read-only, apply: full)
MONITORING:
✓ Notifikasi saat apply berhasil atau gagal
✓ Log apply tersimpan dan bisa diaudit
✓ Alert jika ada perubahan yang tidak terduga (drift detection)
GitOps: Branch sebagai Source of Truth #
GitOps adalah pendekatan di mana kondisi branch Git tertentu selalu mencerminkan kondisi infrastruktur yang seharusnya. Setiap merge ke branch tersebut secara otomatis memicu apply.
GITOPS BRANCHING STRATEGY:
main branch → production environment
staging branch → staging environment
develop branch → development environment
Alur perubahan:
feature-branch → PR ke develop → auto-apply dev
develop → PR ke staging → auto-apply staging (atau dengan approval)
staging → PR ke main → apply production (selalu dengan approval)
Setiap branch mencerminkan kondisi environment-nya.
Git history = audit trail infrastruktur.
# GitHub Actions: GitOps-style automated apply
# .github/workflows/terraform-gitops.yml
name: Terraform GitOps
on:
push:
branches: [develop, staging, main]
paths: ['infrastructure/**']
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Determine Environment
id: env
run: |
case "${{ github.ref_name }}" in
develop) echo "environment=dev" >> $GITHUB_OUTPUT
echo "auto_approve=true" >> $GITHUB_OUTPUT ;;
staging) echo "environment=staging" >> $GITHUB_OUTPUT
echo "auto_approve=true" >> $GITHUB_OUTPUT ;;
main) echo "environment=production" >> $GITHUB_OUTPUT
echo "auto_approve=false" >> $GITHUB_OUTPUT ;;
esac
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: >
arn:aws:iam::${{ vars.AWS_ACCOUNT_ID }}:role/TerraformApplyRole-${{ steps.env.outputs.environment }}
aws-region: ap-southeast-1
- uses: hashicorp/setup-terraform@v3
with:
terraform_version: "1.7.0"
- name: Terraform Init
run: terraform init
working-directory: infrastructure/environments/${{ steps.env.outputs.environment }}
- name: Terraform Plan
run: terraform plan -out=tfplan -no-color
working-directory: infrastructure/environments/${{ steps.env.outputs.environment }}
- name: Terraform Apply (Auto-approve for non-production)
if: steps.env.outputs.auto_approve == 'true'
run: terraform apply tfplan
working-directory: infrastructure/environments/${{ steps.env.outputs.environment }}
- name: Terraform Apply (Production — requires environment approval)
if: steps.env.outputs.auto_approve == 'false'
run: terraform apply tfplan
working-directory: infrastructure/environments/${{ steps.env.outputs.environment }}
environment: production # Environment protection rules berlaku di sini
Safeguard: Deteksi Perubahan Berbahaya Sebelum Apply #
Pipeline yang baik memiliki pemeriksaan tambahan sebelum apply berjalan, terutama untuk mendeteksi perubahan yang berpotensi merusak.
#!/bin/bash
# check-plan-safety.sh — jalankan setelah terraform plan, sebelum apply
PLAN_OUTPUT=$(terraform show -json tfplan)
# Hitung resource yang akan dihapus
DESTROY_COUNT=$(echo $PLAN_OUTPUT | jq '[.resource_changes[] | select(.change.actions[] == "delete")] | length')
# Hitung resource yang akan di-replace (destroy + create)
REPLACE_COUNT=$(echo $PLAN_OUTPUT | jq '[.resource_changes[] | select(.change.actions | contains(["delete", "create"]))] | length')
echo "Resources to destroy: $DESTROY_COUNT"
echo "Resources to replace: $REPLACE_COUNT"
# Gagalkan pipeline jika ada destroy di production
if [ "$ENVIRONMENT" = "production" ] && [ "$DESTROY_COUNT" -gt 0 ]; then
echo "ERROR: Destroy operations detected in production plan!"
echo "Destroy operations require manual review and explicit override."
exit 1
fi
# Warning jika ada replace di production
if [ "$ENVIRONMENT" = "production" ] && [ "$REPLACE_COUNT" -gt 0 ]; then
echo "WARNING: Replace operations detected (resource will be destroyed and recreated)"
echo "This may cause downtime. Ensure this is intentional."
# Tidak exit — hanya warning, tetap butuh human approval via environment protection
fi
# Integrasikan check ke pipeline
- name: Check Plan Safety
run: bash ./scripts/check-plan-safety.sh
env:
ENVIRONMENT: ${{ steps.env.outputs.environment }}
working-directory: infrastructure/environments/${{ steps.env.outputs.environment }}
Rollback Strategy #
Automated apply yang gagal di tengah jalan bisa meninggalkan infrastruktur dalam kondisi partial — sebagian resource sudah dibuat, sebagian belum. Punya strategi rollback yang jelas sangat penting.
STRATEGI ROLLBACK TERRAFORM:
OPSI 1: Re-apply versi sebelumnya (paling aman)
- Revert commit di Git
- Pipeline otomatis trigger apply versi lama
- Terraform akan mengembalikan infrastruktur ke kondisi sebelumnya
Catatan: Ini hanya bekerja jika resource yang bermasalah bisa diubah kembali
(tidak semua resource bisa di-rollback dengan aman)
OPSI 2: Terraform apply dari state point tertentu
- terraform state pull > backup.tfstate (sebelum apply)
- Jika apply gagal: terraform apply -target=resource.yang.perlu.diperbaiki
Catatan: -target hanya untuk perbaikan darurat, bukan workflow rutin
OPSI 3: Restore dari state backup
- Jika state korup atau tidak konsisten
- Restore tfstate dari backup sebelumnya
- Kemudian jalankan plan untuk melihat perbedaan
PENCEGAHAN LEBIH BAIK DARI ROLLBACK:
✓ Selalu backup state sebelum apply besar
✓ Gunakan create_before_destroy untuk resource kritikal
✓ Test perubahan di staging sebelum production
✓ Simpan plan output — bisa menjadi referensi saat debugging
Notifikasi Setelah Apply #
Tim perlu tahu ketika infrastruktur berubah — baik berhasil maupun gagal.
# Notifikasi ke Slack setelah apply
- name: Notify Slack on Success
if: success()
uses: slackapi/slack-github-action@v1
with:
payload: |
{
"text": "✅ Terraform apply berhasil",
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*✅ Terraform Apply Berhasil*\nEnvironment: `${{ steps.env.outputs.environment }}`\nCommit: `${{ github.sha }}`\nPR: ${{ github.event.pull_request.html_url }}"
}
}
]
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_INFRA_WEBHOOK }}
- name: Notify Slack on Failure
if: failure()
uses: slackapi/slack-github-action@v1
with:
payload: |
{
"text": "🚨 Terraform apply GAGAL",
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*🚨 Terraform Apply GAGAL*\nEnvironment: `${{ steps.env.outputs.environment }}`\nLihat log: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
}
}
]
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_INFRA_WEBHOOK }}
Ringkasan #
- Prasyarat automated apply: remote state dengan locking, review process melalui PR, credentials via OIDC, dan monitoring notifikasi.
- GitOps: branch Git mencerminkan kondisi environment — merge ke
develop= apply dev, merge kemain= apply production.- Dev dan staging bisa auto-apply setelah review; production selalu membutuhkan approval eksplisit melalui environment protection rules.
- Safeguard deteksi destroy — cegah apply otomatis di production jika ada operasi delete yang tidak terduga dalam plan.
- Rollback paling aman adalah revert commit di Git dan biarkan pipeline apply versi sebelumnya — ini adalah keunggulan GitOps.
- Notifikasi selalu ada — tim harus tahu setiap kali infrastruktur berubah, baik berhasil maupun gagal, dengan link ke log yang bisa diaudit.
← Sebelumnya: Plan Approval Strategy Berikutnya: Policy as Code →