
A PVS-Studio elemzője C és C++ nyelveken Linux és macOS rendszereken, a 7.04-es verziótól kezdődően, tesztelési lehetőséget kapott a megadott fájlok listájának ellenőrzésére. Az új módban beállíthatja az elemzőt a commitok és pull requestek ellenőrzésére. Ebben a cikkben arról lesz szó, hogyan állítható be a GitHub-projekt módosított fájljainak listájának ellenőrzése népszerű CI (Folytatólagos Integráció) rendszerekben, mint a Travis CI, Buddy és AppVeyor.
Fájlok ellenőrzési mód
— egy olyan eszköz, amely képes az egyik program forráskódjában lévő hibák és potenciális sebezhetőségek felfedezésére, C, C++, C# és Java nyelveken írt programok esetén. 64-bites rendszereken működik Windows, Linux és macOS alatt.
A PVS-Studio 7.04-es verziójában, Linux és macOS rendszereken megjelent a forrásfájlok listájának ellenőrzési módja. Ez olyan projektekhez működik, ahol az építési rendszer képes generálni a fájlt . Ez arra szolgál, hogy az elemző információkat nyerjen a megadott fájlok fordításáról. Ha az Ön építési rendszere nem támogatja a compile_commands.json fájl generálását, megpróbálhatja generálni ezt a fájlt a .
segítségével. Ezen kívül a fájlok listájának ellenőrzési módja használható a fordító indításainak strace nyomvonalnaplójával (pvs-studio-analyzer trace). Ehhez először teljes építést kell végezni a projekten, és nyomon kell követni azt, hogy az elemző összegyűjtse a fordítási paraméterek teljes információját az ellenőrzött fájlokról.
Ennek a megoldásnak azonban van egy jelentős hátránya - a projekt teljes építését minden alkalommal nyomon kell követni, ami önmagában is ellentmond a commit gyors ellenőrzésének ideájának. Vagy, ha a nyomvonal eredményét cache-eljük, a következő elemző futások hiányosak lehetnek, ha az utána a forrásfájlok közötti függőségek struktúrája megváltozik (például egy forrásfájlba új #include került beillesztésre).
Ezért nem ajánljuk a fájlok ellenőrzési módjának használatát a nyomvonal naplóval commitok vagy pull requestek ellenőrzésére. Ha a commitok ellenőrzésekor végezhetők inkrementális építések, érdemes megfontolni az .
Az elemzéshez szükséges forrásfájlok listája szöveges fájlba kerül mentésre, és a paramétert használva átadásra kerül az elemzőnek -S:
pvs-studio-analyzer analyze ... -f build/compile_commands.json -S check-list.txtEbben a fájlban a fájlok relatív vagy abszolút elérési útját kell megadni, ahol minden új fájl új sorba kerül. Megengedett, hogy ne csak fájlneveket adjunk meg, hanem különböző szövegeket is. Az elemző észleli, hogy ez nem fájl, és figyelmen kívül hagyja a sort. Ez hasznos lehet a kommentálás során, ha a fájlokat manuálisan adják meg. A legtöbb esetben azonban a fájlok listája automatikusan generálódik az elemzés során a CI-ben, például ezek lehetnek a commitból vagy pull requestből származó fájlok.
Most ezzel a móddal gyorsan ellenőrizhetjük az új kódot, mielőtt az a fő fejlesztési ágba kerül. Ahhoz, hogy a vizsgálati rendszer reagáljon az elemző figyelmeztetéseire, az eszközzel plog-converter kiegészítették a zászlót —indicate-warnings:
plog-converter ... --indicate-warnings ... -o /path/to/report.tasks ...Ezzel a zászlóval a konverter nem nullás kódot ad vissza, ha az elemző jelentésében figyelmeztetések találhatóak. A visszatérési kód alapján leállítható a pre-commit hook, a commit vagy a pull request, és a generált elemző jelentés megjeleníthető, megosztható vagy emailben elküldhető.
Megjegyzés. Az elemzés első futtatásakor a fájlok listájának teljes projektet kell elemeznie, mivel az elemzőnek generálnia kell a projekt forrásfájljainak és fejlécfájljainak függőségi fáját. Ez a C és C++ fájlok elemzésének sajátossága. A későbbiekben a függőségi fájl tárolható és az automatikusan frissül az elemző által. Az előny, hogy a fájl ellenőrzése a fájl lista ellenőrzési módjában a folyamatos elemzés helyett azt jelenti, hogy csak ezt a fájlt kell tárolni, nem pedig a objektumfájlokat.
A pull request elemzésének általános elvei
A teljes projekt elemzése elég sok időt vesz igénybe, ezért van értelme csak annak egy részét ellenőrizni. A probléma az, hogy meg kell különböztetni az új fájlokat a projekt többi fájljától.
Nézzük meg a commitok egy fának a példáját két ággal:

Képzeljük el, hogy a commit A1 elég sok olyan kódot tartalmaz, amit már ellenőriztünk. Nemrégiben egy ágat készítettünk a commitból A1 és néhány fájlt módosítottunk.
Nyilván észrevette, hogy miután A1 még két commit történt, de ezek is más ágak összevonása volt, hiszen nem commitálunk a master. És most elérkezett az idő, amikor hotfix kész. Ezért létrejött egy pull request az összevonásra B3 és A3.
Persze ellenőrizhettük volna az összevonásuk teljes eredményét, de ez túl hosszú és indokolatlan lett volna, mivel csak néhány fájl változott. Ezért hatékonyabb csak a megváltozottakat elemezni.
Ehhez a következő parancsot használjuk az ágak közötti eltérés megtekintésére, miközben a HEAD ágban vagyunk, ahonnan a masterbe szeretnénk összevonni:
git diff --name-only HEAD origin/$MERGE_BASE > .pvs-pr.list$MERGE_BASE erről részletesen később beszélünk. Az a helyzet, hogy nem minden CI szolgáltatás nyújtja a szükséges információt az összevonás alapjáról, ezért minden alkalommal új módszereket kell kitalálni ezeknek az adatoknak a beszerzésére. Ezekről részletesen írunk az alább leírt web-szolgáltatásokban.
Tehát megkaptuk az ágak közötti eltérést, pontosabban a megváltozott fájlok neveinek listáját. Most át kell adnunk a fájlt .pvs-pr.list (amibe korábban irányítottuk a kimenetet) az elemzőnek:
pvs-studio-analyzer analyze -j8
-o PVS-Studio.log
-S .pvs-pr.listAz elemzés után a naplófájl (PVS-Studio.log) kényelmesebb formátumba való konvertálására van szükség:
plog-converter -t errorfile PVS-Studio.log --cerr -wEz a parancs kiadja a hibák listáját a (a hibaüzenetek standard kimeneti folyamata).
Viszont nem csak a hibákat kell kijelentenünk, hanem tájékoztatnunk kell az építési és tesztelési szolgáltatásunkat a problémák létezéséről. Ezért a konverterhez hozzá lett adva egy zászló -W (—indicate-warnings). Ha az elemző legalább egy figyelmeztetést jelez, a program visszatérési kódja plog-converter 2-re változik, ami viszont tájékoztatja a CI szolgáltatást a potenciális hibák jelenlétéről a pull request fájljaiban.
Travis CI
A konfiguráció egy fájl formájában lett végrehajtva .travis.yml. A kényelem kedvéért javaslom, hogy mindent tegyél egy külön bash-skriptre a benne lévő funkciókkal, amelyeket a fájlból kell hívni: .travis.yml (bash scripted_neve.sh funkció_neve).
A szükséges kódot hozzáadjuk a skripthez, így nagyobb funkcionalitást kapunk. Az bashszekcióban a következőt írjuk: install install: - bash .travis.sh travis_install
Ha voltak bármilyen utasításaid, akkor ezeket átviheted a skriptre, eltávolítva a kötőjeleket.Megnyitjuk a fájlt
.travis.sh és hozzáadjuk az elemző telepítését a travis_install() függvényhez:
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
}Most már hozzáadjuk a szekcióhoz script elemzés indítása:
script:
- bash .travis.sh travis_scriptÉs a bash-szkriptben:
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
}Ezt a kódot a projekt összeállítása után kell futtatni, például, ha CMake-t használtál:
travis_script() {
CMAKE_ARGS="-DCMAKE_EXPORT_COMPILE_COMMANDS=On ${CMAKE_ARGS}"
cmake $CMAKE_ARGS CMakeLists.txt
make -j8
}Így fog kinézni:
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
}Valószínűleg már észrevetted a megadott környezeti változókat $TRAVIS_PULL_REQUEST és $TRAVIS_BRANCH. A Travis CI automatikusan deklarálja őket:
- $TRAVIS_PULL_REQUEST tartalmazza a pull request számát, vagy hamis, ha ez egy normál ág;
- $TRAVIS_REPO_SLUG tartalmazza a projekt repozitóriumának nevét.
E funkció működési algoritmus:

