Analiza urezivanja i pull zahtjeva u Travis CI, Buddy i AppVeyor koristeći PVS-Studio

Analiza urezivanja i pull zahtjeva u Travis CI, Buddy i AppVeyor koristeći PVS-Studio
U analizatoru PVS-Studio za jezike C i C++ na Linuxu i macOS-u, počevši od verzije 7.04, pojavila se testna opcija za provjeru liste navedenih datoteka. Koristeći novi način rada, možete konfigurirati analizator da provjerava urezivanje i povlačenje zahtjeva. Ovaj članak će vam reći kako da podesite provjeru liste promijenjenih datoteka GitHub projekta u popularnim CI (Continuous Integration) sistemima kao što su Travis CI, Buddy i AppVeyor.

Način provjere liste datoteka

PVS Studio je alat za identifikaciju grešaka i potencijalnih ranjivosti u izvornom kodu programa napisanih u C, C++, C# i Javi. Radi na 64-bitnim sistemima na Windows, Linux i macOS.

U verziji PVS-Studio 7.04 za Linux i macOS pojavio se način za provjeru liste izvornih datoteka. Ovo radi za projekte čiji sistem izgradnje vam omogućava da generišete datoteku compile_commands.json. Potrebno je da analizator izdvoji informacije o kompilaciji navedenih datoteka. Ako vaš sistem izgradnje ne podržava generiranje datoteke compile_commands.json, možete pokušati generirati takvu datoteku pomoću uslužnog programa Bear.

Takođe, režim provere liste datoteka može se koristiti zajedno sa evidencijom praćenja pokretanja kompajlera (pvs-studio-analyzer trace). Da biste to učinili, morat ćete prvo izvršiti potpunu izgradnju projekta i pratiti ga tako da analizator prikupi potpune informacije o parametrima kompilacije svih datoteka koje se provjeravaju.

