Semantic Release di GitHub Actions memungkinkan tim menghilangkan proses manual saat menentukan versi, menulis changelog, dan membuat GitHub Release. Selama tim konsisten memakai Conventional Commits, sistem dapat menghitung apakah perubahan berikutnya adalah patch, minor, atau major, lalu menjalankan rilis secara otomatis setiap kali commit masuk ke branch rilis.

Untuk tim kecil-menengah, pendekatan ini berguna karena mengurangi human error: tidak ada lagi versi lompat, changelog terlupa, atau release tag yang tidak sinkron dengan isi repository. Kuncinya bukan hanya memasang package, tetapi memastikan struktur commit, permission GitHub Actions, proteksi branch, dan alur rollback sudah dipikirkan sejak awal.

Bagaimana semantic-release bekerja

semantic-release membaca histori commit sejak release terakhir, menganalisis pesan commit, lalu menentukan tipe kenaikan versi berdasarkan aturan Conventional Commits:

  • fix: menaikkan versi patch
  • feat: menaikkan versi minor
  • BREAKING CHANGE atau tanda !: menaikkan versi major

Setelah itu, semantic-release dapat:

  • membuat tag versi baru
  • menghasilkan atau memperbarui changelog
  • membuat GitHub Release
  • memperbarui file seperti package.json bila diperlukan
  • mendorong commit hasil rilis kembali ke repository

Alur ini bekerja baik jika repository memiliki satu branch rilis utama, misalnya main, dan tim tidak sembarang menulis pesan commit.

Syarat utama sebelum implementasi

1. Tim harus memakai Conventional Commits

Contoh format commit yang aman dipakai:

feat(auth): tambah login dengan OAuth
fix(api): perbaiki validasi parameter kosong
docs(readme): perbarui panduan instalasi
refactor(queue): sederhanakan handler retry
feat!: ubah format response endpoint user

BREAKING CHANGE: response user sekarang menggunakan field profile

Jika commit message tidak konsisten, semantic-release bisa salah membaca perubahan atau tidak merilis sama sekali. Ini adalah jebakan paling umum.

2. Repository harus punya branch rilis yang jelas

Untuk skenario sederhana, gunakan satu branch rilis seperti main. Jangan jalankan semantic-release di banyak branch sebelum aturan branch benar-benar dipahami, karena dapat memicu konflik versi atau release yang tidak diinginkan.

3. Workflow butuh permission yang cukup

Jika workflow akan membuat tag, release, changelog, atau commit balik ke branch, token yang dipakai harus memiliki hak tulis yang sesuai. Banyak kegagalan terjadi bukan karena semantic-release salah, tetapi karena GitHub Actions berjalan dengan permission default yang terlalu ketat.

4. Node.js project atau lingkungan yang bisa menjalankan semantic-release

Contoh paling umum adalah repository JavaScript/TypeScript karena semantic-release tersedia sebagai package npm. Namun konsepnya tetap bisa dipakai untuk project lain selama pipeline dapat menjalankan semantic-release dan plugin yang dibutuhkan.

Struktur package dan plugin yang umum dipakai

Untuk use case yang diminta—otomatisasi versi, changelog, dan GitHub Release—kombinasi plugin yang sering dipakai adalah:

  • @semantic-release/commit-analyzer untuk membaca commit
  • @semantic-release/release-notes-generator untuk membuat catatan rilis
  • @semantic-release/changelog untuk memperbarui CHANGELOG.md
  • @semantic-release/github untuk membuat GitHub Release
  • @semantic-release/git untuk commit kembali perubahan seperti changelog dan file versi

Instal sebagai dev dependency:

npm install -D semantic-release \
  @semantic-release/commit-analyzer \
  @semantic-release/release-notes-generator \
  @semantic-release/changelog \
  @semantic-release/github \
  @semantic-release/git

Jika project adalah package npm yang juga dipublikasikan ke registry, Anda bisa menambahkan @semantic-release/npm. Namun jika fokusnya hanya GitHub Release dan changelog, jangan menambah plugin yang tidak diperlukan. Semakin sedikit plugin, semakin kecil permukaan masalah.

Konfigurasi inti semantic-release

Buat file konfigurasi, misalnya .releaserc.json:

{
  "branches": ["main"],
  "plugins": [
    "@semantic-release/commit-analyzer",
    "@semantic-release/release-notes-generator",
    [
      "@semantic-release/changelog",
      {
        "changelogFile": "CHANGELOG.md"
      }
    ],
    [
      "@semantic-release/git",
      {
        "assets": ["CHANGELOG.md", "package.json"],
        "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
      }
    ],
    "@semantic-release/github"
  ]
}

Penjelasan bagian penting:

  • branches: branch yang dianggap sebagai sumber rilis. Untuk awal, cukup main.
  • commit-analyzer: memutuskan bump patch/minor/major dari commit.
  • release-notes-generator: membuat isi catatan rilis dari commit yang valid.
  • changelog: menulis hasil release notes ke CHANGELOG.md.
  • git: meng-commit kembali file yang berubah akibat proses rilis.
  • github: membuat GitHub Release dan mengaitkan tag rilis ke repository.