A Travis CI reagál a visszatérési kódokra, így a figyelmeztetések jelenléte azt jelzi a szolgáltatásnak, hogy a commitot hibásként kell megjelölni.
Most nézzük meg részletesebben ezt a kódsort:
git diff --name-only origin/HEAD > .pvs-pr.listA helyzet az, hogy a Travis CI automatikusan egyesíti az ágakat a pull request elemzése során:

Ezért elemezni fogjuk A4, nem pedig B3->A3. Ezzel a sajátossággal számolni kell, hogy meg tudjuk határozni a különbséget A3, ami pontosan a csúcság az origin.
Maradt egy fontos részlet — a fordítási egységek (*.c, *.cc, *.cpp stb.) fejlécfájljaiból származó függőségek gyorsítótárazása. Ezeket a függőségeket az elemző az első futtatás során számolja ki, fájlok lista ellenőrzési módban, és ezen a .PVS-Studio könyvtárban tárolja. A Travis CI lehetővé teszi a mappák gyorsítótárazását, ezért elmentjük az adatokat a könyvtárban .PVS-Studio/:
cache:
directories:
- .PVS-Studio/Ezt a kódot a fájlba kell beilleszteni .travis.yml. Ez a könyvtár különböző, az elemzés után gyűjtött adatokat tárol, amelyek jelentősen felgyorsítják a fájlok listájának elemzését vagy az inkrementális elemzést. Ha ezt nem tesszük meg, az elemző gyakorlatilag minden alkalommal elemezni fogja az összes fájlt.
Buddy
Mint a Travis CI, lehetővé teszi a projekteket automatizáltan összeállítani és tesztelni, amelyek a GitHub-on tárolódnak. A Travis CI-től eltérően a webes felületen állítható be (támogatja a bash-t), így nem szükséges konfigurációs fájlokat tárolni a projektben.
Elsősorban új lépést kell hozzáadnunk az építési vonalhoz:

