„PVS-Studio“ analizatoriuje C ir C++ kalboms „Linux“ ir „MacOS“, pradedant nuo 7.04 versijos, pasirodė bandymo galimybė patikrinti nurodytų failų sąrašą. Naudodami naują režimą galite sukonfigūruoti analizatorių, kad jis patikrintų įsipareigojimus ir gautų užklausas. Šiame straipsnyje bus parodyta, kaip nustatyti „GitHub“ projektų failų sąrašo tikrinimą populiariose CI (nuolatinės integracijos) sistemose, tokiose kaip „Travis CI“, „Buddy“ ir „AppVeyor“.
Failų sąrašo tikrinimo režimas
PVS-Studio 7.04 versija, skirta Linux ir macOS, turi šaltinio failų sąrašo tikrinimo režimą. Tai tinka projektams, kurių kūrimo sistema leidžia generuoti failą
Taip pat failų sąrašo tikrinimo režimą galima naudoti kartu su kompiliatoriaus paleidimų trace trace (pvs-studio-analyzer trace). Norėdami tai padaryti, pirmiausia turėsite atlikti visą projekto kūrimą ir jį stebėti, kad analizatorius surinktų visą informaciją apie visų tikrinamų failų kompiliavimo parametrus.
Tačiau ši parinktis turi reikšmingą trūkumą - kiekvieno paleidimo metu turėsite atlikti visą viso projekto kūrimo pėdsaką, o tai savaime prieštarauja greito įsipareigojimo patikrinimo idėjai. Arba, jei patalpinsite patį sekimo rezultatą, vėlesni analizatoriaus paleidimai gali pasirodyti nebaigti, jei po sekimo pasikeis šaltinio failo priklausomybės struktūra (pavyzdžiui, prie vieno iš šaltinio failų pridedamas naujas #include).
Todėl nerekomenduojame naudoti failų sąrašo tikrinimo režimo su sekimo žurnalu, kad patikrintume įsipareigojimus arba ištraukimo užklausas. Jei tikrindami įsipareigojimą galite atlikti laipsnišką kūrimą, apsvarstykite galimybę naudoti režimą
Analizei skirtų šaltinio failų sąrašas išsaugomas tekstiniame faile ir perduodamas analizatoriui naudojant parametrą -S:
pvs-studio-analyzer analyze ... -f build/compile_commands.json -S check-list.txt
Šiame faile nurodomi santykiniai arba absoliutūs failų keliai, o kiekvienas naujas failas turi būti naujoje eilutėje. Leidžiama nurodyti ne tik analizuojamų failų pavadinimus, bet ir įvairų tekstą. Analizatorius pamatys, kad tai ne failas, ir ignoruos eilutę. Tai gali būti naudinga komentuojant, jei failai nurodyti rankiniu būdu. Tačiau dažnai failų sąrašas bus generuojamas CI analizuojant, pavyzdžiui, failai iš įsipareigojimo arba ištraukimo užklausos.
Dabar naudodami šį režimą galite greitai išbandyti naują kodą, kol jis nepateks į pagrindinę kūrimo šaką. Kad patikros sistema reaguotų į analizatoriaus įspėjimus, komunalinė programa plog-keitiklis pridėta vėliavėlė --nurodykite-perspėjimus:
plog-converter ... --indicate-warnings ... -o /path/to/report.tasks ...
Naudodamas šią vėliavėlę, keitiklis grąžins kodą, kuris nėra nulis, jei analizatoriaus ataskaitoje yra įspėjimų. Naudodami grąžinimo kodą galite užblokuoti išankstinio patvirtinimo kabliuką, įvykdymo ar ištraukimo užklausą, o sugeneruotą analizatoriaus ataskaitą rodyti ekrane, dalintis ja arba išsiųsti paštu.
Pastaba. Pirmą kartą pradėjus analizuoti failų sąrašą, bus analizuojamas visas projektas, nes analizatorius turi sugeneruoti projekto šaltinio failų priklausomybių failą nuo antraščių failų. Tai C ir C++ failų analizės funkcija. Ateityje priklausomybės failą bus galima išsaugoti talpykloje ir analizatorius jį automatiškai atnaujins. Įsipareigojimų tikrinimo, kai naudojamas failų sąrašo tikrinimo režimas, pranašumas, palyginti su laipsniško analizavimo režimu, yra tas, kad talpykloje turi būti saugomas tik tas failas, o ne objektų failai.
Bendrieji ištraukimo užklausos analizės principai
Viso projekto analizė užima daug laiko, todėl tikslinga patikrinti tik dalį jo. Problema ta, kad reikia atskirti naujus failus nuo likusių projekto failų.
Apsvarstykite medžio su dviem šakomis pavyzdį:
Apsimeskime, kad įsipareigoja A1 yra gana daug kodo, kuris jau buvo patikrintas. Šiek tiek anksčiau padarėme šaką iš įsipareigojimo A1 ir pakeitė kai kuriuos failus.
Žinoma, jūs tai pastebėjote po to A1 buvo dar du įsipareigojimai, bet tai taip pat buvo kitų filialų sujungimai, nes mes neįsipareigojame meistras. Ir dabar atėjo laikas, kai karštoji pataisa pasiruošę. Todėl atsirado sujungimo prašymas B3 и A3.
Žinoma, būtų galima patikrinti visą jų sujungimo rezultatą, tačiau tai būtų per ilga ir nepagrįsta, nes buvo pakeisti tik keli failai. Todėl efektyviau analizuoti tik pasikeitusius.
Norėdami tai padaryti, mes gauname skirtumą tarp šakų, esančių šakos, iš kurios norime susilieti į šeimininką, GALVOSJE:
git diff --name-only HEAD origin/$MERGE_BASE > .pvs-pr.list
$MERGE_BASE mes išsamiai apsvarstysime vėliau. Faktas yra tas, kad ne kiekviena CI paslauga suteikia reikiamą informaciją apie sujungimo bazę, todėl kiekvieną kartą turite sugalvoti naujų būdų, kaip gauti šiuos duomenis. Tai bus išsamiai aprašyta toliau kiekvienoje iš aprašytų žiniatinklio paslaugų.
Taigi, mes gavome skirtumą tarp šakų, tiksliau, pakeistų failų pavadinimų sąrašą. Dabar turime pateikti failą .pvs-pr.list (aukščiau pateiktą išvestį nukreipėme į jį) į analizatorių:
pvs-studio-analyzer analyze -j8
-o PVS-Studio.log
-S .pvs-pr.list
Atlikę analizę, turime konvertuoti žurnalo failą (PVS-Studio.log) į skaitomą formatą:
plog-converter -t errorfile PVS-Studio.log --cerr -w
Ši komanda išvardys klaidas
Tik čia reikia ne tik rodyti klaidas, bet ir informuoti surinkimo ir testavimo tarnybą apie problemų buvimą. Tam prie keitiklio buvo pridėta vėliavėlė -W (--nurodykite-perspėjimus). Jei yra bent vienas analizatoriaus įspėjimas, programos grąžinimo kodas plog-keitiklis pasikeis į 2, o tai savo ruožtu praneš CI tarnybai, kad ištraukimo užklausos failuose yra galimų klaidų.
Travisas CI
Konfigūracija atliekama failo forma .travis.yml. Patogumui patariu viską sudėti į atskirą bash scenarijų su funkcijomis, kurios bus iškviestos iš failo .travis.yml (bash scenarijaus pavadinimas.sh funkcijos_pavadinimas).
Mes pridėsime reikiamą kodą prie scenarijaus bash, todėl gauname daugiau funkcionalumo. Skyriuje įrengti parašykime taip:
install:
- bash .travis.sh travis_install
Jei turėjote kokių nors instrukcijų, galite perkelti jas į scenarijų pašalindami brūkšnelius.
Atidarykime failą .travis.sh ir pridėkite analizatoriaus sąranką prie funkcijos 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
}
Dabar papildykime skyrių scenarijus paleisti analizę:
script:
- bash .travis.sh travis_script
Ir bash scenarijuje:
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
}
Šis kodas turi būti paleistas sukūrus projektą, pavyzdžiui, jei turėjote CMake kūrimą:
travis_script() {
CMAKE_ARGS="-DCMAKE_EXPORT_COMPILE_COMMANDS=On ${CMAKE_ARGS}"
cmake $CMAKE_ARGS CMakeLists.txt
make -j8
}
Tai pasirodys taip:
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
}
Tikriausiai jau pastebėjote nurodytus aplinkos kintamuosius. $TRAVIS_PULL_REQUEST и $TRAVIS_BRANCH. Travis CI deklaruoja juos pati:
- $TRAVIS_PULL_REQUEST išsaugo ištraukimo užklausos numerį arba klaidingasjei tai įprasta šaka;
- $TRAVIS_REPO_SLUG saugo projekto saugyklos pavadinimą.
Šios funkcijos algoritmas:
„Travis CI“ reaguoja į grąžinimo kodus, todėl įspėjimų buvimas lieps tarnybai pažymėti įsipareigojimą kaip klaidingą.
Pažvelkime atidžiau į šią kodo eilutę:
git diff --name-only origin/HEAD > .pvs-pr.list
Faktas yra tas, kad „Travis CI“ automatiškai sujungia filialus analizuodamas ištraukimo užklausą:
Todėl mes analizuojame A4Ir ne B3->A3. Dėl šios savybės turime apskaičiuoti skirtumą nuo A3, kuri yra tik šakos viršūnė kilmė.
Lieka viena svarbi detalė – antraščių failų priklausomybių nuo sukompiliuotų vertimo vienetų (*.c, *.cc, *.cpp ir kt.) talpinimas. Analizatorius apskaičiuoja šias priklausomybes pirmą kartą paleisdamas failų sąrašo tikrinimo režimą ir išsaugo jas .PVS-Studio kataloge. Travis CI leidžia talpykloje išsaugoti aplankus, todėl išsaugosime katalogų duomenis .PVS-Studio/:
cache:
directories:
- .PVS-Studio/
Šį kodą reikia pridėti prie failo .travis.yml. Šiame kataloge saugomi įvairūs duomenys, surinkti po analizės, o tai žymiai pagreitins tolesnius failų sąrašo analizės arba laipsninės analizės vykdymus. Jei tai nebus padaryta, analizatorius iš tikrųjų kiekvieną kartą analizuos visus failus.
Bičiulis
Kaip ir Travisas C.I.
Visų pirma, į kūrimo eilutę turime pridėti naują veiksmą:
Nurodykite kompiliatorių, kuris buvo naudojamas kuriant projektą. Atkreipkite dėmesį į šioje veikloje įdiegtą doko konteinerį. Pavyzdžiui, yra specialus GCC konteineris:
Dabar įdiegkime PVS-Studio ir reikiamas komunalines paslaugas:
Į redaktorių pridėkite šias eilutes:
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
Dabar eikime į skirtuką Vykdyti (pirmoji piktograma) ir atitinkamame redaktoriaus lauke pridėkite šį kodą:
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
Jei perskaitėte skyrių apie Travs-CI, šis kodas jums jau pažįstamas, tačiau dabar yra naujas žingsnis:
Faktas yra tas, kad dabar mes analizuojame ne sujungimo rezultatą, o šakos, iš kurios pateikiamas prašymas ištraukti, VADOVĄ:
Taigi mes esame sąlyginio įsipareigojimo B3 ir mes turime gauti skirtumą iš 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
Nustatyti A3 Naudokime „GitHub“ API:
https://api.github.com/repos/${USERNAME}/${REPO}/pulls/${PULL_REQUEST_ID}
Naudojome šiuos Buddy pateiktus kintamuosius:
- $BUDDY_EXECUTION_PULL_REQEUST_NO - ištraukti užklausos numerį;
- $BUDDY_REPO_SLUG - vartotojo vardo ir saugyklos derinys (pavyzdžiui, max / test).
Dabar išsaugokime pakeitimus naudodami toliau pateiktą mygtuką ir įgalinkite ištraukimo užklausų analizę:
Skirtingai nei Travis CI, mums nereikia nurodyti .pvs-studio saugojimui talpykloje, nes Buddy automatiškai išsaugo visus failus, skirtus vėlesniam paleidimui. Todėl paskutinis dalykas, belieka išsaugoti PVS-Studio prisijungimo vardą ir slaptažodį Buddy. Išsaugoję pakeitimus grįšime į dujotiekį. Turime pereiti prie kintamųjų nustatymo ir pridėti PVS-Studio prisijungimo vardą ir raktą:
Po to, pasirodžius naujai ištraukimo užklausai arba įsipareigojimui, bus atliktas patikrinimas. Jei įsipareigojime yra klaidų, Buddy nurodys tai ištraukimo užklausos puslapyje.
AppVeyor
„AppVeyor“ nustatymas yra panašus į „Buddy“, nes viskas vyksta žiniatinklio sąsajoje ir nereikia pridėti *.yml failo į projekto saugyklą.
Eikime į projekto apžvalgos skirtuką Nustatymai:
Slinkite žemyn šiuo puslapiu ir įgalinkite talpyklos išsaugojimą kuriant ištraukimo užklausas:
Dabar eikime į skirtuką Aplinka, kur nurodome kuriamą vaizdą ir būtinus aplinkos kintamuosius:
Jei perskaitėte ankstesnius skyrius, jūs puikiai žinote šiuos du kintamuosius − PVS_KEY и PVS_USERNAME. Jei ne, tai priminsiu, kad jie būtini norint patikrinti PVS-Studio analizatoriaus licenciją. Ateityje su jais vėl susitiksime Bash scenarijuose.
Tame pačiame puslapyje žemiau nurodykite aplanką talpykloje:
Jei to nepadarysime, analizuosime visą projektą, o ne keletą failų, bet išvestį gausime pagal nurodytus failus. Todėl svarbu įvesti teisingą katalogo pavadinimą.
Dabar laikas išbandyti scenarijų. Atidarykite skirtuką Testai ir pasirinkite Scenarijus:
Į šią formą įklijuokite šį kodą:
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
Pažvelkime į šią kodo dalį:
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
Gana konkretus komandos pwd reikšmės priskyrimas kintamajam, kuris turėtų saugoti šią numatytąją reikšmę, iš pirmo žvilgsnio atrodo keistas, tačiau tuoj viską paaiškinsiu.
Nustatydamas analizatorių AppVeyor, susidūriau su itin keistu analizatoriaus elgesiu. Viena vertus, viskas veikė teisingai, bet analizė neprasidėjo. Daug laiko praleidau pastebėdamas, kad esame /home/appveyor/projects/testcalc/ kataloge, o analizatorius įsitikinęs, kad esame /opt/appveyor/build-agent/. Tada supratau, kad $PWD kintamasis yra šiek tiek melas. Dėl šios priežasties rankiniu būdu atnaujinau jo vertę prieš pradėdamas analizę.
Ir tada viskas, kaip ir anksčiau:
Dabar apsvarstykite šį fragmentą:
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"`
Jame gauname skirtumą tarp šakų, kuriose deklaruojama ištraukimo užklausa. Tam mums reikia šių aplinkos kintamųjų:
- $APPVEYOR_PULL_REQUEST_NUMBER – ištraukimo užklausos numeris;
- $APPVEYOR_REPO_NAME – naudotojo vardas ir projekto saugykla.
išvada
Žinoma, neapsvarstėme visų galimų nuolatinės integracijos paslaugų, tačiau jos visos turi labai panašią darbo specifiką. Išskyrus talpyklą, kiekviena paslauga sukuria savo „dviratį“, todėl viskas visada skiriasi.
Kai kur, kaip Travis-CI, pora kodo eilučių ir talpyklos kaupimas veikia nepriekaištingai; kažkur, kaip ir AppVeyor, tereikia nustatymuose nurodyti aplanką; bet kažkur reikia sukurti unikalius raktus ir pabandyti įtikinti sistemą, kad suteiktų galimybę perrašyti talpykloje saugomą fragmentą. Todėl, jei norite nustatyti ištraukimo užklausų analizę nuolatinės integracijos paslaugoje, kuri nebuvo aptarta aukščiau, pirmiausia įsitikinkite, kad nekils problemų dėl talpyklos.
Ačiū už dėmesį. Jei kas nors nepavyksta, nedvejodami rašykite mums adresu
Jei norite pasidalinti šiuo straipsniu su angliškai kalbančia auditorija, naudokite vertimo nuorodą: Maksimas Zvyagintsevas.
Šaltinis: www.habr.com