Analyse des demandes de fusion dans GitLab à l'aide de PVS-Studio pour C #

image1.png


Vous aimez GitLab et n'aimez pas les bugs? Vous souhaitez améliorer la qualité de votre code source? Alors vous êtes au bon endroit. Aujourd'hui, nous vous expliquerons comment configurer l'analyseur PVS-Studio C # pour vérifier les demandes de fusion. Toute humeur de licorne et lecture agréable.



PVS-Studio est un outil de détection des erreurs et des vulnérabilités potentielles dans le code source des programmes écrits en C, C ++, C # et Java. Fonctionne dans les systèmes 64 bits sous Windows, Linux et macOS. Peut analyser le code pour les plates-formes ARM 32 bits, 64 bits et intégrées.



En passant, nous avons publié PVS-Studio 7.08, dans lequel nous avons fait beaucoup de choses intéressantes . Par exemple:



  • Analyseur C # pour Linux et macOS;
  • plugin pour Rider;
  • nouveau mode de vérification de la liste des fichiers.


Mode de vérification de la liste de fichiers



Auparavant, pour vérifier certains fichiers, il était nécessaire de passer un .xml avec une liste de fichiers à l'analyseur. Mais comme ce n'est pas très pratique, nous avons ajouté la possibilité de transférer des .txt, ce qui rend la vie très facile.



Afin de vérifier des fichiers spécifiques, vous devez spécifier l' indicateur --sourceFiles ( -f ) et transmettre .txt avec une liste de fichiers. Cela ressemble à ceci:



pvs-studio-dotnet -t path/to/solution.sln -f fileList.txt -o project.json


Si vous souhaitez configurer la vérification des validations ou des pull requests, vous pouvez également le faire en utilisant ce mode. La différence sera d'obtenir une liste de fichiers à analyser et dépendra des systèmes que vous utilisez.



Principe de vérification des demandes de fusion



Le point principal du contrôle est de s'assurer que les problèmes détectés par l'analyseur ne se retrouvent pas dans la branche maître lors de la fusion . De plus, nous ne voulons pas analyser l'ensemble du projet à chaque fois. De plus, lors de la fusion de branches, nous avons une liste des fichiers modifiés. Par conséquent, je suggère d'ajouter un chèque pour la demande de fusion.



Voici à quoi ressemble une demande de fusion avant d'implémenter un analyseur statique:



image2.png


Autrement dit, toutes les erreurs qui se trouvaient dans la branche des modifications iront à la branche principale. Comme nous n'aimerions pas cela, nous ajoutons une analyse, et maintenant le diagramme ressemble à ceci:



image3.png


Nous analysons les modifications2 et, s'il n'y a pas d'erreur, nous acceptons la demande de fusion, sinon nous la rejetons.



En passant, si vous souhaitez analyser les commits et les pull requests pour C / C ++, vous pouvez en savoir plus ici .



Gitlab



GitLab est un outil de cycle de vie DevOps basé sur le Web open source qui fournit un système de gestion de référentiel de code pour Git avec son propre wiki, son outil de suivi des bogues, son pipeline CI / CD, etc.



Avant de commencer à implémenter l'analyse des demandes de fusion, vous devez vous inscrire et télécharger votre projet. Si vous ne savez pas comment faire cela, je vous suggère un article de mon collègue.



