Sinkronisasi linter lokal dan pipeline release otomatis memastikan hasil lint yang diuji oleh developer sama dengan yang dipakai pipeline sebelum melepaskan rilis. Pendekatan ini menjaga lint menjadi gerbang yang konsisten, cepat, dan tidak menunda alur kerja pengembangan.

Untuk menjawab kebutuhan tersebut, kita memerlukan konfigurasi lint yang sama baik di IDE/pre-commit maupun di CI, cache lint agar tidak selalu mengulang kerja, gate lint di workflow release, dan mekanisme rollback terukur saat lint gagal. Dalam artikel ini dibahas langkah praktik yang konkret dan contoh konfigurasi yang dapat langsung diadaptasi.

Pemastian konfigurasi lint konsisten

Lint yang berbeda antara lokal dan pipeline biasanya hadir karena perbedaan konfigurasi atau versi. Solusi praktisnya adalah menyimpan konfigurasi lint satu sumber di repositori dan menjalankan lint menggunakan dependensi proyek.

Contoh konfigurasi ESLint dalam .eslintrc.json:

{
  "root": true,
  "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
  "parser": "@typescript-eslint/parser",
  "rules": {
    "no-console": "warn",
    "@typescript-eslint/no-unused-vars": ["error", {"argsIgnorePattern": "^_"}]
  }
}

Jika proyek menggunakan ruff untuk Python, simpan pyproject.toml dengan bagian [tool.ruff] agar semua lingkungan mengikuti aturan yang sama. Jika ada IDE plugin lint, pastikan plugin membaca file konfig yang sama dan dependency dikunci oleh poetry.lock atau package-lock.json.

Untuk memastikan lint lokal dijalankan sebelum commit, gunakan tool seperti pre-commit dengan hook:

repos:
  - repo: https://github.com/psf/black
    rev: 23.9.1
    hooks:
      - id: black
  - repo: https://github.com/pre-commit/mirrors-eslint
    rev: v9.0.0
    hooks:
      - id: eslint
        additional_dependencies: ["@typescript-eslint/eslint-plugin"]

Hook ini tidak hanya menjalankan lint di lokal, tetapi juga memastikan developer menggunakan versi lint yang sama.

Cache lint di pipeline untuk hasil yang cepat

Lint cenderung memperlambat pipeline, terutama proyek besar. GitHub Actions atau GitLab CI memungkinkan caching direktori dependency lint sehingga job tidak mengunduh ulang package setiap kali.

Contoh potongan job di GitHub Actions:

- name: Cache ESLint
  uses: actions/cache@v4
  with:
    path: ~/.npm
    key: lint-npm-${{ hashFiles('package-lock.json') }}
    restore-keys: lint-npm-
- name: Install dependencies
  run: npm ci
- name: Jalankan lint
  run: npm run lint

Cache menggunakan hash file kunci (package-lock.json) agar invalidasi terjadi jika dependency berubah. Pendekatan serupa bisa digunakan untuk ruff dengan cache pipenv atau poetry di GitHub Actions/GitLab CI.

Untuk lint yang membutuhkan build sebelumnya (misalnya TypeScript transpile), pastikan lint job bergantung pada artefak build minimal agar lint tetap lintas platform.

Gate lint sebelum release otomatis

Lint harus menjadi gate yang memblokir job release jika ada masalah. Dalam workflow GitHub Actions, gunakan job terpisah dan atur needs: agar release hanya berjalan jika lint sukses:

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npm run lint
  release:
    needs: lint
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npm run build
      - run: ./scripts/deploy.sh

Struktur ini menjamin release tidak berjalan kalau lint gagal. Jika lint ingin dijalankan di matrix (contohnya TypeScript dan Python), gunakan job lint per stack lalu job release membutuhkan semua lint job.

Pada GitLab CI, gunakan needs atau stage order:

stages:
  - lint
  - release
lint_job:
  stage: lint
  script:
    - npm ci
    - npm run lint
release_job:
  stage: release
  needs:
    - lint_job
  script:
    - npm ci
    - npm run build
    - ./deploy.sh
  rules:
    - if: '$CI_COMMIT_BRANCH == "main"'

Hubungkan lint dengan job release otomatis

Release otomatis idealnya hanya berjalan ketika semua gate lint terpenuhi. Gunakan artefak lint (misalnya laporan lint) untuk debugging:

- name: Run lint with report
  run: npm run lint -- --format json --output-file lint-report.json
- name: Upload lint report
  if: failure()
  uses: actions/upload-artifact@v4
  with:
    name: lint-report
    path: lint-report.json

Jika lint gagal, laporan tetap tersedia sehingga reviewer dapat cepat melihat kesalahan. Release job hanya mulai ketika lint job sukses tanpa perlu pemeriksaan manual.

Untuk release otomatis, gunakan tag release atau tool seperti semantic-release di job release agar rilis dilakukan tanpa intervensi manusia selama lint sudah bersih.

Strategi rollback saat lint gagal di pipeline release

Rollback menjadi penting bila lint tidak berhasil tetapi pipeline release sudah mulai pada event terpisah (misalnya release otomatis untuk tag). Untuk itu:

  • Pertahankan file .github/workflows/release.yml yang memeriksa status lint terbaru atau menyertakan lint job di dalam pipeline yang sama dengan release.
  • Gunakan feature flag atau canary deployment sehingga release dapat dihentikan dengan cepat tanpa pengaruh besar ke pengguna.
  • Jika release sudah dibuat (misalnya GitHub Release atau artefak terpublish), siapkan script rollback yang menghapus release dan versi yang di-publish jika lint job gagal verifikasi terakhir.

Contohnya, tambahkan job "verify" sesudah release yang menjalankan lint sekali lagi dengan artefak dari build. Jika lint gagal, job ini dapat men-trigger script rollback:

rollback:
  needs: release
  runs-on: ubuntu-latest
  if: failure()
  steps:
    - run: ./scripts/rollback-release.sh

Meski lint idealnya sudah melewati gate, langkah ini menjadi safety net.

Menjaga feedback lint tetap cepat

Feedback lint yang lambat membuat developer melewatkan validasi. Beberapa praktik untuk menjaga kecepatan:

  • Jalankan lint change-focused di pre-commit hook (hanya file yang diubah) dengan eslint --cache atau ruff check {{changed_files}}.
  • Gunakan lint daemon atau IDE integration untuk memberi peringatan sambil mengetik.
  • Tambahkan lint caching di CI agar job lint utama selesai dalam waktu wajar.
  • Kombinasikan lint dengan proses build minimal (misalnya lint sebelum unit test) agar developer mendapat feedback sebelum pipeline penuh berjalan.

Dengan menjaga lint cepat dan sinkron antara lokal dan pipeline, tim dapat memelihara standar kualitas tinggi tanpa menghambat produktivitas.