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

Bild 11

Ab Version 7.04 kann der PVS-Studio Analyzer für C- und C ++ - Sprachen unter Linux und MacOS die Liste der angegebenen Dateien testen. Im neuen Modus können Sie den Analysator so konfigurieren, dass Commits überprüft und Anforderungen abgerufen werden. In diesem Artikel erfahren Sie, wie Sie das Überprüfen der Liste der geänderten Dateien eines GitHub-Projekts in so beliebten CI-Systemen (Continuous Integration) wie Travis CI, Buddy und AppVeyor konfigurieren.

Überprüfungsmodus für Dateilisten


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. Es funktioniert auf 64-Bit-Systemen unter Windows, Linux und MacOS.

In PVS-Studio Version 7.04 für Linux und macOS wurde der Modus zum Überprüfen der Liste der Quelldateien angezeigt. Dies funktioniert für Projekte, deren Build-System die Generierung der Datei compile_commands.json ermöglicht. Es wird benötigt, damit der Analysator Informationen über die Kompilierung der angegebenen Dateien extrahieren kann. 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.

Der Dateilistenprüfmodus kann auch zusammen mit dem Strace-Trace-Protokoll der Compiler-Starts (pvs-studio-analyzer trace) verwendet werden. Dazu müssen Sie zunächst eine vollständige Montage des Projekts durchführen und verfolgen, damit der Analysator vollständige Informationen über die Kompilierungsparameter aller getesteten Dateien sammelt.

