Rust: Otomasi lint, format, dan testing dengan cargo devtools menyelesaikan kebutuhan pengembang Rust yang ingin menggabungkan format, lint, dan test dalam workflow otomatis. Artikel ini menjelaskan langkah konfigurasi cargo fmt, clippy, dan test melalui cargo devtools, lalu memasangkannya ke hook pre-commit serta pipeline CI tanpa mengorbankan kegesitan release.
1. Menyiapkan cargo devtools sebagai entrypoint workflow
cargo devtools menyediakan wrapper untuk mengelola toolchain linting dan testing secara konsisten. Mulailah dengan menambahkan dependensi devtools di Cargo.toml:
[dev-dependencies]
cargo-devtools = "*"
Setelah menginstal, buat file konfigurasi dalam .cargo/devtools.toml yang mendefinisikan task:
[tasks.fmt]
command = "cargo"
args = ["fmt"]
[tasks.clippy]
command = "cargo"
args = ["clippy", "--all-targets", "--all-features", "--", "-D", "warnings"]
[tasks.test]
command = "cargo"
args = ["test", "--workspace"]
Rancang task devtools untuk merepresentasikan tujuan lint, format, dan test. Di environment yang sama, `cargo devtools run fmt` menjadi standar untuk format, sementara `cargo devtools run clippy` dan `cargo devtools run test` menjaga keandalan quality gates.
2. Menggabungkan fmt, clippy, dan test dalam flow developer
Pengembang sebaiknya menjalankan fmt/clippy/test secara lokal sebelum commit. Gunakan cargo devtools untuk memudahkan, misalnya:
cargo devtools run fmt && cargo devtools run clippy && cargo devtools run test
Dengan mengunci perintah di devtools, tim tidak perlu mengingat opsi tambahan. Selain itu, tambahkan file .cargo/config.toml untuk menyetel target default dan cache build agar perintah berjalan konsisten:
[build]
target-dir = "target"
[unstable]
build-std = []
Folder target tunggal memungkinkan caching lint/test lintas task, yang penting untuk pipeline CI nanti.
3. Hook pre-commit dengan cargo-husky
Supaya developer tidak melewati tahap lint/test, gunakan cargo-husky untuk hook git. Pertama pasang dependency:
cargo install cargo-husky
Selanjutnya buat template hook di .husky/pre-commit yang memanggil devtools:
#!/bin/sh
cargo devtools run fmt && cargo devtools run clippy
Jangan lupa menambahkan chmod +x .husky/pre-commit. Hook seperti ini memastikan format dan lint dijalankan sebelum commit, meski developer memilih opsi GUI. Hindari menjalankan test lengkap di pre-commit jika workspace besar; cukup fmt dan clippy untuk menjaga kecepatan.
4. Pipeline lint dan test di GitHub Actions
Untuk lint dan testing otomatis pada push atau pull request, buat workflow minimal .github/workflows/ci.yaml:
name: CI
on:
push:
branches: ["main"]
pull_request:
branches: ["main"]
jobs:
lint-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
components: clippy, rustfmt
override: true
- name: Cache cargo
uses: actions/cache@v4
with:
path: |
target
~/.cargo/registry
~/.cargo/git
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-
- name: Run fmt
run: cargo devtools run fmt
- name: Run clippy
run: cargo devtools run clippy
- name: Run test
run: cargo devtools run test
Cache target dan registri mempercepat lint/test di setiap job. Gunakan kunci cache yang bergantung pada Cargo.lock agar pembaruan dependency otomatis memicu restore baru. Jika workspace besar, pertimbangkan job terpisah untuk lint dan test agar parallelisasi lebih efisien.
5. Strategi caching dan incremental lint
Linting dengan clippy bisa lambat pada workspace besar. Untuk mempercepat, aktifkan fitur incremental compilation bawaan Rust (aktif secara default). Pastikan direktori target digunakan bersama di lokal dan CI agar artifact reusable. Dalam repo monorepo, gunakan flag --package atau --workspace untuk membatasi scope lint saat hanya ada perubahan kecil.
Untuk kontrol fine-grain, buat script yang mendeteksi crate yang berubah lalu menjalankan clippy hanya di crate tersebut:
changed=$(git diff --name-only origin/main | grep '^crates/' | cut -d'/' -f2 | uniq)
for crate in $changed; do
cargo clippy -p "$crate" --all-targets
done
Metode incremental seperti ini mengurangi beban lint saat PR hanya menyentuh beberapa crate.
6. Monitoring status lint dan testing
Laporkan hasil lint/test ke sistem notifikasi agar tim tahu kapan pipeline gagal. GitHub Actions sudah menampilkan status di PR, tapi tambahkan badge di README untuk status terbaru. Jaga log yang jelas dengan format cargo devtools run clippy -- -D warnings sehingga setiap peringatan diperlakukan serius.
Monitoring aktif meningkatkan DX karena developer tahu apakah commit mereka menyelesaikan masalah sebelum merging. Fokuskan pada pesan log reformatting (fmt) yang bisa diamati di diff, dan pastikan clippy warning lawas dilog agar tidak menumpuk.
7. Mencegah false positive dan troubleshooting
False positive clippy biasanya muncul dari lint seperti clippy::restriction; sesuaikan clippy.toml untuk menonaktifkan lint yang relevan atau beri allow di level modul. Ini mencegah developer berhenti karena warning yang tidak berlaku.
Diagnosa umum:
- fmt tidak mengubah apa pun: Pastikan
rustfmtversi sama dengan toolchain, jalankanrustup component add rustfmt. - Cache rusak: Jika job CI melewatkan perubahan dependency, bersihkan cache manual dan kunci cache per commit dengan
hashFiles. - Hook tidak berjalan: Periksa izin file
.husky/pre-commitdan bahwacargo-huskydiinstal di path developer.
Sertakan dokumentasi di repo tentang cara menonaktifkan lint tertentu untuk alasan valid, dan gunakan issue template untuk menangani false positive agar solusinya tersentralisasi.
Kesimpulan
Dengan cargo devtools sebagai otak workflow lint-format-testing, cargo-husky untuk pre-commit, dan GitHub Actions dengan cache, proyek Rust dapat menjaga kualitas kode sambil mempertahankan kecepatan pengembangan. Kombinasi tooling ini memperkuat monitoring lint/test, memungkinkan pengambilan tindakan cepat terhadap kegagalan, serta menjaga false positive terkendali lewat konfigurasi yang eksplisit.
Komentar
0 komentar
Masuk ke akun kamu untuk ikut berkomentar.
Belum ada komentar
Jadilah yang pertama ikut berdiskusi!