Jika project bukan package npm, aset package.json pada plugin git bisa dihapus. Jangan memaksa semantic-release memperbarui file yang sebenarnya tidak dipakai oleh proses build atau distribusi Anda.

Catatan: semantic-release tidak akan membuat rilis hanya karena workflow berjalan. Ia tetap membutuhkan commit yang memenuhi aturan release. Commit seperti docs: atau chore: umumnya tidak memicu rilis kecuali Anda mengubah aturan analisis commit.

Workflow GitHub Actions minimal

Berikut contoh workflow minimal yang cukup aman untuk banyak tim:

name: Release

on:
  push:
    branches:
      - main

permissions:
  contents: write
  issues: write
  pull-requests: write

jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 20

      - name: Install dependencies
        run: npm ci

      - name: Run semantic-release
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: npx semantic-release

Ada tiga detail teknis yang sering diabaikan:

  1. fetch-depth: 0 wajib diperhatikan karena semantic-release perlu histori git dan tag lengkap untuk menghitung release berikutnya. Jika checkout dangkal, versi bisa salah atau release gagal.
  2. permissions harus mengizinkan penulisan ke repository. Jika tidak, pembuatan tag, release, atau commit changelog akan ditolak.
  3. GITHUB_TOKEN umumnya cukup untuk GitHub Release di repository yang sama, selama permission workflow benar.

Kapan perlu Personal Access Token?

Untuk banyak kasus, secrets.GITHUB_TOKEN cukup. Namun pada repository dengan aturan proteksi ketat, kebutuhan lintas repository, atau pembatasan tertentu pada bot bawaan GitHub Actions, Anda mungkin perlu memakai token lain, misalnya fine-grained personal access token atau token dari GitHub App. Gunakan ini hanya jika memang diperlukan, karena pengelolaan token tambahan meningkatkan risiko dan beban administrasi.

Proteksi branch dan implikasinya

Branch main sebaiknya tetap diproteksi, tetapi aturan proteksinya harus kompatibel dengan proses rilis otomatis. Ini kompromi penting antara keamanan dan otomasi.

Pengaturan yang umumnya aman

  • wajib lewat pull request untuk perubahan biasa
  • wajib lulus status check sebelum merge
  • batasi siapa yang boleh push langsung ke branch rilis

Yang perlu diperiksa jika semantic-release melakukan commit balik

Jika Anda memakai plugin @semantic-release/git, workflow akan mencoba mendorong commit baru ke branch rilis. Di sinilah proteksi branch sering menyebabkan kegagalan. Beberapa opsi yang umum dipilih tim:

  • Opsi A: izinkan GitHub Actions bot mendorong commit rilis ke branch tertentu
  • Opsi B: jangan commit balik changelog ke branch, dan hanya buat GitHub Release tanpa mengubah isi repository
  • Opsi C: gunakan branch atau proses rilis terpisah jika kebijakan repository sangat ketat

Untuk tim kecil-menengah, Opsi B sering lebih sederhana jika changelog file di repository tidak benar-benar dibutuhkan. Namun jika tim ingin CHANGELOG.md selalu sinkron di source code, maka pastikan bot CI memang diizinkan menulis ke branch rilis.

Dry run sebelum diaktifkan penuh

Jangan langsung mengaktifkan rilis otomatis di branch utama tanpa simulasi. Semantic-release menyediakan mode dry run untuk memverifikasi apakah commit yang ada akan menghasilkan release yang diharapkan.

npx semantic-release --dry-run

Anda bisa menjalankannya lokal atau melalui workflow sementara. Yang perlu dicek dari hasil dry run:

  • branch yang dibaca sudah benar
  • tag release sebelumnya terdeteksi
  • jenis bump versi sudah sesuai histori commit
  • commit tertentu tidak memicu release secara keliru
  • release notes yang dihasilkan masuk akal

Praktik yang baik adalah membuat beberapa commit uji seperti fix:, feat:, dan feat!: di branch percobaan untuk melihat perilaku aktual.

Jebakan umum dan cara mengatasinya

1. Commit message tidak konsisten

Masalah: semantic-release tidak menemukan commit yang layak dirilis, atau versi yang dihasilkan tidak sesuai ekspektasi.

Solusi:

  • standarkan format commit di tim
  • gunakan template PR yang mengingatkan jenis perubahan
  • tambahkan validasi commit message dengan alat seperti commitlint bila diperlukan

Jika tim sering melakukan squash merge, perhatikan pesan commit hasil squash. Semantic-release membaca commit yang masuk ke branch rilis, jadi pesan akhir merge lebih penting daripada judul commit di branch fitur.

2. Permission workflow kurang

Masalah: gagal membuat tag, gagal membuat GitHub Release, atau gagal push CHANGELOG.md.

Gejala umum:

  • error akses ditolak saat push
  • release tidak muncul meski log menunjukkan analisis commit berjalan
  • tag tidak berhasil dibuat

Solusi:

  • set permissions workflow secara eksplisit
  • pastikan token yang dipakai memang punya hak tulis
  • cek aturan proteksi branch yang mungkin menolak push dari bot

