Multi-Environment Deployment Golang CI: AI Checkpoint, Progressive Delivery
Setup multi-environment deployment untuk Go service dengan AI checkpoint. Progressive delivery dari staging ke production dengan automated verification dan rollback.
Multi-Environment Deployment dengan AI Checkpoint
Multi-environment deployment golang dengan AI checkpoint adalah cara paling aman untuk merilis Go service ke production tanpa deg-degan setiap kali menekan tombol deploy. Deployment ke production memang selalu jadi momen paling kritis dalam software delivery — sekali salah, dampaknya langsung dirasakan user.
Di artikel ini kita bangun pipeline deployment yang progressive dan aman: dari staging ke production, dengan AI checkpoint yang memverifikasi setiap tahap sebelum mempromosikan perubahan ke environment berikutnya. Idenya sederhana — semakin jauh perubahan bergerak menuju production, semakin banyak bukti yang kita kumpulkan bahwa deployment itu aman.
13.1 Arsitektur Multi-Environment
Fondasi dari deployment yang aman adalah rantai environment yang jelas, di mana setiap tahap memberikan gate tambahan sebelum perubahan sampai ke user. Diagram berikut menunjukkan environment chain yang kita pakai di Santekno Shop, dari mesin developer hingga production.
1Environment chain Santekno Shop:
2
3DEVELOPMENT (local)
4 Developer machine
5 Docker Compose
6 Tidak ada pipeline
7
8 ↓ PR merge ke develop
9
10STAGING
11 Environment: staging.santekno.com
12 Deploy: otomatis setelah merge ke develop
13 Database: staging DB (data synthetic)
14 Kafka: staging cluster
15
16 ↓ AI health check + smoke test
17 ↓ Manual approval (optional, sprint demo)
18
19PRODUCTION
20 Environment: santekno.com
21 Deploy: manual trigger atau automatic setelah staging pass
22 Database: production DB
23 Kafka: production cluster
24
25 ↓ Progressive rollout (canary)
26 ↓ AI health monitoring
27 ↓ Rollback if neededPerhatikan bahwa tidak ada perubahan yang bisa “lompat” langsung ke production — setiap environment adalah gerbang yang harus lolos dulu, dan itulah yang membuat progressive delivery ini aman.
13.2 Staging Deployment Workflow
Staging adalah gate wajib pertama, dan deployment ke sini harus otomatis penuh agar tidak ada friksi. Workflow GitHub Actions berikut membangun image, menjalankan test, deploy ke Kubernetes staging, lalu memicu AI health check sebagai checkpoint.
1# .github/workflows/staging-deploy.yml
2name: Deploy to Staging
3
4on:
5 push:
6 branches: [develop]
7
8env:
9 GO_VERSION: '1.22'
10 REGISTRY: ghcr.io
11 IMAGE_NAME: ${{ github.repository }}
12 ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
13
14jobs:
15 build:
16 name: Build & Push Image
17 runs-on: ubuntu-latest
18 permissions:
19 packages: write
20 contents: read
21 outputs:
22 image_tag: ${{ steps.tag.outputs.tag }}
23
24 steps:
25 - uses: actions/checkout@v4
26
27 - name: Set image tag
28 id: tag
29 run: |
30 TAG="${{ github.sha }}"
31 echo "tag=$TAG" >> $GITHUB_OUTPUT
32
33 - name: Build and test
34 run: |
35 go test -race ./...
36 go build -o /tmp/app ./cmd/server/
37
38 - name: Build Docker image
39 run: |
40 docker build \
41 --label "git.sha=${{ github.sha }}" \
42 --label "git.branch=develop" \
43 --label "build.timestamp=$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
44 -t "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.tag.outputs.tag }}" \
45 -t "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:staging-latest" \
46 .
47
48 - name: Push image
49 uses: docker/login-action@v3
50 with:
51 registry: ${{ env.REGISTRY }}
52 username: ${{ github.actor }}
53 password: ${{ secrets.GITHUB_TOKEN }}
54
55 deploy-staging:
56 name: Deploy to Staging
57 runs-on: ubuntu-latest
58 needs: build
59 environment:
60 name: staging
61 url: https://staging.santekno.com
62 permissions:
63 deployments: write
64 steps:
65 - uses: actions/checkout@v4
66
67 - name: Deploy to staging
68 env:
69 KUBECONFIG: ${{ secrets.STAGING_KUBECONFIG }}
70 run: |
71 kubectl set image deployment/santekno-shop \
72 api="${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.build.outputs.image_tag }}" \
73 --namespace=staging
74 kubectl rollout status deployment/santekno-shop \
75 --namespace=staging \
76 --timeout=120s
77
78 - name: Run database migrations
79 env:
80 DATABASE_URL: ${{ secrets.STAGING_DATABASE_URL }}
81 run: |
82 go run ./cmd/migrate/main.go up
83
84 staging-health-check:
85 name: Staging Health Check
86 runs-on: ubuntu-latest
87 needs: deploy-staging
88 steps:
89 - uses: actions/checkout@v4
90
91 - name: Wait for services to stabilize
92 run: sleep 30
93
94 - name: Run smoke tests
95 id: smoke
96 run: |
97 chmod +x scripts/smoke-test.sh
98 RESULTS=$(./scripts/smoke-test.sh staging.santekno.com)
99 echo "results=$RESULTS" >> $GITHUB_OUTPUT
100
101 - name: AI Health Analysis
102 id: ai_health
103 continue-on-error: true
104 env:
105 ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
106 run: |
107 chmod +x scripts/ai-deployment-check.sh
108 ANALYSIS=$(./scripts/ai-deployment-check.sh \
109 "staging.santekno.com" \
110 "${{ needs.build.outputs.image_tag }}")
111 echo "analysis=$ANALYSIS" >> $GITHUB_OUTPUT
112 VERDICT=$(echo "$ANALYSIS" | grep "VERDICT:" | grep -oP '(HEALTHY|DEGRADED|FAILING)' || echo "HEALTHY")
113 echo "verdict=$VERDICT" >> $GITHUB_OUTPUT
114
115 - name: Fail if staging is unhealthy
116 run: |
117 if [ "${{ steps.ai_health.outputs.verdict }}" == "FAILING" ]; then
118 echo "::error::Staging deployment is FAILING — investigate before production"
119 exit 1
120 fiKunci dari workflow ini adalah pemisahan tegas antara build, deploy-staging, dan staging-health-check — sehingga jika AI checkpoint memberi verdict FAILING, pipeline berhenti sebelum ada perubahan yang naik ke production.
13.3 Smoke Test Script
Sebelum AI menganalisis, kita butuh verifikasi deterministik bahwa deployment benar-benar berfungsi. Script smoke test berikut mengecek health endpoint, versi API, konektivitas database dan Redis, hingga response time — semuanya via HTTP call sederhana.
1#!/bin/bash
2# scripts/smoke-test.sh
3# Basic smoke tests untuk verify deployment berhasil
4
5set -euo pipefail
6
7HOST="${1:-staging.santekno.com}"
8BASE_URL="https://${HOST}"
9PASS=true
10RESULTS=()
11
12# Test 1: Health check endpoint
13HEALTH=$(curl -sf "${BASE_URL}/health" 2>/dev/null) || {
14 RESULTS+=("Health check: FAIL")
15 PASS=false
16}
17
18if [ -n "$HEALTH" ]; then
19 STATUS=$(echo "$HEALTH" | jq -r '.status' 2>/dev/null || echo "unknown")
20 if [ "$STATUS" == "ok" ]; then
21 RESULTS+=("Health check: OK")
22 else
23 RESULTS+=("Health check: $STATUS")
24 PASS=false
25 fi
26fi
27
28# Test 2: API version endpoint
29VERSION=$(curl -sf "${BASE_URL}/api/v1/version" 2>/dev/null | jq -r '.version' 2>/dev/null || echo "")
30if [ -n "$VERSION" ]; then
31 RESULTS+=("API version: $VERSION")
32else
33 RESULTS+=("API version: FAIL")
34 PASS=false
35fi
36
37# Test 3: Database connectivity (via health endpoint)
38DB_STATUS=$(curl -sf "${BASE_URL}/health" | jq -r '.checks.database' 2>/dev/null || echo "unknown")
39[ "$DB_STATUS" == "ok" ] && RESULTS+=("Database: connected") || RESULTS+=("Database: $DB_STATUS")
40
41# Test 4: Redis connectivity
42REDIS_STATUS=$(curl -sf "${BASE_URL}/health" | jq -r '.checks.redis' 2>/dev/null || echo "unknown")
43[ "$REDIS_STATUS" == "ok" ] && RESULTS+=("Redis: connected") || RESULTS+=("Redis: $REDIS_STATUS")
44
45# Test 5: Response time check
46RESPONSE_TIME=$(curl -sf -w "%{time_total}" -o /dev/null "${BASE_URL}/api/v1/orders" \
47 -H "Authorization: Bearer ${SMOKE_TEST_TOKEN:-}" 2>/dev/null || echo "999")
48
49if awk "BEGIN {exit ($RESPONSE_TIME < 2.0) ? 0 : 1}"; then
50 RESULTS+=("Response time: ${RESPONSE_TIME}s")
51else
52 RESULTS+=("Response time slow: ${RESPONSE_TIME}s")
53fi
54
55# Output
56echo "=== Smoke Test Results: $HOST ==="
57for result in "${RESULTS[@]}"; do
58 echo " $result"
59done
60
61[ "$PASS" == "true" ] && echo "SMOKE_STATUS: PASS" || echo "SMOKE_STATUS: FAIL"Smoke test yang baik tidak berhenti di /health saja — ia mengecek alur bisnis nyata (list orders, response time), karena itulah yang benar-benar dirasakan user, bukan sekadar apakah binary hidup.
13.4 AI Deployment Health Check
Metrics deterministik menangkap masalah yang jelas, tapi ada pola dalam log yang lolos dari threshold numerik. Script berikut mengumpulkan health response, metrics, dan log terbaru, lalu menyerahkannya ke AI untuk analisis semantik dan verdict HEALTHY | DEGRADED | FAILING.
1#!/bin/bash
2# scripts/ai-deployment-check.sh
3# AI analyze deployment health dari multiple data points
4
5set -euo pipefail
6
7HOST="${1}"
8IMAGE_TAG="${2:-unknown}"
9BASE_URL="https://${HOST}"
10
11# Collect metrics
12HEALTH=$(curl -sf "${BASE_URL}/health" 2>/dev/null || echo '{"status":"error"}')
13METRICS=$(curl -sf "${BASE_URL}/metrics" 2>/dev/null | head -50 || echo "metrics unavailable")
14LOGS=$(kubectl logs deployment/santekno-shop --namespace=staging \
15 --since=5m --tail=50 2>/dev/null || echo "logs unavailable")
16
17PROMPT="Analyze deployment health for Santekno Shop Go service.
18
19Environment: Staging
20Image: $IMAGE_TAG
21Timestamp: $(date -u +%Y-%m-%dT%H:%M:%SZ)
22
23HEALTH CHECK RESPONSE:
24$HEALTH
25
26RECENT LOGS (last 5 minutes):
27$LOGS
28
29METRICS:
30$METRICS
31
32Analyze:
331. Are there any ERROR or PANIC log entries?
342. Is the health check reporting all services healthy?
353. Are there unusual patterns in the metrics?
364. Any signs of memory leak, connection pool exhaustion, or high error rate?
37
38Output:
39VERDICT: HEALTHY | DEGRADED | FAILING
40Issues (if any):
41 - [issue]: [description and severity]
42RECOMMENDATION: [next steps if not HEALTHY]"
43
44RESULT=$(./scripts/claude-call.sh "$PROMPT" 500) || {
45 echo "AI analysis unavailable"
46 echo "VERDICT: HEALTHY" # graceful: assume healthy if AI unavailable
47 exit 0
48}
49
50echo "$RESULT"Yang penting dari script ini adalah pola graceful degradation: jika AI tidak tersedia, verdict default ke HEALTHY agar ketidaktersediaan tooling tidak pernah memblokir deployment yang sebenarnya sehat.
13.5 Production Deployment: Progressive Rollout
Setelah staging lolos, promosi ke production tidak dilakukan 100% sekaligus — kita pakai canary. Workflow berikut men-deploy ke sebagian kecil pod, memonitor error rate selama beberapa menit, lalu meminta AI menilai apakah aman dipromosikan penuh.
1# .github/workflows/production-deploy.yml
2name: Deploy to Production
3
4on:
5 workflow_dispatch:
6 inputs:
7 image_tag:
8 description: 'Image tag to deploy (default: staging-latest)'
9 required: false
10 default: 'staging-latest'
11 rollout_percentage:
12 description: 'Canary rollout percentage (10, 25, 50, 100)'
13 required: false
14 default: '10'
15
16env:
17 ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
18
19jobs:
20 pre-deploy-check:
21 name: Pre-Production Checks
22 runs-on: ubuntu-latest
23 steps:
24 - uses: actions/checkout@v4
25
26 - name: Verify staging is healthy
27 run: |
28 chmod +x scripts/smoke-test.sh
29 ./scripts/smoke-test.sh staging.santekno.com || {
30 echo "::error::Staging is not healthy — cannot proceed to production"
31 exit 1
32 }
33
34 canary-deploy:
35 name: Canary Deploy (${{ github.event.inputs.rollout_percentage }}%)
36 runs-on: ubuntu-latest
37 needs: pre-deploy-check
38 environment:
39 name: production
40 url: https://santekno.com
41 permissions:
42 deployments: write
43 steps:
44 - uses: actions/checkout@v4
45
46 - name: Deploy canary
47 env:
48 KUBECONFIG: ${{ secrets.PRODUCTION_KUBECONFIG }}
49 IMAGE_TAG: ${{ github.event.inputs.image_tag }}
50 ROLLOUT_PCT: ${{ github.event.inputs.rollout_percentage }}
51 run: |
52 TOTAL_REPLICAS=$(kubectl get deployment santekno-shop \
53 -n production -o jsonpath='{.spec.replicas}')
54 CANARY_REPLICAS=$(( TOTAL_REPLICAS * ROLLOUT_PCT / 100 ))
55 [ "$CANARY_REPLICAS" -lt 1 ] && CANARY_REPLICAS=1
56 echo "Deploying to $CANARY_REPLICAS/$TOTAL_REPLICAS pods ($ROLLOUT_PCT%)"
57 kubectl set image deployment/santekno-shop \
58 api="${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${IMAGE_TAG}" \
59 --namespace=production
60 kubectl rollout status deployment/santekno-shop \
61 --namespace=production --timeout=180s
62
63 - name: Monitor canary (5 minutes)
64 run: |
65 for i in {1..5}; do
66 sleep 60
67 echo "Minute $i/5 check..."
68 ERROR_RATE=$(curl -sf "https://metrics.santekno.com/api/v1/query?query=rate(http_requests_errors[1m])" \
69 2>/dev/null | jq '.data.result[0].value[1]' 2>/dev/null || echo "0")
70 echo " Error rate: $ERROR_RATE"
71 if awk "BEGIN {exit ($ERROR_RATE > 0.05) ? 0 : 1}"; then
72 echo "::error::Error rate $ERROR_RATE > 5% — triggering rollback"
73 kubectl rollout undo deployment/santekno-shop --namespace=production
74 exit 1
75 fi
76 done
77 echo "Canary monitoring passed"
78
79 - name: AI canary assessment
80 id: canary_check
81 continue-on-error: true
82 run: |
83 chmod +x scripts/ai-deployment-check.sh
84 ANALYSIS=$(./scripts/ai-deployment-check.sh "santekno.com" "${{ github.event.inputs.image_tag }}")
85 VERDICT=$(echo "$ANALYSIS" | grep "VERDICT:" | grep -oP '(HEALTHY|DEGRADED|FAILING)' || echo "HEALTHY")
86 echo "verdict=$VERDICT" >> $GITHUB_OUTPUT
87
88 - name: Promote or rollback
89 run: |
90 VERDICT="${{ steps.canary_check.outputs.verdict }}"
91 if [ "$VERDICT" == "FAILING" ]; then
92 echo "::error::Canary is FAILING — rolling back"
93 kubectl rollout undo deployment/santekno-shop --namespace=production
94 exit 1
95 elif [ "$VERDICT" == "DEGRADED" ]; then
96 echo "::warning::Canary is DEGRADED — review before full promotion"
97 else
98 echo "Canary healthy — ready for full promotion"
99 fiPola canary ini menggabungkan dua sinyal: threshold error rate yang deterministik (auto-rollback instan) dan verdict AI yang semantik — sehingga keputusan promote/rollback berdiri di atas bukti kuantitatif sekaligus kualitatif.
13.6 Automated Rollback
Jika metrics melewati batas aman, sistem harus bisa rollback tanpa menunggu manusia. Script berikut mengecek error rate dan P99 latency dari Prometheus, dan begitu ambang terlampaui, langsung menjalankan kubectl rollout undo lalu memberi notifikasi ke Slack.
1#!/bin/bash
2# scripts/auto-rollback.sh
3# Trigger rollback berdasarkan metrics threshold
4
5set -euo pipefail
6
7ENVIRONMENT="${1:-production}"
8NAMESPACE="${ENVIRONMENT}"
9
10MAX_ERROR_RATE=0.05 # 5%
11MAX_P99_LATENCY=2000 # 2 detik dalam ms
12
13TRIGGER_ROLLBACK=false
14REASON=""
15
16ERROR_RATE=$(curl -sf "https://metrics.santekno.com/api/v1/query" \
17 --data-urlencode "query=rate(http_requests_total{status=~'5..'}[2m])/rate(http_requests_total[2m])" \
18 2>/dev/null | jq '.data.result[0].value[1]' | tr -d '"' || echo "0")
19
20if awk "BEGIN {exit ($ERROR_RATE > $MAX_ERROR_RATE) ? 0 : 1}"; then
21 TRIGGER_ROLLBACK=true
22 REASON="Error rate ${ERROR_RATE} > ${MAX_ERROR_RATE} threshold"
23fi
24
25P99_LATENCY=$(curl -sf "https://metrics.santekno.com/api/v1/query" \
26 --data-urlencode "query=histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[2m])) * 1000" \
27 2>/dev/null | jq '.data.result[0].value[1]' | tr -d '"' || echo "0")
28
29if awk "BEGIN {exit ($P99_LATENCY > $MAX_P99_LATENCY) ? 0 : 1}"; then
30 TRIGGER_ROLLBACK=true
31 REASON="P99 latency ${P99_LATENCY}ms > ${MAX_P99_LATENCY}ms threshold"
32fi
33
34if [ "$TRIGGER_ROLLBACK" == "true" ]; then
35 echo "ROLLBACK TRIGGERED: $REASON"
36 kubectl rollout undo deployment/santekno-shop --namespace="$NAMESPACE"
37 kubectl rollout status deployment/santekno-shop --namespace="$NAMESPACE" --timeout=120s
38 echo "Rollback completed"
39 curl -X POST "$SLACK_WEBHOOK" \
40 -H "Content-Type: application/json" \
41 -d "$(jq -n --arg reason "$REASON" --arg env "$ENVIRONMENT" \
42 '{text: ("Auto-rollback triggered in *" + $env + "*\nReason: " + $reason)}')"
43 exit 1
44fi
45
46echo "Deployment healthy, no rollback needed"Rollback otomatis berbasis threshold ini adalah jaring pengaman terakhir — ketika sesuatu benar-benar salah, service pulih dalam hitungan menit tanpa perlu ada engineer yang terbangun tengah malam.
13.7 Deployment Notification yang Informatif
Deployment yang selesai harus dikomunikasikan, tapi notifikasi generik “deploy sukses” tidak banyak membantu. Step berikut memakai AI untuk merangkai notifikasi Slack yang ringkas dan kontekstual dalam Bahasa Indonesia, apapun status akhirnya.
1- name: Send deployment notification
2 if: always()
3 env:
4 ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
5 run: |
6 STATUS="${{ job.status }}"
7 VERSION="${{ github.event.inputs.image_tag }}"
8 ENVIRONMENT="production"
9 ACTOR="${{ github.actor }}"
10
11 PROMPT="Generate a brief deployment notification (max 100 words, Bahasa Indonesia).
12 Deploy: $VERSION
13 Environment: $ENVIRONMENT
14 Status: $STATUS
15 Deployed by: $ACTOR
16 Time: $(date -u '+%Y-%m-%d %H:%M UTC')
17 Format sebagai Slack notification yang informative tapi concise."
18
19 NOTIFICATION=$(./scripts/claude-call.sh "$PROMPT" 150) || \
20 NOTIFICATION="Deploy $VERSION ke $ENVIRONMENT: $STATUS"
21
22 curl -X POST "${{ secrets.SLACK_WEBHOOK }}" \
23 -H "Content-Type: application/json" \
24 -d "$(jq -n --arg text "$NOTIFICATION" '{text: $text}')"Dengan if: always() dan fallback string, notifikasi selalu terkirim — bahkan saat deploy gagal atau AI tidak tersedia — sehingga tim tidak pernah kehilangan visibilitas atas apa yang terjadi di production.
13.8 Feature Flags untuk Safe Deployment
Deployment kode dan aktivasi fitur sebaiknya dipisah, dan feature flag adalah mekanismenya. Kode Go berikut menunjukkan manager flag sederhana berbasis environment variable, lalu dipakai di handler untuk memilih alur baru atau lama secara runtime.
1// internal/feature/flags.go
2// Feature flags untuk gradual rollout tanpa deployment
3
4package feature
5
6import (
7 "context"
8 "os"
9)
10
11type Flag string
12
13const (
14 NewCancelOrderFlow Flag = "new_cancel_order_flow"
15 FlashSaleFeature Flag = "flash_sale_feature"
16 AIProductDescription Flag = "ai_product_description"
17)
18
19type Manager struct {
20 // Bisa di-backed oleh Redis, LaunchDarkly, atau simple env vars
21 flags map[Flag]bool
22}
23
24func NewManager() *Manager {
25 return &Manager{
26 flags: map[Flag]bool{
27 NewCancelOrderFlow: os.Getenv("FF_NEW_CANCEL_ORDER") == "true",
28 FlashSaleFeature: os.Getenv("FF_FLASH_SALE") == "true",
29 AIProductDescription: os.Getenv("FF_AI_PRODUCT_DESC") == "true",
30 },
31 }
32}
33
34func (m *Manager) IsEnabled(ctx context.Context, flag Flag) bool {
35 return m.flags[flag]
36}
37
38// Usage di handler:
39func (h *OrderHandler) CancelOrder(c echo.Context) error {
40 if h.flags.IsEnabled(c.Request().Context(), feature.NewCancelOrderFlow) {
41 return h.newCancelOrderFlow(c)
42 }
43 return h.legacyCancelOrderFlow(c)
44}Dengan feature flag, kamu bisa men-deploy kode fitur baru ke production dalam keadaan mati, lalu mengaktifkannya bertahap tanpa deployment ulang — mengurangi risiko dan mempermudah rollback fitur.
13.9 Deployment Checklist Generator
Setiap release punya risiko berbeda tergantung perubahannya, jadi checklist generik sering tidak relevan. Script berikut mengumpulkan commit dan jumlah migration sejak deploy terakhir, lalu meminta AI membuat checklist deployment yang spesifik untuk perubahan itu.
1#!/bin/bash
2# scripts/generate-deployment-checklist.sh
3# AI generate deployment checklist berdasarkan perubahan
4
5set -euo pipefail
6
7VERSION="${1}"
8ENVIRONMENT="${2:-staging}"
9
10LAST_DEPLOY_TAG=$(git tag -l "deploy-${ENVIRONMENT}-*" | sort -V | tail -1)
11COMMITS=$(git log "${LAST_DEPLOY_TAG}..HEAD" --no-merges --pretty=format:"%s" 2>/dev/null | head -20 || \
12 git log --no-merges --pretty=format:"%s" -20)
13
14MIGRATION_COUNT=$(git diff "${LAST_DEPLOY_TAG}..HEAD" --name-only -- 'migrations/**' 2>/dev/null | wc -l || echo "0")
15
16PROMPT="Generate deployment checklist untuk release $VERSION ke $ENVIRONMENT.
17
18Changes (commit messages):
19$COMMITS
20
21Migration count: $MIGRATION_COUNT
22
23Create a concise deployment checklist in Bahasa Indonesia:
241. Pre-deployment steps berdasarkan tipe perubahan
252. Deployment steps
263. Post-deployment verification steps
274. Rollback triggers (apa yang perlu di-monitor)
28
29Be specific berdasarkan changes. Skip generic steps yang tidak relevant."
30
31./scripts/claude-call.sh "$PROMPT" 500Checklist yang di-generate dari diff nyata jauh lebih berguna daripada template statis — ia menyoroti risiko aktual (misalnya ada migration) alih-alih langkah generik yang sering di-skip karena terasa tidak relevan.
13.10 Tips & Gotchas
Sebelum masuk ke topik lanjutan, ada beberapa pelajaran praktis yang layak diingat saat membangun pipeline seperti ini.
Tip 1: Smoke test harus spesifik. Test yang hanya cek /health tidak cukup. Test alur bisnis nyata: bisa create order? bisa list products? Response time acceptable?
Tip 2: Canary dengan persentase kecil dulu. Mulai dengan 10% traffic. Jika 10% healthy selama 5 menit, promote ke 25%, lalu 50%, lalu 100%. Jangan langsung 100%.
Tip 3: Threshold auto-rollback yang realistis. 5% error rate mungkin terlalu rendah untuk canary yang traffic-nya memang sedikit. Kalibrasi threshold berdasarkan baseline error rate di production.
Tip 4: AI health check sebagai suplemen, bukan pengganti. AI bisa miss sesuatu. Pasangkan dengan deterministic metric checks (error rate, latency, CPU).
Gotcha 1: Deploy di peak hours. Notifikasi AI tidak cukup — timing butuh human judgment. Jangan auto-deploy ke production di jam sibuk (12-14 WIB untuk e-commerce).
Gotcha 2: Migration dan rollback. Jika deployment ter-rollback tapi migration sudah jalan, schema data mungkin tidak kompatibel dengan versi lama. Rencanakan ini dengan hati-hati.
Gotcha 3: Smoke test yang flaky. Smoke test yang intermittent fail akan memblokir semua deployment. Perbaiki test yang flaky sebelum menjadikannya deployment gate.
Intinya, tooling secanggih apapun tetap butuh kalibrasi dan penilaian manusia di titik-titik kritis — otomasi memperluas kapasitas, bukan menghapus tanggung jawab.
13.11 GitOps: Environment Configuration as Code
Perbedaan antar environment sebaiknya hidup di git, bukan tersembunyi di dashboard. Contoh values berikut menunjukkan bagaimana konfigurasi staging dan production dipisah sebagai file yang bisa di-review lewat PR.
1# environments/staging/values.yaml
2image: { tag: staging-latest }
3replicas: 2
4env:
5 LOG_LEVEL: debug
6 FEATURE_FLAG_CANCEL_ORDER: "true"
7
8# environments/production/values.yaml
9image: { tag: v1.5.0 } # pinned version
10replicas: 5
11env:
12 LOG_LEVEL: info
13 FEATURE_FLAG_CANCEL_ORDER: "false" # off until fully testedDengan konfigurasi sebagai kode, setiap perubahan environment melewati review PR dan ter-track di git history — audit trail otomatis untuk pertanyaan “kenapa production di-set seperti ini?”.
13.12 Deployment Duration Tracking
Deployment yang makin lama adalah sinyal awal masalah pipeline. Script pendek berikut mengukur durasi deployment, memberi peringatan jika melewati ambang, dan mengirim angkanya sebagai metrics untuk analisis tren.
1#!/bin/bash
2# scripts/track-deployment-duration.sh
3
4START_TIME=$(date +%s)
5
6# ... deployment steps run here ...
7
8END_TIME=$(date +%s)
9DURATION=$((END_TIME - START_TIME))
10echo "Deployment duration: ${DURATION}s"
11
12[ "$DURATION" -gt 300 ] && echo "::warning::Slow deployment (${DURATION}s > 300s)"
13
14curl -sX POST "https://metrics.santekno.com/api/v1/events" \
15 -H "Content-Type: application/json" \
16 -d "{\"event\": \"deployment\", \"env\": \"$1\", \"duration\": $DURATION}" || trueMelacak durasi deployment dari waktu ke waktu membantu mendeteksi degradasi pipeline lebih awal — sebelum “deploy 3 menit” diam-diam berubah jadi “deploy 15 menit”.
13.13 Zero-Downtime Strategy
Deployment aman berarti user tidak pernah melihat error saat pod diganti. Konfigurasi rolling update berikut, dipasangkan dengan graceful shutdown di Go, memastikan tidak ada pod lama yang dimatikan sebelum pod baru siap melayani.
1# Kubernetes rolling update strategy
2strategy:
3 type: RollingUpdate
4 rollingUpdate:
5 maxUnavailable: 0 # zero downtime: no pod removed before new one ready
6 maxSurge: 1 # one extra pod during update
7
8# Coupled dengan graceful shutdown di Go (main.go):
9# signal.Notify(quit, syscall.SIGTERM, syscall.SIGINT)
10# <-quit
11# ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
12# defer cancel()
13# srv.Shutdown(ctx) // wait up to 30s for in-flight requestsKombinasi maxUnavailable: 0 dan graceful shutdown 30 detik ini menjamin request yang sedang berjalan selesai dulu sebelum pod lama dimatikan — dasar dari deployment tanpa downtime.
13.14 Deployment Audit Trail
Untuk kebutuhan audit, setiap deployment production harus meninggalkan jejak. Step berikut mencatat metadata deployment (timestamp, versi, aktor, hasil smoke test, verdict AI) sebagai artifact yang disimpan berbulan-bulan.
1- name: Record deployment
2 run: |
3 cat > /tmp/deploy-record.json << EOF
4 {
5 "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
6 "environment": "production",
7 "version": "${{ github.ref_name }}",
8 "actor": "${{ github.actor }}",
9 "sha": "${{ github.sha }}",
10 "smoke_test": "${{ steps.smoke.outcome }}",
11 "ai_verdict": "${{ steps.ai_health.outputs.verdict }}"
12 }
13 EOF
14
15- uses: actions/upload-artifact@v4
16 with:
17 name: deploy-record-${{ github.sha }}
18 path: /tmp/deploy-record.json
19 retention-days: 90Audit trail seperti ini menjawab pertanyaan penting saat menelusuri incident: “versi apa yang aktif saat itu, siapa yang men-deploy, dan apa verdict health check-nya?”.
13.15 Environment-Specific Config Management
Konfigurasi per environment harus tervalidasi sebelum deploy, bukan setelah service crash. Struktur direktori dan perintah validasi berikut memastikan setiap field wajib terisi dan tidak ada secret kosong sebelum perubahan naik.
1# configs/ diatur per environment dengan secrets terpisah
2configs/
3 base/ # shared config values
4 staging/ # staging-specific overrides
5 production/ # production-specific overrides (secrets via vault)
6
7# Validation: pastikan config valid sebelum deploy
8go run ./cmd/validate-config/main.go --env staging
9go run ./cmd/validate-config/main.go --env production
10# Checks: required fields, type validation, no empty secretsMemvalidasi konfigurasi sebagai langkah pipeline mencegah kelas bug yang paling menyebalkan: service yang deploy sukses tapi langsung crash karena satu secret lupa di-set.
13.16 Ringkasan: Progressive Confidence Building
Multi-environment deployment dengan AI checkpoint pada intinya adalah tentang membangun keyakinan secara bertahap — setiap environment memberikan lebih banyak bukti bahwa perubahan aman untuk dipromosikan.
Elemen kunci:
- Staging sebagai gate wajib sebelum production
- Smoke test untuk verifikasi fungsional
- AI health check untuk analisis semantik dari log dan metrics
- Canary rollout bertahap (10% → 25% → 50% → 100%)
- Auto-rollback berdasarkan threshold metrics
Filosofinya: manusia memutuskan kapan mempromosikan, sistem memonitor dan rollback secara otomatis. Dengan pola ini, deployment berhenti menjadi event menegangkan dan berubah menjadi proses berlapis yang setiap tahapnya bisa dipercaya.