Checklist Release
Halaman ini mencakup seluruh langkah antara kondisi "branch main sudah hijau" dan "tag release sudah tersedia", dalam urutan yang memang harus dijalankan. Gunakan checklist ini sebelum membuat tag untuk chocoalano/panel, dan sebagai template saat merilis plugin atau fork. Sebagian besar langkah bersifat umum, tetapi ada dua pemeriksaan yang khusus untuk package ini dan keduanya tidak dapat dijamin hanya oleh test suite yang lulus.
Contoh minimal yang dapat langsung digunakan
composer ci # pint --test, phpstan, pest
npm run ci # prettier, eslint, vue-tsc, vite build
git archive HEAD | tar -t | awk -F/ '{print $1}' | sort -u # what a composer install gets
git tag -a v0.1.3 -m "v0.1.3"
git push origin v0.1.32
3
4
5
6
7
Di antara command kedua dan ketiga terdapat dua pekerjaan manual yang tidak dapat dilakukan command: menulis entry CHANGELOG dan menambahkan bagian yang sesuai pada upgrade guide.
1. Verification loop
Dua command berikut menjalankan seluruh pemeriksaan CI, kecuali matrix lintas version. Script-nya dideklarasikan di repository sehingga command lokal tidak dapat drift dari pipeline:
"scripts": {
"test": "vendor/bin/pest",
"test-coverage": "vendor/bin/pest --coverage",
"format": "vendor/bin/pint",
"format-check": "vendor/bin/pint --test",
"analyse": "vendor/bin/phpstan analyse --memory-limit=1G",
"ci": ["@format-check", "@analyse", "@test"]
}2
3
4
5
6
7
8
"scripts": {
"lint": "eslint resources/js frontend --max-warnings=0",
"lint:fix": "eslint resources/js frontend --fix",
"format": "prettier --write resources/js frontend resources/css",
"format:check": "prettier --check resources/js frontend resources/css",
"typecheck": "vue-tsc --noEmit -p tsconfig.json",
"build": "vite build",
"ci": "npm run format:check && npm run lint && npm run typecheck && npm run build"
}2
3
4
5
6
7
8
9
composer ci
npm run ci2
Kedua urutan menempatkan failure yang paling murah dan paling spesifik terlebih dahulu: formatting, lalu lint atau static analysis, kemudian type checking, dan terakhir code yang benar-benar dijalankan atau dibuild. Type error biasanya memberi pesan yang jauh lebih berguna daripada error bundler untuk masalah yang sama.
Saat sedang memperbaiki masalah tertentu, jalankan pemeriksaan secara individual:
composer format # pint, writing
composer analyse # phpstan at the memory limit CI uses
composer test # the whole suite
vendor/bin/pest --filter=PluginTest # one file
npm run lint:fix
npm run typecheck2
3
4
5
6
Tambahan yang dijalankan CI
.github/workflows/tests.yml menjalankan pemeriksaan yang sama pada kombinasi environment yang tidak mungkin direproduksi satu mesin secara bersamaan:
| Job | Yang dijalankan | Matrix | Blocking |
|---|---|---|---|
test | vendor/bin/pest | PHP 8.2/8.3/8.4 × Laravel 12/13 × prefer-lowest/prefer-stable, kecuali kombinasi yang tidak didukung Laravel 13 — total 10 job | ya |
static-analysis | vendor/bin/phpstan analyse | kedua ujung supported range | ya |
code-style | vendor/bin/pint --test | satu job | ya |
frontend | format:check, lint, typecheck, build | Node 20, 22, 24 | ya |
frontend-latest | typecheck, build menggunakan version teratas dari setiap npm range | satu job | tidak — continue-on-error |
Tunggu semua job selesai sebelum membuat tag. prefer-lowest khususnya menangkap pemanggilan method yang baru ditambahkan pada minor release padahal constraint package tidak mewajibkan minor tersebut. Ini adalah bagian matrix yang tidak pernah benar-benar direproduksi oleh composer ci lokal. Rincian lengkap tersedia di CI matrix.
Empat test yang memang dibuat untuk gagal saat release bermasalah
Sebagian besar test suite memeriksa perilaku framework. Empat assertion berikut justru memeriksa integritas package, dan masing-masing melindungi jenis kesalahan yang sangat mungkin terjadi saat release:
| Test | Yang dikunci |
|---|---|
PluginTest — "looks up its own version under the name composer knows it by" | PluginCompatibility::PACKAGE harus cocok dengan name di composer.json. Rename yang lupa memperbarui constant dapat menonaktifkan seluruh plugin constraint secara diam-diam. |
AssetUpgradeTest — "reads every real shipped file as current in this repository" | Publish map harus cocok dengan tree. File baru di resources/js yang tidak tercakup PublishedAssets::map() dapat dipublish tetapi tidak pernah terdeteksi sebagai out of date. |
FrontendContractTest | Host-module list harus cocok dengan import pada published tree, dan tiga grid class table harus cocok dengan clamp di PHP. |
StylingTest | overflow-x-clip pada content wrapper — overflow-x-hidden menghitung axis lain menjadi auto dan dapat menangkap seluruh position: sticky di dalamnya tanpa gejala yang jelas. |
Kesalahan seperti ini tidak dapat diperbaiki setelah tag release sudah diterbitkan.
2. Tulis entry CHANGELOG
CHANGELOG.md mengikuti Keep a Changelog. Pada saat release, ## [Unreleased] diubah menjadi version beserta tanggal, lalu section ## [Unreleased] baru yang kosong ditambahkan di atasnya.
## [Unreleased]
## [0.1.3] - 2026-08-15
### Security
- …
### Added
- …
### Fixed
- …2
3
4
5
6
7
8
9
10
11
12
13
14
15
Konvensi internal pada setiap section:
- Awali dengan lead tebal yang menjelaskan perubahan yang terlihat pengguna, lalu jelaskan alasannya. Menyebut failure yang digantikan membuat entry mudah ditemukan di kemudian hari karena developer biasanya mencari berdasarkan error string yang mereka lihat.
Securityditempatkan paling awal. Informasi keamanan yang berada jauh di bawah berisiko tidak dibaca.- Perubahan yang membutuhkan edit harus menyatakannya secara eksplisit, menggunakan marker seperti
**Breaking:**atau**Behaviour change:**, lalu menunjuk ke tempat perbaikannya dijelaskan lengkap.
Cara membaca file dari sisi pengguna — termasuk fakta bahwa breaking change dapat muncul dalam kategori apa pun — dijelaskan di Changelog.
grep -n '^### ' CHANGELOG.md # the categories in this release
grep -n '\*\*Breaking:\|\*\*Behaviour change:' CHANGELOG.md2
3. Tambahkan bagian upgrade guide untuk setiap breaking change
Invariant-nya: setiap entry yang ditandai breaking harus memiliki section yang sesuai di upgrade guide. Changelog menjelaskan apa yang berubah dan mengapa; upgrade guide menjelaskan apa yang rusak dan command atau edit apa yang harus dilakukan. Release yang hanya menambahkan changelog tetapi tidak memberikan langkah migrasi berarti mengirim perubahan yang tidak dapat ditindaklanjuti pengguna.
Dua file yang harus diperbarui:
| File | Yang harus ditambahkan |
|---|---|
docs/upgrading/breaking-changes.md | Section ### bernomor berisi Apa yang berubah, Apa yang rusak, dan perubahan terkecil yang memperbaikinya — lengkap dengan code |
docs/upgrading/upgrade-guide.md | Row pada version-specific notes, termasuk penanda apakah perubahan bersifat silent |
Section yang masih mengatakan "consider" belum selesai. Jika tidak melakukan apa pun tetap membuat aplikasi berjalan benar, perubahan tersebut bukan breaking change dan cukup masuk changelog.
# Every breaking marker in the changelog should have a home in the guide.
grep -c '\*\*Breaking:\|\*\*Behaviour change:' CHANGELOG.md
grep -c '^### [0-9]' docs/upgrading/breaking-changes.md2
3
Ada dua jenis perubahan yang membutuhkan kalimat tambahan dan sering terlupakan:
- Perubahan pada published file.
resources/js/**danresources/css/panda-panel.cssadalah file milik aplikasi setelah dipublish, sehinggacomposer updatetidak membawa fix tersebut. Dokumentasi harus menyebutphp artisan panel:assets --updatedannpm run build, serta mengarah ke Menyelesaikan konflik asset untuk aplikasi yang sudah mengedit file terkait. - Config key baru.
mergeConfigFrom()membuat config lama yang sudah dipublish tetap mendapatkan default baru dari package. Karena itu dokumentasi seharusnya menjelaskan cara opt out, bukan sekadar menyuruh pengguna menambahkan key baru.
4. Pastikan dist berisi semua file yang dibutuhkan installer
Ini adalah pemeriksaan yang tidak dilakukan test suite. Test berjalan langsung dari repository — tempat semua file tersedia — sedangkan aplikasi menerima archive tempat .gitattributes telah menghapus file tertentu.
git archive HEAD | tar -t | awk -F/ '{print $1}' | sort -uLICENSE.md
README.md
composer.json
config
database
resources
src
stubs2
3
4
5
6
7
8
Itulah tree yang benar-benar diterima oleh composer require chocoalano/panel. File lainnya dihapus melalui export-ignore:
/.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.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
Ajukan tiga pertanyaan terhadap listing tersebut, dalam urutan berikut.
Apakah semua file yang dibaca runtime masih ikut dikirim? Directory utama yang dibutuhkan aplikasi adalah src, config, database, dan resources, ditambah stubs untuk generator. Command make:panel* membaca stub milik package dan dapat fallback ke salinan yang dipublish aplikasi:
git archive HEAD | tar -t | grep -c '^src/'
git archive HEAD | tar -t | grep '^stubs/'
git archive HEAD | tar -t | grep -c '^resources/js/'2
3
Apakah release ini menambahkan top-level directory baru? Directory baru ikut terkirim secara default, yang merupakan arah aman. Masalah biasanya terjadi pada kebalikannya: directory baru ditambahkan di bawah path yang sudah export-ignore, atau development directory baru lupa ditambahkan ke .gitattributes sehingga justru ikut terkirim.
Apakah code di src/ membaca file yang tidak ikut masuk archive? Failure mode ini perlu diperiksa secara eksplisit karena dapat bersifat silent. PandaPanel\Support\Installer\FrontendRequirements, misalnya, membaca package.json milik package untuk mendapatkan daftar npm dependency:
$manifest = dirname(__DIR__, 3).'/package.json';
if (! File::exists($manifest)) {
return [];
}2
3
4
5
Jika /package.json diberi export-ignore, file tersebut tidak tersedia pada aplikasi yang diinstal dari dist. Akibatnya npmPackages() mengembalikan [], lalu panel:install tidak melaporkan dependency npm yang kurang — output-nya sama seperti aplikasi yang sudah memiliki semuanya. Install dengan --prefer-source melakukan clone repository sehingga file tetap ada dan masalah ini tidak terlihat. Apakah trade-off tersebut memang disengaja adalah keputusan release; git archive HEAD | tar -t membuat keputusan itu terlihat.
grep -rn "dirname(__DIR__" src/ | grep -v 'src/Support/Installer/PublishedAssets.php'Setelah itu, lakukan instalasi nyata. Listing archive hanya membuktikan isi box; hanya instalasi yang dapat membuktikan box tersebut bekerja.
{
"repositories": [
{ "type": "path", "url": "../panda-panel", "options": { "symlink": false } }
]
}2
3
4
5
composer require chocoalano/panel:@dev
php artisan panel:install
php artisan panel:assets
npm install && npm run build2
3
4
"symlink": false penting. Path repository yang menggunakan symlink sebenarnya menunjuk ke repository penuh, sehingga docs/, tests/, dan package.json tetap tersedia dan tidak menguji kondisi dist. Copy lebih dekat dengan kondisi nyata, walaupun composer archive dan git archive tetap menjadi cara yang benar-benar mengikuti export-ignore.
5. Tentukan version number
composer.json sengaja tidak memiliki key version. Tag Git adalah version, dan menyimpan nomor yang sama di dua tempat hanya menciptakan kemungkinan keduanya berbeda. Composer menurunkan version dari tag dan melaporkan 1.0.0+no-version-set untuk checkout tanpa version, yaitu salah satu kondisi yang diperlakukan PluginCompatibility sebagai "tidak ada version yang dapat diperiksa".
git tag # v0.1.0, v0.1.1, v0.1.2
composer show chocoalano/panel --all # what Packagist knows about2
Package masih berada pada seri 0.x, di mana semantic versioning memiliki aturan berbeda dari setelah 1.0:
| Jenis perubahan | Selama 0.x | Setelah 1.0.0 |
|---|---|---|
| Breaking | minor — 0.1.2 → 0.2.0 | major |
| Surface baru, tidak mematahkan apa pun | minor | minor |
| Hanya bug fix | patch — 0.1.2 → 0.1.3 | patch |
Konsekuensinya terhadap constraint aplikasi: ^0.1 berarti >=0.1.0 <0.2.0. Jadi 0.2.0 harus dipilih secara eksplisit melalui composer require chocoalano/panel:^0.2, sehingga pengguna tidak menerima breaking release tanpa sadar. Detail lain tentang makna version dibahas di Kebijakan versioning.
Ada tiga pertanyaan tentang version yang harus diputuskan pada tahap ini.
Apakah dependency range pada composer.json berubah?
"require": {
"php": "^8.2",
"laravel/framework": "^12.0|^13.0",
"inertiajs/inertia-laravel": "^3.0",
"laravel/fortify": "^1.37.2",
"symfony/finder": "^7.0|^8.0"
}2
3
4
5
6
7
Memperlebar range tidak mematahkan aplikasi. Mempersempit range adalah breaking change karena aplikasi yang berada pada version yang dihapus tidak lagi dapat me-resolve package. Pada seri 0.x, perubahan seperti ini membutuhkan minor bump, penjelasan di Compatibility, serta perubahan pada CI matrix agar deklarasi support dan kombinasi yang diuji tetap konsisten.
Apakah npm range pada package.json berubah? File tersebut tidak selalu ikut diinstal, tetapi daftar di dalamnya tetap menjadi sumber yang dibaca installer dan dokumentasi, sedangkan component dibuild oleh Vite milik aplikasi terhadap dependency tree aplikasi. Perubahan range tetap merupakan compatibility change meskipun Composer sendiri tidak mengetahuinya.
Plugin milik siapa yang akan ditolak version ini? Constraint requiresPanel dievaluasi terhadap version yang dilaporkan Composer untuk chocoalano/panel. Bump 0.1 → 0.2 akan menolak setiap plugin dengan ^0.1, dan penolakan terjadi saat boot sehingga seluruh route dan Artisan command gagal sampai diselesaikan. Ini adalah perilaku yang dirancang dan alasan version bump harus dilakukan dengan sengaja:
use PandaPanel\Exceptions\PanelRegistrationException;
use PandaPanel\Plugins\PluginCompatibility;
// What an application with a ^0.1 plugin will get from 0.2.0.
expect(fn () => PluginCompatibility::assert(new BillingPlugin, 'admin', '0.2.0'))
->toThrow(PanelRegistrationException::class);2
3
4
5
6
composer validate --strict # ./composer.json is valid6. Buat tag dan push
git tag -a v0.1.3 -m "v0.1.3"
git push origin v0.1.32
Packagist membaca tag, lalu menerbitkan version tanpa prefix v. Karena itu v0.1.3 menjadi 0.1.3. Tidak ada perubahan yang perlu dilakukan pada composer.json.
Setelah tag tersedia di Packagist, version pada dasarnya permanen. Tag memang dapat dihapus, tetapi aplikasi yang sudah pernah me-resolve version tersebut sudah menyimpannya di composer.lock. Membuat 0.1.4 lebih aman daripada menghapus dan membuat ulang 0.1.3.
7. Verifikasi dari luar repository
composer show chocoalano/panel # the version an install now resolves
composer why chocoalano/panel2
Pada scratch application:
composer create-project laravel/laravel scratch
cd scratch
composer require chocoalano/panel
php artisan panel:install
php artisan panel:user
npm install && npm run build
php artisan serve2
3
4
5
6
7
Kemudian periksa tiga hal yang hanya dapat dijawab browser: sidebar menampilkan resource yang diharapkan, icon berhasil dirender, dan browser console bersih.
Satu hal perlu diperiksa secara spesifik pada aplikasi yang benar-benar diinstal karena kondisi ini tidak dapat divalidasi dari repository:
use Composer\InstalledVersions;
InstalledVersions::getPrettyVersion('chocoalano/panel'); // '0.1.3', not null2
3
Jika lookup tersebut menghasilkan null, PluginCompatibility::PACKAGE tidak lagi cocok dengan composer.json, sehingga seluruh plugin constraint di semua instalasi dapat nonaktif secara diam-diam. Lihat Migrasi nama package untuk failure mode yang pernah terjadi sebelumnya.
Checklist lengkap
| # | Langkah | Command |
|---|---|---|
| 1 | Pemeriksaan PHP | composer ci |
| 2 | Pemeriksaan frontend | npm run ci |
| 3 | Semua kombinasi CI hijau | — |
| 4 | composer.json tetap valid | composer validate --strict |
| 5 | CHANGELOG: Unreleased menjadi version, lalu buat Unreleased baru di atasnya | — |
| 6 | Breaking entry memiliki section di Breaking changes | — |
| 7 | Tambahkan row version-specific di Upgrade guide | — |
| 8 | Dist berisi seluruh file yang dibutuhkan installer | git archive HEAD | tar -t |
| 9 | Lakukan satu instalasi dari path repository | composer require chocoalano/panel:@dev |
| 10 | Tentukan version berdasarkan Versioning | — |
| 11 | Buat dan push tag | git tag -a v0.1.3 -m "v0.1.3" && git push origin v0.1.3 |
| 12 | Verifikasi dari scratch application | composer require chocoalano/panel |
Hal yang perlu diperhatikan
- Test suite hijau tidak membuktikan dist benar. Test berjalan di repository yang masih memiliki
package.json,docs/, danfrontend/.git archive HEAD | tar -tadalah cara untuk melihat apa yang benar-benar diterima aplikasi. composer.jsonsengaja tidak memiliki keyversion. Tag adalah version. Menambahkan key tersebut membuat ada dua source version yang pada akhirnya dapat berbeda.- Heading changelog bukan release. Composer me-resolve tag, bukan heading di Markdown.
CHANGELOG.mddiberiexport-ignore, sehingga release note dibaca di repository atau release page, bukan darivendor/.--prefer-sourcedapat menyembunyikan kesalahan export. Mode ini melakukan clone alih-alih unpack archive, sehingga fileexport-ignoretetap ada dan code yang bergantung pada file tersebut tampak bekerja.- Minor release pada
0.xboleh breaking dan dapat menolak plugin.requiresPanel: '^0.1'tidak lagi cocok dengan0.2.0, dan refusal terjadi saat boot untuk seluruh aplikasi. Ini memang perilaku yang dimaksud, tetapi tetap harus diketahui sebelum membuat tag. - Mempersempit dependency range adalah breaking change walaupun tidak ada perubahan code.
panel:assetsharus membacacurrentuntuk setiap file pada repository ini. Status lain berarti publish map dan tree sudah drift;AssetUpgradeTestdibuat khusus untuk menangkap kondisi tersebut.- Membuat ulang tag lebih buruk daripada membuat patch release baru. Aplikasi yang sudah resolve tag lama telah menyimpannya di lockfile.
Lihat juga
- Changelog — file yang diedit checklist ini dan cara membacanya
- Breaking changes — section yang wajib ditambahkan pada breaking release
- Panduan upgrade — prosedur yang akan dijalani aplikasi setelah release
- Kebijakan versioning — apa yang dijanjikan version number dan apa yang dicakupnya
- Migrasi nama package — rename dan compatibility check yang pernah terpengaruh
- Manifest asset, Menyelesaikan konflik asset
- CI matrix, Testing setup, Frontend contract tests
- Compatibility, Requirements
panel:install,panel:assets,panel:plugins, publish tags- Plugin compatibility
- Frontend build, Composer di production