Engineering

Semantic versioning dan changelog Anda

5 menit baca

Semantic versioning memberi tahu pemanggil seberapa sakit sebuah rilis bisa dirasakannya sebelum membaca satu entri changelog pun. Naik dari 2.4.1 ke 2.5.0 berarti: kapabilitas baru, tak ada yang rusak. Naik dari 2.5.0 ke 3.0.0 berarti: baca entri ini sebelum update. Changelog dan nomor versi seharusnya menyatakan hal yang sama dalam dua format, dan sebagian besar friksi antara keduanya muncul justru saat keduanya tak sepakat, yang lebih sering terjadi dari yang disarankan spesifikasinya.

Apa sebenarnya yang dijanjikan tiap angka dalam sebuah versi?

Semantic versioning mendefinisikan tiga angka, MAJOR.MINOR.PATCH, masing-masing dengan aturan ketat tentang apa yang memicunya. Lompatan MAJOR berarti perubahan yang tak kompatibel: sesuatu yang bisa disadari integrasi yang benar dan sudah ada, dan karenanya harus berubah. Lompatan MINOR berarti fungsionalitas baru yang kompatibel ke belakang: tak ada yang lama rusak, sesuatu yang baru tersedia. Lompatan PATCH berarti perbaikan yang kompatibel ke belakang: perilaku menjadi lebih dekat dengan yang didokumentasikan, dan siapa pun yang sengaja bergantung pada perilaku lama seharusnya tak menyadari apa pun.

LompatanArtiEntri seharusnya terbaca seperti
MAJOR (1.x.x -> 2.0.0)Perubahan tak kompatibel“Perlu tindakan sebelum update”
MINOR (1.2.x -> 1.3.0)Kapabilitas baru yang kompatibel“Tersedia sekarang, tak ada lagi yang berubah”
PATCH (1.2.3 -> 1.2.4)Perbaikan yang kompatibel“Sekarang berperilaku sesuai dokumentasi”

Tabel ini juga uji terbalik: jika sebuah entri tak terbaca seperti barisnya, entah nomor versinya salah, atau entri itu terlalu kecil atau terlalu besar dalam menjual apa yang sebenarnya terjadi.

Apa yang dihitung sebagai tak kompatibel untuk tujuan versioning?

Uji yang sama yang menentukan apakah sesuatu termasuk dalam changelog API: apakah pemanggil yang benar, ditulis melawan perilaku lama dan tak tersentuh sejak itu, bisa berperilaku berbeda karena perubahan ini. Apa itu perubahan tak kompatibel, dan cara merilisnya membahas keputusan itu secara lengkap, termasuk kasus yang terlihat tak kompatibel padahal bukan, dan yang terlihat kecil padahal bukan. Singkatnya untuk tujuan versioning: jika jawabannya ya, lompatannya MAJOR terlepas dari berapa banyak kode yang sebenarnya disentuh perubahan itu secara internal. Nomor versi mengikuti konsekuensi bagi pemanggil, bukan usaha tim.

Bagaimana seharusnya entri changelog cocok dengan lompatan versi?

Satu entri, satu kategori lompatan, dinyatakan sejak awal. Pola dari tabel berlanjut langsung: entri tak kompatibel berada di bawah versi yang memperkenalkannya, diformulasikan dulu sebagai peringatan lalu sebagai deskripsi. Entri aditif berada di bawah versi MINOR-nya, diformulasikan sebagai ketersediaan. Perbaikan berada di bawah versi PATCH-nya, diformulasikan sebagai koreksi. Mencampur kategori dalam satu entri, seperti melipat perubahan tak kompatibel ke paragraf yang sama dengan perbaikan yang tak berhubungan, adalah cara pembaca melewatkan justru satu hal yang paling penting.

## 3.0.0 (2026-09-07)

### Changed
- **BREAKING:** `GET /reports` sekarang mengembalikan jumlah sebagai
  integer dalam satuan mata uang terkecil (sen) alih-alih desimal.
  Perbarui kode yang membaca `amount` secara langsung.

## 2.9.0 (2026-09-01)

### Added
- Laporan sekarang bisa difilter berdasarkan `status`.

## 2.8.4 (2026-08-28)

### Fixed
- `GET /reports?status=` mengembalikan halaman kosong alih-alih 400
  untuk status yang tidak dikenal.

Dibaca dari atas ke bawah, nomor versi dan label bagian mengatakan hal yang sama dua kali, dan itulah tujuannya: pembaca yang hanya memindai judul mendapat pembacaan risiko yang benar sebelum membuka satu baris pun.

Apakah aturan breaking change berlaku sama sebelum 1.0.0?

