CODE-QUALITY DEVELOPER-EXPERIENCE AUTOMATION GIT-HOOKS LINTING FORMATTING PRE-COMMIT JAVASCRIPT TYPESCRIPT WEB-DEVELOPMENT BEST-PRACTICES TOOLING PRODUCTIVITY SOFTWARE-DEVELOPMENT

Membangun Pipeline Kualitas Kode Lokal: Linting, Formatting, dan Pre-commit Hooks untuk Developer Modern

⏱️ 17 menit baca
👨‍💻

Membangun Pipeline Kualitas Kode Lokal: Linting, Formatting, dan Pre-commit Hooks untuk Developer Modern

Sebagai developer, kita semua tahu betapa frustrasinya saat melihat kode yang berantakan, inkonsisten, atau bahkan mengandung potensi bug yang seharusnya bisa dihindari. Seringkali, dalam tim, kita menghabiskan waktu berharga di code review hanya untuk membahas masalah gaya kode, spasi, atau titik koma, padahal seharusnya kita fokus pada logika bisnis dan arsitektur.

Bayangkan jika setiap kali Anda atau rekan tim Anda menulis kode, kode tersebut secara otomatis diperiksa, dirapikan, dan dipastikan bebas dari masalah gaya atau potensi bug sebelum di-commit ke repository. Kedengarannya seperti mimpi, bukan? Nah, dengan kombinasi Linting, Formatting, dan Pre-commit Hooks, mimpi itu bisa menjadi kenyataan!

Artikel ini akan memandu Anda membangun “pipeline kualitas kode lokal” yang akan menjaga kode Anda tetap bersih, konsisten, dan bebas masalah, bahkan sebelum sampai ke tangan rekan tim untuk di-review. Siap menyulap alur kerja pengembangan Anda menjadi lebih rapi dan efisien? Mari kita mulai!

1. Pendahuluan

Dalam dunia pengembangan perangkat lunak yang serba cepat, kualitas kode seringkali menjadi hal yang terabaikan. Deadline yang ketat, fitur baru yang harus segera dirilis, atau sekadar perbedaan gaya penulisan antar developer bisa menyebabkan kode menjadi tidak konsisten, sulit dibaca, dan rentan terhadap bug.

Masalah-masalah umum yang sering muncul:

Solusinya? Otomatisasi! Dengan mengintegrasikan Linting, Formatting, dan Pre-commit Hooks, kita bisa memastikan standar kualitas kode ditegakkan secara otomatis di setiap commit, menghemat waktu, mengurangi friksi, dan meningkatkan kualitas keseluruhan proyek.

2. Mengapa Kualitas Kode itu Penting?

Mungkin Anda bertanya, “Kan yang penting aplikasinya jalan? Kenapa harus pusing mikirin kualitas kode?” Pertanyaan bagus! Tapi, kualitas kode jauh lebih dari sekadar estetika.

Readability dan Maintainability: Kode yang bersih dan konsisten lebih mudah dibaca, dipahami, dan dirawat oleh siapa pun, termasuk diri Anda di masa depan. Ini mengurangi waktu dan usaha saat melakukan debugging atau menambahkan fitur baru.

Konsistensi Tim: Di proyek tim, setiap orang akan menulis kode dengan gaya yang sama. Ini seperti memiliki satu suara di sebuah paduan suara; hasilnya akan harmonis. Tidak ada lagi “perang” gaya yang menghabiskan energi.

Mencegah Bug Lebih Awal: Linting dapat mendeteksi potensi masalah (misalnya, variabel yang diinisialisasi tapi tidak pernah digunakan) bahkan sebelum kode dijalankan, membantu Anda menangkap bug lebih awal.

Fokus pada Logika Bisnis: Dengan masalah gaya dan potensi bug yang diatasi secara otomatis, code review bisa lebih fokus pada validasi logika bisnis, desain arsitektur, dan aspek keamanan yang lebih krusial.

