Analyse van commits en pull requests in Travis CI, Buddy en AppVeyor met behulp van PVS-Studio

Analyse van commits en pull requests in Travis CI, Buddy en AppVeyor met behulp van PVS-Studio
In de PVS-Studio-analyzer voor C- en C++-talen op Linux en macOS, vanaf versie 7.04, is een testmogelijkheid verschenen om de lijst met opgegeven bestanden te controleren. Met de nieuwe modus kunt u de analysator configureren om commits en pull-aanvragen te controleren. In dit artikel wordt uitgelegd hoe u een GitHub-projectbestandslijstcontrole instelt in populaire CI-systemen (Continuous Integration), zoals Travis CI, Buddy en AppVeyor.

Controlemodus voor bestandslijst

PVS Studio is een hulpmiddel voor het opsporen van fouten en potentiële kwetsbaarheden in de broncode van programma's geschreven in C, C++, C# en Java. Werkt op 64-bit systemen op Windows, Linux en macOS.

De versie van PVS-Studio 7.04 voor Linux en macOS heeft een modus voor het controleren van de lijst met bronbestanden. Dit werkt voor projecten waarvan het bouwsysteem u in staat stelt een bestand te genereren compile_commands.json. Het is nodig voor de analysator om informatie te extraheren over de compilatie van de opgegeven bestanden. Als uw buildsysteem het genereren van een bestand compile_commands.json niet ondersteunt, kunt u proberen een dergelijk bestand te genereren met behulp van het hulpprogramma Beer.

Ook kan de modus voor het controleren van de lijst met bestanden worden gebruikt in combinatie met de strace-tracering van compiler-runs (pvs-studio-analyzer-tracering). Om dit te doen, moet u eerst een volledige build van het project uitvoeren en het volgen, zodat de analysator volledige informatie verzamelt over de compilatieparameters van alle bestanden die worden gecontroleerd.

Deze optie heeft echter een aanzienlijk nadeel: u moet bij elke lancering een volledige build-tracering van het hele project uitvoeren, wat op zichzelf in tegenspraak is met het idee van een snelle commit-controle. Of, als u het traceringsresultaat zelf in de cache opslaat, kunnen latere lanceringen van de analysator onvolledig blijken te zijn als de afhankelijkheidsstructuur van het bronbestand verandert na het traceren (er wordt bijvoorbeeld een nieuwe #include toegevoegd aan een van de bronbestanden).

Daarom raden we af om de bestandslijstcontrolemodus te gebruiken met een traceerlogboek om commits of pull-aanvragen te controleren. Als je een incrementele build kunt doen bij het controleren van een commit, overweeg dan om de modus te gebruiken incrementele analyse.

De lijst met bronbestanden voor analyse wordt opgeslagen in een tekstbestand en doorgegeven aan de analysator met behulp van de parameter -S:

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

Dit bestand specificeert relatieve of absolute paden naar bestanden en elk nieuw bestand moet op een nieuwe regel staan. Het is toegestaan ​​om niet alleen de namen van bestanden voor analyse op te geven, maar ook verschillende teksten. De parser ziet dat dit geen bestand is en negeert de regel. Dit kan handig zijn voor commentaar als bestanden handmatig worden opgegeven. De lijst met bestanden wordt echter vaak gegenereerd tijdens CI-parsing, bijvoorbeeld bestanden van een commit of een pull-verzoek.

Met deze modus kunt u nu snel nieuwe code testen voordat deze in de hoofdontwikkelingstak terechtkomt. Om ervoor te zorgen dat het verificatiesysteem reageert op waarschuwingen van de analysator, moet het hulpprogramma plog-converter vlag toegevoegd --indicatie-waarschuwingen:

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

Met deze vlag retourneert de converter een code die niet gelijk is aan nul als er waarschuwingen in het analysatorrapport staan. Met behulp van de retourcode kunt u een precommit hook, commit of pull request blokkeren en het gegenereerde analysatorrapport op het scherm weergeven, delen of per e-mail verzenden.

Opmerking. De eerste keer dat u begint met het analyseren van de lijst met bestanden, wordt het hele project geanalyseerd, omdat de analysator moet een bestand genereren met de afhankelijkheden van de bronbestanden van het project op de headerbestanden. Dit is een kenmerk van het parseren van C- en C++-bestanden. In de toekomst kan het afhankelijkheidsbestand in de cache worden opgeslagen en wordt het automatisch bijgewerkt door de analysator. Het voordeel van het controleren van commits bij het gebruik van de bestandslijst-controlemodus ten opzichte van het gebruik van de incrementele parseermodus is dat alleen dat bestand in de cache hoeft te worden geplaatst, niet de objectbestanden.

Algemene principes van analyse van pull-aanvragen

De analyse van het hele project kost veel tijd, dus het is logisch om slechts een deel ervan te controleren. Het probleem is dat u de nieuwe bestanden moet scheiden van de rest van de projectbestanden.

Overweeg een voorbeeld van een commit-boom met twee takken:

Analyse van commits en pull requests in Travis CI, Buddy en AppVeyor met behulp van PVS-Studio

Laten we doen alsof de commit A1 bevat een vrij grote hoeveelheid code die al is gecontroleerd. Iets eerder hebben we een branch gemaakt van de commit A1 en enkele bestanden gewijzigd.

Dat merkte je natuurlijk achteraf A1 er waren nog twee commits, maar dit waren ook fusies van andere branches, omdat we niet committen meester. En nu is de tijd gekomen dat hotfix klaar. Daarom verscheen er een pull-verzoek voor de samenvoeging B3 и A3.

Natuurlijk zou het mogelijk zijn om het volledige resultaat van hun samenvoeging te controleren, maar dit zou te lang en onterecht zijn, aangezien er maar een paar bestanden zijn gewijzigd. Daarom is het efficiënter om alleen de gewijzigde te analyseren.

Om dit te doen, krijgen we het verschil tussen de takken, omdat we ons in de HEAD bevinden van de tak van waaruit we willen samenvoegen tot master:

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

$MERGE_BASE we zullen later in detail bekijken. Feit is dat niet elke CI-service de nodige informatie geeft over de basis voor de samenvoeging, dus elke keer moet je nieuwe manieren bedenken om aan deze gegevens te komen. Dit wordt hieronder beschreven in elk van de beschreven webservices.

Dus we hebben het verschil tussen de branches, of beter gezegd, de lijst met bestandsnamen die zijn gewijzigd. Nu moeten we het bestand geven .pvs-pr.lijst (we hebben de uitvoer hierboven ernaar omgeleid) naar de analysator:

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

Na analyse moeten we het logbestand (PVS-Studio.log) converteren naar een leesbaar formaat:

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

Met deze opdracht worden de fouten weergegeven in stderr (standaardfoutuitvoerstroom).

Alleen hier hoeven we niet alleen fouten weer te geven, maar ook onze service voor montage en testen te informeren over de aanwezigheid van problemen. Hiervoor is een vlag toegevoegd aan de converter -W (--indicatie-waarschuwingen). Als er ten minste één analysatorwaarschuwing is, de retourcode van het hulpprogramma plog-converter verandert in 2, wat op zijn beurt de CI-service op de hoogte stelt van mogelijke fouten in de pull-aanvraagbestanden.

Travis CI

De configuratie wordt gemaakt in de vorm van een bestand .travis.yml. Voor het gemak raad ik je aan om alles in een apart bash-script te zetten met functies die vanuit het bestand worden aangeroepen .travis.yml (bash scriptnaam.sh functienaam).

We zullen de benodigde code toevoegen aan het script op slaan, dus we krijgen meer functionaliteit. In sectie installeren laten we het volgende schrijven:

install:
  - bash .travis.sh travis_install

Als u instructies had, kunt u deze naar het script verplaatsen door de koppeltekens te verwijderen.

Laten we het bestand openen .travis.sh en voeg de analysatorinstelling toe aan de functie 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 
}

Laten we nu toevoegen aan de sectie script loop analyse:

script:
  - bash .travis.sh travis_script

En in bash-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
}

Deze code moet worden uitgevoerd nadat het project is gebouwd, bijvoorbeeld als u een CMake-build had:

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

Het zal zo worden:

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
}

De gespecificeerde omgevingsvariabelen zijn u waarschijnlijk al opgevallen. $TRAVIS_PULL_REQUEST и $TRAVIS_BRANCH. Travis CI verklaart ze zelf:

  • $TRAVIS_PULL_REQUEST slaat het pull-aanvraagnummer op, of valsals het een normale tak is;
  • $TRAVIS_REPO_SLUG slaat de naam van de projectrepository op.

Het algoritme van deze functie:

Analyse van commits en pull requests in Travis CI, Buddy en AppVeyor met behulp van PVS-Studio
Travis CI reageert op retourcodes, dus de aanwezigheid van waarschuwingen zal de service vertellen om de commit als buggy te markeren.

Laten we deze coderegel eens nader bekijken:

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

Feit is dat Travis CI branches automatisch samenvoegt tijdens de analyse van een pull request:

Analyse van commits en pull requests in Travis CI, Buddy en AppVeyor met behulp van PVS-Studio
Daarom analyseren we A4En niet B3->A3. Vanwege deze functie moeten we het verschil berekenen van A3, dat is gewoon de bovenkant van de tak van herkomst.

Er blijft één belangrijk detail over: het cachen van de afhankelijkheden van headerbestanden op gecompileerde vertaaleenheden (*.c, *.cc, *.cpp, enz.). De analysator berekent deze afhankelijkheden bij de eerste start in de modus van het controleren van de lijst met bestanden en slaat ze vervolgens op in de .PVS-Studio-directory. Met Travis CI kunt u mappen cachen, zodat we directorygegevens opslaan .PVS-Studio/:

cache:
  directories:
    - .PVS-Studio/

Deze code moet aan het bestand worden toegevoegd .travis.yml. In deze map worden verschillende gegevens opgeslagen die na analyse zijn verzameld, wat de volgende uitvoeringen van bestandslijstanalyse of incrementele analyse aanzienlijk zal versnellen. Gebeurt dit niet, dan zal de analysator eigenlijk elke keer alle bestanden analyseren.

Maat

Zoals Travis C.I., Maat biedt de mogelijkheid om automatisch projecten te bouwen en te testen die zijn opgeslagen op GitHub. In tegenstelling tot Travis CI wordt het geconfigureerd in de webinterface (bash-ondersteuning is beschikbaar), dus het is niet nodig om configuratiebestanden in het project op te slaan.

Allereerst moeten we een nieuwe actie toevoegen aan de bouwregel:

Analyse van commits en pull requests in Travis CI, Buddy en AppVeyor met behulp van PVS-Studio
Geef de compiler op die is gebruikt om het project te bouwen. Let op de docker-container die in deze activiteit is geïnstalleerd. Zo is er een speciale container voor GCC:

Analyse van commits en pull requests in Travis CI, Buddy en AppVeyor met behulp van PVS-Studio
Laten we nu PVS-Studio en de benodigde hulpprogramma's installeren:

Analyse van commits en pull requests in Travis CI, Buddy en AppVeyor met behulp van PVS-Studio
Voeg de volgende regels toe aan de editor:

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

Laten we nu naar het tabblad Uitvoeren gaan (het eerste pictogram) en de volgende code toevoegen aan het overeenkomstige editorveld:

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

Als je het gedeelte over Travs-CI hebt gelezen, dan is deze code je al bekend, maar nu is er een nieuwe stap:

Analyse van commits en pull requests in Travis CI, Buddy en AppVeyor met behulp van PVS-Studio
Het feit is dat we nu niet het resultaat van de samenvoeging analyseren, maar de HEAD van de branch van waaruit het pull-verzoek is gedaan:

Analyse van commits en pull requests in Travis CI, Buddy en AppVeyor met behulp van PVS-Studio
We zitten dus in een voorwaardelijke commit B3 en we moeten het verschil er uit halen 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

Om te bepalen A3 Laten we de GitHub API gebruiken:

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

We gebruikten de volgende variabelen van Buddy:

  • $BUDDY_EXECUTION_PULL_REQEUST_NR - pull-aanvraagnummer;
  • $BUDDY_REPO_SLUG - een combinatie van gebruikersnaam en repository (bijvoorbeeld max/test).

Laten we nu de wijzigingen opslaan met behulp van de onderstaande knop en pull-aanvraaganalyse inschakelen:

Analyse van commits en pull requests in Travis CI, Buddy en AppVeyor met behulp van PVS-Studio
In tegenstelling tot Travis CI hoeven we niet te specificeren .pvs-studio voor caching, aangezien Buddy automatisch alle bestanden in de cache opslaat voor latere lanceringen. Daarom is het laatste wat overblijft het opslaan van de login en het wachtwoord voor PVS-Studio in Buddy. Nadat we de wijzigingen hebben opgeslagen, gaan we terug naar de pijplijn. We moeten naar het instellen van variabelen gaan en login en sleutel toevoegen voor PVS-Studio:

Analyse van commits en pull requests in Travis CI, Buddy en AppVeyor met behulp van PVS-Studio
Daarna zal het verschijnen van een nieuw pull-verzoek of commit een controle activeren. Als een commit fouten bevat, zal Buddy dit aangeven op de pull request-pagina.

AppVeyor

Het instellen van AppVeyor is vergelijkbaar met Buddy, omdat alles in de webinterface gebeurt en het niet nodig is om een ​​*.yml-bestand aan de projectrepository toe te voegen.

