Release
Halaman ini menjelaskan bagaimana perubahan di main menjadi version yang dapat diinstall: arti version number, isi CHANGELOG.md, dan bagaimana .gitattributes menentukan file yang benar-benar masuk archive yang didownload Composer. Bagian terakhir bukan sekadar housekeeping — installer membaca file dari package saat runtime, sehingga export list harus memastikan file tersebut tetap ikut distribusi.
Contoh minimal
composer validate --strict --no-check-publish
composer run format-check
composer run analyse
composer run test
git add .
git commit -m "Update package"
git push origin main
git tag -a v0.1.3 -m "v0.1.3"
git push origin v0.1.32
3
4
5
6
7
8
9
10
11
Itulah isi prosedur UPDATE.md pada repository root. Packagist menerima tag melalui GitHub webhook; tidak ada artifact yang perlu diupload manual.
composer validate --strict --no-check-publish dijalankan pertama karena hanya command ini yang membaca composer.json sebagai manifest, bukan sekadar daftar dependency. Manifest rusak menghasilkan tag yang tidak dapat diinstall siapa pun.
Versioning
Package masih berada pada seri 0.x — tag yang sudah dipublish antara lain v0.1.0, v0.1.1, dan v0.1.2. Semantic Versioning memperlakukan 0.x secara khusus: minor release pada 0.x boleh membawa breaking change. Composer memahami hal tersebut; constraint ^0.1 berarti >=0.1.0 <0.2.0.
| Bump | Kapan digunakan |
|---|---|
Patch — 0.1.2 → 0.1.3 | Bug fix yang tidak membutuhkan edit pada application pengguna. |
Minor — 0.1.x → 0.2.0 | Feature baru dan setiap perubahan yang membutuhkan edit pada application. Sampai 1.0.0, breaking change berada di sini. |
Major — 0.x → 1.0.0 | Titik saat caret mulai membawa compatibility promise seperti package stable pada umumnya. |
Setelah 1.0.0, breaking change harus menjadi major release.
Apa yang tercakup dalam version promise ditentukan .gitattributes: file yang di-export-ignore tidak ada di installed package dan karena itu bukan bagian dari shipped API. Lihat Versioning policy. Ringkasnya, src, config, database, stubs, dan resources adalah shipped surface. Published Vue file berhenti menjadi milik package setelah disalin ke application.
Tidak ada constant Panel::VERSION. Version selalu dibaca dari Composer:
use Composer\InstalledVersions;
InstalledVersions::getPrettyVersion('chocoalano/panel'); // '0.1.2'
InstalledVersions::isInstalled('chocoalano/panel'); // true2
3
4
Hard-coded version mudah terlupakan. Package yang melaporkan 1.2.0 padahal 1.4.1 terinstall lebih buruk daripada package yang tidak melaporkan version sama sekali.
Changelog
CHANGELOG.md menyatakan contract-nya sendiri:
# Changelog
All notable changes to `panda-panel` are documented here.
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project
adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]2
3
4
5
6
7
8
Perubahan baru ditambahkan di bawah ## [Unreleased] menggunakan section Keep a Changelog berikut:
| Section | Untuk |
|---|---|
### Security | Vulnerability yang diperbaiki. Selalu diletakkan pertama. |
### Added | Capability baru yang sebelumnya tidak ada. |
### Changed | Behavior berbeda dari API yang sama. |
### Fixed | Defect / bug fix. |
### Removed | Capability yang dihapus. |
Style changelog adalah prose, bukan sekadar daftar nama fitur. Entry dimulai dengan kalimat bold yang menjelaskan perubahan dari sudut pandang pembaca, lalu menjelaskan apa yang salah dan mengapa fix tersebut benar:
- **A schema that cannot mean what it says is now refused, loudly.** Six declaration mistakes were
silent, and all six produced wrong behaviour rather than no behaviour. `PanelSchemaException`
covers them, and every message names the offending name and the fix:2
3
Jika application perlu melakukan edit, tulis Breaking: di bullet yang sama dan tunjukkan dokumentasi fix:
**Breaking:** these throw where they previously did nothing. An application carrying one of them
has a bug today and will get an exception at schema-build time after upgrading — which is at boot
or on first render, so a test suite finds it before a user does.2
3
Jika behavior berubah tanpa memerlukan migration tetapi dapat mengejutkan pengguna, gunakan Behaviour change:. Kedua istilah sudah digunakan sehingga pembaca dapat mencari perubahan berdasarkan kata tersebut.
Setiap breaking entry juga masuk ke docs/upgrading/breaking-changes.md dengan fix terkecil yang harus dilakukan. Changelog menjelaskan apa yang terjadi; breaking-changes page menjelaskan apa yang harus dilakukan.
Menutup section untuk release
Saat release, ubah heading dan buka block [Unreleased] baru:
## [Unreleased]
## [0.1.3] - 2026-08-162
3
Saat melakukan ini:
- Gabungkan duplicate section heading. Jika ada dua
### Fixed, satukan menjadi satu section. - Urutkan section
Security,Added,Changed,Fixed,Removed, sehingga security selalu terlihat pertama oleh orang yang melakukan upgrade.
Saat ini file tidak memiliki link-reference definitions di bagian bawah dan released-version heading belum digunakan secara konsisten; tag sebelumnya dipotong langsung dari [Unreleased]. Menambahkan compare link per version adalah improvement yang wajar, tetapi jangan mengasumsikan link tersebut sudah tersedia.
CHANGELOG.md di-export-ignore, jadi tidak tersedia di vendor/chocoalano/panel/CHANGELOG.md. Changelog dibaca dari repository.
File yang ikut release
.gitattributes menentukan isi archive:
# Kept out of the distributed package. `src`, `config`, `database`, `stubs`
# and `resources` are what an application installs; everything else is how
# this repository is developed.
/.github export-ignore
/.ai export-ignore
/.claude export-ignore
/.codex export-ignore
/docs export-ignore
/examples export-ignore
/integration export-ignore
/tests export-ignore
/frontend export-ignore
/.editorconfig export-ignore
/.gitattributes export-ignore
/.gitignore export-ignore
/CHANGELOG.md export-ignore
/phpstan.neon export-ignore
/phpunit.xml export-ignore
/pint.json export-ignore
/package-lock.json export-ignore
/tsconfig.json export-ignore
/vite.config.ts export-ignore
/eslint.config.js export-ignore
/.prettierrc.json export-ignore
/.prettierignore export-ignore2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package.json sengaja tidak ada dalam list tersebut, walaupun terlihat seperti development file. Alasannya dijelaskan pada section berikut.
Jika menambahkan config file baru pada repository root, tambahkan juga export-ignore atau file tersebut akan ikut setiap Composer dist archive.
Periksa isi archive sebelum push tag:
git archive HEAD | tar -t | head -40
git archive HEAD | tar -t | wc -l2
git archive menghormati export-ignore dengan cara yang sama seperti Composer dist archive, sehingga hasilnya adalah representasi sebenarnya, bukan perkiraan.
package.json wajib ikut dist
PandaPanel\Support\Installer\FrontendRequirements membaca package.json repository ini saat runtime dari dalam vendor/ agar installer dapat memberi tahu application npm package yang diperlukan published component:
public static function npmManifestPath(): string
{
return dirname(__DIR__, 3).'/package.json';
}
public static function npmPackages(): array
{
$manifest = self::npmManifestPath();
if (! File::exists($manifest)) {
return [];
}
// ... baca `dependencies`, kembalikan pasangan 'name@range' ...
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
Ini keputusan yang sengaja dibuat agar daftar dependency hanya memiliki satu source of truth. php artisan panel:install mencetak daftar tersebut, sehingga installer dan frontend build tidak dapat drift — selama manifest benar-benar tersedia.
Pernah terjadi /package.json export-ignore berada di .gitattributes. Pada install melalui Composer dist archive, npmPackages() tidak menemukan manifest dan menghasilkan []. missingNpmPackages() juga menghasilkan [], sehingga panel:install melaporkan seolah tidak ada dependency yang hilang. Failure baru muncul kemudian saat npm run build gagal pada module specifier. Error itu benar, tetapi terlalu jauh dari penyebab sebenarnya.
Fix sekarang memiliki tiga lapis:
.gitattributestidak lagi meng-export-ignorepackage.jsondan memiliki komentar yang menjelaskan alasannya.Negative/DistributionTestmemeriksa attribute secara langsung —git check-attr export-ignore -- package.jsonharus menghasilkanunspecified, sedangkanpackage-lock.jsonharusset.FrontendRequirements::hasNpmManifest()membedakan dua kondisi empty list. "Tidak ada yang hilang" berbeda dengan "manifest tidak dapat dibaca". Installer sekarang melaporkan kondisi kedua sebagai packaging fault.
Sebelum tagging:
git archive HEAD | tar -t | grep package.json # wajib mencetak package.jsonpackage-lock.json tetap tidak ikut dist karena tidak dibaca runtime dan application harus menginstall berdasarkan range, bukan resolution milik repository ini.
Sisa frontend toolchain memang benar-benar development-only. Lihat Frontend toolchain.
Pelajaran dari rename package
PandaPanel\Plugins\PluginCompatibility membaca version framework berdasarkan package name:
private const PACKAGE = 'chocoalano/panel';Ketika Composer package pernah di-rename, constant tersebut sempat tetap menggunakan nama lama panda-panel. InstalledVersions::getPrettyVersion() melempar jika package name tidak ada; class menafsirkan kondisi tersebut sebagai "tidak terinstall sebagai package" lalu menghasilkan null. Version null membuat constraint plugin dilewati. Akibatnya seluruh requiresPanel plugin tidak lagi benar-benar diperiksa sejak rename.
PluginTest sekarang membandingkan constant tersebut dengan field name di composer.json. General lesson-nya: nilai yang merupakan copy dari sesuatu dalam composer.json harus memiliki test yang membandingkan kedua source. Saat ini ada dua contoh: package constant dan npm dependency list.
Rename package di masa depan juga harus mengikuti Package name migration, karena Composer tidak dapat mengikuti rename secara otomatis.
Sebelum membuat tag
composer validate --strict --no-check-publish # validasi composer.json sebagai manifest
composer ci # pint --test, phpstan, pest
npm run ci # prettier, eslint, vue-tsc, vite build
git archive HEAD | tar -t | grep package.json # wajib ada
git archive HEAD | tar -t | grep 'docs/' # wajib tidak menghasilkan apa pun2
3
4
5
6
Tidak ada command panel:icons --check yang dijalankan langsung di repository ini karena repository bukan Laravel application dan tidak memiliki binary artisan. IconRegistryTest menangani check tersebut sebagai bagian composer ci. Di application pengguna ekuivalennya adalah php artisan panel:icons --check.
Setelah changelog siap, buat annotated tag:
git tag -a v0.1.3 -m "v0.1.3"
git push origin v0.1.32
Annotated tag (-a) menyimpan date dan author. Composer membaca nama tag dan menghapus prefix v, sehingga v0.1.3 dan 0.1.3 memiliki version semantics yang sama; prefix v hanya convention repository ini.
Catatan
- Tag adalah release. Tidak ada build step, artifact upload, atau
distdirectory. Packagist membaca tag. composer.locktidak di-commit, jadi tidak ada lockfile yang perlu diupdate saat release. CI selalu resolve ranges baru.minimum-stabilityadalahstabledanprefer-stabletrue. Application tidak akan menarik dev/beta dependency melalui package ini tanpa constraint yang memang mengizinkannya.- Minor pada
0.xboleh breaking. Sampai1.0.0, caret constraint adalah protection utama. Constraint>=ataudev-mainsecara sengaja menghapus protection tersebut. - Published frontend memiliki version lifecycle terpisah.
composer updatemengubahvendor/chocoalano/panel, bukanresources/js/panelyang sudah menjadi milik application..panel-assets.jsondanphp artisan panel:assetsmenangani lifecycle kedua ini. Lihat Asset manifest. UPDATE.mddi-gitignore. File tersebut adalah working note, sehingga prosedur release juga didokumentasikan di sini.- Jangan menghapus atau memindahkan ADR saat release. ADR yang superseded tetap disimpan dan hanya statusnya yang berubah.
Lihat juga
- Versioning policy — surface yang dijamin version per constraint
- Release checklist
- Breaking changes — lokasi breaking entry selain changelog
- Changelog — organisasi release notes
- Package name migration
- Asset manifest — versioning published frontend
- Frontend toolchain — development file lain yang tidak ikut distribusi
- Pull requests — apa yang harus masuk
mainsebelum release - Packagist troubleshooting