Pada akhirnya, berinvestasi pada kualitas kode adalah investasi pada produktivitas tim dan keberlanjutan proyek Anda dalam jangka panjang.

3. Linting: Penjaga Gerbang Kode Anda

📌 Apa itu Linting? Bayangkan Anda memiliki seorang asisten yang tugasnya membaca setiap baris kode yang Anda tulis, lalu menyoroti kesalahan tata bahasa, ejaan, atau bahkan memberikan saran untuk penulisan yang lebih baik. Itulah Linting. Linter adalah alat analisis statis yang memeriksa kode Anda untuk menemukan masalah gaya, potensi bug, atau pelanggaran terhadap aturan yang telah ditentukan.

💡 Fungsi Utama Linter:

🎯 Contoh Tools Linting:

Mari kita lihat contoh implementasi ESLint untuk proyek JavaScript/TypeScript:

  1. Instalasi ESLint:

    npm install --save-dev eslint
    # Atau yarn add --dev eslint
  2. Inisialisasi Konfigurasi: ESLint memiliki wizard untuk membantu Anda mengatur konfigurasi awal:

    npx eslint --init

    Anda akan ditanya beberapa pertanyaan tentang proyek Anda (misalnya, apakah Anda menggunakan React/Vue, TypeScript, lingkungan browser/Node.js, dll.). Ini akan menghasilkan file konfigurasi seperti .eslintrc.js, .eslintrc.json, atau .eslintrc.yaml.

    Contoh .eslintrc.js (sederhana):

    module.exports = {
      env: {
        browser: true,
        es2021: true,
        node: true,
      },
      extends: [
        'eslint:recommended',
        'plugin:@typescript-eslint/recommended', // Jika pakai TypeScript
        // 'plugin:react/recommended', // Jika pakai React
      ],
      parser: '@typescript-eslint/parser', // Jika pakai TypeScript
      parserOptions: {
        ecmaVersion: 'latest',
        sourceType: 'module',
        // Jika pakai React
        // ecmaFeatures: {
        //   jsx: true,
        // },
      },
      plugins: [
        '@typescript-eslint', // Jika pakai TypeScript
        // 'react', // Jika pakai React
      ],
      rules: {
        'no-console': 'warn', // Beri peringatan jika ada console.log
        'no-unused-vars': 'warn', // Beri peringatan untuk variabel tak terpakai
        'indent': ['error', 2], // Indentasi 2 spasi, jika salah langsung error
        'linebreak-style': ['error', 'unix'],
        'quotes': ['error', 'single'], // Wajib pakai single quotes
        'semi': ['error', 'always'], // Wajib pakai titik koma
      },
      // Jika pakai React
      // settings: {
      //   react: {
      //     version: 'detect',
      //   },
      // },
    };
  3. Menjalankan Linter: Anda bisa menambahkan script di package.json untuk menjalankan ESLint:

    // package.json
    {
      "name": "my-project",
      "scripts": {
        "lint": "eslint . --ext .js,.jsx,.ts,.tsx",
        "lint:fix": "eslint . --ext .js,.jsx,.ts,.tsx --fix"
      }
    }

    Kemudian jalankan:

    npm run lint          # Untuk melihat masalah
    npm run lint:fix      # Untuk mencoba memperbaiki masalah secara otomatis
    // Contoh kode JavaScript yang akan dilinting
    const myVar = "Hello"; // myVar tidak terpakai, akan jadi 'warn' atau 'error'
    console.log("World");  // Akan jadi 'warn' karena 'no-console'
    
    function greet(name) {
      return "Hello, " + name + "!"; // Harusnya single quotes dan template literal
    }

    Dengan eslint --fix, beberapa masalah (seperti quotes dan semi) bisa diperbaiki otomatis.

💡 Tips Praktis untuk Linting:

4. Formatting: Merapikan Tampilan Kode Secara Otomatis

