Dalam penganalisis PVS-Studio untuk bahasa C dan C++ pada Linux dan macOS, bermula dari versi 7.04, pilihan ujian telah muncul untuk menyemak senarai fail yang ditentukan. Menggunakan mod baharu, anda boleh mengkonfigurasi penganalisis untuk menyemak permintaan komit dan tarik. Artikel ini akan memberitahu anda cara untuk menyediakan menyemak senarai fail yang diubah bagi projek GitHub dalam sistem CI (Continuous Integration) yang popular seperti Travis CI, Buddy dan AppVeyor.
Mod semakan senarai fail
Dalam versi PVS-Studio 7.04 untuk Linux dan macOS, mod untuk menyemak senarai fail sumber telah muncul. Ini berfungsi untuk projek yang sistem binaannya membolehkan anda menjana fail
Selain itu, mod semakan senarai fail boleh digunakan bersama-sama dengan log jejak jejak pelancaran pengkompil (jejak pvs-studio-analyzer). Untuk melakukan ini, anda perlu terlebih dahulu melaksanakan binaan penuh projek dan menjejakinya supaya penganalisis mengumpul maklumat lengkap tentang parameter kompilasi semua fail yang sedang diperiksa.
Walau bagaimanapun, pilihan ini mempunyai kelemahan yang ketara - anda sama ada perlu melakukan jejak binaan penuh bagi keseluruhan projek setiap kali anda menjalankannya, yang dengan sendirinya bercanggah dengan idea menyemak komit dengan cepat. Atau, jika anda cache hasil surih itu sendiri, larian penganalisis seterusnya mungkin tidak lengkap jika struktur kebergantungan fail sumber berubah selepas surih (contohnya, #include baharu ditambahkan pada salah satu fail sumber).
Oleh itu, kami tidak mengesyorkan menggunakan mod semakan senarai fail dengan log jejak untuk menyemak permintaan komit atau tarik. Sekiranya anda boleh melakukan binaan tambahan semasa menyemak komit, pertimbangkan untuk menggunakan mod
Senarai fail sumber untuk analisis disimpan dalam fail teks dan dihantar kepada penganalisis menggunakan parameter -S:
pvs-studio-analyzer analyze ... -f build/compile_commands.json -S check-list.txt
Fail ini menentukan laluan relatif atau mutlak kepada fail, dan setiap fail baharu mesti berada pada baris baharu. Ia boleh diterima untuk menentukan bukan sahaja nama fail untuk analisis, tetapi juga pelbagai teks. Penganalisis akan melihat bahawa ini bukan fail dan akan mengabaikan baris. Ini boleh berguna untuk mengulas jika fail ditentukan secara manual. Walau bagaimanapun, selalunya senarai fail akan dijana semasa analisis dalam CI, contohnya, ini mungkin fail daripada permintaan komit atau tarik.
Kini, menggunakan mod ini, anda boleh menyemak kod baharu dengan cepat sebelum ia masuk ke dalam cawangan pembangunan utama. Untuk memastikan sistem pengimbasan bertindak balas kepada amaran penganalisis, utiliti plog-converter bendera ditambah --tunjuk-amaran:
plog-converter ... --indicate-warnings ... -o /path/to/report.tasks ...
Dengan bendera ini, penukar akan mengembalikan kod bukan sifar jika terdapat amaran dalam laporan penganalisis. Menggunakan kod pemulangan, anda boleh menyekat permintaan cangkuk prakomit, komit atau tarik dan laporan penganalisis yang dijana boleh dipaparkan, dikongsi atau dihantar melalui e-mel.
Catatan. Apabila anda mula menganalisis senarai fail, keseluruhan projek akan dianalisis, kerana penganalisis perlu menjana fail kebergantungan fail sumber projek pada fail pengepala. Ini adalah ciri menganalisis fail C dan C++. Pada masa hadapan, fail kebergantungan boleh dicache dan ia akan dikemas kini secara automatik oleh penganalisis. Kelebihan menyemak komit apabila menggunakan mod penyemakan senarai fail berbanding menggunakan mod analisis tambahan ialah anda hanya perlu menyimpan fail itu dan bukan fail objek.
Prinsip umum analisis permintaan tarik
Menganalisis keseluruhan projek memerlukan banyak masa, jadi masuk akal untuk menyemak bahagian tertentu sahaja. Masalahnya ialah anda perlu memisahkan fail baharu daripada fail projek yang lain.
Mari kita lihat contoh pokok komit dengan dua cabang:
Mari bayangkan komitmen itu A1 mengandungi jumlah kod yang agak besar yang telah diuji. Sedikit lebih awal kami membuat cawangan daripada komit A1 dan menukar beberapa fail.
Anda, tentu saja, perasan selepas itu A1 dua lagi komitmen berlaku, tetapi ini juga penggabungan cawangan lain, kerana kami tidak komited untuk master. Dan kini masanya telah tiba hotfix sedia. Itulah sebabnya permintaan tarik untuk penggabungan muncul B3 ΠΈ A3.
Sudah tentu, adalah mungkin untuk menyemak keseluruhan hasil penggabungan mereka, tetapi ini akan memakan masa yang terlalu lama dan tidak wajar, kerana hanya beberapa fail yang diubah. Oleh itu, adalah lebih cekap untuk menganalisis hanya yang berubah.
Untuk melakukan ini, kita mendapat perbezaan antara cawangan, berada di KETUA cawangan dari mana kita ingin bergabung menjadi induk:
git diff --name-only HEAD origin/$MERGE_BASE > .pvs-pr.list
$MERGE_BASE kita akan lihat secara terperinci kemudian. Hakikatnya ialah tidak setiap perkhidmatan CI menyediakan maklumat yang diperlukan tentang pangkalan data untuk penggabungan, jadi setiap kali anda perlu mencari cara baharu untuk mendapatkan data ini. Ini akan diterangkan secara terperinci di bawah dalam setiap perkhidmatan web yang diterangkan.
Jadi, kami mendapat perbezaan antara cawangan, atau lebih tepat, senarai nama fail yang telah ditukar. Sekarang kita perlu memberikan fail .pvs-pr.list (kami mengalihkan output di atas kepadanya) kepada penganalisis:
pvs-studio-analyzer analyze -j8
-o PVS-Studio.log
-S .pvs-pr.list
Selepas analisis, kami perlu menukar fail log (PVS-Studio.log) kepada format yang mudah dibaca:
plog-converter -t errorfile PVS-Studio.log --cerr -w
Perintah ini akan menyenaraikan ralat dalam
Hanya sekarang kami perlu bukan sahaja memaparkan ralat, tetapi juga memaklumkan perkhidmatan kami untuk pemasangan dan ujian tentang kehadiran masalah. Untuk tujuan ini, bendera telah ditambahkan pada penukar -W (--tunjuk-amaran). Jika terdapat sekurang-kurangnya satu amaran penganalisis, kod pulangan utiliti plog-converter akan bertukar kepada 2, yang seterusnya akan memaklumkan perkhidmatan CI tentang kehadiran kemungkinan ralat dalam fail permintaan tarik.
Travis CI
Konfigurasi dibuat sebagai fail .travis.yml. Untuk kemudahan, saya menasihati anda untuk meletakkan segala-galanya ke dalam skrip bash yang berasingan dengan fungsi yang akan dipanggil daripada fail .travis.yml (bash script_name.sh function_name).
Kami akan menambah kod yang diperlukan pada skrip di menampar, dengan cara ini kita akan mendapat lebih banyak fungsi. Dalam bahagian memasang mari kita tulis yang berikut:
install:
- bash .travis.sh travis_install
Jika anda mempunyai sebarang arahan, anda boleh memindahkannya ke dalam skrip, mengalih keluar tanda sempang.
Mari buka fail .travis.sh dan tambah tetapan penganalisis pada fungsi 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 tambah pada bahagian skrip menjalankan 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
}
Kod ini perlu dijalankan selepas membina projek, contohnya, jika anda mempunyai binaan pada CMake:
travis_script() {
CMAKE_ARGS="-DCMAKE_EXPORT_COMPILE_COMMANDS=On ${CMAKE_ARGS}"
cmake $CMAKE_ARGS CMakeLists.txt
make -j8
}
Ia 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 telah melihat pembolehubah persekitaran ini $TRAVIS_PULL_REQUEST ΠΈ $TRAVIS_BRANCH. Travis CI mengisytiharkannya secara bebas:
- $TRAVIS_PULL_REQUEST menyimpan nombor permintaan tarik atau palsu, jika ini adalah cawangan biasa;
- $TRAVIS_REPO_SLUG menyimpan nama repositori projek.
Algoritma untuk fungsi ini:
Travis CI bertindak balas untuk mengembalikan kod, jadi kehadiran amaran akan memberitahu perkhidmatan untuk menandakan komit sebagai mengandungi ralat.
Sekarang mari kita lihat dengan lebih dekat baris kod ini:
git diff --name-only origin/HEAD > .pvs-pr.list
Hakikatnya ialah Travis CI secara automatik menggabungkan cawangan semasa menganalisis permintaan tarik:
Oleh itu kami menganalisis A4Dan tidak B3->A3. Kerana ciri ini, kita perlu mengira perbezaan dengan A3, iaitu bahagian atas cawangan dari asal.
Terdapat satu butiran penting yang tinggal - caching kebergantungan fail pengepala pada unit terjemahan yang disusun (*.c, *.cc, *.cpp, dll.). Penganalisis mengira kebergantungan ini apabila ia mula-mula dilancarkan dalam mod menyemak senarai fail dan kemudian menyimpannya dalam direktori .PVS-Studio. Travis CI membenarkan anda membuat cache folder, jadi kami akan menyimpan data direktori .PVS-Studio/:
cache:
directories:
- .PVS-Studio/
Kod ini perlu ditambahkan pada fail .travis.yml. Direktori ini menyimpan pelbagai data yang dikumpul selepas analisis, yang akan mempercepatkan analisis senarai fail atau analisis tambahan dengan ketara. Jika ini tidak dilakukan, maka penganalisis sebenarnya akan menganalisis semua fail setiap kali.
Buddy
Seperti Travis CI,
Pertama sekali, kita perlu menambah tindakan baharu pada baris pemasangan:
Mari kita nyatakan pengkompil yang digunakan untuk membina projek. Perhatikan bekas docker yang dipasang dalam tindakan ini. Sebagai contoh, terdapat bekas khas untuk GCC:
Sekarang mari pasang PVS-Studio dan utiliti yang diperlukan:
Mari tambahkan baris berikut pada 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 pergi ke tab Run (ikon pertama) dan tambahkan kod berikut pada medan editor yang sepadan:
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 bahagian Travs-CI, maka kod ini sudah biasa kepada anda, namun, kini terdapat peringkat baharu:
Hakikatnya ialah sekarang kita menganalisis bukan hasil gabungan, tetapi KETUA cawangan dari mana permintaan tarik dibuat:
Jadi kita berada dalam komitmen bersyarat B3 dan kita perlu mendapatkan perbezaan daripada 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 pembolehubah berikut yang Buddy sediakan:
- $BUDDY_EXECUTION_PULL_REQEUST_NO β tarik nombor permintaan;
- $BUDDY_REPO_SLUG β gabungan nama pengguna dan repositori (contohnya maks/ujian).
Sekarang mari kita simpan perubahan menggunakan butang di bawah dan dayakan analisis permintaan tarik:
Tidak seperti Travis CI, kami tidak perlu menentukan .pvs-studio untuk caching, kerana Buddy secara automatik menyimpan semua fail untuk pelancaran berikutnya. Oleh itu, perkara terakhir yang tinggal ialah menyimpan log masuk dan kata laluan untuk PVS-Studio dalam Buddy. Selepas menyimpan perubahan, kami akan dibawa kembali ke Pipeline. Kita perlu meneruskan untuk menyediakan pembolehubah dan menambah log masuk dan kunci untuk PVS-Studio:
Selepas ini, kemunculan permintaan tarik atau komitmen baharu akan mencetuskan semakan. Jika komit mengandungi ralat, Buddy akan menunjukkannya pada halaman permintaan tarik.
AppVeyor
Menyediakan AppVeyor adalah serupa dengan Buddy, kerana segala-galanya berlaku dalam antara muka web dan tidak perlu menambah fail *.yml pada repositori projek.
Mari pergi ke tab Tetapan dalam gambaran keseluruhan projek:
Mari tatal ke bawah halaman ini dan dayakan penjimatan cache untuk mengumpul permintaan tarik:
Sekarang mari pergi ke tab Persekitaran, di mana kita menentukan imej untuk pemasangan dan pembolehubah persekitaran yang diperlukan:
Jika anda telah membaca bahagian sebelumnya, anda sangat biasa dengan kedua-dua pembolehubah ini β PVS_KEY ΠΈ PVS_USERNAME. Jika tidak, izinkan saya mengingatkan anda bahawa mereka perlu untuk mengesahkan lesen penganalisis PVS-Studio. Kami akan melihatnya lagi dalam skrip Bash pada masa hadapan.
Pada halaman yang sama di bawah kami menunjukkan folder untuk caching:
Jika kami tidak melakukan ini, kami akan menganalisis keseluruhan projek dan bukannya beberapa fail, tetapi kami akan mendapat output daripada fail yang ditentukan. Oleh itu, adalah penting untuk memasukkan nama direktori yang betul.
Kini tiba masanya untuk skrip diuji. Buka tab Ujian dan pilih Skrip:
Anda perlu menampal kod berikut ke dalam borang 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 bahagian kod berikut:
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 kepada pembolehubah yang sepatutnya menyimpan nilai lalai ini kelihatan pelik pada pandangan pertama, namun, saya akan menerangkan semuanya sekarang.
Semasa menyediakan penganalisis dalam AppVeyor, saya menemui tingkah laku penganalisis yang sangat pelik. Di satu pihak, semuanya berfungsi dengan betul, tetapi analisis tidak bermula. Saya menghabiskan banyak masa menyedari bahawa kita berada dalam direktori /home/appveyor/projects/testcalc/, dan penganalisis pasti bahawa kita berada dalam /opt/appveyor/build-agent/. Kemudian saya menyedari bahawa pembolehubah $PWD berbohong sedikit. Atas sebab ini, saya mengemas kini nilainya secara manual sebelum memulakan analisis.
Dan kemudian semuanya seperti dahulu:
Sekarang pertimbangkan serpihan 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 mendapat perbezaan antara cawangan di mana permintaan tarik diisytiharkan. Untuk melakukan ini, kami memerlukan pembolehubah persekitaran berikut:
- $APPVEYOR_PULL_REQUEST_NUMBER β tarik nombor permintaan;
- $APPVEYOR_REPO_NAME - nama pengguna dan repositori projek.
Kesimpulan
Sudah tentu, kami tidak mempertimbangkan semua perkhidmatan penyepaduan berterusan yang mungkin, walau bagaimanapun, semuanya mempunyai spesifikasi operasi yang sangat serupa antara satu sama lain. Dengan pengecualian caching, setiap perkhidmatan membuat "basikal" sendiri, jadi semuanya sentiasa berbeza.
Di suatu tempat, seperti di Travis-CI, beberapa baris kod dan caching berfungsi dengan sempurna; di suatu tempat, seperti di AppVeyor, anda hanya perlu menentukan folder dalam tetapan; tetapi di suatu tempat anda perlu mencipta kunci unik dan cuba meyakinkan sistem untuk memberi anda peluang untuk menulis ganti serpihan cache. Oleh itu, jika anda ingin menyediakan analisis permintaan tarik pada perkhidmatan penyepaduan berterusan yang tidak dibincangkan di atas, mula-mula pastikan anda tidak akan menghadapi masalah dengan caching.
Terima kasih kerana memberi perhatian. Jika ada yang tidak berjaya, sila tulis kepada kami di
Jika anda ingin berkongsi artikel ini dengan khalayak berbahasa Inggeris, sila gunakan pautan terjemahan: Maxim Zvyagintsev.
Sumber: www.habr.com