Tulis plugin semantic-release custom sesuai kebutuhan organisasi, manfaatkan @semantic-release/exec untuk menjalankan script eksternal, serta integrasikan publish dengan artifact repository atau private registry.

Di episode 15 kita mengelola beberapa branch rilis. Plugin bawaan semantic-release menangani analisis commit, changelog, npm, dan GitHub — sekitar 80 persen kebutuhan. Namun organisasi sering punya kebutuhan khusus: menandatangani artifact, mengunggah ke registry internal, atau memanggil service lain setelah rilis.
Episode ini membahas custom plugins & extensions: bagaimana semantic-release mengeksekusi plugin lewat lifecycle hooks, cara menulis plugin sederhana, memakai @semantic-release/exec untuk perintah shell tanpa menulis kode, dan integrasi dengan private registry.
Setiap plugin adalah objek yang mengekspos satu atau lebih lifecycle hooks. Semantic-release menjalankannya berurutan:
verifyConditions — memvalidasi prasyarat sebelum rilis dimulai.analyzeCommits — menentukan jenis rilis (major/minor/patch).verifyRelease — cek terakhir sebelum versi dikunci.generateNotes — membuat release notes.prepare — menyiapkan file sebelum di-commit (bump versi, changelog).publish — mengunggah artifact.addChannel — menambahkan versi ke channel lain.success — dipanggil setelah rilis berhasil.fail — dipanggil jika terjadi kesalahan.Setiap hook menerima pluginConfig (opsi dari array config) dan context (berisi versi, commits, logger, dan lainnya).
Plugin hanyalah module yang mengekspor fungsi-fungsi tersebut. Contoh plugin yang memvalidasi ukuran artifact dan menulis catatan tambahan:
module.exports = {
async verifyConditions(pluginConfig, context) {
const { logger } = context;
const max = pluginConfig.maxAssetSizeMB || 100;
logger.log('Memastikan ukuran artifact di bawah %d MB', max);
},
async analyzeCommits(pluginConfig, context) {
const { commits } = context;
const breaking = commits.some((c) => c.message.includes('BREAKING CHANGE'));
return breaking ? 'major' : null;
},
async generateNotes(pluginConfig, context) {
const { nextRelease } = context;
return 'Rilis ini ditandatangani oleh pipeline internal.';
},
async publish(pluginConfig, context) {
const { nextRelease, logger } = context;
logger.log('Mengunggah artifact versi %s', nextRelease.version);
return { name: nextRelease.version, url: 'https://artifact.internal.example.com' };
},
};Poin penting:
'major' dari analyzeCommits, atau URL dari publish) atau melempar error untuk menghentikan pipeline.context menyediakan nextRelease, commits, logger, lastRelease, dan lainnya.release.config.cjs.module.exports = {
branches: ['main'],
plugins: [
'@semantic-release/commit-analyzer',
'@semantic-release/release-notes-generator',
['./plugins/cek-artifact.js', { maxAssetSizeMB: 100 }],
'@semantic-release/npm',
'@semantic-release/github',
],
};Tidak semua kebutuhan butuh plugin penuh. @semantic-release/exec menjalankan perintah shell pada titik-titik lifecycle yang kalian pilih:
['@semantic-release/exec', {
verifyConditionsCmd: 'node ./scripts/cek-license.js',
prepareCmd: 'node ./scripts/build-artifact.js',
publishCmd: 'npm publish --registry ${NPM_CONFIG_REGISTRY}',
successCmd: 'node ./scripts/notify.js ${nextRelease.version}',
}],Perintah yang disediakan dapat memakai variabel context — misalnya nomor versi nextRelease.version dan catatan nextRelease.notes. Untuk hook publish, skrip harus mencetak output JSON ke stdout — semantic-release memakainya sebagai hasil publish:
{"name":"1.5.0","url":"https://artifact.internal.example.com/pkg/1.5.0"}Instal dengan bun add -D @semantic-release/exec.
Warning
Shell command dalam publishCmd dijalankan dengan environment CI. Pastikan semua nilai yang sensitif masuk lewat environment variable, bukan di-hardcode di konfigurasi. Jangan pula membuat publishCmd mencetak teks bebas — hasilnya harus JSON yang valid agar plugin lain tidak gagal membaca hasil publish.
Saat mengelola registry internal (misal Verdaccio, Artifactory, atau GitLab Package Registry), cukup arahkan npm ke registry tersebut lewat env:
export NPM_CONFIG_REGISTRY=https://npm.internal.example.com
export NPM_TOKEN=<nilai dari secret CI>
npx semantic-release --dry-run --no-ciNPM_CONFIG_REGISTRY dan NPM_TOKEN adalah dua env yang paling sering dipakai untuk private registry. Pastikan keduanya masuk ke GitHub Actions secrets dan ditambahkan ke env pada step release. Dengan kombinasi plugin custom dan exec, pipeline release bisa diarahkan ke tempat mana pun — asalkan ada endpoint yang bisa menerima artifact.
Tip
Mulailah dari @semantic-release/exec untuk kebutuhan satu-dua perintah, dan tingkatkan ke plugin custom ketika logika sudah rumit, butuh diuji unit, atau dipakai ulang di banyak repository. Plugin custom yang diuji lebih mudah dirawat daripada shell command yang panjang.
Rekap episode 16:
@semantic-release/exec menjalankan script shell tanpa menulis plugin — dengan output JSON untuk publish.NPM_CONFIG_REGISTRY dan NPM_TOKEN.exec.Dengan plugin yang bisa diprogram, release automation sekarang bisa menyesuaikan diri dengan organisasi. Di episode 17 kita membahas Migrasi Repository Existing ke Conventional Commits — mengadopsi gaya commit, menyiapkan commitlint dan husky, serta menangani history lama tanpa conventional commits. Sampai jumpa!