📌 Apa itu Formatting? Jika linter adalah “penjaga gerbang” yang memastikan kualitas kode, maka formatter adalah “tukang bersih-bersih” yang merapikan tampilan kode Anda. Formatter hanya peduli tentang bagaimana kode terlihat, bukan apa yang dilakukan kode tersebut. Ia akan mengatur spasi, indentasi, tanda kutip, dan panjang baris agar kode Anda selalu terlihat rapi dan seragam.

💡 Fungsi Utama Formatter:

🎯 Contoh Tools Formatting:

Mari kita implementasikan Prettier untuk proyek kita:

  1. Instalasi Prettier:

    npm install --save-dev prettier
    # Atau yarn add --dev prettier
  2. Konfigurasi Prettier (Opsional): Prettier didesain untuk “zero-config”, artinya Anda bisa langsung menggunakannya. Namun, Anda bisa membuat file .prettierrc (JSON, YAML, atau JS) untuk menyesuaikan beberapa opsi, seperti:

    // .prettierrc
    {
      "semi": true,          // Selalu tambahkan titik koma di akhir statement
      "singleQuote": true,   // Gunakan single quotes untuk string
      "tabWidth": 2,         // Indentasi 2 spasi
      "trailingComma": "all", // Tambahkan koma di akhir objek/array multi-baris
      "printWidth": 80       // Panjang baris maksimum 80 karakter
    }
  3. Menjalankan Formatter: Tambahkan script di package.json:

    // package.json
    {
      "name": "my-project",
      "scripts": {
        "format": "prettier --write .",
        "check-format": "prettier --check ."
      }
    }

    Kemudian jalankan:

    npm run format        # Untuk memformat semua file yang didukung Prettier
    npm run check-format  # Untuk memeriksa apakah ada file yang belum diformat
    // Contoh kode sebelum Prettier
    function  calculateSum( a,b )  { return a+b ; }
    const myArray = [1,2,3]
    
    // Setelah Prettier (dengan konfigurasi di atas)
    function calculateSum(a, b) {
      return a + b;
    }
    const myArray = [1, 2, 3];

💡 Tips Praktis untuk Formatting:

5. Pre-commit Hooks: Otomatisasi di Setiap Commit

Sekarang kita sudah punya linter dan formatter. Keduanya bekerja dengan baik. Tapi, bagaimana cara memastikan developer selalu menjalankannya sebelum melakukan commit? Di sinilah Pre-commit Hooks berperan!

📌 Apa itu Git Hooks? Git Hooks adalah skrip yang dijalankan Git secara otomatis sebelum atau sesudah kejadian tertentu (seperti commit, push, receive). Bayangkan Git Hooks sebagai “pagar keamanan” di berbagai gerbang dalam alur kerja Git Anda.

💡 Fokus: pre-commit hook. pre-commit hook dijalankan tepat sebelum Git meminta pesan commit dan sebelum commit dibuat. Ini adalah waktu yang sempurna untuk:

⚠️ Masalah dengan Git Hooks bawaan: Git Hooks disimpan di folder .git/hooks dan tidak otomatis di-versi kontrol atau dibagikan antar developer. Untuk itu, kita butuh alat bantu.

🎯 Tools untuk Mengelola Hooks:

