Добавлена команда для переноса замечания на указанного пользователя по набору фильтров

This commit is contained in:
Maximov Valery
2019-07-25 10:55:54 +03:00
parent 0f7a15482a
commit 4cc32aa4fd
5 changed files with 286 additions and 5 deletions
+8
View File
@@ -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
View File
@@ -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", ""));