Laten we naar het tabblad Instellingen in het projectoverzicht gaan:

Analyse van commits en pull requests in Travis CI, Buddy en AppVeyor met behulp van PVS-Studio
Laten we naar beneden scrollen op deze pagina en cacheopslag inschakelen voor het bouwen van pull-aanvragen:

Analyse van commits en pull requests in Travis CI, Buddy en AppVeyor met behulp van PVS-Studio
Laten we nu naar het tabblad Omgeving gaan, waar we de te bouwen afbeelding en de benodigde omgevingsvariabelen specificeren:

Analyse van commits en pull requests in Travis CI, Buddy en AppVeyor met behulp van PVS-Studio
Als je de voorgaande paragrafen hebt gelezen, ben je goed bekend met deze twee variabelen − PVS_KEY и PVS_USERNAME. Zo niet, laat me u er dan aan herinneren dat ze nodig zijn om de licentie van de PVS-Studio-analysator te controleren. In de toekomst zullen we ze weer tegenkomen in Bash-scripts.

Geef op dezelfde pagina hieronder de map voor caching op:

Analyse van commits en pull requests in Travis CI, Buddy en AppVeyor met behulp van PVS-Studio
Als we dit niet doen, analyseren we het hele project in plaats van een paar bestanden, maar krijgen we de uitvoer op basis van de opgegeven bestanden. Daarom is het belangrijk om de juiste mapnaam in te voeren.

Nu is het tijd om het script te testen. Open het tabblad Tests en selecteer Script:

Analyse van commits en pull requests in Travis CI, Buddy en AppVeyor met behulp van PVS-Studio
Plak de volgende code in dit formulier:

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

Laten we eens kijken naar het volgende deel van de code:

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

De nogal specifieke toewijzing van de waarde van het pwd-commando aan een variabele die deze standaardwaarde zou moeten opslaan, lijkt op het eerste gezicht vreemd, maar ik zal alles zo meteen uitleggen.

Tijdens het instellen van de analysator in AppVeyor kwam ik een buitengewoon vreemd gedrag van de analysator tegen. Aan de ene kant werkte alles correct, maar de analyse kwam niet op gang. Ik heb veel tijd besteed aan het opmerken dat we ons in de /home/appveyor/projects/testcalc/ directory bevinden, en de analysator weet zeker dat we ons in /opt/appveyor/build-agent/ bevinden. Toen besefte ik dat de variabele $PWD een beetje een leugen is. Om deze reden heb ik de waarde handmatig bijgewerkt voordat ik met de analyse begon.

En dan alles, zoals voorheen:

Analyse van commits en pull requests in Travis CI, Buddy en AppVeyor met behulp van PVS-Studio
Beschouw nu het volgende 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"`

Daarin krijgen we het verschil tussen de takken waarop het pull-verzoek wordt gedeclareerd. Hiervoor hebben we de volgende omgevingsvariabelen nodig:

  • $APPVEYOR_PULL_REQUEST_NUMBER - pull-aanvraagnummer;
  • $APPVEYOR_REPO_NAME - gebruikersnaam en projectrepository.

Conclusie

Natuurlijk hebben we niet alle mogelijke continue integratieservices overwogen, maar ze hebben allemaal zeer vergelijkbare werkspecificaties. Met uitzondering van caching maakt elke dienst zijn eigen "fiets", dus alles is altijd anders.

Ergens, zoals in Travis-CI, werken een paar regels code en caching feilloos; ergens, zoals in AppVeyor, hoef je alleen maar de map in de instellingen op te geven; maar ergens moet je unieke sleutels maken en proberen het systeem te overtuigen om je de mogelijkheid te geven het in de cache opgeslagen fragment te overschrijven. Als je daarom een ​​pull-aanvraaganalyse wilt opzetten op een continue integratieservice die hierboven niet is besproken, zorg er dan eerst voor dat je geen problemen krijgt met caching.

Bedankt voor uw aandacht. Als er iets niet lukt, schrijf ons dan gerust op ondersteunen. Wij zullen adviseren en helpen.

Analyse van commits en pull requests in Travis CI, Buddy en AppVeyor met behulp van PVS-Studio

Als u dit artikel wilt delen met een Engelssprekend publiek, gebruik dan de vertaallink: Maxim Zvyagintsev. Analyse van commits en pull requests in Travis CI, Buddy en AppVeyor met behulp van PVS-Studio.

Bron: www.habr.com

Voeg een reactie