Review replication: Difference between revisions

From Svacer Wiki
mNo edit summary
No edit summary
Line 1: Line 1:
== Репликация разметки по правилам (экспериментальная функциональность) ==
== Репликация разметки по правилам (экспериментальная функциональность) ==
При использовании разных версий Svace (или иных анализаторов), разных настроек CI/CD и прочих факторах возможны ситуации, когда снимки (snapshots) в рамках одной ветки (branch) могут иметь различные инварианты и разметка автоматически не переносится. Для решения задачи переноса разметки в таких случаях разработана утилита <code>reviewer</code>, которая позволяет применить декларативно описанные правила переноса к существующей разметке. В дальнейшем данная функциональность будет включена в Svacer и доступна в веб интерфейсе.
При использовании разных версий Svace (или иных анализаторов), разных настроек CI/CD и прочих факторах возможны ситуации, когда снимки (snapshots) в рамках одной ветки (branch) могут иметь различные инварианты и разметка автоматически не переносится. Для решения задачи переноса разметки в таких случаях разработана утилита <code>reviewer</code>, которая позволяет применить декларативно описанные правила переноса к существующей разметке. В дальнейшем данная функциональность будет включена в Svacer и доступна в веб-интерфейсе.


=== Описание утилиты ===
=== Описание утилиты ===
Line 24: Line 24:
     --token value        Defines access token for svacer server [$SVACER_AUTH_TOKEN]
     --token value        Defines access token for svacer server [$SVACER_AUTH_TOKEN]
     --help, -h          show help
     --help, -h          show help
Основная команда, это <code>replicate</code>  - она позволяет применить декларативные правила к разметке, полученной либо с сервера либо из файла, куда ранее она была выгружена командой <code>svacer markup2 export</code>.
Основная команда, это <code>replicate</code>  - она позволяет применить декларативные правила к разметке, полученной либо с сервера, либо из файла, куда ранее она была выгружена командой <code>svacer markup2 export</code>.
  NAME:
  NAME:
     reviewer replicate - Replicate non-empty review to invariants according to rules
     reviewer replicate - Replicate non-empty review to invariants according to rules
Line 48: Line 48:
'''Шаги решения:'''
'''Шаги решения:'''


* (опционально, но рекомендуется) Выгрузить разметку с ветке в файл использую команду  
* (опционально, но рекомендуется) Выгрузить разметку с ветки в файл, используя команду:


  svacer markup2 --host=<nowiki>http://localhost:8080</nowiki> --user admin --password admin export --project myproject --branch master  --uncompressed --format json --export-all /tmp/myproject.json
  svacer markup2 --host=<nowiki>http://localhost:8080</nowiki> --user admin --password admin export --project myproject --branch master  --uncompressed --format json --export-all /tmp/myproject.json


* написать правила переноса разметки в файл <code>/tmp/map.txt</code> (формат будет описан ниже)
* написать правила переноса разметки в файл <code>/tmp/map.txt</code> (формат будет описан ниже)
* (если разметка '''была выгружена''') применить утилиту <code>reviewer</code> с загрузкой данных из файла (флаг <code>--html</code> создаст дополнительно HTML с информацией об изменениях , имя файла <code>/tmp/out.json.html</code>)
* (если разметка '''была выгружена''') применить утилиту <code>reviewer</code> с загрузкой данных из файла (флаг <code>--html</code> создаст дополнительно HTML с информацией об изменениях , имя файла <code>/tmp/out.json.html</code>):


  reviewer replicate --file /tmp/myproject.json --rule /tmp/map.txt --html /tmp/out.json
  reviewer replicate --file /tmp/myproject.json --rule /tmp/map.txt --html /tmp/out.json


* ('''без выгрузки''' разметки) применить утилиту <code>reviewer</code> с загрузкой данных с сервера (флаг <code>--html</code> создаст дополнительно HTML с информацией об изменениях , имя файла <code>/tmp/out.json.html</code>)
* ('''без выгрузки''' разметки) применить утилиту <code>reviewer</code> с загрузкой данных с сервера (флаг <code>--html</code> создаст дополнительно HTML с информацией об изменениях , имя файла <code>/tmp/out.json.html</code>):


  reviewer --host=http://localhost:8080 --user admin --password admin replicate --project myproject --branch master --rule /tmp/map.txt --html /tmp/out.json
  reviewer --host=http://localhost:8080 --user admin --password admin replicate --project myproject --branch master --rule /tmp/map.txt --html /tmp/out.json


* просмотреть созданный файл <code>/tmp/out.json.html</code>
* просмотреть созданный файл <code>/tmp/out.json.html</code>
* если результат устраивает, то загрузить обновленную разметку в сервер
* если результат устраивает, то загрузить обновленную разметку в сервер:


  svacer markup2 --host=<nowiki>http://localhost:8080</nowiki> --user admin --password admin import --project myproject --branch master /tmp/out.json
  svacer markup2 --host=<nowiki>http://localhost:8080</nowiki> --user admin --password admin import --project myproject --branch master /tmp/out.json
Line 71: Line 71:
Команда <code>markup2 export</code> с флагом <code>--export-all</code>  выгружает все инварианты с ветки с информацией о разметке и комментариях.  
Команда <code>markup2 export</code> с флагом <code>--export-all</code>  выгружает все инварианты с ветки с информацией о разметке и комментариях.  


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


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


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


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




Line 151: Line 151:
<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





Revision as of 12:54, 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. Технически, это статус, набор комментариев и массив location-ов, которые определяют множество мест, имеющих один и тот же инвариант.

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

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

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

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

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

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

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

Правила - это выражение в синтаксисе (https://expr-lang.org/docs/language-definition), выражения использует операторы && , ||, !, скобки и

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


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 разметки совпадает с одним из аргументов


Пример:

// Перенос разметки для 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