Analyse av forpliktelser og pull-forespørsler i Travis CI, Buddy og AppVeyor ved hjelp av PVS-Studio

Analyse av forpliktelser og pull-forespørsler i Travis CI, Buddy og AppVeyor ved hjelp av PVS-Studio
I PVS-Studio-analysatoren for C- og C++-språk på Linux og macOS, fra og med versjon 7.04, har det dukket opp et testalternativ for å sjekke listen over spesifiserte filer. Ved å bruke den nye modusen kan du konfigurere analysatoren til å sjekke forpliktelser og pull-forespørsler. Denne artikkelen vil fortelle deg hvordan du setter opp å sjekke listen over endrede filer til et GitHub-prosjekt i slike populære CI (Continuous Integration)-systemer som Travis CI, Buddy og AppVeyor.

Kontrollmodus for filliste

PVS-Studio er et verktøy for å identifisere feil og potensielle sårbarheter i kildekoden til programmer skrevet i C, C++, C# og Java. Fungerer på 64-bits systemer på Windows, Linux og macOS.

I versjon PVS-Studio 7.04 for Linux og macOS har det dukket opp en modus for å sjekke listen over kildefiler. Dette fungerer for prosjekter hvis byggesystem lar deg generere en fil compile_commands.json. Det er nødvendig for analysatoren å trekke ut informasjon om kompileringen av de angitte filene. Hvis byggesystemet ditt ikke støtter generering av compile_commands.json-filen, kan du prøve å generere en slik fil ved hjelp av verktøyet Bær.

Fillistekontrollmodusen kan også brukes sammen med trace-sporingsloggen for kompilatorlanseringer (pvs-studio-analyzer trace). For å gjøre dette, må du først utføre en full build av prosjektet og spore det slik at analysatoren samler inn fullstendig informasjon om kompileringsparametrene til alle filene som kontrolleres.

