Analyse von Commits und Pull-Anfragen in Travis CI, Buddy und AppVeyor mit PVS-Studio

Bild 11

Ab Version 7.04 bietet der PVS-Studio Analyzer für C- und C ++ - Sprachen unter Linux und MacOS die Testfunktion zum Überprüfen der Liste der angegebenen Dateien. Im neuen Modus können Sie den Analysator so konfigurieren, dass Commits überprüft und Anforderungen abgerufen werden. Dieser Artikel behandelt das Einrichten der Überprüfung bestimmter geänderter Dateien aus einem GitHub-Projekt in so beliebten CI-Systemen (Continuous Integration) wie Travis CI, Buddy und AppVeyor.

Modus zum Überprüfen der Liste der Dateien


PVS-Studio ist ein Tool zum Erkennen von Fehlern und potenziellen Schwachstellen im Quellcode von Programmen, die in C, C ++, C # und Java geschrieben wurden. Funktioniert in 64-Bit-Systemen unter Windows, Linux und MacOS.

In der PVS-Studio 7.04-Version für Linux und MacOS gibt es jetzt die Möglichkeit, die Liste der Dateien zu überprüfen. Es funktioniert für Projekte, deren Build-System das Generieren der Datei compile_commands.json ermöglicht . Es wird benötigt, damit der Analysator Informationen über die Kompilierung bestimmter Dateien erhält. Wenn Ihr Build-System die Generierung der Datei compile_commands.json nicht unterstützt, können Sie versuchen, eine solche Datei mit dem Dienstprogramm Bear zu generieren.

Diese Art der Überprüfung der Dateiliste kann auch mit dem von strace generierten Compiler-Ablaufverfolgungsprotokoll (pvs-studio-analyzer trace) verwendet werden. Dazu müssen Sie zunächst einen vollständigen Projektaufbau abschließen und verfolgen, damit der Analysator vollständige Informationen zu den Kompilierungsparametern aller überprüften Dateien sammelt.

