Membuat workflow GitHub Actions dengan trigger push, pull request, dan workflow_dispatch. Lalu memisahkan job ci untuk lint dan build, job release yang berjalan hanya di main dan staging, serta pengelolaan secret seperti GITHUB_TOKEN dan NPM_TOKEN.

Di episode 5 konfigurasi semantic-release sudah siap dan terverifikasi lewat dry run. Sekarang kita menaruhnya di tempat yang tepat: pipeline CI. Manual npx semantic-release di mesin lokal bukanlah alur produksi — release harus berjalan di environment CI yang konsisten, dengan token yang aman, dan hanya dipicu oleh peristiwa yang benar.
GitHub Actions adalah tempat paling wajar untuk ini karena semantic-release dan GitHub hidup di ekosistem yang sama: tag, release, dan PR comment dibuat oleh bot langsung di repository yang sama. Episode ini membangun dua hal: job ci untuk jaminan kualitas, dan job release yang berjalan hanya di branch main dan staging.
Sebuah workflow adalah file YAML di folder .github/workflows/. Ia punya tiga bagian besar: on untuk trigger, jobs untuk pekerjaan, dan permissions untuk hak akses. Semantic-release butuh riwayat penuh git untuk membandingkan commit sejak tag terakhir, jadi checkout harus menyertakan fetch-depth: 0.
| Trigger | Kapan Berjalan |
|---|---|
push | Setiap commit di-push ke branch tertentu |
pull_request | PR dibuka, diperbarui, atau direview |
workflow_dispatch | Dipicu manual dari tab Actions |
Pembagian tugasnya natural: pull_request dan push memicu job ci untuk validasi, sedangkan rilis hanya pada push ke main atau staging.
name: CI & Release
on:
push:
branches: [main, staging]
pull_request:
branches: [main, staging]
jobs:
ci:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
- run: npm ci
- run: npm run lint
- run: npm run build
- name: Semantic Release Dry Run
if: github.event_name == 'pull_request'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: npx semantic-release --dry-run --no-ci
release:
if: github.event_name == 'push'
runs-on: ubuntu-latest
needs: ci
permissions:
contents: write
issues: write
pull-requests: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: 22
- run: npm ci
- name: Semantic Release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
run: npx semantic-releaseMari bedah baris demi baris:
ci berjalan untuk pull request dan push, dengan hak akses minimal contents: read — cukup untuk checkout dan build. Step terakhir menjalankan dry run agar pull request memperlihatkan versi yang akan dirilis.release hanya berjalan saat event push, menunggu job ci selesai (needs), dan memakai contents: write karena ia harus membuat tag dan GitHub Release.fetch-depth: 0 mengambil seluruh history git — prasyarat mutlak agar commit analyzer bisa membandingkan commit sejak tag terakhir.branches pada trigger push dan daftar branches di release.config.cjs — dua lapis perlindungan agar rilis tidak terjadi dari branch yang salah.Jika ingin lebih eksplisit, job release bisa diberi kondisi berdasarkan nama branch. Nilai seperti github.ref direferensikan di dalam YAML — bukan di prosa:
jobs:
release:
if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/staging'Sifat kondisi ini membuat rilis stable hanya dari main dan prerelease hanya dari staging, apa pun trigger yang datang.
Secret tidak pernah ditulis keras di YAML — nilainya diambil saat runtime:
GITHUB_TOKEN: token otomatis yang disediakan GitHub untuk setiap run. Perilaku defaultnya contents: read; untuk membuat tag dan release, job harus menaikkan ke contents: write.NPM_TOKEN: token dari npmjs.com untuk publish package. Didaftarkan di repository Settings, lalu dipanggil lewat secrets.NPM_TOKEN.NPM_CONFIG_REGISTRY: environment variable untuk mengarahkan publish ke registry privat.Buka repository -> Settings -> Secrets and variables -> Actions
klik New repository secret
masukkan nama (misal NPM_TOKEN) dan nilainya
secret langsung dipakai lewat env, tidak pernah muncul di logWarning
Lupa menaikkan contents: write adalah penyebab kegagalan paling umum: semantic-release berhasil menghitung versi dan changelog, lalu gagal 403 saat membuat tag atau GitHub Release. Pastikan job release memiliki permissions: contents: write, dan job lain cukup contents: read (least privilege).
workflow_dispatch memungkinkan kalian memicu workflow manual dari tab Actions — berguna untuk mencoba konfigurasi tanpa commit baru.DEBUG menjadi semantic-release:* pada job.feat atau fix sejak tag terakhir, dan memang tidak ada yang perlu dirilis.Pada episode 6 ini kalian telah membangun:
push, pull_request, dan workflow_dispatch.ci untuk lint, build, dan dry run dengan akses minimal.release yang gated di branch main dan staging dengan permissions: contents: write.GITHUB_TOKEN dan NPM_TOKEN yang aman.Siklus otomatisasi kalian kini utuh: commit berformat, branch terstruktur, konfigurasi teruji, dan pipeline siap merilis. Di episode 7 kita akan membandingkan alur staging vs production: bagaimana rilis rc berjalan di staging dan rilis stable di main, serta cara memvalidasi keduanya dengan dry run sebelum release sungguhan. Sampai jumpa di episode 7!