Dalam penganalisis PVS-Studio untuk bahasa C dan C++ di Linux dan macOS, mulai dari versi 7.04, opsi pengujian telah muncul untuk memeriksa daftar file yang ditentukan. Dengan menggunakan mode baru, Anda dapat mengonfigurasi penganalisis untuk memeriksa penerapan dan menarik permintaan. Artikel ini akan memberi tahu Anda cara mengatur pemeriksaan daftar file yang diubah dari proyek GitHub dalam sistem CI (Continuous Integration) yang populer seperti Travis CI, Buddy, dan AppVeyor.
Mode pemeriksaan daftar file
Di versi PVS-Studio 7.04 untuk Linux dan macOS, mode untuk memeriksa daftar file sumber telah muncul. Ini berfungsi untuk proyek yang sistem pembangunannya memungkinkan Anda membuat file
Selain itu, mode pemeriksaan daftar file dapat digunakan bersama dengan log jejak strace dari peluncuran kompiler (pelacakan pvs-studio-analyzer). Untuk melakukan ini, Anda harus terlebih dahulu melakukan pembangunan proyek secara penuh dan melacaknya sehingga penganalisis mengumpulkan informasi lengkap tentang parameter kompilasi dari semua file yang diperiksa.
Namun, opsi ini memiliki kelemahan yang signifikan - Anda harus melakukan jejak build lengkap dari keseluruhan proyek setiap kali Anda menjalankannya, yang dengan sendirinya bertentangan dengan gagasan untuk memeriksa penerapan dengan cepat. Atau, jika Anda menyimpan hasil pelacakan itu sendiri dalam cache, proses penganalisa selanjutnya mungkin tidak lengkap jika struktur ketergantungan file sumber berubah setelah pelacakan (misalnya, #include baru ditambahkan ke salah satu file sumber).
Oleh karena itu, kami tidak menyarankan penggunaan mode pemeriksaan daftar file dengan log jejak untuk memeriksa penerapan atau permintaan penarikan. Jika Anda dapat melakukan build tambahan saat memeriksa penerapan, pertimbangkan untuk menggunakan mode ini
Daftar file sumber untuk analisis disimpan dalam file teks dan diteruskan ke penganalisis menggunakan parameter -S:
pvs-studio-analyzer analyze ... -f build/compile_commands.json -S check-list.txt
File ini menentukan jalur relatif atau absolut ke file, dan setiap file baru harus berada di baris baru. Dapat diterima untuk menentukan tidak hanya nama file untuk analisis, tetapi juga berbagai teks. Penganalisis akan melihat bahwa ini bukan file dan akan mengabaikan baris tersebut. Ini berguna untuk memberi komentar jika file ditentukan secara manual. Namun, sering kali daftar file akan dihasilkan selama analisis di CI, misalnya, ini bisa berupa file dari permintaan penerapan atau penarikan.
Sekarang, dengan menggunakan mode ini, Anda dapat dengan cepat memeriksa kode baru sebelum masuk ke cabang pengembangan utama. Untuk memastikan bahwa sistem pemindaian merespons peringatan penganalisis, utilitas konverter plog bendera ditambahkan --indikasi-peringatan:
plog-converter ... --indicate-warnings ... -o /path/to/report.tasks ...
Dengan tanda ini, konverter akan mengembalikan kode bukan nol jika ada peringatan di laporan penganalisis. Dengan menggunakan kode pengembalian, Anda dapat memblokir permintaan hook, commit, atau pull yang telah dilakukan sebelumnya, dan laporan penganalisis yang dihasilkan dapat ditampilkan, dibagikan, atau dikirim melalui email.
Catatan. Saat Anda pertama kali mulai menganalisis daftar file, keseluruhan proyek akan dianalisis, karena penganalisis perlu membuat file ketergantungan file sumber proyek pada file header. Ini adalah fitur menganalisis file C dan C++. Di masa depan, file ketergantungan dapat di-cache dan akan diperbarui secara otomatis oleh penganalisis. Keuntungan memeriksa komit saat menggunakan mode pemeriksaan daftar file dibandingkan menggunakan mode analisis tambahan adalah Anda hanya perlu menyimpan file tersebut dalam cache dan bukan file objek.
Prinsip umum analisis permintaan tarik
Menganalisis keseluruhan proyek membutuhkan banyak waktu, jadi masuk akal untuk memeriksa hanya bagian tertentu saja. Masalahnya adalah Anda perlu memisahkan file baru dari file proyek lainnya.
Mari kita lihat contoh pohon komit dengan dua cabang:
Mari kita bayangkan komitmen itu A1 berisi sejumlah besar kode yang telah diuji. Beberapa saat sebelumnya kami membuat cabang dari komit A1 dan mengubah beberapa file.
Anda, tentu saja, memperhatikan hal itu setelahnya A1 terjadi dua komitmen lagi, tapi ini juga merupakan penggabungan cabang lain, karena kami tidak berkomitmen menguasai. Dan sekarang waktunya telah tiba perbaikan terbaru siap. Karena itulah muncul pull request merger B3 ΠΈ A3.
Tentu saja, dimungkinkan untuk memeriksa seluruh hasil penggabungannya, tetapi ini akan memakan waktu terlalu lama dan tidak dapat dibenarkan, karena hanya sedikit file yang diubah. Oleh karena itu, akan lebih efisien jika hanya menganalisis perubahan saja.
Untuk melakukan ini, kita mendapatkan perbedaan antar cabang, berada di HEAD cabang tempat kita ingin menggabungkannya menjadi master:
git diff --name-only HEAD origin/$MERGE_BASE > .pvs-pr.list
$MERGE_BASE kita akan melihatnya secara detail nanti. Faktanya adalah tidak semua layanan CI menyediakan informasi yang diperlukan tentang database untuk digabungkan, jadi setiap kali Anda harus menemukan cara baru untuk mendapatkan data ini. Ini akan dijelaskan secara rinci di bawah ini di setiap layanan web yang dijelaskan.
Jadi, kami mendapatkan perbedaan antar cabang, atau lebih tepatnya, daftar nama file yang diubah. Sekarang kita perlu memberikan filenya .pvs-pr.list (kami mengarahkan output di atas ke sana) ke penganalisis:
pvs-studio-analyzer analyze -j8
-o PVS-Studio.log
-S .pvs-pr.list
Setelah analisis, kita perlu mengonversi file log (PVS-Studio.log) ke dalam format yang mudah dibaca:
plog-converter -t errorfile PVS-Studio.log --cerr -w
Perintah ini akan mencantumkan kesalahan di
Hanya sekarang kami tidak hanya perlu menampilkan kesalahan, tetapi juga memberi tahu layanan perakitan dan pengujian kami tentang adanya masalah. Untuk tujuan ini, sebuah bendera telah ditambahkan ke konverter -W (--indikasi-peringatan). Jika ada setidaknya satu peringatan penganalisis, kode pengembalian utilitas konverter plog akan berubah menjadi 2, yang pada gilirannya akan menginformasikan layanan CI tentang adanya potensi kesalahan dalam file permintaan tarik.
Travis CI
Konfigurasi dibuat sebagai file .travis.yml. Untuk kenyamanan, saya menyarankan Anda untuk memasukkan semuanya ke dalam skrip bash terpisah dengan fungsi yang akan dipanggil dari file .travis.yml (bash skrip_nama.sh nama_fungsi).
Kami akan menambahkan kode yang diperlukan ke skrip di menampar, dengan cara ini kita akan mendapatkan lebih banyak fungsi. Di bagian install mari kita tulis yang berikut ini:
install:
- bash .travis.sh travis_install
Jika Anda memiliki instruksi apa pun, Anda dapat mentransfernya ke dalam skrip, menghapus tanda hubung.
Mari kita buka filenya .travis.sh dan tambahkan pengaturan penganalisis ke fungsinya travis_install():
travis_install() {
wget -q -O - https://files.viva64.com/etc/pubkey.txt
| sudo apt-key add -
sudo wget -O /etc/apt/sources.list.d/viva64.list
https://files.viva64.com/etc/viva64.list
sudo apt-get update -qq
sudo apt-get install -qq pvs-studio
}
Sekarang mari kita tambahkan ke bagian tersebut naskah jalankan analisis:
script:
- bash .travis.sh travis_script
Dan dalam skrip bash:
travis_script() {
pvs-studio-analyzer credentials $PVS_USERNAME $PVS_KEY
if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then
git diff --name-only origin/HEAD > .pvs-pr.list
pvs-studio-analyzer analyze -j8
-o PVS-Studio.log
-S .pvs-pr.list
--disableLicenseExpirationCheck
else
pvs-studio-analyzer analyze -j8
-o PVS-Studio.log
--disableLicenseExpirationCheck
fi
plog-converter -t errorfile PVS-Studio.log --cerr -w
}
Kode ini perlu dijalankan setelah membangun proyek, misalnya, jika Anda membangun CMake:
travis_script() {
CMAKE_ARGS="-DCMAKE_EXPORT_COMPILE_COMMANDS=On ${CMAKE_ARGS}"
cmake $CMAKE_ARGS CMakeLists.txt
make -j8
}
Ini akan menjadi seperti ini:
travis_script() {
CMAKE_ARGS="-DCMAKE_EXPORT_COMPILE_COMMANDS=On ${CMAKE_ARGS}"
cmake $CMAKE_ARGS CMakeLists.txt
make -j8
pvs-studio-analyzer credentials $PVS_USERNAME $PVS_KEY
if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then
git diff --name-only origin/HEAD > .pvs-pr.list
pvs-studio-analyzer analyze -j8
-o PVS-Studio.log
-S .pvs-pr.list
--disableLicenseExpirationCheck
else
pvs-studio-analyzer analyze -j8
-o PVS-Studio.log
--disableLicenseExpirationCheck
fi
plog-converter -t errorfile PVS-Studio.log --cerr -w
}
Anda mungkin sudah memperhatikan variabel lingkungan ini $TRAVIS_PULL_REQUEST ΠΈ $TRAVIS_BRANCH. Travis CI mendeklarasikannya secara independen:
- $TRAVIS_PULL_REQUEST menyimpan nomor permintaan tarik atau palsu, jika ini adalah cabang biasa;
- $TRAVIS_REPO_SLUG menyimpan nama repositori proyek.
Algoritma untuk fungsi ini:
Travis CI merespons kode yang dikembalikan, sehingga adanya peringatan akan memberitahu layanan untuk menandai penerapan sebagai mengandung kesalahan.
Sekarang mari kita lihat lebih dekat baris kode ini:
git diff --name-only origin/HEAD > .pvs-pr.list
Faktanya adalah Travis CI secara otomatis menggabungkan cabang saat menganalisis permintaan tarik:
Oleh karena itu kami menganalisis A4Dan tidak B3->A3. Karena fitur ini, kita perlu menghitung selisihnya dengan A3, yang tepatnya merupakan bagian atas cabang asal.
Ada satu detail penting yang tersisa - menyimpan cache dependensi file header pada unit terjemahan yang dikompilasi (*.c, *.cc, *.cpp, dll.). Penganalisis menghitung dependensi ini saat pertama kali diluncurkan dalam mode pemeriksaan daftar file dan kemudian menyimpannya di direktori .PVS-Studio. Travis CI memungkinkan Anda melakukan cache folder, jadi kami akan menyimpan data direktori .PVS-Studio/:
cache:
directories:
- .PVS-Studio/
Kode ini perlu ditambahkan ke file .travis.yml. Direktori ini menyimpan berbagai data yang dikumpulkan setelah analisis, yang secara signifikan akan mempercepat proses analisis daftar file atau analisis tambahan berikutnya. Jika hal ini tidak dilakukan, maka penganalisa akan menganalisis semua file setiap saat.
Buddy
Seperti Travis CI,
Pertama-tama, kita perlu menambahkan tindakan baru ke jalur perakitan:
Mari tunjukkan kompiler yang digunakan untuk membangun proyek. Perhatikan kontainer buruh pelabuhan yang diinstal dalam tindakan ini. Misalnya, ada wadah khusus untuk GCC:
Sekarang mari kita instal PVS-Studio dan utilitas yang diperlukan:
Mari tambahkan baris berikut ke editor:
apt-get update && apt-get -y install wget gnupg jq
wget -q -O - https://files.viva64.com/etc/pubkey.txt | apt-key add -
wget -O /etc/apt/sources.list.d/viva64.list
https://files.viva64.com/etc/viva64.list
apt-get update && apt-get -y install pvs-studio
Sekarang mari kita pergi ke tab Run (ikon pertama) dan tambahkan kode berikut ke kolom editor yang sesuai:
pvs-studio-analyzer credentials $PVS_USERNAME $PVS_KEY
if [ "$BUDDY_EXECUTION_PULL_REQUEST_NO" != '' ]; then
PULL_REQUEST_ID="pulls/$BUDDY_EXECUTION_PULL_REQUEST_NO"
MERGE_BASE=`wget -qO -
https://api.github.com/repos/${BUDDY_REPO_SLUG}/${PULL_REQUEST_ID}
| jq -r ".base.ref"`
git diff --name-only HEAD origin/$MERGE_BASE > .pvs-pr.list
pvs-studio-analyzer analyze -j8
-o PVS-Studio.log
--disableLicenseExpirationCheck
-S .pvs-pr.list
else
pvs-studio-analyzer analyze -j8
-o PVS-Studio.log
--disableLicenseExpirationCheck
fi
plog-converter -t errorfile PVS-Studio.log --cerr -w
Jika Anda membaca bagian Travs-CI, maka kode ini sudah tidak asing lagi bagi Anda, namun sekarang ada tahap baru:
Faktanya adalah sekarang kita menganalisis bukan hasil penggabungan, tetapi KEPALA cabang tempat permintaan penarikan dibuat:
Jadi kita berada dalam komitmen bersyarat B3 dan kita perlu mendapatkan perbedaannya A3:
PULL_REQUEST_ID="pulls/$BUDDY_EXECUTION_PULL_REQUEST_NO"
MERGE_BASE=`wget -qO -
https://api.github.com/repos/${BUDDY_REPO_SLUG}/${PULL_REQUEST_ID}
| jq -r ".base.ref"`
git diff --name-only HEAD origin/$MERGE_BASE > .pvs-pr.list
Untuk menentukan A3 Mari gunakan API GitHub:
https://api.github.com/repos/${USERNAME}/${REPO}/pulls/${PULL_REQUEST_ID}
Kami menggunakan variabel berikut yang Sobat sediakan:
- $BUDDY_EXECUTION_PULL_REQEUST_NO β nomor permintaan tarik;
- $BUDDY_REPO_SLUG β kombinasi nama pengguna dan repositori (misalnya max/test).
Sekarang mari simpan perubahan menggunakan tombol di bawah dan aktifkan analisis permintaan tarik:
Berbeda dengan Travis CI, kami tidak perlu menentukannya .pvs-studio untuk caching, karena Sobat secara otomatis menyimpan semua file dalam cache untuk peluncuran selanjutnya. Oleh karena itu, hal terakhir yang tersisa adalah menyimpan login dan password PVS-Studio di Buddy. Setelah menyimpan perubahan, kita akan dibawa kembali ke Pipeline. Kita perlu melanjutkan ke pengaturan variabel dan menambahkan login dan kunci untuk PVS-Studio:
Setelah ini, kemunculan pull request atau commit baru akan memicu peninjauan. Jika komit mengandung kesalahan, Sobat akan menunjukkannya di halaman permintaan penarikan.
AplikasiVeyor
Menyiapkan AppVeyor mirip dengan Buddy, karena semuanya terjadi di antarmuka web dan tidak perlu menambahkan file *.yml ke repositori proyek.
Mari buka tab Pengaturan di ikhtisar proyek:
Mari gulir ke bawah halaman ini dan aktifkan penyimpanan cache untuk mengumpulkan permintaan tarik:
Sekarang mari kita pergi ke tab Lingkungan, tempat kita menentukan gambar untuk perakitan dan variabel lingkungan yang diperlukan:
Jika Anda telah membaca bagian sebelumnya, Anda sangat familiar dengan kedua variabel ini - PVS_KEY ΠΈ PVS_USERNAME. Jika tidak, izinkan saya mengingatkan Anda bahwa hal itu diperlukan untuk memverifikasi lisensi penganalisis PVS-Studio. Kita akan melihatnya lagi di skrip Bash di masa mendatang.
Pada halaman yang sama di bawah ini kami menunjukkan folder untuk caching:
Jika kami tidak melakukan ini, kami akan menganalisis keseluruhan proyek, bukan beberapa file, tetapi kami akan mendapatkan output dari file yang ditentukan. Oleh karena itu, penting untuk memasukkan nama direktori yang benar.
Sekarang saatnya skrip diuji. Buka tab Tes dan pilih Skrip:
Anda perlu menempelkan kode berikut ke formulir ini:
sudo apt-get update && sudo apt-get -y install jq
wget -q -O - https://files.viva64.com/etc/pubkey.txt
| sudo apt-key add -
sudo wget -O /etc/apt/sources.list.d/viva64.list
https://files.viva64.com/etc/viva64.list
sudo apt-get update && sudo apt-get -y install pvs-studio
pvs-studio-analyzer credentials $PVS_USERNAME $PVS_KEY
PWD=$(pwd -L)
if [ "$APPVEYOR_PULL_REQUEST_NUMBER" != '' ]; then
PULL_REQUEST_ID="pulls/$APPVEYOR_PULL_REQUEST_NUMBER"
MERGE_BASE=`wget -qO -
https://api.github.com/repos/${APPVEYOR_REPO_NAME}/${PULL_REQUEST_ID}
| jq -r ".base.ref"`
git diff --name-only HEAD origin/$MERGE_BASE > .pvs-pr.list
pvs-studio-analyzer analyze -j8
-o PVS-Studio.log
--disableLicenseExpirationCheck
--dump-files --dump-log pvs-dump.log
-S .pvs-pr.list
else
pvs-studio-analyzer analyze -j8
-o PVS-Studio.log
--disableLicenseExpirationCheck
fi
plog-converter -t errorfile PVS-Studio.log --cerr -w
Mari kita perhatikan bagian kode berikut ini:
PWD=$(pwd -L)
if [ "$APPVEYOR_PULL_REQUEST_NUMBER" != '' ]; then
PULL_REQUEST_ID="pulls/$APPVEYOR_PULL_REQUEST_NUMBER"
MERGE_BASE=`wget -qO -
https://api.github.com/repos/${APPVEYOR_REPO_NAME}/${PULL_REQUEST_ID}
| jq -r ".base.ref"`
git diff --name-only HEAD origin/$MERGE_BASE > .pvs-pr.list
pvs-studio-analyzer analyze -j8
-o PVS-Studio.log
--disableLicenseExpirationCheck
--dump-files --dump-log pvs-dump.log
-S .pvs-pr.list
else
pvs-studio-analyzer analyze -j8
-o PVS-Studio.log
--disableLicenseExpirationCheck
fi
Penetapan nilai perintah pwd yang agak spesifik ke variabel yang seharusnya menyimpan nilai default ini tampak aneh pada pandangan pertama, namun, saya akan menjelaskan semuanya sekarang.
Saat menyiapkan penganalisis di AppVeyor, saya menemukan perilaku penganalisis yang sangat aneh. Di satu sisi, semuanya bekerja dengan benar, tetapi analisis tidak dimulai. Saya menghabiskan banyak waktu memperhatikan bahwa kita berada di direktori /home/appveyor/projects/testcalc/, dan penganalisis yakin bahwa kita berada di /opt/appveyor/build-agent/. Kemudian saya menyadari bahwa variabel $PWD sedikit berbohong. Karena alasan ini, saya memperbarui nilainya secara manual sebelum memulai analisis.
Dan kemudian semuanya seperti sebelumnya:
Sekarang perhatikan cuplikan berikut:
PULL_REQUEST_ID="pulls/$APPVEYOR_PULL_REQUEST_NUMBER"
MERGE_BASE=`wget -qO -
https://api.github.com/repos/${APPVEYOR_REPO_NAME}/${PULL_REQUEST_ID}
| jq -r ".base.ref"`
Di dalamnya kita mendapatkan perbedaan antara cabang tempat permintaan penarikan dideklarasikan. Untuk melakukan ini kita memerlukan variabel lingkungan berikut:
- $APPVEYOR_PULL_REQUEST_NUMBER β nomor permintaan penarikan;
- $APPVEYOR_REPO_NAME - nama pengguna dan repositori proyek.
Kesimpulan
Tentu saja, kami belum mempertimbangkan semua kemungkinan layanan integrasi berkelanjutan, namun semuanya memiliki spesifikasi pengoperasian yang sangat mirip satu sama lain. Kecuali caching, setiap layanan membuat βsepedaβ sendiri, jadi semuanya selalu berbeda.
Di suatu tempat, seperti di Travis-CI, beberapa baris kode dan caching berfungsi dengan sempurna; di suatu tempat, seperti di AppVeyor, Anda hanya perlu menentukan folder di pengaturan; tetapi di suatu tempat Anda perlu membuat kunci unik dan mencoba meyakinkan sistem untuk memberi Anda kesempatan untuk menimpa fragmen yang di-cache. Oleh karena itu, jika Anda ingin mengatur analisis permintaan tarik pada layanan integrasi berkelanjutan yang tidak dibahas di atas, pastikan terlebih dahulu bahwa Anda tidak akan mengalami masalah dengan caching.
Terima kasih atas perhatian Anda. Jika ada yang tidak berhasil, jangan ragu untuk menulis kepada kami di
Jika Anda ingin membagikan artikel ini kepada audiens berbahasa Inggris, silakan gunakan tautan terjemahan: Maxim Zvyagintsev.
Sumber: www.habr.com