Tidak, dan di sinilah sebagian besar kebingungan tentang “apakah itu sungguh breaking” berasal. SemVer eksplisit menyatakan versi mayor nol, 0.y.z, untuk pengembangan awal: apa pun bisa berubah kapan saja, dan API publik tidak boleh dianggap stabil. Lompatan 0.4.0 ke 0.5.0 bisa membawa breaking change tanpa melanggar spec, karena jaminan versi mayor baru berlaku begitu proyek merilis 1.0.0. Entri changelog tetap berutang kejujuran yang sama tentang apa yang rusak; yang berubah hanyalah nomor versi itu sendiri bukan sinyal yang bisa diandalkan sebelum 1.0.0 tiba.

Bagaimana jika produk Anda tak merilis versi diskrit?

Kebanyakan produk SaaS melakukan deploy berkelanjutan dan tak pernah menampilkan nomor versi ke pemanggil, yang tak menghilangkan kebutuhan akan disiplin ini, hanya angka yang biasanya membawanya. Entri changelog harus melakukan semua pekerjaan sendiri: menyatakan dengan jelas apakah perubahan itu tak kompatibel, aditif, atau perbaikan, dengan tiga kata yang sama yang dipakai semantic versioning, bahkan tanpa kolom versi untuk menempelkannya. Beberapa tim menjaga versi yang murni internal hanya untuk menjangkarkan entri changelog ke sesuatu yang bisa ditautkan, tanpa pernah menunjukkannya langsung ke pemanggil.

Bagaimana ini berlaku khusus untuk changelog API?

Lebih ketat daripada hampir di mana pun, karena pemanggil API adalah kode, bukan orang yang bisa mengangkat bahu menghadapi perubahan tak terduga. Changelog API: apa yang dipublikasikan dan siapa yang membacanya membahas bentuk lengkap dokumen itu; disiplin versioning di sini adalah yang menjaga kejujuran bagian breaking dan aditifnya. API yang menawarkan beberapa versi sekaligus, seperti v1 dan v2 disajikan bersamaan selama jendela migrasi, secara efektif menerapkan semantic versioning pada skala seluruh antarmuka alih-alih satu paket, dan kosakata tiga kata yang sama masih berlaku untuk setiap entri.

Apa yang dikatakan Keep a Changelog tentang versioning?

Ia terhubung langsung dengan nama ke semantic versioning dan merekomendasikan kosakata kategori yang sama yang dipakai artikel ini: Added, Changed, Deprecated, Removed, Fixed, Security. Keep a Changelog, dalam praktik membahas cara mengadopsi spesifikasi itu, termasuk di mana tim biasanya menyimpang. Tumpang tindihnya bukan kebetulan: kedua spesifikasi mencoba memecahkan masalah yang sama dari ujung yang berlawanan, satu menstandarkan nomor versi dan yang lain entri yang menjelaskannya.

FAQ

Apakah setiap entri changelog butuh nomor versi? Jika produk merilis versi, ya, karena angka itu memungkinkan pembaca langsung melompat ke “seberapa ini memengaruhi saya” tanpa membaca entrinya dulu. Jika produk deploy berkelanjutan tanpa kolom versi, formulasi entri harus membawa sinyal itu sendiri.

Apa bedanya lompatan MAJOR dengan entri perubahan tak kompatibel? Keduanya seharusnya peristiwa yang sama dijelaskan dengan dua cara. Nomor versi adalah sinyal yang bisa dibaca mesin (tooling pemanggil bisa bereaksi terhadapnya); entri changelog adalah penjelasan yang bisa dibaca manusia tentang apa yang berubah secara konkret.

Bisakah rilis PATCH bersifat tak kompatibel? Secara definisi seharusnya tidak. Jika ternyata tetap dirilis, jangan edit atau beri tag ulang versi yang sudah dipublikasikan: SemVer FAQ menyarankan merilis versi baru yang memulihkan kompatibilitas, atau MAJOR baru jika kerusakannya tetap ada, dan mendokumentasikan versi bermasalah itu agar pengguna tahu harus melewatinya.

Apakah perubahan yang murni internal butuh lompatan versi? Tidak. Semantic versioning mengikuti antarmuka publik. Refactor tanpa efek yang bisa diamati bagi pemanggil tak butuh lompatan atau entri changelog, meskipun secara internal itu pekerjaan engineering yang signifikan.


Klaim teknis dalam artikel ini belum ditinjau secara independen. Jika ada yang keliru, beri tahu kami dan kami akan memperbaikinya.

Terkait di changeloop: Generator changelog, Dokumentasi developer

changeloop
Tim di balik changelog yang menutup lingkaran. Pengguna meminta sesuatu, timmu mengirimkannya, yang meminta jadi tahu.