Imidlertid har dette alternativet en betydelig ulempe - du må enten utføre et fullstendig byggespor av hele prosjektet hver gang du kjører det, noe som i seg selv motsier ideen om å raskt sjekke en forpliktelse. Eller, hvis du hurtigbuffer selve sporingsresultatet, kan påfølgende kjøringer av analysatoren være ufullstendige hvis avhengighetsstrukturen til kildefilene endres etter sporingen (for eksempel legges en ny #include til en av kildefilene).

Derfor anbefaler vi ikke å bruke fillistekontrollmodusen med sporingsloggen for å sjekke forpliktelser eller pull-forespørsler. Hvis du kan gjøre en inkrementell build når du sjekker en commit, bør du vurdere å bruke modusen inkrementell analyse.

Listen over kildefiler for analyse lagres i en tekstfil og sendes til analysatoren ved hjelp av parameteren -S:

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

Denne filen spesifiserer relative eller absolutte stier til filer, og hver ny fil må være på en ny linje. Det er akseptabelt å spesifisere ikke bare filnavn for analyse, men også forskjellig tekst. Analysatoren vil se at dette ikke er en fil og vil ignorere linjen. Dette kan være nyttig for å kommentere hvis filer er spesifisert manuelt. Imidlertid vil ofte en liste over filer genereres under analyse i CI, for eksempel kan disse være filer fra en commit- eller pull-forespørsel.

Nå, ved å bruke denne modusen, kan du raskt sjekke ny kode før den kommer inn i hovedutviklingsgrenen. For å sikre at skannesystemet reagerer på analysatoradvarsler, må verktøyet plog-omformer flagg lagt til --indikerer-advarsler:

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

Med dette flagget vil omformeren returnere en ikke-nullkode hvis det er advarsler i analysatorrapporten. Ved å bruke returkoden kan du blokkere en precommit-krok-, commit- eller pull-forespørsel, og den genererte analysatorrapporten kan vises, deles eller sendes via e-post.

Merk. Når du først begynner å analysere en liste over filer, vil hele prosjektet bli analysert, fordi analysatoren må generere en fil med avhengigheter til prosjektkildefilene på overskriftsfilene. Dette er en funksjon for å analysere C- og C++-filer. I fremtiden kan avhengighetsfilen bufres og den vil bli oppdatert automatisk av analysatoren. Fordelen med å sjekke forpliktelser når du bruker fillistekontrollmodus fremfor bruk av inkrementell analysemodus, er at du bare trenger å cache den filen og ikke objektfilene.

Generelle prinsipper for pull request-analyse

Å analysere hele prosjektet tar mye tid, så det er fornuftig å sjekke bare en viss del av det. Problemet er at du må skille de nye filene fra resten av prosjektfilene.

La oss se på et eksempel på et commit-tre med to grener:

Analyse av forpliktelser og pull-forespørsler i Travis CI, Buddy og AppVeyor ved hjelp av PVS-Studio

La oss forestille oss den forpliktelsen A1 inneholder en ganske stor mengde kode som allerede er testet. Litt tidligere har vi laget en gren fra commit A1 og endret noen filer.

Du la selvfølgelig merke til det etterpå A1 ytterligere to forpliktelser skjedde, men disse var også sammenslåinger av andre grener, fordi vi ikke forplikter oss til Master. Og nå er tiden kommet når hurtigreparasjon klar. Derfor dukket det opp en pull-forespørsel om sammenslåingen B3 и A3.

Selvfølgelig ville det være mulig å sjekke hele resultatet av deres sammenslåing, men dette ville være for tidkrevende og uberettiget, siden bare noen få filer ble endret. Derfor er det mer effektivt å analysere kun de endrede.

For å gjøre dette får vi forskjellen mellom grenene, som er i HODET til grenen som vi ønsker å slå sammen til master:

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

$MERGE_BASE vi vil se nærmere på det senere. Faktum er at ikke alle CI-tjenester gir den nødvendige informasjonen om databasen for sammenslåing, så hver gang må du finne nye måter å skaffe disse dataene på. Dette vil bli beskrevet i detalj nedenfor i hver av de beskrevne nettjenestene.

Så vi fikk forskjellen mellom grenene, eller rettere sagt, en liste over filnavn som ble endret. Nå må vi gi filen .pvs-pr.list (vi omdirigerte utdataene ovenfor til den) til analysatoren:

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

Etter analyse må vi konvertere loggfilen (PVS-Studio.log) til et lettlest format:

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

Denne kommandoen vil liste opp feilene i stderr (standard feilmeldingsutgang).

Først nå må vi ikke bare vise feil, men også informere vår tjeneste for montering og testing om tilstedeværelsen av problemer. For dette formålet ble et flagg lagt til omformeren -W (--indikerer-advarsler). Hvis det er minst én analysatoradvarsel, returnerer verktøyet koden plog-omformer endres til 2, som igjen vil informere CI-tjenesten om tilstedeværelsen av potensielle feil i pull request-filene.

Travis C.I.

Konfigurasjonen er laget som en fil .travis.yml. For enkelhets skyld anbefaler jeg deg å legge alt inn i et eget bash-skript med funksjoner som kalles opp fra filen .travis.yml (bash script_name.sh funksjonsnavn).

Vi vil legge til den nødvendige koden til skriptet på bash, på denne måten vil vi få mer funksjonalitet. I seksjon installere la oss skrive følgende:

install:
  - bash .travis.sh travis_install

Hvis du hadde noen instruksjoner, kan du overføre dem til skriptet ved å fjerne bindestrekene.

La oss åpne filen .travis.sh og legg til analysatorinnstillingen til funksjonen 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 
}

La oss nå legge til delen script kjør analyse:

script:
  - bash .travis.sh travis_script

Og i bash-manuset:

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
}

Denne koden må kjøres etter å ha bygget prosjektet, for eksempel hvis du hadde en build på CMake:

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

Det vil bli slik:

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 sikkert allerede lagt merke til disse miljøvariablene $TRAVIS_PULL_REQUEST и $TRAVIS_BRANCH. Travis CI erklærer dem uavhengig:

  • $TRAVIS_PULL_REQUEST lagrer pull request-nummeret eller falsk, hvis dette er en vanlig gren;
  • $TRAVIS_REPO_SLUG lagrer navnet på prosjektlageret.

Algoritmen for denne funksjonen:

Analyse av forpliktelser og pull-forespørsler i Travis CI, Buddy og AppVeyor ved hjelp av PVS-Studio
Travis CI reagerer på returkoder, så tilstedeværelsen av advarsler vil fortelle tjenesten om å markere forpliktelsen som inneholder feil.

La oss nå se nærmere på denne kodelinjen:

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

Faktum er at Travis CI automatisk slår sammen grener mens han analyserer en pull-forespørsel:

Analyse av forpliktelser og pull-forespørsler i Travis CI, Buddy og AppVeyor ved hjelp av PVS-Studio
Derfor analyserer vi A4Og ikke B3->A3. På grunn av denne funksjonen må vi beregne forskjellen med A3, som er nettopp toppen av grenen fra opprinnelse.

Det er én viktig detalj igjen - bufring av avhengighetene til overskriftsfiler på kompilerte oversettelsesenheter (*.c, *.cc, *.cpp, etc.). Analysatoren beregner disse avhengighetene når den først startes i modusen for å sjekke en liste over filer og lagrer dem deretter i .PVS-Studio-katalogen. Travis CI lar deg cache mapper, så vi lagrer katalogdataene .PVS-Studio/:

cache:
  directories:
    - .PVS-Studio/

Denne koden må legges til filen .travis.yml. Denne katalogen lagrer forskjellige data som er samlet inn etter analyse, noe som vil øke betydelig hastighet på påfølgende kjøringer av fillisteanalyse eller inkrementell analyse. Hvis dette ikke gjøres, vil analysatoren faktisk analysere alle filene hver gang.

Buddy

Som Travis CI, Buddy gir muligheten til å automatisk bygge og teste prosjekter lagret på GitHub. I motsetning til Travis CI er det konfigurert i webgrensesnittet (bash-støtte er tilgjengelig), så det er ikke nødvendig å lagre konfigurasjonsfiler i prosjektet.

Først av alt må vi legge til en ny handling på samlebåndet:

Analyse av forpliktelser og pull-forespørsler i Travis CI, Buddy og AppVeyor ved hjelp av PVS-Studio
La oss angi kompilatoren som ble brukt til å bygge prosjektet. Legg merke til docker-beholderen som er installert i denne handlingen. For eksempel er det en spesiell beholder for GCC:

Analyse av forpliktelser og pull-forespørsler i Travis CI, Buddy og AppVeyor ved hjelp av PVS-Studio
La oss nå installere PVS-Studio og de nødvendige verktøyene:

Analyse av forpliktelser og pull-forespørsler i Travis CI, Buddy og AppVeyor ved hjelp av PVS-Studio
La oss legge til følgende linjer i editoren:

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

La oss nå gå til Kjør-fanen (første ikon) og legge til følgende kode i det tilsvarende redigeringsfeltet:

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

Hvis du leser avsnittet om Travs-CI, er denne koden allerede kjent for deg, men nå er det et nytt stadium:

Analyse av forpliktelser og pull-forespørsler i Travis CI, Buddy og AppVeyor ved hjelp av PVS-Studio
Faktum er at nå analyserer vi ikke resultatet av sammenslåingen, men HEAD for grenen som pull-forespørselen er gjort fra:

Analyse av forpliktelser og pull-forespørsler i Travis CI, Buddy og AppVeyor ved hjelp av PVS-Studio
Så vi er i en betinget forpliktelse B3 og vi må få forskjellen fra 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

Å bestemme A3 La oss bruke GitHub API:

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

Vi brukte følgende variabler som Buddy gir:

  • $BUDDY_EXECUTION_PULL_REQEUST_NO — pull request number;
  • $BUDDY_REPO_SLUG — en kombinasjon av brukernavn og repository (for eksempel max/test).

La oss nå lagre endringene ved å bruke knappen nedenfor og aktivere analyse av pull-forespørselen:

Analyse av forpliktelser og pull-forespørsler i Travis CI, Buddy og AppVeyor ved hjelp av PVS-Studio
I motsetning til Travis CI, trenger vi ikke spesifisere .pvs-studio for caching, siden Buddy automatisk cacher alle filer for påfølgende lanseringer. Derfor er det siste som gjenstår å lagre innlogging og passord for PVS-Studio i Buddy. Etter å ha lagret endringene, vil vi bli tatt tilbake til Pipeline. Vi må gå videre til å sette opp variabler og legge til en pålogging og nøkkel for PVS-Studio:

Analyse av forpliktelser og pull-forespørsler i Travis CI, Buddy og AppVeyor ved hjelp av PVS-Studio
Etter dette vil utseendet til en ny pull-forespørsel eller commit utløse anmeldelsen. Hvis en commit inneholder feil, vil Buddy indikere dette på pull request-siden.

AppVeyor

Oppsett av AppVeyor ligner på Buddy, siden alt skjer i nettgrensesnittet og det er ikke nødvendig å legge til en *.yml-fil i prosjektlageret.