Diese Option hat jedoch einen erheblichen Nachteil: Sie müssen entweder bei jedem Lauf eine vollständige Build-Ablaufverfolgung des gesamten Projekts durchführen, was der Idee einer schnellen Commit-Überprüfung widerspricht. Wenn Sie das Ablaufverfolgungsergebnis selbst zwischenspeichern, sind nachfolgende Analysatorläufe möglicherweise unvollständig, wenn sich nach dem Verfolgen der Struktur der Quelldateien die Abhängigkeiten ändern (z. B. wird in einer der Quelldateien ein neues #include hinzugefügt).

Daher empfehlen wir nicht, den Modus zum Überprüfen der Dateiliste mit einem Ablaufverfolgungsprotokoll zu verwenden, um Commits oder Pull-Anforderungen zu überprüfen. Wenn Sie beim Überprüfen eines Commits einen inkrementellen Build ausführen können, sollten Sie den inkrementellen Analysemodus verwenden .

Die Liste der Quelldateien für die Analyse wird in der Textdatei gespeichert und mit dem Parameter -S an den Analysator übergeben:

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

Diese Datei enthält relative und absolute Pfade zu Dateien, in denen jede neue Datei in einer neuen Zeile steht. Sie können sowohl Dateinamen für die Analyse als auch unterschiedlichen Text angeben. Der Analysator erkennt, dass es sich nicht um einen Dateinamen handelt, und ignoriert die Zeile. Dies kann zum Kommentieren hilfreich sein, wenn Dateien manuell angegeben werden. Häufig wird die Liste der Dateien jedoch während der CI-Analyse generiert. Dies können beispielsweise Dateien aus einem Commit oder einer Pull-Anforderung sein.

In diesem Modus können Sie jetzt schnell neuen Code überprüfen, bevor er in den Hauptentwicklungszweig gelangt. Das Flag --indicate-warnings wurde im Dienstprogramm plog-converter hinzugefügt, damit das Prüfsystem auf das Vorhandensein von Warnungen des Analysators reagiert.

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

Mit diesem Flag gibt der Konverter einen Code ungleich Null zurück, wenn der Analysatorbericht Warnungen enthält. Sie können den Pre-Commit-Hook, die Commit- oder Pull-Anforderung blockieren und den generierten Analysatorbericht anzeigen, freigeben oder per E-Mail senden.

Hinweis Während der ersten Analyse der Dateiliste wird das gesamte Projekt überprüft, da der Analysator die Datei mit Abhängigkeiten von Projektquelldateien aus Headerdateien generieren muss. Dies ist eine Besonderheit der Analyse von C- und C ++ - Dateien. In Zukunft kann diese Abhängigkeitsdatei zwischengespeichert werden und wird vom Analysator automatisch aktualisiert. Der Vorteil der Überprüfung von Commits im Modus zum Überprüfen der Dateiliste gegenüber dem inkrementellen Analysemodus besteht darin, dass Sie nur diese Datei und nicht die Objektdateien zwischenspeichern müssen.

Allgemeine Prinzipien der Pull-Request-Analyse


Die gesamte Projektanalyse nimmt viel Zeit in Anspruch, daher ist es sinnvoll, nur einen Teil davon zu überprüfen. Das Problem ist, dass Sie neue Dateien von den übrigen Projektdateien trennen müssen.

Schauen wir uns das Beispiel eines Commit-Baums mit zwei Zweigen an:

Bild 5


Stellen Sie sich vor, das A1- Commit enthält ziemlich viel Code, der bereits überprüft wurde. Zuvor haben wir einen Zweig aus dem A1- Commit erstellt und einige Dateien geändert.

Natürlich haben Sie bemerkt, dass nach A1 zwei weitere Commits stattgefunden haben und zwei weitere Zweige zusammengeführt wurden, da wir im Master keine Commits durchführen. Hier kommt der Moment, in dem der Hotfix bereit ist. Aus diesem Grund haben wir eine Pull-Anfrage für die Zusammenführung von B3 und A3 erhalten .

Wir könnten das Ergebnis ihrer Zusammenführung überprüfen, aber es wäre zu lang und unvernünftig, da nur wenige Dateien geändert wurden. Daher ist es effizienter, nur die geänderten zu analysieren.

Dazu erhalten wir den Unterschied zwischen Zweigen, die sich im KOPF des Zweigs befinden, von dem wir in den Master übergehen möchten:

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

Wir werden $ MERGE_BASE später im Detail betrachten. Tatsache ist, dass nicht jeder CI-Service die erforderlichen Informationen auf der Zusammenführungsbasis bereitstellt. Daher müssen wir jedes Mal über neue Wege nachdenken, um diese Daten abzurufen. Dies wird nachstehend für jeden der beschriebenen Webdienste im Detail betrachtet.

Wir haben also einen Unterschied zwischen Zweigen, dh der Liste der geänderten Dateinamen. Jetzt müssen wir diese .pvs-pr.list- Datei dem Analysator zuführen . Wir haben die Ausgabe früher darauf umgeleitet.

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

Nach der Analyse müssen wir die Protokolldatei (PVS-Studio.log) in ein benutzerfreundliches Format konvertieren:

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

Dieser Befehl gibt die Fehlerliste in stderr (Standardfehlerstrom) aus.

Der Haken ist, dass wir nicht nur die Fehler ausgeben müssen, sondern auch unseren Build- und Test-Service über die Probleme informieren müssen. Zu diesem Zweck wurde im Konverter das Flag -W ( --indicate-warnings ) hinzugefügt. Wenn mindestens eine Analysatorwarnung vorliegt , ändert sich der Rückkehrcode des Plog-Converter- Dienstprogramms in 2, wodurch der CI-Dienst über mögliche Fehler in den Dateien der Pull-Anforderung informiert wird.

Travis ci


Die Konfiguration erfolgt in Form der Datei .travis.yml . Der Einfachheit halber empfehle ich Ihnen, alle Befehle, die sich auf PVS-Studio beziehen, in einem separaten Bash-Skript mit Funktionen zu isolieren, die aus der Datei .travis.yml ( Bash-Skriptname.sh Funktionsname ) aufgerufen werden .

Durch Erweitern des Skripts erhalten Sie mehr Funktionen. Schreiben Sie im Installationsabschnitt Folgendes:

 install: - bash .travis.sh travis_install 

Wenn Sie einige Anweisungen hatten, können Sie diese im Skript verschieben, nachdem Sie Bindestriche entfernt haben.

Öffnen Sie die Datei .travis.sh und fügen Sie die Analyzer-Installation in die Funktion travis_install () ein :

 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 } 

Fügen wir nun den im Skriptabschnitt ausgeführten Analysator hinzu:

 script: - bash .travis.sh travis_script 

Und im Bash-Skript:

 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 } 

Sie müssen diesen Code nach dem Erstellen des Projekts ausführen, wenn Sie beispielsweise CMake erstellt haben:

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

Sie erhalten Folgendes:

 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 } 

