Topik ini membahas pemasangan gerbang kualitas pada pipeline continuous integration (CI) untuk proyek Rust, yaitu cargo fmt --check untuk keseragaman format, cargo clippy untuk pemeriksaan lanjutan, dan cargo test untuk seluruh rangkaian pengujian. Pembahasan mencakup struktur berkas pipeline GitHub Actions beserta arti setiap langkahnya, cara menjalankan ketiga gerbang secara lokal sebelum push dilakukan, serta cara membaca laporan kegagalan setiap gerbang. Contoh memakai proyek penyaring-ci yang lolos ketiga gerbang dan dijalankan sungguhan. Setelah membacanya, berkas pipeline dapat dipasang pada repository dan kegagalan gerbang dapat diperbaiki sebelum mencapai server CI.
Tiga gerbang kualitas#
Pipeline CI menjalankan rangkaian perintah setiap kali perubahan di-push ke repository, dan setiap perintah yang keluar dengan kode bukan nol menghentikan rangkaian itu serta menandai pipeline gagal. Tiga gerbang berikut menjadi susunan yang umum untuk proyek Rust karena masing-masing memeriksa lapis yang berbeda, yaitu gaya penulisan, idiom bahasa, dan perilaku program.
| Gerbang | Perintah | Yang diperiksa | Bentuk laporan kegagalan |
|---|---|---|---|
| format | cargo fmt --all --check | keseragaman gaya penulisan kode | diff perbaikan format |
| pemeriksaan | cargo clippy --all-targets -- -D warnings | linter umum dan idiom yang lebih baik | pesan error dengan saran perbaikan |
| pengujian | cargo test --all | unit test, integration test, dan doc test | laporan kegagalan pengujian |
Gerbang format memakai rustfmt yang sama dengan yang dipakai saat menyunting kode, dan tanda --check mengubah perilakunya dari menulis berkas menjadi mencetak diff lalu keluar dengan kode satu. Gerbang pemeriksaan memakai clippy yang menerapkan linter rustc beserta linter idiomnya, dan tanda -D warnings setelah -- menaikkan seluruh peringatan menjadi error sehingga pipeline gagal. Gerbang pengujian menjalankan ketiga jenis pengujian yang dibahas pada modul ini dalam satu perintah.
Urutan gerbang menentukan kecepatan umpan balik. Format diperiksa tanpa kompilasi sehingga selesai dalam hitungan detik, clippy mengompilasi seluruh target dalam mode pemeriksaan, dan pengujian melakukan kompilasi penuh lalu menjalankan program. Kegagalan format yang terdeteksi lebih dahulu menghemat waktu kompilasi, sebab perubahan yang ditolak karena alasan gaya tidak dilanjutkan ke tahap kompilasi.
Berkas pipeline GitHub Actions#
Layanan GitHub Actions membaca berkas YAML pada direktori .github/workflows/ dan menjalankan langkah-langkahnya pada mesin yang disediakan. Berkas berikut memasang ketiga gerbang untuk setiap push ke branch main dan setiap pull request.
name: ci-rust
on:
push:
branches: [main]
pull_request:
jobs:
gerbang:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy
- name: Format
run: cargo fmt --all --check
- name: Clippy
run: cargo clippy --all-targets -- -D warnings
- name: Test
run: cargo test --allBagian on menentukan peristiwa pemantik, yaitu push ke branch main dan setiap pull request. Bagian jobs memuat satu pekerjaan bernama gerbang yang berjalan pada mesin Ubuntu, dan steps mengurutkan langkah-langkahnya. Langkah uses: actions/checkout@v4 menyalin isi repository ke mesin tersebut, sedangkan uses: dtolnay/rust-toolchain@stable memasang toolchain stabil beserta komponen rustfmt dan clippy yang tidak terpasang secara bawaan. Setiap langkah run menjalankan satu perintah, dan kegagalan salah satunya menghentikan pekerjaan sehingga langkah berikutnya tidak dijalankan. Rangkaian lengkap dari push sampai pipeline dinyatakan lolos dirangkum pada diagram berikut.
Berkas YAML hanya dijalankan oleh layanan CI, sehingga isinya tidak dapat diuji secara lokal. Nilai praktisnya terletak pada isi setiap langkah run, karena ketiga baris itu adalah perintah lokal biasa yang dapat diperiksa lebih dahulu pada mesin sendiri. Pemeriksaan lokal semacam itu dilakukan pada proyek contoh penyaring-ci.
Proyek contoh yang lolos ketiga gerbang#
Proyek penyaring-ci memuat pustaka penyaring baris catatan dengan dua fungsi publik dan dua unit test. Seluruh berkasnya sengaja lolos ketiga gerbang sehingga keluaran pemeriksaan bersih dan dapat dibandingkan dengan laporan kegagalan yang disusun setelahnya.
[package]
name = "penyaring-ci"
version = "0.1.0"
edition = "2021"// tidak-dijalankan sendirian oleh rustc karena berkas pustaka tanpa fungsi main.
//! Penyaring baris catatan berdasarkan kata kunci.
/// Mengembalikan seluruh baris yang memuat kata kunci.
pub fn cari_baris<'a>(catatan: &'a str, kata_kunci: &str) -> Vec<&'a str> {
catatan
.lines()
.filter(|baris| baris.contains(kata_kunci))
.collect()
}
/// Menghitung banyaknya baris yang memuat kata kunci.
pub fn hitung_baris(catatan: &str, kata_kunci: &str) -> usize {
cari_baris(catatan, kata_kunci).len()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn cari_dua_baris() {
let catatan = "beli buku\nbeli pulpen\njual buku";
assert_eq!(cari_baris(catatan, "beli").len(), 2);
}
#[test]
fn hitung_nol_bila_tidak_ada() {
assert_eq!(hitung_baris("halo", "selamat"), 0);
}
}Pemeriksaan dilakukan pada proyek di luar pohon konten situs. Berkas ci-rust.yml dari bundle disalin ke posisi kanonisnya pada .github/workflows/ci.yml agar susunan proyek sama dengan repository yang sesungguhnya.
# siapkan proyek percobaan yang bersih di luar pohon konten
rm -rf /tmp/proyek-ci
cargo new /tmp/proyek-ci --lib -q --vcs none
# salin berkas proyek dari bundle ke posisinya masing-masing
cp Cargo.toml /tmp/proyek-ci/Cargo.toml
cp src/lib.rs /tmp/proyek-ci/src/lib.rs
# pasang berkas pipeline pada posisi kanonisnya
mkdir -p /tmp/proyek-ci/.github/workflows
cp ci-rust.yml /tmp/proyek-ci/.github/workflows/ci.ymlMenjalankan ketiga gerbang secara lokal#
Ketiga perintah berikut sama dengan tiga langkah run pada berkas pipeline, dengan tambahan --manifest-path karena perintah dijalankan dari luar direktori proyek. Gerbang yang lolos tidak mencetak apa pun dan keluar dengan kode nol, sedangkan gerbang pengujian tetap mencetak laporannya.
# periksa format tanpa menulis berkas
cargo fmt --manifest-path /tmp/proyek-ci/Cargo.toml --all --check# periksa seluruh target dengan clippy dan peringatan dinaikkan menjadi error
cargo clippy --manifest-path /tmp/proyek-ci/Cargo.toml --all-targets -q -- -D warnings 2>/dev/null# jalankan seluruh rangkaian pengujian secara berurutan
cargo test --manifest-path /tmp/proyek-ci/Cargo.toml -q -- --test-threads=1 2>/dev/null | sed 's/; finished in [0-9.]*s$//'running 2 tests
..
test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered outDua blok pertama tidak diikuti blok keluaran karena keduanya tidak mencetak apa pun ketika lolos. Kode keluar setiap perintah dapat diperiksa dengan echo $? yang mencetak 0 saat lolos. Laporan pengujian memuat dua bagian, yaitu dua unit test pada pustaka dan bagian doc test yang kosong karena dokumentasi fungsi belum memuat contoh berpagar.
Membaca kegagalan gerbang#
Bentuk kegagalan kedua gerbang pertama dapat diperiksa dengan sengaja merusak berkas pustaka lalu memulihkannya. Blok pertama menghapus spasi sebelum usize sehingga rustfmt melaporkan diff, dan blok kedua menambahkan kata kunci return yang oleh clippy dianggap tidak perlu pada baris terakhir fungsi.
# rusak format pada tanda panah fungsi hitung_baris
sed -i 's/-> usize {/->usize {/' /tmp/proyek-ci/src/lib.rs
# periksa format lalu perhatikan diff yang dicetak
cargo fmt --manifest-path /tmp/proyek-ci/Cargo.toml --all --check
# pulihkan berkas asli dari bundle
cp src/lib.rs /tmp/proyek-ci/src/lib.rsDiff in /tmp/proyek-ci/src/lib.rs:11:
}
/// Menghitung banyaknya baris yang memuat kata kunci.
-pub fn hitung_baris(catatan: &str, kata_kunci: &str) ->usize {
+pub fn hitung_baris(catatan: &str, kata_kunci: &str) -> usize {
cari_baris(catatan, kata_kunci).len()
}
Baris Diff in menyebut berkas dan baris pertama yang berbeda, baris berawalan - menunjukkan tulisan saat ini, dan baris berawalan + menunjukkan hasil rapi yang diinginkan rustfmt. Perbaikannya cukup menjalankan cargo fmt tanpa --check pada direktori proyek, karena versi tanpa --check menulis perbaikan itu langsung ke berkas.
# tambahkan return yang tidak perlu pada baris terakhir fungsi
sed -i 's|cari_baris(catatan, kata_kunci).len()|return cari_baris(catatan, kata_kunci).len();|' /tmp/proyek-ci/src/lib.rs
# periksa seluruh target dengan clippy dan peringatan dinaikkan menjadi error
cargo clippy --manifest-path /tmp/proyek-ci/Cargo.toml --all-targets -q -- -D warnings
# pulihkan berkas asli dari bundle
cp src/lib.rs /tmp/proyek-ci/src/lib.rserror: unneeded `return` statement
--> src/lib.rs:15:5
|
15 | return cari_baris(catatan, kata_kunci).len();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.99.0/index.html#needless_return
= note: `-D clippy::needless-return` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::needless_return)]`
help: remove `return`
|
15 - return cari_baris(catatan, kata_kunci).len();
15 + cari_baris(catatan, kata_kunci).len()
|
error: could not compile `penyaring-ci` (lib) due to 1 previous error
error: could not compile `penyaring-ci` (lib test) due to 1 previous errorLaporan clippy memuat nama linter needless_return, lokasi persisnya pada kolom -->, dan saran perbaikan yang menggambarkan bentuk kode yang diharapkan. Baris catatan -D clippy::needless-return implied by -D warnings menjelaskan mengapa peringatan berubah menjadi error, dan dua baris terakhir menunjukkan bahwa pustaka beserta target pengujianannya sama-sama gagal dikompilasi. Seluruh gerbang pengujian tidak dijalankan karena langkah clippy pada pipeline berhenti lebih dahulu, sehingga urutan langkah menentukan laporan mana yang terlihat lebih dulu.
Kesalahan umum#
Menjalankan cargo fmt tanpa --check pada pipeline. Tanpa tanda itu, rustfmt menulis berkas dan langkah selalu lolos, sehingga format tidak pernah diperiksa. Simpan penulisan berkas untuk mesin lokal, dan biarkan pipeline hanya memeriksa.
Melupakan komponen rustfmt dan clippy. Toolchain stabil yang dipasang layanan CI tidak selalu memuat kedua biner tersebut, sehingga langkah gagal dengan perintah tidak ditemukan alih-alih laporan yang berarti. Cantumkan komponennya pada langkah pemasangan toolchain sebagaimana berkas pipeline di atas.
Menghilangkan -D warnings pada clippy. Tanpa tanda itu, peringatan tidak menggagalkan pipeline dan menumpuk dari waktu ke waktu sampai satu linter tertentu dinaikkan menjadi error pada versi clippy yang lebih baru. Naikkan seluruh peringatan sejak awal agar setiap temuan diperbaiki pada perubahan yang memuatnya.
Ringkasan#
- Pipeline CI menjalankan
cargo fmt --all --check,cargo clippy --all-targets -- -D warnings, dancargo test --allsecara berurutan, dan kegagalan satu langkah menghentikan langkah berikutnya. - Setiap baris
runpada berkas.github/workflows/adalah perintah lokal biasa, sehingga ketiga gerbang dapat dijalankan lebih dahulu dengan--manifest-pathsebelum push dilakukan. - Gerbang format yang gagal mencetak diff dengan baris
-dan+, sedangkan gerbang clippy memuat nama linter, lokasi, dan saran perbaikannya. - Tanda
--checkmenjaga fmt tidak menulis berkas, dan-D warningsmenaikkan peringatan clippy menjadi error agar pipeline benar-benar gagal.
Referensi#
- Clippy — The Rust linter
— Daftar linter beserta cara kerja
-D warningspada clippy. - rustfmt — The Rust formatter
— Perilaku
cargo fmtdan mode--check. - Understanding GitHub Actions — GitHub Docs
— Struktur berkas workflow, peristiwa pemantik, dan langkah
runmaupunuses. - dtolnay/rust-toolchain — GitHub — Langkah pemasangan toolchain beserta komponennya pada pipeline.