Diese Option hat jedoch einen erheblichen Nachteil: Sie müssen entweder bei jedem Start eine vollständige Ablaufverfolgung der gesamten Projektbaugruppe erstellen, was der Idee einer schnellen Überprüfung des Commits widerspricht. Wenn das Trace-Ergebnis selbst zwischengespeichert wird, ist der nachfolgende Start des Analysators möglicherweise nicht abgeschlossen, wenn sich die Abhängigkeitsstruktur der Quelldateien nach dem Trace ändert (z. B. wird einer der Quelldateien ein neues #include hinzugefügt).

Daher empfehlen wir nicht, den Dateilistenprüfmodus mit dem Ablaufverfolgungsprotokoll zum Überprüfen von Commits oder Pull-Anforderungen zu verwenden. Wenn Sie beim Überprüfen eines Commits eine inkrementelle Assemblierung durchführen können, sollten Sie den inkrementellen Analysemodus verwenden .

Die Liste der zu analysierenden Quelldateien wird in einer Textdatei gespeichert und mit dem Parameter -S an den Analysator übertragen:

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

In dieser Datei werden relative oder absolute Pfade zu den Dateien angegeben, und jede neue Datei sollte sich in einer neuen Zeile befinden. Es ist zulässig, nicht nur die Namen der zu analysierenden Dateien, sondern auch verschiedene Texte anzugeben. Der Analysator erkennt, dass dies keine Datei ist, und ignoriert die Zeile. Dies kann zum Kommentieren hilfreich sein, wenn Dateien manuell angegeben werden. Während der Analyse in CI wird jedoch häufig eine Liste von Dateien generiert. Dies können beispielsweise Dateien aus einer Festschreibungs- oder Pull-Anforderung sein.

In diesem Modus können Sie jetzt schnell neuen Code überprüfen, bevor er in den Hauptentwicklungszweig gelangt. Damit das Verifizierungssystem auf Warnungen des Analysators reagieren kann, wurde dem Dienstprogramm plog-converter das Flag --indicate-warnings hinzugefügt:

 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. Mit dem Rückkehrcode können Sie den Pre-Commit-Hook, die Commit- oder Pull-Anforderung blockieren und den generierten Analysebericht auf dem Bildschirm anzeigen, freigeben oder per E-Mail senden.

Hinweis Wenn Sie zum ersten Mal eine Dateilistenanalyse ausführen, wird das gesamte Projekt analysiert, da Der Analysator muss aus den Header-Dateien eine Datei mit Abhängigkeiten der Projektquelldateien generieren. Dies ist eine Funktion der Analyse von C- und C ++ - Dateien. In Zukunft kann die Abhängigkeitsdatei zwischengespeichert werden und wird vom Analysator automatisch aktualisiert. Der Vorteil der Überprüfung von Commits bei Verwendung des Dateilistenüberprüfungsmodus gegenüber der Verwendung des inkrementellen Analysemodus besteht darin, dass Sie nur diese Datei zwischenspeichern müssen, nicht die Objektdateien.

Allgemeine Prinzipien der Pull-Request-Analyse


Die Analyse des gesamten Projekts nimmt viel Zeit in Anspruch, daher ist es sinnvoll, nur einen bestimmten Teil davon zu überprüfen. Das Problem ist, dass Sie die neuen Dateien von den übrigen Projektdateien trennen müssen.

Betrachten Sie ein Beispiel für einen Festschreibungsbaum mit zwei Zweigen:

Bild 5


Stellen wir uns vor, dass Commit A1 eine ziemlich große Menge an Code enthält, der bereits getestet wurde. Etwas früher haben wir einen Zweig aus dem Commit A1 erstellt und einige Dateien geändert.

Natürlich haben Sie bemerkt, dass es nach A1 zwei weitere Commits gab, aber dies waren auch Fusionen anderer Niederlassungen, da wir keine Master- Commits durchführen. Und jetzt ist die Zeit gekommen, in der der Hotfix fertig ist. Daher erschien eine Pull-Anfrage für die Fusion von B3 und A3 .

Natürlich könnte man das gesamte Ergebnis ihrer Fusion überprüfen, aber dies wäre zu lang und ungerechtfertigt, da nur wenige Dateien geändert wurden. Daher ist es effizienter, nur die geänderten zu analysieren.

Dazu erhalten wir den Unterschied zwischen den Zweigen, die sich im KOPF des Zweigs befinden, von dem aus wir zum Master verschmelzen möchten:

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

$ MERGE_BASE werden wir später genauer betrachten. Tatsache ist, dass nicht jeder CI-Dienst die erforderlichen Informationen über die Grundlage für das Zusammenführen bereitstellt. Daher müssen Sie jedes Mal neue Wege finden, um diese Daten abzurufen. Dies wird nachstehend in jedem der beschriebenen Webdienste detailliert beschrieben.

Wir haben also den Unterschied zwischen den Zweigen oder besser gesagt eine Liste der Dateinamen, die geändert wurden. Jetzt müssen wir die .pvs-pr.list-Datei (wir haben die Ausgabe oben darauf umgeleitet) an den Analysator übergeben:

 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 Format konvertieren, das leicht zu lesen ist:

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

Dieser Befehl listet Fehler in stderr (Standard-Ausgabestream für Fehlermeldungen) auf.

Erst jetzt müssen wir nicht nur Fehler anzeigen, sondern auch unseren Service für die Montage und Prüfung von Problemen informieren. Zu diesem Zweck wurde dem 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 Pull-Anforderungsdateien informiert wird.

Travis ci


Die Konfiguration erfolgt als .travis.yml- Datei. Der Einfachheit halber empfehle ich Ihnen, alles in ein separates Bash-Skript mit Funktionen zu stellen, die aus der Datei .travis.yml ( bash script_name.sh function_name ) aufgerufen werden .

Wir werden den erforderlichen Code zum Bash- Skript hinzufügen, damit wir mehr Funktionalität erhalten. Schreiben Sie im Installationsabschnitt Folgendes:

 install: - bash .travis.sh travis_install 

Wenn Sie Anweisungen hatten, können Sie diese durch Entfernen von Bindestrichen in das Skript übertragen.

Öffnen Sie die Datei .travis.sh und fügen Sie die Analyse- Installation zur Funktion travis_install () hinzu :

 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 Sie nun den Analyselauf zum Skriptabschnitt 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 } 

