Analys av commits och pull requests i Travis CI, Buddy och AppVeyor med PVS-Studio

Analys av commits och pull requests i Travis CI, Buddy och AppVeyor med hjÀlp av PVS-Studio
I analysatorn PVS-Studio för sprÄken C och C++ pÄ Linux och macOS, frÄn version 7.04, har en testfunktion införts för att kontrollera listan över angivna filer. Med den nya lÀget kan analysatorn konfigureras för att kontrollera commits och pull requests. I denna artikel kommer vi att diskutera hur man stÀller in kontrollen av listan med Àndrade filer i ett GitHub-projekt i populÀra CI-system som Travis CI, Buddy och AppVeyor.

FilkontrolllÀge

PVS-Studio Àr ett verktyg för att identifiera fel och potentiella sÄrbarheter i programkod som skrivits i sprÄk som C, C++, C# och Java. Det fungerar pÄ 64-bitarsystem i Windows, Linux och macOS.

I version PVS-Studio 7.04 för Linux och macOS har ett filkontrolllÀge lagts till. Detta fungerar för projekt vars byggsystem kan generera en fil compile_commands.json. Denna fil behövs för att analysatorn ska kunna extrahera information om kompileringen av de angivna filerna. Om ditt byggsystem inte stöder generering av filen compile_commands.json kan du försöka generera en sÄdan fil med hjÀlp av verktyget Bear.

. FilkontrolllÀget kan ocksÄ anvÀndas tillsammans med loggen frÄn strace över kompilatorns körningar (pvs-studio-analyzer trace). För detta behöver du först genomföra en fullstÀndig byggen av projektet och spÄra den, sÄ att analysatorn samlar in fullstÀndig information om kompileringstillstÄnden för alla kontrollerade filer.

