Analyse des validations et des demandes d'extraction dans Travis CI, Buddy et AppVeyor à l'aide de PVS-Studio

Image 11

À partir de la version 7.04, l'analyseur PVS-Studio pour les langages C et C ++ sous Linux et macOS fournit la fonction de test de vérification de la liste des fichiers spécifiés. En utilisant le nouveau mode, vous pouvez configurer l'analyseur pour vérifier les validations et les demandes d'extraction. Cet article couvre la configuration de la vérification de certains fichiers modifiés à partir d'un projet GitHub dans des systèmes CI (intégration continue) populaires, tels que Travis CI, Buddy et AppVeyor.

Mode de vérification de la liste des fichiers


PVS-Studio est un outil conçu pour détecter les erreurs et les vulnérabilités potentielles dans le code source des programmes, écrit en C, C ++, C # et Java. Fonctionne dans les systèmes 64 bits sur Windows, Linux et macOS.

Dans la version PVS-Studio 7.04 pour Linux et macOS, il existe désormais le mode de vérification de la liste des fichiers. Il fonctionne pour les projets, dont le système de construction permet de générer le fichier compile_commands.json . Il est nécessaire pour que l'analyseur obtienne des informations sur la compilation de certains fichiers. Si votre système de génération ne prend pas en charge la génération du fichier compile_commands.json, vous pouvez essayer de générer ce fichier à l'aide de l'utilitaire Bear .

Ce mode de vérification de la liste des fichiers peut également être utilisé avec le journal de suivi d'exécution du compilateur généré par strace (trace pvs-studio-analyzer). Pour ce faire, vous devez d'abord terminer une génération de projet complète et la suivre afin que l'analyseur collecte des informations complètes sur les paramètres de compilation de tous les fichiers vérifiés.

Cependant, cette option présente un inconvénient important - vous devrez soit effectuer un suivi complet de la construction de l'ensemble du projet à chaque exécution, ce qui va à l'encontre de l'idée d'une vérification de validation rapide. Ou si vous mettez en cache le résultat du suivi lui-même, les exécutions d'analyseurs suivantes peuvent être incomplètes si, après le suivi, la structure des fichiers sources change (par exemple, un nouveau #include est ajouté dans l'un des fichiers source).

Par conséquent, nous ne recommandons pas d'utiliser le mode de vérification de la liste des fichiers avec un journal de suivi pour vérifier les validations ou les demandes d'extraction. Si vous pouvez effectuer une génération incrémentielle lors de la vérification d'une validation, envisagez d'utiliser le mode d' analyse incrémentielle .

La liste des fichiers source pour l'analyse est enregistrée dans le fichier texte et transmise à l'analyseur à l'aide du paramètre -S :

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

Ce fichier contient des chemins relatifs et absolus vers des fichiers où chaque nouveau fichier arrive sur une nouvelle ligne. Vous pouvez spécifier les deux noms de fichier pour l'analyse et un texte différent. Quant au texte, l'analyseur remarquera qu'il ne s'agit pas d'un nom de fichier et ignorera la ligne. Il peut être utile de commenter si les fichiers sont spécifiés manuellement. Cependant, la liste des fichiers est souvent générée lors de l'analyse CI, par exemple, il peut s'agir de fichiers provenant d'une validation ou d'une demande d'extraction.

Maintenant, en utilisant ce mode, vous pouvez rapidement vérifier le nouveau code avant qu'il n'entre dans la branche principale de développement. L' indicateur --indicate-warnings a été ajouté dans l' utilitaire de conversion de plog afin que le système de vérification réponde à la présence d'avertissements de l'analyseur.

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

Avec cet indicateur, le convertisseur retournera un code différent de zéro s'il y a des avertissements dans le rapport de l'analyseur. Vous pouvez bloquer le crochet de pré-validation, la demande de validation ou d'extraction et afficher le rapport généré de l'analyseur, le partager ou l'envoyer par courrier.