Dieser Code muss nach dem Erstellen des Projekts ausgeführt werden, wenn Sie beispielsweise CMake erstellt haben:

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

Es wird sich so herausstellen:

 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 } 

Sie haben wahrscheinlich bereits die angegebenen Umgebungsvariablen $ TRAVIS_PULL_REQUEST und $ TRAVIS_BRANCH bemerkt . Travis CI kündigt sie selbst an:

  • $ 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.

Der Algorithmus dieser Funktion:

Bild 7

Travis CI reagiert auf Rückkehrcodes, sodass das Vorhandensein von Warnungen den Dienst anweist, 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 Zweige während der Pull-Anforderungsanalyse automatisch zusammenführt:

Bild 8

Daher analysieren wir A4 , nicht B3-> A3 . Aufgrund dieser Funktion müssen wir die Differenz mit A3 berechnen, das genau die Spitze des Zweigs vom Ursprung ist .

Ein wichtiges Detail blieb - das Zwischenspeichern von Abhängigkeiten von Header-Dateien von kompilierten Übersetzungseinheiten (* .c, * .cc, * .cpp usw.). Der Analysator berechnet diese Abhängigkeiten beim ersten Start im Überprüfungsmodus der Dateiliste und speichert sie dann im Verzeichnis .PVS-Studio. Mit Travis CI können Sie Ordner zwischenspeichern, sodass wir die Daten des Verzeichnisses .PVS-Studio / speichern :

 cache: directories: - .PVS-Studio/ 

Dieser Code muss zur Datei .travis.yml hinzugefügt werden. In diesem Verzeichnis werden verschiedene Daten gespeichert, die nach der Analyse erfasst wurden. Dies beschleunigt den späteren Start der Dateilistenanalyse oder der inkrementellen Analyse erheblich. Ist dies nicht der Fall, analysiert der Analysator jedes Mal alle Dateien.

Kumpel


Wie Travis CI bietet Buddy die Möglichkeit, Projekte, die auf GitHub gespeichert sind, automatisch zu erstellen und zu 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.

Zunächst müssen wir dem Fließband eine neue Aktion hinzufügen:

Bild 1

Wir geben den Compiler an, mit dem das Projekt erstellt wurde. Achten Sie auf den Docker-Container, der in dieser Aktion installiert ist. Zum Beispiel gibt es einen speziellen Container für GCC:

Bild 6

Installieren Sie 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 

Gehen Sie nun zur Registerkarte Ausführen (erstes Symbol) und fügen Sie den folgenden Code in das entsprechende Feld des Editors ein:

 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 bereits bekannt. Jetzt ist jedoch eine neue Phase erschienen:

Bild 9

Tatsache ist, dass wir jetzt nicht das Ergebnis der Fusion analysieren, sondern den HEAD des Zweigs, von dem aus die Pull-Anfrage gestellt wird:

Bild 10

Daher befinden wir uns im bedingten Commit B3 und müssen den Unterschied zu A3 ermitteln :

 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 

Verwenden Sie die GitHub-API, um A3 zu bestimmen:

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

Wir haben die folgenden Variablen verwendet, die Buddy bereitstellt:

  • $ BUDDY_EXECUTION_PULL_REQEUST_NO - Anforderungsnummer ziehen;
  • $ BUDDY_REPO_SLUG - Kombination aus Benutzername und Repository (zum Beispiel max / test).

Speichern Sie nun die Änderungen über die Schaltfläche unten und aktivieren Sie die Pull-Anforderungsanalyse:

Bild 3

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

Bild 4

Danach löst das Erscheinen einer neuen Pull-Anforderung oder eines neuen Commits eine Prüfung aus. Wenn das Commit Fehler enthält, gibt Buddy dies auf der Pull-Anforderungsseite an.

Förderer


Das AppVeyor-Setup ähnelt Buddy, da alles in der Weboberfläche geschieht und keine * .yml-Datei zum Projekt-Repository hinzugefügt werden muss.

Gehen Sie in der Projektübersicht zur Registerkarte Einstellungen:

