Proyek Elixir yang sehat mengandalkan tiga perkakas rutin, yaitu mix format untuk menyeragamkan gaya penulisan, Credo untuk memeriksa kualitas dan konsistensi kode secara statis, serta CI (continuous integration) yang menjalankan semuanya pada setiap perubahan. Topik ini membahas cara kerja ketiganya beserta konfigurasinya dan ditutup dengan bentuk paling sederhana dari alur CI untuk proyek Elixir. Setelah topik ini diselesaikan, pemeriksaan gaya dan kualitas dapat diotomatisasi dari komputer lokal sampai repositori.
mix format#
Perintah mix format mengubah kode menjadi satu gaya kanonik yang ditetapkan compiler, tanpa opsi penyetelan gaya yang dapat diperdebatkan. Formatter menjadi bagian bawaan Elixir sejak rilis 1.6, dan kode yang sama selalu terformat secara identik, sehingga perbedaan gaya antar pengembang tidak lagi muncul pada review kode. Formatter bekerja dengan mengurai kode lalu menuliskannya kembali, tanpa mengeksekusi kode yang diformatnya. Berikut adalah berkas yang sengaja ditulis berantakan di dalam proyek contoh.
# membuat proyek contoh dengan berkas Elixir yang berantakan
cd /tmp && rm -rf kalkulator && mix new kalkulator >/dev/null
mkdir -p kalkulator/lib/kalkulator
cat > kalkulator/lib/kalkulator/hitung.ex <<'EOF'
defmodule Kalkulator.Hitung do
def tambah(a,b), do: a+b
def kali(a, b), do: a*b
end
EOF
cat kalkulator/lib/kalkulator/hitung.exdefmodule Kalkulator.Hitung do
def tambah(a,b), do: a+b
def kali(a, b), do: a*b
endBerkas di atas memuat tiga kebiasaan yang sering terlihat, yaitu hilangnya spasi setelah koma pada daftar argumen, spasi di sekitar operator yang tidak konsisten, dan indentasi kode yang tidak seragam. Opsi --check-formatted memeriksa berkas tanpa menulis apa pun, dan apabila ada berkas yang belum terformat, perintah menampilkan perubahan yang akan dilakukan formatter lalu berakhir dengan kode gagal. Sifat ini menjadikan opsi tersebut cocok untuk hook pre-commit dan pemeriksaan CI.
# memeriksa format; perintah berakhir dengan kode gagal bila ada berkas berantakan
cd /tmp/kalkulator && mix format --check-formatted** (Mix) mix format failed due to --check-formatted.
The following files are not formatted:
/tmp/kalkulator/lib/kalkulator/hitung.ex
1 1 |defmodule Kalkulator.Hitung do
2 -|def tambah(a,b), do: a+b
3 -|def kali(a, b), do: a*b
2 +| def tambah(a, b), do: a + b
3 +| def kali(a, b), do: a * b
4 4 |end
5 5 |Keluaran di atas menunjukkan baris yang dihapus dengan tanda - dan baris penggantinya dengan tanda +. Menjalankan mix format tanpa opsi memformat seluruh berkas yang terdaftar pada konfigurasinya, lalu hasilnya dapat dilihat kembali.
# memformat seluruh berkas dalam proyek, lalu menampilkan hasilnya
mix format && cat lib/kalkulator/hitung.exdefmodule Kalkulator.Hitung do
def tambah(a, b), do: a + b
def kali(a, b), do: a * b
endPemeriksaan ulang dengan opsi yang sama kini berjalan tanpa keluaran apa pun, yang berarti seluruh berkas sudah terformat dan perintah berakhir dengan kode sukses.
# memeriksa ulang; tanpa keluaran berarti semua berkas sudah terformat
mix format --check-formattedKonfigurasi formatter#
Konfigurasi formatter berada pada berkas .formatter.exs di akar proyek, dan mix new menghasilkan berkas bawaan yang memuat pola berkas yang akan diformat.
# Used by "mix format"
[
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
]Kunci inputs memuat pola glob, dan pola {mix,.formatter}.exs berarti kedua berkas tersebut ikut diformat bersama kode di folder config, lib, dan test. Kunci line_length menetapkan panjang baris yang dituju ketika sebuah ekspresi harus dipecah ke beberapa baris, dengan nilai bawaan 98. Kunci import_deps menerima daftar nama dependensi yang konfigurasi formatnya ikut diimpor, misalnya pustaka yang menetapkan aturan khusus untuk DSL miliknya, sehingga kode yang dihasilkan pustaka itu tetap konsisten dengan gaya proyek.
Perintah mix format tanpa argumen memformat seluruh pola pada inputs, sedangkan perintah dengan argumen hanya menyentuh berkas yang disebut, misalnya mix format lib/kalkulator/hitung.ex. Argumen pola juga sah, sehingga sebagian folder dapat diformat tanpa memengaruhi sisanya. Batasan 98 karakter bukan aturan baku seluruh ekosistem, karena proyek bebas menetapkan nilai lain melalui line_length pada konfigurasinya.
Credo#
Credo adalah alat analisis statis dari komunitas yang membaca kode sumber dan melaporkan isu ke dalam lima kategori, yaitu consistency, readability, design, refactor, dan warning. Fokusnya adalah kebiasaan penulisan dan tanda-tanda desain yang dapat diperbaiki, misalnya nama modul yang tidak mengikuti konvensi atau baris yang terlalu panjang, dan bukan kebenaran tipe yang menjadi ranah Dialyzer. Karena bekerja di atas kode sumber, Credo dapat dijalankan tanpa menunggu kompilasi selesai.
Setelah {:credo, "~> 1.7", only: [:dev, :test], runtime: false} ditambahkan ke fungsi deps/0, perintah mix deps.get mengunduh paketnya dan mix credo menjalankan analisis bawaan pada berkas proyek. Mode --strict mengaktifkan pemeriksaan tambahan yang lebih teliti, sedangkan mix credo explain menjelaskan satu isu tertentu beserta alasan dan contoh perbaikannya.
# tidak-dijalankan
# memasang Credo mengunduh paket dari Hex sehingga melebihi batas waktu blok
cd /tmp/kalkulator
mix deps.get
mix credoBerkas .credo.exs mengatur daftar pemeriksaan yang aktif beserta opsinya. Berkas lengkap dihasilkan oleh perintah mix credo gen.config dan memuat lebih dari seratus pemeriksaan yang sebagian besar dinonaktifkan, sedangkan bentuk ringkasnya seperti berikut.
# cuplikan .credo.exs yang memperlihatkan bentuk konfigurasinya
%{
configs: [
%{
name: "default",
files: %{
included: ["lib/", "src/", "test/", "web/", "apps/*/lib/"],
excluded: [~r"/_build/", ~r"/deps/"]
},
checks: %{
enabled: [
{Credo.Check.Consistency.TabsOrSpaces, []},
{Credo.Check.Readability.ModuleNames, []}
]
}
}
]
}Kunci files menentukan berkas yang dianalisis, sedangkan checks memuat daftar pemeriksaan dalam pasangan modul dan opsinya. Perintah mix credo berakhir dengan kode gagal apabila menemukan isu, sehingga analisis ini dapat dijadikan gerbang CI di samping tes.
CI dengan GitHub Actions#
CI menjalankan pemeriksaan pada setiap push dan pull request, sehingga pelanggaran gaya atau tes yang gagal tertangkap sebelum perubahan digabungkan. Untuk proyek Elixir pada GitHub Actions, pemeriksaan dinyatakan sebagai workflow, yaitu satu berkas YAML di dalam repositori, sedangkan action setup-beam memasang Elixir dan Erlang/OTP pada runner, yaitu mesin yang menjalankan langkah-langkah workflow tersebut.
name: CI
on:
push:
branches: ["main"]
pull_request:
jobs:
pemeriksaan:
runs-on: ubuntu-latest
name: Format dan tes
steps:
- name: Unduh kode
uses: actions/checkout@v4
- name: Siapkan Elixir dan Erlang
uses: erlef/setup-beam@v1
with:
elixir-version: "1.20.5"
otp-version: "29.1"
- name: Pasang dependensi
run: mix deps.get
- name: Periksa format
run: mix format --check-formatted
- name: Jalankan tes
run: mix testBerkas workflow di atas disimpan pada folder .github/workflows/, dan GitHub menjalankannya pada setiap push ke cabang main serta pada setiap pull request. Runner ubuntu-latest tidak membawa Elixir, sehingga langkah setup-beam memasang pasangan versi yang ditetapkan, yaitu Elixir 1.20.5 di atas Erlang/OTP 29.1. Langkah berikutnya tidak dijalankan apabila langkah sebelumnya gagal, sehingga masalah selalu terlihat pada pemeriksaan paling awal yang tidak lolos. Urutan langkahnya disusun dari yang termurah, yaitu mengunduh dependensi lebih dahulu, memeriksa format dengan opsi yang langsung gagal, dan menjalankan tes paling akhir. Ketika Credo atau dialyxir sudah digunakan pada proyek, masing-masing cukup ditambahkan sebagai langkah baru dengan perintah mix credo dan mix dialyzer.
Ringkasan#
mix formatmenyeragamkan gaya secara deterministik, dan--check-formattedmenolak kode yang belum terformat dengan menampilkan perubahannya.- Konfigurasi formatter menetapkan pola berkas melalui
inputs, panjang baris dengan nilai bawaan 98, dan dependensi yang konfigurasinya ikut diimpor. - Credo melaporkan isu dalam lima kategori dan pemeriksaannya disetel melalui
.credo.exs. - Workflow CI memadukan pengunduhan dependensi, pemeriksaan format, dan tes pada setiap push dan pull request.
Referensi#
- mix format — Dokumentasi Mix — opsi –check-formatted, kunci konfigurasi, dan impor konfigurasi dependensi.
- Code.format_string!/2 — Dokumentasi Elixir — opsi :line_length beserta nilai bawaan 98.
- Elixir v1.6.0 released — elixir-lang.org — rilis yang memperkenalkan formatter dan tugas mix format.
- Credo — Dokumentasi Credo — ikhtisar kategori pemeriksaan dan penggunaan perintahnya.
- GitHub Actions — GitHub Docs — konsep workflow, job, dan step.
- setup-beam — erlef — action untuk memasang Elixir dan Erlang/OTP pada runner.