Men denna metod har en betydande nackdel - det krÀvs antingen att du gör en fullstÀndig spÄrning av hela projektbyggen vid varje körning, vilket gÄr emot syftet med snabb kontroll av commiten. Eller, om du cacher resultatet av spÄrningen, kan efterföljande körningar av analysatorn bli ofullstÀndiga ifall struktureringen av beroendena i kÀllfilerna Àndras (till exempel om en ny #include lÀggs till i en av kÀllfilerna).

DÀrför rekommenderar vi inte att anvÀnda filkontrolllÀget med spÄrningsloggen för att kontrollera commits eller pull requests. Om du kan göra en inkrementell byggning vid kontroll av en commit, övervÀg att anvÀnda lÀget inkrementell analys.

Listan över kÀllfiler för analys sparas i en textfil och överlÀmnas till analysatorn med parametern -S:

pvs-studio-analyzer analyze ... -f build/compile_commands.json -S check-list.txt

Denna fil innehÄller relativa eller absoluta sökvÀgar till filer, dÀr varje ny fil ska anges pÄ en ny rad. Det Àr tillÄtet att ange inte bara filnamn för analysen, utan ocksÄ olika text. Analysatorn kommer att se att detta inte Àr en fil och ignorera raden. Detta kan vara anvÀndbart för kommentar, om filerna anges manuellt. Men oftast kommer fillistan att genereras under analysen i CI, till exempel kan det vara filer frÄn en commit eller pull request.

Nu kan man snabbt kontrollera ny kod innan den hamnar i huvudutvecklingsgrenen med hjĂ€lp av detta lĂ€ge. För att kontrollsystemet ska reagera pĂ„ analyserarens varningsmeddelanden, i verktyget plog-converter har en flagga lagts till —indicate-warnings:

plog-converter ... --indicate-warnings ... -o /path/to/report.tasks ...

Med detta flagga kommer konverteraren att returnera en icke-noll kod om det finns varningar i analyserarens rapport. UtifrÄn returkoden kan man blockera pre-commit hook, commit eller pull request, och den genererade analyserarens rapport kan visas pÄ skÀrmen, delas eller skickas via e-post.

Observera. Vid första körningen av filanalysen kommer hela projektet att analyseras, eftersom analysatorn mÄste generera en beroendefil för projektets kÀllfiler till header-filer. Detta Àr en egenskap hos analysen av C- och C++-filer. I framtiden kan beroendefilen cachas och kommer att uppdateras automatiskt av analysatorn. Fördelen med commit-kontroll med hjÀlp av filanalyslÀget jÀmfört med inkremental analys Àr att man bara behöver cacha denna fil och inte objektfiler.

AllmÀnna principer för analys av pull request

Att analysera hela projektet tar ganska mycket tid, sÄ det Àr meningsfullt att bara kontrollera en del av det. Problemet Àr att man mÄste separera nya filer frÄn övriga filer i projektet.

LÄt oss titta pÄ ett exempel pÄ ett commit-trÀd med tvÄ grenar:

Analys av commits och pull requests i Travis CI, Buddy och AppVeyor med hjÀlp av PVS-Studio

LÄt oss förestÀlla oss att commit A1 innehÄller en tillrÀckligt stor mÀngd kod som redan har granskats. Tidigare gjorde vi en gren frÄn commit A1 och Àndrade nÄgra filer.

Ni har sÀkert mÀrkt att efter A1 har det skett ytterligare tvÄ commits, men dessa var ocksÄ sammanslagningar av andra grenar, eftersom vi inte commit:ar i master. Och nu har tiden kommit dÄ hotfix Àr redo. DÀrför har det skapats en pull request för att slÄ samman B3 och A3.

SjÀlvklart skulle man kunna kontrollera hela resultatet av deras sammanslagning, men det skulle ta för lÄng tid och vara orimligt, eftersom endast nÄgra filer har Àndrats. DÀrför Àr det effektivare att analysera endast de Àndrade filerna.

För detta fÄr vi skillnaden mellan grenarna, medan vi Àr i HEAD-grenen som vi vill slÄ ihop till master:

git diff --name-only HEAD origin/$MERGE_BASE > .pvs-pr.list

$MERGE_BASE vi kommer att gÄ igenom detta mer ingÄende senare. Saken Àr den att lÄngt ifrÄn varje CI-tjÀnst tillhandahÄller nödvÀndig information om basen för sammanslagning, sÄ varje gÄng mÄste vi komma pÄ nya sÀtt att fÄ dessa data. Detta kommer att beskrivas mer detaljerat nedan i varje beskrivna webbtjÀnst.

SĂ„ vi har fĂ„tt skillnaden mellan grenarna, eller mer specifikt — listan över filnamn som har Ă€ndrats. Nu behöver vi ge filen .pvs-pr.list (vi har omdirigerat utdata dit ovan) till analyzern:

pvs-studio-analyzer analyze -j8 
                            -o PVS-Studio.log 
                            -S .pvs-pr.list

Efter analysen mÄste vi konvertera loggfilen (PVS-Studio.log) till ett mer lÀttlÀst format:

plog-converter -t errorfile PVS-Studio.log --cerr -w

Detta kommando kommer att skriva ut en lista över fel i stderr (standard utdataflöde för felmeddelanden).

Men vi behöver inte bara skriva ut fel, utan Ă€ven meddela vĂ„r bygg- och testtjĂ€nst om förekomsten av problem. För detta har en flagga lagts till i konverteraren -W (—indicate-warnings). Om det finns minst en varning frĂ„n analyzern, kommer Ă„tervĂ€ndande koden för verktyget plog-converter att Ă€ndras till 2, vilket i sin tur meddelar CI-tjĂ€nsten om potentiella fel i pull request-filerna.

Travis CI

Konfigurationen görs i form av en fil .travis.yml. För bekvÀmlighetens skull rekommenderar jag att flytta allt till ett separat bash-skript med funktioner som kommer att anropas frÄn filen .travis.yml (bash namn_pÄ_skriptet.sh funktionsnamn).

Vi kommer att lÀgga till nödvÀndig kod i skriptet pÄ bash, pÄ sÄ sÀtt fÄr vi mer funktionalitet. I avsnittet install ska vi skriva följande:

install:
  - bash .travis.sh travis_install

Om du har haft nÄgra instruktioner, kan du flytta dem till skriptet och ta bort bindestrecken.

Vi öppnar filen .travis.sh och lÀgger till installationen av analyzern i funktionen 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 
}

Nu lÀgger vi till i avsnittet script kör analys:

script:
  - bash .travis.sh travis_script

Och i bash-skriptet:

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
}

Denna kod ska köras efter att projektet har byggts, till exempel om du har en byggning med CMake:

travis_script() {
  CMAKE_ARGS="-DCMAKE_EXPORT_COMPILE_COMMANDS=On ${CMAKE_ARGS}"
  cmake $CMAKE_ARGS CMakeLists.txt
  make -j8
}

Det blir sÄ hÀr:

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
}

Du har antagligen redan noterat de angivna miljövariablerna $TRAVIS_PULL_REQUEST och $TRAVIS_BRANCH. Travis CI deklarerar dem automatiskt:

  • $TRAVIS_PULL_REQUEST innehĂ„ller numret pĂ„ pull requesten eller false, om det Ă€r en vanlig gren;
  • $TRAVIS_REPO_SLUG innehĂ„ller namnet pĂ„ projektets repository.

Algoritmen för denna funktion:

Analys av commits och pull requests i Travis CI, Buddy och AppVeyor med hjÀlp av PVS-Studio
Travis CI reagerar pÄ returkoder, sÄ förekomsten av varningar kommer att indikera för tjÀnsten att markera commit som innehÄllande fel.

