Menjawab kebutuhan integrasi lint-staged, Danger, dan CI Matrix

Integrasi lint-staged, Danger, dan CI Matrix memastikan monorepo Node memberikan lintasan feedback terurut: pre-commit di lokal, quality gate di PR, dan pemeriksaan lengkap di pipeline. Kombinasi ini menghindari lint ganda, memperjelas batas tanggung jawab tiap lapisan, serta menjaga waktu release tetap cepat.

Artikel ini memandu langkah praktis: konfigurasi lint-staged, Dangerfile, matriks lint/test di GitHub Actions atau GitLab CI, serta aturan otomatisasi feedback pada level lokal, pull request, dan release.

Mengapa kombinasi lint-staged, Danger, dan CI Matrix diperlukan

Monorepo seringkali memiliki banyak paket, lint rule berbeda, dan rangkaian tes panjang. Tanpa strategi berlapis, developer menunggu CI penuh hanya untuk mendapati lint lokal yang terlewat. lint-staged membantu menangkap masalah paling dasar saat commit, Danger menjaga kualitas PR sebelum merge, sedangkan CI Matrix memvalidasi lint dan test untuk semua kombinasi paket atau versi.

Strategi ini memecah tanggung jawab:

  • Lokal (lint-staged): lint/format terbatas pada file staged agar commit tidak gagal karena masalah trivial.
  • PR (Danger): memastikan pola PR (deskripsi, label, testing minimal) dan memberi komentar otomatis jika ada pelanggaran.
  • CI Matrix: jalankan lint atau test sesuai paket, target environment, atau versi Node; hasilnya menjadi jaminan bagi merge.

Konfigurasi lint-staged di monorepo Node

Lint-staged menjalankan perintah hanya pada file yang akan dikomit. Di monorepo, kita bisa mengarahkan ke area tertentu untuk menghindari lint ganda. Contoh konfigurasi dalam package.json:

"lint-staged": {
  "packages/*/{src,__tests__}/**/*.{ts,js}": [
    "pnpm lint --filter ${PWD}/packages/*",
    "pnpm test --filter ${PWD}/packages/* --runInBand"
  ]
}

Cara ini memastikan lint-staged memanggil skrip package-filter dengan path file staged, bukan seluruh monorepo. Jangan panggil lint global; gunakan pnpm --filter agar lint terisolasi. Jika terjadi lint ganda, kurangi perintah lint-staged dan biarkan CI Matrix mengelola lint paket penuh.

Danger sebagai quality gate PR

Danger berjalan di CI dan memberi komentar otomatis atau memblokir PR jika syarat belum terpenuhi. Berikut contoh Dangerfile.js sederhana:

import { danger, warn, fail } from "danger";
const modifiedPackages = danger.git.modified_files.filter((file) => file.startsWith("packages/"));
if (modifiedPackages.length === 0) {
  fail("PR harus menyentuh setidaknya satu paket agar review relevan.");
}
if (!danger.github.pr.body?.includes("## Testing")) {
  warn("Tambahkan bagian '## Testing' untuk menjelaskan langkah verifikasi.");
}
if (danger.github.pr.labels?.length === 0) {
  warn("Tambahkan label terkait scope agar reviewer tahu konteks.");
}

Danger dapat memeriksa artifacts, mengonfirmasi lint-staged berjalan (misalnya dengan memeriksa script bernama), atau memverifikasi versi Node target. Jika ada aturan lain seperti file CHANGELOG wajib, tambahkan di Dangerfile.

Membangun CI Matrix lint/test di GitHub Actions

CI Matrix memberi kesempatan menjalankan lint/test untuk kombinasi paket dan versi Node, sekaligus menjaga lint-staged tidak perlu mengulang pemeriksaan penuh. Berikut contoh workflow ci.yml:

name: CI Matrix

on:
  pull_request:
    paths:
      - 'packages/**'
      - '.github/workflows/**'

jobs:
  lint-test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [18, 20]
        package: [core, ui, utils]
    name: Package ${{ matrix.package }} on Node ${{ matrix.node-version }}
    steps:
      - uses: actions/checkout@v4
      - uses: pnpm/action-setup@v2
        with:
          version: 8
      - name: Install dependencies
        run: pnpm install
      - name: Run lint and tests
        run: pnpm --filter ${matrix.package} lint && pnpm --filter ${matrix.package} test
        env:
          NODE_OPTIONS: "--max-old-space-size=4096"

Matriks ini menjalankan lint dan test per paket dan versi Node. Sebagai trade-off, jumlah job meningkat, tapi Danger membantu fail-fast bila PR tidak memenuhi syarat. Untuk monorepo besar, pertimbangkan membatasi job pada paket yang terpengaruh dengan skrip bantu (misalnya menggunakan nx affected:apps atau mengolah file berubah di workflow).

Alternatif GitLab CI

Jika menggunakan GitLab CI, gunakan parallel:matrix dengan rules yang memastikan job hanya berjalan ketika path relevan berubah. Gunakan skrip pembantu untuk menentukan paket mana yang harus diuji berdasarkan $CI_MERGE_REQUEST_DIFF_BASE_SHA.

Menghindari lint ganda dan mempercepat feedback

Lint ganda terjadi jika lint-staged dan CI Matrix menjalankan perintah sama tanpa membedakan scope. Solusinya:

  • Lint-staged hanya memeriksa file staged, cukup pakai eslint --cache atau lint tertentu.
  • CI Matrix menjalankan lint penuh atau kombinasi paket, termasuk cache agar cepat.
  • Pastikan lint-staged tidak memanggil script yang juga dijalankan di CI matrix (misalnya jangan panggil skrip verify yang menjalankan seluruh suite). Gunakan skrip terpisah seperti lint:staged.

Untuk debugging, jalankan lint-staged dengan npx lint-staged --debug saat hasil tidak sesuai. Di CI, sertakan log detail saat job gagal agar cepat mengetahui paket mana yang bermasalah.

Otomatisasi feedback di setiap level

Lokal: lint-staged memberi peringatan awal sebelum commit. Otomatiskan dengan husky pre-commit hook yang memanggil lint-staged dan hanya memperbolehkan commit jika lint sukses.

PR: Danger mengupdate PR dengan komentar/kesalahan. Gunakan Danger agar reviewer tidak perlu mencari file yang terlewat. Pastikan workflow Danger berjalan sebelum merge agar kualitas gate konsisten.

Release: CI Matrix harus menjadi bagian release pipeline untuk memastikan paket kombinasi (misal paket + environment) diuji sebelum publish. Untuk mempercepat, gunakan caching dependencies dan artefak build per paket.

Penutup dan praktik terbaik

Integrasi lint-staged, Danger, dan CI Matrix memberikan pendekatan terstruktur: lint cepat di lokal, quality gate transparan di PR, serta validasi lengkap di CI. Fokus pada batas tanggung jawab tiap lapisan untuk menghindari pengulangan kerja. Gunakan Danger untuk feedback otomatis tanpa menambah beban reviewer, dan sesuaikan matriks CI agar relevan dengan paket yang berubah.

Terakhir, dokumentasikan flow ini di repo agar kontributor baru tahu ekspektasi lokal, PR, dan release. Dengan pendekatan ini, monorepo Node mempertahankan kecepatan pengembangan tanpa mengorbankan kualitas.