Höchstwahrscheinlich haben Sie die Umgebungsvariablen $ TRAVIS_PULL_REQUEST und $ TRAVIS_BRANCH bereits bemerkt. Travis CI erklärt sie selbst:

  • $ TRAVIS_PULL_REQUEST speichert die Pull-Anforderungsnummer oder false, wenn es sich um eine reguläre Verzweigung handelt.
  • $ TRAVIS_REPO_SLUG speichert den Namen des Projekt-Repositorys.

Hier ist der Betriebsalgorithmus dieser Funktion:

Bild 13

Travis CI reagiert auf Rückkehrcodes, sodass das Vorhandensein von Warnungen den Dienst meldet, um das Commit als fehlerhaft zu markieren.

Schauen wir uns nun diese Codezeile genauer an:
 git diff --name-only origin/HEAD > .pvs-pr.list 

Tatsache ist, dass Travis CI bei der Analyse einer Pull-Anforderung automatisch Zweige zusammenführt:

Bild 8

Deshalb analysieren wir A4 , nicht B3-> A3 . Aufgrund dieser Besonderheit müssen wir den Unterschied zu A3 bewerten, dem Kopf des Zweigs vom Ursprung .

Ein wichtiges Detail bleibt - das Zwischenspeichern der Abhängigkeiten von Header-Dateien von kompilierten Übersetzungseinheiten (* .c, * .cc, * .cpp und andere). Der Analysator wertet diese Abhängigkeiten während des ersten Durchlaufs aus, indem er die Liste der Dateien überprüft und sie dann im Verzeichnis .PVS-Studio speichert. Travis CI ermöglicht das Zwischenspeichern von Repositorys, daher speichern wir Daten im Verzeichnis .PVS-Studio / :

 cache: directories: - .PVS-Studio/ 

Dieser Code muss in die Datei .travis.yml eingefügt werden: In diesem Verzeichnis werden verschiedene Daten gespeichert, die nach der Analyse erfasst wurden. Diese Daten beschleunigen nachfolgende Durchläufe der Dateilistenanalyse oder der inkrementellen Analyse erheblich. Wenn Sie dies nicht tun, analysiert der Analysator jedes Mal alle Dateien.

Kumpel


Mit Buddy können Sie wie mit Travis CI automatisch Projekte aus GitHub erstellen und testen. Im Gegensatz zu Travis CI wird es über die Weboberfläche konfiguriert (Bash-Unterstützung ist verfügbar), sodass keine Konfigurationsdateien im Projekt gespeichert werden müssen.

Zuerst müssen wir der Pipeline einen neuen Schritt hinzufügen:

Bild 1

Geben Sie den Compiler an, der zum Erstellen des Projekts verwendet wird. Achten Sie auf den Docker-Container, der in diesem Schritt installiert wurde. Zum Beispiel gibt es einen speziellen Container für GCC:

Bild 6

Installieren wir nun PVS-Studio und die erforderlichen Dienstprogramme:

Bild 2

Fügen Sie dem Editor die folgenden Zeilen hinzu:

 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 

Fahren wir mit der Registerkarte Ausführen (erstes Symbol) fort und fügen dem folgenden Editorfeld den folgenden Code hinzu:
 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 

Wenn Sie den Abschnitt über Travs-CI lesen, ist Ihnen dieser Code bekannt. Aber hier gibt es einen neuen Schritt:

Bild 14

Tatsache ist, dass wir jetzt nicht das Ergebnis der Zusammenführung analysieren, sondern den HEAD des Zweigs mit der aktivierten Pull-Anforderung:

Bild 10

Wir sind also in einem B3- Commit und müssen den Unterschied zu A3 herausfinden :

 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 

Um A3 zu definieren, verwenden wir die GitHub-API:

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

Wir haben die folgenden Variablen verwendet, die Buddy uns zur Verfügung stellt:

  • $ BUDDY_EXECUTION_PULL_REQEUST_NO - Nummer einer Pull-Anfrage;
  • $ BUDDY_REPO_SLUG - Kombination aus Benutzername und Repository (z. B. max / test).

Speichern Sie nun die Änderungen mithilfe der folgenden Schaltfläche und aktivieren Sie die Pull-Anforderungsanalyse:

Bild 3

Im Gegensatz zu Travis CI müssen wir für das Caching nicht .pvs-studio angeben, da Buddy automatisch alle Dateien für nachfolgende Läufe zwischenspeichert. Als letztes müssen Sie also den Login und das Passwort für PVS-Studio in Buddy speichern. Nach dem Speichern der Änderungen kehren wir in die Pipeline zurück. Wir müssen mit dem Einrichten der Variablen fortfahren und den Login und den Schlüssel für PVS-Studio einfügen:

Bild 4