Međutim, ova opcija ima značajan nedostatak - morat ćete ili izvršiti potpuni trag izgradnje cijelog projekta svaki put kada ga pokrenete, što je samo po sebi u suprotnosti s idejom brze provjere urezivanja. Ili, ako keširate sam rezultat praćenja, naredna pokretanja analizatora mogu biti nepotpuna ako se struktura zavisnosti izvornih datoteka promijeni nakon praćenja (na primjer, novi #include se dodaje jednoj od izvornih datoteka).

Stoga, ne preporučujemo korištenje načina provjere liste datoteka s dnevnikom praćenja za provjeru urezivanja ili zahtjeva za povlačenjem. U slučaju da možete napraviti inkrementalnu izgradnju kada provjeravate urezivanje, razmislite o korištenju moda inkrementalna analiza.

Lista izvornih datoteka za analizu se sprema u tekstualnu datoteku i prosljeđuje analizatoru pomoću parametra -S:

pvs-studio-analyzer analyze ... -f build/compile_commands.json -S check-list.txt

Ova datoteka specificira relativne ili apsolutne putanje do datoteka, a svaki novi fajl mora biti na novom redu. Prihvatljivo je navesti ne samo nazive datoteka za analizu, već i razni tekst. Analizator će vidjeti da ovo nije datoteka i zanemarit će liniju. Ovo može biti korisno za komentiranje ako su datoteke specificirane ručno. Međutim, često će se tokom analize u CI generisati lista datoteka, na primjer, to mogu biti datoteke iz zahtjeva za urezivanje ili povlačenje.

Sada, koristeći ovaj način rada, možete brzo provjeriti novi kod prije nego što uđe u glavnu razvojnu granu. Da bi se osiguralo da sistem za skeniranje odgovara na upozorenja analizatora, uslužni program plog-konverter zastava dodana --indicate-warnings:

plog-converter ... --indicate-warnings ... -o /path/to/report.tasks ...

Sa ovom zastavicom, pretvarač će vratiti kod koji nije nula ako postoje upozorenja u izvještaju analizatora. Koristeći povratni kod, možete blokirati zakačicu prije urezivanja, urezivanje ili zahtjev za povlačenjem, a generirani izvještaj analizatora može se prikazati, dijeliti ili poslati e-poštom.

Bilješka. Kada prvi put počnete analizirati listu datoteka, cijeli projekat će biti analiziran, jer analizator treba da generiše datoteku zavisnosti izvornih datoteka projekta na fajlovima zaglavlja. Ovo je karakteristika analize C i C++ datoteka. U budućnosti, datoteka zavisnosti može biti keširana i analizator će je automatski ažurirati. Prednost provjere urezivanja kada koristite način provjere liste datoteka u odnosu na korištenje inkrementalnog načina analize je u tome što trebate keširati samo tu datoteku, a ne objektne datoteke.

Opći principi analize zahtjeva za povlačenjem

Analiza cijelog projekta oduzima dosta vremena, pa je logično provjeriti samo određeni dio. Problem je što morate odvojiti nove datoteke od ostalih projektnih datoteka.

Pogledajmo primjer stabla urezivanja sa dvije grane:

Analiza urezivanja i pull zahtjeva u Travis CI, Buddy i AppVeyor koristeći PVS-Studio

Zamislimo tu obavezu A1 sadrži prilično veliku količinu koda koji je već testiran. Malo ranije smo napravili granu od komita A1 i promijenio neke fajlove.

To ste, naravno, primetili posle A1 dogodila su se još dva obvezivanja, ali su to bila i spajanja drugih grana, jer se ne obavezujemo majstor. A sada je došlo vrijeme kada hotfix spreman. Zbog toga se pojavio pull request za spajanje B3 и A3.

Naravno, bilo bi moguće provjeriti cijeli rezultat njihovog spajanja, ali to bi bilo previše vremena i neopravdano, jer je promijenjeno samo nekoliko fajlova. Stoga je efikasnije analizirati samo promijenjene.

Da bismo to uradili, dobijamo razliku između grana, koja se nalazi u GLAVI grane iz koje želimo da se spojimo u master:

git diff --name-only HEAD origin/$MERGE_BASE > .pvs-pr.list

$MERGE_BASE kasnije ćemo to detaljno pogledati. Činjenica je da ne pruža svaki CI servis potrebne informacije o bazi podataka za spajanje, tako da svaki put morate smišljati nove načine za dobivanje ovih podataka. Ovo će biti detaljno opisano u nastavku u svakom od opisanih web servisa.

Dakle, dobili smo razliku između grana, tačnije, listu imena datoteka koje su promijenjene. Sada moramo dati fajl .pvs-pr.list (preusmjerili smo izlaz iznad na njega) u analizator:

pvs-studio-analyzer analyze -j8 
                            -o PVS-Studio.log 
                            -S .pvs-pr.list

Nakon analize, moramo konvertovati datoteku dnevnika (PVS-Studio.log) u format koji je lak za čitanje:

plog-converter -t errorfile PVS-Studio.log --cerr -w

Ova komanda će ispisati greške u stderr (standardni izlaz poruke o grešci).

Tek sada moramo ne samo prikazati greške, već i obavijestiti našu službu za montažu i testiranje o prisutnosti problema. U tu svrhu konvertoru je dodana zastavica -W (--indicate-warnings). Ako postoji barem jedno upozorenje analizatora, povratni kod uslužnog programa plog-konverter će se promijeniti u 2, što će zauzvrat obavijestiti CI uslugu o prisutnosti potencijalnih grešaka u datotekama zahtjeva za povlačenjem.

Travis C.I.

Konfiguracija je napravljena kao fajl .travis.yml. Radi praktičnosti, savjetujem vam da sve stavite u zasebnu bash skriptu s funkcijama koje će biti pozvane iz datoteke .travis.yml (bash ime_skripte.sh ime_funkcije).

Skripti ćemo dodati potreban kod na bash, na ovaj način ćemo dobiti više funkcionalnosti. U sekciji instalirajte hajde da napišemo sledeće:

install:
  - bash .travis.sh travis_install

Ako ste imali instrukcije, možete ih prenijeti u skriptu, uklanjajući crtice.

Hajde da otvorimo fajl .travis.sh i dodajte postavku analizatora u funkciju 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 
}

Sada dodajmo sekciju skripta izvrši analizu:

script:
  - bash .travis.sh travis_script

I u bash skripti:

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
}

Ovaj kod se mora pokrenuti nakon izgradnje projekta, na primjer, ako ste imali build na CMake:

travis_script() {
  CMAKE_ARGS="-DCMAKE_EXPORT_COMPILE_COMMANDS=On ${CMAKE_ARGS}"
  cmake $CMAKE_ARGS CMakeLists.txt
  make -j8
}

Ispast će ovako:

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
}

Vjerovatno ste već primijetili ove varijable okruženja $TRAVIS_PULL_REQUEST и $TRAVIS_BRANCH. Travis CI ih nezavisno proglašava:

  • $TRAVIS_PULL_REQUEST pohranjuje broj zahtjeva za povlačenjem ili lažan, ako je ovo redovna grana;
  • $TRAVIS_REPO_SLUG pohranjuje ime projektnog spremišta.

Algoritam za ovu funkciju:

Analiza urezivanja i pull zahtjeva u Travis CI, Buddy i AppVeyor koristeći PVS-Studio
Travis CI odgovara na povratne kodove, tako da će prisustvo upozorenja reći servisu da označi urezivanje kao da sadrži greške.

Sada pogledajmo izbliza ovu liniju koda:

git diff --name-only origin/HEAD > .pvs-pr.list

Činjenica je da Travis CI automatski spaja grane dok analizira zahtjev za povlačenjem:

Analiza urezivanja i pull zahtjeva u Travis CI, Buddy i AppVeyor koristeći PVS-Studio
Stoga analiziramo A4, a ne B3->A3. Zbog ove karakteristike moramo izračunati razliku sa A3, što je upravo vrh grane iz Poreklo.

Ostao je jedan važan detalj - keširanje zavisnosti datoteka zaglavlja na prevedene prevodilačke jedinice (*.c, *.cc, *.cpp, itd.). Analizator izračunava ove zavisnosti kada se prvi put pokrene u režimu provere liste fajlova, a zatim ih sprema u .PVS-Studio direktorijum. Travis CI vam omogućava keširanje foldera, tako da ćemo sačuvati podatke direktorija .PVS-Studio/:

cache:
  directories:
    - .PVS-Studio/

Ovaj kod treba dodati u datoteku .travis.yml. Ovaj direktorij pohranjuje različite podatke prikupljene nakon analize, što će značajno ubrzati naredna izvođenja analize liste datoteka ili inkrementalne analize. Ako se to ne uradi, onda će analizator zapravo svaki put analizirati sve datoteke.

prijatelj

Kao Travis CI, prijatelj pruža mogućnost automatske izgradnje i testiranja projekata pohranjenih na GitHub-u. Za razliku od Travis CI, konfiguriše se u web interfejsu (dostupna je podrška za bash), tako da nema potrebe za pohranjivanjem konfiguracionih fajlova u projekat.

Prije svega, moramo dodati novu akciju na montažnu liniju:

Analiza urezivanja i pull zahtjeva u Travis CI, Buddy i AppVeyor koristeći PVS-Studio
Naznačimo kompajler koji je korišten za izgradnju projekta. Obratite pažnju na docker kontejner koji je instaliran u ovoj radnji. Na primjer, postoji poseban kontejner za GCC:

Analiza urezivanja i pull zahtjeva u Travis CI, Buddy i AppVeyor koristeći PVS-Studio
Sada instalirajmo PVS-Studio i potrebne uslužne programe:

Analiza urezivanja i pull zahtjeva u Travis CI, Buddy i AppVeyor koristeći PVS-Studio
Dodajmo sljedeće redove u 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

Sada idemo na karticu Run (prva ikona) i dodamo sljedeći kod u odgovarajuće polje uređivača:

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

Ako pročitate odjeljak o Travs-CI, onda vam je ovaj kod već poznat, međutim, sada je nova faza:

Analiza urezivanja i pull zahtjeva u Travis CI, Buddy i AppVeyor koristeći PVS-Studio
Činjenica je da sada ne analiziramo rezultat spajanja, već GLAVU grane iz koje je napravljen zahtjev za povlačenje:

Analiza urezivanja i pull zahtjeva u Travis CI, Buddy i AppVeyor koristeći PVS-Studio
Dakle, mi smo u uslovnoj obavezi B3 i moramo da dobijemo razliku iz 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

Za utvrđivanje A3 Koristimo GitHub API:

https://api.github.com/repos/${USERNAME}/${REPO}/pulls/${PULL_REQUEST_ID}

Koristili smo sljedeće varijable koje Buddy pruža:

  • $BUDDY_EXECUTION_PULL_REQEUST_NO — broj zahtjeva za povlačenjem;
  • $BUDDY_REPO_SLUG — kombinacija korisničkog imena i spremišta (na primjer max/test).

Sada spremimo promjene pomoću dugmeta ispod i omogućimo analizu zahtjeva za povlačenje:

Analiza urezivanja i pull zahtjeva u Travis CI, Buddy i AppVeyor koristeći PVS-Studio
Za razliku od Travis CI, ne trebamo precizirati .pvs-studio za keširanje, pošto Buddy automatski kešira sve datoteke za naredna pokretanja. Stoga, posljednje što preostaje je da sačuvate login i lozinku za PVS-Studio u Buddyju. Nakon što sačuvamo promjene, bit ćemo vraćeni na Pipeline. Moramo da pređemo na podešavanje varijabli i dodavanje logina i ključa za PVS-Studio:

Analiza urezivanja i pull zahtjeva u Travis CI, Buddy i AppVeyor koristeći PVS-Studio
Nakon toga, pojavljivanje novog zahtjeva za povlačenjem ili urezivanja će pokrenuti pregled. Ako urezivanje sadrži greške, Buddy će to naznačiti na stranici zahtjeva za povlačenjem.