Och nu lÄt oss ta en nÀrmare titt pÄ denna kodrad:

git diff --name-only origin/HEAD > .pvs-pr.list

PoÀngen Àr att Travis CI automatiskt gör sammanslagningar av grenar under analysen av pull requests:

Analys av commits och pull requests i Travis CI, Buddy och AppVeyor med hjÀlp av PVS-Studio
DÀrför analyserar vi A4, inte B3->A3. PÄ grund av denna egenskap behöver vi berÀkna skillnaden med A3, vilket just Àr toppen av grenen frÄn origin.

Det finns en viktig detalj kvar — cache av beroenden i huvudfilsskĂ€l frĂ„n de kompilationsenheter som översĂ€tts (*.c, *.cc, *.cpp osv.). Dessa beroenden berĂ€knas av analysatorn vid första körningen i filkollĂ€ge och sparas sedan i katalogen .PVS-Studio. Travis CI möjliggör cachning av mappar, sĂ„ vi sparar data frĂ„n katalogen .PVS-Studio/:

cache:
  directories:
    - .PVS-Studio/

Denna kod mÄste lÀggas till i filen .travis.yml. Denna katalog lagrar olika data som samlas in efter analysen, vilket vÀsentligt snabbar upp efterföljande körningar av filanalyslistan eller inkrementell analys. Om detta inte görs, kommer analysatorn faktiskt att analysera alla filer varje gÄng.

Buddy

Precis som Travis CI, Buddy möjliggör automatiserad byggnation och testning av projekt som lagras pÄ GitHub. Till skillnad frÄn Travis CI, konfigureras det i webbgrÀnssnittet (bash-stöd finns), sÄ det Àr inte nödvÀndigt att lagra konfigurationsfiler i projektet.

Först mÄste vi lÀgga till en ny ÄtgÀrd i bygglinjen:

Analys av commits och pull requests i Travis CI, Buddy och AppVeyor med hjÀlp av PVS-Studio
Vi anger kompilatorn som anvÀndes för att bygga projektet. Observera dockerbehÄllaren som Àr installerad i denna ÄtgÀrd. Till exempel, för GCC finns det en speciell behÄllare:

Analys av commits och pull requests i Travis CI, Buddy och AppVeyor med hjÀlp av PVS-Studio
Nu installerar vi PVS-Studio och nödvÀndiga verktyg:

Analys av commits och pull requests i Travis CI, Buddy och AppVeyor med hjÀlp av PVS-Studio
LÀgg till följande rader i redigeraren:

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

Nu gÄr vi till fliken Run (den första ikonen) och lÀgger till följande kod i det angivna redigeringsfÀltet:

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

Om du har lÀst avsnittet om Travs-CI, sÄ Àr denna kod redan bekant för dig, men nu har ett nytt steg tillkommit:

Analys av commits och pull requests i Travis CI, Buddy och AppVeyor med hjÀlp av PVS-Studio
Det handlar om att vi nu analyserar inte resultatet av sammanslagningen, utan HEAD pÄ den gren som pull requesten görs frÄn:

Analys av commits och pull requests i Travis CI, Buddy och AppVeyor med hjÀlp av PVS-Studio
DÀrför befinner vi oss i ett hypotetiskt commit B3 och vi behöver fÄ skillnaden med 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

För att faststÀlla A3 anvÀnder vi GitHub API:

https://api.github.com/repos/${USERNAME}/${REPO}/pulls/${PULL_REQUEST_ID}

Vi anvÀnde följande variabler som tillhandahÄlls av Buddy:

  • $BUDDY_EXECUTION_PULL_REQEUST_NO – numret pĂ„ pull requesten;
  • $BUDDY_REPO_SLUG – en kombination av anvĂ€ndarnamn och repository (t.ex. max/test).

Nu sparar vi Àndringarna med hjÀlp av knappen nedan och aktiverar analysen av pull request:

Analys av commits och pull requests i Travis CI, Buddy och AppVeyor med hjÀlp av PVS-Studio
Till skillnad frĂ„n Travis CI behöver vi inte specificera .pvs-studio för caching, eftersom Buddy automatiskt cacherar alla filer för efterföljande körningar. Det Ă„terstĂ„r bara en sak — att spara inloggningen och lösenordet för PVS-Studio i Buddy. NĂ€r Ă€ndringarna sparas kommer vi tillbaka till Pipeline. Vi behöver gĂ„ till instĂ€llningarna för variabler och lĂ€gga till inloggning och nyckel för PVS-Studio:

Analys av commits och pull requests i Travis CI, Buddy och AppVeyor med hjÀlp av PVS-Studio
Efter detta kommer en ny pull request eller commit att starta en kontroll. Om commiten innehÄller fel kommer Buddy att pÄpeka detta pÄ sidan för pull request.