Mari kita implementasikan Husky dan lint-staged:

  1. Instalasi Husky dan lint-staged:

    npm install --save-dev husky lint-staged
    # Atau yarn add --dev husky lint-staged
  2. Konfigurasi Husky: Aktifkan Husky dengan perintah berikut (untuk Git versi 2.9+):

    npx husky install

    Kemudian, tambahkan script di package.json agar Husky terinstal otomatis setiap kali npm install dijalankan:

    // package.json
    {
      "scripts": {
        "prepare": "husky install"
      }
    }

    Sekarang, buat pre-commit hook:

    npx husky add .husky/pre-commit "npx lint-staged"

    Ini akan membuat file .husky/pre-commit yang berisi npx lint-staged.

  3. Konfigurasi lint-staged: Tambahkan konfigurasi lint-staged di package.json Anda. Ini akan menentukan perintah apa yang dijalankan untuk jenis file tertentu yang di-stage.

    // package.json
    {
      "name": "my-project",
      "version": "1.0.0",
      "scripts": {
        "lint": "eslint . --ext .js,.jsx,.ts,.tsx",
        "lint:fix": "eslint . --ext .js,.jsx,.ts,.tsx --fix",
        "format": "prettier --write .",
        "prepare": "husky install"
      },
      "devDependencies": {
        "eslint": "^8.x.x",
        "prettier": "^2.x.x",
        "husky": "^8.x.x",
        "lint-staged": "^13.x.x",
        "eslint-config-prettier": "^8.x.x", // Pastikan ini juga ada
        "@typescript-eslint/eslint-plugin": "^5.x.x", // Jika pakai TypeScript
        "@typescript-eslint/parser": "^5.x.x" // Jika pakai TypeScript
      },
      "lint-staged": {
        "*.{js,jsx,ts,tsx}": [
          "eslint --fix",    // Jalankan linter dan coba perbaiki
          "prettier --write" // Jalankan formatter
        ],
        "*.{json,css,md,html}": [
          "prettier --write" // Hanya jalankan formatter untuk file ini
        ]
      }
    }

🎯 Bagaimana Alur Kerjanya Sekarang?

  1. Anda membuat perubahan pada kode.
  2. Anda menambahkan file yang diubah ke staging area: git add .
  3. Anda mencoba melakukan commit: git commit -m "Fitur baru"
  4. Husky akan mengaktifkan pre-commit hook.
  5. pre-commit hook menjalankan npx lint-staged.
  6. lint-staged akan mengidentifikasi file-file yang ada di staging area (*.js, *.ts, *.json, dll.).
  7. Untuk file-file tersebut, lint-staged menjalankan perintah yang sudah kita tentukan (eslint --fix dan prettier --write).
  8. Jika eslint menemukan masalah yang tidak bisa diperbaiki otomatis (error level), atau jika prettier gagal, proses commit akan dibatalkan. Anda harus memperbaiki masalah tersebut secara manual, lalu git add kembali file yang sudah diperbaiki, dan coba commit lagi.
  9. Jika semua perintah berhasil dijalankan dan tidak ada error, perubahan akan di-commit dengan sukses!

Dengan alur ini, Anda memastikan bahwa setiap commit yang masuk ke repository Anda sudah bersih dan sesuai standar.

6. Integrasi dengan CI/CD (Opsional, tapi Direkomendasikan)

Meskipun pre-commit hooks sangat kuat, ada satu kelemahan: mereka bisa di-bypass. Developer bisa saja sengaja atau tidak sengaja menggunakan git commit --no-verify untuk melewati hooks.

Oleh karena itu, sangat disarankan untuk tetap menjalankan perintah linting dan formatting di pipeline CI/CD Anda (misalnya, GitHub Actions, GitLab CI, Jenkins). Ini bertindak sebagai “lapisan keamanan terakhir” dan memastikan bahwa kode yang masuk ke main branch atau siap di-deploy selalu memenuhi standar kualitas.

Contoh sederhana step di GitHub Actions:

# .github/workflows/ci.yml
name: Code Quality Check

on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main

jobs:
  lint-and-format:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '18'

      - name: Install dependencies
        run: npm ci

      - name: Run ESLint
        run: npm run lint

      - name: Check Prettier format
        run: npm run check-format

Jika npm run lint atau npm run check-format mengembalikan error, pipeline CI/CD akan gagal, mencegah merge atau deployment kode yang tidak memenuhi standar.

Kesimpulan

Selamat! Anda telah mempelajari cara membangun pipeline kualitas kode lokal yang tangguh menggunakan Linting, Formatting, dan Pre-commit Hooks. Ini bukan hanya tentang membuat kode terlihat bagus, tetapi juga tentang: