
Volite GitLab i ne volite greške? Želite poboljšati kvalitetu izvornog koda? Onda ste na pravom mjestu. Danas ćemo vam pokazati kako postaviti C# analizator PVS-Studio za provjeru merge zahtjeva. Svima želimo veselo raspoloženje i ugodno čitanje.
— to je alat za otkrivanje grešaka i potencijalnih ranjivosti u izvornom kodu programa pisanih na jezicima C, C++, C# i Java. Radi na 64-bitnim sustavima na Windows, Linux i macOS. Može analizirati kod namijenjen za 32-bitne, 64-bitne i ugrađene ARM platforme.
Usput, objavili smo PVS-Studio 7.08, u kojem smo napravili mnogo toga . Na primjer:
- analizator C# za Linux i macOS;
- plugin za Rider;
- novi režim provjere popisa datoteka.
Režim provjere popisa datoteka
Ranije je bilo potrebno proslijediti analizatoru .xml sa popisom datoteka kako bi se provjerile određene datoteke. No, budući da to nije baš praktično, dodali smo mogućnost proslijediti .txt, što znatno olakšava život.
Da biste provjerili određene datoteke, potrebno je navesti oznaku —sourceFiles (-f) i proslijediti .txt sa popisom datoteka. Izgleda ovako:
pvs-studio-dotnet -t path/to/solution.sln -f fileList.txt -o project.jsonAko vas zanima postavljanje provjere za commitove ili pull zahtjeve, to također možete učiniti koristeći ovaj režim. Razlika će biti u dobivanju popisa datoteka za analizu i ovisit će o tome koje sustave koristite.
Način provjere merge zahtjeva
Osnovna suština provjere je da problemi otkriveni analizatorom ne dospiju u master granu tijekom spajanja. Također, ne želimo svaki put analizirati cijeli projekt. Tim više što imamo popis izmijenjenih datoteka tijekom spajanja grana. Stoga predlažem da dodamo provjeru merge zahtjeva.
Ovako izgleda merge zahtjev prije uvođenja statičkog analizatora:

To jest, sve greške koje su bile u grani changes, preći će u glavnu granu. Budući da to ne želimo, dodajemo analizu, i sada shema izgleda ovako:

Analiziramo changes2 i, ako nema grešaka, prihvaćamo merge zahtjev, a u suprotnom ga odbacujemo.
Usput, ako vas zanima analiza commitova i pull zahtjeva za C/C++, možete pročitati o tome .
GitLab
— web alat za životni ciklus DevOps s otvorenim izvorom, koji predstavlja sustav za upravljanje repozitorijima koda za Git s vlastitom wikijem, sustavom za praćenje grešaka, CI/CD pipeline-om i drugim funkcijama.
Prije nego što započnete s analizom merge request-ova, potrebno je registrirati se i učitati svoj projekt. Ako ne znate kako to učiniti, predlažem mojeg kolegu.
Napomena. Metoda postavljanja okruženja opisana u nastavku jedan je od mogućih načina. Cilj je pokazati korake potrebne za postavljanje okruženja za analizu i pokretanje analizatora. Možda će za vas optimalnije biti razdvajanje faza pripreme okruženja (dodavanje repozitorija, instalacija analizatora) i analize: na primjer, priprema Docker slika s potrebnim okruženjem i njihova upotreba ili neki drugi način.
Kako biste jasnije shvatili što će se događati, predlažem da pogledate sljedeću shemu:

Za rad analizatoru je potreban .NET Core SDK 3, stoga prije instalacije analizatora treba dodati Microsoft repozitorije iz kojih će se instalirati potrebne zavisnosti za analizator. Dodavanje Microsoft repozitorija za različite distribucije Linuxa .
Za instalaciju PVS-Studio putem paketnog menadžera također će biti potrebno dodati PVS-Studio repozitorije. Dodavanje repozitorija za različite distribucije detaljnije je opisano u .
Analizatoru je potreban licencni ključ. Probnu licencu možete dobiti na .
Napomena. Imajte na umu da je za opisani način rada (analiza merge request-ova) potrebna Enterprise licenca. Stoga, ako želite isprobati ovaj način rada, u polju "Poruka" ne zaboravite naznačiti da vam je potrebna upravo Enterprise licenca.
Ako se dogodi merge request, trebamo analizirati samo popis izmijenjenih datoteka, inače analiziramo sve datoteke. Nakon analize potrebno je konvertirati logove u željeni format.
Sada, imajući pred sobom algoritam rada, možemo preći na pisanje skripte. Za to je potrebno promijeniti datoteku .gitlab-ci.yml ili, ako ne postoji, stvoriti je. Za njeno stvaranje potrebno je kliknuti na naziv vašeg projekta -> Postavi CI/CD.

Sada smo spremni za pisanje skripte. Prvo, hajde da napišemo kod koji će instalirati analizator i uneti licencu:
before_script:
- apt-get update && apt-get -y install wget gnupg
- apt-get -y install git
- wget https://packages.microsoft.com/config/debian/10/
packages-microsoft-prod.deb -O packages-microsoft-prod.deb
- dpkg -i packages-microsoft-prod.deb
- apt-get update
- apt-get install apt-transport-https
- apt-get update
- 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-dotnet
- pvs-studio-analyzer credentials $PVS_NAME $PVS_KEY
- dotnet restore "$CI_PROJECT_DIR"/Test/Test.slnBudući da instalacija i aktivacija treba da se obave pre svih drugih skripti, koristićemo posebnu oznaku before_script. Malo ću objasniti ovaj deo.
Priprema za instalaciju analizatora:
- wget https://packages.microsoft.com/config/debian/10/
packages-microsoft-prod.deb -O packages-microsoft-prod.deb
- dpkg -i packages-microsoft-prod.deb
- apt-get update
- apt-get install apt-transport-https
- apt-get updateDodavanje PVS-Studio i analizator repozitorija:
- 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-dotnetAktivacija licence:
- pvs-studio-analyzer credentials $PVS_NAME $PVS_KEY$PVS_NAME — korisničko ime.
$PVS_KEY — ključ proizvoda.
Obnavljanje zavisnosti projekta, gde $CI_PROJECT_DIR – puna putanja do direktorijuma projekta:
- dotnet restore "$CI_PROJECT_DIR"/Path/To/Solution.slnZa ispravno analiziranje projekat mora biti uspešno kompajliran, a njegove zavisnosti moraju biti obnovljene (na primer, neophodni NuGet paketi moraju biti preuzeti).
Promenljive okruženja koje sadrže licencne informacije možete postaviti tako što ćete kliknuti na Podešavanje, a zatim — na CI / CD.

U otvorenom prozoru pronalazimo stavku Varijable, s desne strane kliknemo na dugme Proširi i dodajemo promenljive. Rezultat bi trebao izgledati ovako:

Sada možemo preći na analizu. Prvo dodajmo skriptu za potpunu analizu. U zastavicu -t prosledimo putanju do rešenja, u zastavicu -o unosimo putanju do datoteke u koju će biti zapisani rezultati analize. Takođe, zanima nas kod povratka. U ovom slučaju nas zanima da rad prestane kada kod povratka sadrži informacije o tome da su tokom analize izdate opaske. Ovako izgleda ovaj deo:
job:
script:
- exit_code=0
- pvs-studio-dotnet -t "$CI_PROJECT_DIR"/Test/Test.sln -o
PVS-Studio.json || exit_code=$?
- exit_code=$((($exit_code & 8)/8))
- if [[ $exit_code == 1 ]]; then exit 1; else exit 0; fiKodovi povrata funkcionišu na osnovu bitne maske. Na primer, ako su tokom analize izdata upozorenja, kod povrata će biti 8. Ako licenca ističe u toku meseca, kod povrata će biti 4. Ako su tokom analize otkrivene greške, a licenca ističe u toku meseca, kod povrata će sadržati obe vrednosti: sabiramo brojeve i dobijamo konačni kod povrata — 8+4=12. Tako možemo proveriti odgovarajuće bitove i dobiti informacije o različitim stanjima tokom analize. Detaljnije informacije o kodovima povrata su opisane u odeljku "Kodovi povrata pvs-studio-dotnet (Linux / macOS)" dokumentacije.".
U ovom slučaju nas interesuju svi kodovi povrata gde se pojavljuje 8.
- exit_code=$((($exit_code & 8) / 8))Dobijamo 1 kada kod povrata sadrži bit koji nas zanima, a inače dobijamo 0.
Došlo je vreme da dodamo analizu merge request-a. Pre nego što to uradimo, pripremićemo mesto za skriptu. Potrebno je da se izvršava samo kada se desi merge request. Izgleda ovako:
merge:
script:
only:
- merge_requestsPrelazimo na samu skriptu. Susreo sam se sa time da virtuelna mašina ništa ne zna o origin/master. Zato joj malo pomažemo:
- git fetch originSada dobijamo razliku između grana i čuvamo rezultat u txt fajl:
- git diff --name-only origin/master $CI_COMMIT_SHA > pvs-fl.txtGdje $CI_COMMIT_SHA – heš poslednjeg commit-a.
Zatim pokrećemo analizu liste fajlova koristeći flag -f. U njega prosledjujemo ranije dobijen .txt fajl. Takođe, kao i kod potpune analize, gledamo kodove povrata:
- exit_code=0
- pvs-studio-dotnet -t "$CI_PROJECT_DIR"/Test/Test.sln -f
pvs-fl.txt -o PVS-Studio.json || exit_code=$?
- exit_code=$((($exit_code & 8) / 8))
- if [[ $exit_code == 1 ]]; then exit 1; else exit 0; fiPuna skripta za proveru merge request-a izgleda ovako:
merge:
script:
- git fetch origin
- git diff --name-only origin/master $CI_COMMIT_SHA > pvs-fl.txt
- exit_code=0
- pvs-studio-dotnet -t "$CI_PROJECT_DIR"/Test/Test.sln -f
pvs-fl.txt -o PVS-Studio.json || exit_code=$?
- exit_code=$((($exit_code & 8) / 8))
- if [[ $exit_code == 1 ]]; then exit 1; else exit 0; fi
only:
- merge_requestsPreostaje samo da dodamo konverziju loga nakon što su svi skripti izvršeni. Koristimo oznaku after_script i alatku plog-converter:
after_script:
- plog-converter -t html -o eLog ./PVS-Studio.jsonAlat — je open source projekt koji se koristi za prevođenje izvještaja o greškama analizatora u različite oblike, poput HTML-a. Detaljniji opis alata naveden je u pododjeljku "Plog Converter Utility" .
Usput, ako želite lako raditi s .json izvještajem lokalno iz IDE-a, preporučujem naš za IDE Rider. Detaljnije o njegovoj upotrebi opisano je u .
Radi lakšeg rada, evo .gitlab-ci.yml u cijelosti:
image: debian
before_script:
- apt-get update && apt-get -y install wget gnupg
- apt-get -y install git
- wget https://packages.microsoft.com/config/debian/10/
packages-microsoft-prod.deb -O packages-microsoft-prod.deb
- dpkg -i packages-microsoft-prod.deb
- apt-get update
- apt-get install apt-transport-https
- apt-get update
- 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-dotnet
- pvs-studio-analyzer credentials $PVS_NAME $PVS_KEY
- dotnet restore "$CI_PROJECT_DIR"/Test/Test.sln
merge:
script:
- git fetch origin
- git diff --name-only origin/master $CI_COMMIT_SHA > pvs-fl.txt
- exit_code=0
- pvs-studio-dotnet -t "$CI_PROJECT_DIR"/Test/Test.sln -f
pvs-fl.txt -o PVS-Studio.json || exit_code=$?
- exit_code=$((($exit_code & 8)/8))
- if [[ $exit_code == 1 ]]; then exit 1; else exit 0; fi
only:
- merge_requests
job:
script:
- exit_code=0
- pvs-studio-dotnet -t "$CI_PROJECT_DIR"/Test/Test.sln -o
PVS-Studio.json || exit_code=$?
- exit_code=$((($exit_code & 8)/8))
- if [[ $exit_code == 1 ]]; then exit 1; else exit 0; fi
after_script:
- plog-converter -t html -o eLog ./PVS-Studio.jsonJednom kada dodate sve u datoteku, kliknite na Commit changes. Da biste provjerili je li sve u redu, idemo u CI/CD -> Cevovodi -> Ispunjeno. Otvorit će se prozor virtualne mašine u kojem bi na kraju trebalo biti sljedeće:

Vidjeli ste Job succeeded – uspjeh, sve super. Sada možemo i testirati što je napravljeno.
Primjeri rada
Za primjer rada stvorit ćemo jednostavan projekt (u master) u kojem će biti nekoliko datoteka. Nakon toga, u drugoj grani promijenit ćemo samo jednu datoteku i pokušati napraviti merge request.
Razmotrit ćemo dva slučaja: kada promijenjena datoteka sadrži grešku i kada ne. Prvo primjer s greškom.
Pretpostavimo da u master grani postoji datoteka Program.cs, koja ne sadrži greške, a u drugoj grani programer je dodao pogrešan kod i želi napraviti merge request. Koju je točno grešku napravio – nije toliko važno, bitno je da ona postoji. Na primjer, zaboravio je operator throw (da, ):
void MyAwesomeMethod(String name)
{
if (name == null)
new ArgumentNullException(....);
// radite nešto
....
}Pogledajmo rezultat analize primjera s greškom. Također, kako bismo bili sigurni da je samo jedna datoteka analizirana, dodao sam zastavicu -r u redak za pokretanje pvs-studio-dotnet:

Vidimo da je analizator pronašao grešku i nije dopustio spajanje grana.
Provjeravamo primjer bez greške. Ispravimo kod:
void MyAwesomeMethod(String name)
{
if (name == null)
throw new ArgumentNullException(....);
// radite nešto
....
}Rezultati analize merge requesta:

Kao što vidimo, greške nisu pronađene, a izvršenje zadatka prošlo je uspješno, što smo i željeli provjeriti.
Zaključak
Filtriranje lošeg koda prije spajanja grana — to je vrlo zgodno i ugodno. Stoga, ako koristite CI/CD, pokušajte integrirati statički analizator za provjeru. Osim toga, to se radi prilično lako.
Hvala na pažnji.
Ako želite podijeliti ovaj članak s engleskom publikom, molim vas koristite link na prijevod: Nikolay Mironov. .
Izvor: habr.com