Bild 12

Scrollen Sie auf dieser Seite nach unten und aktivieren Sie das Speichern des Caches, um Pull-Anforderungen zu erstellen:

Bild 18

Wechseln Sie nun zur Registerkarte Umgebung, auf der wir das Image für die Assembly und die erforderlichen Umgebungsvariablen angeben:

Bild 19

Wenn Sie die vorherigen Abschnitte gelesen haben, sind Sie mit diesen beiden Variablen - PVS_KEY und PVS_USERNAME - gut vertraut . Wenn nicht, erinnere ich Sie daran, dass sie zur Überprüfung der Lizenz des PVS-Studio-Analysators erforderlich sind. In Zukunft werden wir sie in Bash-Skripten wieder sehen.

Auf derselben Seite unten geben wir den Ordner für das Caching an:

Bild 15

Wenn wir dies nicht tun, analysieren wir das gesamte Projekt anstelle eines Dateipaares, erhalten jedoch die Ausgabe aus den angegebenen Dateien. Daher ist es wichtig, den richtigen Verzeichnisnamen einzugeben.

Jetzt ist es Zeit für das Skript zu überprüfen. Öffnen Sie die Registerkarte Tests und wählen Sie Skript:

Bild 20

Fügen Sie den folgenden Code in dieses Formular ein:

 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 Sie 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 

Die ziemlich spezifische Zuordnung des Werts des Befehls pwd zu der Variablen, die diesen Standardwert speichern soll, erscheint auf den ersten Blick seltsam, ich werde jedoch jetzt alles erklären.

Bei der Konfiguration des Analysators in AppVeyor bin ich auf ein äußerst seltsames Verhalten des Analysators gestoßen. Einerseits hat alles richtig funktioniert, aber die Analyse hat nicht begonnen. Ich habe viel Zeit damit verbracht zu bemerken, dass wir uns im Verzeichnis / home / appveyor / projects / testcalc / befinden und der Analysator sicher ist, dass wir uns in / opt / appveyor / build-agent / befinden. Dann wurde mir klar, dass die Variable $ PWD ein wenig lügt. Aus diesem Grund habe ich den Wert vor dem Start der Analyse manuell aktualisiert.

Und dann alles wie bisher:

Bild 17

Betrachten Sie nun den folgenden Ausschnitt:

 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 die Differenz zwischen den Zweigen, über die die Pull-Anforderung deklariert wird. Dazu benötigen wir folgende Umgebungsvariablen:

  • $ APPVEYOR_PULL_REQUEST_NUMBER - Nummer der Pull-Anfrage;
  • $ APPVEYOR_REPO_NAME - Projektbenutzername und Repository.

Fazit


Natürlich haben wir nicht alle möglichen Dienste einer kontinuierlichen Integration in Betracht gezogen, aber alle haben sehr ähnliche Arbeitsspezifikationen. Mit Ausnahme des Caching stellt jeder Dienst sein eigenes „Fahrrad“ her, sodass immer alles anders ist.

Irgendwo, wie in Travis-CI, funktionieren ein paar Zeilen Code und Caching einwandfrei. Irgendwo, wie in AppVeyor, müssen Sie nur den Ordner in den Einstellungen angeben. Aber irgendwo müssen Sie eindeutige Schlüssel erstellen und versuchen, das System davon zu überzeugen, dass Sie das zwischengespeicherte Fragment überschreiben können. Wenn Sie daher die Analyse von Pull-Anforderungen für den Continuous Integration Service konfigurieren möchten, die oben nicht erläutert 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 sich gerne an uns wenden. Wir werden umgehend bitten und helfen.



Wenn Sie diesen Artikel einem englischsprachigen Publikum zugänglich machen möchten, verwenden Sie bitte den Link zur Übersetzung: Maxim Zvyagintsev. Analyse von Commits und Pull-Anfragen in Travis CI, Buddy und AppVeyor mit PVS-Studio .

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


All Articles