3. Konflik pada release branch

Masalah: semantic-release ingin commit changelog, tetapi branch sudah bergerak karena push lain, merge paralel, atau workflow ganda.

Solusi:

  • pastikan hanya satu workflow release berjalan per branch pada saat yang sama
  • hindari trigger yang tidak perlu
  • pertimbangkan concurrency control di GitHub Actions untuk mencegah dua job release saling balapan

Contoh tambahan di workflow:

concurrency:
  group: release-main
  cancel-in-progress: false

Ini membantu mencegah dua proses release untuk branch yang sama berjalan bersamaan.

4. Histori git tidak lengkap

Masalah: semantic-release tidak menemukan tag sebelumnya atau salah menghitung rilis.

Solusi: pastikan checkout memakai fetch-depth: 0.

5. Release branch salah konfigurasi

Masalah: semantic-release berjalan di branch yang tidak seharusnya, atau tidak berjalan di branch utama.

Solusi: samakan definisi branch pada file workflow dan file konfigurasi semantic-release. Jangan mengandalkan asumsi.

Strategi rollback saat rilis gagal

Rollback pada semantic-release harus dibedakan berdasarkan titik kegagalannya. Tidak semua kegagalan perlu tindakan yang sama.

Skenario 1: Gagal sebelum tag dan release dibuat

Ini paling aman. Biasanya cukup memperbaiki konfigurasi, permission, atau commit message, lalu jalankan ulang workflow. Karena belum ada artefak rilis yang terpublikasi, tidak ada rollback khusus.

Skenario 2: Tag sudah dibuat, tetapi changelog atau GitHub Release gagal

Di sini Anda perlu hati-hati. Jangan buru-buru membuat tag manual baru dengan nomor versi lain. Langkah umum yang lebih aman:

  1. identifikasi apa yang sudah berhasil dibuat: tag, release, atau commit changelog
  2. hapus artefak yang setengah jadi jika kebijakan tim mengizinkan
  3. perbaiki penyebab utama, misalnya permission atau konflik branch
  4. jalankan ulang hanya setelah repository kembali konsisten

Jika tag sudah ter-push tetapi release belum lengkap, tim harus sepakat apakah tag tersebut dianggap batal atau tetap dipertahankan. Hindari keputusan ad hoc karena ini memengaruhi histori versi.

Skenario 3: GitHub Release berhasil, tetapi isi changelog di repository tidak sinkron

Jika ini terjadi karena push changelog ditolak proteksi branch, Anda punya dua pilihan praktis:

  • perbaiki permission lalu ulangi proses pada commit berikutnya
  • sederhanakan pipeline dengan menghapus plugin @semantic-release/git dan andalkan GitHub Release sebagai sumber catatan rilis

Untuk tim kecil-menengah, opsi kedua sering lebih stabil jika branch protection tidak fleksibel.

Prinsip rollback yang perlu dipegang

  • jangan mengedit versi secara manual di tengah pipeline kecuali benar-benar paham konsekuensinya
  • hindari membuat tag duplikat atau meloncat versi tanpa alasan jelas
  • dokumentasikan prosedur rollback internal agar semua orang mengikuti langkah yang sama

Checklist adopsi untuk tim kecil-menengah

  1. Tentukan branch rilis utama, misalnya main.
  2. Sepakati standar Conventional Commits di seluruh tim.
  3. Pasang package semantic-release dan plugin yang benar-benar dibutuhkan.
  4. Buat file .releaserc.json dengan branch dan plugin yang sesuai.
  5. Siapkan workflow GitHub Actions dengan fetch-depth: 0.
  6. Set permission workflow agar bisa membuat tag dan GitHub Release.
  7. Tentukan apakah changelog akan di-commit kembali ke repository atau hanya disimpan di GitHub Release.
  8. Pastikan aturan proteksi branch tidak memblokir alur rilis yang dipilih.
  9. Jalankan dry run sebelum mengaktifkan rilis otomatis penuh.
  10. Tambahkan concurrency agar tidak ada dua release berjalan bersamaan.
  11. Dokumentasikan langkah rollback bila rilis gagal di tengah jalan.

Rekomendasi implementasi yang realistis

Jika Anda baru memulai, gunakan setup sesederhana mungkin:

  • satu branch rilis: main
  • Conventional Commits wajib
  • GitHub Actions dengan satu job release
  • GitHub Release aktif
  • changelog file hanya jika branch protection mengizinkan commit bot

Pendekatan ini lebih mudah dipelihara daripada langsung membuat skema multi-branch, prerelease, atau sinkronisasi ke banyak target publikasi. Setelah alur dasar stabil, baru pertimbangkan penambahan seperti commitlint, release channel, atau publikasi package ke registry.

Intinya, Semantic Release di GitHub Actions untuk versioning tanpa manual akan efektif jika tiga hal dijaga sekaligus: histori commit yang rapi, workflow dengan permission yang tepat, dan kebijakan branch yang tidak bertabrakan dengan proses otomatis. Bila salah satu diabaikan, masalah biasanya muncul bukan pada tooling-nya, melainkan pada integrasi proses tim.