Web Artisan

Tema

Font

Ukuran teks

GIT · PICTO

Replace release ceremony with Release Please

Tukar version bump manual, changelog di Confluence, dan release branch dengan Conventional Commits, Git tag, dan satu release PR otomatis.

11 menit bacaJun 2026

Alur rilis yang umum terlihat bertanggung jawab: naikkan versi di package.json dengan tangan, tulis changelog di Confluence, merge working branch ke develop, potong sebuah release branch, merge develop ke dalamnya, lalu buka satu PR lagi ke master. Ia selalu berhasil mengirim. Ia juga diam-diam memajakimu setiap kali.

teks
1. Naikkan versi package.json dengan tangan 2. Tulis changelog di Confluence 3. Merge working branch → develop (PR) 4. Buat release branch 5. Merge develop → release branch 6. Merge release branch → master (PR) 7. Produksi ter-deploy

Tiap langkah adalah tempat untuk lupa menaikkan versi, untuk membiarkan changelog menjauh dari kode yang sebenarnya berubah, atau untuk menjaga sebuah branch QA beku tetap hidup lama setelah tim berhenti membutuhkannya. Tanpa Git tag, tidak ada penanda tunggal yang jujur tentang apa yang sedang dijalankan produksi.

MASALAH SEBENARNYA Alur lama tidak salah. Ia hanya membungkus seremoni manual di sekitar sesuatu yang bisa dilakukan CI dengan andal dan tak pernah lupa.

Apa yang sebenarnya kamu otomatiskan

Kupas seremoninya jadi empat bagian bergerak dan gambarannya jadi sederhana.

teks
Git tag = versi rilis resmi CHANGELOG.md = release notes, hidup di dalam repo Conventional Commit = input yang meng-generate notes itu Release Please = bot yang membuka release PR, menulis changelog, memberi tag, dan memotong GitHub Release

Deployment produksi bergantung pada rilis, bukan pada tiap push ke master. Dan untuk aplikasi privat yang tak pernah dipublikasikan ke npm, versi di package.json itu opsional. Git tag adalah identitas rilis, dan ia terbaca persis seperti yang diharapkan manusia.

teks
v1.0.0 v1.1.0 v1.1.1

Bentuk alur yang baru

Ketukan yang sama tetap ada, tapi separuh yang membosankan jadi otomatis.

teks
feature branch ↓ squash merge develop ↓ deploy staging develop → master (merge commit, bukan squash) Release Please membuka release PR ↓ merge PR-nya Git tag + GitHub Release deploy produksi

Feature branch di-squash-merge ke develop. Merge dari develop ke master mempertahankan tiap commit-nya. Release Please membaca commit feat: dan fix: bermakna yang mendarat di master, dan produksi hanya ter-deploy setelah sebuah rilis dipotong.

Strategi merge adalah pilihan penyangga

Ini satu keputusan yang menjadi tumpuan seluruh workflow, dan ia mengarah ke dua arah berbeda tergantung kamu di mana.

Feature ke develop: squash and merge. Kamu ingin satu commit bersih per tiket, bukan jejak wip, fix typo, oops yang berisik dari branch. Judul squash tunggal itulah yang akan dikutip changelog, jadi ia harus berupa Conventional Commit.

teks
# commit di branch (derau) feat(navbar): flatten Shop All mega-menu feat(shop-all): revamp filters, hero banner & page surfaces feat(home): reorder sections & restore Beauty Impact # judul squash yang mendarat di develop (sinyal) feat(shop-all): revamp homepage, Shop All, and navbar

Develop ke master: merge commit sungguhan. Squash di sini akan meruntuhkan tiap feat dan fix jadi satu chore: merge develop to master yang kabur, dan Release Please tidak akan melihat apa pun yang layak dirilis. Sebuah merge commit mempertahankan semua commit bersih agar bot masih bisa membacanya.

SATU ATURAN Squash branch kecil ke develop. Jangan pernah squash develop ke master.

Conventional Commits adalah input-nya

Release notes hanya sebaik judul commit yang menyuapinya. Kosakata kecil dan membosankan sudah cukup.

teks
feat(scope): fitur atau peningkatan yang dilihat pengguna fix(scope): perbaikan bug yang dilihat pengguna perf(scope): peningkatan performa refactor(scope): penataan ulang internal, perilaku tak berubah chore(scope): tooling atau pemeliharaan docs(scope): dokumentasi saja style(scope): perapian format atau styling

Prefix-nya menentukan kenaikan versi, dan itulah inti dari melewati bump manual.

teks
feat: → rilis minor (1.1.0) fix: → rilis patch (1.1.1) feat! / BREAKING CHANGE: → rilis major (2.0.0) chore / docs / style / refactor: → biasanya tanpa release note

Tulis judul yang bisa dibaca orang asing di sebuah changelog. Yang bagus menggambarkan perubahan produk; yang buruk tidak menggambarkan apa-apa.

teks
# bagus feat(shop-all): revamp homepage, Shop All, and navbar fix(cart): prevent duplicate checkout submission perf(product-list): reduce initial render cost # buruk Neo 2260 update stuff fix bug merge develop

JEBAKANNYA Kalau judul squash bukan Conventional Commit, Release Please mengabaikannya. Run Action yang hijau tanpa release PR hampir selalu berarti persis ini.

Merangkai GitHub Action

