
Ljubiš GitLab i ne voliš greške? Želiš poboljšati kvalitetu izvornog koda? Onda si na pravom mestu. Danas ćemo ti pokazati kako podesiti C# analizer PVS-Studio za proveru merge request-ova. Svi jednorog napredak i prijatno čitanje.
— to je alat za otkrivanje grešaka i potencijalnih ranjivosti u izvornom kodu programa napisanih u jezicima C, C++, C# i Java. Radi na 64-bitnim sistemima na Windows, Linux i macOS. Može analizirati kod namenjen za 32-bitne, 64-bitne i ugrađene ARM platforme.
Usput, imali smo izdanje PVS-Studio 7.08, u kojem smo uradili mnogo toga . Na primer:
- C# analizer za Linux i macOS;
- plugin za Rider;
- novi režim provere liste datoteka.
Режим проверки списка файлов
Ranije je da bi proverio određene datoteke, bilo potrebno proslediti analizeru .xml sa spiskom datoteka. Ali pošto to nije bilo baš praktično, dodali smo mogućnost proslediti .txt, što veoma olakšava život.
Da bi proverio određene datoteke, potrebno je navesti flag —sourceFiles (-f) i proslediti .txt sa spiskom datoteka. Izgleda ovako:
pvs-studio-dotnet -t path/to/solution.sln -f fileList.txt -o project.jsonAko te zanima kako da podesiš proveru commit-a ili pull request-ova, možeš to takođe uraditi koristeći ovaj režim. Razlika će se sastojati u dobijanju spiska datoteka za analizu i zavisiće od toga koje sisteme koristiš.
Način provere merge request-a
Osnovna svrha provere je da problemi otkriveni analizerom ne pređu u master granu. Takođe ne želimo da svaki put analiziramo ceo projekat. Pogotovo što pri spajanju grana imamo spisak izmenjenih datoteka. Zato predlažem da dodamo proveru merge request-a.
Ovako izgleda merge request pre implementacije statičkog analizer:

To jest, sve greške koje su bile u grani spremembe, preći će u master granu. Pošto to ne bismo želeli, dodajemo analizu, i sada shema izgleda ovako:

Analiziramo changes2 i, ako nema grešaka, prihvatamo merge request, inače ga odbijamo.
Usput, ako te interesuje analiza commit-a i pull request-ova za C/C++, možeš pročitati o tome .
GitLab
— web alat životnog ciklusa DevOps sa otvorenim kodom, koji predstavlja sistem upravljanja repozitorijumima koda za Git sa sopstvenom wiki, sistemom praćenja grešaka, CI/CD pipeline-om i drugim funkcijama.
Preden se lotite izvajanja analize merge requestov, se morate registrirati in naložiti svoj projekt. Če ne veste, kako to storiti, predlagam mojega kolega.
Napomena. Spodaj opisani način nastavitve okolja je le eden od možnih. Cilj je prikazati korake za nastavitev potrebnega okolja za analizo in zagon analizerja. Morda bo v vašem primeru bolj optimalno ločiti faze priprave okolja (dodajanje repozitorijev, namestitev analizerja) in analizo: na primer, priprava Docker slik z ustreznim okoljem in njihova uporaba ali kakšen drug način.
Da bi bolje razumeli, kaj se bo zgodilo, predlagam, da si ogledate naslednjo shemo:

Za delovanje analizerja je potreben .NET Core SDK 3, zato je pred namestitvijo analizerja potrebno dodati repozitorije Microsoft, iz katerih bodo nameščene potrebne odvisnosti za analizer. Dodajanje repozitorijev Microsoft za različne distribucije Linux .
Za namestitev PVS-Studio preko paketnega upravitelja bo prav tako potrebno dodati repozitorije PVS-Studio. Dodajanje repozitorijev za različne distribucije je podrobneje opisano v .
Za delovanje analizerja je potrebna licenčna koda. Preizkusno licenco lahko pridobite na .
Napomena. Upoštevajte, da potrebujete za opisani način delovanja (analizo merge requestov) Enterprise licenco. Zato, če želite preizkusiti ta način dela, v polje "Sporočilo" ne pozabite navesti, da potrebujete prav Enterprise licenco.
Ko pride do merge requesta, moramo analizirati le seznam spremenjenih datotek, sicer pa analiziramo vse datoteke. Po analizi je treba konvertirati dnevnike v želeni format.
Zdaj, ko imamo pred očmi algoritem dela, lahko preidemo k pisanju skripte. Da to storimo, je treba spremeniti datoteko .gitlab-ci.yml ali, če je ni, jo ustvariti. Za njeno ustvarjanje kliknite na ime svojega projekta -> Nastavi CI/CD.

Zdaj smo pripravljeni na pisanje skripte. Najprej napišimo kodo, ki bo namestila analizer in vnesla licenco:
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.slnPоскольку установка и активация должны происходить перед всеми другими скриптами, мы используем специальную метку before_script. Позвольте объяснить этот фрагмент.
Подготовка к установке анализатора:
- 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Добавление репозиториев PVS-Studio и анализатора:
- 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$PVS_NAME — имя пользователя.
$PVS_KEY — ключ продукта.
Восстановление зависимостей проекта, где $CI_PROJECT_DIR – полный путь до директории проекта:
- dotnet restore "$CI_PROJECT_DIR"/Path/To/Solution.slnДля корректного анализа проект должен успешно собираться, и его зависимости должны быть восстановлены (например, должны быть загружены необходимые NuGet пакеты).
Задать переменные окружения, содержащие лицензионную информацию, можно, нажав на Настройка, а после — на CI / CD.

