
Milujete GitLab a nenávidíte chyby? Chcete zlepšit kvalitu zdrojového kódu? Tak jste na správném místě. Dnes vám ukážeme, jak nastavit C# analyzátor PVS-Studio na kontrolu merge requestů. Všem přejeme fantazijní náladu a příjemné čtení.
— je nástroj pro odhalování chyb a potenciálních zranitelností ve zdrojovém kódu programů napsaných v jazycích C, C++, C# a Java. Funguje na 64bitových systémech Windows, Linux a macOS. Může analyzovat kód určený pro 32bitové, 64bitové a vestavěné ARM platformy.
Mimochodem, uskutečnil se nám vydání PVS-Studio 7.08, ve kterém jsme udělali spoustu nového. . Například:
- analyzátor C# pod Linux a macOS;
- plugin pro Rider;
- nový režim kontroly seznamu souborů.
Režim kontroly seznamu souborů
Dříve bylo nutné, abyste pro kontrolu určitých souborů předali analyzátoru .xml se seznamem souborů. Protože to ale nebylo příliš pohodlné, přidali jsme možnost předání .txt, což život velmi usnadňuje.
Abychom zkontrolovali určité soubory, je nutné uvést příznak —sourceFiles (-f) a předat .txt se seznamem souborů. Vypadá to takto:
pvs-studio-dotnet -t path/to/solution.sln -f fileList.txt -o project.jsonPokud vás zajímá nastavení kontroly commitů nebo pull requestů, můžete to také udělat pomocí tohoto režimu. Rozdíl bude spočívat ve získání seznamu souborů pro analýzu a závisí na tom, jaké systémy používáte.
Princip kontroly merge requestu
Hlavním smyslem kontroly je, aby se problémy odhalené analyzátorem při sloučení nedostaly do master větev. Také nechceme pokaždé analyzovat celý projekt. O to více, že při sloučení větví máme seznam změněných souborů. Proto navrhuji přidat kontrolu merge requestů.
Takto vypadá merge request před zavedením statického analyzátoru:

Tedy všechny chyby, které byly ve větvi changes, přejdou do master větve. Protože bychom to nechtěli, přidáme analýzu a nyní schéma vypadá následovně:

Analyzujeme changes2 a pokud nejsou žádné chyby, přijmeme merge request, jinak ho odmítneme.
Mimochodem, pokud vás zajímá analýza commitů a pull requestů pro C/C++, můžete si o tom přečíst .
GitLab
— webový nástroj pro životní cyklus DevOps s otevřeným zdrojovým kodem, představující systém pro správu repozitářů kódu pro Git s vlastními wiki, systémem sledování chyb, CI/CD pipeline a dalšími funkcemi.
Před tím, než začnete implementaci analýzy merge requestů, je nutné se zaregistrovat a nahrát svůj projekt. Pokud nevíte, jak to udělat, doporučuji mého kolegu.
Poznámka. Následující způsob nastavení prostředí je jednou z možností. Cílem je ukázat kroky potřebné k nastavení prostředí pro analýzu a spuštění analyzátoru. Možná bude pro vás optimálnější rozdělit fáze přípravy prostředí (přidání repozitářů, instalace analyzátoru) a analýzy: například příprava Docker obrazů s potřebným prostředím a jejich využití nebo jiný způsob.
Abyste lépe pochopili, co se nyní bude dít, navrhuji se podívat na následující schéma:

Pro práci analyzátoru je potřeba .NET Core SDK 3, a proto je před instalací analyzátoru nutné přidat repozitáře Microsoft, z nichž budou nainstalovány potřebné závislosti pro analyzátor. Přidání repozitářů Microsoft pro různé distribuce Linuxu .
Pro instalaci PVS-Studio prostřednictvím balíčkového manažera bude rovněž nutné přidat repozitáře PVS-Studio. Přidání repozitářů pro různé distribuce je podrobněji popsáno v .
Analyzátor potřebuje licenční klíč. Zkušební licenci lze získat na .
PoznámkaVšimněte si, že pro popisovaný režim práce (analýza merge requestů) je potřeba Enterprise licence. Pokud tedy chcete vyzkoušet tento pracovní režim, nezapomeňte v poli "Zpráva" uvést, že potřebujete právě Enterprise licenci.
Pokud dojde k merge requestu, bude třeba analyzovat pouze seznam změněných souborů, jinak analyzujeme všechny soubory. Po analýze je třeba převést logy do požadovaného formátu.
Nyní, když máme před očima algoritmus práce, můžeme přejít k psaní skriptu. K tomu je nutné změnit soubor .gitlab-ci.yml nebo, pokud neexistuje, vytvořit. Pro jeho vytvoření klikněte na název svého projektu -> Nastavit CI/CD.

Teď jsme připraveni k napsání skriptu. Nejprve napíšeme kód, který nainstaluje analyzátor a zadá licenci:
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.slnJelikož instalace a aktivace musí proběhnout před všemi ostatními skripty, použijeme speciální značku before_script. Trochu vysvětlím tento fragment.
Příprava na instalaci analyzátoru:
- 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 updatePřidání repozitářů PVS-Studio a analyzátoru:
- 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-dotnetAktivace licence:
- pvs-studio-analyzer credentials $PVS_NAME $PVS_KEY$PVS_NAME — uživatelské jméno.
$PVS_KEY — produktový klíč.
Obnovení závislostí projektu, kde $CI_PROJECT_DIR – úplná cesta k adresáři projektu:
- dotnet restore "$CI_PROJECT_DIR"/Path/To/Solution.slnPro správnou analýzu musí být projekt úspěšně sestaven a jeho závislosti musí být obnoveny (například musí být staženy potřebné NuGet balíčky).
Zadat proměnné prostředí, které obsahují licenční informace, lze kliknutím na Nastavení, a poté — na CI / CD.