Satu workflow mengawasi master dan mengerjakan pembukuannya. release-type: simple adalah strategi untuk repo generik yang tidak punya file versi bahasa untuk dirawat, jadi package.json dibiarkan utuh.

.github/workflows/release-please.yml
name: Release Please on: push: branches: - master permissions: contents: write pull-requests: write issues: write jobs: release-please: runs-on: ubuntu-latest steps: - name: Run Release Please id: release uses: googleapis/release-please-action@v4 with: release-type: simple target-branch: master

Pada tiap push ke master, action memindai Conventional Commits sejak tag rilis terakhir, lalu membuka atau memperbarui satu Release Please PR. Di PR itulah CHANGELOG.md ditulis ulang. Merge ia, dan action membuat Git tag dan GitHub Release. Kalau branch produksimu main, ganti kedua baris master jadi main, karena nama branch di config harus cocok dengan kenyataan.

Belum ada tag sebelumnya? Tetapkan baseline

Banyak repo punya riwayat bertahun-tahun dan nol tag rilis. Jangan menulis ulang riwayat dan jangan menambal changelog lama. Beri tag pada branch produksi saat ini sekali saja, dan biarkan otomasi mengambil alih dari sana.

Terminal
git checkout master git pull origin master git tag -a v1.0.0 -m "v1.0.0 baseline release" git push origin v1.0.0

Beri benih CHANGELOG.md dengan satu entri jujur agar file-nya ada dan ceritanya punya titik awal.

md
# Changelog ## v1.0.0 Rilis baseline awal. Ini menandai keadaan produksi saat ini sebelum mengadopsi release notes otomatis. Semua setelah titik ini dilacak otomatis.

Dari v1.0.0 dan seterusnya, tiap rilis di-generate dari commit yang datang sesudahnya. Entri changelog yang sudah jadi sengaja tetap pendek, karena ia merangkum perubahan produk alih-alih menggemakan riwayat commit mentah.

md
## [1.1.0](https://github.com/org/repo/compare/v1.0.0...v1.1.0) (2026-06-18) ### Features * revamp homepage, Shop All, and navbar

Satu tiket jadi satu baris. Kalau dua perubahan benar-benar independen, itu pertanda keduanya ingin jadi dua PR.

Deploy saat rilis, bukan tiap push

Push ke master seharusnya tidak men-deploy produksi. Sebuah rilis yang dipotonglah yang seharusnya. Pergeseran tunggal itu menjamin tiap deploy produksi punya tag di belakangnya, yang membuat rollback dan audit jadi sepele. Cara paling bersih merangkainya adalah menjaga Release Please dan deploy di workflow yang sama, tiap langkah deploy digerbangi oleh output release_created milik action.

.github/workflows/release-and-deploy.yml
name: Release Please and Production Deploy on: push: branches: - master permissions: contents: write pull-requests: write issues: write jobs: release-and-deploy: runs-on: ubuntu-latest steps: - name: Run Release Please id: release uses: googleapis/release-please-action@v4 with: release-type: simple target-branch: master - name: Checkout release commit if: ${{ steps.release.outputs.release_created }} uses: actions/checkout@v4 - name: Setup Node if: ${{ steps.release.outputs.release_created }} uses: actions/setup-node@v4 with: node-version: 22 cache: yarn - name: Install dependencies if: ${{ steps.release.outputs.release_created }} run: yarn install --frozen-lockfile - name: Build if: ${{ steps.release.outputs.release_created }} run: yarn build - name: Deploy production if: ${{ steps.release.outputs.release_created }} run: echo "Taruh perintah deploy produksi di sini"

release_created hanya true setelah Release Please PR di-merge dan sebuah rilis benar-benar dipotong. Tiap push yang tidak menghasilkan rilis menjalankan langkah pertama lalu berhenti, jadi produksi tak pernah ter-deploy mendahului metadata rilisnya sendiri.

Jebakan yang layak dicatat

Beberapa sudut tajam muncul di minggu pertama lalu tak pernah lagi setelah kamu tahu.

Run Action yang sukses tidak selalu berarti ada release PR. Kalau satu-satunya commit sejak tag terakhir adalah merge commit atau judul non-konvensional seperti Neo 2260, tidak ada yang bisa dirilis dan bot dengan benar tidak membuka apa-apa. Setelah squash merge, hanya judul squash final yang penting, commit asli di branch sudah hilang.

Pola satu-workflow di atas bukan preferensi gaya, ia sebuah workaround. GitHub Release yang dibuat GITHUB_TOKEN default tidak akan memicu workflow terpisah yang mendengarkan release: published. Menggerbangi deploy pada release_created di dalam satu workflow menghindari itu sepenuhnya.

ATURAN TIM Judul Conventional Commit di tiap PR. Squash ke develop, merge-commit ke master. Jangan pernah mengedit versi aplikasi privat dengan tangan. Beri tag baseline sekali. Deploy saat rilis, bukan saat push. Pecah perubahan tak terkait jadi PR terpisah.

Intinya

Langkah manual bukan musuhnya; seremoni berulanglah musuhnya. Biarkan engineer menghabiskan penilaian mereka pada satu hal yang hanya bisa mereka putuskan, dan biarkan pipeline menangani versioning, changelog, tag, dan pemicu deploy.

POLA PIKIRNYA Manusia memutuskan kesiapan rilis. Otomasi menangani mekanika rilis.