AppVeyor

Podešavanje AppVeyor-a je slično Buddyju, pošto se sve dešava u web interfejsu i nema potrebe za dodavanjem *.yml fajla u repozitorijum projekta.

Idemo na karticu Postavke u pregledu projekta:

Analiza urezivanja i pull zahtjeva u Travis CI, Buddy i AppVeyor koristeći PVS-Studio
Pomaknimo ovu stranicu prema dolje i omogućimo spremanje keša za prikupljanje zahtjeva za povlačenje:

Analiza urezivanja i pull zahtjeva u Travis CI, Buddy i AppVeyor koristeći PVS-Studio
Sada idemo na karticu Environment, gdje navodimo sliku za sklapanje i potrebne varijable okruženja:

Analiza urezivanja i pull zahtjeva u Travis CI, Buddy i AppVeyor koristeći PVS-Studio
Ako ste pročitali prethodne odeljke, vrlo ste upoznati s ove dvije varijable − PVS_KEY и PVS_USERNAME. Ako nisu, da vas podsjetim da su oni neophodni za verifikaciju licence za PVS-Studio analizator. Vidjet ćemo ih ponovo u Bash skriptama u budućnosti.

Na istoj stranici ispod označavamo folder za keširanje:

Analiza urezivanja i pull zahtjeva u Travis CI, Buddy i AppVeyor koristeći PVS-Studio
Ako to ne učinimo, analizirat ćemo cijeli projekt umjesto nekoliko datoteka, ali ćemo dobiti izlaz iz navedenih datoteka. Stoga je važno unijeti ispravan naziv direktorija.

Sada je vrijeme da se skripta testira. Otvorite karticu Testovi i odaberite Skripta:

Analiza urezivanja i pull zahtjeva u Travis CI, Buddy i AppVeyor koristeći PVS-Studio
Morate zalijepiti sljedeći kod u ovaj obrazac:

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

Obratimo pažnju na sljedeći dio koda:

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

Prilično specifična dodjela vrijednosti naredbe pwd varijabli koja bi trebala pohraniti ovu zadanu vrijednost na prvi pogled izgleda čudno, međutim, sada ću sve objasniti.

Prilikom postavljanja analizatora u AppVeyor-u, naišao sam na izuzetno čudno ponašanje analizatora. S jedne strane, sve je funkcionisalo kako treba, ali analiza nije počela. Proveo sam dosta vremena primjećujući da se nalazimo u direktoriju /home/appveyor/projects/testcalc/, a analizator je siguran da se nalazimo u /opt/appveyor/build-agent/. Tada sam shvatio da varijabla $PWD malo laže. Iz tog razloga sam ručno ažurirao njegovu vrijednost prije početka analize.

A onda je sve po starom:

Analiza urezivanja i pull zahtjeva u Travis CI, Buddy i AppVeyor koristeći PVS-Studio
Sada razmotrite sljedeći fragment:

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"`

U njemu dobijamo razliku između grana preko kojih je deklarisan zahtjev za povlačenjem. Za ovo su nam potrebne sljedeće varijable okruženja:

  • $APPVEYOR_PULL_REQUEST_NUMBER — broj zahtjeva za povlačenjem;
  • $APPVEYOR_REPO_NAME - korisničko ime i spremište projekta.

zaključak

Naravno, nismo uzeli u obzir sve moguće usluge kontinuirane integracije, međutim, sve one imaju izuzetno slične operativne specifičnosti jedna drugoj. Sa izuzetkom keširanja, svaki servis pravi svoj „bicikl“, tako da je sve uvek drugačije.

Negdje, kao u Travis-CI, par linija koda i keširanje radi besprijekorno; negdje, kao u AppVeyoru, samo trebate navesti mapu u postavkama; ali negde treba da kreirate jedinstvene ključeve i pokušate da ubedite sistem da vam da mogućnost da prepišete keširani fragment. Stoga, ako želite postaviti analizu zahtjeva za povlačenjem na uslugu kontinuirane integracije o kojoj gore nije bilo riječi, onda se prvo uvjerite da nećete imati problema sa keširanjem.

Hvala vam na pažnji. Ako nešto ne uspije, slobodno nam pišite na podrška. Mi ćemo savjetovati i pomoći.

Analiza urezivanja i pull zahtjeva u Travis CI, Buddy i AppVeyor koristeći PVS-Studio

Ako želite da podijelite ovaj članak sa publikom koja govori engleski, koristite link za prijevod: Maxim Zvyagintsev. Analiza urezivanja i pull zahtjeva u Travis CI, Buddy i AppVeyor koristeći PVS-Studio.

izvor: www.habr.com

Dodajte komentar