Review replication: Difference between revisions

From Svacer Wiki
mNo edit summary
mNo edit summary
Line 95: Line 95:




<code>unprocessed()</code>
* <code>unprocessed()</code>


проверка, что target еще не содержит разметки. Рекомендуется использовать, чтобы избежать перезаписи разметки, если несколько правил сработали.  
проверка, что target еще не содержит разметки. Рекомендуется использовать, чтобы избежать перезаписи разметки, если несколько правил сработали.  


 
* <code>processed()</code>
 
<code>processed()</code>


проверка, что target уже содержит какую-либо не дефолтную разметку
проверка, что target уже содержит какую-либо не дефолтную разметку


 
* <code>match_loc(field1, field2, ...)</code>  
 
<code>match_loc(field1, field2, ...)</code>  


проверка, содержат ли locations в source и target хотя бы один общий location, какой совпадает по указанным полям
проверка, содержат ли locations в source и target хотя бы один общий location, какой совпадает по указанным полям
Line 115: Line 111:
Пример: <code>match_loc(warnclass,file,lang,tool,line)</code>
Пример: <code>match_loc(warnclass,file,lang,tool,line)</code>


 
* <code>match_loc_strict(field1, field2, ...)</code>  
 
<code>match_loc_strict(field1, field2, ...)</code>  


 проверка, содержат ли locations source и target одинаковые location по указанным полям
 проверка, содержат ли locations source и target одинаковые location по указанным полям
Line 123: Line 117:
 Пример: <code>match_loc_strict(warnclass,file,lang,tool,line)</code>
 Пример: <code>match_loc_strict(warnclass,file,lang,tool,line)</code>


 
* <code>match_source_re (field, value)</code>
 
<code>match_source_re (field, value)</code>


 проверка, содержит ли location в source запись где field совпадает с value. Value - Golang regexp
 проверка, содержит ли location в source запись где field совпадает с value. Value - Golang regexp


 
* <code>match_target_re (field, value)</code>
 
<code>match_target_re (field, value)</code>


 проверка, содержит ли location в target запись где field совпадает с value. Value - Golang regexp
 проверка, содержит ли location в target запись где field совпадает с value. Value - Golang regexp


 
* <code>source_review(status[, severity, action])</code>  
 
<code>source_review(status[, severity, action])</code>  


 проверка, если разметка source соответствует указанным параметрам
 проверка, если разметка source соответствует указанным параметрам
Line 145: Line 133:
 шаблон <code>"*"</code> соответствует всему
 шаблон <code>"*"</code> соответствует всему


 
* <code>target_review(status[, severity, action])</code>  
 
<code>target_review(status[, severity, action])</code>  


 проверка, если разметка target соответствует указанным параметрам
 проверка, если разметка target соответствует указанным параметрам
Line 155: Line 141:
 шаблон <code>"*"</code> соответствует всему
 шаблон <code>"*"</code> соответствует всему


 
* <code>match_source_range (lower_bound,upper_bound)</code>
 
<code>match_source_range (lower_bound,upper_bound)</code>


проверка, если в source есть location где line попадает в указанный диапазон. Значение -1 означает отсутствие границы     
проверка, если в source есть location где line попадает в указанный диапазон. Значение -1 означает отсутствие границы     


 
* <code>match_target_range (lower_bound,upper_bound)</code>
 
<code>match_target_range (lower_bound,upper_bound)</code>


проверка, если в target есть location, где line попадает в указанный диапазон. Значение -1 означает отсутствие границы
проверка, если в target есть location, где line попадает в указанный диапазон. Значение -1 означает отсутствие границы


 
* <code>match_suffix_re (field, source_prefix[,target_prefix])</code>
 
<code>match_suffix_re (field, source_prefix[,target_prefix])</code>


проверка, есть ли <code>location</code> в <code>source</code> и <code>target</code>, какой содержит общий суффикс. Суффикс вычисляется путем отрезания префикса <code>source_prefix</code> и <code>target_prefix</code>. Если target_prefix не указан, то считается что он равен source_prefix. Префикс определяется как Go regexp
проверка, есть ли <code>location</code> в <code>source</code> и <code>target</code>, какой содержит общий суффикс. Суффикс вычисляется путем отрезания префикса <code>source_prefix</code> и <code>target_prefix</code>. Если target_prefix не указан, то считается что он равен source_prefix. Префикс определяется как Go regexp


 
* <code>match_source_id (id1, id2, ....)</code>
 
<code>match_source_id (id1, id2, ....)</code>


проверка, если внутренний id source разметки совпадает с одним из аргументов
проверка, если внутренний id source разметки совпадает с одним из аргументов


 
* <code>match_target_id (id1, id2, ....)</code>
 
<code>match_target_id (id1, id2, ....)</code>