Remarque... La méthode de configuration de l'environnement décrite ci-dessous est l'une des méthodes possibles. L'objectif est de montrer les étapes de configuration de l'environnement requis pour l'analyse et l'exécution de l'analyseur. Peut-être, dans votre cas, serait-il plus optimal de séparer les étapes de préparation de l'environnement (ajout de référentiels, installation de l'analyseur) et d'analyse: par exemple, préparer les images Docker avec l'environnement nécessaire et les utiliser, ou une autre méthode.



Pour mieux comprendre ce qui va se passer maintenant, je suggère de jeter un œil au diagramme suivant:



image4.png


L'analyseur nécessite .NET Core SDK 3 pour fonctionner, donc avant d'installer l'analyseur, vous devez ajouter les référentiels Microsoft, à partir desquels les dépendances nécessaires à l'analyseur seront installées. L'ajout de référentiels Microsoft pour diverses distributions Linux est décrit dans le document correspondant .



Pour installer PVS-Studio via le gestionnaire de packages, vous devrez également ajouter des référentiels PVS-Studio. L'ajout de référentiels pour différentes distributions est décrit plus en détail dans la section correspondante de la documentation .



L'analyseur nécessite une clé de licence pour fonctionner. Vous pouvez obtenir une licence d'essai sur la page de téléchargement de l'analyseur .



Remarque... Veuillez noter que le mode de fonctionnement décrit (analyse des demandes de fusion) nécessite une licence Entreprise. Par conséquent, si vous souhaitez essayer ce mode de fonctionnement, n'oubliez pas d'indiquer dans le champ "Message" que vous avez besoin de la licence Enterprise.



Si une demande de fusion se produit, il suffit d'analyser la liste des fichiers modifiés, sinon nous analysons tous les fichiers. Après l'analyse, nous devons convertir les journaux dans le format dont nous avons besoin.



Maintenant, ayant sous les yeux l'algorithme de travail, vous pouvez procéder à l'écriture d'un script. Pour ce faire, vous devez modifier le fichier .gitlab-ci.yml ou, sinon, le créer. Pour le créer, vous devez cliquer sur le nom de votre projet -> Configurer CI / CD .



image5.png


Nous sommes maintenant prêts à écrire le script. Commençons par écrire le code qui installera l'analyseur et entrez la licence:



before_script:
  - apt-get update && apt-get -y install wget gnupg 

  - apt-get -y install git
  - wget https://packages.microsoft.com/config/debian/10/
packages-microsoft-prod.deb -O packages-microsoft-prod.deb
  - dpkg -i packages-microsoft-prod.deb
  - apt-get update
  - apt-get install apt-transport-https
  - apt-get update
  
  - 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-dotnet

  - pvs-studio-analyzer credentials $PVS_NAME $PVS_KEY
  - dotnet restore "$CI_PROJECT_DIR"/Test/Test.sln


Puisque l'installation et l'activation doivent avoir lieu avant tous les autres scripts, nous utilisons une balise before_script spéciale . Je vais expliquer un peu ce fragment.



Préparation de l'installation de l'analyseur:



  - wget https://packages.microsoft.com/config/debian/10/
packages-microsoft-prod.deb -O packages-microsoft-prod.deb
  - dpkg -i packages-microsoft-prod.deb
  - apt-get update
  - apt-get install apt-transport-https
  - apt-get update


Ajout de référentiels et d'analyseur PVS-Studio:



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


Activation de la licence:



  - pvs-studio-analyzer credentials $PVS_NAME $PVS_KEY


$ PVS_NAME - nom d'utilisateur.



$ PVS_KEY - clé de produit.



Restauration des dépendances du projet, où $ CI_PROJECT_DIR est le chemin complet vers le répertoire du projet:



  - dotnet restore "$CI_PROJECT_DIR"/Path/To/Solution.sln


Pour une analyse correcte, le projet doit être généré avec succès et ses dépendances doivent être restaurées (par exemple, les packages NuGet nécessaires doivent être chargés).



Vous pouvez définir des variables d'environnement contenant des informations de licence en cliquant sur Paramètres , puis sur CI / CD .



image6.png


Dans la fenêtre qui s'ouvre, nous trouvons l'élément Variables , à droite, cliquez sur le bouton Développer et ajoutez des variables. Le résultat devrait ressembler à ceci:



image7.png


Vous pouvez maintenant procéder à l'analyse. Tout d'abord, ajoutons un script pour une analyse complète. Le drapeau -t transfère le chemin vers la solution, un drapeau -o emplacement d'écriture du fichier dans lequel sont enregistrés les résultats de l'analyse. Nous sommes également intéressés par le code retour. Dans ce cas, nous nous intéressons à l'opération terminée lorsque le code retour contient des informations indiquant que des avertissements ont été émis lors de l'analyse. Voici à quoi ressemble cet extrait:



job:
  script:
  - exit_code=0
  - pvs-studio-dotnet -t "$CI_PROJECT_DIR"/Test/Test.sln -o 
PVS-Studio.json || exit_code=$?
  - exit_code=$((($exit_code & 8)/8))
  - if [[ $exit_code == 1 ]]; then exit 1; else exit 0; fi


Les codes de retour fonctionnent comme un masque de bits. Par exemple, si des avertissements ont été émis à la suite de l'analyse, le code de retour sera 8. Si la licence expire dans un mois, le code de retour sera 4. Si des erreurs ont été trouvées pendant l'analyse et que la licence expire dans un mois, dans le code return, les deux valeurs seront écrites: additionnez les nombres ensemble et obtenez le code de retour final - 8 + 4 = 12. Ainsi, en vérifiant les bits correspondants, il est possible d'obtenir des informations sur différents états lors de l'analyse. Les codes de retour sont décrits plus en détail dans la section «Codes de retour pvs-studio-dotnet (Linux / macOS)» du document « Vérification des projets Visual Studio / MSBuild / .NET Core à partir de la ligne de commande à l'aide de PVS-Studio ».



Dans ce cas, nous nous intéressons à tous les codes retour,où 8 apparaît.



  - exit_code=$((($exit_code & 8)/8))


Nous obtiendrons 1 lorsque le code de retour contient le bit du nombre qui nous intéresse, sinon nous obtiendrons 0.



Il est temps d'ajouter l'analyse de la demande de fusion. Avant de faire cela, préparons une place pour le script. Nous en avons seulement besoin pour s'exécuter lorsqu'une demande de fusion se produit. Cela ressemble à ceci:



merge:
  script:
  only:
  - merge_requests


Passons au script lui-même. Je suis tombé sur le fait que la machine virtuelle ne sait rien de l' origine / maître . Par conséquent, nous l'aidons un peu:



  - git fetch origin


Voyons maintenant la différence entre les branches et enregistrons le résultat dans un fichier txt :



  - git diff --name-only origin/master $CI_COMMIT_SHA > pvs-fl.txt


$ CI_COMMIT_SHA est le hachage du dernier commit.



Ensuite, nous exécutons l'analyse de la liste de fichiers à l'aide de l' option -f . Nous y transférons le fichier .txt reçu précédemment. Eh bien, par analogie avec l'analyse complète, nous examinons les codes de retour:



  - exit_code=0
  - pvs-studio-dotnet -t "$CI_PROJECT_DIR"/Test/Test.sln -f 
pvs-fl.txt -o PVS-Studio.json || exit_code=$?
  - exit_code=$((($exit_code & 8)/8))
  - if [[ $exit_code == 1 ]]; then exit 1; else exit 0; fi


Le script complet pour vérifier la demande de fusion ressemblera à ceci:



merge:
  script:
  - git fetch origin
  - git diff --name-only origin/master $CI_COMMIT_SHA > pvs-fl.txt
  - exit_code=0
  - pvs-studio-dotnet -t "$CI_PROJECT_DIR"/Test/Test.sln -f 
pvs-fl.txt -o PVS-Studio.json || exit_code=$?
  - exit_code=$((($exit_code & 8)/8))
  - if [[ $exit_code == 1 ]]; then exit 1; else exit 0; fi
  only:
  - merge_requests


Il ne reste plus qu'à ajouter la conversion du journal une fois tous les scripts exécutés. Nous utilisons l'étiquette after_script et l' utilitaire plog-converter :



after_script:
  - plog-converter -t html -o eLog ./PVS-Studio.json


L' utilitaire plog-converter est un projet open source utilisé pour convertir le rapport d'erreur de l'analyseur sous diverses formes, telles que HTML. Une description plus détaillée de l'utilitaire est donnée dans la sous-section «Utilitaire Plog Converter» de la section correspondante de la documentation .



Au fait, si vous souhaitez travailler facilement avec le rapport .json localement à partir de l'EDI, je vous suggère notre plugin pour l'IDE Rider. Son utilisation est décrite plus en détail dans le document correspondant .



Pour plus de commodité, voici l' intégralité du fichier .gitlab-ci.yml :



image: debian

before_script:
  - apt-get update && apt-get -y install wget gnupg 

  - apt-get -y install git
  - wget https://packages.microsoft.com/config/debian/10/
packages-microsoft-prod.deb -O packages-microsoft-prod.deb
  - dpkg -i packages-microsoft-prod.deb
  - apt-get update
  - apt-get install apt-transport-https
  - apt-get update
  
  - 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-dotnet

  - pvs-studio-analyzer credentials $PVS_NAME $PVS_KEY
  - dotnet restore "$CI_PROJECT_DIR"/Test/Test.sln

merge:
  script:
  - git fetch origin
  - git diff --name-only origin/master $CI_COMMIT_SHA > pvs-fl.txt
  - exit_code=0
  - pvs-studio-dotnet -t "$CI_PROJECT_DIR"/Test/Test.sln -f 
pvs-fl.txt -o PVS-Studio.json || exit_code=$?
  - exit_code=$((($exit_code & 8)/8))
  - if [[ $exit_code == 1 ]]; then exit 1; else exit 0; fi
  only:
  - merge_requests

job:
  script:
  - exit_code=0
  - pvs-studio-dotnet -t "$CI_PROJECT_DIR"/Test/Test.sln -o 
PVS-Studio.json || exit_code=$?
  - exit_code=$((($exit_code & 8)/8))
  - if [[ $exit_code == 1 ]]; then exit 1; else exit 0; fi
  
after_script:
  - plog-converter -t html -o eLog ./PVS-Studio.json


Une fois que tout a été ajouté au fichier, cliquez sur Valider les modifications . Pour voir que tout est correct, allez dans CI / CD -> Pipelines -> Running . Une fenêtre de machine virtuelle s'ouvrira, à la fin de laquelle devrait être la suivante:



image8.png


Nous avons vu Job réussir - le succès, tout va bien. Vous pouvez maintenant tester ce que vous avez fait.



Exemples de travaux



Pour un exemple de travail, créons un projet simple (en master ) dans lequel il y aura plusieurs fichiers. Après cela, dans une autre branche, nous ne modifierons qu'un seul fichier et essayerons de faire une demande de fusion.



Considérez deux cas: lorsque le fichier modifié contient une erreur et dans le cas contraire. Tout d'abord, un exemple avec une erreur.



Disons qu'il y a un fichier Program.cs dans la branche master , qui ne contient pas d'erreurs, et dans une autre branche, le développeur a ajouté un code erroné et souhaite faire une demande de fusion. Le genre d'erreur qu'il a commis n'est pas si important, l'essentiel est que cela existe. Par exemple, j'ai oublié l'opérateur throw (oui, ils sont si faux ):



void MyAwesomeMethod(String name)
{
  if (name == null)
    new ArgumentNullException(....);
  // do something
  ....
}


Regardons le résultat de l'analyse d'un exemple avec une erreur. De plus, pour m'assurer qu'un seul fichier a été analysé, j'ai ajouté l'indicateur -r à la ligne de démarrage pvs-studio-dotnet:



image9.png


On voit que l'analyseur a trouvé une erreur et n'a pas permis la fusion des branches.



Vérification de l'exemple sans erreur. Correction du code:



void MyAwesomeMethod(String name)
{
  if (name == null)
    throw new ArgumentNullException(....);
  // do something
  ....
}


Résultats de l'analyse des demandes de fusion:



image10.png


Comme nous pouvons le voir, aucune erreur n'a été trouvée et l'exécution de la tâche a réussi, ce que nous voulions vérifier.



Conclusion



Filtrer le mauvais code avant de fusionner des branches est très pratique et agréable. Par conséquent, si vous utilisez CI / CD, essayez de créer un analyseur statique pour les tests. De plus, cela se fait tout simplement.



Merci de votre attention.





Si vous souhaitez partager cet article avec un public anglophone, veuillez utiliser le lien de traduction: Nikolay Mironov. Analyse des demandes de fusion dans GitLab à l'aide de PVS-Studio pour C # .



All Articles