Danach beginnt eine Überprüfung mit jeder neuen Pull-Anforderung oder jedem neuen Commit. Wenn ein Commit Fehler enthält, weist Buddy auf der Pull-Anforderungsseite darauf hin.

Förderer


Die AppVeyor-Einstellung ist ähnlich wie bei Buddy, da dies alles in der Weboberfläche geschieht und die Datei * .yml nicht im Projekt-Repository hinzugefügt werden muss.

Gehen wir in der Projektübersicht zur Registerkarte Einstellungen:

Bild 12

Scrollen Sie auf dieser Seite nach unten und aktivieren Sie das Speichern des Cache für die Erstellung von Pull-Anforderungen:

Bild 18


Fahren wir nun mit der Registerkarte Umgebung fort, auf der wir das Image für den Build und die benötigten Umgebungsvariablen angeben:

Bild 19

Wenn Sie die vorherigen Abschnitte gelesen haben, sind Sie bereits mit diesen beiden Variablen vertraut - PVS_KEY und PVS_USERNAME . Wenn nicht, möchte ich Sie daran erinnern, dass sie zur Überprüfung der PVS-Studio Analyzer-Lizenz benötigt werden. In Zukunft werden wir sie in Bash-Skripten wieder sehen.

Geben Sie auf derselben Seite unten den Cache-Ordner an:

Bild 15

Wenn wir dies nicht tun, analysieren wir das gesamte Projekt anstelle einiger Dateien, erhalten jedoch die Ausgabe für die angegebenen Dateien. Daher ist es wichtig, den richtigen Namen des Repositorys einzugeben.

Jetzt ist die Zeit für das Überprüfungsskript gekommen. Öffnen Sie die Registerkarte Tests und wählen Sie Skript:

Bild 20

Der folgende Code sollte in dieses Formular eingefügt werden:

 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 

Beachten wir den folgenden Teil des Codes:

 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 

Es ist eine ganz bestimmte Zuordnung des Ausgabewerts des Befehls pwd zur Variablen, die diesen Wert standardmäßig speichern muss. Zunächst scheint es seltsam, aber lassen Sie mich alles erklären.

Beim Einrichten des Analysators in AppVeyor bin ich auf ein sehr seltsames Verhalten des Analysators gestoßen. Einerseits hat alles richtig funktioniert, aber die Analyse hat nicht begonnen. Es hat viel Zeit gekostet zu bemerken, dass wir uns im Verzeichnis / home / appveyor / projects / testcalc / befanden, während der Analysator sicher war, dass wir uns in / opt / appveyor / build-agent / befanden. In diesem Moment wurde mir klar, dass die Variable $ PWD trügerisch ist. Aus diesem Grund habe ich den Wert vor dem Ausführen der Analyse manuell erneuert.

Die weitere Reihenfolge der Aktionen war dieselbe wie zuvor:

Bild 16

Schauen Sie sich nun dieses Fragment an:

 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"` 

Darin erhalten wir den Unterschied zwischen Zweigen, bezogen auf die überprüfte Pull-Anforderung. Dazu benötigen wir folgende Umgebungsvariablen:

  • $ APPVEYOR_PULL_REQUEST_NUMBER - Anforderungsnummer ziehen;
  • $ APPVEYOR_REPO_NAME - Benutzername und Projekt-Repository.

Fazit


Nun, wir haben nicht alle möglichen kontinuierlichen Integrationsdienste in Betracht gezogen, sie haben jedoch alle ähnliche betriebliche Besonderheiten. Beim Caching erfindet jeder Dienst sein eigenes Rad neu, sodass es immer anders ist.

In einigen Fällen (wie in Travis-CI) sind einige Codezeilen erforderlich - und das Caching funktioniert einwandfrei. In anderen Fällen (wie in AppVeyor) müssen Sie nur das Verzeichnis in den Einstellungen angeben. Es gibt jedoch einige Dienste, bei denen Sie spezielle Schlüssel erstellen und versuchen müssen, das System davon zu überzeugen, dass Sie die Möglichkeit haben, ein zwischengespeichertes Fragment neu zu schreiben. Wenn Sie die Pull-Anforderungsanalyse für einen kontinuierlichen Integrationsdienst konfigurieren möchten, der oben nicht berücksichtigt wurde, stellen Sie zunächst sicher, dass Sie keine Probleme mit dem Caching haben.

Vielen Dank für Ihre Aufmerksamkeit. Wenn etwas nicht funktioniert, können Sie sicher an unseren Support schreiben. Wir geben Ihnen einen Hinweis und helfen Ihnen.

Source: https://habr.com/ru/post/de470982/


All Articles