1. Добавлена команда для формирования отчета по разработчикам

2. Выполнены рефакторинг и исправление ошибок
This commit is contained in:
Maximov Valery
2019-05-15 10:51:46 +03:00
parent 69648abf79
commit 0f7a15482a
9 changed files with 636 additions and 215 deletions
+8 -2
View File
@@ -43,8 +43,14 @@ SonarQube может создавать несколько замечаний п
На данный момент поддерживаются следующие варианты формирования отчета:
- **JSON** - формируется отчет в формате json, метрики выгружаются дважды - для идентификатора метрики и для русского представления. [Пример: examples\example-report.json](examples\example-report.json)
- **HTML** - формируется отчет в формате html, метрики выгнржаются только для русского представления. [Пример: examples\example-report.html](examples\example-report.html)
- **JSON** - формируется отчет в формате json, метрики выгружаются дважды - для идентификатора метрики и для русского представления. [Пример: examples\example-report.json](examples/example-report.json)
- **HTML** - формируется отчет в формате html, метрики выгнржаются только для русского представления. [Пример: examples\example-report.html](examples/example-report.html)
### Сводный отчет по разработчикам
При необходимоси получить отчет по разработчикам (не конкретные замечания, а "температуру") и понять, кто в команде как работает можно вручную собирать информацию по страницам SonarQube, но проще использовать **`sonar-helper`**, вызвав команду **`usr-report`** и проанализировать полученный результат.
На данный момент поддерживается вариант формирования отчета в формате **JSON**. [Пример отчета: examples\example-usr-report.json](examples/example-usr-report.json)
## Примеры
@@ -0,0 +1,8 @@
{
"--token": "2ef785ca946170b7086668132175eb01386943a1",
"--server": "http://my.sonar.server:9000",
"--projects": "bsp,mdm",
"--statuses": "OPEN",
"--report-path": "usr-rep.json",
"--report-format": "JSON"
}
+29
View File
@@ -0,0 +1,29 @@
{
"ДатаФормирования": "2019-05-06T14:17:17.5125591",
"СерверSonarQube": "http:\/\/my.sonar.server:9000",
"Количество": 2,
"Замечания": [
{
"КлючПроекта": "mdm",
"Статус": "OPEN",
"Автор": "my.user@mail.domain",
"Отвественный": "my.user",
"Правило": "RuleCode",
"Критичность": "MAJOR",
"Тип": "BUG",
"Время": 40,
"Количество": 20
},
{
"КлючПроекта": "bsp",
"Статус": "OPEN",
"Автор": "my.user@mail.domain",
"Отвественный": "my.user",
"Правило": "RuleCode2",
"Критичность": "MINOR",
"Тип": "CODE_SMELL",
"Время": 29,
"Количество": 29
}
]
}
@@ -1,15 +1,20 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
//
// Служебный модуль с реализацией работы команды issue-resolver
//
// (C) Maximov Valery (aka theshadowco)
//
///////////////////////////////////////////////////////////////////////////////////////////////////
Перем Лог;
Перем Токен;
Перем АдресСервера;
Перем РодительскийПроект;
Перем ДочерниеПроекты;
Перем ИсключаемыеПроекты;
Перем Статусы;
Перем ИзEDTВКонфигуратор;
Перем Теги;
Перем МаксимальноеКоличествоСтатусов;
Перем ПрочитанныеПараметры;
///////////////////////////////////////////////////////////////////////////////////////////////////
// Прикладной интерфейс
///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -54,15 +59,19 @@
Лог = ДополнительныеПараметры.Лог;
ОшибокНет = ПрочитатьПараметрыЗапуска(ПараметрыКоманды);
Если НЕ ОшибокНет Тогда
Возврат СообщитьОбОшибке("Ошибка запуска");
Возврат ОбщегоНазначения.СообщитьОбОшибке("Ошибка запуска");
КонецЕсли;
АдресСервера = ПрочитанныеПараметры.Получить("АдресСервера");
Токен = ПрочитанныеПараметры.Получить("Токен");
РодительскийПроект = ПрочитанныеПараметры.Получить("РодительскийПроект");
Лог.Информация("Получение информации о проектах");
ПроектыSQ = Сонар.ПолучитьПроекты(АдресСервера, Токен);
Лог.Информация("Получение информации о родительском проекте");
ОписаниеРодительскогоПроекта = ПроектыSQ.Получить(РодительскийПроект);
Если ОписаниеРодительскогоПроекта = Неопределено Тогда
Возврат СообщитьОбОшибке(СтрШаблон("Родительский проект `%1` в списке проектов не обнаружен", РодительскийПроект));
Возврат ОбщегоНазначения.СообщитьОбОшибке(СтрШаблон("Родительский проект `%1` в списке проектов не обнаружен", РодительскийПроект));
КонецЕсли;
Лог.Информация("Получение закрываемых замечаний из родительского проекта");
@@ -70,7 +79,7 @@
АдресСервера, Токен,
ОписаниеРодительскогоПроекта,
СтрСоединить(Статусы, ","),
ИзEDTВКонфигуратор);
ПрочитанныеПараметры.Получить("ИзEDTВКонфигуратор"));
Если НЕ ЗамечанияРодительскогоПроекта.Количество() Тогда
@@ -102,6 +111,7 @@
КонецЦикла;
Лог.Информация("Закрытие замечаний в дочерних проектах");
Теги = ПрочитанныеПараметры.Получить("Теги");
Для Каждого ДочернийПроект Из ДочерниеПроекты Цикл
Лог.Информация("Закрытие замечаний в проекте `%1`", ДочернийПроект);
ОписаниеПроекта = ПроектыSQ.Получить(СокрЛП(ДочернийПроект));
@@ -127,103 +137,33 @@
Функция ПрочитатьПараметрыЗапуска(ПараметрыКоманды)
ПрочитанныеПараметры = ОбщегоНазначения.ПрочитатьПараметрыЗапуска(ПараметрыКоманды, Истина);
ОшибокНет = ПрочитанныеПараметры.Получить("ОшибокНет");
МаксимальноеКоличествоСтатусов = 5;
ОшибокНет = Истина;
Токен = ПараметрыКоманды["--token"];
АдресСервера = ПараметрыКоманды["--server"];
РодительскийПроект = ПараметрыКоманды["--parent-project"];
ДочерниеПроектыСтрокой = ПараметрыКоманды["--child-projects"];
ИсключаемыеПроектыСтрокой = ПараметрыКоманды["--exclude-projects"];
СтатусыСтрокой = ПараметрыКоманды["--statuses"];
Теги = ПараметрыКоманды["--tags"];
ИзEDTВКонфигуратор = ПараметрыКоманды["--edt2cfg"];
ПутьККонфигурационномуФайлу = ПараметрыКоманды["--cfg-file"];
Если ПутьККонфигурационномуФайлу <> Неопределено Тогда
Файл = Новый Файл(ПутьККонфигурационномуФайлу);
Если Файл.Существует() Тогда
ТекстовыйДокумент = Новый ТекстовыйДокумент();
ТекстовыйДокумент.Прочитать(ПутьККонфигурационномуФайлу);
Лог.Отладка("Содержимое конфигурационного файла: %1%2", Символы.ПС, ТекстовыйДокумент.ПолучитьТекст());
JSON = Новый ЧтениеJSON();
JSON.УстановитьСтроку(ТекстовыйДокумент.ПолучитьТекст());
ПараметрыИзФайла = ПрочитатьJSON(JSON, Истина);
Если Токен = Неопределено Тогда
Токен = ПараметрыИзФайла.Получить("--token");
КонецЕсли;
Если АдресСервера = Неопределено Тогда
АдресСервера = ПараметрыИзФайла.Получить("--server");
КонецЕсли;
Если РодительскийПроект = Неопределено Тогда
РодительскийПроект = ПараметрыИзФайла.Получить("--parent-project");
КонецЕсли;
Если ДочерниеПроектыСтрокой = Неопределено Тогда
ДочерниеПроектыСтрокой = ПараметрыИзФайла.Получить("--child-projects");
КонецЕсли;
Если ИсключаемыеПроектыСтрокой = Неопределено Тогда
ИсключаемыеПроектыСтрокой = ПараметрыИзФайла.Получить("--exclude-projects");
КонецЕсли;
Если СтатусыСтрокой = Неопределено Тогда
СтатусыСтрокой = ПараметрыИзФайла.Получить("--statuses");
КонецЕсли;
Если Теги = Неопределено Тогда
Теги = ПараметрыИзФайла.Получить("--tags");
КонецЕсли;
Если ИзEDTВКонфигуратор = Ложь И ПараметрыИзФайла.Получить("--edt2cfg") <> Неопределено Тогда
ИзEDTВКонфигуратор = ПараметрыИзФайла.Получить("--edt2cfg");
КонецЕсли;
Иначе
Лог.Ошибка("Конфигурационный файл по пути `%1` не обнаружен", ОбернутьЗначениеДляПечати(ПутьККонфигурационномуФайлу));
ОшибокНет = Ложь;
КонецЕсли;
КонецЕсли;
Лог.Отладка("Прочитанные параметры:");
Лог.Отладка(" Токен = `%1`", ОбернутьЗначениеДляПечати(Токен));
Лог.Отладка(" Адрес сервера = `%1`", ОбернутьЗначениеДляПечати(АдресСервера));
Лог.Отладка(" Ключ родительского проекта = `%1`", ОбернутьЗначениеДляПечати(РодительскийПроект));
Лог.Отладка(" Ключ дочерних проектов (строкой) = `%1`", ОбернутьЗначениеДляПечати(ДочерниеПроектыСтрокой));
Лог.Отладка(" Ключ исключаемых проектов (строкой) = `%1`", ОбернутьЗначениеДляПечати(ИсключаемыеПроектыСтрокой));
Лог.Отладка(" Статусы строкой = `%1`", ОбернутьЗначениеДляПечати(СтатусыСтрокой));
Лог.Отладка(" Устанавливаемые теги = `%1`", ОбернутьЗначениеДляПечати(Теги));
Лог.Отладка(" Нужно переводить из EDT = `%1`", ОбернутьЗначениеДляПечати(ИзEDTВКонфигуратор));
Если Не ЗначениеЗаполнено(Токен) Тогда
Лог.Ошибка("Не указан токен для авторизации");
ОшибокНет = Ложь;
КонецЕсли;
Если Не ЗначениеЗаполнено(АдресСервера) Тогда
Лог.Ошибка("Не указан адрес сервера SonarQube");
ОшибокНет = Ложь;
КонецЕсли;
Если Не ЗначениеЗаполнено(РодительскийПроект) Тогда
Если Не ЗначениеЗаполнено(ПрочитанныеПараметры.Получить("РодительскийПроект")) Тогда
Лог.Ошибка("Не указан ключ родительского проекта");
ОшибокНет = Ложь;
КонецЕсли;
Если Не ЗначениеЗаполнено(ДочерниеПроектыСтрокой) Тогда
Лог.Ошибка("Не указаны ключ дочерних проектов");
Если Не ЗначениеЗаполнено(ПрочитанныеПараметры.Получить("ДочерниеПроектыСтрокой")) Тогда
Лог.Ошибка("Не указаны ключи дочерних проектов");
ОшибокНет = Ложь;
Иначе
ДочерниеПроекты = СтрРазделить(ДочерниеПроектыСтрокой, ",", Ложь);
ДочерниеПроекты = СтрРазделить(ПрочитанныеПараметры.Получить("ДочерниеПроектыСтрокой"), ", ", Ложь);
КонецЕсли;
ИсключаемыеПроекты = Новый Массив();
Если ЗначениеЗаполнено(ИсключаемыеПроектыСтрокой) Тогда
ИсключаемыеПроекты = СтрРазделить(ИсключаемыеПроектыСтрокой, ",", Ложь);
Если ЗначениеЗаполнено(ПрочитанныеПараметры.Получить("ИсключаемыеПроектыСтрокой")) Тогда
ИсключаемыеПроекты = СтрРазделить(ПрочитанныеПараметры.Получить("ИсключаемыеПроектыСтрокой"), ", ", Ложь);
КонецЕсли;
ИсключаемыеПроекты.Добавить(СокрЛП(РодительскийПроект));
ИсключаемыеПроекты.Добавить(СокрЛП(ПрочитанныеПараметры.Получить("РодительскийПроект")));
Если Не ЗначениеЗаполнено(СтатусыСтрокой) Тогда
Если Не ЗначениеЗаполнено(ПрочитанныеПараметры.Получить("СтатусыСтрокой")) Тогда
Статусы = СтрРазделить("RESOLVED,CLOSED", ",", Ложь);
Иначе
Статусы = Новый Массив();
СтатусыВрем = СтрРазделить(ВРЕГ(СтатусыСтрокой), ",", Ложь);
СтатусыВрем = СтрРазделить(ВРЕГ(ПрочитанныеПараметры.Получить("СтатусыСтрокой")), ", ", Ложь);
ВсеСтатусы = СтрРазделить("OPEN,CONFIRMED,REOPENED,RESOLVED,CLOSED", ",");
Для Каждого Статус Из СтатусыВрем Цикл
Если ВсеСтатусы.Найти(Статус) <> Неопределено Тогда
@@ -237,25 +177,11 @@
ОшибокНет = Ложь;
КонецЕсли;
КонецЕсли;
Если НЕ ЗначениеЗаполнено(Теги) Тогда
Теги = "";
Если НЕ ЗначениеЗаполнено(ПрочитанныеПараметры.Получить("Теги")) Тогда
ПрочитанныеПараметры.Вставить("Теги", "");
КонецЕсли;
Возврат ОшибокНет;
КонецФункции
Функция ОбернутьЗначениеДляПечати(Знач Значение)
Если ЗначениеЗаполнено(Значение) Тогда
Возврат Строка(Значение);
КонецЕсли;
Возврат "<Незаполнено>";
КонецФункции
Функция СообщитьОбОшибке(ТекстОшибки)
Лог.Ошибка(ТекстОшибки);
Возврат МенеджерКомандПриложения.РезультатыКоманд().ОшибкаВремениВыполнения;
КонецФункции
@@ -1,13 +1,19 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
//
// Служебный модуль с реализацией работы команды report
//
// (C) Maximov Valery (aka theshadowco)
//
///////////////////////////////////////////////////////////////////////////////////////////////////
Перем Лог;
Перем Токен;
Перем АдресСервера;
Перем РодительскийПроект;
Перем Проекты;
Перем Метрики;
Перем ПутьКОтчету;
Перем ФорматОтчета;
Перем ПрочитанныеПараметры;
///////////////////////////////////////////////////////////////////////////////////////////////////
// Прикладной интерфейс
///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -17,7 +23,7 @@
ОписаниеКоманды = Парсер.ОписаниеКоманды(ИмяКоманды, "Формирует отчет по проекту/списку проектов");
Парсер.ДобавитьИменованныйПараметрКоманды(ОписаниеКоманды, "--token", "Токен для авторизации на сервере SonarQube");
Парсер.ДобавитьИменованныйПараметрКоманды(ОписаниеКоманды, "--server", "Адрес сервера SonarQube (например http://my.sonar.server:9000)");
Парсер.ДобавитьИменованныйПараметрКоманды(ОписаниеКоманды, "--projects", "Ключ проектов, строкой через запятую (например hrm:develop,buh)");
Парсер.ДобавитьИменованныйПараметрКоманды(ОписаниеКоманды, "--projects", "Ключи проектов, строкой через запятую (например hrm:develop,buh)");
Парсер.ДобавитьИменованныйПараметрКоманды(ОписаниеКоманды, "--total-metrics", "Вывод в отчет метрик по проекту.
| Нужные метрики передаются строкой через запятую.
| Возможные значения (ключ - расшифровка):
@@ -75,20 +81,18 @@
Лог = ДополнительныеПараметры.Лог;
ОшибокНет = ПрочитатьПараметрыЗапуска(ПараметрыКоманды);
Если НЕ ОшибокНет Тогда
Возврат СообщитьОбОшибке("Ошибка запуска");
Возврат ОбщегоНазначения.СообщитьОбОшибке("Ошибка запуска");
КонецЕсли;
Если ПустаяСтрока(ПутьКОтчету) Тогда
ПутьКОтчету = ОбъединитьПути(".", "report." + НРег(ФорматОтчета));
КонецЕсли;
АдресСервера = ПрочитанныеПараметры.Получить("АдресСервера");
Токен = ПрочитанныеПараметры.Получить("Токен");
Лог.Информация("Получение информации о проектах");
ПроектыSQ = Сонар.ПолучитьПроекты(АдресСервера, Токен);
КоллекцияОтчетов = СоздатьКоллекциюОтчетов(АдресСервера);
КоллекцияОтчетов = СоздатьКоллекциюОтчетов();
Лог.Информация("Формирование отчетов по проектам");
КоллекцияПроектов = СтрРазделить(Проекты, ",", Ложь);
КоллекцияПроектов = СтрРазделить(ПрочитанныеПараметры.Получить("Проекты"), ",", Ложь);
Для Каждого Проект Из КоллекцияПроектов Цикл
Лог.Информация(" Формирование отчета для проекта `%1`", Проект);
@@ -115,112 +119,39 @@
Функция ПрочитатьПараметрыЗапуска(ПараметрыКоманды)
МаксимальноеКоличествоСтатусов = 5;
ОшибокНет = Истина;
Токен = ПараметрыКоманды["--token"];
АдресСервера = ПараметрыКоманды["--server"];
Проекты = ПараметрыКоманды["--projects"];
Метрики = ПараметрыКоманды["--total-metrics"];
ПутьКОтчету = ПараметрыКоманды["--report-path"];
ФорматОтчета = ПараметрыКоманды["--report-format"];
ПрочитанныеПараметры = ОбщегоНазначения.ПрочитатьПараметрыЗапуска(ПараметрыКоманды, Истина);
ОшибокНет = ПрочитанныеПараметры.Получить("ОшибокНет");
ПутьККонфигурационномуФайлу = ПараметрыКоманды["--cfg-file"];
Если ПутьККонфигурационномуФайлу <> Неопределено Тогда
Файл = Новый Файл(ПутьККонфигурационномуФайлу);
Если Файл.Существует() Тогда
ТекстовыйДокумент = Новый ТекстовыйДокумент();
ТекстовыйДокумент.Прочитать(ПутьККонфигурационномуФайлу);
Лог.Отладка("Содержимое конфигурационного файла: %1%2", Символы.ПС, ТекстовыйДокумент.ПолучитьТекст());
JSON = Новый ЧтениеJSON();
JSON.УстановитьСтроку(ТекстовыйДокумент.ПолучитьТекст());
ПараметрыИзФайла = ПрочитатьJSON(JSON, Истина);
Если Токен = Неопределено Тогда
Токен = ПараметрыИзФайла.Получить("--token");
КонецЕсли;
Если АдресСервера = Неопределено Тогда
АдресСервера = ПараметрыИзФайла.Получить("--server");
КонецЕсли;
Если Проекты = Неопределено Тогда
Проекты = ПараметрыИзФайла.Получить("--projects");
КонецЕсли;
Если Метрики = Неопределено Тогда
Метрики = ПараметрыИзФайла.Получить("--total-metrics");
КонецЕсли;
Если ПутьКОтчету = Неопределено Тогда
ПутьКОтчету = ПараметрыИзФайла.Получить("--report-path");
КонецЕсли;
Если ФорматОтчета = Неопределено Тогда
ФорматОтчета = ПараметрыИзФайла.Получить("--report-format");
КонецЕсли;
Иначе
Лог.Ошибка("Конфигурационный файл по пути `%1` не обнаружен", ОбернутьЗначениеДляПечати(ПутьККонфигурационномуФайлу));
ОшибокНет = Ложь;
КонецЕсли;
КонецЕсли;
Лог.Отладка("Прочитанные параметры:");
Лог.Отладка(" Токен = `%1`", ОбернутьЗначениеДляПечати(Токен));
Лог.Отладка(" Адрес сервера = `%1`", ОбернутьЗначениеДляПечати(АдресСервера));
Лог.Отладка(" Ключи проектов = `%1`", ОбернутьЗначениеДляПечати(Проекты));
Лог.Отладка(" Метрики проекта = `%1`", ОбернутьЗначениеДляПечати(Метрики));
Лог.Отладка(" Путь к отчету = `%1`", ОбернутьЗначениеДляПечати(ПутьКОтчету));
Лог.Отладка(" Формат отчета = `%1`", ОбернутьЗначениеДляПечати(ФорматОтчета));
Если Не ЗначениеЗаполнено(Токен) Тогда
Лог.Ошибка("Не указан токен для авторизации");
ОшибокНет = Ложь;
КонецЕсли;
Если Не ЗначениеЗаполнено(АдресСервера) Тогда
Лог.Ошибка("Не указан адрес сервера SonarQube");
ОшибокНет = Ложь;
КонецЕсли;
Если Не ЗначениеЗаполнено(Проекты) Тогда
Если Не ЗначениеЗаполнено(ПрочитанныеПараметры.Получить("Проекты")) Тогда
Лог.Ошибка("Не указан ключ(-и) проекта(-ов)");
ОшибокНет = Ложь;
КонецЕсли;
Метрики = ПолучитьПравильныеМетрики(Метрики, ОшибокНет);
Если Не ЗначениеЗаполнено(ПутьКОтчету) Тогда
ПутьКОтчету = "";
КонецЕсли;
Метрики = ПолучитьПравильныеМетрики(ПрочитанныеПараметры.Получить("Метрики"), ОшибокНет);
ПутьКОтчету = ПрочитанныеПараметры.Получить("ПутьКОтчету");
ФорматОтчета = ПрочитанныеПараметры.Получить("ФорматОтчета");
Если Не ЗначениеЗаполнено(ФорматОтчета) Тогда
ФорматОтчета = "JSON";
Иначе
ФорматОтчета = ПолучитьПравильныйФорматОтчета(ФорматОтчета, ОшибокНет);
КонецЕсли;
Если Не ЗначениеЗаполнено(ПутьКОтчету) Тогда
ПутьКОтчету = ОбъединитьПути(".", "report." + НРег(ФорматОтчета));
КонецЕсли;
Возврат ОшибокНет;
КонецФункции
Функция ОбернутьЗначениеДляПечати(Знач Значение)
Если ЗначениеЗаполнено(Значение) Тогда
Возврат Строка(Значение);
КонецЕсли;
Возврат "<Незаполнено>";
КонецФункции
Функция СообщитьОбОшибке(ТекстОшибки)
Лог.Ошибка(ТекстОшибки);
Возврат МенеджерКомандПриложения.РезультатыКоманд().ОшибкаВремениВыполнения;
КонецФункции
Функция ПолучитьПравильныйФорматОтчета(Знач ВыбранныйФорматОтчета, ОшибокНет)
ВРЕГВыбранныйФорматОтчета = ВРЕГ(ВыбранныйФорматОтчета);
Если НЕ (ВРЕГВыбранныйФорматОтчета = "HTML" ИЛИ ВРЕГВыбранныйФорматОтчета = "JSON") Тогда
ОшибокНет = Ложь;
Лог.Ошибка("Указан неизвестный формат отчета `%1`", ОбернутьЗначениеДляПечати(ВыбранныйФорматОтчета));
Лог.Ошибка("Указан неизвестный формат отчета `%1`", ОбщегоНазначения.ОбернутьЗначениеДляПечати(ВыбранныйФорматОтчета));
КонецЕсли;
@@ -243,7 +174,7 @@
ПравильныеМетрики.Вставить(СокрЛП(Метрика), 0);
Иначе
ОшибокНет = Ложь;
Лог.Ошибка("Указана неизвестная метрика `%1`", ОбернутьЗначениеДляПечати(Метрика));
Лог.Ошибка("Указана неизвестная метрика `%1`", ОбщегоНазначения.ОбернутьЗначениеДляПечати(Метрика));
КонецЕсли;
КонецЦикла;
КонецЕсли;
@@ -252,7 +183,7 @@
КонецФункции
Функция СоздатьКоллекциюОтчетов()
Функция СоздатьКоллекциюОтчетов(АдресСервера)
Результат = Новый Структура();
Результат.Вставить("ДатаФормирования", ТекущаяДата());
@@ -0,0 +1,252 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
//
// Служебный модуль с реализацией работы команды report
//
// (C) Maximov Valery (aka theshadowco)
//
///////////////////////////////////////////////////////////////////////////////////////////////////
Перем Лог;
Перем ПутьКОтчету;
Перем ФорматОтчета;
Перем СтатусыСтрокой;
Перем ПрочитанныеПараметры;
///////////////////////////////////////////////////////////////////////////////////////////////////
// Прикладной интерфейс
///////////////////////////////////////////////////////////////////////////////////////////////////
Процедура ЗарегистрироватьКоманду(Знач ИмяКоманды, Знач Парсер) Экспорт
ОписаниеКоманды = Парсер.ОписаниеКоманды(ИмяКоманды, "Формирует сводный отчет по наличию замечаний пользователей");
Парсер.ДобавитьИменованныйПараметрКоманды(ОписаниеКоманды, "--token", "Токен для авторизации на сервере SonarQube");
Парсер.ДобавитьИменованныйПараметрКоманды(ОписаниеКоманды, "--server", "Адрес сервера SonarQube (например http://my.sonar.server:9000)");
Парсер.ДобавитьИменованныйПараметрКоманды(ОписаниеКоманды, "--projects", "Ключи проектов, строкой через запятую (например hrm:develop,buh)");
Парсер.ДобавитьИменованныйПараметрКоманды(ОписаниеКоманды, "--statuses", "Отбор замечаний только соответствующих статусов.
| Необходимые статусы необходимо передавать строкой через запятую.
| Возможные значения:
| OPEN - открытые
| CONFIRMED - подтвержденные:
| REOPENED - переоткрытые
| RESOLVED - решенные
| CLOSED - закрытые
|
| По умолчанию выбираются только OPEN, CONFIRMED и REOPENED");
Парсер.ДобавитьИменованныйПараметрКоманды(ОписаниеКоманды, "--report-path", "Путь для сохранения отчета");
Парсер.ДобавитьИменованныйПараметрКоманды(ОписаниеКоманды, "--report-format", "Формат сохраняемого отчета.
| Возможные варианнты:
| HTML - создает html - страницу
| JSON - выгружает файл json
|
| По умолчанию используется формат JSON");
Парсер.ДобавитьИменованныйПараметрКоманды(ОписаниеКоманды, "--cfg-file", "Путь к конфигурационному файлу в формате json (utf-8), свойства объекта соответствуют ключам запуска.
| Пример конфигурационного файла находится в каталоге examples");
Парсер.ДобавитьКоманду(ОписаниеКоманды);
КонецПроцедуры
// Выполняет логику команды
//
// Параметры:
// ПараметрыКоманды - Соответствие - Соответствие ключей командной строки и их значений
// ДополнительныеПараметры - Соответствие - (необязательно) дополнительные параметры
//
Функция ВыполнитьКоманду(Знач ПараметрыКоманды, Знач ДополнительныеПараметры = Неопределено) Экспорт
Лог = ДополнительныеПараметры.Лог;
ОшибокНет = ПрочитатьПараметрыЗапуска(ПараметрыКоманды);
Если НЕ ОшибокНет Тогда
Возврат ОбщегоНазначения.СообщитьОбОшибке("Ошибка запуска");
КонецЕсли;
АдресСервера = ПрочитанныеПараметры.Получить("АдресСервера");
Токен = ПрочитанныеПараметры.Получить("Токен");
Лог.Информация("Получение информации о проектах");
ПроектыSQ = Сонар.ПолучитьПроекты(АдресСервера, Токен);
КоллекцияОтчетов = СоздатьКоллекциюОтчетов(АдресСервера);
Лог.Информация("Формирование отчетов по проектам");
Проекты = ПрочитанныеПараметры.Получить("Проекты");
Если Не ЗначениеЗаполнено(Проекты) Тогда
Проекты = "";
КонецЕсли;
КоллекцияПроектов = СтрРазделить(Проекты, ",", Ложь);
Замечания = Неопределено;
Для Каждого ОписаниеПроекта Из ПроектыSQ Цикл
Если КоллекцияПроектов.Количество() И КоллекцияПроектов.Найти(ОписаниеПроекта.Значение.Код) = Неопределено Тогда
Продолжить;
КонецЕсли;
Лог.Информация(" Формирование отчета для проекта `%1`", ОписаниеПроекта.Значение.Код);
Замечания = Сонар.ПолучитьСводнуюИнформациюПоЗамечаниямиПроекта(АдресСервера, Токен, ОписаниеПроекта.Значение, СтатусыСтрокой, Замечания);
КонецЦикла;
КоллекцияОтчетов.Замечания = Замечания;
КоллекцияОтчетов.Количество = КоллекцияОтчетов.Замечания.Количество();
Лог.Информация("Сохранение отчетов в файл '%1'", ПутьКОтчету);
СформироватьОтчет(КоллекцияОтчетов);
Возврат МенеджерКомандПриложения.РезультатыКоманд().Успех;
КонецФункции
///////////////////////////////////////////////////////////////////////////////////////////////////
Функция ПрочитатьПараметрыЗапуска(ПараметрыКоманды)
ПрочитанныеПараметры = ОбщегоНазначения.ПрочитатьПараметрыЗапуска(ПараметрыКоманды, Истина);
ОшибокНет = ПрочитанныеПараметры.Получить("ОшибокНет");
МаксимальноеКоличествоСтатусов = 5;
Если Не ЗначениеЗаполнено(ПрочитанныеПараметры.Получить("СтатусыСтрокой")) Тогда
СтатусыСтрокой = "OPEN,CONFIRMED,REOPENED";
Иначе
Статусы = Новый Массив();
СтатусыВрем = СтрРазделить(ВРЕГ(ПрочитанныеПараметры.Получить("СтатусыСтрокой")), ",", Ложь);
ВсеСтатусы = СтрРазделить("OPEN,CONFIRMED,REOPENED,RESOLVED,CLOSED", ",");
Для Каждого Статус Из СтатусыВрем Цикл
Если ВсеСтатусы.Найти(Статус) <> Неопределено Тогда
Статусы.Добавить(Статус);
Иначе
Лог.Ошибка("Неопознанный статус `%1`", Статус);
КонецЕсли;
КонецЦикла;
Если Статусы.Количество() = 0 Тогда
Лог.Ошибка("Указанный фильтр по статусам не содержит корректных значений");
ОшибокНет = Ложь;
КонецЕсли;
СтатусыСтрокой = СтрСоединить(Статусы, ",");
КонецЕсли;
ПутьКОтчету = ПрочитанныеПараметры.Получить("ПутьКОтчету");
ФорматОтчета = ПрочитанныеПараметры.Получить("ФорматОтчета");
Если Не ЗначениеЗаполнено(ФорматОтчета) Тогда
ФорматОтчета = "JSON";
Иначе
ФорматОтчета = ПолучитьПравильныйФорматОтчета(ФорматОтчета, ОшибокНет);
КонецЕсли;
Если Не ЗначениеЗаполнено(ПутьКОтчету) Тогда
ПутьКОтчету = ОбъединитьПути(".", "report." + НРег(ФорматОтчета));
КонецЕсли;
Возврат ОшибокНет;
КонецФункции
Функция ПолучитьПравильныйФорматОтчета(Знач ВыбранныйФорматОтчета, ОшибокНет)
ВРЕГВыбранныйФорматОтчета = ВРЕГ(ВыбранныйФорматОтчета);
Если ВРЕГВыбранныйФорматОтчета <> "JSON" Тогда
ОшибокНет = Ложь;
Лог.Ошибка("Указан неизвестный формат отчета `%1`", ОбщегоНазначения.ОбернутьЗначениеДляПечати(ВыбранныйФорматОтчета));
КонецЕсли;
Возврат ВРЕГВыбранныйФорматОтчета;
КонецФункции
Функция СоздатьКоллекциюОтчетов(АдресСервера)
Результат = Новый Структура();
Результат.Вставить("ДатаФормирования", ТекущаяДата());
Результат.Вставить("СерверSonarQube", АдресСервера);
Результат.Вставить("Количество", 0);
Результат.Вставить("Замечания", Неопределено);
Возврат Результат;
КонецФункции
Процедура СформироватьОтчет(КоллекцияОтчетов)
Если ФорматОтчета = "JSON" Тогда
ЗаписьJSON = Новый ЗаписьJSON();
ЗаписьJSON.ОткрытьФайл(ПутьКОтчету);
КоллекцияОтчетов.Замечания = ТаблицаЗначенийВМассив(КоллекцияОтчетов.Замечания);
ЗаписатьJSON(ЗаписьJSON, КоллекцияОтчетов);
ЗаписьJSON.Закрыть();
КонецЕсли;
КонецПроцедуры
Функция ТаблицаЗначенийВМассив(ТаблицаЗначений, РезультатВФиксированнуюКоллекцию = Ложь)
МассивРезультат = Новый Массив();
СтруктураСтрокой = "";
НоваяСтрока = Неопределено;
КолонкиСТипомТЧ = Новый Массив;
Если ТипЗнч(ТаблицаЗначений) = Тип("ТаблицаЗначений") Тогда
КолонкиТаблицы = ТаблицаЗначений.Колонки;
ИначеЕсли ТипЗнч(ТаблицаЗначений) = Тип("Массив") И ТипЗнч(ТаблицаЗначений[0]) = Тип("СтрокаТаблицыЗначений") Тогда
КолонкиТаблицы = ТаблицаЗначений[0].Владелец().Колонки;
Иначе
ВызватьИсключение "Не поддерживаемый тип параметра";
КонецЕсли;
Если ТаблицаЗначений.Количество() = 0 Тогда
Возврат МассивРезультат;
КонецЕсли;
Для Каждого Колонка Из КолонкиТаблицы Цикл
СтруктураСтрокой = СтруктураСтрокой + ?(ПустаяСтрока(СтруктураСтрокой), "", ",") + Колонка.Имя ;
КонецЦикла;
Для Каждого Строка Из ТаблицаЗначений Цикл
НоваяСтрока = Новый Структура(СтруктураСтрокой);
ЗаполнитьЗначенияСвойств(НоваяСтрока, Строка);
Для Каждого КолонкаСТипомТЧ Из КолонкиСТипомТЧ Цикл
Если ТипЗнч(Строка[КолонкаСТипомТЧ]) = Тип("ТаблицаЗначений") Тогда
НоваяСтрока[КолонкаСТипомТЧ] = ТаблицаЗначенийВМассив(Строка[КолонкаСТипомТЧ], РезультатВФиксированнуюКоллекцию);
КонецЕсли;
КонецЦикла;
Если РезультатВФиксированнуюКоллекцию Тогда
НоваяСтрока = Новый ФиксированнаяСтруктура(НоваяСтрока);
КонецЕсли;
МассивРезультат.Добавить(НоваяСтрока);
КонецЦикла;
Если РезультатВФиксированнуюКоллекцию Тогда
МассивРезультат = Новый ФиксированныйМассив(МассивРезультат);
КонецЕсли;
Возврат МассивРезультат;
КонецФункции // ТаблицаЗначенийВМассив
@@ -0,0 +1,148 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
//
// Служебный модуль с общими методами приложения
//
// (C) Maximov Valery (aka theshadowco)
//
///////////////////////////////////////////////////////////////////////////////////////////////////
// ОбернутьЗначениеДляПечати
// Формирует строку из значения для удобной печати
// Параметры:
// Значение - Произвольное - Значение, которое необходимо преобразовать в строку для последующей печати
//
// Возвращаемое значение:
// Строка - Преобразованное в строку входное значение. Если значение не заполнено, то вернется "<Незаполнено>"
//
Функция ОбернутьЗначениеДляПечати(Знач Значение) Экспорт
Если ЗначениеЗаполнено(Значение) Тогда
Возврат Строка(Значение);
КонецЕсли;
Возврат "<Незаполнено>";
КонецФункции
// ПрочитатьПараметрыЗапуска
// Читает входные параметры включа конфигурационный файл
// Параметры:
// ПараметрыКоманды - Соответствие - Входные параметры приложения
// ВыполнятьПроверкуАвторизацииСразу - Булево - Выполнение проверки корректности параметров авторизации
//
// Возвращаемое значение:
// Соответствие - Ключи и значения параметров запуска
//
Функция ПрочитатьПараметрыЗапуска(ПараметрыКоманды, ВыполнятьПроверкуАвторизацииСразу) Экспорт
Лог = Логирование.ПолучитьЛог(ПараметрыСистемы.ИмяЛогаСистемы());
ПрочитанныеПараметры = Новый Соответствие();
ОшибокНет = Истина;
ВозможныеКлючи = ВозможныеКлючи();
Для Каждого ВозможныйКлюч Из ВозможныеКлючи Цикл
ПрочитанныеПараметры.Вставить(ВозможныйКлюч.Ключ, ПараметрыКоманды.Получить(ВозможныйКлюч.Значение));
КонецЦикла;
ПутьККонфигурационномуФайлу = ПараметрыКоманды["--cfg-file"];
Если ПутьККонфигурационномуФайлу <> Неопределено Тогда
Файл = Новый Файл(ПутьККонфигурационномуФайлу);
Если Файл.Существует() Тогда
ТекстовыйДокумент = Новый ТекстовыйДокумент();
ТекстовыйДокумент.Прочитать(ПутьККонфигурационномуФайлу);
Лог.Отладка("Содержимое конфигурационного файла: %1%2", Символы.ПС, ТекстовыйДокумент.ПолучитьТекст());
JSON = Новый ЧтениеJSON();
JSON.УстановитьСтроку(ТекстовыйДокумент.ПолучитьТекст());
ПараметрыИзФайла = ПрочитатьJSON(JSON, Истина);
Для Каждого ВозможныйКлюч Из ВозможныеКлючи Цикл
ЗначениеИзФайла = ПараметрыИзФайла.Получить(ВозможныйКлюч.Значение);
Если ЗначениеИзФайла <> Неопределено И ПрочитанныеПараметры.Получить(ВозможныйКлюч.Ключ) = Неопределено Тогда
ПрочитанныеПараметры.Вставить(ВозможныйКлюч.Ключ, ЗначениеИзФайла);
КонецЕсли;
КонецЦикла;
Иначе
Лог.Ошибка("Конфигурационный файл по пути `%1` не обнаружен", ОбернутьЗначениеДляПечати(ПутьККонфигурационномуФайлу));
ОшибокНет = ЛОЖЬ;
КонецЕсли;
КонецЕсли;
Лог.Отладка("Прочитанные параметры:");
Для Каждого ПрочитанныйПараметр Из ПрочитанныеПараметры Цикл
Лог.Отладка(" %2 = `%1`", ОбернутьЗначениеДляПечати(ПрочитанныйПараметр.Значение), ПрочитанныйПараметр.Ключ);
КонецЦикла;
Если ВыполнятьПроверкуАвторизацииСразу Тогда
Если Не ЗначениеЗаполнено(ПрочитанныеПараметры.Получить("Токен")) Тогда
Лог.Ошибка("Не указан токен для авторизации");
ОшибокНет = Ложь;
КонецЕсли;
Если Не ЗначениеЗаполнено(ПрочитанныеПараметры.Получить("АдресСервера")) Тогда
Лог.Ошибка("Не указан адрес сервера SonarQube");
ОшибокНет = Ложь;
КонецЕсли;
КонецЕсли;
ПрочитанныеПараметры.Вставить("ОшибокНет", ОшибокНет);
Возврат ПрочитанныеПараметры;
КонецФункции
// СообщитьОбОшибке
// Выводит сообщение об ошибке и возвращает статус ошибочного завершения приложения
// Параметры:
// ТекстОшибки - Строка - Выводимое сообщение об ошибке
//
// Возвращаемое значение:
// Число - Код ошибки выполнения
//
Функция СообщитьОбОшибке(ТекстОшибки) Экспорт
Лог = Логирование.ПолучитьЛог(ПараметрыСистемы.ИмяЛогаСистемы());
Лог.Ошибка(ТекстОшибки);
Возврат МенеджерКомандПриложения.РезультатыКоманд().ОшибкаВремениВыполнения;
КонецФункции
///////////////////////////////////////////////////////////////////////////////////////////////////
Функция ВозможныеКлючи()
ВозможныеКлючи = Новый Структура();
ВозможныеКлючи.Вставить("Токен", "--token");
ВозможныеКлючи.Вставить("АдресСервера", "--server");
ВозможныеКлючи.Вставить("РодительскийПроект", "--parent-project");
ВозможныеКлючи.Вставить("ИсключаемыеПроектыСтрокой", "--exclude-projects");
ВозможныеКлючи.Вставить("СтатусыСтрокой", "--statuses");
ВозможныеКлючи.Вставить("Теги", "--tags");
ВозможныеКлючи.Вставить("ИзEDTВКонфигуратор", "--edt2cfg");
ВозможныеКлючи.Вставить("Проекты", "--projects");
ВозможныеКлючи.Вставить("Метрики", "--total-metrics");
ВозможныеКлючи.Вставить("ПутьКОтчету", "--report-path");
ВозможныеКлючи.Вставить("ФорматОтчета", "--report-format");
Возврат ВозможныеКлючи;
КонецФункции
@@ -50,6 +50,7 @@
ВозможныеКомандыПриложения.Вставить("ПоказатьВерсию", "version");
ВозможныеКомандыПриложения.Вставить("ЗакрытьИшузы", "issue-resolver");
ВозможныеКомандыПриложения.Вставить("СгенерироватьОтчет", "report");
ВозможныеКомандыПриложения.Вставить("СгенерироватьОтчетПоПользователям", "usr-report");
ВозможныеКомандыПриложения = Новый ФиксированнаяСтруктура(ВозможныеКомандыПриложения);
@@ -61,12 +62,11 @@
Процедура ПриРегистрацииКомандПриложения(Знач КлассыРеализацииКоманд) Экспорт
КлассыРеализацииКоманд[ВозможныеКоманды().Помощь] = "КомандаСправкаПоПараметрам";
КлассыРеализацииКоманд[ИмяКомандыВерсия()] = "КомандаVersion";
КлассыРеализацииКоманд[ВозможныеКоманды().ЗакрытьИшузы] = "КомандаЗакрытьИшузы";
КлассыРеализацииКоманд[ВозможныеКоманды().СгенерироватьОтчет] = "КомандаСгенерироватьОтчет";
//...
//КлассыРеализацииКоманд["<имя команды>"] = "<КлассРеализации>";
КлассыРеализацииКоманд[ВозможныеКоманды().Помощь] = "КомандаСправкаПоПараметрам";
КлассыРеализацииКоманд[ИмяКомандыВерсия()] = "КомандаVersion";
КлассыРеализацииКоманд[ВозможныеКоманды().ЗакрытьИшузы] = "КомандаЗакрытьИшузы";
КлассыРеализацииКоманд[ВозможныеКоманды().СгенерироватьОтчет] = "КомандаСгенерироватьОтчет";
КлассыРеализацииКоманд[ВозможныеКоманды().СгенерироватьОтчетПоПользователям] = "КомандаСгенерироватьОтчетПоПользователям";
КонецПроцедуры // ПриРегистрацииКомандПриложения
+122 -1
View File
@@ -176,6 +176,127 @@
КонецФункции
// ПолучитьСводнуюИнформациюПоЗамечаниямиПроекта
// Возвращает свернутую таблицу с пользователями и их замечаниями на проекте проекта
// Параметры:
// АдресСервера - Строка - Адрес (хост) сервера SonarQube
// Токен - Строка - Токен пользователя, от имени которого выполняются запросы к API
// ОписаниеПроекта - Структура - Описание проекта SonarQube
// * Идентификатор - Строка - Идентификатор проекта
// * Код - Строка - Код (Ключ) проекта
// СтатусыСтрокой - Строка - Строка с идентификаторами статусов замечаний
// Замечания - ТаблицаЗначений - Таблица со сводной информацией замечаний, аналогичная выходной. Используется при необходимости дополнять для нескольких проектов
//
// Возвращаемое значение:
// ТаблицаЗначения - Содвная таблица с замечаниями
// * КлючПроекта - Строка - Ключ проекта sonarqube
// * Статус - Строка - Статус замечания
// * Автор - Строка - Пользователь, автор замечания по git (email)
// * Отвественный - Строка, NULL - Пользователь, на которого назначено замечание (учетная запись)
// * Правило - Строка - Ключ правила
// * Критичность - Строка - Критичность замечания
// * Тип - Строка - Тип замечания
// * Время - Число - Время на исправление замечания (в минутах)
// * Количество - Число - Количество замечаний
//
Функция ПолучитьСводнуюИнформациюПоЗамечаниямиПроекта(АдресСервера, Токен, ОписаниеПроекта, СтатусыСтрокой, Замечания = Неопределено) Экспорт
КлючиКомпонентов = ПолучитьКлючиКомпонентов(АдресСервера, Токен, ОписаниеПроекта.Код, СтатусыСтрокой);
URLШаблон = "issues/search?ps=500&componentKeys=%1%2";
Если Не ПустаяСтрока(СтатусыСтрокой) Тогда
URLШаблон = URLШаблон + "&statuses=" + СтатусыСтрокой;
КонецЕсли;
URLШаблон = URLШаблон + "&p=";
КоличествоКомпонентов = КлючиКомпонентов.Количество();
Если Замечания = Неопределено Тогда
Замечания = Новый ТаблицаЗначений();
Замечания.Колонки.Добавить("КлючПроекта");
Замечания.Колонки.Добавить("Статус");
Замечания.Колонки.Добавить("Автор");
Замечания.Колонки.Добавить("Отвественный");
Замечания.Колонки.Добавить("Правило");
Замечания.Колонки.Добавить("Критичность");
Замечания.Колонки.Добавить("Тип");
Замечания.Колонки.Добавить("Время");
Замечания.Колонки.Добавить("Количество");
КонецЕсли;
Для Ит = 0 По КоличествоКомпонентов - 1 Цикл
КлючКомпонента = КлючиКомпонентов[Ит];
НомерСтраницы = 1;
URL = СтрШаблон(URLШаблон, КлючКомпонента, "");
Пока Истина Цикл
Ответ = ВыполнитьЗапрос(АдресСервера, Токен, URL + Формат(НомерСтраницы, "ЧГ="), "GET");
Если Ответ.total > МаксимальныйРазмерПорцииДанных Тогда
// прочитаем компоненты, перенесем их в общий список, а по текущем прочтем только те, что висят именно на нем
КлючиДочернихКомпонентов = ПолучитьКлючиКомпонентов(АдресСервера, Токен, КлючКомпонента, СтатусыСтрокой, Ложь);
Для Каждого КлючДочернегоКомпонента Из КлючиДочернихКомпонентов Цикл
КлючиКомпонентов.Добавить(КлючДочернегоКомпонента);
КонецЦикла;
КоличествоКомпонентов = КлючиКомпонентов.Количество();
URL = СтрШаблон(URLШаблон, КлючКомпонента, "&onComponentOnly=true");
Ответ = ВыполнитьЗапрос(АдресСервера, Токен, URL + Формат(НомерСтраницы, "ЧГ="), "GET");
КонецЕсли;
Для Каждого ОписаниеОшибки Из Ответ.issues Цикл
Замечание = Замечания.Добавить();
Замечание.КлючПроекта = ОписаниеПроекта.Код;
Замечание.Автор = ОписаниеОшибки.author;
Если Не ОписаниеОшибки.Свойство("assignee") Тогда
Замечание.Отвественный = NULL;
Иначе
Замечание.Отвественный = ОписаниеОшибки.assignee;
КонецЕсли;
Замечание.Правило = ОписаниеОшибки.rule;
Замечание.Статус = ОписаниеОшибки.status;
Замечание.Критичность = ОписаниеОшибки.severity;
Замечание.Тип = ОписаниеОшибки.type;
Замечание.Количество = 1;
Замечание.Время = 0;
Если ОписаниеОшибки.Свойство("debt") Тогда
ВремяСтрокой = СтрЗаменить(ОписаниеОшибки.debt, "min", "");
Поз = СтрНайти(ВремяСтрокой, "h");
Если Поз <> СтрДлина(ВремяСтрокой) Тогда
ВремяСтрокой = СтрЗаменить(ВремяСтрокой, "h", "*60+");
Иначе
ВремяСтрокой = СтрЗаменить(ВремяСтрокой, "h", "*60");
КонецЕсли;
Поз = СтрНайти(ВремяСтрокой, "d");
Если Поз <> СтрДлина(ВремяСтрокой) Тогда
ВремяСтрокой = СтрЗаменить(ВремяСтрокой, "d", "*480+"); // рабочие дни
Иначе
ВремяСтрокой = СтрЗаменить(ВремяСтрокой, "d", "*480");
КонецЕсли;
Замечание.Время = Вычислить(ВремяСтрокой);
КонецЕсли;
КонецЦикла;
Если БольшеНетДанных(Ответ) Тогда
Прервать;
КонецЕсли;
НомерСтраницы = НомерСтраницы + 1;
КонецЦикла;
КонецЦикла;
Замечания.Свернуть("КлючПроекта, Автор, Отвественный, Правило, Критичность, Тип, Статус", "Время, Количество");
Возврат Замечания;
КонецФункции
// ЗаполнитьКоличествоОдинаковыхЗамечанийПроекта
// По сформированному набору замечаний дополняет общее количество замечаний со всеми статусами с тем же хэшем
// Параметры:
@@ -474,7 +595,6 @@
HTTPЗапрос = Новый HTTPЗапрос;
HTTPЗапрос.АдресРесурса = Префикс + "api/" + URL;
Сообщить(HTTPЗапрос.АдресРесурса);
HTTPЗапрос.Заголовки.Вставить("Content-Type", "application/json");
HTTP = Новый HTTPСоединение(АдресСервера, , Токен);
@@ -485,6 +605,7 @@
КонецЕсли;
Если ОтветHTTP.КодСостояния = 200 Тогда
// Сообщить(ОтветHTTP.ПолучитьТелоКакСтроку());
json = Новый ЧтениеJSON();
json.УстановитьСтроку(ОтветHTTP.ПолучитьТелоКакСтроку());
Возврат ПрочитатьJson(json);