Počínaje verzí 7.04 má analyzátor PVS-Studio pro jazyky C a C++ v systémech Linux a macOS možnost testování pro kontrolu seznamu zadaných souborů. Pomocí nového režimu můžete konfigurovat analyzátor tak, aby kontroloval potvrzení a žádosti o stažení. Tento článek vám ukáže, jak nastavit kontrolu seznamu souborů projektu GitHub v populárních systémech CI (Continuous Integration), jako jsou Travis CI, Buddy a AppVeyor.
Režim kontroly seznamu souborů
Verze PVS-Studio 7.04 pro Linux a macOS má režim pro kontrolu seznamu zdrojových souborů. Toto funguje pro projekty, jejichž systém sestavení umožňuje generovat soubor
Také režim kontroly seznamu souborů lze použít spolu s trasovacím trasováním běhů kompilátoru (pvs-studio-analyzer trace). Chcete-li to provést, musíte nejprve provést úplné sestavení projektu a sledovat jej, aby analyzátor shromáždil úplné informace o parametrech kompilace všech kontrolovaných souborů.
Tato možnost má však významnou nevýhodu – buď budete muset při každém spuštění provést kompletní trasování sestavení celého projektu, což samo o sobě odporuje myšlence rychlé kontroly odevzdání. Nebo pokud uložíte do mezipaměti samotný výsledek trasování, následné spuštění analyzátoru se může ukázat jako neúplné, pokud se po trasování změní struktura závislosti zdrojového souboru (například se do jednoho ze zdrojových souborů přidá nový #include).
Proto nedoporučujeme používat režim kontroly seznamu souborů s protokolem trasování ke kontrole potvrzení nebo žádostí o stažení. V případě, že při kontrole odevzdání můžete provést přírůstkové sestavení, zvažte použití režimu
Seznam zdrojových souborů pro analýzu se uloží do textového souboru a pomocí parametru se předá analyzátoru -S:
pvs-studio-analyzer analyze ... -f build/compile_commands.json -S check-list.txt
Tento soubor určuje relativní nebo absolutní cesty k souborům a každý nový soubor musí být na novém řádku. Je přípustné specifikovat nejen názvy souborů pro analýzu, ale také různé texty. Analyzátor uvidí, že se nejedná o soubor a bude řádek ignorovat. To může být užitečné pro komentování, pokud jsou soubory zadány ručně. Často se však seznam souborů vygeneruje během analýzy CI, například soubory z potvrzení nebo požadavku na stažení.
Nyní pomocí tohoto režimu můžete nový kód rychle otestovat, než se dostane do hlavní vývojové větve. Aby ověřovací systém reagoval na varování analyzátoru, obslužný program plog-konvertor přidána vlajka --indikovat-varování:
plog-converter ... --indicate-warnings ... -o /path/to/report.tasks ...
S tímto příznakem převodník vrátí nenulový kód, pokud jsou ve zprávě analyzátoru varování. Pomocí návratového kódu můžete zablokovat háček předběžného potvrzení, požadavek potvrzení nebo vytažení a zobrazit vygenerovanou zprávu analyzátoru na obrazovce, sdílet ji nebo poslat poštou.
Poznámka. Když poprvé začnete analyzovat seznam souborů, bude analyzován celý projekt, protože analyzátor potřebuje vygenerovat soubor závislostí zdrojových souborů projektu na hlavičkových souborech. Toto je funkce analýzy souborů C a C++. V budoucnu může být soubor závislostí uložen do mezipaměti a bude automaticky aktualizován analyzátorem. Výhodou kontroly odevzdání při použití režimu kontroly seznamu souborů oproti režimu přírůstkové analýzy je, že do mezipaměti je třeba uložit pouze tento soubor, nikoli soubory objektů.
Obecné principy analýzy tahových požadavků
Analýza celého projektu zabere hodně času, proto má smysl kontrolovat jen jeho část. Problém je v tom, že musíte oddělit nové soubory od ostatních souborů projektu.
Zvažte příklad stromu odevzdání se dvěma větvemi:
Předstírejme, že závazek A1 obsahuje poměrně velké množství kódu, který již byl zkontrolován. O něco dříve jsme z commitu udělali větev A1 a změnil některé soubory.
Samozřejmě jste si toho všimli až poté A1 byly tam další dva commity, ale to byly také fúze jiných poboček, protože my se nezavazujeme mistr. A teď nastal čas, kdy opravu hotfix připraveno. Proto se objevil požadavek na stažení pro sloučení B3 и A3.
Samozřejmě by bylo možné zkontrolovat celý výsledek jejich sloučení, ale bylo by to příliš dlouhé a neopodstatněné, protože se změnilo jen několik souborů. Proto je efektivnější analyzovat pouze ty změněné.
Abychom to udělali, dostaneme rozdíl mezi větvemi, které jsou v HEAD větve, ze které se chceme sloučit do hlavní:
git diff --name-only HEAD origin/$MERGE_BASE > .pvs-pr.list
$MERGE_BASE podrobně zvážíme později. Faktem je, že ne každá služba CI poskytuje potřebné informace o základně pro sloučení, takže pokaždé musíte vymýšlet nové způsoby, jak tato data získat. To bude podrobně popsáno níže v každé z popsaných webových služeb.
Dostali jsme tedy rozdíl mezi větvemi, nebo spíše seznamem jmen souborů, které byly změněny. Nyní musíme dát soubor .pvs-pr.list (výstup výše jsme na něj přesměrovali) do analyzátoru:
pvs-studio-analyzer analyze -j8
-o PVS-Studio.log
-S .pvs-pr.list
Po analýze musíme převést soubor protokolu (PVS-Studio.log) do čitelného formátu:
plog-converter -t errorfile PVS-Studio.log --cerr -w
Tento příkaz zobrazí seznam chyb
Pouze zde musíme nejen zobrazovat chyby, ale také informovat naši službu pro montáž a testování o přítomnosti problémů. Za tímto účelem byl do převodníku přidán příznak -W (--indikovat-varování). Pokud existuje alespoň jedno varování analyzátoru, návratový kód obslužného programu plog-konvertor se změní na 2, což zase upozorní službu CI, že v souborech požadavku na stažení jsou potenciální chyby.
Travis CI
Konfigurace se provádí ve formě souboru .travis.yml. Pro pohodlí vám doporučuji dát vše do samostatného bash skriptu s funkcemi, které budou volány ze souboru .travis.yml (bash název_scriptu.sh název_funkce).
Potřebný kód přidáme do skriptu na praštit, takže získáme více funkcí. V sekci instalovat napíšeme následující:
install:
- bash .travis.sh travis_install
Pokud jste měli nějaké pokyny, můžete je přesunout do skriptu odstraněním pomlček.
Otevřeme soubor .travis.sh a přidejte nastavení analyzátoru do funkce 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
}
Nyní přidáme do sekce skript spustit analýzu:
script:
- bash .travis.sh travis_script
A v bash skriptu:
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
}
Tento kód je nutné spustit po sestavení projektu, například pokud jste měli sestavení CMake:
travis_script() {
CMAKE_ARGS="-DCMAKE_EXPORT_COMPILE_COMMANDS=On ${CMAKE_ARGS}"
cmake $CMAKE_ARGS CMakeLists.txt
make -j8
}
Dopadne to takto:
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
}
Pravděpodobně jste si již všimli zadaných proměnných prostředí. $TRAVIS_PULL_REQUEST и $TRAVIS_BRANCH. Travis CI je prohlašuje samostatně:
- $TRAVIS_PULL_REQUEST ukládá číslo požadavku na stažení, popř nepravdivýpokud je to normální větev;
- $TRAVIS_REPO_SLUG ukládá název úložiště projektu.
Algoritmus této funkce:
Travis CI reaguje na návratové kódy, takže přítomnost varování řekne službě, aby označila odevzdání jako chybné.
Podívejme se blíže na tento řádek kódu:
git diff --name-only origin/HEAD > .pvs-pr.list
Faktem je, že Travis CI automaticky sloučí větve během analýzy požadavku na stažení:
Proto analyzujeme A4A ne B3->A3. Kvůli této vlastnosti musíme vypočítat rozdíl od A3, což je právě vrchol větve z původ.
Zbývá jeden důležitý detail – cachování závislostí hlavičkových souborů na zkompilovaných překladových jednotkách (*.c, *.cc, *.cpp atd.). Analyzátor tyto závislosti vypočítá při prvním spuštění v režimu kontroly seznamu souborů a následně je uloží do adresáře .PVS-Studio. Travis CI umožňuje ukládat složky do mezipaměti, takže uložíme data adresáře .PVS-Studio/:
cache:
directories:
- .PVS-Studio/
Tento kód je třeba přidat do souboru .travis.yml. Tento adresář ukládá různá data shromážděná po analýze, což výrazně urychlí následné spuštění analýzy seznamu souborů nebo přírůstkové analýzy. Pokud tak neučiníte, analyzátor bude ve skutečnosti pokaždé analyzovat všechny soubory.
kámoš
Stejně jako Travis C.I.
Nejprve musíme do řádku sestavení přidat novou akci:
Zadejte kompilátor, který byl použit k sestavení projektu. Všimněte si ukotvitelného kontejneru, který je nainstalován v této aktivitě. Například existuje speciální kontejner pro GCC:
Nyní nainstalujme PVS-Studio a potřebné nástroje:
Přidejte do editoru následující řádky:
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
Nyní přejděte na kartu Spustit (první ikona) a do odpovídajícího pole editoru přidejte následující kód:
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
Pokud jste četli sekci o Travs-CI, pak je vám tento kód již známý, nyní je tu však nový krok:
Faktem je, že nyní neanalyzujeme výsledek sloučení, ale HEAD větve, ze které je požadavek na stažení proveden:
Takže jsme v podmíněném potvrzení B3 a my potřebujeme získat rozdíl od 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
Určit A3 Použijme GitHub API:
https://api.github.com/repos/${USERNAME}/${REPO}/pulls/${PULL_REQUEST_ID}
Použili jsme následující proměnné poskytnuté Buddym:
- $BUDDY_EXECUTION_PULL_REQEUST_NO - vytáhnout číslo požadavku;
- $BUDDY_REPO_SLUG - kombinace uživatelského jména a úložiště (například max / test).
Nyní uložme změny pomocí tlačítka níže a povolme analýzu požadavku na stažení:
Na rozdíl od Travise CI nemusíme specifikovat .pvs-studio pro ukládání do mezipaměti, protože Buddy automaticky ukládá všechny soubory do mezipaměti pro následující spuštění. Poslední, co tedy zbývá, je uložit přihlašovací jméno a heslo pro PVS-Studio do Buddy. Po uložení změn se vrátíme zpět do Pipeline. Musíme přejít na nastavení proměnných a přidat přihlašovací jméno a klíč pro PVS-Studio:
Poté výskyt nového požadavku na stažení nebo potvrzení spustí kontrolu. Pokud potvrzení obsahuje chyby, Buddy na to upozorní na stránce žádosti o stažení.
AppVeyor
Nastavení AppVeyor je podobné jako u Buddyho, protože vše se děje ve webovém rozhraní a není třeba přidávat soubor *.yml do úložiště projektu.
Pojďme na kartu Nastavení v přehledu projektu:
Pojďme na této stránce posouvat dolů a povolit ukládání do mezipaměti pro požadavky na stahování budov:
Nyní přejdeme na kartu Prostředí, kde určíme obrázek k sestavení a potřebné proměnné prostředí:
Pokud jste četli předchozí části, tyto dvě proměnné − dobře znáte PVS_KEY и PVS_USERNAME. Pokud ne, pak připomínám, že je nutné zkontrolovat licenci analyzátoru PVS-Studio. V budoucnu se s nimi opět setkáme ve skriptech Bash.
Na stejné stránce níže zadejte složku pro ukládání do mezipaměti:
Pokud to neuděláme, analyzujeme celý projekt místo několika souborů, ale výstup dostaneme na základě zadaných souborů. Proto je důležité zadat správný název adresáře.
Nyní je čas na testování skriptu. Otevřete kartu Testy a vyberte Skript:
Do tohoto formuláře vložte následující kód:
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
Podívejme se na následující část kódu:
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
Poněkud konkrétní přiřazení hodnoty příkazu pwd k proměnné, která by měla tuto výchozí hodnotu uchovávat, působí na první pohled podivně, nicméně za chvíli vše vysvětlím.
Při nastavování analyzátoru v AppVeyor jsem se setkal s extrémně zvláštním chováním analyzátoru. Na jednu stranu vše fungovalo správně, ale rozbor se nespustil. Strávil jsem spoustu času tím, že jsem si všiml, že jsme v adresáři /home/appveyor/projects/testcalc/ a analyzátor si je jistý, že jsme v /opt/appveyor/build-agent/. Pak jsem si uvědomil, že proměnná $PWD je tak trochu lež. Z tohoto důvodu jsem před zahájením analýzy ručně aktualizoval jeho hodnotu.
A pak všechno, jako předtím:
Nyní zvažte následující úryvek:
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"`
V něm získáme rozdíl mezi větvemi, na kterých je deklarován pull request. K tomu potřebujeme následující proměnné prostředí:
- $APPVEYOR_PULL_REQUEST_NUMBER - vytáhnout číslo požadavku;
- $APPVEYOR_REPO_NAME - uživatelské jméno a úložiště projektu.
Závěr
Samozřejmě jsme nezvažovali všechny možné služby kontinuální integrace, nicméně všechny mají velmi podobná pracovní specifika. S výjimkou cachování si každá služba vyrábí své „kolo“, takže je vždy vše jinak.
Někde, jako v Travis-CI, funguje pár řádků kódu a ukládání do mezipaměti bezchybně; někde, jako v AppVeyor, stačí zadat složku v nastavení; ale někde je třeba vytvořit jedinečné klíče a pokusit se přesvědčit systém, aby vám dal možnost přepsat fragment uložený v mezipaměti. Pokud tedy chcete nastavit analýzu požadavků na vytažení na službu nepřetržité integrace, která nebyla zmíněna výše, nejprve se ujistěte, že nebudete mít problémy s ukládáním do mezipaměti.
Děkuji za pozornost. Pokud by se něco nepovedlo, tak nám klidně napište na
Pokud chcete tento článek sdílet s anglicky mluvícím publikem, použijte prosím odkaz na překlad: Maxim Zvjagincev.
Zdroj: www.habr.com