Megadjuk a fordítót, amelyet a projekt összerakásához használtunk. Ne feledje a docker konténert, amely ebben a lépésben van. Például a GCC-hez külön konténer áll rendelkezésre:

Most telepítsük a PVS-Studio-t és a szükséges eszközöket:

Adja hozzá a következő sorokat a szerkesztőhöz:
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-studioMost lépjünk a Futtatás fülre (első ikonkép), és a szerkesztő megfelelő mezőjébe adjuk hozzá a következő kódot:
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 -wHa olvastad a Travs-CI-nek szentelt részt, akkor ez a kód már ismerős lehet számodra, azonban most egy új szakasz következik:

Az a helyzet, hogy most nem a találkozás eredményét elemezzük, hanem a pull request-ből származó ág HEAD-jét:

Ezért egy feltételes elágazásban vagyunk B3 és meg kell kapnunk a különbséget a 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.listA meghatározáshoz A3 használjuk a GitHub API-t:
https://api.github.com/repos/${USERNAME}/${REPO}/pulls/${PULL_REQUEST_ID}A következő változókat használtuk, amelyeket Buddy biztosít:
- $BUDDY_EXECUTION_PULL_REQEUST_NO — a pull request száma;
- $BUDDY_REPO_SLUG — a felhasználónév és a tároló kombinációja (például max/test).
Most már elmentjük a módosításokat az alábbi gomb segítségével, és engedélyezzük a pull request elemzést:

A Travis CI-val ellentétben nekünk nem szükséges megadni .pvs-studio a cache-eléshez, mivel a Buddy automatikusan cache-eli az összes fájlt a következő futtatásokhoz. Ezért már csak annyi van hátra, hogy elmentsük a PVS-Studio felhasználónév és jelszó adatait a Buddy-ban. A módosítások mentése után visszakerülünk a Pipeline-ba. Át kell lépnünk a változók beállítására, és hozzáadni a PVS-Studio felhasználónevet és kulcsot:

