Linting paralel untuk setiap paket TypeScript dalam monorepo dan release otomatis di CI itu bisa diatur secara deterministik: jalankan linting dan tes secara terisolasi, kumpulkan hasilnya, lalu baru biarkan pipeline merilis saat semuanya sukses. Dalam panduan ini saya tunjukkan bagaimana mengonfigurasi pnpm/Nx, mengelola lint-staged atau ESLint paralel, dan menautkannya dengan tahap release otomatis di GitHub Actions.

Fokusnya adalah membuat CI yang bisa dipercaya—linting dijalankan serentak di seluruh paket, hasilnya terakumulasi, dan hanya jika linting dan tes valid maka stage release (generate changelog, tagging, publish npm) dijalankan. Berikut langkah-langkah terperinci dan contoh YAML konkret.

Mengurai tantangan linting paralel di monorepo TypeScript

Monorepo TypeScript biasanya terdiri dari banyak paket yang punya konfigurasi ESLint masing-masing. Menjalankan linting secara serial di seluruh paket bisa memakan waktu. Maka dari itu, gunakan fitur paralel yang ditawarkan pnpm atau Nx untuk mengeksekusi linting per paket sekaligus.

Jika menggunakan pnpm, pastikan Anda menulis script lint di package.json di root ataupun setiap paket. Contoh struktur skrip:

{
  "scripts": {
    "lint": "eslint . --ext .ts,.tsx",
    "lint:packages": "pnpm --parallel --filter "@org/*" lint"
  }
}

Dengan flag --parallel dan --filter Anda bisa memanggil linting untuk paket-paket yang relevan secara bersamaan. Jangan lupa define pnpm-workspace.yaml agar pnpm mengenali relasi antar paket.

Alternatifnya, jika Anda memakai Nx, gunakan target lint dan jalankan nx run-many --target=lint --parallel. Nx mengoptimalkan dependensi dan mendeteksi paket-paket yang tidak berubah sehingga linting hanya dilakukan di apa yang perlu.

Lint-staged masih penting untuk menjaga kualitas kode di developer machine. Jalankan lint-staged untuk memformat file yang di-commit, tapi dalam konteks CI gunakan lint global agar tidak bergantung pada env lokal.

Pipeline CI langkah demi langkah

Desain pipeline harus berurutan: pertama install dan cache, lalu linting paralel, tes, dan terakhir release otomatis. Berikut langkah-langkahnya:

  1. Instal dependensi dan caching: gunakan cache untuk pnpm store dan node_modules agar install lebih cepat. Simpan file pnpm-lock.yaml dan node_modules/.pnpm.
  2. Linting paralel per paket: jalankan pnpm lint:packages atau nx run-many --target=lint --parallel. Simpan log dan gunakan reporter yang bisa diaggregate (misal format JUnit) bila Anda butuh integrasi hasil.
  3. Agregasi hasil linting: jika lint gagal di satu paket, pipeline harus langsung berhenti. Sertakan output path file agar tim mudah men-debug. Bisa juga tambahkan langkah tambahan untuk menyimpan artefak log lint agar reviewer bisa melihat detail.
  4. Jalankan tes unit/integrasi: jalankan pnpm test atau nx run-many --target=test --parallel sesudah lint sukses.
  5. Release otomatis: hanya jika lint dan tes sukses, jalankan job release yang membuat changelog, menandai commit, dan melakukan pnpm publish.

Dengan pendekatan ini, linting dan testing melewati seluruh paket sebelum job release dijalankan. Jika linting gagal, job release tidak akan dieksekusi karena job release bergantung (needs) pada lint/test yang sukses.

Contoh GitHub Actions pipeline

Berikut contoh file .github/workflows/ci.yml yang menerapkan linting paralel dan release otomatis:

name: CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  lint-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: pnpm/action-setup@v2
        with:
          version: 9
      - name: Restore pnpm cache
        uses: actions/cache@v4
        with:
          path: ~/.pnpm-store
          key: pnpm-store-${{ hashFiles('pnpm-lock.yaml') }}
      - name: Install dependencies
        run: pnpm install
      - name: Lint semua paket
        run: pnpm lint:packages
      - name: Jalankan tes
        run: pnpm test

  release:
    needs: lint-test
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    steps:
      - uses: actions/checkout@v4
      - uses: pnpm/action-setup@v2
        with:
          version: 9
      - name: Restore pnpm cache
        uses: actions/cache@v4
        with:
          path: ~/.pnpm-store
          key: pnpm-store-${{ hashFiles('pnpm-lock.yaml') }}
      - name: Install dependencies
        run: pnpm install --frozen-lockfile
      - name: Generate changelog
        run: pnpm conventional-changelog -p angular -i CHANGELOG.md -s
      - name: Create release tag
        run: |
          VERSION=$(node -p "require('./package.json').version")
          git tag v$VERSION
          git push origin v$VERSION
      - name: Publish ke npm
        run: pnpm publish --access public
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

Job lint-test menjalankan linting paralel lalu tes. Job release membutuhkan job sebelumnya sukses, dan hanya berjalan di branch main.

Mekanisme release otomatis dan gate lint/test

Release otomatis membutuhkan tiga hal utama:

  • Generate changelog otomatis: gunakan tool seperti conventional-changelog atau changesets. Di pipeline hanya jalankan tool ini setelah lint + tes berhasil.
  • Tagging: pipeline harus memanfaatkan versi dari package.json atau tool versioning, lalu buat tag Git dan push instant.
  • Publish npm: langkah terakhir, hanya dieksekusi bila semua job sebelumnya berhasil, dan memerlukan token npm aman di GitHub Secrets.

Gunakan job dependency via needs agar release tidak jalan bila lint/test gagal. Tambahkan if: github.ref == 'refs/heads/main' untuk mencegah release dari cabang lain.

Jika menggunakan Nx, release job bisa memanggil target khusus misalnya nx release yang menggabungkan lint, tes, changelog, dan publish.

Tips caching dan debugging

Cache sangat penting untuk kecepatan:

  • Simpan pnpm store dengan actions/cache. Gunakan key berbasis hash lockfile agar cache invalid saat lockfile berubah.
  • Cache node_modules/ pnpm store agar proses install lebih cepat, khususnya untuk linting paralel yang membutuhkan dependensi.
  • Jika linting mengalami timeouts, periksa parallel limit di ESLint: Anda bisa gunakan ESLINT_PARALLEL=4 atau pnpm lint -- --max-warnings=0 untuk menghindari warning.

Debugging linting paralel: jika job lint menyatakan failed tapi output tidak jelas, tambahkan step tambahan untuk mencetak pnpm lint --report-unused-disable-directives atau gunakan reporter JUnit agar Anda bisa melihat file tepatnya.

Dengan desain ini, CI Anda akan menjalankan linting per paket secara paralel, hasil linting dan test dijadikan gate untuk release otomatis, dan caching menjaga pipeline tetap responsif.