mirror of
https://github.com/bia-technologies/sonar-helper.git
synced 2026-06-18 17:24:22 +02:00
Добавлена команда для переноса замечания на указанного пользователя по набору фильтров
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"--token": "2ef785ca946170b7086668132175eb01386943a1",
|
||||
"--server": "http://my.sonar.server:9000",
|
||||
"--projects": "bsp,mdm",
|
||||
"--statuses": "OPEN",
|
||||
"--assigned": "notme,false",
|
||||
"--assign": "me"
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Служебный модуль с реализацией работы команды transfer-issues
|
||||
//
|
||||
// (C) Maximov Valery (aka theshadowco)
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Перем Лог;
|
||||
|
||||
Перем Проекты;
|
||||
Перем ИсключаемыеПроекты;
|
||||
Перем Статусы;
|
||||
Перем МаксимальноеКоличествоСтатусов;
|
||||
|
||||
Перем ПрочитанныеПараметры;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Прикладной интерфейс
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Процедура ЗарегистрироватьКоманду(Знач ИмяКоманды, Знач Парсер) Экспорт
|
||||
|
||||
ОписаниеКоманды = Парсер.ОписаниеКоманды(ИмяКоманды, "Выполняет перенос замечаний на указанного пользователя");
|
||||
Парсер.ДобавитьИменованныйПараметрКоманды(ОписаниеКоманды, "--token", "Токен для авторизации на сервере SonarQube");
|
||||
Парсер.ДобавитьИменованныйПараметрКоманды(ОписаниеКоманды, "--server", "Адрес сервера SonarQube (например http://my.sonar.server:9000)");
|
||||
Парсер.ДобавитьИменованныйПараметрКоманды(ОписаниеКоманды, "--assigned", "Идентификаторы пользователей, с которых необходимо перенести замечания (список через запятую).
|
||||
|Для выбора 'Не назначено' используйте значение 'false'");
|
||||
Парсер.ДобавитьИменованныйПараметрКоманды(ОписаниеКоманды, " - -assign", "Идентификатор пользователя, на которого необходимо назначить замечания.
|
||||
|Для выбора 'Не назначено' используйте значение 'false'");
|
||||
Парсер.ДобавитьИменованныйПараметрКоманды(ОписаниеКоманды, "--projects", "Ключи проектов, строкой через запятую (например hrm:develop,buh:master).
|
||||
| Для того, чтобы указать все проекты, необходимо передать #all");
|
||||
Парсер.ДобавитьИменованныйПараметрКоманды(ОписаниеКоманды, "--exclude-projects", "Ключи проектов, которые необходимо исключить из обработки");
|
||||
Парсер.ДобавитьИменованныйПараметрКоманды(ОписаниеКоманды, "--statuses", "Отбор замечаний только соответствующих статусов.
|
||||
| Необходимые статусы необходимо передавать строкой через запятую.
|
||||
| Возможные значения:
|
||||
| OPEN - открытые
|
||||
| CONFIRMED - подтвержденные:
|
||||
| REOPENED - переоткрытые
|
||||
| RESOLVED - решенные
|
||||
| CLOSED - закрытые
|
||||
|
|
||||
| По умолчанию выбираются только RESOLVED и CLOSED");
|
||||
Парсер.ДобавитьИменованныйПараметрКоманды(ОписаниеКоманды, "--cfg-file", "Путь к конфигурационному файлу в формате json (utf-8), свойства объекта соответствуют ключам запуска.
|
||||
| Пример конфигурационного файла находится в каталоге examples");
|
||||
|
||||
Парсер.ДобавитьКоманду(ОписаниеКоманды);
|
||||
|
||||
КонецПроцедуры
|
||||
|
||||
// Выполняет логику команды
|
||||
//
|
||||
// Параметры:
|
||||
// ПараметрыКоманды - Соответствие - Соответствие ключей командной строки и их значений
|
||||
// ДополнительныеПараметры - Соответствие - (необязательно) дополнительные параметры
|
||||
//
|
||||
Функция ВыполнитьКоманду(Знач ПараметрыКоманды, Знач ДополнительныеПараметры = Неопределено) Экспорт
|
||||
|
||||
Лог = ДополнительныеПараметры.Лог;
|
||||
ОшибокНет = ПрочитатьПараметрыЗапуска(ПараметрыКоманды);
|
||||
Если НЕ ОшибокНет Тогда
|
||||
Возврат ОбщегоНазначения.СообщитьОбОшибке("Ошибка запуска");
|
||||
КонецЕсли;
|
||||
|
||||
АдресСервера = ПрочитанныеПараметры.Получить("АдресСервера");
|
||||
Токен = ПрочитанныеПараметры.Получить("Токен");
|
||||
РодительскийПроект = ПрочитанныеПараметры.Получить("РодительскийПроект");
|
||||
|
||||
Лог.Информация("Получение информации о проектах");
|
||||
ПроектыSQ = Сонар.ПолучитьПроекты(АдресСервера, Токен);
|
||||
|
||||
Если Проекты.Найти("#all") <> Неопределено Тогда
|
||||
Проекты.Очистить();
|
||||
Для Каждого ОписаниеПроекта Из ПроектыSQ Цикл
|
||||
Если ОписаниеПроекта.Ключ <> РодительскийПроект Тогда
|
||||
Проекты.Добавить(ОписаниеПроекта.Ключ);
|
||||
КонецЕсли;
|
||||
КонецЦикла;
|
||||
КонецЕсли;
|
||||
|
||||
Для Каждого ИсключаемыйПроект Из ИсключаемыеПроекты Цикл
|
||||
Позиция = Проекты.Найти(СокрЛП(ИсключаемыйПроект));
|
||||
Если Позиция <> Неопределено Тогда
|
||||
Проекты.Удалить(Позиция);
|
||||
КонецЕсли;
|
||||
КонецЦикла;
|
||||
|
||||
ПользователиСтрокой = ПрочитанныеПараметры.Получить("Пользователи");
|
||||
Если ЗначениеЗаполнено(ПользователиСтрокой) Тогда
|
||||
Пользователи = СтрРазделить(ПользователиСтрокой, ",", Ложь);
|
||||
ПользовательВСписке = Пользователи.Найти(ПрочитанныеПараметры.Получить("НазначитьНа"));
|
||||
Если ПользовательВСписке <> Неопределено Тогда
|
||||
Пользователи.Удалить(ПользовательВСписке);
|
||||
КонецЕсли;
|
||||
|
||||
Если Пользователи.Количество() Тогда
|
||||
ПользователиСтрокой = СтрСоединить(Пользователи, ",");
|
||||
Иначе
|
||||
ПользователиСтрокой = "";
|
||||
КонецЕсли;
|
||||
КонецЕсли;
|
||||
|
||||
Лог.Информация("Чтение замечаний по фильтру");
|
||||
|
||||
Фильтр = Новый Структура();
|
||||
Фильтр.Вставить("Пользователи", ПользователиСтрокой);
|
||||
Фильтр.Вставить("Статусы", СтрСоединить(Статусы, ","));
|
||||
НайденныеЗамечания = Сонар.ПолучитьЗамечанияПоФильтру(АдресСервера, Токен, Проекты, Фильтр);
|
||||
Если НайденныеЗамечания.Количество() Тогда
|
||||
Лог.Информация("Найдено `%1` замечаний", НайденныеЗамечания.Количество());
|
||||
Лог.Информация("Перенос найденных замечаний на `%1`", ПрочитанныеПараметры.Получить("НазначитьНа"));
|
||||
Сонар.НазначитьЗамечания(АдресСервера, Токен, НайденныеЗамечания, ПрочитанныеПараметры.Получить("НазначитьНа"));
|
||||
Иначе
|
||||
Лог.Информация("Подходящих замечаний не обнаружено");
|
||||
КонецЕсли;
|
||||
|
||||
Возврат МенеджерКомандПриложения.РезультатыКоманд().Успех;
|
||||
|
||||
КонецФункции
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Функция ПрочитатьПараметрыЗапуска(ПараметрыКоманды)
|
||||
|
||||
ПрочитанныеПараметры = ОбщегоНазначения.ПрочитатьПараметрыЗапуска(ПараметрыКоманды, Истина);
|
||||
ОшибокНет = ПрочитанныеПараметры.Получить("ОшибокНет");
|
||||
МаксимальноеКоличествоСтатусов = 5;
|
||||
|
||||
Если Не ЗначениеЗаполнено(ПрочитанныеПараметры.Получить("НазначитьНа")) Тогда
|
||||
Лог.Ошибка("Не указан идентификатор пользователя, на которого необходимо перенести замечания");
|
||||
ОшибокНет = Ложь;
|
||||
КонецЕсли;
|
||||
|
||||
ИсключаемыеПроекты = Новый Массив();
|
||||
Если ЗначениеЗаполнено(ПрочитанныеПараметры.Получить("ИсключаемыеПроектыСтрокой")) Тогда
|
||||
ИсключаемыеПроекты = СтрРазделить(ПрочитанныеПараметры.Получить("ИсключаемыеПроектыСтрокой"), ", ", Ложь);
|
||||
КонецЕсли;
|
||||
|
||||
Проекты = Новый Массив();
|
||||
Если ЗначениеЗаполнено(ПрочитанныеПараметры.Получить("Проекты")) Тогда
|
||||
Проекты = СтрРазделить(ПрочитанныеПараметры.Получить("Проекты"), ", ", Ложь);
|
||||
Иначе
|
||||
Проекты.Добавить("#all");
|
||||
КонецЕсли;
|
||||
|
||||
Если Не ЗначениеЗаполнено(ПрочитанныеПараметры.Получить("СтатусыСтрокой")) Тогда
|
||||
Статусы = СтрРазделить("OPEN,CONFIRMED,REOPENED", ",", Ложь);
|
||||
Иначе
|
||||
Статусы = Новый Массив();
|
||||
СтатусыВрем = СтрРазделить(ВРЕГ(ПрочитанныеПараметры.Получить("СтатусыСтрокой")), ", ", Ложь);
|
||||
ВсеСтатусы = СтрРазделить("OPEN,CONFIRMED,REOPENED,RESOLVED,CLOSED", ",");
|
||||
Для Каждого Статус Из СтатусыВрем Цикл
|
||||
Если ВсеСтатусы.Найти(Статус) <> Неопределено Тогда
|
||||
Статусы.Добавить(Статус);
|
||||
Иначе
|
||||
Лог.Ошибка("Неопознанный статус `%1`", Статус);
|
||||
КонецЕсли;
|
||||
КонецЦикла;
|
||||
Если Статусы.Количество() = 0 Тогда
|
||||
Лог.Ошибка("Указанный фильтр по статусам не содержит корректных значений");
|
||||
ОшибокНет = Ложь;
|
||||
КонецЕсли;
|
||||
КонецЕсли;
|
||||
|
||||
Возврат ОшибокНет;
|
||||
|
||||
КонецФункции
|
||||
@@ -142,6 +142,8 @@
|
||||
ВозможныеКлючи.Вставить("Метрики", "--total-metrics");
|
||||
ВозможныеКлючи.Вставить("ПутьКОтчету", "--report-path");
|
||||
ВозможныеКлючи.Вставить("ФорматОтчета", "--report-format");
|
||||
ВозможныеКлючи.Вставить("Пользователи", "--assigned");
|
||||
ВозможныеКлючи.Вставить("НазначитьНа", "--assign");
|
||||
|
||||
Возврат ВозможныеКлючи;
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
ВозможныеКомандыПриложения.Вставить("ЗакрытьИшузы", "issue-resolver");
|
||||
ВозможныеКомандыПриложения.Вставить("СгенерироватьОтчет", "report");
|
||||
ВозможныеКомандыПриложения.Вставить("СгенерироватьОтчетПоПользователям", "usr-report");
|
||||
ВозможныеКомандыПриложения.Вставить("ПеренестиИшузы", "transfer-issues");
|
||||
|
||||
ВозможныеКомандыПриложения = Новый ФиксированнаяСтруктура(ВозможныеКомандыПриложения);
|
||||
|
||||
@@ -67,6 +68,7 @@
|
||||
КлассыРеализацииКоманд[ВозможныеКоманды().ЗакрытьИшузы] = "КомандаЗакрытьИшузы";
|
||||
КлассыРеализацииКоманд[ВозможныеКоманды().СгенерироватьОтчет] = "КомандаСгенерироватьОтчет";
|
||||
КлассыРеализацииКоманд[ВозможныеКоманды().СгенерироватьОтчетПоПользователям] = "КомандаСгенерироватьОтчетПоПользователям";
|
||||
КлассыРеализацииКоманд[ВозможныеКоманды().ПеренестиИшузы] = "КомандаПеренестиИшузы";
|
||||
|
||||
КонецПроцедуры // ПриРегистрацииКомандПриложения
|
||||
|
||||
|
||||
+107
-5
@@ -106,7 +106,7 @@
|
||||
Ответ = ВыполнитьЗапрос(АдресСервера, Токен, URL + Формат(НомерСтраницы, "ЧГ="), "GET");
|
||||
Если Ответ.total > МаксимальныйРазмерПорцииДанных Тогда
|
||||
// прочитаем компоненты, перенесем их в общий список, а по текущем прочтем только те, что висят именно на нем
|
||||
КлючиДочернихКомпонентов = ПолучитьКлючиКомпонентов(АдресСервера, Токен, КлючКомпонента, СтатусыСтрокой, Ложь);
|
||||
КлючиДочернихКомпонентов = ПолучитьКлючиКомпонентов(АдресСервера, Токен, КлючКомпонента, СтатусыСтрокой, "", Ложь);
|
||||
Для Каждого КлючДочернегоКомпонента Из КлючиДочернихКомпонентов Цикл
|
||||
КлючиКомпонентов.Добавить(КлючДочернегоКомпонента);
|
||||
КонецЦикла;
|
||||
@@ -176,6 +176,72 @@
|
||||
|
||||
КонецФункции
|
||||
|
||||
// ПолучитьЗамечанияПоФильтру
|
||||
// Получает массив идентификаторов замечаний по фильтру
|
||||
// Параметры:
|
||||
// АдресСервера - Строка - Адрес (хост) сервера SonarQube
|
||||
// Токен - Строка - Токен пользователя, от имени которого выполняются запросы к API
|
||||
// Проекты - Массив - Идентификаторы проектов для анализа
|
||||
// Фильтр - Структура - Фильтры для отбора замечаний
|
||||
// * Статусы - Строка - Статусы замечаний
|
||||
// * Пользователи - Строка - Идентификаторы пользователей, на которых назначены замечания
|
||||
//
|
||||
// Возвращаемое значение:
|
||||
// Массив - Идентификаторы замечаний
|
||||
//
|
||||
Функция ПолучитьЗамечанияПоФильтру(АдресСервера, Токен, Проекты, Фильтр) Экспорт
|
||||
|
||||
Замечания = Новый Массив();
|
||||
URLШаблон = "issues/search?ps=500&componentKeys=%1%2";
|
||||
Если Не ПустаяСтрока(Фильтр.Статусы) Тогда
|
||||
URLШаблон = URLШаблон + "&statuses=" + Фильтр.Статусы;
|
||||
КонецЕсли;
|
||||
Если Не ПустаяСтрока(Фильтр.Пользователи) Тогда
|
||||
URLШаблон = URLШаблон + "&assignees=" + Фильтр.Пользователи;
|
||||
КонецЕсли;
|
||||
URLШаблон = URLШаблон + "&p=";
|
||||
|
||||
Для Каждого Проект Из Проекты Цикл
|
||||
|
||||
КлючиКомпонентов = ПолучитьКлючиКомпонентов(АдресСервера, Токен, Проект, Фильтр.Статусы, Фильтр.Пользователи);
|
||||
КоличествоКомпонентов = КлючиКомпонентов.Количество();
|
||||
Для Ит = 0 По КоличествоКомпонентов - 1 Цикл
|
||||
КлючКомпонента = КлючиКомпонентов[Ит];
|
||||
НомерСтраницы = 1;
|
||||
URL = СтрШаблон(URLШаблон, КлючКомпонента, "");
|
||||
Пока Истина Цикл
|
||||
Ответ = ВыполнитьЗапрос(АдресСервера, Токен, URL + Формат(НомерСтраницы, "ЧГ="), "GET");
|
||||
Если Ответ.total > МаксимальныйРазмерПорцииДанных Тогда
|
||||
// прочитаем компоненты, перенесем их в общий список, а по текущем прочтем только те, что висят именно на нем
|
||||
КлючиДочернихКомпонентов = ПолучитьКлючиКомпонентов(АдресСервера, Токен, КлючКомпонента, Фильтр.Статусы, Фильтр.Пользователи, Ложь);
|
||||
Для Каждого КлючДочернегоКомпонента Из КлючиДочернихКомпонентов Цикл
|
||||
КлючиКомпонентов.Добавить(КлючДочернегоКомпонента);
|
||||
КонецЦикла;
|
||||
КоличествоКомпонентов = КлючиКомпонентов.Количество();
|
||||
URL = СтрШаблон(URLШаблон, КлючКомпонента, "&onComponentOnly=true");
|
||||
Ответ = ВыполнитьЗапрос(АдресСервера, Токен, URL + Формат(НомерСтраницы, "ЧГ="), "GET");
|
||||
КонецЕсли;
|
||||
|
||||
Для Каждого ОписаниеОшибки Из Ответ.issues Цикл
|
||||
Замечания.Добавить(ОписаниеОшибки.key);
|
||||
КонецЦикла;
|
||||
|
||||
Если БольшеНетДанных(Ответ) Тогда
|
||||
Прервать;
|
||||
КонецЕсли;
|
||||
|
||||
НомерСтраницы = НомерСтраницы + 1;
|
||||
|
||||
КонецЦикла;
|
||||
|
||||
КонецЦикла;
|
||||
|
||||
КонецЦикла;
|
||||
|
||||
Возврат Замечания;
|
||||
|
||||
КонецФункции
|
||||
|
||||
// ПолучитьСводнуюИнформациюПоЗамечаниямиПроекта
|
||||
// Возвращает свернутую таблицу с пользователями и их замечаниями на проекте проекта
|
||||
// Параметры:
|
||||
@@ -233,7 +299,7 @@
|
||||
Ответ = ВыполнитьЗапрос(АдресСервера, Токен, URL + Формат(НомерСтраницы, "ЧГ="), "GET");
|
||||
Если Ответ.total > МаксимальныйРазмерПорцииДанных Тогда
|
||||
// прочитаем компоненты, перенесем их в общий список, а по текущем прочтем только те, что висят именно на нем
|
||||
КлючиДочернихКомпонентов = ПолучитьКлючиКомпонентов(АдресСервера, Токен, КлючКомпонента, СтатусыСтрокой, Ложь);
|
||||
КлючиДочернихКомпонентов = ПолучитьКлючиКомпонентов(АдресСервера, Токен, КлючКомпонента, СтатусыСтрокой, "", Ложь);
|
||||
Для Каждого КлючДочернегоКомпонента Из КлючиДочернихКомпонентов Цикл
|
||||
КлючиКомпонентов.Добавить(КлючДочернегоКомпонента);
|
||||
КонецЦикла;
|
||||
@@ -459,6 +525,39 @@
|
||||
|
||||
КонецПроцедуры
|
||||
|
||||
// НазначитьЗамечания
|
||||
// Выполняет назначение замечаний на указанного пользователя
|
||||
// Параметры:
|
||||
// АдресСервера - Строка - Адрес (хост) сервера SonarQube
|
||||
// Токен - Строка - Токен пользователя, от имени которого выполняются запросы к API
|
||||
// Замечания - Массив - Ключи замечаний для переназначения
|
||||
// НазначитьНа - Строка - Идентификатор пользователя, на которого необходимо назначить замечание
|
||||
//
|
||||
Процедура НазначитьЗамечания(АдресСервера, Токен, Замечания, НазначитьНа) Экспорт
|
||||
|
||||
URL = СтрШаблон("issues/bulk_change?assign=%1&issues=", НазначитьНа);
|
||||
|
||||
ЗамечанияДляОбработки = Новый Массив();
|
||||
Порция = 500;
|
||||
Для Каждого Замечание Из Замечания Цикл
|
||||
|
||||
Если ЗамечанияДляОбработки.Количество() = Порция Тогда
|
||||
КлючиЗамечаний = СтрСоединить(ЗамечанияДляОбработки, ",");
|
||||
ВыполнитьЗапрос(АдресСервера, Токен, URL + КлючиЗамечаний, "POST");
|
||||
ЗамечанияДляОбработки.Очистить();
|
||||
КонецЕсли;
|
||||
|
||||
ЗамечанияДляОбработки.Добавить(Замечание);
|
||||
|
||||
КонецЦикла;
|
||||
|
||||
Если ЗамечанияДляОбработки.Количество() Тогда
|
||||
КлючиЗамечаний = СтрСоединить(ЗамечанияДляОбработки, ",");
|
||||
ВыполнитьЗапрос(АдресСервера, Токен, URL + КлючиЗамечаний, "POST");
|
||||
КонецЕсли;
|
||||
|
||||
КонецПроцедуры
|
||||
|
||||
// ПолучитьМетрикиПроекта
|
||||
// Возвращает набор метрик проекта
|
||||
// Параметры:
|
||||
@@ -621,22 +720,25 @@
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
Функция ПолучитьКоличествоЗамечанийКомпонента(АдресСервера, Токен, КлючКомпонента, СтатусыСтрокой = "")
|
||||
Функция ПолучитьКоличествоЗамечанийКомпонента(АдресСервера, Токен, КлючКомпонента, СтатусыСтрокой = "", НазначеныНа = "")
|
||||
|
||||
URL = "issues/search?ps=1&componentKeys=" + КлючКомпонента;
|
||||
Если Не ПустаяСтрока(СтатусыСтрокой) Тогда
|
||||
URL = URL + "&statuses=" + СтатусыСтрокой;
|
||||
КонецЕсли;
|
||||
Если Не ПустаяСтрока(НазначеныНа) Тогда
|
||||
URL = URL + "&assignees=" + НазначеныНа;
|
||||
КонецЕсли;
|
||||
ОтветСервера = ВыполнитьЗапрос(АдресСервера, Токен, URL, "GET");
|
||||
|
||||
Возврат ОтветСервера.total;
|
||||
|
||||
КонецФункции
|
||||
|
||||
Функция ПолучитьКлючиКомпонентов(АдресСервера, Токен, КлючКомпонента, СтатусыСтрокой, ТолькоКаталоги = Истина)
|
||||
Функция ПолучитьКлючиКомпонентов(АдресСервера, Токен, КлючКомпонента, СтатусыСтрокой, НазначеныНа = "", ТолькоКаталоги = Истина)
|
||||
|
||||
КлючиКомпонент = Новый СписокЗначений();
|
||||
КоличествоЗамечанийПроекта = ПолучитьКоличествоЗамечанийКомпонента(АдресСервера, Токен, КлючКомпонента, СтатусыСтрокой);
|
||||
КоличествоЗамечанийПроекта = ПолучитьКоличествоЗамечанийКомпонента(АдресСервера, Токен, КлючКомпонента, СтатусыСтрокой, НазначеныНа);
|
||||
Если КоличествоЗамечанийПроекта > МаксимальныйРазмерПорцииДанных Тогда
|
||||
|
||||
URLШаблон = СтрШаблон("components/tree?component=%1%2&ps=500&p=", КлючКомпонента, ?(ТолькоКаталоги, "&qualifiers=DIR", ""));
|
||||
|
||||
Reference in New Issue
Block a user