проверка, если внутренний id target разметки совпадает с одним из аргументов
проверка, если внутренний id target разметки совпадает с одним из аргументов


<code>source_review_ct() time.Time</code>
* <code>source_review_ct() time.Time</code>


возвращает время создания разметки в source
возвращает время создания разметки в source


<code>target_review_ct() time.Time</code>
* <code>target_review_ct() time.Time</code>


возвращает время создания разметки в target
возвращает время создания разметки в target


<code>source_reviewed_by() string</code>
* <code>source_reviewed_by() string</code>


возвращает автора разметки в source
возвращает автора разметки в source


<code>target_reviewed_by() string</code>
* <code>target_reviewed_by() string</code>


возвращает автора разметки в target
возвращает автора разметки в target


Пример:
Пример:

Revision as of 14:22, 4 March 2025

Репликация разметки по правилам (экспериментальная функциональность)

При использовании разных версий Svace (или иных анализаторов), разных настроек CI/CD и прочих факторах возможны ситуации, когда снимки (snapshots) в рамках одной ветки (branch) могут иметь различные инварианты и разметка автоматически не переносится. Для решения задачи переноса разметки в таких случаях разработана утилита reviewer, которая позволяет применить декларативно описанные правила переноса к существующей разметке. В дальнейшем данная функциональность будет включена в Svacer и доступна в веб-интерфейсе.

Описание утилиты

Утилита reviewer предназначена для Svacer версии 10 и выше.

NAME:
   reviewer - Svacer review help tool

USAGE:
   reviewer [global options] command [command options] [arguments...]

COMMANDS:
   syntax     Prints help information about rule syntax
   replicate  Replicate non-empty review to invariants according to rules
   help, h    Shows a list of commands or help for one command

GLOBAL OPTIONS:
   --debug              Enabled debug output (default: false)
   --log-file value     Define log file for output
   --host value         Defines URL to svacer server. Format: http://host:port
   --user value         User login. When using env variable SVACER_AUTH_CREDS the format is SVACER_AUTH_CREDS=<login>:<password> (default: admin) [$SVACER_AUTH_CREDS]
   --password value     User password (default: admin)
   --ldap_server value  Server for LDAP authentication [$SVACER_LDAP_SERVER]
   --token value        Defines access token for svacer server [$SVACER_AUTH_TOKEN]
   --help, -h           show help

Основная команда, это replicate - она позволяет применить декларативные правила к разметке, полученной либо с сервера, либо из файла, куда ранее она была выгружена командой svacer markup2 export.

NAME:
   reviewer replicate - Replicate non-empty review to invariants according to rules

USAGE:
   reviewer replicate [command options] <file name> - path to output file with applied rules

OPTIONS:
   --project value  Project name or id
   --branch value   Branch name or id (default: master)
   --file value     Load review from file instead of server. File must be in 'json with new line separator' format. File may be gzipped (must have *.gz extension)
   --rule value     Path to file containing replicate rules
   --html           Produce HTML report showing applied changes.Report wil have name <file name>.html (default: false)
   --verbose        Verbose output of rule applications (default: false)
   --process-all    Process all reviews, even with non-default values (default: false)
   --skip-comments  Skip comments while replicating review information (default: false)
   --skip-status    Skip review status and copy only comments while replicating review information (default: false)
   --help, -h       show help

Шаги применения утилиты

Задача: В проекте myproject на ветке master необходимо перенести существующую разметку по некоторым правилам. Сервер запущен на localhost на порте 8080.

Шаги решения:

  • (опционально, но рекомендуется) Выгрузить разметку с ветки в файл, используя команду:
svacer markup2 --host=http://localhost:8080 --user admin --password admin export --project myproject --branch master  --uncompressed --format json --export-all /tmp/myproject.json
  • написать правила переноса разметки в файл /tmp/map.txt (формат будет описан ниже)
  • (если разметка была выгружена) применить утилиту reviewer с загрузкой данных из файла (флаг --html создаст дополнительно HTML с информацией об изменениях , имя файла /tmp/out.json.html):
reviewer replicate --file /tmp/myproject.json --rule /tmp/map.txt --html /tmp/out.json
  • (без выгрузки разметки) применить утилиту reviewer с загрузкой данных с сервера (флаг --html создаст дополнительно HTML с информацией об изменениях , имя файла /tmp/out.json.html):
reviewer --host=http://localhost:8080 --user admin --password admin replicate --project myproject --branch master --rule /tmp/map.txt --html /tmp/out.json
  • просмотреть созданный файл /tmp/out.json.html
  • если результат устраивает, то загрузить обновленную разметку в сервер:
svacer markup2 --host=http://localhost:8080 --user admin --password admin import --project myproject --branch master /tmp/out.json

Пояснения