Remarque Lors de la première analyse de la liste des fichiers, l'ensemble du projet sera vérifié, car l'analyseur doit générer le fichier avec les dépendances des fichiers source du projet à partir des fichiers d'en-tête. Il s'agit d'une particularité de l'analyse des fichiers C et C ++. À l'avenir, ce fichier de dépendance peut être mis en cache et sera automatiquement mis à jour par l'analyseur. L'avantage de la vérification des validations en utilisant le mode de vérification de la liste des fichiers par rapport au mode d'analyse incrémentielle est le fait que vous ne devez mettre en cache que ce fichier, pas les fichiers objets.

Principes généraux de l'analyse des demandes de tirage


L'analyse complète du projet prend beaucoup de temps, il est donc logique de n'en vérifier qu'une partie. Le problème est que vous devez séparer les nouveaux fichiers du reste des fichiers du projet.

Regardons l'exemple d'un arbre de validation à deux branches:

Image 5


Imaginez que la validation A1 contienne une quantité de code assez importante qui a déjà été vérifiée. Auparavant, nous avons créé une branche à partir de la validation A1 et modifié certains fichiers.

Bien sûr, vous avez remarqué qu'après A1 , deux autres validations ont eu lieu et deux autres branches ont fusionné, car nous ne validons pas en master . Voici le moment où le correctif est prêt. C'est pourquoi nous avons reçu une demande d'extraction pour la fusion B3 et A3 .

Nous pourrions vérifier le résultat de leur fusion, mais ce serait trop long et déraisonnable, car seuls quelques fichiers ont été modifiés. Par conséquent, il est plus efficace d'analyser uniquement les modifications.

Pour ce faire, nous recevrons la différence entre les branches, étant en tête de la branche, à partir de laquelle nous voulons fusionner dans le maître:

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

Nous considérerons $ MERGE_BASE en détail plus tard. Le fait est que tous les services CI ne fournissent pas les informations nécessaires sur la base de fusion, donc à chaque fois nous devons penser à de nouvelles façons d'obtenir ces données. Ceci sera considéré dans les détails ci-dessous pour chacun des services Web décrits.

Nous avons donc obtenu la différence entre les branches, qui est la liste des noms de fichiers modifiés. Maintenant, nous devons envoyer ce fichier .pvs-pr.list à l'analyseur. Nous y avons redirigé la sortie plus tôt.

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

Après l'analyse, nous devons convertir le fichier journal (PVS-Studio.log) dans un format convivial:

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

Cette commande affichera la liste des erreurs dans stderr (flux d'erreurs standard).

Le problème est que nous devons non seulement générer les erreurs, mais également signaler notre service de génération et de test des problèmes. Pour ce faire, l' indicateur -W ( --indicate-warnings ) a été ajouté dans le convertisseur. S'il y a au moins un avertissement de l'analyseur, le code de retour de l' utilitaire de conversion de plog passera à 2, qui à son tour signalera le service CI sur les erreurs potentielles dans les fichiers de demande d'extraction.

Travis ci


La configuration se fait sous la forme du fichier .travis.yml . Pour plus de commodité, je vous conseille d'isoler toutes les commandes liées à PVS-Studio dans un script bash séparé avec des fonctions qui seront appelées à partir du fichier .travis.yml ( bash script_name.sh function_name ).

En développant le script, vous obtiendrez plus de fonctionnalités. Dans la section d' installation , écrivez ce qui suit:

 install: - bash .travis.sh travis_install 

Si vous aviez des instructions, vous pouvez les déplacer dans le script, après avoir supprimé les tirets.

Ouvrez le fichier .travis.sh et ajoutez l'installation de l'analyseur dans la fonction 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 } 

Ajoutons maintenant l'analyse exécutée dans la section script :

 script: - bash .travis.sh travis_script 

Et dans le script bash:

 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 } 

Vous devez exécuter ce code après la construction du projet, par exemple, si vous aviez une build sur CMake:

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

Vous obtiendrez les éléments suivants:

 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 } 