В открывшемся окне находим пункт Spremenljivke, справа нажимаем на кнопку Развернуть и добавляем переменные. В результате должно получиться следующее:

Теперь можно переходить к анализу. Сначала добавим скрипт для полного анализа. В флаг -t передаем путь до solution, в флаг -o пишем путь до файла, в который будут записаны результаты анализа. Также нас интересует код возврата. В данном случае нам интересно, чтобы работа прекращалась, когда код возврата содержит информацию о том, что в ходе анализа были выданы предупреждения. Вот как выглядит данный фрагмент:
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; fiKode vrnitve delujejo na osnovi bitne maske. Na primer, če so bili med analizo izdanih opozoril, bo koda vrnitve enaka 8. Če licenca poteče v enem mesecu, bo koda vrnitve enaka 4. Če pa so bile med analizo odkrite napake, poleg tega pa licenca poteče v enem mesecu, bosta v kodo vrnitve zapisana oba vrednosti: seštejemo številke in dobimo končno kodo vrnitve — 8+4=12. Tako lahko z verificiranjem ustreznih bitov pridobimo informacije o različnih stanjih med analizo. Podrobneje so kode vrnitve opisane v razdelku "Kode vrnitve pvs-studio-dotnet (Linux / macOS)" dokumenta "".
V tem primeru nas zanimajo vse kode vrnitve, kjer je prisotna 8.
- exit_code=$((($exit_code & 8)/8))Dobili bomo 1, ko koda vrnitve vsebuje zanimivi bit števila, sicer bomo dobili 0.
Prišel je čas, da dodamo analizo merge request. Preden to storimo, pripravimo mesto za skript. Potrebujemo, da se izvede le, ko se zgodi merge request. Izgleda takole:
merge:
script:
only:
- merge_requestsPreidimo k samemu skriptu. Soočen sem s tem, da virtualni stroj nič ne ve o origin/master. Zato ji malo pomagamo:
- git fetch originZdaj dobimo razliko med vejami in shranimo rezultat v txt fajl:
- git diff --name-only origin/master $CI_COMMIT_SHA > pvs-fl.txtKjer $CI_COMMIT_SHA – hash zadnjega commit-a.
Nato zagnamo analizo seznama datotek, s pomočjo zastavice -f. Vanjo posredujemo prej pridobljen .txt datoteko. In na podoben način preverimo kode vrnitve:
- 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; fiCeloten skript za preverjanje merge request bo izgledal takole:
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_requestsOstane le še, da dodamo konvertiranje loga, potem ko so se vsi skripti izvedli. Uporabimo oznako after_script in pripomoček plog-converter:
after_script:
- plog-converter -t html -o eLog ./PVS-Studio.jsonOrodje — je odprtokodni projekt, ki se uporablja za pretvorbo poročil o napakah analizatorja v različne oblike, na primer HTML. Podrobnejši opis pripomočka je naveden v pododdelku "Plog Converter Utility" .
Sicer, če želite enostavno delati z .json poročilom lokalno iz IDE, vam priporočam naš za IDE Rider. Podrobneje je njegovo uporabo opisano v .
Za udobje je tu .gitlab-ci.yml v celoti:
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.jsonKo vse dodate v datoteko, pritisnite na Commit changes. Da preverite, ali je vse pravilno, pojdite na CI/CD -> Cevovodi -> Running. Odprlo se bo okno virtualnega stroja, na koncu katerega bi moralo biti naslednje:

Videli smo Job succeeded – uspeh, vse je v redu. Zdaj lahko tudi preizkusite narejeno.
Primeri dela
Za primer dela bomo ustvarili preprost projekt (v master) v katerem bo več datotek. Po tem bomo v drugi veji spremenili le eno datoteko in poskusili narediti merge request.
Oglejmo si dva primera: ko spremenjena datoteka vsebuje napako in ko ne. Najprej primer z napako.
Recimo, da v master veji obstaja datoteka Program.cs, ki ne vsebuje napak, medtem ko je drug razvijalec v drugi veji dodal napačno kodo in želi narediti merge request. Kakšno napako je storil – ni tako pomembno, glavna stvar je, da ta obstaja. Na primer, pozabil je operater throw (ja, ):
void MyAwesomeMethod(String name)
{
if (name == null)
new ArgumentNullException(....);
// naredite nekaj
....
}Poglejmo rezultat analize primera z napako. Da bi se prepričali, da je bila analizirana le ena datoteka, sem dodal zastavico -r v ukazno vrstico pvs-studio-dotnet:

Vidimo, da je analizator našel napako in ni dovolil združitve vej.
Preverimo primer brez napake. Popravimo kodo:
void MyAwesomeMethod(String name)
{
if (name == null)
throw new ArgumentNullException(....);
// naredite nekaj
....
}Rezultati analize merge request:

Kot vidimo, napak ni bilo najdenih, in izvajanje naloge je potekalo uspešno, kar smo želeli preveriti.
Zaključek
Zavračanje slabega kode pred združitvijo vej je zelo priročno in prijetno. Zato, če uporabljate CI/CD, poskusite vgraditi statični analizator za preverjanje. Še posebej, ker je to precej preprosto.
Hvala na pažnji.
Če želite deliti ta članek z angleško govorečo javnostjo, prosim uporabite povezavo na prevod: Nikolay Mironov. .
Izvor: habr.com
