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 ++ sur Linux et macOS a une capacité de test pour vérifier 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 vous montrera comment configurer la vérification de la liste des fichiers de projet GitHub modifiés 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 pour détecter les erreurs et les vulnérabilités potentielles dans le code source des programmes écrits en C, C ++, C # et Java. Il fonctionne sur les systèmes 64 bits sous Windows, Linux et macOS.

Dans PVS-Studio version 7.04 pour Linux et macOS, le mode de vérification de la liste des fichiers source est apparu. Cela 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 puisse extraire des informations sur la compilation des fichiers spécifiés. 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 un tel fichier à l'aide de l'utilitaire Bear .

En outre, le mode de vérification de la liste des fichiers peut être utilisé avec le journal de suivi de strace des démarrages du compilateur (trace pvs-studio-analyzer). Pour ce faire, vous devez d'abord effectuer un assemblage complet du projet et le suivre afin que l'analyseur collecte des informations complètes sur les paramètres de compilation de tous les fichiers testés.

Cependant, cette option présente un inconvénient important - vous devrez soit faire une trace complète de l'ensemble du projet à chaque démarrage, ce qui en soi contredit l'idée d'une vérification rapide de la validation. Ou, si le résultat de la trace lui-même est mis en cache, les démarrages d'analyseurs suivants peuvent ne pas être terminés si la structure de dépendance des fichiers source change après la trace (par exemple, un nouveau #include est ajouté à 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 le journal de suivi pour vérifier les validations ou les demandes d'extraction. Si vous pouvez effectuer un assemblage incrémentiel 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 un fichier texte et transférée à l'analyseur à l'aide du paramètre -S :

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

Dans ce fichier, les chemins d'accès relatifs ou absolus aux fichiers sont indiqués, et chaque nouveau fichier doit être sur une nouvelle ligne. Il est permis de spécifier non seulement les noms des fichiers à analyser, mais aussi divers textes. L'analyseur verra qu'il ne s'agit pas d'un fichier et ignorera la ligne. Cela peut être utile pour commenter si les fichiers sont spécifiés manuellement. Cependant, une liste de fichiers est souvent générée lors de l'analyse dans CI, par exemple, il peut s'agir de fichiers provenant d'une demande de validation ou 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. Pour que le système de vérification réponde aux avertissements de l'analyseur, l' indicateur --indicate-warnings a été ajouté à l' utilitaire de conversion de plog :

 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. En utilisant le code de retour, vous pouvez bloquer le crochet de pré-validation, la demande de validation ou d'extraction et afficher le rapport d'analyseur généré à l'écran, le partager ou l'envoyer par courrier.

Remarque La première fois que vous exécutez l'analyse de la liste des fichiers, l'ensemble du projet sera analysé, car l'analyseur doit générer un fichier de dépendances des fichiers source du projet à partir des fichiers d'en-tête. Il s'agit d'une caractéristique de l'analyse des fichiers C et C ++. À l'avenir, le fichier de dépendance peut être mis en cache et il sera mis à jour automatiquement par l'analyseur. L'avantage de la vérification des validations lors de l'utilisation du mode de vérification de la liste des fichiers par rapport au mode d'analyse incrémentielle est que vous n'avez besoin que de mettre en cache ce fichier, pas les fichiers objets.

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


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

Prenons un exemple d'arbre de validation avec deux branches:

Image 5


Imaginons que la validation A1 contienne une quantité assez importante de code qui a déjà été testée. Un peu plus tôt, nous avons créé une branche à partir de la validation A1 et modifié certains fichiers.

Bien sûr, vous avez remarqué qu'après A1, il y avait deux autres validations, mais il s'agissait également de fusions d'autres branches, car nous ne nous engageons pas en master . Et maintenant, le moment est venu où le correctif est prêt. Par conséquent, une demande de retrait pour la fusion de B3 et A3 est apparue .

Bien sûr, on pourrait vérifier l'ensemble du résultat de leur fusion, mais cela serait trop long et injustifié, car seuls quelques fichiers ont été modifiés. Par conséquent, il est plus efficace d'analyser uniquement les modifications.

Pour ce faire, nous obtenons la différence entre les branches, étant dans la branche HEAD, à partir de laquelle nous voulons fusionner en maître:

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

$ MERGE_BASE, nous examinerons plus en détail plus tard. Le fait est que tous les services CI ne fournissent pas les informations nécessaires sur la base de la fusion, donc chaque fois que vous devez trouver de nouvelles façons d'obtenir ces données. Ceci sera détaillé ci-dessous dans chacun des services Web décrits.

Ainsi, nous avons obtenu la différence entre les branches, ou plutôt, une liste de noms de fichiers qui ont été modifiés. Maintenant, nous devons donner le fichier .pvs-pr.list (nous y avons redirigé la sortie ci-dessus) à l'analyseur:

 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 facile à lire:

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

Cette commande répertorie les erreurs dans stderr (flux de sortie de message d'erreur standard).

Ce n'est que maintenant que nous devons non seulement afficher les erreurs, mais également informer notre service pour l'assemblage et le test des problèmes. Pour ce faire, l'indicateur -W ( --indicate-warnings ) a été ajouté au convertisseur. S'il y a au moins un avertissement d'analyseur, le code de retour de l'utilitaire de conversion de plog passera à 2, ce qui informera le service CI de la présence d'erreurs potentielles dans les fichiers de demande d'extraction.

Travis ci


La configuration est effectuée sous la forme d'un fichier .travis.yml . Pour plus de commodité, je vous conseille de tout mettre dans un script bash séparé avec des fonctions qui seront appelées depuis le fichier .travis.yml ( bash script_name.sh function_name ).

Nous ajouterons le code nécessaire au script bash , afin d'obtenir 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 transférer dans le script en supprimant les tirets.

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

Ajoutez maintenant l'analyse à 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 } 

Ce code doit être exécuté 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 } 

Cela se passera comme ceci:

 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 spécifiées $ TRAVIS_PULL_REQUEST et $ TRAVIS_BRANCH . Travis CI les annonce de son propre chef:

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

L'algorithme de cette fonction:

Image 7

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

Maintenant, regardons 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 des demandes de pull:

Image 8

Par conséquent, nous analysons A4 , pas B3-> A3 . En raison de cette fonctionnalité, nous devons calculer la différence avec A3 , qui est précisément le sommet de la branche d' origine .

Un détail important restait - la mise en cache des dépendances des fichiers d'en-tête sur les unités de traduction compilées (* .c, * .cc, * .cpp, etc.). L'analyseur calcule ces dépendances au premier démarrage dans le mode de vérification de la liste de fichiers, puis l'enregistre dans le répertoire .PVS-Studio. Travis CI vous permet de mettre en cache des dossiers, nous allons donc enregistrer les données du répertoire .PVS-Studio / :

 cache: directories: - .PVS-Studio/ 

Ce code doit être ajouté au fichier .travis.yml . Ce répertoire stocke diverses données collectées après l'analyse, ce qui accélérera considérablement les lancements ultérieurs de l'analyse de la liste des fichiers ou de l'analyse incrémentielle. Si cela n'est pas fait, l'analyseur analysera en fait tous les fichiers à chaque fois.

Copain


Comme Travis CI, Buddy offre la possibilité de créer et de tester automatiquement des projets stockés sur 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 action à la chaîne de montage:

Image 1

Nous indiquons le compilateur qui a été utilisé pour construire le projet. Faites attention au conteneur Docker installé dans cette action. Par exemple, il existe un conteneur spécial pour GCC:

Image 6

Installez maintenant 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 

Accédez maintenant à l'onglet Exécuter (première icône) et ajoutez le code suivant au champ approprié de l'éditeur:

 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, alors ce code vous est déjà familier, cependant, maintenant une nouvelle étape est apparue:

Image 9

Le fait est que nous analysons maintenant non pas le résultat de la fusion, mais la branche HEAD à partir de laquelle la demande d'extraction est effectuée:

Image 10

Par conséquent, nous sommes dans le commit conditionnel 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éterminer A3, utilisez l'API GitHub:

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

Nous avons utilisé les variables suivantes fournies par Buddy:

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

Maintenant, enregistrez les modifications à l'aide du bouton ci-dessous et activez 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 lancements ultérieurs. Par conséquent, la dernière chose qui reste est d'enregistrer le login et le mot de passe pour PVS-Studio dans Buddy. Après avoir enregistré les modifications, nous reviendrons sur Pipeline. Nous devons passer à la configuration des variables et ajouter le login et la clé pour PVS-Studio:

Image 4

Après cela, l'apparition d'une nouvelle demande de pull ou commit déclenchera une vérification. Si le commit contient des erreurs, Buddy l'indiquera sur la page de demande de pull.

Appveyor


La configuration d'AppVeyor est similaire à Buddy, car tout se passe dans l'interface Web et il n'est pas nécessaire d'ajouter un fichier * .yml au référentiel du projet.

Accédez à l'onglet Paramètres dans l'aperçu du projet:

Image 12

Faites défiler cette page vers le bas et activez l'enregistrement du cache pour créer des demandes d'extraction:

Image 18

Maintenant, allez dans l'onglet Environnement, où nous spécifions l'image pour l'assemblage et les variables d'environnement nécessaires:

Image 19

Si vous lisez les sections précédentes, vous connaissez bien ces deux variables - PVS_KEY et PVS_USERNAME . Sinon, je vous rappelle 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 ci-dessous, nous indiquons le dossier pour la mise en cache:

Image 15

Si nous ne le faisons pas, nous analyserons l'ensemble du projet au lieu d'une paire de fichiers, mais nous obtiendrons la sortie des fichiers spécifiés. Par conséquent, il est important de saisir le nom de répertoire correct.

Il est maintenant temps pour le script de vérifier. Ouvrez l'onglet Tests et sélectionnez Script:

Image 20

Insérez le code suivant 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 

Faites 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 

L'affectation plutôt spécifique de la valeur de la commande pwd à la variable qui devrait stocker cette valeur par défaut semble étrange à première vue, cependant, je vais tout expliquer maintenant.

Lors de la configuration de l'analyseur dans AppVeyor, j'ai rencontré un comportement d'analyseur extrêmement étrange. D'une part, tout fonctionnait correctement, mais l'analyse n'a pas commencé. J'ai passé beaucoup de temps à remarquer que nous sommes dans le répertoire / home / appveyor / projects / testcalc /, et l'analyseur est sûr que nous sommes dans / opt / appveyor / build-agent /. Ensuite, j'ai réalisé que la variable $ PWD ment un peu. Pour cette raison, j'ai mis à jour manuellement sa valeur avant de démarrer l'analyse.

Et puis tout, comme avant:

Image 17

Considérez maintenant l'extrait de code suivant:

 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 sur lesquelles la demande de tirage est déclarée. Pour ce faire, nous avons besoin des variables d'environnement suivantes:

  • $ APPVEYOR_PULL_REQUEST_NUMBER - nombre de demandes de tirage;
  • $ APPVEYOR_REPO_NAME - nom d'utilisateur et référentiel du projet.

Conclusion


Bien sûr, nous n'avons pas considéré tous les services possibles d'intégration continue, cependant, ils ont tous des caractéristiques de travail très similaires. À l'exception de la mise en cache, chaque service crée son propre «vélo», donc tout est toujours différent.

Quelque part, comme dans Travis-CI, quelques lignes de code et la mise en cache fonctionnent parfaitement; quelque part, comme dans AppVeyor, il vous suffit de spécifier le dossier dans les paramètres; mais quelque part, vous devez créer des clés uniques et essayer de convaincre le système de vous donner la possibilité d'écraser le fragment mis en cache. Par conséquent, si vous souhaitez configurer l'analyse des demandes d'extraction sur le service d'intégration continue, qui n'a pas été abordée 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, n'hésitez pas à nous écrire pour vous aider . Nous vous inviterons et vous aiderons.



Si vous souhaitez partager cet article avec un public anglophone, veuillez utiliser le lien vers la traduction: Maxim Zvyagintsev. Analyse des validations et des demandes d'extraction dans Travis CI, Buddy et AppVeyor à l'aide de PVS-Studio .

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


All Articles