Разметка в Svacer привязана к инвариантам. Инвариант это некоторый хэш, формируемый из полей предупреждения. Алгоритм формирования хэша описан здесь: формирование инвариантов. В рамках одного снимка все инварианты всегда уникальны.

Команда markup2 export с флагом --export-all выгружает все инварианты с ветки с информацией о разметке и комментариях.

При экспорте, разметка на инварианте представлена как объект соответствующей схеме, описанной здесь Markup2. Технически - это:

  • статус (тройка status, severity, action)
  • набор комментариев
  • массив location-ов, которые определяют множество мест, имеющих один и тот же инвариант.

Алгоритм переноса разметки

Входные данные (разметка), полученные из файла или с сервера разбиваются на два вектора source и target. В source включаются все элементы с разметкой отличной от разметки по умолчанию. В target включаются все оставшиеся элементы. Если указана опция --process-all , то в source и target включаются все элементы (данная опция предназначена для случаев, если мы хотим заместить существующую разметку)

Процедура проходит по всем парам (source_item,target_item) и для каждой пары вычисляет предикаты из файла с правилами в порядке их определения. Если какой либо предикат вычислен в true, то происходит копирование статусов разметки и комментариев с source_item на target_item.Во избежание перезаписи разметки можно в правилах использовать предикат unprocessed() описанный ниже.

Файл задания предикатов переноса

Формат файла: UTF-8

Правила разделяются ;;

В качестве комментариев допустимы /**/ и //

Правила - это булевы выражение в синтаксисе go-expr , выражения использует операторы && , ||, !, скобки и

следующие дополнительные предикаты:


  • unprocessed()

проверка, что target еще не содержит разметки. Рекомендуется использовать, чтобы избежать перезаписи разметки, если несколько правил сработали.

  • processed()

проверка, что target уже содержит какую-либо не дефолтную разметку

  • match_loc(field1, field2, ...)

проверка, содержат ли locations в source и target хотя бы один общий location, какой совпадает по указанным полям

возможные поля: warnclass, function, details, invariant, line, file, mtid, tool, lang

Пример: match_loc(warnclass,file,lang,tool,line)

  • match_loc_strict(field1, field2, ...)

 проверка, содержат ли locations source и target одинаковые location по указанным полям

 Пример: match_loc_strict(warnclass,file,lang,tool,line)

  • match_source_re (field, value)

 проверка, содержит ли location в source запись где field совпадает с value. Value - Golang regexp

  • match_target_re (field, value)

 проверка, содержит ли location в target запись где field совпадает с value. Value - Golang regexp

  • source_review(status[, severity, action])

 проверка, если разметка source соответствует указанным параметрам

 severity, action можно опускать

 шаблон "*" соответствует всему

  • target_review(status[, severity, action])

 проверка, если разметка target соответствует указанным параметрам

 severity, action можно опускать

 шаблон "*" соответствует всему

  • match_source_range (lower_bound,upper_bound)

проверка, если в source есть location где line попадает в указанный диапазон. Значение -1 означает отсутствие границы   

  • match_target_range (lower_bound,upper_bound)

проверка, если в target есть location, где line попадает в указанный диапазон. Значение -1 означает отсутствие границы

  • match_suffix_re (field, source_prefix[,target_prefix])

проверка, есть ли location в source и target, какой содержит общий суффикс. Суффикс вычисляется путем отрезания префикса source_prefix и target_prefix. Если target_prefix не указан, то считается что он равен source_prefix. Префикс определяется как Go regexp

  • match_source_id (id1, id2, ....)

проверка, если внутренний id source разметки совпадает с одним из аргументов

  • match_target_id (id1, id2, ....)

проверка, если внутренний id target разметки совпадает с одним из аргументов

  • source_review_ct() time.Time

возвращает время создания разметки в source

  • target_review_ct() time.Time

возвращает время создания разметки в target

  • source_reviewed_by() string

возвращает автора разметки в source

  • target_reviewed_by() string

возвращает автора разметки в target

Пример:

// Перенос разметки для Go, где поменялся формат поля function в последних Svace

unprocessed() &&  // ensure target has no review
        match_loc(warnclass,file,lang,tool,mtid, line) && // ensure main fields are the same
        match_suffix_re (function, "(.+/)" /* regexp for prefix */ ) // trim prefix and match suffix

HTML отчет о результатах переноса

При использовании опции --htmlутилита формирует HTML файл с информацией о разметке и операциях по переносу. Файл предназначен для отладки процесса переноса. В будущем, в Svacer UI будет предусмотрен специальный интерфейс для просмотра результатов переноса.

При наличии переноса разметки в столбце с Review будет запись Review Source с ссылкой на элемент, откуда была перенесена разметка

При раскрытии элемента Review Source будут представлены основные поля location-ов, соответствующих исходной разметки, откуда был сделан перенос.