La oss gå til fanen Innstillinger i prosjektoversikten:

Analyse av forpliktelser og pull-forespørsler i Travis CI, Buddy og AppVeyor ved hjelp av PVS-Studio
La oss bla nedover denne siden og aktivere hurtigbufferlagring for å samle inn pull-forespørsler:

Analyse av forpliktelser og pull-forespørsler i Travis CI, Buddy og AppVeyor ved hjelp av PVS-Studio
La oss nå gå til fanen Miljø, der vi spesifiserer bildet for montering og de nødvendige miljøvariablene:

Analyse av forpliktelser og pull-forespørsler i Travis CI, Buddy og AppVeyor ved hjelp av PVS-Studio
Hvis du har lest de foregående avsnittene, er du godt kjent med disse to variablene − PVS_KEY и PVS_USERNAME. Hvis ikke, la meg minne deg på at de er nødvendige for å bekrefte lisensen til PVS-Studio-analysatoren. Vi vil se dem igjen i Bash-manus i fremtiden.

På samme side nedenfor angir vi mappen for caching:

Analyse av forpliktelser og pull-forespørsler i Travis CI, Buddy og AppVeyor ved hjelp av PVS-Studio
Hvis vi ikke gjør dette, vil vi analysere hele prosjektet i stedet for et par filer, men vi får utdata fra de angitte filene. Derfor er det viktig å angi riktig katalognavn.

Nå er det på tide at manuset skal testes. Åpne Tester-fanen og velg Script:

Analyse av forpliktelser og pull-forespørsler i Travis CI, Buddy og AppVeyor ved hjelp av PVS-Studio
Du må lime inn følgende kode i dette skjemaet:

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

La oss ta hensyn til følgende del 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

Den ganske spesifikke tilordningen av verdien til pwd-kommandoen til en variabel som skal lagre denne standardverdien virker rart ved første øyekast, men jeg skal forklare alt nå.

Mens jeg satte opp analysatoren i AppVeyor, møtte jeg ekstremt merkelig oppførsel til analysatoren. På den ene siden fungerte alt riktig, men analysen startet ikke. Jeg brukte mye tid på å legge merke til at vi er i /home/appveyor/projects/testcalc/-katalogen, og analysatoren er sikker på at vi er i /opt/appveyor/build-agent/. Så skjønte jeg at $PWD-variabelen løy litt. Av denne grunn oppdaterte jeg verdien manuelt før jeg startet analysen.

Og så er alt som før:

Analyse av forpliktelser og pull-forespørsler i Travis CI, Buddy og AppVeyor ved hjelp av PVS-Studio
Tenk nå på følgende 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"`

I den får vi forskjellen mellom grenene som pull-forespørselen er deklarert over. For å gjøre dette trenger vi følgende miljøvariabler:

  • $APPVEYOR_PULL_REQUEST_NUMBER — pull request nummer;
  • $APPVEYOR_REPO_NAME - brukernavn og prosjektlager.

Konklusjon

Selvfølgelig har vi ikke vurdert alle mulige kontinuerlige integreringstjenester, men de har alle ekstremt like driftsspesifikasjoner som hverandre. Med unntak av caching lager hver tjeneste sin egen "sykkel", så alt er alltid annerledes.

Et eller annet sted, som i Travis-CI, fungerer et par linjer med kode og caching feilfritt; et sted, som i AppVeyor, trenger du bare å spesifisere mappen i innstillingene; men et sted må du lage unike nøkler og prøve å overbevise systemet om å gi deg muligheten til å overskrive det bufrede fragmentet. Derfor, hvis du ønsker å sette opp analyse av pull-forespørsler på en kontinuerlig integrasjonstjeneste som ikke ble diskutert ovenfor, så sørg først for at du ikke får problemer med caching.

Takk for din oppmerksomhet. Hvis noe ikke fungerer, skriv gjerne til oss på Brukerstøtte. Vi vil gi råd og hjelpe.

Analyse av forpliktelser og pull-forespørsler i Travis CI, Buddy og AppVeyor ved hjelp av PVS-Studio

Hvis du vil dele denne artikkelen med et engelsktalende publikum, vennligst bruk oversettelseslenken: Maxim Zvyagintsev. Analyse av forpliktelser og pull-forespørsler i Travis CI, Buddy og AppVeyor ved hjelp av PVS-Studio.

Kilde: www.habr.com

Legg til en kommentar