Ezt követően egy új pull request vagy commit létrejöttekor automatikusan elindul az ellenőrzés. Ha a commit hibát tartalmaz, akkor a Buddy jelezni fog a pull request oldalán.
AppVeyor
Az AppVeyor beállítása hasonló a Buddy-hoz, mivel minden a webes felületen történik, és nem szükséges *.yml fájlt hozzáadni a projekt repositoryhoz.
Lépjünk a Projekt áttekintésének Beállítások fülére:

Görgessünk lejjebb az oldalon, és aktiváljuk a cache mentését a pull request-ekhez:

Most lépjünk az Environment fülre, ahol megadjuk a build képet és a szükséges környezeti változókat:

Ha elolvastad az előző szakaszokat, akkor jól ismered ezeket a két változót — PVS_KEY és PVS_USERNAME. Ha nem, akkor emlékeztetnélek, hogy ezek a PVS-Studio elemző licence ellenőrzéséhez szükségesek. Később ismét találkozni fogunk velük a Bash script-ekben.
Ugyanezen az oldalon, alul megadjuk a cache mappát:

Ha ezt nem tesszük meg, akkor ahelyett, hogy pár fájlt elemeznék, az egész projektet elemezni fogjuk, de a kimenetet a megadott fájlok szerint kapjuk. Ezért fontos, hogy a megfelelő könyvtár nevét megadjuk.
Most elérkezett az idő a ellenőrző scriptre. Nyissuk meg a Teszt fülét és válasszuk a Script lehetőséget:

Ebben a formában be kell illesztenünk az alábbi kódot:
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 -wFigyeljünk a kód következő részére:
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
fiBár az érték hozzárendelése a pwd parancsnak, ami a változót tárolja, első látásra furcsának tűnik, valójában ésszerű magyarázata van.
Amikor az AppVeyor-ban beállítottam az elemzőt, furcsa viselkedéssel találkoztam. Egyrészt minden jól működött, de az elemzés nem indult el. Sok időt töltöttem azzal, hogy észre vegyem: a /home/appveyor/projects/testcalc/ könyvtárban vagyunk, míg az elemző azt hiszi, hogy az /opt/appveyor/build-agent/ könyvtárban tartózkodunk. Ekkor realizáltam, hogy a $PWD változó kicsit hazudik. Ezért kézzel frissítettem az értékét az elemzés indítása előtt.
Aztán minden folytatódik, mint korábban:

Most nézzük meg a következő részt:
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"`Ebben a részben megkapjuk a különbséget a pull request által érintett ágak között. Ehhez az alábbi környezeti változókra van szükség:
- $APPVEYOR_PULL_REQUEST_NUMBER — a pull request száma;
- $APPVEYOR_REPO_NAME — a felhasználó és a projekt repository neve.
Zárás
Természetesen nem vizsgáltuk meg az összes folyamatintegrációs szolgáltatást, de mindegyiknek nagyon hasonló a működése. A gyorsítótár kivételével minden szolgáltatás más 'biciklit' épít, tehát mindegyik különböző.
Valahol, mint a Travis-CI-nél, pár sor kód és a gyorsítótár hibátlanul működik; máshol, mint az AppVeyor-nál, csak meg kell adni a mappát a beállításokban; de van, ahol egyedi kulcsokat kell létrehozni, és megpróbálni meggyőzni a rendszert, hogy lehetőséget adjon a gyorsítótárazott rész felülírására. Ezért, ha szeretnéd beállítani a pull requestek elemzését egy olyan folyamatintegrációs szolgáltatásnál, amely nem volt felmérve korábban, először győződj meg róla, hogy a gyorsítótárazással nem lesznek problémáid.
Köszönöm a figyelmet. Ha valami nem működik, bátran írj nekünk a . Segítünk és támogatunk.
Ha meg szeretné osztani ezt a cikket angol nyelvű közönséggel, kérem, használja a fordítás linkjét: Maxim Zvyagintsev. .
Forrás: habr.com