V otevřeném okně nalezneme položku Proměnné, vpravo klikneme na tlačítko Rozbalit a přidáme proměnné. Výsledkem by mělo být následující:

Nyní můžeme přejít k analýze. Nejdříve přidáme skript pro úplnou analýzu. V parametru -t předáváme cestu k solution, v parametru -o uvádíme cestu k souboru, do kterého budou zapsány výsledky analýzy. Také nás zajímá návratový kód. V tomto případě nás zajímá, aby se práce zastavila, když návratový kód obsahuje informace o tom, že během analýzy byly vydány upozornění. Takto vypadá tento fragment:
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; fiKódy návratu fungují na principu bitové masky. Například, pokud během analýzy byly vydány varování, kód návratu bude 8. Pokud licence vyprší během měsíce, kód návratu bude 4. Pokud byly během analýzy nalezeny chyby a licence vyprší během měsíce, do kódu návratu budou zapsány obě hodnoty: sečteme čísla dohromady a získáme konečný kód návratu — 8+4=12. Takto lze kontrolou odpovídajících bitů získat informace o různých stavech během analýzy. Podrobněji jsou kódy návratu popsány v části "Kódy návratu pvs-studio-dotnet (Linux / macOS)" dokumentu "".
V tomto případě nás zajímají všechny kódy návratu, kde figuruje 8.
- exit_code=$((($exit_code & 8)/8))Získáme 1, když kód návratu obsahuje zajímavý bit čísla, jinak získáme 0.
Nastala doba přidat analýzu merge requestu. Než to uděláme, připravíme místo pro skript. Potřebujeme, aby se spouštěl pouze tehdy, když se provádí merge request. Vypadá to takto:
merge:
script:
only:
- merge_requestsPřejdeme k samotnému skriptu. Narazil jsem na to, že virtuální stroj nic neví o origin/master. Proto ji trochu pomůžeme:
- git fetch originNyní získáme rozdíl větví a uložíme výsledek do txt souboru:
- git diff --name-only origin/master $CI_COMMIT_SHA > pvs-fl.txtKde $CI_COMMIT_SHA – hash posledního commitu.
Dále spouštíme analýzu seznamu souborů pomocí příznaku -f. Do něj předáme dříve získaný .txt soubor. A podle analogie s úplnou analýzou sledujeme kódy návratu:
- 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Úplný skript pro kontrolu merge requestu bude vypadat takto:
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_requestsZbývá jen přidat konverzi logu poté, co proběhly všechny skripty. Použijeme značku after_script a utilitu plog-converter:
after_script:
- plog-converter -t html -o eLog ./PVS-Studio.jsonNástroj — je open source projekt, který se používá k přetváření chybových zpráv analyzátoru do různých forem, například HTML. Podrobnější popis nástroje je uveden v části "Nástroj Plog Converter" .
Mimochodem, pokud chcete pohodlně pracovat s .json reportem lokálně z IDE, nabízím náš pro IDE Rider. Jeho použití je podrobněji popsáno v .
Pro pohodlí je zde .gitlab-ci.yml v celku:
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.jsonJakmile přidáte vše do souboru, klikněte na Commit changes. Chcete-li zkontrolovat, zda je vše v pořádku, přejděte do CI/CD -> Pipeline -> Dokončeno. Otevře se okno virtuálního stroje, na jehož konci by mělo být následující:

Viděli jste Job succeeded – úspěch, vše je skvělé. Nyní můžeme otestovat, co bylo provedeno.
Příklady práce
Pro příklad práce vytvoříme jednoduchý projekt (v master) s několika soubory. Poté ve jiné větvi změníme pouze jeden soubor a pokusíme se provést merge request.
Zvážíme dva případy: když změněný soubor obsahuje chybu a když ne. Nejprve příklad s chybou.
Představme si, že v master větvi je soubor Program.cs, který neobsahuje žádné chyby, a v jiné větvi vývojář přidal chybový kód a chce provést merge request. Jakou konkrétní chybu udělal – není tak důležité, hlavní je, že nějaká je. Například zapomněl na operátor IllegalStateException( (ano, ):
void MyAwesomeMethod(String name)
{
if (name == null)
new ArgumentNullException(....);
// udělej něco
....
}Podívejme se na výsledek analýzy příkladu s chybou. Abych se také ujistil, že byl analyzován pouze jeden soubor, přidal jsem příznak -r do příkazového řádku pvs-studio-dotnet:

Vidíme, že analyzátor našel chybu a neumožnil sloučení větví.
Zkontrolujeme příklad bez chyby. Opravit kód:
void MyAwesomeMethod(String name)
{
if (name == null)
throw new ArgumentNullException(....);
// udělej něco
....
}Výsledky analýzy merge requestu:

Jak vidíme, chyby nebyly nalezeny a úkol byl úspěšně vykonán, což jsme chtěli zkontrolovat.
Závěr
Filtrování špatného kódu před sloučením větví je velmi pohodlné a příjemné. Proto, pokud používáte CI/CD, zkuste integrovat statický analyzátor pro kontrolu. O to více, že se to dělá docela snadno.
Děkuji za pozornost.
Pokud chcete sdílet tento článek s anglicky mluvícím publikem, prosím použijte odkaz na překlad: Nikolay Mironov. .
Zdroj: habr.com
