﻿# Как в GitHub смотреть красивые отчеты об ошибках с помощью SARIF

Вы пользуетесь GitHub, пишете код и делаете прочие веселые штуки\. Для повышения качества своей работы и оптимизации своего времени используете статический анализатор\. И вот вам приходит идея \- а почему бы не смотреть на ошибки, которые выдал анализатор, прямо в GitHub? Да и еще, чтобы это красиво выглядело\. Что же делать в этом случае? Ответ очень простой\. Ваш выбор – SARIF\. О том что это такое, как это настроить, и будет рассказано в данной статье\. Приятного чтения\.

![0798_SARIF_ru/image1.png](https://import.viva64.com/docx/blog/0798_SARIF_ru/image1.png)

## Что такое SARIF?

[SARIF](https://docs.oasis-open.org/sarif/sarif/v2.0/sarif-v2.0.html) \(Static Analysis Results Interchange Format\) – это формат обмена результатами статического анализа на основе JSON для вывода инструментов статического анализа\. То есть нам достаточно получить отчет анализатора в этом формате, и далее мы можем его использовать в тех продуктах, которые поддерживают данный формат \- например, на GitHub или в Visual Studio Code\. 

Этот формат появился из\-за того, что в мире инструментов статического анализа каждый создавал свой собственный выходной формат\. Однако, даже если отчёты разных анализаторов представлены в одном и том же формате \(например, JSON\), структура самих отчетов может кардинально отличаться друг от друга\. Поэтому один общий стандарт был лишь вопросом времени\. 

Данный формат \(SARIF\) быстро развивается, и его начинают использовать все чаще и чаще\. Однако на данный момент у него есть небольшой недостаток\. Иногда он меняет свою структуру, и приходится немного корректировать код, чтобы SARIF файл проходил валидацию\. Однако это мелочи по сравнению с тем, какую пользу он несёт\. В теории, в идеальном мире, достаточно получить отчет в этом формате и далее его можно открыть в любой программе\\системе, которая работает с результатами статического анализа\. Ну красота же\!

## Настройка репозитория GitHub

Чтобы GitHub начал анализировать SARIF файлы, сначала необходимо настроить репозиторий\. При настройке мы пользовались [вот этой](https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/enabling-code-scanning-for-a-repository) инструкцией\. 

Итак, открываем свой репозиторий и нажимаем на "Security"\.

![0798_SARIF_ru/image2.png](https://import.viva64.com/docx/blog/0798_SARIF_ru/image2.png)

Находим по центру "Code scanning alerts" и нажимаем справа на кнопку "Set up code scanning"\.

![0798_SARIF_ru/image3.png](https://import.viva64.com/docx/blog/0798_SARIF_ru/image3.png)

Далее нажимаем на "Set up this workflow"\.

![0798_SARIF_ru/image4.png](https://import.viva64.com/docx/blog/0798_SARIF_ru/image4.png)

Теперь даем имя для yml файла \(например upload\-sarif\.yml\) и пишем следующее содержимое:

```cpp
name: "Upload SARIF"

# Run workflow each time code is pushed to your repository and on a schedule.
# The scheduled workflow runs every at 00:00 on Sunday UTC time.
on:
  push:
  schedule:
  - cron: '0 0 * * 0'

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    # This step checks out a copy of your repository.
    - name: Checkout repository
      uses: actions/checkout@v2
    - name: Upload SARIF file
      uses: github/codeql-action/upload-sarif@v1
      with:
        # Path to SARIF file relative to the root of the repository
        sarif_file: results.sarif
```

Выглядеть это должно следующим образом:

![0798_SARIF_ru/image5.png](https://import.viva64.com/docx/blog/0798_SARIF_ru/image5.png)

Теперь нажимаем "Start commit", пишем какое\-то сообщение \(например "Create upload\-sarif\.yml"\) и коммитим\.

Отлично, мы настроили репозиторий\! Можно приступать к получению SARIF файла\.

## Получение SARIF файла

Как вы поняли, SARIF – унифицированный стандарт, и получить его можно с помощью разных статических анализаторов и инструментов\. В этой статье мы будем использовать PVS\-Studio и PlogConverter\. Обо всем об этом – далее\.

### Проверяем проект

Чтобы получить SARIF файл, сначала нам необходимо проверить проект с помощью статического анализатора\. Поэтому в настроенный выше репозиторий мы добавили небольшой тестовый С\+\+ проект с одним файлом для демонстрации\. Ибо что мы будет проверять\-то в самом деле? :\) Вот содержимое файла:

```cpp
#include <iostream>
void f(unsigned int ch) 
{
  unsigned int chx = -1;
  if (ch >= 0x0fff0)
  {
    if ( !((ch >= 0x0FF10) && (ch <= 0x0FF19)) 
       || ((ch >= 0x0FF21) && (ch <= 0x0FF3A)) 
       || ((ch >= 0x0FF41) && (ch <= 0x0FF5A)))
    {
      ch = chx;
    }
  }
}
int main()
{
  std::cout << "error" << std::endl;
}
```

Кстати, синтетический пример с ошибкой имеет реальный прототип, описанный в статье "[Как PVS\-Studio оказался внимательнее, чем три с половиной программиста](https://pvs-studio.ru/ru/blog/posts/cpp/0587/)"\.

Как уже было упомянуто выше, проверка будет осуществляться с помощью статического анализатора [PVS\-Studio](https://pvs-studio.ru/ru/pvs-studio/)\. А именно \- с помощью консольной утилиты "PVS\-Studio\_Cmd\.exe"\. Данная утилита позволяет производить анализ C\+\+, C\# MSBuild\-проектов на Windows\. По умолчанию найти ее можно по пути "C:\\Program Files \(x86\)\\PVS\-Studio"\. Подробнее о данной утилите Вы можете почитать [здесь](https://pvs-studio.ru/ru/docs/manual/0035/)\.

Если у вас нет лицензии для проверки, то не отчаивайтесь\. Кликнув [сюда](https://pvs-studio.ru/ru/pvs-studio/download/), вы перейдёте на сайт анализатора, где сможете скачать его, а также получить триальную лицензию\. 

Собственно, приступаем к анализу\. Чтобы его произвести достаточно выполнить вот эту команду:

```cpp
PVS-Studio_Cmd.exe -t "D:\Use_SARIF_Example\BestProjectCpp.sln" \
-o "D:\Use_SARIF_Example\results.plog" -e "D:\Use_SARIF_Example\"
```

Рассмотрим строку запуска немного подробнее\. Флаг "\-t" является обязательным\. Он позволяет указать объект для проверки \(sln или csproj/vcxproj файл\)\. Флаг "\-o" отвечает за путь до файла, в который будут записаны результаты анализа\. Флаг "\-e" \- корневая часть пути, которую PVS\-Studio будет использовать при генерации относительных путей в предупреждениях\. Нужно это потому, что отчет будет обрабатываться в облаке\.

Отлично, теперь нужно преобразовать plog файл в SARIF файл\. Для этого воспользуемся утилитой PlogConverter\.

### Преобразование из Plog в SARIF

Преобразование мы будем выполнять с помощью утилиты PlogConverter, поэтому пару слов о ней\. [PlogConverter](https://github.com/viva64/plog-converter) – это утилита с открытым исходным кодом, предназначенная для преобразования отчетов анализатора PVS\-Studio из одного формата в другой\. Более подробно утилита описана в [документации](https://pvs-studio.ru/ru/docs/manual/0038/)\. 

Итак, нам необходимо найти PlogConverter\.exe на компьютере\. Эта утилита устанавливается вместе с PVS\-Studio и располагается рядом с "PVS\-Studio\_Cmd\.exe"\. Переходим туда, открываем консоль и пишем следующую команду:

```cpp
PlogConverter.exe "D:\Use_SARIF_Example\results.plog" \
-o "D:\Use_SARIF_Example" -t sarif -n results
```

Вот и все\. Теперь можно заливать этот файл и смотреть результаты анализа\.

## Проверяем, что все работает

Чтобы проверить, что мы все сделали правильно, быстренько загрузим наш SARIF файл руками и посмотрим результаты анализа\. Для этого переходим в репозиторий и нажимаем "Add file \-\> Upload files"\.

![0798_SARIF_ru/image6.png](https://import.viva64.com/docx/blog/0798_SARIF_ru/image6.png)

Далее добавляем SARIF файл и ждем, пока он обработается\. Если хочется посмотреть, как там проходит обработка, то необходимо нажать на "Actions" и далее выбрать работающую задачу\. 

Как только все будет готово, заходим во вкладку "Security"\. В ней выбираем слева "Code scanning alerts \-\> PVS\-Studio"\. 

![0798_SARIF_ru/image7.png](https://import.viva64.com/docx/blog/0798_SARIF_ru/image7.png)

Справа у нас и будут сообщения анализатора\. Откроем какое\-нибудь предупреждение:

![0798_SARIF_ru/image8.png](https://import.viva64.com/docx/blog/0798_SARIF_ru/image8.png)

Мы видим:

1. Быстрый фильтр по ошибкам;
1. Сообщение об ошибке\. Оно же и указывает, где именно в исходном коде находится ошибка;
1. Ссылка на документацию для предупреждения анализатора\.

## Реальный сценарий использования SARIF в GitHub

Пришло время посмотреть, как это все может работать на практике\. Предлагаю рассмотреть сценарий, когда человек скачает репозиторий, выполнит какую\-то работу и с помощью описанных выше команд, создаст SARIF файл и зальет изменения в отдельную ветку\. В итоге такой сценарий позволит нам смотреть не только, какие файлы изменил пользователь, но и какие ошибки он допустил\. Поэтому скачиваем репозиторий и делаем изменения в файле с C\+\+ кодом:

```cpp
#include <iostream>
void f(unsigned int ch) 
{
  unsigned int chx = -1;
  if (ch >= 0x0fff0)
  {
    if (!((ch >= 0x0FF10) && (ch <= 0x0FF19)) 
      || ((ch >= 0x0FF21) && (ch <= 0x0FF3A)) 
      || ((ch >= 0x0FF41) && (ch <= 0x0FF5A)))
    {
      ch = chx;
    }
  }
}

int ComputeProjectionMatrixFOV(float fov)
{
  float yScale = 1.0 / tan((3.141592538 / 180.0) * fov / 2);
  return yScale;
}

int main()
{
  std::cout << "error" << std::endl;
}
```

Далее проверяем файл, сохраняем отчет, получаем SARIF файл \(заменяя им уже лежащий в скаченном репозитории\) и делаем коммит в отдельную ветку\. Все, пользователь сделал свое дело\. Теперь черед смотреть ошибки\.

Заходим в репозиторий\. Далее "Security" \-\> "Code scanning alerts" \-\> "PVS\-Studio" и справа в "Branch" выбираем нужную ветку\. Смотрим результаты:

![0798_SARIF_ru/image9.png](https://import.viva64.com/docx/blog/0798_SARIF_ru/image9.png)

Как вы видите, сообщения об ошибках в ветке хранятся отдельно\. Согласитесь, это достаточно удобно\. При желании можно, например, создать bat файл, который будет запускать анализатор, конвертировать отчет в SARIF и заменять существующий SARIF файл\. 

## Что можно делать результатами?

Итак, вы остались один на один с отчетом\. Что доступно в вашем распоряжении? Первое, на что нужно обратить внимание, — это то, что все ошибки разделены на две группы\. Это "Open" и "Closed"\. "Open" — это активные ошибки, которые мы не обработали\. "Closed" – это ошибки, которые мы исправили или пометили как ложные\.

![0798_SARIF_ru/image10.png](https://import.viva64.com/docx/blog/0798_SARIF_ru/image10.png)

Второе — это фильтры по статусам ошибок \(закрытые, отрытые и все такое\)\. 

![0798_SARIF_ru/image11.png](https://import.viva64.com/docx/blog/0798_SARIF_ru/image11.png)

Еще есть фильтры по характеристикам ошибок\. Например, можно отсортировать по номеру ошибки\.

![0798_SARIF_ru/image12.png](https://import.viva64.com/docx/blog/0798_SARIF_ru/image12.png)

Также GitHub позволяет нам помечать сообщения как "false positive", "used in tests", и мое любимое "won't fix" :\)\.  Чтобы пометить сообщение, необходимо его выбрать \(слева от сообщения есть checkbox\) и справа вверху нажать на "Dismiss"\. 

![0798_SARIF_ru/image13.png](https://import.viva64.com/docx/blog/0798_SARIF_ru/image13.png)

Сообщения, которые вы так разметите, не будут попадать в графу открытых ошибок при следующей загрузке SARIF файла\.

Если у нас появилась необходимость вернуть сообщения в "Open", то это очень легко сделать\. Для этого выбираем "Closed", далее выбираем то, что хотим вернуть, и нажимаем справа "Reopen"\.

Также обратите внимание, что если загрузить новый лог, то он перезаписывает текущие открытые ошибки\. Если ошибки, которые были в "Open", не встретились в новом логе, то они попадают в "Closed"\. Поэтому рекомендуем использовать SARIF только для анализа всего проекта\. Если вам требуется проанализировать только pull request, то для этого у нас есть ряд статей на эту тему\. Например, вот [эта](https://pvs-studio.ru/ru/blog/posts/0750/)\. Использовать же SARIF для анализа pull request будет не очень удобно\.

## А работает только для C\+\+?

Конечно же нет, вы вообще не зависите от языка\. Все, что вам нужно – это инструмент статического анализа, который сможет проанализировать ваш код и создать SARIF файл\. Например, используемый в этой статье PVS\-Studio умеет анализировать C\+\+, C\#, Java\. Поэтому давайте еще попробуем проверить код на C\#, потому что ~~это лучший язык в мире~~ один из авторов статьи его любит\. Для примера быстренько проделываем все то же самое, о чем говорилось в статье, но уже для C\# проекта\. Вот содержимое файла, который был проанализирован:

```cpp
using System;
using System.Collections.Generic;
using System.Linq;

namespace TestSarif
{
  class Program
  {
    static void Main()
    {
      var result = Formula42(3, 5);
    }

    static int Formula42(int? coefficientA, int? coefficientB)
    {
      var data = new List<int>();
      if (coefficientA != null)
        data.Add(Formula42(coefficientA.Value));
      else if (coefficientB != null)
        data.Add(Formula42(coefficientA.Value));
      return data.SingleOrDefault();
    }

    static private int Formula42(int coefficient)
    {
      return coefficient;
    }
  }
}
```

Вот результат:

![0798_SARIF_ru/image14.png](https://import.viva64.com/docx/blog/0798_SARIF_ru/image14.png)

Ну и посмотрим на саму ошибку\.

![0798_SARIF_ru/image15.png](https://import.viva64.com/docx/blog/0798_SARIF_ru/image15.png)

## Вывод

Подводя итог, хочется сказать, что SARIF — это удобный формат, который позволяет просматривать результаты анализа\. Да и настройка использования SARIF быстрая и простая\. Например, в VS Code это вообще делается в пару кликов\. Кстати, если вам будет интересно, как это сделать, то напишите об этом в комментариях\. Да и вообще, если у вас есть какие\-то пожелания по темам статьи, то напишите об этом\. 

Так что пробуйте и пользуйтесь\. Спасибо за внимание\.