This commit is contained in:
Maximov Valery
2019-01-18 14:19:25 +03:00
commit 5b168b1551
12 changed files with 948 additions and 0 deletions
+3
View File
@@ -0,0 +1,3 @@
build/
*.log
*.ospx
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018-2019 Maximov Valery aka theshadowco
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+17
View File
@@ -0,0 +1,17 @@
# Sonar Helper
Предоставляет набор утилит, помогающих при работе с SonarQube.
При работе используется REST API SonarQube.
Обращаю внимание, что для выполнения большинства операций необходимы расширенные права пользователя.
## Возможности
На данный момент предоставляются следующие инструменты:
### Закрытие замечаний, привнесенных родительским проектом
Часто возникают ситуации, когда в разных проектах используется общая кодовая база и есть потребность исключить замечания родительского проекта, т.к. исправление их в дочернем самостоятельно не планируется. Переносить руками все замечания достаточно проблематично.
Для закрытия замечаний необходимо вызвать команду `issue-resolver` и передать ей информацию для авторизации, данные родительского и дочерних проектов.
+9
View File
@@ -0,0 +1,9 @@
{
"--token": "2ef785ca946170b7086668132175eb01386943a1",
"--server": "http://my.sonar.server:9000",
"--parent-project": "zarplataiupravleniepersonalomkorp:develop",
"--child-projects": "zarplataiupravleniepersonalomkorp:master,zarplataiupravleniepersonalomprof:develop",
"--exclude-projects": "upravleniepredpriiatiem:develop",
"--statuses": "CLOSED",
"--edt2cfg": false
}
+17
View File
@@ -0,0 +1,17 @@
ПутьКСценариюПараметров = ОбъединитьПути(ТекущийСценарий().Каталог, "src", "Модули", "ПараметрыСистемы.os");
ПараметрыСистемы_ЛокальнаяВерсия = ЗагрузитьСценарий(ПутьКСценариюПараметров);
Описание.Имя(ПараметрыСистемы_ЛокальнаяВерсия.ИмяПродукта())
.Версия(ПараметрыСистемы_ЛокальнаяВерсия.ВерсияПродукта())
.ВерсияСреды("1.0.20")
.ЗависитОт("logos", "1.2.0")
.ЗависитОт("cmdline", "1.0.0")
.ЗависитОт("1commands", "1.3.5")
.ВключитьФайл("src")
.ВключитьФайл("packagedef")
.ВключитьФайл("readme.md")
.ВключитьФайл("LICENSE")
.ВключитьФайл("examples")
.ИсполняемыйФайл("src/main.os", "sonar-helper")
+109
View File
@@ -0,0 +1,109 @@
///////////////////////////////////////////////////////////////////
//
// Рекомендованная структура модуля точки входа приложения
//
///////////////////////////////////////////////////////////////////
#Использовать cmdline
#Использовать logos
#Использовать 1commands
#Использовать "."
///////////////////////////////////////////////////////////////////
Перем Лог;
///////////////////////////////////////////////////////////////////
Процедура Инициализация()
Лог = Логирование.ПолучитьЛог(ПараметрыСистемы.ИмяЛогаСистемы());
МенеджерКомандПриложения.РегистраторКоманд(ПараметрыСистемы);
КонецПроцедуры
Функция ВыполнениеКоманды()
ПараметрыЗапуска = РазобратьАргументыКоманднойСтроки();
Если ПараметрыЗапуска = Неопределено ИЛИ ПараметрыЗапуска.Количество() = 0 Тогда
ВывестиВерсию();
Лог.Ошибка("Некорректные аргументы командной строки");
МенеджерКомандПриложения.ПоказатьСправкуПоКомандам();
Возврат МенеджерКомандПриложения.РезультатыКоманд().ОшибкаВремениВыполнения;
КонецЕсли;
Команда = "";
ЗначенияПараметров = Неопределено;
Если ТипЗнч(ПараметрыЗапуска) = Тип("Структура") Тогда
// это команда
Команда = ПараметрыЗапуска.Команда;
ЗначенияПараметров = ПараметрыЗапуска.ЗначенияПараметров;
Лог.Отладка("Выполняю команду продукта %1", Команда);
ИначеЕсли ЗначениеЗаполнено(ПараметрыСистемы.ИмяКомандыПоУмолчанию()) Тогда
// это команда по-умолчанию
Команда = ПараметрыСистемы.ИмяКомандыПоУмолчанию();
ЗначенияПараметров = ПараметрыЗапуска;
Лог.Отладка("Выполняю команду продукта по умолчанию %1", Команда);
Иначе
ВызватьИсключение "Некорректно настроено имя команды по-умолчанию.";
КонецЕсли;
Если Команда <> ПараметрыСистемы.ИмяКомандыВерсия() Тогда
ВывестиВерсию();
КонецЕсли;
// ДополнитьЗначенияПараметров(Команда, ЗначенияПараметров);
Возврат МенеджерКомандПриложения.ВыполнитьКоманду(Команда, ЗначенияПараметров);
КонецФункции // ВыполнениеКоманды()
Процедура ВывестиВерсию()
Сообщить(СтрШаблон("%1 v%2", ПараметрыСистемы.ИмяПродукта(), ПараметрыСистемы.ВерсияПродукта()));
КонецПроцедуры // ВывестиВерсию()
Функция РазобратьАргументыКоманднойСтроки()
Парсер = ПолучитьПарсерКоманднойСтроки();
Возврат Парсер.Разобрать(АргументыКоманднойСтроки);
КонецФункции // РазобратьАргументыКоманднойСтроки
Функция ПолучитьПарсерКоманднойСтроки()
Парсер = Новый ПарсерАргументовКоманднойСтроки();
МенеджерКомандПриложения.ЗарегистрироватьКоманды(Парсер);
Возврат Парсер;
КонецФункции // ПолучитьПарсерКоманднойСтроки
///////////////////////////////////////////////////////////////////
Инициализация();
Попытка
КодВозврата = ВыполнениеКоманды();
ЗавершитьРаботу(КодВозврата);
Исключение
Лог.КритичнаяОшибка(ОписаниеОшибки());
ЗавершитьРаботу(МенеджерКомандПриложения.РезультатыКоманд().ОшибкаВремениВыполнения);
КонецПопытки;
+28
View File
@@ -0,0 +1,28 @@
///////////////////////////////////////////////////////////////////
//
// Служебный модуль с реализацией работы команды version
//
// Структура модуля реализована в соответствии с рекомендациями
// oscript-app-template (C) EvilBeaver
//
///////////////////////////////////////////////////////////////////
Процедура ЗарегистрироватьКоманду(Знач ИмяКоманды, Знач Парсер) Экспорт
ОписаниеКоманды = Парсер.ОписаниеКоманды(ИмяКоманды, "Выводит версию приложения");
Парсер.ДобавитьКоманду(ОписаниеКоманды);
КонецПроцедуры // ЗарегистрироватьКоманду
// Выполняет логику команды
//
// Параметры:
// ПараметрыКоманды - Соответствие - Соответствие ключей командной строки и их значений
// ДополнительныеПараметры - Соответствие - дополнительные параметры (необязательно)
//
Функция ВыполнитьКоманду(Знач ПараметрыКоманды, Знач ДополнительныеПараметры) Экспорт
Сообщить(ПараметрыСистемы.ВерсияПродукта());
Возврат МенеджерКомандПриложения.РезультатыКоманд().Успех;
КонецФункции // ВыполнитьКоманду
@@ -0,0 +1,226 @@
Перем Лог;
Перем Токен;
Перем АдресСервера;
Перем РодительскийПроект;
Перем ДочерниеПроекты;
Перем ИсключаемыеПроекты;
Перем Статусы;
Перем ИзEDTВКонфигуратор;
///////////////////////////////////////////////////////////////////////////////////////////////////
// Прикладной интерфейс
///////////////////////////////////////////////////////////////////////////////////////////////////
Процедура ЗарегистрироватьКоманду(Знач ИмяКоманды, Знач Парсер) Экспорт
ОписаниеКоманды = Парсер.ОписаниеКоманды(ИмяКоманды, "Выполняет закрытие замечаний (как не требующих исправление) из родительского проекта в дочерних");
Парсер.ДобавитьИменованныйПараметрКоманды(ОписаниеКоманды, "--token", "Токен для авторизации на сервере SonarQube");
Парсер.ДобавитьИменованныйПараметрКоманды(ОписаниеКоманды, "--server", "Адрес сервера SonarQube (например http://my.sonar.server:9000)");
Парсер.ДобавитьИменованныйПараметрКоманды(ОписаниеКоманды, "--parent-project", "Ключ родительского проекта (например bsp:master)");
Парсер.ДобавитьИменованныйПараметрКоманды(ОписаниеКоманды, "--child-projects", "Ключи дочерних проектов, строкой через запятую (например hrm:develop,buh:master).
| Для того, чтобы указать все проекты, необходимо передать #all");
Парсер.ДобавитьИменованныйПараметрКоманды(ОписаниеКоманды, "--exclude-projects", "Ключи дочерних проектов, которые необходимо исключить из обработки");
Парсер.ДобавитьИменованныйПараметрКоманды(ОписаниеКоманды, "--statuses", "Отбор замечаний родительского проекта только соответствующих статусов.
| Необходимые статусы необходимо передавать строкой через запятую.
| Возможные значения:
| OPEN - открытые
| CONFIRMED - подтвержденные:
| REOPENED - переоткрытые
| RESOLVED - решенные
| CLOSED - закрытые
|
| По умолчанию выбираются только RESOLVED и CLOSED");
Парсер.ДобавитьПараметрФлагКоманды(ОписаниеКоманды, "--edt2cfg", "Необходимо использовать тогда, когда родительский проект в формате EDT, а дочерний в формате конфигуратора");
Парсер.ДобавитьИменованныйПараметрКоманды(ОписаниеКоманды, "--cfg-file", "Путь к конфигурационному файлу в формате json (utf-8), свойства объекта соответствуют ключам запуска.
| Пример конфигурационного файла находится в каталоге examples");
Парсер.ДобавитьКоманду(ОписаниеКоманды);
КонецПроцедуры
// Выполняет логику команды
//
// Параметры:
// ПараметрыКоманды - Соответствие - Соответствие ключей командной строки и их значений
// ДополнительныеПараметры - Соответствие - (необязательно) дополнительные параметры
//
Функция ВыполнитьКоманду(Знач ПараметрыКоманды, Знач ДополнительныеПараметры = Неопределено) Экспорт
Лог = ДополнительныеПараметры.Лог;
ОшибокНет = ПрочитатьПараметрыЗапуска(ПараметрыКоманды);
Если НЕ ОшибокНет Тогда
Возврат СообщитьОбОшибке("Ошибка запуска");
КонецЕсли;
Лог.Информация("Получение информации о проектах");
ПроектыSQ = Сонар.ПолучитьПроекты(АдресСервера, Токен);
Лог.Информация("Получение информации о родительском проекте");
ОписаниеРодительскогоПроекта = ПроектыSQ.Получить(РодительскийПроект);
Если ОписаниеРодительскогоПроекта = Неопределено Тогда
Возврат СообщитьОбОшибке(СтрШаблон("Родительский проект `%1` в списке проектов не обнаружен", РодительскийПроект));
КонецЕсли;
Лог.Информация("Получение закрываемых замечаний из родительского проекта");
ЗамечанияРодительскогоПроекта = Сонар.ПолучитьЗамечанияПроекта(
АдресСервера, Токен,
ОписаниеРодительскогоПроекта,
Статусы,
ИзEDTВКонфигуратор);
Если НЕ ЗамечанияРодительскогоПроекта.Количество() Тогда
Лог.Информация("Закрываемых замечаний в родительском проекте нет");
Возврат МенеджерКомандПриложения.РезультатыКоманд().Успех;
КонецЕсли;
Если ДочерниеПроекты.Найти("#all") <> Неопределено Тогда
ДочерниеПроекты.Очистить();
Для Каждого ОписаниеПроекта Из ПроектыSQ Цикл
Если ОписаниеПроекта.Ключ <> РодительскийПроект Тогда
ДочерниеПроекты.Добавить(ОписаниеПроекта.Ключ);
КонецЕсли;
КонецЦикла;
КонецЕсли;
Для Каждого ИсключаемыйПроект Из ИсключаемыеПроекты Цикл
Позиция = ДочерниеПроекты.Найти(СокрЛП(ИсключаемыйПроект));
Если Позиция <> Неопределено Тогда
ДочерниеПроекты.Удалить(Позиция);
КонецЕсли;
КонецЦикла;
Лог.Информация("Закрытие замечаний в дочерних проектах");
Для Каждого ДочернийПроект Из ДочерниеПроекты Цикл
Лог.Информация("Закрытие замечаний в проекте `%1`", ДочернийПроект);
ОписаниеПроекта = ПроектыSQ.Получить(СокрЛП(ДочернийПроект));
Если ОписаниеПроекта = Неопределено Тогда
Лог.Ошибка("Проект `%1` не обнаружен", ДочернийПроект);
Продолжить;
КонецЕсли;
ЗакрываемыеЗамечания = Сонар.ПолучитьЗакрываемыеЗамечания(АдресСервера, Токен, ОписаниеПроекта, ЗамечанияРодительскогоПроекта);
Если ЗакрываемыеЗамечания.Количество() Тогда
Лог.Информация("Для проекта `%1` будет закрыто замечаний: `%2` ", ДочернийПроект, ЗакрываемыеЗамечания.Количество());
Сонар.ЗакрытьЗамечания(АдресСервера, Токен, ЗакрываемыеЗамечания, "Привнесено '" + РодительскийПроект + "'");
КонецЕсли;
КонецЦикла;
Возврат МенеджерКомандПриложения.РезультатыКоманд().Успех;
КонецФункции
///////////////////////////////////////////////////////////////////////////////////////////////////
Функция ПрочитатьПараметрыЗапуска(ПараметрыКоманды)
ОшибокНет = Истина;
Токен = ПараметрыКоманды["--token"];
АдресСервера = ПараметрыКоманды["--server"];
РодительскийПроект = ПараметрыКоманды["--parent-project"];
ДочерниеПроектыСтрокой = ПараметрыКоманды["--child-projects"];
ИсключаемыеПроектыСтрокой = ПараметрыКоманды["--exclude-projects"];
СтатусыСтрокой = ПараметрыКоманды["--statuses"];
ИзEDTВКонфигуратор = ПараметрыКоманды["--edt2cfg"];
ПутьККонфигурационномуФайлу = ПараметрыКоманды["--cfg-file"];
Если ПутьККонфигурационномуФайлу <> Неопределено Тогда
Файл = Новый Файл(ПутьККонфигурационномуФайлу);
Если Файл.Существует() Тогда
ТекстовыйДокумент = Новый ТекстовыйДокумент();
ТекстовыйДокумент.Прочитать(ПутьККонфигурационномуФайлу);
Лог.Отладка("Содержимое конфигурационного файла: %1%2", Символы.ПС, ТекстовыйДокумент.ПолучитьТекст());
JSON = Новый ЧтениеJSON();
JSON.УстановитьСтроку(ТекстовыйДокумент.ПолучитьТекст());
ПараметрыИзФайла = ПрочитатьJSON(JSON, Истина);
Если Токен = Неопределено Тогда
Токен = ПараметрыИзФайла.Получить("--token");
КонецЕсли;
Если АдресСервера = Неопределено Тогда
АдресСервера = ПараметрыИзФайла.Получить("--server");
КонецЕсли;
Если РодительскийПроект = Неопределено Тогда
РодительскийПроект = ПараметрыИзФайла.Получить("--parent-project");
КонецЕсли;
Если ДочерниеПроектыСтрокой = Неопределено Тогда
ДочерниеПроектыСтрокой = ПараметрыИзФайла.Получить("--child-projects");
КонецЕсли;
Если ИсключаемыеПроектыСтрокой = Неопределено Тогда
ИсключаемыеПроектыСтрокой = ПараметрыИзФайла.Получить("--exclude-projects");
КонецЕсли;
Если СтатусыСтрокой = Неопределено Тогда
СтатусыСтрокой = ПараметрыИзФайла.Получить("--statuses");
КонецЕсли;
Если ИзEDTВКонфигуратор = Ложь И ПараметрыИзФайла.Получить("--edt2cfg") <> Неопределено Тогда
ИзEDTВКонфигуратор = ПараметрыИзФайла.Получить("--edt2cfg");
КонецЕсли;
Иначе
Лог.Ошибка("Конфигурационный файл по пути `%1` не обнаружен", ОбернутьЗначениеДляПечати(ПутьККонфигурационномуФайлу));
ОшибокНет = Ложь;
КонецЕсли;
КонецЕсли;
Лог.Отладка("Прочитанные параметры:");
Лог.Отладка(" Токен = `%1`", ОбернутьЗначениеДляПечати(Токен));
Лог.Отладка(" Адрес сервера = `%1`", ОбернутьЗначениеДляПечати(АдресСервера));
Лог.Отладка(" Ключ родительского проекта = `%1`", ОбернутьЗначениеДляПечати(РодительскийПроект));
Лог.Отладка(" Ключ дочерних проектов (строкой) = `%1`", ОбернутьЗначениеДляПечати(ДочерниеПроектыСтрокой));
Лог.Отладка(" Ключ исключаемых проектов (строкой) = `%1`", ОбернутьЗначениеДляПечати(ИсключаемыеПроектыСтрокой));
Лог.Отладка(" Статусы строкой = `%1`", ОбернутьЗначениеДляПечати(СтатусыСтрокой));
Лог.Отладка(" Нужно переводить из EDT = `%1`", ОбернутьЗначениеДляПечати(ИзEDTВКонфигуратор));
Если Не ЗначениеЗаполнено(Токен) Тогда
Лог.Ошибка("Не указан токен для авторизации");
ОшибокНет = Ложь;
КонецЕсли;
Если Не ЗначениеЗаполнено(АдресСервера) Тогда
Лог.Ошибка("Не указан адрес сервера SonarQube");
ОшибокНет = Ложь;
КонецЕсли;
Если Не ЗначениеЗаполнено(РодительскийПроект) Тогда
Лог.Ошибка("Не указан ключ родительского проекта");
ОшибокНет = Ложь;
КонецЕсли;
Если Не ЗначениеЗаполнено(ДочерниеПроектыСтрокой) Тогда
Лог.Ошибка("Не указаны ключ дочерних проектов");
ОшибокНет = Ложь;
Иначе
ДочерниеПроекты = СтрРазделить(ДочерниеПроектыСтрокой, ",", Ложь);
КонецЕсли;
ИсключаемыеПроекты = Новый Массив();
Если ЗначениеЗаполнено(ИсключаемыеПроектыСтрокой) Тогда
ИсключаемыеПроекты = СтрРазделить(ИсключаемыеПроектыСтрокой, ",", Ложь);
КонецЕсли;
ИсключаемыеПроекты.Добавить(СокрЛП(РодительскийПроект));
Если Не ЗначениеЗаполнено(СтатусыСтрокой) Тогда
Статусы = СтрРазделить("RESOLVED,CLOSED", ",", Ложь);
Иначе
Статусы = СтрРазделить(СтатусыСтрокой, ",", Ложь);
КонецЕсли;
Возврат ОшибокНет;
КонецФункции
Функция ОбернутьЗначениеДляПечати(Знач Значение)
Если ЗначениеЗаполнено(Значение) Тогда
Возврат Строка(Значение);
КонецЕсли;
Возврат "<Незаполнено>";
КонецФункции
Функция СообщитьОбОшибке(ТекстОшибки)
Лог.Ошибка(ТекстОшибки);
Возврат МенеджерКомандПриложения.РезультатыКоманд().ОшибкаВремениВыполнения;
КонецФункции
@@ -0,0 +1,54 @@
///////////////////////////////////////////////////////////////////
//
// Служебный модуль с набором методов работы с командами приложения
//
// Структура модуля реализована в соответствии с рекомендациями
// oscript-app-template (C) EvilBeaver
//
///////////////////////////////////////////////////////////////////
Процедура ЗарегистрироватьКоманду(Знач ИмяКоманды, Знач Парсер) Экспорт
ОписаниеКоманды = Парсер.ОписаниеКоманды(ИмяКоманды, "Выводит справку по параметрам");
Парсер.ДобавитьПозиционныйПараметрКоманды(ОписаниеКоманды, "Команда", "Имя команды, для которой выводится справка");
Парсер.ДобавитьКоманду(ОписаниеКоманды);
КонецПроцедуры // ЗарегистрироватьКоманду
// Выполняет логику команды
//
// Параметры:
// ПараметрыКоманды - Соответствие - Соответствие ключей командной строки и их значений
// ДополнительныеПараметры - Соответствие - дополнительные параметры (необязательно)
//
Функция ВыполнитьКоманду(Знач ПараметрыКоманды, Знач Неиспользуется = Неопределено) Экспорт
Парсер = Новый ПарсерАргументовКоманднойСтроки;
МенеджерКомандПриложения.ЗарегистрироватьКоманды(Парсер);
Если ПараметрыКоманды["Команда"] = Неопределено Тогда
ПоказатьВозможныеКоманды(Парсер);
Иначе
ПоказатьСправкуПоКоманде(Парсер, ПараметрыКоманды["Команда"]);
КонецЕсли;
Возврат МенеджерКомандПриложения.РезультатыКоманд().Успех;
КонецФункции // ВыполнитьКоманду
Процедура ПоказатьВозможныеКоманды(Знач Парсер)
Парсер.ВывестиСправкуПоКомандам();
КонецПроцедуры // ПоказатьВозможныеКоманды
Процедура ПоказатьСправкуПоКоманде(Знач Парсер, Знач ИмяКоманды)
Парсер.ВывестиСправкуПоКоманде(ИмяКоманды);
КонецПроцедуры // ПоказатьСправкуПоКоманде
@@ -0,0 +1,108 @@
///////////////////////////////////////////////////////////////////
//
// Служебный модуль с набором методов работы с командами приложения
//
// Структура модуля реализована в соответствии с рекомендациями
// oscript-app-template (C) EvilBeaver
//
///////////////////////////////////////////////////////////////////
#Использовать logos
///////////////////////////////////////////////////////////////////
Перем ИсполнителиКоманд;
Перем РегистраторКоманд;
Перем ДополнительныеПараметры;
///////////////////////////////////////////////////////////////////
Процедура ЗарегистрироватьКоманды(Знач Парсер) Экспорт
КомандыИРеализация = Новый Соответствие;
РегистраторКоманд.ПриРегистрацииКомандПриложения(КомандыИРеализация);
Для Каждого КлючИЗначение Из КомандыИРеализация Цикл
ДобавитьКоманду(КлючИЗначение.Ключ, КлючИЗначение.Значение, Парсер);
КонецЦикла;
КонецПроцедуры // ЗарегистрироватьКоманды
Процедура РегистраторКоманд(Знач ОбъектРегистратор) Экспорт
ИсполнителиКоманд = Новый Соответствие;
РегистраторКоманд = ОбъектРегистратор;
ДополнительныеПараметры = Новый Структура;
ДополнительныеПараметры.Вставить("Лог", Логирование.ПолучитьЛог(ПараметрыСистемы.ИмяЛогаСистемы()));
КонецПроцедуры // РегистраторКоманд
Функция ПолучитьКоманду(Знач ИмяКоманды) Экспорт
КлассРеализации = ИсполнителиКоманд[ИмяКоманды];
Если КлассРеализации = Неопределено Тогда
ВызватьИсключение "Неверная операция. Команда '" + ИмяКоманды + "' не предусмотрена.";
КонецЕсли;
Возврат КлассРеализации;
КонецФункции // ПолучитьКоманду
Функция ВыполнитьКоманду(Знач ИмяКоманды, Знач ПараметрыКоманды) Экспорт
Команда = ПолучитьКоманду(ИмяКоманды);
КодВозврата = Команда.ВыполнитьКоманду(ПараметрыКоманды, ДополнительныеПараметры);
Возврат КодВозврата;
КонецФункции // ВыполнитьКоманду
Процедура ПоказатьСправкуПоКомандам(ИмяКоманды = Неопределено) Экспорт
ПараметрыКоманды = Новый Соответствие;
Если ИмяКоманды <> Неопределено Тогда
ПараметрыКоманды.Вставить("Команда", ИмяКоманды);
КонецЕсли;
ВыполнитьКоманду(ПараметрыСистемы.ВозможныеКоманды().Помощь, ПараметрыКоманды);
КонецПроцедуры // ПоказатьСправкуПоКомандам
Процедура ДобавитьКоманду(Знач ИмяКоманды, Знач КлассРеализации, Знач Парсер)
Попытка
РеализацияКоманды = Новый(КлассРеализации);
РеализацияКоманды.ЗарегистрироватьКоманду(ИмяКоманды, Парсер);
ИсполнителиКоманд.Вставить(ИмяКоманды, РеализацияКоманды);
Исключение
ДополнительныеПараметры.Лог.Ошибка("Не удалось выполнить команду %1 для класса %2", ИмяКоманды, КлассРеализации);
ВызватьИсключение;
КонецПопытки;
КонецПроцедуры
///////////////////////////////////////////////////////////////////
Функция РезультатыКоманд() Экспорт
РезультатыКоманд = Новый Структура;
РезультатыКоманд.Вставить("Успех", 0);
РезультатыКоманд.Вставить("НеверныеПараметры", 5);
РезультатыКоманд.Вставить("ОшибкаВремениВыполнения", 1);
Возврат РезультатыКоманд;
КонецФункции // РезультатыКоманд
Функция КодВозвратаКоманды(Знач Команда) Экспорт
Возврат Число(Команда);
КонецФункции // КодВозвратаКоманды
@@ -0,0 +1,85 @@
///////////////////////////////////////////////////////////////////
//
// Служебный модуль с набором служебных параметров приложения
//
// Структура модуля реализована в соответствии с рекомендациями
// oscript-app-template (C) EvilBeaver
//
///////////////////////////////////////////////////////////////////
Перем ВозможныеКомандыПриложения;
// Возвращает идентификатор лога приложения
//
// Возвращаемое значение:
// Строка - Значение идентификатора лога приложения
//
Функция ИмяЛогаСистемы() Экспорт
Возврат "oscript.app." + ИмяПродукта();
КонецФункции // ИмяЛогаСистемы
// Возвращает текущую версию продукта
//
// Возвращаемое значение:
// Строка - Значение текущей версии продукта
//
Функция ВерсияПродукта() Экспорт
Версия = "1.0.1";
Возврат Версия;
КонецФункции // ВерсияПродукта()
// Возвращает имя продукта
//
// Возвращаемое значение:
// Строка - имя продукта
//
Функция ИмяПродукта() Экспорт
Возврат "sonar-helper";
КонецФункции
Функция ВозможныеКоманды() Экспорт
Если ВозможныеКомандыПриложения = Неопределено Тогда
ВозможныеКомандыПриложения = Новый Структура;
ВозможныеКомандыПриложения.Вставить("Помощь", "help");
ВозможныеКомандыПриложения.Вставить("ПоказатьВерсию", "version");
ВозможныеКомандыПриложения.Вставить("ЗакрытьИшузы", "issue-resolver");
ВозможныеКомандыПриложения = Новый ФиксированнаяСтруктура(ВозможныеКомандыПриложения);
КонецЕсли;
Возврат ВозможныеКомандыПриложения;
КонецФункции
Процедура ПриРегистрацииКомандПриложения(Знач КлассыРеализацииКоманд) Экспорт
КлассыРеализацииКоманд[ВозможныеКоманды().Помощь] = "КомандаСправкаПоПараметрам";
КлассыРеализацииКоманд[ИмяКомандыВерсия()] = "КомандаVersion";
КлассыРеализацииКоманд[ВозможныеКоманды().ЗакрытьИшузы] = "КомандаЗакрытьИшузы";
//...
//КлассыРеализацииКоманд["<имя команды>"] = "<КлассРеализации>";
КонецПроцедуры // ПриРегистрацииКомандПриложения
// Одна из команд может вызываться неявно, без указания команды.
// Иными словами, здесь указывается какой обработчик надо вызывать, если приложение запущено без какой-либо команды
// myapp /home/user/somefile.txt будет аналогично myapp default-action /home/user/somefile.txt
Функция ИмяКомандыПоУмолчанию() Экспорт
Возврат ВозможныеКоманды().Помощь;
КонецФункции
// Возвращает имя команды версия (ключ командной строки)
//
// Возвращаемое значение:
// Строка - имя команды
//
Функция ИмяКомандыВерсия() Экспорт
Возврат ВозможныеКоманды().ПоказатьВерсию;
КонецФункции
+271
View File
@@ -0,0 +1,271 @@
///////////////////////////////////////////////////////////////////
//
// Модуль с набором методов работы с SonarQube
// Используются методы rest-api sonarqube
// (C) TheShadowCo
//
///////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
// Программный интерфейс
///////////////////////////////////////////////////////////////////
// ПолучитьПроекты
// Возвращает набор проектов
// Параметры:
// АдресСервера - Строка - Адрес (хост) сервера SonarQube
// Токен - Строка - Токен пользователя, от имени которого выполняются запросы к API
//
// Возвращаемое значение:
// Соответствие - Коллекция проектов
// * Ключ - Строка - Код (Ключ) проекта
// * Значение - Структура - Описание проекта
// ** Идентификатор - Строка - Идентификатор проекта
// ** Код - Строка - Код (Ключ) проекта
//
Функция ПолучитьПроекты(АдресСервера, Токен) Экспорт
URLШаблон = "components/search?qualifiers=TRK&ps=500&p=%1";
НомерСтраницы = 1;
Проекты = Новый Соответствие();
Пока Истина Цикл
URL = СтрШаблон(URLШаблон, Формат(НомерСтраницы, "ЧГ="));
Ответ = ВыполнитьЗапрос(АдресСервера, Токен, URL, "GET");
Для Каждого ОписаниеПроекта Из Ответ.components Цикл
НовыйПроект = Новый Структура();
НовыйПроект.Вставить("Идентификатор", ОписаниеПроекта.id);
НовыйПроект.Вставить("Код", ОписаниеПроекта.key);
Проекты.Вставить(НовыйПроект.Код, НовыйПроект);
КонецЦикла;
Если БольшеНетДанных(Ответ) Тогда
Прервать;
КонецЕсли;
НомерСтраницы = НомерСтраницы + 1;
КонецЦикла;
Возврат Проекты;
КонецФункции
// ПолучитьЗамечанияПроекта
// Возвращает набор замечаний проекта по установленным отборам
// Параметры:
// АдресСервера - Строка - Адрес (хост) сервера SonarQube
// Токен - Строка - Токен пользователя, от имени которого выполняются запросы к API
// ОписаниеПроекта - Структура - Описание проекта SonarQube
// * Идентификатор - Строка - Идентификатор проекта
// * Код - Строка - Код (Ключ) проекта
// Статусы - Массив - Массив строковых идентификаторов статусов замечаний
// ИзEDTВКонфигуратор - Булево - Признак необходимости преобразования замечаний между родительским проектом и дочерними
//
// Возвращаемое значение:
// Соответствие - Коллекция замечаний
// * Ключ - Строка - Относительный путь к файлу, в котором зафиксировано замечание
// * Значение - Структура - Описание проекта
// ** ПутьКФайлу - Строка - Относительный путь к файлу, в котором зафиксировано замечание
// ** Ошибки - Соответствие - Набор зарегистрированных замечаний (ошибок)
// *** Ключ - Строка - Хэш замечания
// *** Значение - Структура - Описание замечания
// **** ПутьКФайлу - Строка - Относительный путь к файлу, в котором зафиксировано замечание
// **** Код - Строка - Ключ замечания
// **** Хэш - Строка - Хэш замечания
//
Функция ПолучитьЗамечанияПроекта(АдресСервера, Токен, ОписаниеПроекта, Статусы, ИзEDTВКонфигуратор) Экспорт
URLШаблон = "issues/search?ps=500&statuses=%1&projectUuids=%2&p=";
Замечания = Новый Соответствие();
Для Каждого Статус Из Статусы Цикл
НомерСтраницы = 1;
Пока Истина Цикл
URL = СтрШаблон(URLШаблон, ВРег(СокрЛП(Статус)), ОписаниеПроекта.Идентификатор);
Ответ = ВыполнитьЗапрос(АдресСервера, Токен, URL + Формат(НомерСтраницы, "ЧГ="), "GET");
Для Каждого ОписаниеОшибки Из Ответ.issues Цикл
ПутьКФайлу = СтрЗаменить(ОписаниеОшибки.component, ОписаниеПроекта.Код + ":", "");
Если ИзEDTВКонфигуратор Тогда
ПутьКФайлу = СтрЗаменить(ПутьКФайлу, "configuration/src/", "src/configuration/");
ПутьКФайлу = СтрЗаменить(ПутьКФайлу, "/ManagerModule.bsl", "/Ext/ManagerModule.bsl");
ПутьКФайлу = СтрЗаменить(ПутьКФайлу, "/ObjectModule.bsl", "/Ext/ObjectModule.bsl");
ПутьКФайлу = СтрЗаменить(ПутьКФайлу, "/CommandModule.bsl", "/Ext/CommandModule.bsl");
ПутьКФайлу = СтрЗаменить(ПутьКФайлу, "/ValueManagerModule.bsl", "/Ext/ValueManagerModule.bsl");
ПутьКФайлу = СтрЗаменить(ПутьКФайлу, "/configuration/Configuration", "/configuration/Ext");
Если СтрНайти(ПутьКФайлу, "Forms") Тогда
ПутьКФайлу = СтрЗаменить(ПутьКФайлу, "/Module.bsl", "/Ext/Form/Module.bsl");
Иначе
ПутьКФайлу = СтрЗаменить(ПутьКФайлу, "/Module.bsl", "/Ext/Module.bsl");
КонецЕсли;
КонецЕсли;
НовоеОписаниеОшибки = Новый Структура();
НовоеОписаниеОшибки.Вставить("ПутьКФайлу", ПутьКФайлу);
НовоеОписаниеОшибки.Вставить("Код", ОписаниеОшибки.key);
Хэш = ПолучитьХэшЗамечания(ОписаниеОшибки, ПутьКФайлу);
НовоеОписаниеОшибки.Вставить("Хэш", Хэш);
ТекущийМодуль = Замечания.Получить(ПутьКФайлу);
Если ТекущийМодуль = Неопределено Тогда
ТекущийМодуль = Новый Структура("ПутьКФайлу, Ошибки", ПутьКФайлу, Новый Соответствие());
КонецЕсли;
ТекущийМодуль.Ошибки.Вставить(Хэш, НовоеОписаниеОшибки);
Замечания.Вставить(ПутьКФайлу, ТекущийМодуль);
КонецЦикла;
Если БольшеНетДанных(Ответ) Тогда
Прервать;
КонецЕсли;
НомерСтраницы = НомерСтраницы + 1;
КонецЦикла;
КонецЦикла;
Возврат Замечания;
КонецФункции
// ПолучитьЗакрываемыеЗамечания
// Возвращает набор открытых замечаний проекта, которые необходимо закрыть
// Параметры:
// АдресСервера - Строка - Адрес (хост) сервера SonarQube
// Токен - Строка - Токен пользователя, от имени которого выполняются запросы к API
// ОписаниеПроекта - Структура - Описание проекта SonarQube
// * Идентификатор - Строка - Идентификатор проекта
// * Код - Строка - Код (Ключ) проекта
// ЗамечанияРодительскогоПроекта - Соответствие - Замечания для закрытия из родительского проекта. См. ПолучитьЗамечанияПроекта
//
// Возвращаемое значение:
// Соответствие - Коллекция замечаний
// * Ключ - Строка - Хэш замечания
// * Значение - Структура - Описание замечания
// ** ПутьКФайлу - Строка - Относительный путь к файлу, в котором зафиксировано замечание
// ** Код - Строка - Ключ замечания
// ** Хэш - Строка - Хэш замечания
//
Функция ПолучитьЗакрываемыеЗамечания(АдресСервера, Токен, ОписаниеПроекта, ЗамечанияРодительскогоПроекта) Экспорт
URLШаблон = "issues/search?ps=500&statuses=OPEN,CONFIRMED,REOPENED&projectUuids=%1&componentKeys=%2&p=";
Замечания = Новый Соответствие();
Для Каждого МодульСЗмечаниями Из ЗамечанияРодительскогоПроекта Цикл
URL = СтрШаблон(URLШаблон, ОписаниеПроекта.Идентификатор, ОписаниеПроекта.Код + ":" + МодульСЗмечаниями.Ключ);
НомерСтраницы = 1;
Пока Истина Цикл
Ответ = ВыполнитьЗапрос(АдресСервера, Токен, URL + Формат(НомерСтраницы, "ЧГ="), "GET");
Для Каждого ОписаниеОшибки Из Ответ.issues Цикл
ПутьКФайлу = СтрЗаменить(ОписаниеОшибки.component, ОписаниеПроекта.Код + ":", "");
Хэш = ПолучитьХэшЗамечания(ОписаниеОшибки, ПутьКФайлу);
Если МодульСЗмечаниями.Значение.Ошибки.Получить(Хэш) = Неопределено Тогда
Продолжить;
КонецЕсли;
НовоеОписаниеОшибки = Новый Структура();
НовоеОписаниеОшибки.Вставить("ПутьКФайлу", ПутьКФайлу);
НовоеОписаниеОшибки.Вставить("Код", ОписаниеОшибки.key);
НовоеОписаниеОшибки.Вставить("Хэш", Хэш);
Замечания.Вставить(Хэш, НовоеОписаниеОшибки);
КонецЦикла;
Если БольшеНетДанных(Ответ) Тогда
Прервать;
КонецЕсли;
НомерСтраницы = НомерСтраницы + 1;
КонецЦикла;
КонецЦикла;
Возврат Замечания;
КонецФункции
// ЗакрытьЗамечания
// Выполняет закрытие замечаний: устанавливает признак "WONTFIX" со ссылкой на родительский проект
// Параметры:
// АдресСервера - Строка - Адрес (хост) сервера SonarQube
// Токен - Строка - Токен пользователя, от имени которого выполняются запросы к API
// ЗакрываемыеЗамечания - Соответствие - Замечания, которые привнесены из родительского проекта и требуют закрытия. См. ПолучитьЗакрываемыеЗамечания
// Комментарий - Строка - Текстовое сообщение, которое будет добавлено как коментарий к закрываемому замечанию
//
Процедура ЗакрытьЗамечания(АдресСервера, Токен, ЗакрываемыеЗамечания, Комментарий) Экспорт
URL = СтрШаблон("issues/bulk_change?do_transition=wontfix&comment=%1&issues=", Комментарий);
ЗамечанияДляОбработки = Новый Массив();
Для Каждого Замечание Из ЗакрываемыеЗамечания Цикл
Если ЗамечанияДляОбработки.Количество() = 100 Тогда
ВыполнитьЗапрос(АдресСервера, Токен, URL + СтрСоединить(ЗамечанияДляОбработки, ","), "POST");
ЗамечанияДляОбработки.Очистить();
КонецЕсли;
ЗамечанияДляОбработки.Добавить(Замечание.Значение.Идентификатор);
КонецЦикла;
Если ЗамечанияДляОбработки.Количество() Тогда
ВыполнитьЗапрос(АдресСервера, Токен, URL + СтрСоединить(ЗамечанияДляОбработки, ","), "POST");
КонецЕсли;
КонецПроцедуры
///////////////////////////////////////////////////////////////////
// Слубные процедуры и функции
///////////////////////////////////////////////////////////////////
Функция БольшеНетДанных(ОтветСервера)
Возврат ОтветСервера.paging.pageSize * ОтветСервера.paging.pageIndex >= ОтветСервера.paging.total;
КонецФункции
Функция ПолучитьХэшЗамечания(ОписаниеОшибки, ПутьКФайлу)
Возврат ПутьКФайлу + ОписаниеОшибки.rule
+ ?(ОписаниеОшибки.Свойство("textRange"),
"" + ОписаниеОшибки.textRange.startLine + ОписаниеОшибки.textRange.endLine
+ ОписаниеОшибки.textRange.startOffset + ОписаниеОшибки.textRange.endOffset,
"");
КонецФункции
Функция ВыполнитьЗапрос(АдресСервера, Токен, URL, Операция)
HTTPЗапрос = Новый HTTPЗапрос;
HTTPЗапрос.АдресРесурса = "/api/" + URL;
HTTPЗапрос.Заголовки.Вставить("Content-Type", "application/json");
HTTP = Новый HTTPСоединение(АдресСервера, , Токен);
Если Операция = "GET" Тогда
ОтветHTTP = HTTP.Получить(HTTPЗапрос);
Иначе
ОтветHTTP = HTTP.ОтправитьДляОбработки(HTTPЗапрос);
КонецЕсли;
Если ОтветHTTP.КодСостояния = 200 Тогда
json = Новый ЧтениеJSON();
json.УстановитьСтроку(ОтветHTTP.ПолучитьТелоКакСтроку());
Возврат ПрочитатьJson(json);
КонецЕсли;
ВызватьИсключение
"Код ответа: " + ОтветHTTP.КодСостояния + Символы.ПС
+ "Ответ: " + ОтветHTTP.ПолучитьТелоКакСтроку();
КонецФункции