Vous avez probablement déjà remarqué les variables d'environnement $ TRAVIS_PULL_REQUEST et $ TRAVIS_BRANCH . Travis CI les déclare lui-même:

  • $ TRAVIS_PULL_REQUEST stocke le numéro de demande d'extraction ou false s'il s'agit d'une branche régulière;
  • $ TRAVIS_REPO_SLUG stocke le nom du référentiel de projet.

Voici l'algorithme opérationnel de cette fonction:

Image 13

Travis CI répond aux codes de retour, donc la présence d'avertissements signalera le service pour marquer la validation comme contenant des erreurs.

Examinons maintenant de plus près cette ligne de code:
 git diff --name-only origin/HEAD > .pvs-pr.list 

Le fait est que Travis CI fusionne automatiquement les branches lors de l'analyse d'une demande de pull:

Image 8

C'est pourquoi nous analysons A4 , pas B3-> A3 . En raison de cette particularité, nous devons évaluer la différence avec A3 , qui est le chef de la branche d' origine .

Un détail important demeure - la mise en cache des dépendances des fichiers d'en-tête des unités de traduction compilées (* .c, * .cc, * .cpp et autres). L'analyseur évalue ces dépendances lors de la première exécution en mode de vérification de la liste des fichiers puis les stocke dans le répertoire .PVS-Studio. Travis CI permet la mise en cache des référentiels, nous allons donc enregistrer les données dans le répertoire .PVS-Studio / :

 cache: directories: - .PVS-Studio/ 

Ce code doit être ajouté dans le fichier .travis.yml : ce répertoire stocke diverses données, collectées après l'analyse. Ces données accélèrent considérablement les exécutions suivantes de l'analyse de la liste des fichiers ou de l'analyse incrémentielle. Si vous ne le faites pas, l'analyseur analysera tous les fichiers à chaque fois.

Copain


Comme Travis CI, Buddy vous permet de créer et de tester automatiquement des projets à partir de GitHub. Contrairement à Travis CI, il est configuré dans l'interface Web (le support bash est disponible), il n'est donc pas nécessaire de stocker les fichiers de configuration dans le projet.

Tout d'abord, nous devons ajouter une nouvelle étape au pipeline:

Image 1

Précisons le compilateur utilisé pour construire le projet. Faites attention au conteneur docker, installé lors de cette étape. Par exemple, il existe un conteneur spécial pour GCC:

Image 6

Maintenant, installons PVS-Studio et les utilitaires nécessaires:

Image 2

Ajoutez les lignes suivantes à l'éditeur:

 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 

Passons à l'onglet Exécuter (première icône) et ajoutons le code suivant au champ de l'éditeur approprié:
 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 

Si vous lisez la section sur Travs-CI, ce code vous est familier. Mais ici, il y a une nouvelle étape:

Image 14

Le fait est que maintenant nous analysons non pas le résultat de la fusion, mais le HEAD de la branche avec la demande d'extraction vérifiée:

Image 10

Nous sommes donc dans un commit B3 et nous devons faire la différence avec 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 

Pour définir A3 , utilisons l'API GitHub:

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

Nous avons utilisé les variables suivantes, que Buddy nous fournit:

  • $ BUDDY_EXECUTION_PULL_REQEUST_NO - numéro d'une demande d'extraction;
  • $ BUDDY_REPO_SLUG - combinaison d'un nom d'utilisateur et d'un référentiel (par exemple, max / test).

Maintenant, enregistrons les modifications, en utilisant le bouton ci-dessous et activons l'analyse des demandes d'extraction:

Image 3

Contrairement à Travis CI, nous n'avons pas besoin de spécifier .pvs-studio pour la mise en cache, car Buddy met automatiquement en cache tous les fichiers pour les exécutions suivantes. Il ne reste donc plus qu'à enregistrer le login et le mot de passe de PVS-Studio dans Buddy. Après avoir enregistré les modifications, nous reviendrons dans le Pipeline. Nous devons passer à la configuration des variables et insérer le login et la clé pour PVS-Studio:

