Во анализаторот PVS-Studio за јазиците C и C++ на Linux и macOS, почнувајќи од верзијата 7.04, се појави опција за тестирање за проверка на списокот со наведени датотеки. Користејќи го новиот режим, можете да го конфигурирате анализаторот да ги проверува обврските и да ги повлече барањата. Оваа статија ќе ви каже како да поставите проверка на списокот со променети датотеки на проектот GitHub во такви популарни системи CI (континуирана интеграција) како Travis CI, Buddy и AppVeyor.
Режим за проверка на списокот со датотеки
Во верзијата PVS-Studio 7.04 за Linux и macOS, се појави режим за проверка на списокот со изворни датотеки. Ова работи за проекти чиј систем за градење ви овозможува да генерирате датотека
Исто така, режимот за проверка на списокот со датотеки може да се користи заедно со дневникот за трага на траги на стартувањата на компајлерот (pvs-studio-analyzer trace). За да го направите ова, ќе треба прво да извршите целосна изградба на проектот и да го следите, така што анализаторот ќе собере целосни информации за параметрите за компилација на сите датотеки што се проверуваат.
Сепак, оваа опција има значителен недостаток - или ќе треба да извршите целосна изградба на трага на целиот проект секој пат кога ќе го извршите, што само по себе е во спротивност со идејата за брза проверка на извршување. Или, ако го кеширате самиот резултат на трага, последователните работи на анализаторот може да бидат нецелосни ако структурата на зависност на изворните датотеки се промени по трагата (на пример, нов #include се додава на една од изворните датотеки).
Затоа, не препорачуваме да го користите режимот за проверка на списокот со датотеки со дневникот за трага за да ги проверите обврските или барањата за повлекување. Во случај да можете да направите инкрементално градење при проверка на обврзување, размислете за користење на режимот
Списокот на изворни датотеки за анализа се зачувува во текстуална датотека и се пренесува до анализаторот користејќи го параметарот -S:
pvs-studio-analyzer analyze ... -f build/compile_commands.json -S check-list.txt
Оваа датотека одредува релативни или апсолутни патеки до датотеките и секоја нова датотека мора да биде на нова линија. Прифатливо е да се наведат не само имиња на датотеки за анализа, туку и различен текст. Анализаторот ќе види дека ова не е датотека и ќе ја игнорира линијата. Ова може да биде корисно за коментирање ако датотеките се наведени рачно. Сепак, честопати списокот на датотеки ќе се генерира за време на анализата во CI, на пример, тоа може да се датотеки од барање за задолжување или повлекување.
Сега, користејќи го овој режим, можете брзо да го проверите новиот код пред да влезе во главната развојна гранка. За да се осигура дека системот за скенирање реагира на предупредувањата на анализаторот, алатката лог-конвертор додадено знаме --покажи-предупредувања:
plog-converter ... --indicate-warnings ... -o /path/to/report.tasks ...
Со ова знаменце, конверторот ќе врати ненулта шифра ако има предупредувања во извештајот на анализаторот. Користејќи ја шифрата за враќање, можете да блокирате барање за предложена кука, да извршите или да го повлечете, а генерираниот извештај на анализаторот може да се прикаже, сподели или испрати по е-пошта.
Забелешка. Кога првпат ќе започнете да анализирате список на датотеки, целиот проект ќе биде анализиран, бидејќи анализаторот треба да генерира датотека со зависности на изворните датотеки на проектот на датотеките за заглавие. Ова е карактеристика за анализа на датотеките C и C++. Во иднина, датотеката за зависност може да се кешира и таа автоматски ќе се ажурира од страна на анализаторот. Предноста на проверката на обврзниците при користење на режимот за проверка на списокот на датотеки во однос на користењето на режимот за постепена анализа е тоа што треба само да ја кеширате таа датотека, а не и објектните датотеки.
Општи принципи на анализа на барање за повлекување
Анализирањето на целиот проект одзема многу време, па затоа има смисла да се провери само одреден дел од него. Проблемот е што треба да ги одделите новите датотеки од останатите проектни датотеки.
Ајде да погледнеме пример на дрво за обврзување со две гранки:
Да ја замислиме таа обврска A1 содржи прилично голема количина на код кој е веќе тестиран. Малку порано направивме гранка од commit A1 и смени некои датотеки.
Вие, се разбира, забележавте дека после A1 се случија уште две обврски, но тоа беа и спојувања на други гранки, бидејќи не се обврзуваме да господар. И сега дојде време кога испраќање подготвени. Затоа се појави барање за повлекување за спојување B3 и A3.
Се разбира, би било можно да се провери целиот резултат од нивното спојување, но тоа би одземало премногу време и неоправдано, бидејќи само неколку датотеки се сменети. Затоа, поефикасно е да се анализираат само променетите.
За да го направите ова, ја добиваме разликата помеѓу гранките, кои се наоѓаат во HEAD на гранката од која сакаме да се споиме во господар:
git diff --name-only HEAD origin/$MERGE_BASE > .pvs-pr.list
$MERGE_BASE ќе го разгледаме подетално подоцна. Факт е дека не секоја услуга CI ги обезбедува потребните информации за базата на податоци за спојување, така што секој пат треба да смислите нови начини за да ги добиете овие податоци. Ова ќе биде детално опишано подолу во секоја од опишаните веб-услуги.
Значи, ја добивме разликата помеѓу гранките, поточно, списокот со имиња на датотеки што беа променети. Сега треба да ја дадеме датотеката .pvs-pr.листа (го пренасочивме излезот погоре кон него) до анализаторот:
pvs-studio-analyzer analyze -j8
-o PVS-Studio.log
-S .pvs-pr.list
По анализата, треба да ја конвертираме датотеката за евиденција (PVS-Studio.log) во лесно читлив формат:
plog-converter -t errorfile PVS-Studio.log --cerr -w
Оваа команда ќе ги наведе грешките во
Само сега треба не само да прикажуваме грешки, туку и да ја информираме нашата услуга за склопување и тестирање за присуството на проблеми. За таа цел, на конверторот беше додадено знаме -W (--покажи-предупредувања). Ако има барем едно предупредување од анализаторот, шифрата за враќање на услужната програма лог-конвертор ќе се смени во 2, што пак ќе ја информира CI услугата за присуството на потенцијални грешки во датотеките со барање за повлекување.
Тревис ЦИ
Конфигурацијата е направена како датотека .travis.yml. За погодност, ве советувам да ставите сè во посебна баш скрипта со функции што ќе бидат повикани од датотеката .travis.yml (bash script_name.sh функција_име).
Ќе го додадеме потребниот код во скриптата на баш, на овој начин ќе добиеме поголема функционалност. Во делот инсталира да го напишеме следново:
install:
- bash .travis.sh travis_install
Ако сте имале инструкции, можете да ги пренесете во сценариото, отстранувајќи ги цртичките.
Ајде да ја отвориме датотеката .тревис.ш и додадете го дотерувањето на анализаторот на функцијата 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
}
Сега да додадеме во делот скрипта извршете анализа:
script:
- bash .travis.sh travis_script
И во сценариото за баш:
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
}
Овој код треба да се изврши по изградбата на проектот, на пример, ако сте имале изградба на CMake:
travis_script() {
CMAKE_ARGS="-DCMAKE_EXPORT_COMPILE_COMMANDS=On ${CMAKE_ARGS}"
cmake $CMAKE_ARGS CMakeLists.txt
make -j8
}
Ќе испадне вака:
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
}
Веројатно веќе сте ги забележале овие променливи на околината $TRAVIS_PULL_REQUEST и $TRAVIS_BRANCH. Тревис ЦИ ги изјавува независно:
- $TRAVIS_PULL_REQUEST го зачувува бројот на барање за повлекување или лажни, ако ова е редовна гранка;
- $TRAVIS_REPO_SLUG го складира името на складиштето на проектот.
Алгоритмот за оваа функција:
Тревис CI одговара на шифрите за враќање, така што присуството на предупредувања ќе и каже на услугата да го означи извршувањето како да содржи грешки.
Сега да ја разгледаме подетално оваа линија на код:
git diff --name-only origin/HEAD > .pvs-pr.list
Факт е дека Travis CI автоматски ги спојува гранките додека го анализира барањето за повлекување:
Затоа анализираме A4и не Б3->А3. Поради оваа карактеристика, треба да ја пресметаме разликата со A3, што е токму врвот на гранката од потекло.
Остана уште еден важен детал - кеширање на зависностите на датотеките за заглавија на компајлирани преведувачки единици (*.c, *.cc, *.cpp, итн.). Анализаторот ги пресметува овие зависности кога првпат ќе се вклучи во режимот на проверка на список со датотеки и потоа ги зачувува во директориумот .PVS-Studio. Travis CI ви овозможува кеширање на папки, така што ќе ги зачуваме податоците од директориумот .ПВС-Студио/:
cache:
directories:
- .PVS-Studio/
Овој код треба да се додаде во датотеката .travis.yml. Овој директориум складира различни податоци собрани по анализата, што значително ќе ги забрза последователните циклуси на анализа на списокот со датотеки или постепена анализа. Ако ова не е направено, тогаш анализаторот всушност ќе ги анализира сите датотеки секој пат.
Бади
Како Тревис ЦИ,
Пред сè, треба да додадеме ново дејство на склопувачката линија:
Да го посочиме компајлерот што се користел за изградба на проектот. Забележете го докерскиот контејнер што е инсталиран во оваа акција. На пример, постои посебен контејнер за GCC:
Сега ајде да инсталираме PVS-Studio и потребните комунални услуги:
Ајде да ги додадеме следните редови во уредникот:
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
Сега да одиме во табулаторот Run (првата икона) и да го додадеме следниов код во соодветното поле за уредувач:
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
Ако го прочитате делот за Travs-CI, тогаш овој код веќе ви е познат, сепак, сега има нова фаза:
Факт е дека сега не го анализираме резултатот од спојувањето, туку ГЛАВАТА на гранката од која е направено барањето за повлекување:
Значи ние сме во условно обврзување B3 и ние треба да ја добиеме разликата од 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
Да се утврди A3 Ајде да го користиме GitHub API:
https://api.github.com/repos/${USERNAME}/${REPO}/pulls/${PULL_REQUEST_ID}
Ги користевме следните променливи што ги дава Бади:
- $BUDDY_EXECUTION_PULL_REQEUST_NO — број на барање за повлекување;
- $BUDDY_REPO_SLUG — комбинација од корисничко име и складиште (на пример макс/тест).
Сега да ги зачуваме промените користејќи го копчето подолу и да овозможиме анализа на барањето за повлекување:
За разлика од Travis CI, не треба да прецизираме .pvs-studio за кеширање, бидејќи Бади автоматски ги кешира сите датотеки за следните лансирања. Затоа, последното нешто што останува е да ги зачувате најавувањето и лозинката за PVS-Studio во Бади. Откако ќе ги зачуваме промените, ќе бидеме вратени на Pipeline. Треба да продолжиме со поставување на променливи и додавање најава и клуч за PVS-Studio:
По ова, појавата на ново барање за повлекување или извршување ќе го активира прегледот. Ако извршувањето содржи грешки, Бади ќе го покаже ова на страницата со барање за повлекување.
AppVeyor
Поставувањето на AppVeyor е слично на Бади, бидејќи сè се случува во веб-интерфејсот и нема потреба да се додава датотека *.yml во складиштето на проектот.
Ајде да одиме во јазичето Поставки во прегледот на проектот:
Ајде да се движиме надолу оваа страница и да овозможиме зачувување на кешот за собирање барања за повлекување:
Сега да одиме во табулаторот Environment, каде што ја одредуваме сликата за склопување и потребните променливи на животната средина:
Ако сте ги прочитале претходните делови, многу сте запознаени со овие две променливи − PVS_KEY и PVS_USERNAME. Ако не, дозволете ми да ве потсетам дека тие се неопходни за да се потврди лиценцата на анализаторот PVS-Studio. Ќе ги видиме повторно во скриптите на Bash во иднина.
На истата страница подолу ја означуваме папката за кеширање:
Ако не го направиме ова, ќе го анализираме целиот проект наместо неколку датотеки, но ќе го добиеме излезот од наведените датотеки. Затоа, важно е да го внесете точното име на директориумот.
Сега е време за тестирање на сценариото. Отворете го јазичето Тестови и изберете Скрипта:
Треба да го залепите следниов код во оваа форма:
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
Ајде да обрнеме внимание на следниот дел од кодот:
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
Прилично специфичното доделување на вредноста на командата pwd на променливата што треба да ја зачува оваа стандардна вредност изгледа чудно на прв поглед, сепак, сега ќе објаснам сè.
При поставувањето на анализаторот во AppVeyor, наидов на крајно чудно однесување на анализаторот. Од една страна, сè функционираше правилно, но анализата не започна. Поминав многу време забележувајќи дека сме во директориумот /home/appveyor/projects/testcalc/, а анализаторот е сигурен дека сме во /opt/appveyor/build-agent/. Тогаш сфатив дека променливата $PWD малку лажеше. Поради оваа причина, рачно ја ажурирав неговата вредност пред да ја започнам анализата.
И тогаш сè е како порано:
Сега разгледајте го следниот фрагмент:
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"`
Во него ја добиваме разликата помеѓу гранките над кои се декларира барањето за повлекување. За да го направите ова, потребни ни се следните променливи на околината:
- $APPVEYOR_PULL_REQUEST_NUMBER — број на барање за повлекување;
- $APPVEYOR_REPO_NAME - корисничко име и складиште на проектот.
Заклучок
Се разбира, не ги разгледавме сите можни услуги за континуирана интеграција, меѓутоа, сите тие имаат екстремно слични оперативни специфики едни на други. Со исклучок на кеширањето, секоја услуга прави свој „велосипед“, така што сè е секогаш различно.
Некаде, како во Travis-CI, неколку линии код и кеширање функционираат беспрекорно; некаде, како во AppVeyor, само треба да ја наведете папката во поставките; но некаде треба да креирате уникатни клучеви и да се обидете да го убедите системот да ви даде можност да го презапишете кешираниот фрагмент. Затоа, ако сакате да поставите анализа на барања за повлекување на услуга за континуирана интеграција што не беше дискутирана погоре, тогаш прво уверете се дека нема да имате проблеми со кеширањето.
Ви благодариме за вниманието. Ако нешто не успее, слободно пишете ни на
Ако сакате да ја споделите оваа статија со публика што зборува англиски, ве молиме користете ја врската за превод: Максим Звјагинцев.
Извор: www.habr.com