AI di CI/CD Pipeline Go: Quality Gates, Auto Review, Architecture Check
Integrasikan AI tools ke CI/CD pipeline Golang. Pre-commit AI review, GitHub Actions quality gates, architecture enforcement, AI-generated PR descriptions untuk Go.
AI Tools di CI/CD Pipeline Golang
Mengintegrasikan AI tools ke CI/CD pipeline Golang membuka kelas quality gate yang tidak bisa dicapai static analysis biasa. AI tools tidak hanya berguna saat developer coding — tapi juga di pipeline untuk pemeriksaan yang lebih cerdas. Artikel ini menunjukkan cara integrasi AI yang practical dan cost-effective ke pipeline Go, dari pre-commit hook sampai release notes.
18.1 CI/CD Stages yang Benefit dari AI
Tidak semua tahap pipeline butuh AI. Peta berikut menandai lima stage yang paling jelas mendapat nilai dari AI beserta perkiraan biayanya.
1Pipeline stages dimana AI memberikan nilai clear:
2
3Stage 1: Pre-commit (local, sebelum push)
4 - Quick AI review via cheap model (haiku)
5 - Architecture violation check
6 - Secret detection
7 Cost: < $0.001 per commit
8
9Stage 2: Pull Request (GitHub Actions)
10 - Copilot automated PR review (built-in jika punya Copilot)
11 - Spec compliance audit
12 - AI-generated PR description
13 Cost: $0.001-0.01 per PR
14
15Stage 3: Build & Test
16 - Test failure AI analysis (only if failure)
17 - Coverage gap identification
18 Cost: $0 jika pass, minimal jika fail
19
20Stage 4: Code Quality Gates
21 - Architecture enforcement (Go script, no AI cost)
22 - Complexity analysis
23 Cost: $0 (static analysis)
24
25Stage 5: Post-merge / Deployment
26 - AI-generated release notes
27 - Deployment notes generator
28 Cost: < $0.01 per deploymentPeta ini menegaskan prinsip biaya: AI dipakai hanya di titik yang menambah judgment (review, analisis failure), sementara enforcement mekanis tetap ditangani static analysis yang gratis.
18.2 Pre-commit Hook dengan AI Review
Titik intervensi termurah adalah sebelum kode bahkan di-push. Hook berikut menjalankan review cepat dengan model haiku terhadap diff yang di-stage dan memblokir commit jika ada isu CRITICAL.
1#!/bin/bash
2# .git/hooks/pre-commit
3# Quick AI review sebelum commit
4
5set -e
6
7# Only check Go files
8CHANGED_GO=$(git diff --cached --name-only --diff-filter=ACM | grep '\.go$' || true)
9
10if [ -z "$CHANGED_GO" ]; then
11 exit 0 # No Go changes, skip
12fi
13
14echo "Running pre-commit AI review..."
15
16# Collect diff dari semua changed files
17DIFF=$(echo "$CHANGED_GO" | while read -r file; do
18 git diff --cached "$file"
19done)
20
21if [ -z "$DIFF" ]; then
22 exit 0
23fi
24
25# Call Claude API (haiku = cheap dan fast)
26REVIEW=$(curl -sf -X POST https://api.anthropic.com/v1/messages \
27 -H "x-api-key: ${ANTHROPIC_API_KEY}" \
28 -H "anthropic-version: 2023-06-01" \
29 -H "content-type: application/json" \
30 -d "$(jq -n \
31 --arg diff "$DIFF" \
32 '{
33 model: "claude-haiku-4-5-20251001",
34 max_tokens: 300,
35 messages: [{
36 role: "user",
37 content: ("Go code quick review. ONLY flag CRITICAL:\n1. Error not wrapped (return err without fmt.Errorf)\n2. float64 for money (must int64)\n3. _ ignoring errors\n4. Architecture violation (handler import repo impl)\nDiff:\n" + $diff + "\nOutput: CRITICAL:[file:line issue] or OK")
38 }]
39 }'
40 )" | jq -r '.content[0].text' 2>/dev/null || echo "OK")
41
42if echo "$REVIEW" | grep -q "^CRITICAL:"; then
43 echo ""
44 echo "AI Pre-commit Review — CRITICAL ISSUES FOUND:"
45 echo "$REVIEW"
46 echo ""
47 echo "Fix issues above before committing."
48 echo "Skip (not recommended): git commit --no-verify"
49 exit 1
50fi
51
52echo "AI Pre-commit: OK"
53exit 0Hook ini memberi feedback ke developer sebelum push, saat memperbaiki masih paling murah — hanya isu CRITICAL yang diblokir agar tidak mengganggu alur kerja harian. Untuk memasangnya secara rapi, gunakan pre-commit framework seperti berikut.
1# Install hook:
2chmod +x .git/hooks/pre-commit
3
4# Alternative: pakai pre-commit framework
5# .pre-commit-config.yaml
6repos:
7 - repo: local
8 hooks:
9 - id: ai-review
10 name: AI Quick Review
11 entry: .git/hooks/pre-commit
12 language: script
13 types: [go]Dengan mendaftarkan hook di .pre-commit-config.yaml, seluruh tim mendapat gate yang sama secara konsisten alih-alih mengandalkan setiap developer memasang hook manual.
18.3 GitHub Actions Workflow Lengkap
Setelah pre-commit, lapisan berikutnya adalah pipeline GitHub Actions. Workflow berikut menyusun lima job — dari build/test standar sampai review AI dan analisis failure — dengan AI hanya dipakai di tempat yang tepat.
1# .github/workflows/ci.yml
2
3name: CI Pipeline with AI Quality Gates
4
5on:
6 push:
7 branches: [main, develop]
8 pull_request:
9 branches: [main, develop]
10 types: [opened, synchronize, ready_for_review]
11
12env:
13 GO_VERSION: '1.22'
14
15jobs:
16 # Job 1: Standard Go (always run, no AI, fast)
17 go-build-test:
18 name: Build & Test
19 runs-on: ubuntu-latest
20 steps:
21 - uses: actions/checkout@v4
22 - uses: actions/setup-go@v5
23 with:
24 go-version: ${{ env.GO_VERSION }}
25 cache: true
26
27 - name: Build
28 run: go build ./...
29
30 - name: Test with Race
31 run: go test -race -count=1 -timeout=5m ./...
32
33 - name: Coverage Gate
34 run: |
35 go test -coverprofile=coverage.out ./...
36 COVERAGE=$(go tool cover -func=coverage.out | \
37 grep "total:" | awk '{print $3}' | tr -d '%')
38 echo "Test coverage: ${COVERAGE}%"
39 if awk "BEGIN {exit ($COVERAGE >= 70) ? 0 : 1}"; then
40 echo "Coverage ${COVERAGE}% >= 70%"
41 else
42 echo "Coverage ${COVERAGE}% < 70% threshold"
43 exit 1
44 fi
45
46 - name: Vet
47 run: go vet ./...
48
49 - name: golangci-lint
50 uses: golangci/golangci-lint-action@v6
51 with:
52 version: latest
53
54 # Job 2: Architecture Enforcement (no AI, custom Go script)
55 architecture-check:
56 name: Architecture Boundary Check
57 runs-on: ubuntu-latest
58 steps:
59 - uses: actions/checkout@v4
60 - uses: actions/setup-go@v5
61 with:
62 go-version: ${{ env.GO_VERSION }}
63
64 - name: Check layer boundaries
65 run: go run ./scripts/check-architecture.go ./...
66
67 # Job 3: AI PR Review (only for non-draft PRs)
68 ai-pr-review:
69 name: Copilot PR Review
70 runs-on: ubuntu-latest
71 if: |
72 github.event_name == 'pull_request' &&
73 !github.event.pull_request.draft
74 permissions:
75 pull-requests: write
76 contents: read
77 steps:
78 - uses: actions/checkout@v4
79 with:
80 fetch-depth: 0
81 - uses: github/copilot-for-pull-requests@v1
82 with:
83 github-token: ${{ secrets.GITHUB_TOKEN }}
84 review-instructions: |
85 Review Go code. Flag as CRITICAL:
86 - Error not wrapped: return err (must fmt.Errorf)
87 - Repository returns error for not-found (must nil, nil)
88 - float64 for monetary values
89 - Architecture violations (wrong layer imports)
90 - Errors ignored with _
91 End with REVIEW_SCORE: X/100
92
93 # Job 4: AI-generated PR description (only for new PRs)
94 generate-pr-description:
95 name: Generate PR Description
96 runs-on: ubuntu-latest
97 if: github.event.action == 'opened'
98 permissions:
99 pull-requests: write
100 contents: read
101 env:
102 ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
103 steps:
104 - uses: actions/checkout@v4
105 with:
106 fetch-depth: 0
107 - uses: actions/setup-node@v4
108 with:
109 node-version: '20'
110 - name: Generate and update PR description
111 uses: actions/github-script@v7
112 with:
113 script: |
114 const { execSync } = require('child_process');
115 const diff = execSync(
116 'git diff origin/main...HEAD -- "*.go" 2>/dev/null | head -300',
117 { encoding: 'utf-8' }
118 );
119
120 if (!diff.trim()) {
121 console.log('No Go changes detected');
122 return;
123 }
124
125 const res = await fetch('https://api.anthropic.com/v1/messages', {
126 method: 'POST',
127 headers: {
128 'x-api-key': process.env.ANTHROPIC_API_KEY,
129 'anthropic-version': '2023-06-01',
130 'content-type': 'application/json',
131 },
132 body: JSON.stringify({
133 model: 'claude-haiku-4-5-20251001',
134 max_tokens: 600,
135 messages: [{
136 role: 'user',
137 content: `Generate PR description from this Go diff.
138Format:
139## Summary
140[one paragraph what this PR does]
141
142## Changes
143- [bullet list of key changes]
144
145## Testing
146- [ ] go test -race ./...
147
148Diff:
149${diff}`
150 }]
151 })
152 });
153
154 const data = await res.json();
155 const body = data.content?.[0]?.text || '';
156
157 await github.rest.pulls.update({
158 owner: context.repo.owner,
159 repo: context.repo.repo,
160 pull_number: context.issue.number,
161 body
162 });
163
164 # Job 5: Test failure analysis (only on failure)
165 analyze-test-failure:
166 name: Analyze Test Failure
167 runs-on: ubuntu-latest
168 needs: go-build-test
169 if: failure() && github.event_name == 'pull_request'
170 permissions:
171 pull-requests: write
172 env:
173 ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
174 steps:
175 - uses: actions/checkout@v4
176 - uses: actions/setup-go@v5
177 with:
178 go-version: ${{ env.GO_VERSION }}
179
180 - name: Capture test output
181 run: |
182 go test ./... 2>&1 | head -100 > /tmp/test-output.txt || true
183
184 - name: AI analysis of failure
185 run: |
186 OUTPUT=$(cat /tmp/test-output.txt)
187 ANALYSIS=$(curl -sf -X POST https://api.anthropic.com/v1/messages \
188 -H "x-api-key: ${ANTHROPIC_API_KEY}" \
189 -H "anthropic-version: 2023-06-01" \
190 -H "content-type: application/json" \
191 -d "$(jq -n --arg out "$OUTPUT" '{
192 model: "claude-haiku-4-5-20251001",
193 max_tokens: 300,
194 messages: [{
195 role: "user",
196 content: ("Analyze this Go test failure briefly. Root cause and fix suggestion:\n" + $out)
197 }]
198 }')" | jq -r '.content[0].text' || echo "Analysis failed")
199
200 gh pr comment ${{ github.event.number }} \
201 --body "## AI Test Failure Analysis\n\n${ANALYSIS}"
202 env:
203 GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}Desain pipeline ini penting: job build/test/architecture berjalan tanpa AI dan tetap cepat, sementara job AI (review, PR description, analisis failure) dikondisikan hanya jalan saat relevan — sehingga biaya dan waktu tetap terjaga.
18.4 Architecture Enforcement Script
Job architecture-check tadi memanggil skrip Go tanpa AI. Skrip berikut mem-parse import tiap file dan menggagalkan build bila ada layer yang melanggar aturan Clean Architecture.
1// scripts/check-architecture.go
2// Enforce Clean Architecture layer boundaries
3
4//go:build ignore
5
6package main
7
8import (
9 "fmt"
10 "go/parser"
11 "go/token"
12 "os"
13 "path/filepath"
14 "strings"
15)
16
17// forbiddenImports: layer prefix -> list of forbidden import substrings
18var forbiddenImports = map[string][]string{
19 "internal/delivery": {
20 "internal/repository", // handler must NOT import repo impl
21 "internal/usecase/", // handler imports usecase INTERFACE, not pkg directly
22 },
23 "internal/usecase": {
24 "internal/delivery", // usecase must NOT import handler
25 "github.com/jackc/pgx", // usecase must NOT import DB driver
26 "github.com/redis/go-redis", // usecase must NOT import Redis
27 "github.com/labstack/echo", // usecase must NOT import HTTP framework
28 },
29 "internal/domain": {
30 "github.com/jackc/pgx",
31 "github.com/redis/go-redis",
32 "github.com/labstack/echo",
33 "github.com/confluentinc/confluent-kafka-go",
34 },
35}
36
37func main() {
38 violations := 0
39 fset := token.NewFileSet()
40
41 err := filepath.Walk(".", func(path string, info os.FileInfo, err error) error {
42 if err != nil || info.IsDir() {
43 return err
44 }
45 if !strings.HasSuffix(path, ".go") {
46 return nil
47 }
48 if strings.HasSuffix(path, "_test.go") {
49 return nil // skip tests
50 }
51
52 // Determine which layer this file is in
53 var currentLayer string
54 for layer := range forbiddenImports {
55 if strings.Contains(path, layer) {
56 currentLayer = layer
57 break
58 }
59 }
60 if currentLayer == "" {
61 return nil
62 }
63
64 f, err := parser.ParseFile(fset, path, nil, parser.ImportsOnly)
65 if err != nil {
66 return nil
67 }
68
69 for _, imp := range f.Imports {
70 impPath := strings.Trim(imp.Path.Value, `"`)
71 for _, forbidden := range forbiddenImports[currentLayer] {
72 if strings.Contains(impPath, forbidden) {
73 fmt.Printf("VIOLATION [%s]: %s\n imports: %s\n\n",
74 currentLayer, path, impPath)
75 violations++
76 }
77 }
78 }
79 return nil
80 })
81
82 if err != nil {
83 fmt.Fprintf(os.Stderr, "walk error: %v\n", err)
84 os.Exit(2)
85 }
86
87 if violations > 0 {
88 fmt.Printf("Total: %d architecture violations\n", violations)
89 os.Exit(1)
90 }
91
92 fmt.Println("Architecture check: PASSED")
93}Skrip ini adalah gate paling bernilai per rupiah: nol biaya AI, deterministik, dan menangkap pelanggaran arsitektur — jenis bug yang paling mahal jika lolos ke production. Jalankan tanpa syarat di setiap PR.
18.5 AI-Generated Release Notes
AI juga berguna di tahap pasca-merge, misalnya menyusun changelog. Program Go berikut mengumpulkan commit sejak tag terakhir dan meminta model haiku merangkumnya menjadi release notes yang rapi.
1// cmd/release-notes/main.go
2// Jalankan sebelum setiap release untuk generate changelog
3
4package main
5
6import (
7 "context"
8 "fmt"
9 "os"
10 "os/exec"
11 "strings"
12
13 anthropic "github.com/anthropics/anthropic-sdk-go"
14)
15
16func main() {
17 // Get commit log dari last tag
18 lastTag, _ := exec.Command("git", "describe", "--tags", "--abbrev=0").Output()
19 tag := strings.TrimSpace(string(lastTag))
20
21 commits, err := exec.Command(
22 "git", "log", "--oneline", "--no-merges",
23 fmt.Sprintf("%s..HEAD", tag),
24 ).Output()
25 if err != nil {
26 fmt.Fprintln(os.Stderr, "No previous tag found, using all commits")
27 commits, _ = exec.Command("git", "log", "--oneline", "--no-merges", "-50").Output()
28 }
29
30 if len(commits) == 0 {
31 fmt.Println("No commits found")
32 return
33 }
34
35 client := anthropic.NewClient()
36
37 msg, err := client.Messages.New(context.Background(), anthropic.MessageNewParams{
38 Model: anthropic.F(anthropic.ModelClaudeHaiku4_5),
39 MaxTokens: anthropic.F(int64(800)),
40 Messages: anthropic.F([]anthropic.MessageParam{
41 anthropic.NewUserMessage(anthropic.NewTextBlock(fmt.Sprintf(`
42Generate release notes dari commit messages berikut untuk Go service.
43Format markdown yang clean:
44
45## What's New
46[new features]
47
48## Bug Fixes
49[bug fixes]
50
51## Internal Changes
52[refactoring, dependencies, etc.]
53
54Commits (from %s to HEAD):
55%s`, tag, string(commits)))),
56 }),
57 })
58 if err != nil {
59 fmt.Fprintf(os.Stderr, "Claude error: %v\n", err)
60 os.Exit(1)
61 }
62
63 fmt.Println(msg.Content[0].Text)
64}Program ini mengubah tugas menulis changelog yang membosankan menjadi satu perintah — commit yang tidak deskriptif pun tetap terangkum rapi karena AI mengelompokkannya per kategori.
18.6 Cost Estimation untuk AI di CI/CD
Ketakutan terbesar mengadopsi AI di CI biasanya soal biaya. Rincian berikut menghitung estimasi bulanan nyata untuk tim 5 developer dan menunjukkan bahwa API call bukan cost utama.
1Estimasi biaya bulanan untuk tim 5 developer, 3 PR/dev/week:
2
3Pre-commit hook (haiku):
4 Commits per month: 5 dev × 20 commits = 100
5 Input: ~500 tokens, output: ~100 tokens
6 Cost per commit: $0.0001
7 Monthly: 100 × $0.0001 = $0.01
8
9PR description generation (haiku):
10 PRs per month: 5 × 3 × 4 weeks = 60 PRs
11 Input: ~1000 tokens, output: ~400 tokens
12 Cost per PR: $0.0002
13 Monthly: 60 × $0.0002 = $0.012
14
15Test failure analysis (haiku):
16 Failures per month: ~10 (assuming 83% PR pass rate)
17 Input: ~500 tokens, output: ~300 tokens
18 Cost per failure: $0.0001
19 Monthly: 10 × $0.0001 = $0.001
20
21Release notes (haiku):
22 Releases per month: 4
23 Cost: 4 × $0.001 = $0.004
24
25Total AI API cost: ~$0.03/bulan
26GitHub Copilot Business (PR review): $19 × 5 = $95/bulan
27
28Copilot adalah cost utama, bukan API calls.
29API calls untuk automation: sangat affordable.Kesimpulan angka ini melegakan: automasi berbasis haiku hanya menelan sekitar $0.03/bulan — biaya sebenarnya ada di langganan Copilot, bukan pada API call yang kamu tambahkan sendiri.
18.7 Security: Redact Secrets Sebelum AI Review
Mengirim diff ke API AI berisiko membocorkan secret. Skrip berikut menyaring pola secret umum dari diff sebelum dikirim ke model.
1#!/bin/bash
2# scripts/redact-diff.sh
3# Redact potential secrets dari diff sebelum kirim ke AI
4
5DIFF="$1"
6
7# Common secret patterns
8echo "$DIFF" | \
9 sed 's/sk-ant-[a-zA-Z0-9_-]*/sk-ant-REDACTED/g' | \
10 sed 's/ghp_[a-zA-Z0-9]*/ghp_REDACTED/g' | \
11 sed 's/AKIA[A-Z0-9]*/AKIAXXXXXXXXXXXXXXXX/g' | \
12 sed 's/password=[^\s]*/password=REDACTED/g' | \
13 sed 's/secret=[^\s]*/secret=REDACTED/g' | \
14 sed 's/DATABASE_URL=postgres:\/\/[^\s]*/DATABASE_URL=postgres:\/\/REDACTED/g'Redaksi ini adalah lapisan pertahanan penting: meski provider AI punya kebijakan retensi, mencegah secret keluar dari mesin kamu sejak awal jauh lebih aman. Cara memakainya di dalam pipeline seperti berikut.
1# Gunakan dalam GitHub Actions:
2- name: Redact secrets from diff
3 run: |
4 git diff origin/main...HEAD -- '*.go' | \
5 bash scripts/redact-diff.sh > /tmp/safe-diff.txt
6
7- name: AI Review on safe diff
8 run: |
9 # Use /tmp/safe-diff.txt instead of raw diff
10 # ... call AI API dengan safe-diff.txtDengan menempatkan langkah redaksi sebelum setiap call AI, kamu memastikan yang dikirim ke API selalu versi yang sudah dibersihkan — bukan diff mentah yang mungkin memuat kredensial.
18.8 Monitoring AI Usage di CI
Biaya AI perlu dipantau agar tidak diam-diam membengkak. Langkah berikut mencatat metrik penggunaan AI ke GitHub Step Summary untuk kontrol biaya.
1# Track AI spending di CI untuk cost control
2- name: Track AI Usage
3 if: always()
4 run: |
5 # Log basic metrics ke GitHub Step Summary
6 cat >> $GITHUB_STEP_SUMMARY << EOF
7 ## AI Usage This Run
8 - Model: claude-haiku-4-5-20251001
9 - Task: PR description generation
10 - Estimated cost: <$0.001
11 EOF
12
13# Monthly cost report via scheduled job:
14- name: Monthly AI Cost Report
15 if: github.event_name == 'schedule'
16 run: |
17 # Aggregate dari billing API atau manual tracking
18 echo "Review AI tool costs at: anthropic.com/account/usage"Mencatat estimasi biaya per run langsung di ringkasan workflow membuat pengeluaran AI transparan bagi seluruh tim — kejutan tagihan di akhir bulan bisa dihindari.
18.9 Graduated AI Enforcement
Memaksakan gate AI penuh sejak hari pertama sering memicu resistensi. Strategi enforcement bertahap berikut memperkenalkan aturan secara gradual dari sekadar warning hingga score gate penuh.
1Pipeline enforcement strategy yang lebih gentle untuk adoption:
2
3PHASE 1 (Month 1): Warning only
4 - AI review runs tapi TIDAK block merge
5 - Developer lihat output tapi tidak forced to fix
6 - Collect baseline: berapa issues per PR?
7
8PHASE 2 (Month 2): Enforce CRITICAL only
9 - CRITICAL issues block merge
10 - SUGGESTION tetap warning
11 - Target: zero CRITICAL in merge
12
13PHASE 3 (Month 3+): Full enforcement
14 - CRITICAL block merge
15 - SUGGESTION block merge jika > 5 per PR
16 - Score gate: AI review score < 80 = block
17
18Config untuk graduated enforcement:
19 .github/ai-enforcement.yml:
20 phase: 2
21 block_on_critical: true
22 block_on_suggestions: false
23 minimum_score: 0 # not enforced yetPendekatan bertahap ini menjaga adopsi tetap manusiawi: tim punya waktu menyesuaikan diri dan membangun kepercayaan pada AI review sebelum gate mulai benar-benar memblokir merge.
18.10 Tips & Gotchas
Beberapa pelajaran praktis berikut merangkum apa yang biasanya menentukan sukses-tidaknya integrasi AI di CI/CD.
💡 Tip 1: Mulai dengan pre-commit hook saja — zero GitHub Actions setup, immediate value, dan developer mendapat feedback sebelum even push.
💡 Tip 2: Haiku model untuk CI tasks — 10× lebih murah dari Sonnet, cukup untuk mechanical review di CI. Reserve Sonnet untuk complex reasoning di developer sessions.
💡 Tip 3: Cache AI results berdasarkan commit hash — jika PR tidak ada new commits sejak last review, skip AI call untuk hemat cost.
💡 Tip 4: Architecture check script (18.4) TIDAK butuh AI — pure static analysis. Jalankan ini sebelum AI steps untuk quick catch without cost.
⚠️ Gotcha 1: ANTHROPIC_API_KEY di GitHub Secrets harus di-rotate minimal setiap 6 bulan. Setup key dengan permissions minimal.
⚠️ Gotcha 2: AI calls menambah CI time. Design sebagai parallel jobs, bukan sequential. PR description dan architecture check bisa parallel.
⚠️ Gotcha 3: Jangan kirim entire codebase ke AI di CI. Hanya diff yang relevant. Kirim lebih banyak = lebih mahal + slower + mungkin expose unneeded code.
Benang merahnya jelas: pakai model murah untuk tugas mekanis, jalankan job AI secara paralel, dan batasi input hanya ke diff yang relevan — tiga kebiasaan yang menjaga pipeline tetap cepat dan hemat.
18.11 Integration dengan Existing Go Quality Tools
AI bukan pengganti tool kualitas Go yang sudah ada, melainkan lapisan tambahan. Workflow berikut menyusun semua lapisan — build, test, vet, lint, architecture, lalu AI — dalam urutan yang logis.
1# Full pipeline yang combine semua tools:
2
3name: Complete Quality Pipeline
4
5on: [pull_request]
6
7jobs:
8 quality:
9 runs-on: ubuntu-latest
10 steps:
11 # Layer 1: Standard Go (fastest, no cost)
12 - name: Build
13 run: go build ./...
14
15 - name: Test
16 run: go test -race ./...
17
18 - name: Vet
19 run: go vet ./...
20
21 # Layer 2: golangci-lint (no AI, great coverage)
22 - uses: golangci/golangci-lint-action@v6
23
24 # Layer 3: Architecture check (no AI, custom rules)
25 - name: Architecture
26 run: go run ./scripts/check-architecture.go ./...
27
28 # Layer 4: AI review (adds judgment, has cost)
29 - name: AI Review
30 if: '!github.event.pull_request.draft'
31 uses: github/copilot-for-pull-requests@v1
32 with:
33 github-token: ${{ secrets.GITHUB_TOKEN }}
34
35# Each layer catches different issues:
36# Build: compilation errors
37# Test: runtime behavior
38# Vet: suspicious constructs
39# golangci-lint: style + common mistakes
40# Architecture: layer boundary violations
41# AI: semantic issues, missing error handling, Go idiomUrutan berlapis ini efisien secara biaya: lapisan gratis dan cepat (build, test, lint, architecture) menyaring mayoritas masalah lebih dulu, sehingga AI hanya mengevaluasi kode yang sudah lolos gate murah.
18.12 Workflow untuk Database Migration Review
Migration SQL adalah area berisiko tinggi yang cocok untuk review AI khusus. Skrip berikut meminta AI menandai migration berbahaya (DROP, TRUNCATE, ALTER berat) sebelum di-apply.
1#!/bin/bash
2# scripts/review-migration.sh
3# AI review untuk SQL migration files
4
5MIGRATION_FILE="$1"
6
7if [ -z "$MIGRATION_FILE" ]; then
8 echo "Usage: review-migration.sh <migration-file>"
9 exit 1
10fi
11
12SQL=$(cat "$MIGRATION_FILE")
13
14REVIEW=$(curl -sf -X POST https://api.anthropic.com/v1/messages \
15 -H "x-api-key: ${ANTHROPIC_API_KEY}" \
16 -H "anthropic-version: 2023-06-01" \
17 -H "content-type: application/json" \
18 -d "$(jq -n \
19 --arg sql "$SQL" \
20 '{
21 model: "claude-haiku-4-5-20251001",
22 max_tokens: 400,
23 messages: [{
24 role: "user",
25 content: ("Review SQL migration. Flag:\nBLOCKING: DROP without backup, TRUNCATE, lock-heavy ALTER on large table\nWARNING: Missing index for FK, NOT NULL without default on existing table\nOK: safe migration\n\nMigration:\n" + $sql)
26 }]
27 }'
28 )" | jq -r '.content[0].text')
29
30echo "$REVIEW"
31
32# Block jika ada BLOCKING issues
33if echo "$REVIEW" | grep -q "^BLOCKING:"; then
34 exit 1
35fiReview migration adalah salah satu ROI tertinggi AI di CI: satu migration yang mengunci tabel besar bisa menyebabkan downtime produksi, dan gate ini menangkapnya sebelum merge.
18.13 Slack/Discord Notification dengan AI Summary
Setelah deployment, tim biasanya ingin ringkasan singkat yang mudah dibaca. Langkah berikut meminta AI meringkas commit menjadi 2-3 kalimat dan mengirimnya ke Slack.
1# Kirim AI summary ke Slack setelah deployment
2
3- name: Generate Deployment Summary
4 if: github.ref == 'refs/heads/main' && success()
5 env:
6 ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
7 SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
8 run: |
9 COMMITS=$(git log --oneline --no-merges -10)
10
11 SUMMARY=$(curl -sf -X POST https://api.anthropic.com/v1/messages \
12 -H "x-api-key: ${ANTHROPIC_API_KEY}" \
13 -H "anthropic-version: 2023-06-01" \
14 -H "content-type: application/json" \
15 -d "$(jq -n --arg c "$COMMITS" '{
16 model: "claude-haiku-4-5-20251001",
17 max_tokens: 200,
18 messages: [{
19 role: "user",
20 content: ("Summarize these commits into 2-3 sentences for a Slack deployment notification. Be concise and informative:\n" + $c)
21 }]
22 }')" | jq -r '.content[0].text')
23
24 # Send to Slack
25 curl -X POST "$SLACK_WEBHOOK" \
26 -H "Content-Type: application/json" \
27 -d "$(jq -n \
28 --arg summary "$SUMMARY" \
29 --arg sha "${{ github.sha }}" \
30 '{
31 text: ("*Deployed to Production* :rocket:\n" + $summary + "\nCommit: " + $sha[:8])
32 }'
33 )"Notifikasi seperti ini mengubah daftar commit yang kering menjadi ringkasan yang bisa dipahami non-engineer sekalipun — meningkatkan visibilitas deployment tanpa usaha manual.
18.14 Metrics Tracking untuk AI CI Pipeline
Agar bisa mengevaluasi efektivitas AI review, hasilnya perlu direkam sebagai metrik. Langkah berikut menyimpan skor review dan status critical ke artifact untuk analisis tren bulanan.
1# Track effectiveness AI di CI dengan metrics sederhana
2
3# Di GitHub Actions, simpan ke GitHub Variables:
4- name: Track AI Review Effectiveness
5 uses: actions/github-script@v7
6 with:
7 script: |
8 // Get AI review result dari previous step
9 const aiScore = parseInt(process.env.AI_SCORE || '0');
10 const hasCritical = process.env.HAS_CRITICAL === 'true';
11
12 // Log ke PR comment untuk tracking
13 const body = [
14 `## AI Quality Metrics`,
15 `- Score: ${aiScore}/100`,
16 `- Critical issues: ${hasCritical ? 'YES' : 'None'}`,
17 `- Timestamp: ${new Date().toISOString()}`,
18 ].join('\n');
19
20 // Store as workflow artifact for monthly analysis
21 require('fs').writeFileSync(
22 `ai-metrics-${context.payload.number}.json`,
23 JSON.stringify({ pr: context.payload.number, score: aiScore, hasCritical, timestamp: new Date() })
24 );
25
26# Monthly: aggregate metrics JSON files untuk trend analysis
27# "Average AI review score trending up = context files improving"Metrik ini menutup loop feedback: skor review yang naik dari bulan ke bulan adalah bukti kuantitatif bahwa context files dan kualitas kode tim sedang membaik.
18.15 Troubleshooting Common CI/AI Issues
Integrasi AI di CI punya masalah khasnya sendiri. Panduan berikut memetakan masalah yang paling sering muncul beserta solusi praktisnya.
1Problem: Pre-commit hook terlalu lambat (> 30 detik)
2Solution:
3 1. Gunakan haiku (bukan sonnet) — 3× lebih cepat
4 2. Limit diff size: head -200 sebelum kirim ke AI
5 3. Only check CRITICAL rules (3-4 rules, bukan 10+)
6 4. Cache hasil: jika file tidak berubah, skip
7
8Problem: AI review score bervariasi untuk kode yang sama
9Solution:
10 1. Structured prompt dengan exact rules
11 2. Request format yang specific ("CRITICAL: atau OK only")
12 3. Gunakan temperature=0 jika API mendukung
13
14Problem: False positives yang annoying
15Solution:
16 1. Tambahkan exception rules ke prompt
17 "Exception: test files boleh use _ for errors"
18 "Exception: main.go boleh pakai log.Fatal"
19 2. Update CLAUDE.md untuk explicit exceptions
20 3. Track false positive jenis apa, update rules
21
22Problem: AI review tidak catch issues yang lolos
23Solution:
24 1. Add rule yang specific untuk issue tersebut
25 2. Include code example di review prompt
26 3. Test prompt dengan code yang explicitly violate rulePola solusinya konsisten: prompt yang terstruktur dan spesifik, input yang dibatasi, plus daftar exception yang terus diperbarui — kombinasi yang membuat AI review stabil dan tepercaya.
18.16 Ringkasan
AI di CI/CD adalah layer terakhir dari quality gate stack. Bukan pengganti test atau lint — tapi tambahan yang menangkap pattern yang static analysis tidak bisa.
Recommended setup per phase:
- Week 1: Pre-commit hook (local, cheap, immediate)
- Week 2: Copilot PR review (jika sudah punya Copilot)
- Week 3: Architecture check script (zero AI cost)
- Month 2: Test failure analysis, PR description generation
Total setup untuk semua ini 1-2 hari, dengan ongoing cost < $1/bulan untuk API call — nilai yang dihasilkan berupa review cycle yang lebih cepat dan reviewer manusia yang bisa fokus ke logic, bukan isu mekanis. Digabung dengan context files dan multi-tool workflow dari artikel sebelumnya, ini melengkapi ekosistem AI-driven Go development. Langkah berikutnya adalah memastikan semua otomasi ini aman: security dan privacy AI coding tools.