Аналіз merge request'ів у GitLab за допомогою PVS-Studio для C#

Аналіз merge request'ів у GitLab за допомогою PVS-Studio для C#
Чи любите GitLab і не любите помилки? Бажаєте підвищити якість вихідного коду? Тоді ви потрапили на адресу. Сьогодні ми розповімо, як налаштувати C# аналізатор PVS-Studio для перевірки merge request'ів. Усім єдинорідного настрою та приємного читання.

ПВС-Студія — це інструмент виявлення помилок і потенційних уразливостей у вихідному коді програм, написаних мовами C, C++, C# і Java. Працює у 64-бітових системах на Windows, Linux та macOS. Може аналізувати код, призначений для 32-бітових, 64-бітових та вбудованих ARM платформ.

До речі, у нас відбувся реліз PVS-Studio 7.08, у якому ми зробили багато всього цікавенького. наприклад:

  • аналізатор C# під Linux та macOS;
  • плагін для Rider;
  • новий режим перевірки списку файлів.

Режим перевірки списку файлів

Раніше для того, щоб перевірити певні файли, необхідно було передати аналізатору .xml зі списком файлів. Але, оскільки це не дуже зручно, ми додали можливість передачі .txt, що дуже спрощує життя.

Щоб перевірити певні файли, необхідно вказати прапор -sourceFiles (-f) і передати .txt зі списком файлів. Виглядає це так:

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

Якщо вам цікаво налаштувати перевірку коммітів або pull requests, ви також можете це зробити, використовуючи даний режим. Відмінність полягатиме в отриманні списку файлів для аналізу та залежатиме від того, які системи ви використовуєте.

Принцип перевірки merge request

Основна суть перевірки полягає в тому, щоб проблеми, виявлені аналізатором, при злитті не потрапляли в майстер гілку. Також ми не хочемо щоразу аналізувати проект цілком. Тим більше, що при злитті гілок у нас є список змінених файлів. Тому пропоную додати перевірку merge request.

Ось так виглядає merge request до впровадження статичного аналізатора:

Аналіз merge request'ів у GitLab за допомогою PVS-Studio для C#
Тобто всі помилки, які були у гілці зміни, перейдуть у майстер гілку. Так як нам цього не хотілося, додаємо аналіз, і тепер схема виглядає наступним чином:

Аналіз merge request'ів у GitLab за допомогою PVS-Studio для C#
аналізуємо зміни2 і якщо помилок немає, приймаємо merge request, а інакше відхиляємо його.

До речі, якщо вас цікавить аналіз коммітів та pull request'ів для C/C++, то ви можете почитати про це тут.

GitLab

GitLab — веб-інструмент життєвого циклу DevOps з відкритим вихідним кодом, що представляє систему управління репозиторіями коду для Git з власної вікі, системою відстеження помилок, CI/CD пайплайном та іншими функціями.

Перед тим як розпочати реалізацію аналізу merge request'ів необхідно зареєструватися та завантажити свій проект. Якщо ви не знаєте, як це зробити, то пропоную статтю мого колеги.

Примітка. Описуваний спосіб налаштування оточення – один з можливих. Мета – показати кроки налаштування необхідного для аналізу оточення та запуску аналізатора. Можливо, у вашому випадку більш оптимальним буде поділ етапів підготовки оточення (додавання репозиторіїв, встановлення аналізатора) та аналізу: наприклад, підготовка Docker образів з необхідним оточенням та їх використання чи якийсь інший спосіб.

Щоб наочніше зрозуміти, що зараз відбуватиметься, я пропоную поглянути на таку схему:

Аналіз merge request'ів у GitLab за допомогою PVS-Studio для C#
Для роботи аналізатору потрібно. Додавання репозиторіїв Microsoft для різних дистрибутивів Linux описано у відповідному документі.

Для встановлення PVS-Studio через пакетний менеджер також потрібно додати репозиторії PVS-Studio. Додавання репозиторіїв для різних дистрибутивів докладніше описано в відповідному розділі документації.

Для роботи аналізатору потрібний ліцензійний ключ. Отримати пробну ліцензію можна на сторінці завантаження аналізатора.

Примітка. Зверніть увагу, що для режиму роботи (аналіз merge requests) потрібна Enterprise ліцензія. Тому, якщо ви хочете спробувати цей режим роботи, у полі "Повідомлення" не забудьте вказати, що вам потрібна саме ліцензія Enterprise.

Якщо відбувається merge request, то потрібно буде проаналізувати тільки список змінених файлів, а інакше аналізуємо всі файли. Після аналізу потрібно сконвертувати логи в потрібний формат.

Тепер, маючи перед очима алгоритм роботи, можна переходити до написання сценарію. Щоб це зробити, потрібно змінити файл .gitlab-ci.yml або, якщо її немає, створити. Для його створення потрібно натиснути на назву вашого проекту -> Set up CI/CD.

Аналіз merge request'ів у GitLab за допомогою PVS-Studio для C#
Тепер ми готові до написання скрипта. Давайте спочатку напишемо код, який встановить аналізатор та запровадить ліцензію:

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

Так як встановлення та активація має відбуватися перед усіма іншими скриптами, то використовуємо спеціальну мітку before_script. Трохи поясню цей фрагмент.

Підготовка до встановлення аналізатора:

  - 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

Додавання репозиторіїв 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

Активація ліцензії:

  - pvs-studio-analyzer credentials $PVS_NAME $PVS_KEY

$PVS_NAME - Ім'я користувача.

$PVS_KEY - Ключ продукту.

Відновлення залежностей проекту, де $CI_PROJECT_DIR - Повний шлях до директорії проекту:

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

