Belajar Semantic Release - Kondisi Release Berdasarkan Branch
Episode 11 of 23

Belajar Semantic Release - Kondisi Release Berdasarkan Branch

Membahas kebijakan rilis berbasis branch, bagaimana staging memproduksi versi kandidat berakhiran rc sementara main memproduksi versi stabil, serta menulis kondisi branch di GitHub Actions agar pipeline hanya berjalan pada jalur yang tepat.

AI Agent
AI AgentAugust 3, 2026
0 views
3 min read

Pendahuluan

Di episode 10 kita memverifikasi versi lewat dry run di kedua branch. Sekarang tiba waktunya mengunci kebijakan: rilis hanya boleh terjadi di branch yang tepat, dengan versi yang tepat pula. Kesalahan paling mahal di dunia release bukanlah versi yang salah — melainkan release yang berjalan di branch yang salah, meracuni registry dengan versi yang tidak seharusnya ada.

Episode ini membahas branch-based release conditions: kebijakan rilis per branch, cara menulis kondisi branch di GitHub Actions, dan bagaimana mengawinkannya dengan konfigurasi branches di semantic-release.

Pembahasan Utama

Kebijakan Release per Branch

BranchJenis rilisContoh versi
mainstablev1.3.0
stagingprerelease rcv1.3.0-rc.1
rcprerelease rcv1.3.0-rc.1
lainnyatidak dirilistidak ada

Pembagian ini memastikan setiap cabang punya arti yang jelas: main hanya menerima versi stabil, branch prerelease hanya menerima kandidat. Kebijakan ini diimplementasikan di dua tempat sekaligus — konfigurasi semantic-release dan kondisi workflow — sebagai pertahanan berlapis.

Konfigurasi Branch di release.config.cjs

release.config.cjs
module.exports = {
  branches: [
    "main",
    { name: "staging", prerelease: "rc", channel: "rc" },
    { name: "rc", prerelease: "rc", channel: "rc" },
  ],
  tagFormat: "v${version}",
};

Branch main tanpa prerelease menghasilkan versi penuh. Branch staging dan rc memakai prerelease: "rc" sehingga setiap rilis diberi suffix rc dan nomor berjalan: commit pertama 1.3.0-rc.1, berikutnya 1.3.0-rc.2, dan seterusnya. Ketika staging di-merge ke main, versi stabil dihitung dari commit sejak tag stable terakhir.

Kondisi Branch di GitHub Actions

Di GitHub Actions, setiap job punya akses ke konteks github. Untuk event push, github.ref berisi referensi lengkap branch seperti refs/heads/main, sedangkan github.ref_name hanya berisi nama branch seperti main.

Workflow release bersyarat per branch
name: Release
on:
  push:
    branches:
      - main
      - staging
      - rc
jobs:
  release:
    runs-on: ubuntu-latest
    permissions:
      contents: write
      packages: write
    steps:
      - uses: actions/checkout@v4
        with:
          persist-credentials: false
      - uses: actions/setup-node@v4
        with:
          node-version: 22
      - run: npm ci
      - name: Semantic Release
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: npx semantic-release
      - name: Deploy ke pra-produksi
        if: github.ref == 'refs/heads/staging' || github.ref == 'refs/heads/rc'
        run: npm run deploy:staging
      - name: Deploy ke produksi
        if: github.ref == 'refs/heads/main'
        run: npm run deploy:prod

Workflow hanya dipicu oleh push ke tiga branch yang terdaftar di blok on, sehingga branch lain tidak pernah memicu rilis. Di dalam job, kondisi if memastikan tiap langkah deploy berjalan pada branch yang tepat. Rilis sendiri cukup satu perintah npx semantic-release — hasil versinya sudah ditentukan konfigurasi branch.

Warning

Perhatikan prefix refs/heads/. github.ref mengembalikan referensi lengkap, jadi if: github.ref == 'main' tidak akan pernah benar dan langkah akan selalu di-skip. Gunakan refs/heads/main, atau bandingkan dengan github.ref_name == 'main' yang lebih pendek.

Menghindari Release Ganda

Release ganda sering terjadi saat push dan merge mendarat hampir bersamaan. Tambahkan concurrency agar run lama dibatalkan dan run terbaru yang dilanjutkan:

Mencegah tumpang tindih release
concurrency:
  group: release-${{ github.ref }}
  cancel-in-progress: false

cancel-in-progress: false membuat release tidak dibatalkan di tengah jalan — yang tidak boleh terjadi karena bisa meninggalkan tag tanpa package atau sebaliknya. Run berikutnya menunggu run aktif selesai lebih dulu.

Tip

Jangan menaruh logika release pada lebih dari satu workflow. Satu file workflow yang membaca branch, dikombinasikan dengan konfigurasi branches, menjaga satu sumber kebenaran. Workflow kedua yang ikut rilis hanya akan membuat versi bertabrakan.

Kondisi Job-level untuk Rilis Stable

Jika ingin memisahkan job rilis stable, gunakan kondisi di level job:

Job rilis stable hanya untuk main
  release-stable:
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    permissions:
      contents: write
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - name: Semantic Release
        run: npx semantic-release

Pola yang sama berlaku untuk staging: cukup ubah perbandingan menjadi refs/heads/staging atau refs/heads/rc. Job yang kondisinya tidak terpenuhi akan ditandai "skipped" dan tidak memengaruhi status pipeline.

Kesalahan Umum

KesalahanGejalaSolusi
Bandingkan github.ref dengan mainKondisi tidak pernah benarPakai refs/heads/main atau github.ref_name
Branch tidak terdaftar di configTidak ada rilis saat pushDaftarkan branch di branches
Release commit memicu loopRilis berulang terusSertakan [skip ci] pada commit rilis
Dua workflow release aktifVersi bertabrakanSatu workflow plus concurrency
cancel-in-progress: trueTag dibuat tanpa publishSet false untuk job release

Penutup

Pada episode 11 ini kalian telah:

  • Menetapkan kebijakan rilis: main stable, branch prerelease berakhiran rc.
  • Membedakan github.ref (referensi lengkap) dan github.ref_name (nama branch).
  • Membatasi trigger di blok on dan memakai if untuk langkah deploy per branch.
  • Mencegah release ganda dengan concurrency dan cancel-in-progress: false.

Di episode 12 kita akan mengamankan semuanya dengan GitHub Actions Security Best Practices — least privilege, pembatasan branch, dan pengamanan secret. Sampai jumpa di episode 12!

Belajar Semantic Release - Kondisi Release Berdasarkan Branch | Belajar Semantic Release