Amankan pipeline release dengan branch protection rules di main dan rc, wajibkan status checks lint build dan dry run, terapkan mandatory reviewers, dan pilih strategi merge yang menjaga riwayat Conventional Commits tetap bersih.

Di episode 12 kita membahas keamanan workflow, dari least privilege hingga proteksi secrets. Kini pertimbangkan sebuah kenyataan: begitu release berjalan otomatis, satu commit buruk di main langsung menjadi versi produksi yang dirilis. Di sinilah branch protection menjadi garda terakhir sebelum kode menyentuh rilis.
Branch protection rules adalah gerbang yang memaksa setiap perubahan melewati PR, status check, dan review sebelum masuk ke branch penting. Untuk pipeline semantic-release, ini bukan sekadar praktik baik — melainkan syarat mutlak agar otomatisasi tidak menjadi bumerang.
Dua branch paling sensitif di repository kita:
main — sumber rilis stable; setiap merge di sini berpotensi menghasilkan versi baru 1.2.3.staging (alias rc) — sumber rilis release candidate 1.2.3-rc.N yang diuji di environment staging.Karena kedua branch ini memicu release otomatis, mereka harus diatur dengan aturan paling ketat. Branch feature/* boleh longgar — cukup pipeline hijau — tetapi main dan rc wajib lulus semua gerbang.
Note
Branch protection rule bekerja berbasis pola nama branch, bukan satu branch. Kalian bisa membuat aturan main, staging, dan feature/* dengan tingkat ketat yang berbeda-beda, dihitung dari yang terpenting ke yang paling longgar.
Langkahnya melalui antarmuka GitHub:
main.staging.Untuk tim yang ingin menerapkan aturan yang sama lintas repository, GitHub juga menyediakan rulesets (Settings → Rules → Rulesets) yang bisa dikelola terpusat dan mendukung konfigurasi berbasis kode.
Status check di GitHub diambil dari nama job di workflow CI yang berjalan pada pull request. Nama inilah yang kalian centang di daftar required status checks:
name: CI
on:
pull_request:
branches: [main, staging]
permissions:
contents: read
jobs:
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
- run: bun install --frozen-lockfile
- run: bun run lint
build:
name: Build
runs-on: ubuntu-latest
needs: lint
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
- run: bun install --frozen-lockfile
- run: bun run build
dry-run:
name: Dry Run
runs-on: ubuntu-latest
needs: build
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
- run: bun install --frozen-lockfile
- run: npx semantic-release --dry-run --no-ciDi form branch protection, centang Lint, Build, dan Dry Run sebagai required checks. Kehadiran check Dry Run sangat penting: ia memvalidasi bahwa commit-commit di PR tersebut akan menghasilkan versi yang benar, changelog yang valid, dan tidak ada error konfigurasi — tanpa benar-benar merilis apa pun. Kalian bisa mencoba perintah yang sama secara lokal dengan npx semantic-release --dry-run --no-ci.
Warning
Nama status check harus persis dengan nama job di workflow. Jika workflow diganti namanya tetapi branch protection masih memakai nama lama, PR akan terkunci permanen sampai kalian memperbarui daftar required checks. Selalu verifikasi setelah mengganti nama job.
Selain pipeline otomatis, review manusia tetap wajib. Atur:
CODEOWNERS, perubahan pada bagian tertentu otomatis menunjuk reviewer.Branch protection juga bisa diterapkan secara reproducible memakai GitHub CLI dengan file JSON sebagai input:
{
"required_status_checks": {
"strict": true,
"contexts": ["Lint", "Build", "Dry Run"]
},
"required_pull_request_reviews": {
"required_approving_review_count": 1
},
"enforce_admins": true
}Pendekatan ini membuat konfigurasi keamanan bisa di-review seperti kode biasa dan dipakai ulang di repository lain.
Cara PR di-merge menentukan bentuk history yang dibaca semantic-release. Tiga opsi utama di tombol merge GitHub:
| Strategi | Bentuk history | Dampak ke semantic-release |
|---|---|---|
| Merge commit | Commit gabungan "Merge pull request #12" ditambah commit asli | Commit merge tak ber-type jadi aman, tapi history jadi berisik |
| Squash and merge | Satu commit baru memakai judul PR | Commit asli dirangkum; versi hanya naik jika pesan squash valid |
| Rebase and merge | Commit asli ditulis ulang tanpa commit gabungan | Menjaga detail per-commit; semua pesan harus mengikuti spec |
Warning
Jika tim memakai squash and merge, pastikan judul PR mengikuti Conventional Commits, misal feat(api): tambah endpoint export. Judul squash itulah satu-satunya commit yang dianalisis commit-analyzer — kalau kalian menulis Update branch sebagai judul, release tidak akan pernah terbit padahal fitur sudah masuk.
Sebaliknya, merge commit menyimpan pesan per-commit asli sehingga analisis lebih akurat, tetapi ada risikonya: jika komitmen di dalamnya tidak konsisten, versi bisa naik lebih dari sekali untuk satu PR. Banyak tim mengkombinasikan squash-merge dengan aturan "judul PR harus valid" untuk mendapatkan history yang bersih sekaligus analisis yang bisa diprediksi.
Untuk memaksa kebijakan ini di tingkat repository, atur Settings → Allow merge commits / Allow squash merging / Allow rebase merging dan matikan opsi yang tidak diinginkan.
Rekap episode 13:
main dan staging (rc) dengan branch protection rule yang ketat.Dengan gerbang yang kuat, rilis yang keluar sudah teruji dua lapis: otomatis dan manusia. Episode berikutnya kita membahas Audit, Changelog & Release Notes — bagaimana semantic-release menulis changelog otomatis dan menghubungkannya ke GitHub Releases. Sampai jumpa!