Image 4

Après cela, une vérification commencera à chaque nouvelle demande d'extraction ou validation. Si un commit contient des erreurs, Buddy le signalera sur la page de demande de pull.

Appveyor


Le paramètre AppVeyor est Buddy similaire, car tout se passe dans l'interface Web et il n'est pas nécessaire d'ajouter le fichier * .yml dans le référentiel du projet.

Passons à l'onglet Paramètres dans la revue de projet:

Image 12

Faites défiler cette page vers le bas et activez l'enregistrement du cache pour la génération de demande de tirage:

Image 18


Passons maintenant à l'onglet Environnement, où nous allons spécifier l'image pour la construction et les variables d'environnement nécessaires:

Image 19

Si vous avez lu les sections précédentes, vous connaissez déjà ces deux variables - PVS_KEY et PVS_USERNAME . Sinon, permettez-moi de vous rappeler qu'ils sont nécessaires pour vérifier la licence de l'analyseur PVS-Studio. À l'avenir, nous les retrouverons dans des scripts Bash.

Sur la même page en bas, spécifions le dossier cache:

Image 15

Si nous ne le faisons pas, nous analyserons l'ensemble du projet au lieu de quelques fichiers, mais nous recevrons la sortie pour les fichiers spécifiés. Il est donc important de saisir le nom correct du référentiel.

Le moment est venu pour le script de vérification. Ouvrez l'onglet Tests et choisissez Script:

Image 20

Le code suivant doit être inséré dans ce formulaire:

 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 

Prenons attention à la partie suivante du 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 

C'est une affectation assez spécifique de la valeur de sortie de la commande pwd à la variable, qui doit stocker cette valeur par défaut. Au début, cela semble étrange, mais permettez-moi de tout expliquer.

Lors de la configuration de l'analyseur dans AppVeyor, je suis tombé sur un comportement d'analyseur très étrange. D'une part, tout fonctionnait correctement, mais l'analyse n'a pas commencé. Il a fallu beaucoup de temps pour remarquer que nous étions dans le répertoire / home / appveyor / projects / testcalc /, alors que l'analyseur était sûr que nous étions dans / opt / appveyor / build-agent /. A ce moment, j'ai réalisé que la variable $ PWD est trompeuse. Pour cette raison, j'ai renouvelé manuellement sa valeur avant d'exécuter l'analyse.

L'ordre des actions était le même que précédemment:

Image 16

Jetez maintenant un œil à ce 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"` 

Dans ce document, nous obtenons la différence entre les branches, liée à la demande d'extraction vérifiée. Pour ce faire, nous avons besoin des variables d'environnement suivantes:

  • $ APPVEYOR_PULL_REQUEST_NUMBER - numéro de demande d'extraction;
  • $ APPVEYOR_REPO_NAME - nom d'utilisateur et référentiel de projet.

Conclusion


Eh bien, nous n'avons pas envisagé tous les services d'intégration continue possibles, mais ils ont tous des caractéristiques opérationnelles similaires. Mais quant à la mise en cache, chaque service réinvente sa propre roue, donc c'est toujours différent.

Dans certains cas (comme dans Travis-CI), cela prend quelques lignes de code - et la mise en cache fonctionne parfaitement. Dans d'autres cas (comme dans AppVeyor), il vous suffit de spécifier le répertoire dans les paramètres. Mais il existe certains services, où vous devez créer des clés spéciales et essayer de convaincre le système de vous donner la possibilité de réécrire un fragment mis en cache. Par conséquent, si vous souhaitez configurer l'analyse des demandes d'extraction sur un service d'intégration continue, ce qui n'a pas été considéré ci-dessus, assurez-vous d'abord que vous n'aurez pas de problèmes de mise en cache.

Merci de votre attention. Si quelque chose ne fonctionne pas, vous pouvez écrire en toute sécurité à notre support . Nous vous donnerons un indice et de l'aide.

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


All Articles