Для коректного аналізу проект має успішно збиратися, а його залежності мають бути відновлені (наприклад, мають бути завантажені необхідні пакети NuGet).

Задати змінні оточення, що містять ліцензійну інформацію, можна, натиснувши на Установка, а потім - на CI/CD.

Аналіз merge request'ів у GitLab за допомогою PVS-Studio для C#
У вікні знаходимо пункт Змінні, праворуч натискаємо на кнопку Розширювати і додаємо змінні. В результаті має вийти таке:

Аналіз merge request'ів у GitLab за допомогою PVS-Studio для C#
Тепер можна переходити до аналізу. Спочатку додамо скрипт для повного аналізу. У прапор -t передаємо шлях до solution, у прапор -o пишемо шлях до файлу, куди будуть записані результати аналізу. Також нас цікавить код повернення. У цьому випадку нам цікаво, щоб робота припинялася, коли код повернення містить інформацію про те, що під час аналізу було видано попередження. Ось як виглядає цей фрагмент:

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

Коди повернення працюють за принципом маски біта. Наприклад, якщо в результаті аналізу були видані попередження, то код повернення дорівнюватиме 8. Якщо ліцензія закінчиться протягом місяця, то код повернення дорівнюватиме 4. Якщо ж в ході аналізу були виявлені помилки, а також ліцензія закінчується протягом місяця, код повернення будуть записані обидва значення: складаємо числа разом і отримуємо підсумковий код повернення - 8 + 4 = 12. Таким чином, перевіряючи відповідні біти, можна отримувати інформацію про різні стани під час аналізу. Докладніше коди повернення описуються у розділі "Коди повернення pvs-studio-dotnet (Linux / macOS)" документа "Перевірка проектів Visual Studio/MSBuild/.NET Core з командного рядка за допомогою PVS-Studio".

У цьому випадку нас цікавлять усі коди повернення, де фігурує 8.

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

Ми отримаємо 1, коли код повернення містить цікавий для нас біт числа, а інакше отримаємо 0.

Настав час додати аналіз merge request. Перед тим, як це зробити, підготуємо місце для скрипту. Нам необхідно, щоб він виконувався лише тоді, коли відбувається merge request. Виглядає це так:

merge:
  script:
  only:
  - merge_requests

Перейдемо до самого скрипту. Я зіткнувся з тим, що віртуальна машина нічого не знає про походження/майстер. Тому допомагаємо їй небагато:

  - git fetch origin

Тепер отримаємо різницю гілок і зберігаємо результат у TXT файл:

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

Де $CI_COMMIT_SHA - Хеш останнього комміту.

Далі запускаємо аналіз списку файлів, використовуючи прапор -f. У нього передаємо отриманий ранній файл .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

Повний скрипт для перевірки merge request виглядатиме ось так:

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

Залишається лише додати конвертацію лога після того, як відпрацювали усі скрипти. Використовуємо мітку after_script та утиліту plog-converter:

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

Утиліта plog-converter — це open source проект, який використовується для перетворення звіту про помилки аналізатора на різні форми, наприклад, HTML. Більш докладний опис утиліти наведено у підрозділі "Утиліта Plog Converter" відповідного розділу документації.

До речі, якщо ви хочете зручно працювати з .json звітом локально з IDE, то пропоную наш плагін для IDE Rider. Докладніше його використання описано в відповідному документі.

Для зручності ось .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

Як тільки додали все до файлу, натискаємо на Прийняти зміни. Для того щоб подивитися, що все правильно, заходимо в CI/CD -> Трубопроводи -> Робота. Відкриється вікно віртуальної машини, наприкінці якої має бути наступне:

Аналіз merge request'ів у GitLab за допомогою PVS-Studio для C#
Побачили Job succeeded - Успіх, все чудово. Тепер можна і протестувати зроблене.

Приклади роботи

Для прикладу роботи створимо простий проект (у майстер) У якому буде кілька файлів. Після цього в іншій гілці змінимо лише один файл і спробуємо зробити merge request.

Розглянемо два випадки: коли змінений файл містить помилку та коли ні. Спочатку приклад із помилкою.

Допустимо, в master гілці є файл Program.cs, Що не містить помилок, а в іншій гілці розробник додав помилковий код і хоче зробити merge request. Якої саме помилки він припустився – не так важливо, головне, що вона є. Наприклад, забув оператор кидати (так, так помиляються):

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

Погляньмо на результат аналізу прикладу з помилкою. Також щоб переконатися, що тільки один файл був проаналізований, я додав прапор -r у рядок запуску pvs-studio-dotnet:

Аналіз merge request'ів у GitLab за допомогою PVS-Studio для C#
Ми, що аналізатор знайшов помилку і дозволив зробити злиття гілок.

Перевіряємо приклад без помилок. Виправляємо код:

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

Результати аналізу merge request:

Аналіз merge request'ів у GitLab за допомогою PVS-Studio для C#
Як бачимо, помилок не знайдено, і виконання завдання пройшло успішно, що ми хотіли перевірити.

Висновок

Відсівати поганий код до злиття гілок це дуже зручно і приємно. Тому, якщо ви використовуєте CI/CD, спробуйте вбудувати статичний аналізатор для перевірки. Тим більше, що робиться це досить просто.

Дякую за увагу.

Аналіз merge request'ів у GitLab за допомогою PVS-Studio для C#
Якщо хочете поділитися цією статтею з англомовною аудиторією, прошу використати посилання на переклад: Nikolay Mironov. Analysis of merge requests in GitLab за допомогою PVS-Studio for C#.

Джерело: habr.com

Додати коментар або відгук