AppVeyor

InstÀllningen av AppVeyor liknar Buddy, eftersom allt sker i webgrÀnssnittet och det inte behövs att lÀgga till en fil *.yml i projektets repository.

GÄ till fliken InstÀllningar i projektöversikten:

Analys av commits och pull requests i Travis CI, Buddy och AppVeyor med hjÀlp av PVS-Studio
Rulla ner pÄ sidan och aktivera cachning för pull request-byggnader:

Analys av commits och pull requests i Travis CI, Buddy och AppVeyor med hjÀlp av PVS-Studio
Nu gÄr vi till fliken Miljö, dÀr vi anger bild för byggandet och nödvÀndiga miljövariabler:

Analys av commits och pull requests i Travis CI, Buddy och AppVeyor med hjÀlp av PVS-Studio
Om du har lĂ€st de föregĂ„ende avsnitten Ă€r du redan bekant med dessa tvĂ„ variabler — PVS_KEY och PVS_USERNAME. Om inte, pĂ„minner jag dig om att de behövs för att verifiera licensen för PVS-Studio-analysatorn. Vi kommer att trĂ€ffa dem igen i Bash-skripten.

LÀngst ner pÄ samma sida anger vi en mapp för caching:

Analys av commits och pull requests i Travis CI, Buddy och AppVeyor med hjÀlp av PVS-Studio
Om vi inte gör detta kommer vi att analysera hela projektet istÀllet för ett par filer, men fÄ output baserat pÄ de angivna filerna. DÀrför Àr det viktigt att ange rÀtt katalognamn.

Nu Àr det dags för skriptet för kontroll. Vi öppnar fliken Tester och vÀljer Skript:

Analys av commits och pull requests i Travis CI, Buddy och AppVeyor med hjÀlp av PVS-Studio
I detta formulÀr behöver vi klistra in följande 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

LÄt oss titta nÀrmare pÄ den följande delen av koden:

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

Att tilldela vÀrdet av kommandot pwd till en variabel som bör lagra detta vÀrde som standard kan verka konstigt vid första anblick, men jag ska förklara det nu.

NĂ€r jag satte upp analyzern i AppVeyor stötte jag pĂ„ ett extremt mĂ€rkligt beteende hos analyzern. Å ena sidan fungerade allt korrekt, men analysen startade aldrig. Jag spenderade mycket tid pĂ„ att inse att vi var i katalogen /home/appveyor/projects/testcalc/, medan analyzern var övertygad om att vi var i /opt/appveyor/build-agent/. DĂ„ insĂ„g jag att variabeln $PWD ljuger lite grann. DĂ€rför uppdaterade jag dess vĂ€rde manuellt innan jag startade analysen.

Och sedan Àr det som vanligt:

Analys av commits och pull requests i Travis CI, Buddy och AppVeyor med hjÀlp av PVS-Studio
LÄt oss nu titta pÄ nÀsta 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"`

HÀr fÄr vi skillnaden mellan de grenar som en pull request Àr deklarerad för. För detta behöver vi följande miljövariabler:

  • $APPVEYOR_PULL_REQUEST_NUMBER — numret pĂ„ pull requesten;
  • $APPVEYOR_REPO_NAME — anvĂ€ndarnamn och projektnamn.

Slutsats

SjÀlvklart har vi inte granskat alla möjliga tjÀnster för kontinuerlig integrering, men de har alla en extremt liknande arbetsspecifikation. Med undantag för caching, gör varje tjÀnst sin "egen cykel", sÄ det Àr alltid olika.

NÄgonstans, som i Travis-CI, krÀvs nÄgra rader kod och cache fungerar felfritt; nÄgonstans, som i AppVeyor, mÄste du bara ange mappen i instÀllningarna; men nÄgonstans mÄste du skapa unika nycklar och försöka övertyga systemet att ge dig möjlighet att ÄsidosÀtta den cachade delen. SÄ, om du vill stÀlla in analys av pull requests pÄ en tjÀnst för kontinuerlig integrering som inte diskuterades ovan, se först till att du inte fÄr problem med cache.

Tack för att du lyssnade. Om nÄgot inte fungerar, tveka inte att skriva till oss pÄ supporten. Vi hjÀlper gÀrna till.

Analys av commits och pull requests i Travis CI, Buddy och AppVeyor med hjÀlp av PVS-Studio

Om du vill dela denna artikel med en engelsktalande publik, vÀnligen anvÀnd lÀnken till översÀttningen: Maxim Zvyagintsev. Analys av commits och pull requests i Travis CI, Buddy och AppVeyor med hjÀlp av PVS-Studio.

KĂ€lla: habr.com

Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar đŸ”„ Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar | ProHoster