mirror of
https://github.com/firstBitMarksistskaya/jenkins-lib.git
synced 2025-02-08 14:29:15 +02:00
Merge branch 'develop'
This commit is contained in:
commit
44e479711a
29
README.md
29
README.md
@ -21,10 +21,9 @@
|
|||||||
|
|
||||||
1. Для шага подготовки требуется любой агент с меткой `agent`.
|
1. Для шага подготовки требуется любой агент с меткой `agent`.
|
||||||
1. Для запуска шага анализа SonarQube требуется агент с меткой `sonar`.
|
1. Для запуска шага анализа SonarQube требуется агент с меткой `sonar`.
|
||||||
1. Для запуска шагов, работающих с EDT (валидация, трансформация формата исходников) требуется агент с меткой `edt` и агент с меткой `oscript` (для трансформации результатов с помощью библиотеки [stebi](https://github.com/Stepa86/stebi)).
|
1. Для запуска шагов, работающих с EDT (валидация, трансформация формата исходников) требуется агент с меткой `edt` (если используется несколько версий EDT необходимо к метке добавить версию, например `edt@2021.3.4:x86_64`) и агент с меткой `oscript`, на котором глобально установлена библиотека [stebi](https://github.com/Stepa86/stebi) версии 1.9.1 или новее.
|
||||||
1. Для запуска шагов, работающих с 1С (подготовка, синтаксический контроль и т.д.) требуется агент с меткой, совпадающей со значением в поле `v8version` файла конфигурации.
|
1. Для запуска шагов, работающих с 1С (подготовка, синтаксический контроль и т.д.) требуется агент с меткой, совпадающей со значением в поле `v8version` файла конфигурации.
|
||||||
1. В качестве ИБ используется файловая база, создаваемая в каталоге `./build/ib`. При необходимости вы можете создать пользователей на фазе инициализации ИБ.
|
1. В качестве ИБ используется файловая база, создаваемая в каталоге `./build/ib`. При необходимости вы можете создать пользователей на фазе инициализации ИБ.
|
||||||
1. Шаг "Дымовые тесты" пока пустой.
|
|
||||||
|
|
||||||
## Возможности
|
## Возможности
|
||||||
|
|
||||||
@ -40,6 +39,7 @@
|
|||||||
1. Запуск валидации проекта средствами EDT и конвертация отчета в формате generic issues.
|
1. Запуск валидации проекта средствами EDT и конвертация отчета в формате generic issues.
|
||||||
1. Запуск статического анализа для SonarQube.
|
1. Запуск статического анализа для SonarQube.
|
||||||
1. Публикация результатов junit и Allure в интерфейс Jenkins.
|
1. Публикация результатов junit и Allure в интерфейс Jenkins.
|
||||||
|
1. Рассылка результатов сборки на почту и в Telegram.
|
||||||
1. Конфигурирование логгера запускаемых oscript-приложений.
|
1. Конфигурирование логгера запускаемых oscript-приложений.
|
||||||
|
|
||||||
## Подключение
|
## Подключение
|
||||||
@ -77,6 +77,7 @@ pipeline1C()
|
|||||||
Пример переопределения:
|
Пример переопределения:
|
||||||
|
|
||||||
* указывается точная версия платформы (и соответственно метка агента, см. ограничения)
|
* указывается точная версия платформы (и соответственно метка агента, см. ограничения)
|
||||||
|
* указывается точная версия модуля EDT (и соответственно метка агента, см. ограничения)
|
||||||
* идентификаторы credentials для пути к хранилищу и к паре логин/пароль для авторизации в хранилище (необходимы, если применяются шаги, работающие с информационной базой)
|
* идентификаторы credentials для пути к хранилищу и к паре логин/пароль для авторизации в хранилище (необходимы, если применяются шаги, работающие с информационной базой)
|
||||||
* включаются шаги запуска статического анализа SonarQube, валидации средствами EDT и синтаксического контроля
|
* включаются шаги запуска статического анализа SonarQube, валидации средствами EDT и синтаксического контроля
|
||||||
|
|
||||||
@ -84,6 +85,7 @@ pipeline1C()
|
|||||||
{
|
{
|
||||||
"$schema": "https://raw.githubusercontent.com/firstBitSemenovskaya/jenkins-lib/master/resources/schema.json",
|
"$schema": "https://raw.githubusercontent.com/firstBitSemenovskaya/jenkins-lib/master/resources/schema.json",
|
||||||
"v8version": "8.3.14.1976",
|
"v8version": "8.3.14.1976",
|
||||||
|
"edtVersion": "2021.3.4:x86_64",
|
||||||
"secrets": {
|
"secrets": {
|
||||||
"storagePath": "f7b21c02-711a-4883-81c5-d429454e3f8b",
|
"storagePath": "f7b21c02-711a-4883-81c5-d429454e3f8b",
|
||||||
"storage" : "c1fc5f33-67d4-493f-a2a4-97d3040e4b8c"
|
"storage" : "c1fc5f33-67d4-493f-a2a4-97d3040e4b8c"
|
||||||
@ -104,12 +106,15 @@ pipeline1C()
|
|||||||
|
|
||||||
* Общее:
|
* Общее:
|
||||||
* В качестве маски версии платформы используется строка "8.3" (`v8version`).
|
* В качестве маски версии платформы используется строка "8.3" (`v8version`).
|
||||||
|
* По-умолчанию версия модуля EDT не заполнена, т.к. в случае единственной версии для утилиты ring дополнительного указания не требуется (`edtVersion`).
|
||||||
* Исходники конфигурации ожидаются в каталоге `src/cf` (`srcDir`).
|
* Исходники конфигурации ожидаются в каталоге `src/cf` (`srcDir`).
|
||||||
* Формат исходников - выгрузка из Конфигуратора (`sourceFormat`).
|
* Формат исходников - выгрузка из Конфигуратора (`sourceFormat`).
|
||||||
* Ветка по умолчанию (для комбинированного режима загрузки конфигурации) - "main" (`defaultBranch`).
|
* Ветка по умолчанию (для комбинированного режима загрузки конфигурации) - "main" (`defaultBranch`).
|
||||||
* Имена "секретов" (jenkins credentials, `secrets`) по умолчанию высчитываются из пути к git-репозиторию (без учета домена, с заменой `/` на `_`) с прибавлением ключа секрета. Например, для репозитория https://github.com/firstBitSemenovskaya/jenkins-lib секрет с адресом хранилища будет выглядеть как `firstBitSemenovskaya_jenkins-lib_STORAGE_PATH`. Ключи секретов:
|
* Имена большинства "секретов" (jenkins credentials, `secrets`) по умолчанию высчитываются из пути к git-репозиторию (без учета домена, с заменой `/` на `_`) с прибавлением ключа секрета. Например, для репозитория https://github.com/firstBitSemenovskaya/jenkins-lib секрет с адресом хранилища будет выглядеть как `firstBitSemenovskaya_jenkins-lib_STORAGE_PATH`. Ключи секретов:
|
||||||
* `STORAGE_PATH` - путь к хранилищу конфигурации (для `secrets` -> `storagePath`);
|
* `STORAGE_PATH` - путь к хранилищу конфигурации (для `secrets` -> `storagePath`);
|
||||||
* `STORAGE_USER` - параметры авторизации в хранилище вида "username with password" (для `secrets` -> `storage`).
|
* `STORAGE_USER` - параметры авторизации в хранилище вида "username with password" (для `secrets` -> `storage`).
|
||||||
|
* `TELEGRAM_CHAT_ID` - идентификатор чата Telegram для рассылки уведомлений и результате сборки вида "secret text" (для `secrets` -> `telegramChatId`).
|
||||||
|
* Секрет `TELEGRAM_BOT_TOKEN` задается глобально на весь сервер Jenkins, либо может быть переопределен (`secrets` -> `telegramBotToken`)
|
||||||
* Все "шаги" по умолчанию выключены (`stages`).
|
* Все "шаги" по умолчанию выключены (`stages`).
|
||||||
* Если в корне репозитория существует файл `packagedef`, то в шагах, работающих с информационной базой, будет выполнена попытка установки локальных зависимостей средствами `opm`.
|
* Если в корне репозитория существует файл `packagedef`, то в шагах, работающих с информационной базой, будет выполнена попытка установки локальных зависимостей средствами `opm`.
|
||||||
* Если после установки локальных зависимостей в каталоге `oscript_modules/bin` существует файл `vrunner`, то для выполнения команд работы с информационной базой будет использоваться он, а не глобально установленный `vrunner` из `PATH`.
|
* Если после установки локальных зависимостей в каталоге `oscript_modules/bin` существует файл `vrunner`, то для выполнения команд работы с информационной базой будет использоваться он, а не глобально установленный `vrunner` из `PATH`.
|
||||||
@ -143,6 +148,20 @@ pipeline1C()
|
|||||||
* Предполагается наличие единственной настройки `SonarQube installation` (`sonarqube` -> `sonarQubeInstallation`).
|
* Предполагается наличие единственной настройки `SonarQube installation` (`sonarqube` -> `sonarQubeInstallation`).
|
||||||
* Используется `sonar-scanner` из переменной окружения `PATH` (`sonarqube` -> `useSonarScannerFromPath`).
|
* Используется `sonar-scanner` из переменной окружения `PATH` (`sonarqube` -> `useSonarScannerFromPath`).
|
||||||
* Если использование `sonar-scanner` из переменной окружения `PATH` выключено, предполагается наличие настроенного глобального инструмента `SonarQube Scanner` с идентификатором инструмента `sonar-scanner` (`sonarqube` -> `sonarScannerToolName`).
|
* Если использование `sonar-scanner` из переменной окружения `PATH` выключено, предполагается наличие настроенного глобального инструмента `SonarQube Scanner` с идентификатором инструмента `sonar-scanner` (`sonarqube` -> `sonarScannerToolName`).
|
||||||
* Если разработка ведется с использованием подсистемы [БСП "Обновление версии ИБ"](https://its.1c.ru/db/bsp315doc#content:4:1:issogl1_обновление_версии_иб), то в значение параметра `sonar.projectVersion=$configurationVersion` утилиты `sonar-scanner` можно передавать версию из созданного общего модуля.
|
* Применяется расчет аргументов командной строки для работы [`branch plugin`](https://github.com/mc1arke/sonarqube-community-branch-plugin) или коммерческих версий SonarQube (`sonarqube` -> `branchAnalysisConfiguration`).
|
||||||
Для этого необходимо заполнить параметр (`sonarqube` -> `infoBaseUpdateModuleName`). Если параметр не заполнен, версия передается из корня конфигурации.
|
* Если разработка ведется с использованием подсистемы [БСП "Обновление версии ИБ"](https://its.1c.ru/db/bsp315doc#content:4:1:issogl1_обновление_версии_иб), то в значение параметра `sonar.projectVersion=$configurationVersion` утилиты `sonar-scanner` можно передавать версию из созданного общего модуля. Для этого необходимо заполнить параметр (`sonarqube` -> `infoBaseUpdateModuleName`). Если параметр не заполнен, версия передается из корня конфигурации.
|
||||||
|
* По умолчанию шаг анализа не дожидается окончания фонового задания на сервере SonarQube и не анализирует результат прохождения Порога качества (`sonarqube` -> `waitForQualityGate`).
|
||||||
* Если выполнялась валидация EDT, результаты валидации в формате `generic issues` передаются утилите `sonar-scanner` как значение параметра `sonar.externalIssuesReportPaths`.
|
* Если выполнялась валидация EDT, результаты валидации в формате `generic issues` передаются утилите `sonar-scanner` как значение параметра `sonar.externalIssuesReportPaths`.
|
||||||
|
* Рассылка уведомлений:
|
||||||
|
* Электронная почта:
|
||||||
|
* Для отправки используется плагин [`email-ext`](https://plugins.jenkins.io/email-ext). Шаблоны сообщений конфигурируются в настройках плагина.
|
||||||
|
* Уведомления о результатах сборки по умолчанию рассылаются только при полном падении сборочной линии (`notifications` -> `email` -> `onAlways`, `onFailure`, `onUnstable`, `onSuccess`).
|
||||||
|
* Лог сборки прикладывается к письму при полном падении сборочной линии и при отправке в режиме "всегда отправлять" (`notifications` -> `email` -> `*options` -> `attachLog`).
|
||||||
|
* В качестве получателей писем (`notifications` -> `email` -> `*options` -> `recipientProviders`) в различных режимах отправки используются:
|
||||||
|
* всегда - разработчики и запустивший сборку;
|
||||||
|
* при падении - разработчики, запустивший сборку и подозреваемый в причине падения сборки;
|
||||||
|
* при успехе - разработчики и запустивший сборку;
|
||||||
|
* при нестабильной сборке (упавшие тесты) - разработчики и запустивший сборку.
|
||||||
|
* Прямые получатели уведомлений не заполнены (`notifications` -> `email` -> `*options` -> `directRecipients`).
|
||||||
|
* Telegram:
|
||||||
|
* Уведомления о результатах сборки по умолчанию рассылаются всегда (`notifications` -> `telegram` -> `onAlways`, `onFailure`, `onUnstable`, `onSuccess`).
|
@ -80,6 +80,7 @@ sharedLibrary {
|
|||||||
dependency("org.jenkins-ci.plugins", "pipeline-build-step", "2.12")
|
dependency("org.jenkins-ci.plugins", "pipeline-build-step", "2.12")
|
||||||
dependency("org.jenkins-ci.plugins", "pipeline-utility-steps", "2.8.0")
|
dependency("org.jenkins-ci.plugins", "pipeline-utility-steps", "2.8.0")
|
||||||
dependency("org.jenkins-ci.plugins", "git", "4.4.4")
|
dependency("org.jenkins-ci.plugins", "git", "4.4.4")
|
||||||
|
dependency("org.jenkins-ci.plugins", "http_request", "1.15")
|
||||||
dependency("org.6wind.jenkins", "lockable-resources", "2.7")
|
dependency("org.6wind.jenkins", "lockable-resources", "2.7")
|
||||||
dependency("ru.yandex.qatools.allure", "allure-jenkins-plugin", "2.28.1")
|
dependency("ru.yandex.qatools.allure", "allure-jenkins-plugin", "2.28.1")
|
||||||
val declarativePluginsVersion = "1.6.0"
|
val declarativePluginsVersion = "1.6.0"
|
||||||
@ -87,5 +88,6 @@ sharedLibrary {
|
|||||||
dependency("org.jenkinsci.plugins", "pipeline-model-declarative-agent", "1.1.1")
|
dependency("org.jenkinsci.plugins", "pipeline-model-declarative-agent", "1.1.1")
|
||||||
dependency("org.jenkinsci.plugins", "pipeline-model-definition", declarativePluginsVersion)
|
dependency("org.jenkinsci.plugins", "pipeline-model-definition", declarativePluginsVersion)
|
||||||
dependency("org.jenkinsci.plugins", "pipeline-model-extensions", declarativePluginsVersion)
|
dependency("org.jenkinsci.plugins", "pipeline-model-extensions", declarativePluginsVersion)
|
||||||
|
dependency("io.jenkins.blueocean", "blueocean-pipeline-api-impl", "1.25.3")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
{
|
{
|
||||||
"$schema": "schema.json",
|
"$schema": "schema.json",
|
||||||
"v8version": "8.3",
|
"v8version": "8.3",
|
||||||
|
"edtVersion": "",
|
||||||
"srcDir": "src/cf",
|
"srcDir": "src/cf",
|
||||||
"sourceFormat": "designer",
|
"sourceFormat": "designer",
|
||||||
"defaultBranch": "main",
|
"defaultBranch": "main",
|
||||||
"secrets": {
|
"secrets": {
|
||||||
"storagePath": "UNKNOWN_ID",
|
"storagePath": "UNKNOWN_ID",
|
||||||
"storage": "UNKNOWN_ID"
|
"storage": "UNKNOWN_ID",
|
||||||
|
"telegramBotToken": "UNKNOWN_ID",
|
||||||
|
"telegramChatId": "UNKNOWN_ID"
|
||||||
},
|
},
|
||||||
"stages": {
|
"stages": {
|
||||||
"initSteps": false,
|
"initSteps": false,
|
||||||
@ -14,7 +17,9 @@
|
|||||||
"bdd": false,
|
"bdd": false,
|
||||||
"syntaxCheck": false,
|
"syntaxCheck": false,
|
||||||
"edtValidate": false,
|
"edtValidate": false,
|
||||||
"smoke": false
|
"smoke": false,
|
||||||
|
"email": false,
|
||||||
|
"telegram": false
|
||||||
},
|
},
|
||||||
"timeout": {
|
"timeout": {
|
||||||
"smoke": 240,
|
"smoke": 240,
|
||||||
@ -43,7 +48,9 @@
|
|||||||
"sonarQubeInstallation": "",
|
"sonarQubeInstallation": "",
|
||||||
"useSonarScannerFromPath": true,
|
"useSonarScannerFromPath": true,
|
||||||
"sonarScannerToolName": "sonar-scanner",
|
"sonarScannerToolName": "sonar-scanner",
|
||||||
"infoBaseUpdateModuleName" : ""
|
"infoBaseUpdateModuleName" : "",
|
||||||
|
"branchAnalysisConfiguration": "fromEnv",
|
||||||
|
"waitForQualityGate": false
|
||||||
},
|
},
|
||||||
"syntaxCheck": {
|
"syntaxCheck": {
|
||||||
"groupErrorsByMetadata": true,
|
"groupErrorsByMetadata": true,
|
||||||
@ -74,5 +81,52 @@
|
|||||||
"removeSupport": true,
|
"removeSupport": true,
|
||||||
"supportLevel": 0
|
"supportLevel": 0
|
||||||
},
|
},
|
||||||
|
"notifications": {
|
||||||
|
"email": {
|
||||||
|
"onAlways": false,
|
||||||
|
"onFailure": true,
|
||||||
|
"onUnstable": false,
|
||||||
|
"onSuccess": false,
|
||||||
|
"alwaysOptions": {
|
||||||
|
"attachLog": true,
|
||||||
|
"directRecipients": [],
|
||||||
|
"recipientProviders": [
|
||||||
|
"developers",
|
||||||
|
"requestor"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"failureOptions": {
|
||||||
|
"attachLog": true,
|
||||||
|
"directRecipients": [],
|
||||||
|
"recipientProviders": [
|
||||||
|
"developers",
|
||||||
|
"requestor",
|
||||||
|
"brokenBuildSuspects"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"successOptions": {
|
||||||
|
"attachLog": false,
|
||||||
|
"directRecipients": [],
|
||||||
|
"recipientProviders": [
|
||||||
|
"developers",
|
||||||
|
"requestor"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unstableOptions": {
|
||||||
|
"attachLog": false,
|
||||||
|
"directRecipients": [],
|
||||||
|
"recipientProviders": [
|
||||||
|
"developers",
|
||||||
|
"requestor"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"telegram": {
|
||||||
|
"onAlways": true,
|
||||||
|
"onFailure": false,
|
||||||
|
"onUnstable": false,
|
||||||
|
"onSuccess": false
|
||||||
|
}
|
||||||
|
},
|
||||||
"logosConfig": ""
|
"logosConfig": ""
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,10 @@
|
|||||||
"type" : "string",
|
"type" : "string",
|
||||||
"description" : "Версия платформы 1С:Предприятие в формате 8.3.хх.хххх."
|
"description" : "Версия платформы 1С:Предприятие в формате 8.3.хх.хххх."
|
||||||
},
|
},
|
||||||
|
"edtVersion" : {
|
||||||
|
"type" : "string",
|
||||||
|
"description" : "Версия модуля 1C:Enterprise Development Tools формате xxxx.x.x:x86_64"
|
||||||
|
},
|
||||||
"srcDir" : {
|
"srcDir" : {
|
||||||
"type" : "string",
|
"type" : "string",
|
||||||
"description" : "Путь к корневому каталогу с исходниками конфигурации, в случае хранения исходников в формате EDT, необходимо указать путь к проекту"
|
"description" : "Путь к корневому каталогу с исходниками конфигурации, в случае хранения исходников в формате EDT, необходимо указать путь к проекту"
|
||||||
@ -31,6 +35,14 @@
|
|||||||
"storage" : {
|
"storage" : {
|
||||||
"type" : "string",
|
"type" : "string",
|
||||||
"description" : "Данные авторизации в хранилище конфигурации"
|
"description" : "Данные авторизации в хранилище конфигурации"
|
||||||
|
},
|
||||||
|
"telegramChatId" : {
|
||||||
|
"type" : "string",
|
||||||
|
"description" : "Идентификатор telegram-чата для отправки уведомлений"
|
||||||
|
},
|
||||||
|
"telegramBotToken" : {
|
||||||
|
"type" : "string",
|
||||||
|
"description" : "Токен авторизации telegram-бота для отправки уведомлений"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -62,6 +74,14 @@
|
|||||||
"bdd" : {
|
"bdd" : {
|
||||||
"type" : "boolean",
|
"type" : "boolean",
|
||||||
"description" : "Запуск BDD сценариев включен"
|
"description" : "Запуск BDD сценариев включен"
|
||||||
|
},
|
||||||
|
"email" : {
|
||||||
|
"type" : "boolean",
|
||||||
|
"description" : "Выполнять рассылку результатов сборки на email"
|
||||||
|
},
|
||||||
|
"telegram" : {
|
||||||
|
"type" : "boolean",
|
||||||
|
"description" : "Выполнять рассылку результатов сборки в telegram"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -118,7 +138,7 @@
|
|||||||
},
|
},
|
||||||
"initInfobase" : {
|
"initInfobase" : {
|
||||||
"type" : "object",
|
"type" : "object",
|
||||||
"id" : "urn:jsonschema:ru:pulsar:jenkins:library:configuration:InitInfobaseOptions",
|
"id" : "urn:jsonschema:ru:pulsar:jenkins:library:configuration:InitInfoBaseOptions",
|
||||||
"description" : "Настройки шага инициализации ИБ",
|
"description" : "Настройки шага инициализации ИБ",
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"initMethod" : {
|
"initMethod" : {
|
||||||
@ -173,6 +193,15 @@
|
|||||||
"infoBaseUpdateModuleName" : {
|
"infoBaseUpdateModuleName" : {
|
||||||
"type" : "string",
|
"type" : "string",
|
||||||
"description" : "Имя общего модуля (например, ОбновлениеИнформационнойБазыXXX), в котором указана версия библиотеки.\n Версия должна задаваться в виде присвоения `Описание.Версия = \"ваш номер версии\";`\n "
|
"description" : "Имя общего модуля (например, ОбновлениеИнформационнойБазыXXX), в котором указана версия библиотеки.\n Версия должна задаваться в виде присвоения `Описание.Версия = \"ваш номер версии\";`\n "
|
||||||
|
},
|
||||||
|
"branchAnalysisConfiguration" : {
|
||||||
|
"type" : "string",
|
||||||
|
"description" : "Вариант конфигурации branch plugin.\n Поддерживаемые варианты:\n * auto - применяется автоконфигурация sonar-scanner силами branchplugin. Так же может применяться для отключения конфигурирования, если branch plugin отсутствует;\n * fromEnv - применяется ручная конфигурация sonar-scanner на основе переменных среды.\n Значение по умолчанию: fromEnv.",
|
||||||
|
"enum" : [ "auto", "fromEnv" ]
|
||||||
|
},
|
||||||
|
"waitForQualityGate" : {
|
||||||
|
"type" : "boolean",
|
||||||
|
"description" : "Ожидать состояние Quality Gate от SonarQube после загрузки анализа. По умолчанию `false`.\n Таймаут ожидания состояния равен таймауту шага.\n "
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -244,6 +273,93 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"notifications" : {
|
||||||
|
"type" : "object",
|
||||||
|
"id" : "urn:jsonschema:ru:pulsar:jenkins:library:configuration:NotificationsOptions",
|
||||||
|
"description" : "Настройки рассылки результатов сборки",
|
||||||
|
"properties" : {
|
||||||
|
"email" : {
|
||||||
|
"type" : "object",
|
||||||
|
"id" : "urn:jsonschema:ru:pulsar:jenkins:library:configuration:notification:EmailNotificationOptions",
|
||||||
|
"description" : "Настройки рассылки результатов сборки через email",
|
||||||
|
"properties" : {
|
||||||
|
"onAlways" : {
|
||||||
|
"type" : "boolean",
|
||||||
|
"description" : "Отправлять всегда"
|
||||||
|
},
|
||||||
|
"onSuccess" : {
|
||||||
|
"type" : "boolean",
|
||||||
|
"description" : "Отправлять при успешной сборке"
|
||||||
|
},
|
||||||
|
"onFailure" : {
|
||||||
|
"type" : "boolean",
|
||||||
|
"description" : "Отправлять при падении сборки"
|
||||||
|
},
|
||||||
|
"onUnstable" : {
|
||||||
|
"type" : "boolean",
|
||||||
|
"description" : "Отправлять при нестабильной сборке"
|
||||||
|
},
|
||||||
|
"alwaysOptions" : {
|
||||||
|
"type" : "object",
|
||||||
|
"id" : "urn:jsonschema:ru:pulsar:jenkins:library:configuration:notification:email:EmailExtConfiguration",
|
||||||
|
"properties" : {
|
||||||
|
"attachLog" : {
|
||||||
|
"type" : "boolean"
|
||||||
|
},
|
||||||
|
"directRecipients" : {
|
||||||
|
"type" : "array",
|
||||||
|
"items" : {
|
||||||
|
"type" : "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"recipientProviders" : {
|
||||||
|
"type" : "array",
|
||||||
|
"items" : {
|
||||||
|
"type" : "string",
|
||||||
|
"enum" : [ "developers", "requestor", "brokenBuildSuspects", "brokenTestsSuspects" ]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"successOptions" : {
|
||||||
|
"type" : "object",
|
||||||
|
"$ref" : "urn:jsonschema:ru:pulsar:jenkins:library:configuration:notification:email:EmailExtConfiguration"
|
||||||
|
},
|
||||||
|
"failureOptions" : {
|
||||||
|
"type" : "object",
|
||||||
|
"$ref" : "urn:jsonschema:ru:pulsar:jenkins:library:configuration:notification:email:EmailExtConfiguration"
|
||||||
|
},
|
||||||
|
"unstableOptions" : {
|
||||||
|
"type" : "object",
|
||||||
|
"$ref" : "urn:jsonschema:ru:pulsar:jenkins:library:configuration:notification:email:EmailExtConfiguration"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"telegram" : {
|
||||||
|
"type" : "object",
|
||||||
|
"id" : "urn:jsonschema:ru:pulsar:jenkins:library:configuration:notification:TelegramNotificationOptions",
|
||||||
|
"description" : "Настройки рассылки результатов сборки через telegram",
|
||||||
|
"properties" : {
|
||||||
|
"onAlways" : {
|
||||||
|
"type" : "boolean",
|
||||||
|
"description" : "Отправлять всегда"
|
||||||
|
},
|
||||||
|
"onSuccess" : {
|
||||||
|
"type" : "boolean",
|
||||||
|
"description" : "Отправлять при успешной сборке"
|
||||||
|
},
|
||||||
|
"onFailure" : {
|
||||||
|
"type" : "boolean",
|
||||||
|
"description" : "Отправлять при падении сборки"
|
||||||
|
},
|
||||||
|
"onUnstable" : {
|
||||||
|
"type" : "boolean",
|
||||||
|
"description" : "Отправлять при нестабильной сборке"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"logosConfig" : {
|
"logosConfig" : {
|
||||||
"type" : "string",
|
"type" : "string",
|
||||||
"description" : "Конфигурация библиотеки logos. Применяется перед запуском каждой стадии сборки"
|
"description" : "Конфигурация библиотеки logos. Применяется перед запуском каждой стадии сборки"
|
||||||
|
@ -27,12 +27,12 @@ contributor(ctx) {
|
|||||||
method(name: 'library', type: 'Object', namedParams: [parameter(name: 'identifier', type: 'java.lang.String'), parameter(name: 'changelog', type: 'java.lang.Boolean'), parameter(name: 'retriever', type: 'Map'),], doc: 'Load a shared library on the fly')
|
method(name: 'library', type: 'Object', namedParams: [parameter(name: 'identifier', type: 'java.lang.String'), parameter(name: 'changelog', type: 'java.lang.Boolean'), parameter(name: 'retriever', type: 'Map'),], doc: 'Load a shared library on the fly')
|
||||||
method(name: 'libraryResource', type: 'Object', params: [resource: 'java.lang.String'], doc: 'Load a resource file from a shared library')
|
method(name: 'libraryResource', type: 'Object', params: [resource: 'java.lang.String'], doc: 'Load a resource file from a shared library')
|
||||||
method(name: 'libraryResource', type: 'Object', namedParams: [parameter(name: 'resource', type: 'java.lang.String'), parameter(name: 'encoding', type: 'java.lang.String'),], doc: 'Load a resource file from a shared library')
|
method(name: 'libraryResource', type: 'Object', namedParams: [parameter(name: 'resource', type: 'java.lang.String'), parameter(name: 'encoding', type: 'java.lang.String'),], doc: 'Load a resource file from a shared library')
|
||||||
method(name: 'lock', type: 'Object', params: [resource: java.lang.String, body: 'Closure'], doc: 'Lock shared resource')
|
method(name: 'lock', type: 'Object', params: [resource: String, body: 'Closure'], doc: 'Lock shared resource')
|
||||||
method(name: 'lock', type: 'Object', params: [body: Closure], namedParams: [parameter(name: 'resource', type: 'java.lang.String'), parameter(name: 'extra', type: 'Map'), parameter(name: 'inversePrecedence', type: 'boolean'), parameter(name: 'label', type: 'java.lang.String'), parameter(name: 'quantity', type: 'int'), parameter(name: 'variable', type: 'java.lang.String'),], doc: 'Lock shared resource')
|
method(name: 'lock', type: 'Object', params: [body: Closure], namedParams: [parameter(name: 'resource', type: 'java.lang.String'), parameter(name: 'extra', type: 'Map'), parameter(name: 'inversePrecedence', type: 'boolean'), parameter(name: 'label', type: 'java.lang.String'), parameter(name: 'quantity', type: 'int'), parameter(name: 'variable', type: 'java.lang.String'),], doc: 'Lock shared resource')
|
||||||
method(name: 'mail', type: 'Object', namedParams: [parameter(name: 'subject', type: 'java.lang.String'), parameter(name: 'body', type: 'java.lang.String'), parameter(name: 'bcc', type: 'java.lang.String'), parameter(name: 'cc', type: 'java.lang.String'), parameter(name: 'charset', type: 'java.lang.String'), parameter(name: 'from', type: 'java.lang.String'), parameter(name: 'mimeType', type: 'java.lang.String'), parameter(name: 'replyTo', type: 'java.lang.String'), parameter(name: 'to', type: 'java.lang.String'),], doc: 'Mail')
|
method(name: 'mail', type: 'Object', namedParams: [parameter(name: 'subject', type: 'java.lang.String'), parameter(name: 'body', type: 'java.lang.String'), parameter(name: 'bcc', type: 'java.lang.String'), parameter(name: 'cc', type: 'java.lang.String'), parameter(name: 'charset', type: 'java.lang.String'), parameter(name: 'from', type: 'java.lang.String'), parameter(name: 'mimeType', type: 'java.lang.String'), parameter(name: 'replyTo', type: 'java.lang.String'), parameter(name: 'to', type: 'java.lang.String'),], doc: 'Mail')
|
||||||
method(name: 'milestone', type: 'Object', params: [ordinal: 'java.lang.Integer'], doc: 'The milestone step forces all builds to go through in order')
|
method(name: 'milestone', type: 'Object', params: [ordinal: 'java.lang.Integer'], doc: 'The milestone step forces all builds to go through in order')
|
||||||
method(name: 'milestone', type: 'Object', namedParams: [parameter(name: 'ordinal', type: 'java.lang.Integer'), parameter(name: 'label', type: 'java.lang.String'),], doc: 'The milestone step forces all builds to go through in order')
|
method(name: 'milestone', type: 'Object', namedParams: [parameter(name: 'ordinal', type: 'java.lang.Integer'), parameter(name: 'label', type: 'java.lang.String'),], doc: 'The milestone step forces all builds to go through in order')
|
||||||
method(name: 'node', type: 'Object', params: [label: java.lang.String, body: 'Closure'], doc: 'Allocate node')
|
method(name: 'node', type: 'Object', params: [label: String, body: 'Closure'], doc: 'Allocate node')
|
||||||
method(name: 'nodesByLabel', type: 'Object', params: [label: 'java.lang.String'], doc: 'List of nodes by Label, by default excludes offline nodes.')
|
method(name: 'nodesByLabel', type: 'Object', params: [label: 'java.lang.String'], doc: 'List of nodes by Label, by default excludes offline nodes.')
|
||||||
method(name: 'nodesByLabel', type: 'Object', namedParams: [parameter(name: 'label', type: 'java.lang.String'), parameter(name: 'offline', type: 'boolean'),], doc: 'List of nodes by Label, by default excludes offline nodes.')
|
method(name: 'nodesByLabel', type: 'Object', namedParams: [parameter(name: 'label', type: 'java.lang.String'), parameter(name: 'offline', type: 'boolean'),], doc: 'List of nodes by Label, by default excludes offline nodes.')
|
||||||
method(name: 'properties', type: 'Object', params: [properties: 'Map'], doc: 'Set job properties')
|
method(name: 'properties', type: 'Object', params: [properties: 'Map'], doc: 'Set job properties')
|
||||||
@ -55,26 +55,30 @@ contributor(ctx) {
|
|||||||
method(name: 'script', type: 'Object', params: [body: 'Closure'], doc: 'Run arbitrary Pipeline script')
|
method(name: 'script', type: 'Object', params: [body: 'Closure'], doc: 'Run arbitrary Pipeline script')
|
||||||
method(name: 'sleep', type: 'Object', params: [time: 'int'], doc: 'Sleep')
|
method(name: 'sleep', type: 'Object', params: [time: 'int'], doc: 'Sleep')
|
||||||
method(name: 'sleep', type: 'Object', namedParams: [parameter(name: 'time', type: 'int'), parameter(name: 'unit', type: 'java.util.concurrent.TimeUnit'),], doc: 'Sleep')
|
method(name: 'sleep', type: 'Object', namedParams: [parameter(name: 'time', type: 'int'), parameter(name: 'unit', type: 'java.util.concurrent.TimeUnit'),], doc: 'Sleep')
|
||||||
method(name: 'stage', type: 'Object', params: [name: java.lang.String, body: 'Closure'], doc: 'Stage')
|
method(name: 'stage', type: 'Object', params: [name: String, body: 'Closure'], doc: 'Stage')
|
||||||
method(name: 'stage', type: 'Object', params: [body: Closure], namedParams: [parameter(name: 'name', type: 'java.lang.String'), parameter(name: 'concurrency', type: 'java.lang.Integer'),], doc: 'Stage')
|
method(name: 'stage', type: 'Object', params: [body: Closure], namedParams: [parameter(name: 'name', type: 'java.lang.String'), parameter(name: 'concurrency', type: 'java.lang.Integer'),], doc: 'Stage')
|
||||||
|
method(name: 'options', type: 'Object', params: [body: 'Closure'], doc: 'Options')
|
||||||
method(name: 'timeout', type: 'Object', params: [time: int, body: 'Closure'], doc: 'Enforce time limit')
|
method(name: 'timeout', type: 'Object', params: [time: int, body: 'Closure'], doc: 'Enforce time limit')
|
||||||
method(name: 'timeout', type: 'Object', params: [body: Closure], namedParams: [parameter(name: 'time', type: 'int'), parameter(name: 'activity', type: 'boolean'), parameter(name: 'unit', type: 'java.util.concurrent.TimeUnit'),], doc: 'Enforce time limit')
|
method(name: 'timeout', type: 'Object', params: [body: Closure], namedParams: [parameter(name: 'time', type: 'java.lang.Integer'), parameter(name: 'activity', type: 'boolean'), parameter(name: 'unit', type: 'java.util.concurrent.TimeUnit'),], doc: 'Enforce time limit')
|
||||||
method(name: 'timestamps', type: 'Object', params: [body: 'Closure'], doc: 'Timestamps')
|
method(name: 'timestamps', type: 'Object', params: [body: 'Closure'], doc: 'Timestamps')
|
||||||
method(name: 'tool', type: 'Object', params: [name: 'java.lang.String'], doc: 'Use a tool from a predefined Tool Installation')
|
method(name: 'tool', type: 'Object', params: [name: 'java.lang.String'], doc: 'Use a tool from a predefined Tool Installation')
|
||||||
method(name: 'tool', type: 'Object', namedParams: [parameter(name: 'name', type: 'java.lang.String'), parameter(name: 'type', type: 'java.lang.String'),], doc: 'Use a tool from a predefined Tool Installation')
|
method(name: 'tool', type: 'Object', namedParams: [parameter(name: 'name', type: 'java.lang.String'), parameter(name: 'type', type: 'java.lang.String'),], doc: 'Use a tool from a predefined Tool Installation')
|
||||||
method(name: 'unstable', type: 'Object', params: [message: 'java.lang.String'], doc: 'Set stage result to unstable')
|
method(name: 'unstable', type: 'Object', params: [message: 'java.lang.String'], doc: 'Set stage result to unstable')
|
||||||
method(name: 'waitUntil', type: 'Object', params: [body: 'Closure'], doc: 'Wait for condition')
|
method(name: 'waitUntil', type: 'Object', params: [body: 'Closure'], doc: 'Wait for condition')
|
||||||
method(name: 'warnError', type: 'Object', params: [message: java.lang.String, body: 'Closure'], doc: 'Catch error and set build and stage result to unstable')
|
method(name: 'warnError', type: 'Object', params: [message: String, body: 'Closure'], doc: 'Catch error and set build and stage result to unstable')
|
||||||
method(name: 'warnError', type: 'Object', params: [body: Closure], namedParams: [parameter(name: 'message', type: 'java.lang.String'), parameter(name: 'catchInterruptions', type: 'boolean'),], doc: 'Catch error and set build and stage result to unstable')
|
method(name: 'warnError', type: 'Object', params: [body: Closure], namedParams: [parameter(name: 'message', type: 'java.lang.String'), parameter(name: 'catchInterruptions', type: 'boolean'),], doc: 'Catch error and set build and stage result to unstable')
|
||||||
method(name: 'withCredentials', type: 'Object', params: [bindings: Map, body: 'Closure'], doc: 'Bind credentials to variables')
|
method(name: 'withCredentials', type: 'Object', params: [bindings: List, body: 'Closure'], doc: 'Bind credentials to variables')
|
||||||
|
method(name: 'string', type: 'Object', namedParams: [parameter(name: 'credentialsId', type: String), parameter(name: 'variable', type: String)], doc: 'Bind secret text credentials to variable')
|
||||||
method(name: 'withEnv', type: 'Object', params: [overrides: Map, body: 'Closure'], doc: 'Set environment variables')
|
method(name: 'withEnv', type: 'Object', params: [overrides: Map, body: 'Closure'], doc: 'Set environment variables')
|
||||||
method(name: 'ws', type: 'Object', params: [dir: java.lang.String, body: 'Closure'], doc: 'Allocate workspace')
|
method(name: 'ws', type: 'Object', params: [dir: String, body: 'Closure'], doc: 'Allocate workspace')
|
||||||
method(name: 'dockerFingerprintRun', type: 'Object', params: [containerId: 'java.lang.String'], doc: 'Advanced/Deprecated Record trace of a Docker image run in a container')
|
method(name: 'dockerFingerprintRun', type: 'Object', params: [containerId: 'java.lang.String'], doc: 'Advanced/Deprecated Record trace of a Docker image run in a container')
|
||||||
method(name: 'dockerFingerprintRun', type: 'Object', namedParams: [parameter(name: 'containerId', type: 'java.lang.String'), parameter(name: 'toolName', type: 'java.lang.String'),], doc: 'Record trace of a Docker image run in a container')
|
method(name: 'dockerFingerprintRun', type: 'Object', namedParams: [parameter(name: 'containerId', type: 'java.lang.String'), parameter(name: 'toolName', type: 'java.lang.String'),], doc: 'Record trace of a Docker image run in a container')
|
||||||
method(name: 'envVarsForTool', type: 'Object', namedParams: [parameter(name: 'toolId', type: 'java.lang.String'), parameter(name: 'toolVersion', type: 'java.lang.String'),], doc: 'Fetches the environment variables for a given tool in a list of \'FOO=bar\' strings suitable for the withEnv step.')
|
method(name: 'envVarsForTool', type: 'Object', namedParams: [parameter(name: 'toolId', type: 'java.lang.String'), parameter(name: 'toolVersion', type: 'java.lang.String'),], doc: 'Fetches the environment variables for a given tool in a list of \'FOO=bar\' strings suitable for the withEnv step.')
|
||||||
method(name: 'getContext', type: 'Object', params: [type: 'Map'], doc: 'Advanced/Deprecated Get contextual object from internal APIs')
|
method(name: 'getContext', type: 'Object', params: [type: 'Map'], doc: 'Advanced/Deprecated Get contextual object from internal APIs')
|
||||||
method(name: 'podTemplate', type: 'Object', params: [body: Closure], namedParams: [parameter(name: 'label', type: 'java.lang.String'), parameter(name: 'name', type: 'java.lang.String'), parameter(name: 'activeDeadlineSeconds', type: 'int'), parameter(name: 'annotations', type: 'Map'), parameter(name: 'cloud', type: 'java.lang.String'), parameter(name: 'containers', type: 'Map'), parameter(name: 'envVars', type: 'Map'), parameter(name: 'idleMinutes', type: 'int'), parameter(name: 'imagePullSecrets', type: 'Map'), parameter(name: 'inheritFrom', type: 'java.lang.String'), parameter(name: 'instanceCap', type: 'int'), parameter(name: 'namespace', type: 'java.lang.String'), parameter(name: 'nodeSelector', type: 'java.lang.String'), parameter(name: 'nodeUsageMode', type: 'java.lang.String'), parameter(name: 'podRetention', type: 'Map'), parameter(name: 'serviceAccount', type: 'java.lang.String'), parameter(name: 'slaveConnectTimeout', type: 'int'), parameter(name: 'volumes', type: 'Map'), parameter(name: 'workingDir', type: 'java.lang.String'), parameter(name: 'workspaceVolume', type: 'Map'), parameter(name: 'yaml', type: 'java.lang.String'),], doc: 'Define a podTemplate to use in the kubernetes plugin')
|
method(name: 'podTemplate', type: 'Object', params: [body: Closure], namedParams: [parameter(name: 'label', type: 'java.lang.String'), parameter(name: 'name', type: 'java.lang.String'), parameter(name: 'activeDeadlineSeconds', type: 'int'), parameter(name: 'annotations', type: 'Map'), parameter(name: 'cloud', type: 'java.lang.String'), parameter(name: 'containers', type: 'Map'), parameter(name: 'envVars', type: 'Map'), parameter(name: 'idleMinutes', type: 'int'), parameter(name: 'imagePullSecrets', type: 'Map'), parameter(name: 'inheritFrom', type: 'java.lang.String'), parameter(name: 'instanceCap', type: 'int'), parameter(name: 'namespace', type: 'java.lang.String'), parameter(name: 'nodeSelector', type: 'java.lang.String'), parameter(name: 'nodeUsageMode', type: 'java.lang.String'), parameter(name: 'podRetention', type: 'Map'), parameter(name: 'serviceAccount', type: 'java.lang.String'), parameter(name: 'slaveConnectTimeout', type: 'int'), parameter(name: 'volumes', type: 'Map'), parameter(name: 'workingDir', type: 'java.lang.String'), parameter(name: 'workspaceVolume', type: 'Map'), parameter(name: 'yaml', type: 'java.lang.String'),], doc: 'Define a podTemplate to use in the kubernetes plugin')
|
||||||
method(name: 'withContext', type: 'Object', params: [context: java.lang.Object, body: 'Closure'], doc: 'Advanced/Deprecated Use contextual object from internal APIs within a block')
|
method(name: 'withContext', type: 'Object', params: [context: Object, body: 'Closure'], doc: 'Advanced/Deprecated Use contextual object from internal APIs within a block')
|
||||||
|
method(name: 'httpRequest', type: 'jenkins.plugins.http_request.ResponseContentSupplier', params: [url:'java.lang.String'], doc: 'Perform an HTTP Request and return a response object')
|
||||||
|
method(name: 'httpRequest', type: 'jenkins.plugins.http_request.ResponseContentSupplier', namedParams: [parameter(name: 'url', type: 'java.lang.String'), parameter(name: 'acceptType', type: 'Map'), parameter(name: 'authentication', type: 'java.lang.String'), parameter(name: 'consoleLogResponseBody', type: 'java.lang.Boolean'), parameter(name: 'contentType', type: 'jenkins.plugins.http_request.MimeType'), parameter(name: 'customHeaders', type: 'java.util.List'), parameter(name: 'formData', type: 'java.util.List'), parameter(name: 'httpMode', type: 'jenkins.plugins.http_request.HttpMode'), parameter(name: 'httpProxy', type: 'java.lang.String'), parameter(name: 'ignoreSslErrors', type: 'boolean'), parameter(name: 'multipartName', type: 'java.lang.String'), parameter(name: 'outputFile', type: 'java.lang.String'), parameter(name: 'proxyAuthentication', type: 'java.lang.String'), parameter(name: 'quiet', type: 'java.lang.Boolean'), parameter(name: 'requestBody', type: 'java.lang.String'), parameter(name: 'responseHandle', type: 'Map'), parameter(name: 'timeout', type: 'java.lang.Integer'), parameter(name: 'uploadFile', type: 'java.lang.String'), parameter(name: 'useNtlm', type: 'boolean'), parameter(name: 'useSystemProperties', type: 'java.lang.Boolean'), parameter(name: 'validResponseCodes', type: 'java.lang.String'), parameter(name: 'validResponseContent', type: 'java.lang.String'), parameter(name: 'wrapAsMultipart', type: 'boolean'), ], doc: 'Perform an HTTP Request and return a response object')
|
||||||
property(name: 'docker', type: 'org.jenkinsci.plugins.docker.workflow.DockerDSL')
|
property(name: 'docker', type: 'org.jenkinsci.plugins.docker.workflow.DockerDSL')
|
||||||
property(name: 'pipeline', type: 'org.jenkinsci.plugins.pipeline.modeldefinition.ModelStepLoader')
|
property(name: 'pipeline', type: 'org.jenkinsci.plugins.pipeline.modeldefinition.ModelStepLoader')
|
||||||
property(name: 'env', type: 'org.jenkinsci.plugins.workflow.cps.EnvActionImpl.Binder')
|
property(name: 'env', type: 'org.jenkinsci.plugins.workflow.cps.EnvActionImpl.Binder')
|
||||||
@ -82,6 +86,17 @@ contributor(ctx) {
|
|||||||
property(name: 'currentBuild', type: 'org.jenkinsci.plugins.workflow.cps.RunWrapperBinder')
|
property(name: 'currentBuild', type: 'org.jenkinsci.plugins.workflow.cps.RunWrapperBinder')
|
||||||
property(name: 'scm', type: 'org.jenkinsci.plugins.workflow.multibranch.SCMVar')
|
property(name: 'scm', type: 'org.jenkinsci.plugins.workflow.multibranch.SCMVar')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Steps that require a options context
|
||||||
|
def optionsCtx = context(scope: closureScope())
|
||||||
|
contributor(optionsCtx) {
|
||||||
|
def call = enclosingCall('options')
|
||||||
|
if (call) {
|
||||||
|
method(name: 'timestamps', type: 'Object', params: [], doc: 'Timestamps')
|
||||||
|
method(name: 'timeout', type: 'Object', namedParams: [parameter(name: 'time', type: 'java.lang.Integer'), parameter(name: 'activity', type: 'boolean'), parameter(name: 'unit', type: 'java.util.concurrent.TimeUnit'),], doc: 'Enforce time limit')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//Steps that require a node context
|
//Steps that require a node context
|
||||||
def nodeCtx = context(scope: closureScope())
|
def nodeCtx = context(scope: closureScope())
|
||||||
contributor(nodeCtx) {
|
contributor(nodeCtx) {
|
||||||
@ -92,7 +107,7 @@ contributor(nodeCtx) {
|
|||||||
method(name: 'containerLog', type: 'Object', params: [name: 'java.lang.String'], doc: 'Get container log from Kubernetes')
|
method(name: 'containerLog', type: 'Object', params: [name: 'java.lang.String'], doc: 'Get container log from Kubernetes')
|
||||||
method(name: 'containerLog', type: 'Object', namedParams: [parameter(name: 'name', type: 'java.lang.String'), parameter(name: 'limitBytes', type: 'int'), parameter(name: 'returnLog', type: 'boolean'), parameter(name: 'sinceSeconds', type: 'int'), parameter(name: 'tailingLines', type: 'int'),], doc: 'Get container log from Kubernetes')
|
method(name: 'containerLog', type: 'Object', namedParams: [parameter(name: 'name', type: 'java.lang.String'), parameter(name: 'limitBytes', type: 'int'), parameter(name: 'returnLog', type: 'boolean'), parameter(name: 'sinceSeconds', type: 'int'), parameter(name: 'tailingLines', type: 'int'),], doc: 'Get container log from Kubernetes')
|
||||||
method(name: 'deleteDir', type: 'Object', params: [:], doc: 'Recursively delete the current directory from the workspace')
|
method(name: 'deleteDir', type: 'Object', params: [:], doc: 'Recursively delete the current directory from the workspace')
|
||||||
method(name: 'dir', type: 'Object', params: [path: java.lang.String, body: 'Closure'], doc: 'Change current directory')
|
method(name: 'dir', type: 'Object', params: [path: String, body: 'Closure'], doc: 'Change current directory')
|
||||||
method(name: 'fileExists', type: 'Object', params: [file: 'java.lang.String'], doc: 'Verify if file exists in workspace')
|
method(name: 'fileExists', type: 'Object', params: [file: 'java.lang.String'], doc: 'Verify if file exists in workspace')
|
||||||
method(name: 'findFiles', type: 'Object', params: [:], doc: 'Find files in the workspace')
|
method(name: 'findFiles', type: 'Object', params: [:], doc: 'Find files in the workspace')
|
||||||
method(name: 'findFiles', type: 'Object', namedParams: [parameter(name: 'excludes', type: 'java.lang.String'), parameter(name: 'glob', type: 'java.lang.String'),], doc: 'Find files in the workspace')
|
method(name: 'findFiles', type: 'Object', namedParams: [parameter(name: 'excludes', type: 'java.lang.String'), parameter(name: 'glob', type: 'java.lang.String'),], doc: 'Find files in the workspace')
|
||||||
@ -122,7 +137,7 @@ contributor(nodeCtx) {
|
|||||||
method(name: 'step', type: 'Object', params: [delegate: 'Map'], doc: 'General Build Step')
|
method(name: 'step', type: 'Object', params: [delegate: 'Map'], doc: 'General Build Step')
|
||||||
method(name: 'svn', type: 'Object', params: [url: 'java.lang.String'], doc: 'Subversion')
|
method(name: 'svn', type: 'Object', params: [url: 'java.lang.String'], doc: 'Subversion')
|
||||||
method(name: 'svn', type: 'Object', namedParams: [parameter(name: 'url', type: 'java.lang.String'), parameter(name: 'changelog', type: 'boolean'), parameter(name: 'poll', type: 'boolean'),], doc: 'Subversion')
|
method(name: 'svn', type: 'Object', namedParams: [parameter(name: 'url', type: 'java.lang.String'), parameter(name: 'changelog', type: 'boolean'), parameter(name: 'poll', type: 'boolean'),], doc: 'Subversion')
|
||||||
method(name: 'tee', type: 'Object', params: [file: java.lang.String, body: 'Closure'], doc: 'Tee output to file')
|
method(name: 'tee', type: 'Object', params: [file: String, body: 'Closure'], doc: 'Tee output to file')
|
||||||
method(name: 'tm', type: 'Object', params: [stringWithMacro: 'java.lang.String'], doc: 'Expand a string containing macros')
|
method(name: 'tm', type: 'Object', params: [stringWithMacro: 'java.lang.String'], doc: 'Expand a string containing macros')
|
||||||
method(name: 'touch', type: 'Object', params: [file: 'java.lang.String'], doc: 'Create a file (if not already exist) in the workspace, and set the timestamp')
|
method(name: 'touch', type: 'Object', params: [file: 'java.lang.String'], doc: 'Create a file (if not already exist) in the workspace, and set the timestamp')
|
||||||
method(name: 'touch', type: 'Object', namedParams: [parameter(name: 'file', type: 'java.lang.String'), parameter(name: 'timestamp', type: 'java.lang.Long'),], doc: 'Create a file (if not already exist) in the workspace, and set the timestamp')
|
method(name: 'touch', type: 'Object', namedParams: [parameter(name: 'file', type: 'java.lang.String'), parameter(name: 'timestamp', type: 'java.lang.Long'),], doc: 'Create a file (if not already exist) in the workspace, and set the timestamp')
|
||||||
@ -141,12 +156,12 @@ contributor(nodeCtx) {
|
|||||||
method(name: 'zip', type: 'Object', namedParams: [parameter(name: 'zipFile', type: 'java.lang.String'), parameter(name: 'archive', type: 'boolean'), parameter(name: 'dir', type: 'java.lang.String'), parameter(name: 'glob', type: 'java.lang.String'),], doc: 'Create Zip file')
|
method(name: 'zip', type: 'Object', namedParams: [parameter(name: 'zipFile', type: 'java.lang.String'), parameter(name: 'archive', type: 'boolean'), parameter(name: 'dir', type: 'java.lang.String'), parameter(name: 'glob', type: 'java.lang.String'),], doc: 'Create Zip file')
|
||||||
method(name: 'archive', type: 'Object', params: [includes: 'java.lang.String'], doc: 'Advanced/Deprecated Archive artifacts')
|
method(name: 'archive', type: 'Object', params: [includes: 'java.lang.String'], doc: 'Advanced/Deprecated Archive artifacts')
|
||||||
method(name: 'archive', type: 'Object', namedParams: [parameter(name: 'includes', type: 'java.lang.String'), parameter(name: 'excludes', type: 'java.lang.String'),], doc: 'Archive artifacts')
|
method(name: 'archive', type: 'Object', namedParams: [parameter(name: 'includes', type: 'java.lang.String'), parameter(name: 'excludes', type: 'java.lang.String'),], doc: 'Archive artifacts')
|
||||||
method(name: 'container', type: 'Object', params: [name: java.lang.String, body: 'Closure'], doc: 'Advanced/Deprecated Run build steps in a container')
|
method(name: 'container', type: 'Object', params: [name: String, body: 'Closure'], doc: 'Advanced/Deprecated Run build steps in a container')
|
||||||
method(name: 'container', type: 'Object', params: [body: Closure], namedParams: [parameter(name: 'name', type: 'java.lang.String'), parameter(name: 'shell', type: 'java.lang.String'),], doc: 'Run build steps in a container')
|
method(name: 'container', type: 'Object', params: [body: Closure], namedParams: [parameter(name: 'name', type: 'java.lang.String'), parameter(name: 'shell', type: 'java.lang.String'),], doc: 'Run build steps in a container')
|
||||||
method(name: 'dockerFingerprintFrom', type: 'Object', namedParams: [parameter(name: 'dockerfile', type: 'java.lang.String'), parameter(name: 'image', type: 'java.lang.String'), parameter(name: 'commandLine', type: 'java.lang.String'), parameter(name: 'toolName', type: 'java.lang.String'),], doc: 'Record trace of a Docker image used in FROM')
|
method(name: 'dockerFingerprintFrom', type: 'Object', namedParams: [parameter(name: 'dockerfile', type: 'java.lang.String'), parameter(name: 'image', type: 'java.lang.String'), parameter(name: 'commandLine', type: 'java.lang.String'), parameter(name: 'toolName', type: 'java.lang.String'),], doc: 'Record trace of a Docker image used in FROM')
|
||||||
method(name: 'unarchive', type: 'Object', params: [:], doc: 'Advanced/Deprecated Copy archived artifacts into the workspace')
|
method(name: 'unarchive', type: 'Object', params: [:], doc: 'Advanced/Deprecated Copy archived artifacts into the workspace')
|
||||||
method(name: 'unarchive', type: 'Object', namedParams: [parameter(name: 'mapping', type: 'Map'),], doc: 'Copy archived artifacts into the workspace')
|
method(name: 'unarchive', type: 'Object', namedParams: [parameter(name: 'mapping', type: 'Map'),], doc: 'Copy archived artifacts into the workspace')
|
||||||
method(name: 'withDockerContainer', type: 'Object', params: [image: java.lang.String, body: 'Closure'], doc: 'Advanced/Deprecated Run build steps inside a Docker container')
|
method(name: 'withDockerContainer', type: 'Object', params: [image: String, body: 'Closure'], doc: 'Advanced/Deprecated Run build steps inside a Docker container')
|
||||||
method(name: 'withDockerContainer', type: 'Object', params: [body: Closure], namedParams: [parameter(name: 'image', type: 'java.lang.String'), parameter(name: 'args', type: 'java.lang.String'), parameter(name: 'toolName', type: 'java.lang.String'),], doc: 'Run build steps inside a Docker container')
|
method(name: 'withDockerContainer', type: 'Object', params: [body: Closure], namedParams: [parameter(name: 'image', type: 'java.lang.String'), parameter(name: 'args', type: 'java.lang.String'), parameter(name: 'toolName', type: 'java.lang.String'),], doc: 'Run build steps inside a Docker container')
|
||||||
method(name: 'withDockerRegistry', type: 'Object', params: [registry: Map, body: 'Closure'], doc: 'Advanced/Deprecated Sets up Docker registry endpoint')
|
method(name: 'withDockerRegistry', type: 'Object', params: [registry: Map, body: 'Closure'], doc: 'Advanced/Deprecated Sets up Docker registry endpoint')
|
||||||
method(name: 'withDockerRegistry', type: 'Object', params: [body: Closure], namedParams: [parameter(name: 'registry', type: 'Map'), parameter(name: 'toolName', type: 'java.lang.String'),], doc: 'Sets up Docker registry endpoint')
|
method(name: 'withDockerRegistry', type: 'Object', params: [body: Closure], namedParams: [parameter(name: 'registry', type: 'Map'), parameter(name: 'toolName', type: 'java.lang.String'),], doc: 'Sets up Docker registry endpoint')
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
package ru.pulsar.jenkins.library
|
package ru.pulsar.jenkins.library
|
||||||
|
|
||||||
|
import jenkins.plugins.http_request.HttpMode
|
||||||
|
import jenkins.plugins.http_request.MimeType
|
||||||
|
import jenkins.plugins.http_request.ResponseContentSupplier
|
||||||
import org.jenkinsci.plugins.pipeline.utility.steps.fs.FileWrapper
|
import org.jenkinsci.plugins.pipeline.utility.steps.fs.FileWrapper
|
||||||
import org.jenkinsci.plugins.workflow.support.actions.EnvironmentAction
|
import org.jenkinsci.plugins.workflow.support.actions.EnvironmentAction
|
||||||
|
import org.jenkinsci.plugins.workflow.support.steps.build.RunWrapper
|
||||||
|
|
||||||
interface IStepExecutor {
|
interface IStepExecutor {
|
||||||
|
|
||||||
@ -69,7 +73,9 @@ interface IStepExecutor {
|
|||||||
|
|
||||||
def catchError(Closure body)
|
def catchError(Closure body)
|
||||||
|
|
||||||
def httpRequest(String url, String outputFile, String responseHandle, boolean wrapAsMultipart)
|
ResponseContentSupplier httpRequest(String url, String outputFile, String responseHandle, boolean wrapAsMultipart)
|
||||||
|
|
||||||
|
ResponseContentSupplier httpRequest(String url, HttpMode httpMode, MimeType contentType, String requestBody, String validResponseCodes, boolean consoleLogResponseBody)
|
||||||
|
|
||||||
def error(String errorMessage)
|
def error(String errorMessage)
|
||||||
|
|
||||||
@ -78,4 +84,16 @@ interface IStepExecutor {
|
|||||||
def junit(String testResults, boolean allowEmptyResults)
|
def junit(String testResults, boolean allowEmptyResults)
|
||||||
|
|
||||||
def installLocalDependencies()
|
def installLocalDependencies()
|
||||||
|
|
||||||
|
def emailext(String subject, String body, String to, List recipientProviders, boolean attachLog)
|
||||||
|
|
||||||
|
def developers()
|
||||||
|
|
||||||
|
def requestor()
|
||||||
|
|
||||||
|
def brokenBuildSuspects()
|
||||||
|
|
||||||
|
def brokenTestsSuspects()
|
||||||
|
|
||||||
|
RunWrapper currentBuild()
|
||||||
}
|
}
|
@ -1,7 +1,11 @@
|
|||||||
package ru.pulsar.jenkins.library
|
package ru.pulsar.jenkins.library
|
||||||
|
|
||||||
|
import jenkins.plugins.http_request.HttpMode
|
||||||
|
import jenkins.plugins.http_request.MimeType
|
||||||
|
import jenkins.plugins.http_request.ResponseContentSupplier
|
||||||
import org.jenkinsci.plugins.pipeline.utility.steps.fs.FileWrapper
|
import org.jenkinsci.plugins.pipeline.utility.steps.fs.FileWrapper
|
||||||
import org.jenkinsci.plugins.workflow.support.actions.EnvironmentAction
|
import org.jenkinsci.plugins.workflow.support.actions.EnvironmentAction
|
||||||
|
import org.jenkinsci.plugins.workflow.support.steps.build.RunWrapper
|
||||||
import ru.yandex.qatools.allure.jenkins.config.ResultsConfig
|
import ru.yandex.qatools.allure.jenkins.config.ResultsConfig
|
||||||
|
|
||||||
class StepExecutor implements IStepExecutor {
|
class StepExecutor implements IStepExecutor {
|
||||||
@ -139,7 +143,7 @@ class StepExecutor implements IStepExecutor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
def zip(String dir, String zipFile, String glob = '') {
|
def zip(String dir, String zipFile, String glob = '') {
|
||||||
steps.zip dir: dir, zipFile: zipFile, glob: glob
|
steps.zip dir: dir, zipFile: zipFile, glob: glob, overwrite: true
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -153,10 +157,22 @@ class StepExecutor implements IStepExecutor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
def httpRequest(String url, String outputFile, String responseHandle = 'NONE', boolean wrapAsMultipart = false) {
|
ResponseContentSupplier httpRequest(String url, String outputFile, String responseHandle = 'NONE', boolean wrapAsMultipart = false) {
|
||||||
steps.httpRequest responseHandle: responseHandle, outputFile: outputFile, url: url, wrapAsMultipart: wrapAsMultipart
|
steps.httpRequest responseHandle: responseHandle, outputFile: outputFile, url: url, wrapAsMultipart: wrapAsMultipart
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
ResponseContentSupplier httpRequest(String url, HttpMode httpMode, MimeType contentType, String requestBody, String validResponseCodes, boolean consoleLogResponseBody) {
|
||||||
|
steps.httpRequest(
|
||||||
|
url: url,
|
||||||
|
httpMode: httpMode,
|
||||||
|
contentType: contentType,
|
||||||
|
requestBody: requestBody,
|
||||||
|
validResponseCodes: validResponseCodes,
|
||||||
|
consoleLogResponseBody: consoleLogResponseBody
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
def error(String errorMessage) {
|
def error(String errorMessage) {
|
||||||
steps.error errorMessage
|
steps.error errorMessage
|
||||||
@ -183,4 +199,40 @@ class StepExecutor implements IStepExecutor {
|
|||||||
def installLocalDependencies() {
|
def installLocalDependencies() {
|
||||||
steps.installLocalDependencies()
|
steps.installLocalDependencies()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
def emailext(String subject, String body, String to, List recipientProviders, boolean attachLog) {
|
||||||
|
steps.emailext(
|
||||||
|
subject: subject,
|
||||||
|
body: body,
|
||||||
|
to: to,
|
||||||
|
recipientProviders: recipientProviders,
|
||||||
|
attachLog: attachLog,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
def developers() {
|
||||||
|
steps.developers()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
def requestor() {
|
||||||
|
steps.requestor()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
def brokenBuildSuspects() {
|
||||||
|
steps.brokenBuildSuspects()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
def brokenTestsSuspects() {
|
||||||
|
steps.brokenTestsSuspects()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
RunWrapper currentBuild() {
|
||||||
|
steps.currentBuild
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
package ru.pulsar.jenkins.library.configuration
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty
|
||||||
|
import com.fasterxml.jackson.annotation.JsonPropertyDescription
|
||||||
|
|
||||||
|
enum BranchAnalysisConfiguration {
|
||||||
|
@JsonPropertyDescription(
|
||||||
|
"""Применяется автоконфигурация sonar-scanner силами branchplugin.
|
||||||
|
Так же может применяться для отключения конфигурирования, если branch plugin отсутствует"""
|
||||||
|
)
|
||||||
|
@JsonProperty("auto")
|
||||||
|
AUTO,
|
||||||
|
|
||||||
|
@JsonPropertyDescription("Применяется ручная конфигурация sonar-scanner на основе переменных среды")
|
||||||
|
@JsonProperty("fromEnv")
|
||||||
|
FROM_ENV
|
||||||
|
}
|
@ -6,8 +6,11 @@ import com.fasterxml.jackson.databind.ObjectMapper
|
|||||||
import org.apache.commons.beanutils.BeanUtilsBean
|
import org.apache.commons.beanutils.BeanUtilsBean
|
||||||
import org.apache.commons.beanutils.ConvertUtilsBean
|
import org.apache.commons.beanutils.ConvertUtilsBean
|
||||||
import ru.pulsar.jenkins.library.IStepExecutor
|
import ru.pulsar.jenkins.library.IStepExecutor
|
||||||
|
import ru.pulsar.jenkins.library.configuration.notification.email.EmailExtConfiguration
|
||||||
import ru.pulsar.jenkins.library.ioc.ContextRegistry
|
import ru.pulsar.jenkins.library.ioc.ContextRegistry
|
||||||
|
|
||||||
|
import static java.util.Collections.emptySet
|
||||||
|
|
||||||
class ConfigurationReader implements Serializable {
|
class ConfigurationReader implements Serializable {
|
||||||
|
|
||||||
private static ObjectMapper mapper
|
private static ObjectMapper mapper
|
||||||
@ -62,12 +65,21 @@ class ConfigurationReader implements Serializable {
|
|||||||
"sonarQubeOptions",
|
"sonarQubeOptions",
|
||||||
"smokeTestOptions",
|
"smokeTestOptions",
|
||||||
"syntaxCheckOptions",
|
"syntaxCheckOptions",
|
||||||
"resultsTransformOptions"
|
"resultsTransformOptions",
|
||||||
|
"notificationsOptions",
|
||||||
|
"emailNotificationOptions",
|
||||||
|
"alwaysEmailOptions",
|
||||||
|
"successEmailOptions",
|
||||||
|
"failureEmailOptions",
|
||||||
|
"unstableEmailOptions",
|
||||||
|
"recipientProviders",
|
||||||
|
"telegramNotificationOptions"
|
||||||
).toSet()
|
).toSet()
|
||||||
|
|
||||||
mergeObjects(baseConfiguration, configurationToMerge, nonMergeableSettings)
|
mergeObjects(baseConfiguration, configurationToMerge, nonMergeableSettings)
|
||||||
mergeInitInfoBaseOptions(baseConfiguration.initInfoBaseOptions, configurationToMerge.initInfoBaseOptions);
|
mergeInitInfoBaseOptions(baseConfiguration.initInfoBaseOptions, configurationToMerge.initInfoBaseOptions)
|
||||||
mergeBddOptions(baseConfiguration.bddOptions, configurationToMerge.bddOptions);
|
mergeBddOptions(baseConfiguration.bddOptions, configurationToMerge.bddOptions)
|
||||||
|
mergeNotificationsOptions(baseConfiguration.notificationsOptions, configurationToMerge.notificationsOptions)
|
||||||
|
|
||||||
return baseConfiguration;
|
return baseConfiguration;
|
||||||
}
|
}
|
||||||
@ -84,10 +96,16 @@ class ConfigurationReader implements Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
nonMergeableSettings.forEach({ key ->
|
nonMergeableSettings.forEach({ key ->
|
||||||
|
if (!baseObject.hasProperty(key)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (objectToMerge == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
mergeObjects(
|
mergeObjects(
|
||||||
baseObject[key],
|
baseObject[key],
|
||||||
objectToMerge[key],
|
objectToMerge[key],
|
||||||
Collections.emptySet()
|
nonMergeableSettings
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -107,4 +125,53 @@ class ConfigurationReader implements Serializable {
|
|||||||
}
|
}
|
||||||
baseObject.vrunnerSteps = objectToMerge.vrunnerSteps.clone()
|
baseObject.vrunnerSteps = objectToMerge.vrunnerSteps.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static void mergeNotificationsOptions(NotificationsOptions baseObject, NotificationsOptions objectToMerge) {
|
||||||
|
if (objectToMerge == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (objectToMerge.telegramNotificationOptions != null) {
|
||||||
|
|
||||||
|
mergeObjects(
|
||||||
|
baseObject.telegramNotificationOptions,
|
||||||
|
objectToMerge.telegramNotificationOptions,
|
||||||
|
emptySet()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
def emailNotificationOptionsBase = baseObject.emailNotificationOptions
|
||||||
|
def emailNotificationOptionsToMerge = objectToMerge.emailNotificationOptions
|
||||||
|
|
||||||
|
if (emailNotificationOptionsToMerge != null) {
|
||||||
|
mergeEmailExtConfiguration(
|
||||||
|
emailNotificationOptionsBase.successEmailOptions,
|
||||||
|
emailNotificationOptionsToMerge.successEmailOptions
|
||||||
|
)
|
||||||
|
mergeEmailExtConfiguration(
|
||||||
|
emailNotificationOptionsBase.failureEmailOptions,
|
||||||
|
emailNotificationOptionsToMerge.failureEmailOptions
|
||||||
|
)
|
||||||
|
mergeEmailExtConfiguration(
|
||||||
|
emailNotificationOptionsBase.unstableEmailOptions,
|
||||||
|
emailNotificationOptionsToMerge.unstableEmailOptions
|
||||||
|
)
|
||||||
|
mergeEmailExtConfiguration(
|
||||||
|
emailNotificationOptionsBase.alwaysEmailOptions,
|
||||||
|
emailNotificationOptionsToMerge.alwaysEmailOptions
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonCPS
|
||||||
|
private static void mergeEmailExtConfiguration(EmailExtConfiguration baseObject, EmailExtConfiguration objectToMerge) {
|
||||||
|
if (objectToMerge != null && objectToMerge.recipientProviders != null) {
|
||||||
|
baseObject.recipientProviders = objectToMerge.recipientProviders.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (objectToMerge != null && objectToMerge.directRecipients != null) {
|
||||||
|
baseObject.directRecipients = objectToMerge.directRecipients.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,9 @@ class JobConfiguration implements Serializable {
|
|||||||
@JsonPropertyDescription("Версия платформы 1С:Предприятие в формате 8.3.хх.хххх.")
|
@JsonPropertyDescription("Версия платформы 1С:Предприятие в формате 8.3.хх.хххх.")
|
||||||
String v8version
|
String v8version
|
||||||
|
|
||||||
|
@JsonPropertyDescription("Версия модуля 1C:Enterprise Development Tools формате xxxx.x.x:x86_64")
|
||||||
|
String edtVersion
|
||||||
|
|
||||||
@JsonPropertyDescription("Путь к корневому каталогу с исходниками конфигурации, в случае хранения исходников в формате EDT, необходимо указать путь к проекту")
|
@JsonPropertyDescription("Путь к корневому каталогу с исходниками конфигурации, в случае хранения исходников в формате EDT, необходимо указать путь к проекту")
|
||||||
String srcDir
|
String srcDir
|
||||||
|
|
||||||
@ -56,6 +59,10 @@ class JobConfiguration implements Serializable {
|
|||||||
@JsonPropertyDescription("Настройки трансформации результатов анализа")
|
@JsonPropertyDescription("Настройки трансформации результатов анализа")
|
||||||
ResultsTransformOptions resultsTransformOptions;
|
ResultsTransformOptions resultsTransformOptions;
|
||||||
|
|
||||||
|
@JsonProperty("notifications")
|
||||||
|
@JsonPropertyDescription("Настройки рассылки результатов сборки")
|
||||||
|
NotificationsOptions notificationsOptions;
|
||||||
|
|
||||||
@JsonProperty("logosConfig")
|
@JsonProperty("logosConfig")
|
||||||
@JsonPropertyDescription("Конфигурация библиотеки logos. Применяется перед запуском каждой стадии сборки")
|
@JsonPropertyDescription("Конфигурация библиотеки logos. Применяется перед запуском каждой стадии сборки")
|
||||||
String logosConfig;
|
String logosConfig;
|
||||||
@ -65,6 +72,7 @@ class JobConfiguration implements Serializable {
|
|||||||
String toString() {
|
String toString() {
|
||||||
return "JobConfiguration{" +
|
return "JobConfiguration{" +
|
||||||
"v8version='" + v8version + '\'' +
|
"v8version='" + v8version + '\'' +
|
||||||
|
", edtVersion='" + edtVersion + '\'' +
|
||||||
", srcDir='" + srcDir + '\'' +
|
", srcDir='" + srcDir + '\'' +
|
||||||
", sourceFormat=" + sourceFormat +
|
", sourceFormat=" + sourceFormat +
|
||||||
", stageFlags=" + stageFlags +
|
", stageFlags=" + stageFlags +
|
||||||
@ -77,6 +85,7 @@ class JobConfiguration implements Serializable {
|
|||||||
", syntaxCheckOptions=" + syntaxCheckOptions +
|
", syntaxCheckOptions=" + syntaxCheckOptions +
|
||||||
", smokeTestOptions=" + smokeTestOptions +
|
", smokeTestOptions=" + smokeTestOptions +
|
||||||
", resultsTransformOptions=" + resultsTransformOptions +
|
", resultsTransformOptions=" + resultsTransformOptions +
|
||||||
|
", notificationOptions=" + notificationsOptions +
|
||||||
", logosConfig='" + logosConfig + '\'' +
|
", logosConfig='" + logosConfig + '\'' +
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
@ -90,4 +99,16 @@ class JobConfiguration implements Serializable {
|
|||||||
return (initMethod == InitInfoBaseMethod.FROM_SOURCE) ||
|
return (initMethod == InitInfoBaseMethod.FROM_SOURCE) ||
|
||||||
(initMethod == InitInfoBaseMethod.DEFAULT_BRANCH_FROM_STORAGE && branchName != defaultBranch)
|
(initMethod == InitInfoBaseMethod.DEFAULT_BRANCH_FROM_STORAGE && branchName != defaultBranch)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String v8AgentLabel() {
|
||||||
|
return v8version
|
||||||
|
}
|
||||||
|
|
||||||
|
String edtAgentLabel() {
|
||||||
|
String edtVersionForRing = "edt"
|
||||||
|
if (edtVersion != '') {
|
||||||
|
edtVersionForRing += "@" + edtVersion
|
||||||
|
}
|
||||||
|
return edtVersionForRing
|
||||||
|
}
|
||||||
}
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package ru.pulsar.jenkins.library.configuration
|
||||||
|
|
||||||
|
import com.cloudbees.groovy.cps.NonCPS
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty
|
||||||
|
import com.fasterxml.jackson.annotation.JsonPropertyDescription
|
||||||
|
import ru.pulsar.jenkins.library.configuration.notification.EmailNotificationOptions
|
||||||
|
import ru.pulsar.jenkins.library.configuration.notification.TelegramNotificationOptions
|
||||||
|
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
class NotificationsOptions implements Serializable {
|
||||||
|
|
||||||
|
@JsonProperty("email")
|
||||||
|
@JsonPropertyDescription("Настройки рассылки результатов сборки через email")
|
||||||
|
EmailNotificationOptions emailNotificationOptions;
|
||||||
|
|
||||||
|
@JsonProperty("telegram")
|
||||||
|
@JsonPropertyDescription("Настройки рассылки результатов сборки через telegram")
|
||||||
|
TelegramNotificationOptions telegramNotificationOptions;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NonCPS
|
||||||
|
String toString() {
|
||||||
|
return "NotificationOptions{" +
|
||||||
|
"emailNotificationOptions=" + emailNotificationOptions +
|
||||||
|
", telegramNotificationOptions=" + telegramNotificationOptions +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -15,12 +15,20 @@ class Secrets implements Serializable {
|
|||||||
@JsonPropertyDescription("Данные авторизации в хранилище конфигурации")
|
@JsonPropertyDescription("Данные авторизации в хранилище конфигурации")
|
||||||
String storage
|
String storage
|
||||||
|
|
||||||
|
@JsonPropertyDescription("Идентификатор telegram-чата для отправки уведомлений")
|
||||||
|
String telegramChatId
|
||||||
|
|
||||||
|
@JsonPropertyDescription("Токен авторизации telegram-бота для отправки уведомлений")
|
||||||
|
String telegramBotToken
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NonCPS
|
@NonCPS
|
||||||
String toString() {
|
String toString() {
|
||||||
return "Secrets{" +
|
return "Secrets{" +
|
||||||
"storagePath='" + storagePath + '\'' +
|
"storagePath='" + storagePath + '\'' +
|
||||||
", storage='" + storage + '\'' +
|
", storage='" + storage + '\'' +
|
||||||
|
", telegramChatId='" + telegramChatId + '\'' +
|
||||||
|
", telegramBotToken='" + telegramBotToken + '\'' +
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,18 @@ class SonarQubeOptions implements Serializable {
|
|||||||
""")
|
""")
|
||||||
String infoBaseUpdateModuleName
|
String infoBaseUpdateModuleName
|
||||||
|
|
||||||
|
@JsonPropertyDescription("""Вариант конфигурации branch plugin.
|
||||||
|
Поддерживаемые варианты:
|
||||||
|
* auto - применяется автоконфигурация sonar-scanner силами branchplugin. Так же может применяться для отключения конфигурирования, если branch plugin отсутствует;
|
||||||
|
* fromEnv - применяется ручная конфигурация sonar-scanner на основе переменных среды.
|
||||||
|
Значение по умолчанию: fromEnv.""")
|
||||||
|
BranchAnalysisConfiguration branchAnalysisConfiguration
|
||||||
|
|
||||||
|
@JsonPropertyDescription("""Ожидать состояние Quality Gate от SonarQube после загрузки анализа. По умолчанию `false`.
|
||||||
|
Таймаут ожидания состояния равен таймауту шага.
|
||||||
|
""")
|
||||||
|
Boolean waitForQualityGate
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NonCPS
|
@NonCPS
|
||||||
String toString() {
|
String toString() {
|
||||||
@ -33,6 +45,8 @@ class SonarQubeOptions implements Serializable {
|
|||||||
", sonarScannerToolName='" + sonarScannerToolName + '\'' +
|
", sonarScannerToolName='" + sonarScannerToolName + '\'' +
|
||||||
", sonarQubeInstallation='" + sonarQubeInstallation + '\'' +
|
", sonarQubeInstallation='" + sonarQubeInstallation + '\'' +
|
||||||
", infoBaseUpdateModuleName='" + infoBaseUpdateModuleName + '\'' +
|
", infoBaseUpdateModuleName='" + infoBaseUpdateModuleName + '\'' +
|
||||||
|
", branchAnalysisConfiguration='" + branchAnalysisConfiguration + '\'' +
|
||||||
|
", waitForQualityGate='" + waitForQualityGate + '\'' +
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,12 @@ class StageFlags implements Serializable {
|
|||||||
@JsonPropertyDescription("Запуск BDD сценариев включен")
|
@JsonPropertyDescription("Запуск BDD сценариев включен")
|
||||||
Boolean bdd
|
Boolean bdd
|
||||||
|
|
||||||
|
@JsonPropertyDescription("Выполнять рассылку результатов сборки на email")
|
||||||
|
Boolean email
|
||||||
|
|
||||||
|
@JsonPropertyDescription("Выполнять рассылку результатов сборки в telegram")
|
||||||
|
Boolean telegram
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NonCPS
|
@NonCPS
|
||||||
String toString() {
|
String toString() {
|
||||||
@ -34,6 +40,8 @@ class StageFlags implements Serializable {
|
|||||||
", smoke=" + smoke +
|
", smoke=" + smoke +
|
||||||
", initSteps=" + initSteps +
|
", initSteps=" + initSteps +
|
||||||
", bdd=" + bdd +
|
", bdd=" + bdd +
|
||||||
|
", email=" + email +
|
||||||
|
", telegram=" + telegram +
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,46 @@
|
|||||||
|
package ru.pulsar.jenkins.library.configuration.notification
|
||||||
|
|
||||||
|
import com.cloudbees.groovy.cps.NonCPS
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty
|
||||||
|
import com.fasterxml.jackson.annotation.JsonPropertyDescription
|
||||||
|
import ru.pulsar.jenkins.library.configuration.notification.email.EmailExtConfiguration
|
||||||
|
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
class EmailNotificationOptions implements Serializable {
|
||||||
|
|
||||||
|
@JsonPropertyDescription("Отправлять всегда")
|
||||||
|
Boolean onAlways
|
||||||
|
@JsonPropertyDescription("Отправлять при успешной сборке")
|
||||||
|
Boolean onSuccess
|
||||||
|
@JsonPropertyDescription("Отправлять при падении сборки")
|
||||||
|
Boolean onFailure
|
||||||
|
@JsonPropertyDescription("Отправлять при нестабильной сборке")
|
||||||
|
Boolean onUnstable
|
||||||
|
|
||||||
|
@JsonProperty("alwaysOptions")
|
||||||
|
EmailExtConfiguration alwaysEmailOptions
|
||||||
|
@JsonProperty("successOptions")
|
||||||
|
EmailExtConfiguration successEmailOptions
|
||||||
|
@JsonProperty("failureOptions")
|
||||||
|
EmailExtConfiguration failureEmailOptions
|
||||||
|
@JsonProperty("unstableOptions")
|
||||||
|
EmailExtConfiguration unstableEmailOptions
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NonCPS
|
||||||
|
String toString() {
|
||||||
|
return "EmailNotificationOptions{" +
|
||||||
|
"onAlways=" + onAlways +
|
||||||
|
", onSuccess=" + onSuccess +
|
||||||
|
", onFailure=" + onFailure +
|
||||||
|
", onUnstable=" + onUnstable +
|
||||||
|
", alwaysEmailOptions=" + alwaysEmailOptions +
|
||||||
|
", successEmailOptions=" + successEmailOptions +
|
||||||
|
", failureEmailOptions=" + failureEmailOptions +
|
||||||
|
", unstableEmailOptions=" + unstableEmailOptions +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,31 @@
|
|||||||
|
package ru.pulsar.jenkins.library.configuration.notification
|
||||||
|
|
||||||
|
import com.cloudbees.groovy.cps.NonCPS
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties
|
||||||
|
import com.fasterxml.jackson.annotation.JsonPropertyDescription
|
||||||
|
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
class TelegramNotificationOptions implements Serializable {
|
||||||
|
|
||||||
|
@JsonPropertyDescription("Отправлять всегда")
|
||||||
|
Boolean onAlways
|
||||||
|
@JsonPropertyDescription("Отправлять при успешной сборке")
|
||||||
|
Boolean onSuccess
|
||||||
|
@JsonPropertyDescription("Отправлять при падении сборки")
|
||||||
|
Boolean onFailure
|
||||||
|
@JsonPropertyDescription("Отправлять при нестабильной сборке")
|
||||||
|
Boolean onUnstable
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NonCPS
|
||||||
|
String toString() {
|
||||||
|
return "TelegramNotificationOptions{" +
|
||||||
|
"onAlways=" + onAlways +
|
||||||
|
", onSuccess=" + onSuccess +
|
||||||
|
", onFailure=" + onFailure +
|
||||||
|
", onUnstable=" + onUnstable +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,21 @@
|
|||||||
|
package ru.pulsar.jenkins.library.configuration.notification.email
|
||||||
|
|
||||||
|
import com.cloudbees.groovy.cps.NonCPS
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties
|
||||||
|
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
class EmailExtConfiguration implements Serializable {
|
||||||
|
Boolean attachLog;
|
||||||
|
String[] directRecipients
|
||||||
|
RecipientProvider[] recipientProviders
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NonCPS
|
||||||
|
String toString() {
|
||||||
|
return "EmailExtConfiguration{" +
|
||||||
|
"attachLog=" + attachLog +
|
||||||
|
", directRecipients=" + directRecipients +
|
||||||
|
", recipientProviders=" + recipientProviders +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
package ru.pulsar.jenkins.library.configuration.notification.email
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty
|
||||||
|
|
||||||
|
enum RecipientProvider {
|
||||||
|
|
||||||
|
@JsonProperty("developers")
|
||||||
|
DEVELOPERS,
|
||||||
|
@JsonProperty("requestor")
|
||||||
|
REQUESTOR,
|
||||||
|
@JsonProperty("brokenBuildSuspects")
|
||||||
|
BROKEN_BUILD_SUSPECTS,
|
||||||
|
@JsonProperty("brokenTestsSuspects")
|
||||||
|
BROKEN_TESTS_SUSPECTS
|
||||||
|
}
|
@ -5,6 +5,7 @@ import ru.pulsar.jenkins.library.IStepExecutor
|
|||||||
import ru.pulsar.jenkins.library.configuration.JobConfiguration
|
import ru.pulsar.jenkins.library.configuration.JobConfiguration
|
||||||
import ru.pulsar.jenkins.library.ioc.ContextRegistry
|
import ru.pulsar.jenkins.library.ioc.ContextRegistry
|
||||||
import ru.pulsar.jenkins.library.utils.Constants
|
import ru.pulsar.jenkins.library.utils.Constants
|
||||||
|
import ru.pulsar.jenkins.library.utils.EDT
|
||||||
import ru.pulsar.jenkins.library.utils.Logger
|
import ru.pulsar.jenkins.library.utils.Logger
|
||||||
|
|
||||||
class DesignerToEdtFormatTransformation implements Serializable {
|
class DesignerToEdtFormatTransformation implements Serializable {
|
||||||
@ -34,12 +35,13 @@ class DesignerToEdtFormatTransformation implements Serializable {
|
|||||||
|
|
||||||
def workspaceDir = "$env.WORKSPACE/$WORKSPACE"
|
def workspaceDir = "$env.WORKSPACE/$WORKSPACE"
|
||||||
def configurationRoot = new File(env.WORKSPACE, config.srcDir).getAbsolutePath()
|
def configurationRoot = new File(env.WORKSPACE, config.srcDir).getAbsolutePath()
|
||||||
|
def edtVersionForRing = EDT.ringModule(config)
|
||||||
|
|
||||||
steps.deleteDir(workspaceDir)
|
steps.deleteDir(workspaceDir)
|
||||||
|
|
||||||
Logger.println("Конвертация исходников из формата конфигуратора в формат EDT")
|
Logger.println("Конвертация исходников из формата конфигуратора в формат EDT")
|
||||||
|
|
||||||
def ringCommand = "ring edt workspace import --configuration-files \"$configurationRoot\" --project-name $PROJECT_NAME --workspace-location \"$workspaceDir\""
|
def ringCommand = "ring $edtVersionForRing workspace import --configuration-files \"$configurationRoot\" --project-name $PROJECT_NAME --workspace-location \"$workspaceDir\""
|
||||||
|
|
||||||
def ringOpts = [Constants.DEFAULT_RING_OPTS]
|
def ringOpts = [Constants.DEFAULT_RING_OPTS]
|
||||||
steps.withEnv(ringOpts) {
|
steps.withEnv(ringOpts) {
|
||||||
|
@ -6,6 +6,7 @@ import ru.pulsar.jenkins.library.configuration.JobConfiguration
|
|||||||
import ru.pulsar.jenkins.library.configuration.SourceFormat
|
import ru.pulsar.jenkins.library.configuration.SourceFormat
|
||||||
import ru.pulsar.jenkins.library.ioc.ContextRegistry
|
import ru.pulsar.jenkins.library.ioc.ContextRegistry
|
||||||
import ru.pulsar.jenkins.library.utils.Constants
|
import ru.pulsar.jenkins.library.utils.Constants
|
||||||
|
import ru.pulsar.jenkins.library.utils.EDT
|
||||||
import ru.pulsar.jenkins.library.utils.Logger
|
import ru.pulsar.jenkins.library.utils.Logger
|
||||||
|
|
||||||
class EdtToDesignerFormatTransformation implements Serializable {
|
class EdtToDesignerFormatTransformation implements Serializable {
|
||||||
@ -37,13 +38,14 @@ class EdtToDesignerFormatTransformation implements Serializable {
|
|||||||
def projectDir = new File("$env.WORKSPACE/$srcDir").getCanonicalPath()
|
def projectDir = new File("$env.WORKSPACE/$srcDir").getCanonicalPath()
|
||||||
def workspaceDir = "$env.WORKSPACE/$WORKSPACE"
|
def workspaceDir = "$env.WORKSPACE/$WORKSPACE"
|
||||||
def configurationRoot = "$env.WORKSPACE/$CONFIGURATION_DIR"
|
def configurationRoot = "$env.WORKSPACE/$CONFIGURATION_DIR"
|
||||||
|
def edtVersionForRing = EDT.ringModule(config)
|
||||||
|
|
||||||
steps.deleteDir(workspaceDir)
|
steps.deleteDir(workspaceDir)
|
||||||
steps.deleteDir(configurationRoot)
|
steps.deleteDir(configurationRoot)
|
||||||
|
|
||||||
Logger.println("Конвертация исходников из формата EDT в формат Конфигуратора")
|
Logger.println("Конвертация исходников из формата EDT в формат Конфигуратора")
|
||||||
|
|
||||||
def ringCommand = "ring edt workspace export --workspace-location \"$workspaceDir\" --project \"$projectDir\" --configuration-files \"$configurationRoot\""
|
def ringCommand = "ring $edtVersionForRing workspace export --workspace-location \"$workspaceDir\" --project \"$projectDir\" --configuration-files \"$configurationRoot\""
|
||||||
|
|
||||||
def ringOpts = [Constants.DEFAULT_RING_OPTS]
|
def ringOpts = [Constants.DEFAULT_RING_OPTS]
|
||||||
steps.withEnv(ringOpts) {
|
steps.withEnv(ringOpts) {
|
||||||
|
@ -5,6 +5,7 @@ import ru.pulsar.jenkins.library.configuration.JobConfiguration
|
|||||||
import ru.pulsar.jenkins.library.configuration.SourceFormat
|
import ru.pulsar.jenkins.library.configuration.SourceFormat
|
||||||
import ru.pulsar.jenkins.library.ioc.ContextRegistry
|
import ru.pulsar.jenkins.library.ioc.ContextRegistry
|
||||||
import ru.pulsar.jenkins.library.utils.Constants
|
import ru.pulsar.jenkins.library.utils.Constants
|
||||||
|
import ru.pulsar.jenkins.library.utils.EDT
|
||||||
import ru.pulsar.jenkins.library.utils.Logger
|
import ru.pulsar.jenkins.library.utils.Logger
|
||||||
|
|
||||||
class EdtValidate implements Serializable {
|
class EdtValidate implements Serializable {
|
||||||
@ -40,14 +41,15 @@ class EdtValidate implements Serializable {
|
|||||||
projectList = "--project-name-list $DesignerToEdtFormatTransformation.PROJECT_NAME"
|
projectList = "--project-name-list $DesignerToEdtFormatTransformation.PROJECT_NAME"
|
||||||
} else {
|
} else {
|
||||||
String projectDir = new File("$env.WORKSPACE/$config.srcDir").getCanonicalPath()
|
String projectDir = new File("$env.WORKSPACE/$config.srcDir").getCanonicalPath()
|
||||||
projectList = "--project-list '$projectDir'"
|
projectList = "--project-list \"$projectDir\""
|
||||||
}
|
}
|
||||||
|
|
||||||
def resultFile = "$env.WORKSPACE/$RESULT_FILE"
|
def resultFile = "$env.WORKSPACE/$RESULT_FILE"
|
||||||
|
def edtVersionForRing = EDT.ringModule(config)
|
||||||
|
|
||||||
Logger.println("Выполнение валидации EDT")
|
Logger.println("Выполнение валидации EDT")
|
||||||
|
|
||||||
def ringCommand = "ring edt workspace validate --workspace-location \"$workspaceLocation\" --file \"$resultFile\" $projectList"
|
def ringCommand = "ring $edtVersionForRing workspace validate --workspace-location \"$workspaceLocation\" --file \"$resultFile\" $projectList"
|
||||||
def ringOpts = [Constants.DEFAULT_RING_OPTS]
|
def ringOpts = [Constants.DEFAULT_RING_OPTS]
|
||||||
steps.withEnv(ringOpts) {
|
steps.withEnv(ringOpts) {
|
||||||
steps.catchError {
|
steps.catchError {
|
||||||
|
95
src/ru/pulsar/jenkins/library/steps/EmailNotification.groovy
Normal file
95
src/ru/pulsar/jenkins/library/steps/EmailNotification.groovy
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
package ru.pulsar.jenkins.library.steps
|
||||||
|
|
||||||
|
import hudson.model.Result
|
||||||
|
import ru.pulsar.jenkins.library.IStepExecutor
|
||||||
|
import ru.pulsar.jenkins.library.configuration.JobConfiguration
|
||||||
|
import ru.pulsar.jenkins.library.configuration.notification.email.EmailExtConfiguration
|
||||||
|
import ru.pulsar.jenkins.library.configuration.notification.email.RecipientProvider
|
||||||
|
import ru.pulsar.jenkins.library.ioc.ContextRegistry
|
||||||
|
import ru.pulsar.jenkins.library.utils.Logger
|
||||||
|
import ru.pulsar.jenkins.library.utils.StringJoiner
|
||||||
|
|
||||||
|
class EmailNotification implements Serializable {
|
||||||
|
|
||||||
|
private final JobConfiguration config;
|
||||||
|
|
||||||
|
EmailNotification(JobConfiguration config) {
|
||||||
|
this.config = config
|
||||||
|
}
|
||||||
|
|
||||||
|
def run() {
|
||||||
|
|
||||||
|
Logger.printLocation()
|
||||||
|
|
||||||
|
if (!config.stageFlags.email) {
|
||||||
|
Logger.println("Email notifications are disabled")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
IStepExecutor steps = ContextRegistry.getContext().getStepExecutor()
|
||||||
|
|
||||||
|
def options = config.notificationsOptions.emailNotificationOptions
|
||||||
|
|
||||||
|
def currentBuild = steps.currentBuild()
|
||||||
|
def currentResult = Result.fromString(currentBuild.getCurrentResult())
|
||||||
|
|
||||||
|
EmailExtConfiguration configuration = null;
|
||||||
|
if (options.onAlways) {
|
||||||
|
configuration = options.alwaysEmailOptions
|
||||||
|
} else if (options.onFailure && (currentResult == Result.FAILURE || currentResult == Result.ABORTED)) {
|
||||||
|
configuration = options.failureEmailOptions
|
||||||
|
} else if (options.onUnstable && currentResult == Result.UNSTABLE) {
|
||||||
|
configuration = options.unstableEmailOptions
|
||||||
|
} else if (options.onSuccess && currentResult == Result.SUCCESS) {
|
||||||
|
configuration = options.successEmailOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
sendEmail(configuration)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void sendEmail(EmailExtConfiguration configuration) {
|
||||||
|
|
||||||
|
if (configuration == null) {
|
||||||
|
Logger.println("Unknown build result. Can't send an email!")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
IStepExecutor steps = ContextRegistry.getContext().getStepExecutor()
|
||||||
|
|
||||||
|
String subject = '$DEFAULT_SUBJECT'
|
||||||
|
String body = '$DEFAULT_CONTENT'
|
||||||
|
|
||||||
|
StringJoiner toJoiner = new StringJoiner(",")
|
||||||
|
configuration.directRecipients.each {
|
||||||
|
toJoiner.add(it)
|
||||||
|
}
|
||||||
|
String to = toJoiner.toString()
|
||||||
|
|
||||||
|
List recipientProviders = new ArrayList();
|
||||||
|
configuration.recipientProviders.each {
|
||||||
|
switch (it) {
|
||||||
|
case RecipientProvider.BROKEN_BUILD_SUSPECTS:
|
||||||
|
recipientProviders.add(steps.brokenBuildSuspects())
|
||||||
|
break
|
||||||
|
case RecipientProvider.BROKEN_TESTS_SUSPECTS:
|
||||||
|
recipientProviders.add(steps.brokenTestsSuspects())
|
||||||
|
break
|
||||||
|
case RecipientProvider.DEVELOPERS:
|
||||||
|
recipientProviders.add(steps.developers())
|
||||||
|
break
|
||||||
|
case RecipientProvider.REQUESTOR:
|
||||||
|
recipientProviders.add(steps.requestor())
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
steps.emailext(
|
||||||
|
subject,
|
||||||
|
body,
|
||||||
|
to,
|
||||||
|
recipientProviders,
|
||||||
|
configuration.attachLog
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -7,6 +7,7 @@ import ru.pulsar.jenkins.library.configuration.JobConfiguration
|
|||||||
import ru.pulsar.jenkins.library.configuration.Secrets
|
import ru.pulsar.jenkins.library.configuration.Secrets
|
||||||
import ru.pulsar.jenkins.library.ioc.ContextRegistry
|
import ru.pulsar.jenkins.library.ioc.ContextRegistry
|
||||||
import ru.pulsar.jenkins.library.utils.Logger
|
import ru.pulsar.jenkins.library.utils.Logger
|
||||||
|
import ru.pulsar.jenkins.library.utils.RepoUtils
|
||||||
import ru.pulsar.jenkins.library.utils.VRunner
|
import ru.pulsar.jenkins.library.utils.VRunner
|
||||||
import ru.pulsar.jenkins.library.utils.VersionParser
|
import ru.pulsar.jenkins.library.utils.VersionParser
|
||||||
|
|
||||||
@ -14,8 +15,6 @@ import static ru.pulsar.jenkins.library.configuration.Secrets.UNKNOWN_ID
|
|||||||
|
|
||||||
class InitFromStorage implements Serializable {
|
class InitFromStorage implements Serializable {
|
||||||
|
|
||||||
final static REPO_SLUG_REGEXP = ~/(?m)^(?:[^:\/?#\n]+:)?(?:\/+[^\/?#\n]*)?\/?([^?\n]*)/
|
|
||||||
|
|
||||||
private final JobConfiguration config
|
private final JobConfiguration config
|
||||||
|
|
||||||
InitFromStorage(JobConfiguration config) {
|
InitFromStorage(JobConfiguration config) {
|
||||||
@ -37,8 +36,7 @@ class InitFromStorage implements Serializable {
|
|||||||
String storageVersion = VersionParser.storage()
|
String storageVersion = VersionParser.storage()
|
||||||
String storageVersionParameter = storageVersion == "" ? "" : "--storage-ver $storageVersion"
|
String storageVersionParameter = storageVersion == "" ? "" : "--storage-ver $storageVersion"
|
||||||
|
|
||||||
EnvironmentAction env = steps.env();
|
String repoSlug = RepoUtils.getRepoSlug()
|
||||||
String repoSlug = computeRepoSlug(env.GIT_URL)
|
|
||||||
|
|
||||||
Secrets secrets = config.secrets
|
Secrets secrets = config.secrets
|
||||||
|
|
||||||
@ -61,14 +59,4 @@ class InitFromStorage implements Serializable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonCPS
|
|
||||||
private static String computeRepoSlug(String text) {
|
|
||||||
def matcher = text =~ REPO_SLUG_REGEXP
|
|
||||||
String repoSlug = matcher != null && matcher.getCount() == 1 ? matcher[0][1] : ""
|
|
||||||
if (repoSlug.endsWith(".git")) {
|
|
||||||
repoSlug = repoSlug[0..-5]
|
|
||||||
}
|
|
||||||
repoSlug = repoSlug.replace('/', '_')
|
|
||||||
return repoSlug
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -17,13 +17,19 @@ class PublishAllure implements Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def run() {
|
def run() {
|
||||||
steps = ContextRegistry.getContext().getStepExecutor()
|
|
||||||
|
|
||||||
Logger.printLocation()
|
Logger.printLocation()
|
||||||
|
|
||||||
|
if (config == null) {
|
||||||
|
Logger.println("jobConfiguration is not initialized")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
steps = ContextRegistry.getContext().getStepExecutor()
|
||||||
|
|
||||||
safeUnstash('init-allure')
|
safeUnstash('init-allure')
|
||||||
safeUnstash('bdd-allure')
|
safeUnstash('bdd-allure')
|
||||||
if (config.smokeTestOptions.publishToAllureReport) {
|
if (config.stageFlags.smoke && config.smokeTestOptions.publishToAllureReport) {
|
||||||
safeUnstash(SmokeTest.SMOKE_ALLURE_STASH)
|
safeUnstash(SmokeTest.SMOKE_ALLURE_STASH)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ class ResultsTransformer implements Serializable {
|
|||||||
def genericIssueFile = "$env.WORKSPACE/$RESULT_FILE"
|
def genericIssueFile = "$env.WORKSPACE/$RESULT_FILE"
|
||||||
|
|
||||||
String srcDir = config.sourceFormat == SourceFormat.DESIGNER ? config.srcDir : Paths.get(config.srcDir, "src")
|
String srcDir = config.sourceFormat == SourceFormat.DESIGNER ? config.srcDir : Paths.get(config.srcDir, "src")
|
||||||
steps.cmd("stebi convert $edtValidateFile $genericIssueFile $srcDir")
|
steps.cmd("stebi convert -r $edtValidateFile $genericIssueFile $srcDir")
|
||||||
|
|
||||||
if (config.resultsTransformOptions.removeSupport) {
|
if (config.resultsTransformOptions.removeSupport) {
|
||||||
def supportLevel = config.resultsTransformOptions.supportLevel
|
def supportLevel = config.resultsTransformOptions.supportLevel
|
||||||
|
30
src/ru/pulsar/jenkins/library/steps/SendNotifications.groovy
Normal file
30
src/ru/pulsar/jenkins/library/steps/SendNotifications.groovy
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package ru.pulsar.jenkins.library.steps
|
||||||
|
|
||||||
|
import ru.pulsar.jenkins.library.configuration.JobConfiguration
|
||||||
|
import ru.pulsar.jenkins.library.utils.Logger
|
||||||
|
|
||||||
|
class SendNotifications implements Serializable {
|
||||||
|
|
||||||
|
private final JobConfiguration config;
|
||||||
|
|
||||||
|
SendNotifications(JobConfiguration config) {
|
||||||
|
this.config = config
|
||||||
|
}
|
||||||
|
|
||||||
|
def run() {
|
||||||
|
|
||||||
|
Logger.printLocation()
|
||||||
|
|
||||||
|
if (config == null) {
|
||||||
|
Logger.println("jobConfiguration is not initialized")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
def emailNotification = new EmailNotification(config);
|
||||||
|
emailNotification.run()
|
||||||
|
|
||||||
|
def telegramNotification = new TelegramNotification(config);
|
||||||
|
telegramNotification.run();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -6,6 +6,7 @@ import ru.pulsar.jenkins.library.configuration.JobConfiguration
|
|||||||
import ru.pulsar.jenkins.library.ioc.ContextRegistry
|
import ru.pulsar.jenkins.library.ioc.ContextRegistry
|
||||||
import ru.pulsar.jenkins.library.utils.FileUtils
|
import ru.pulsar.jenkins.library.utils.FileUtils
|
||||||
import ru.pulsar.jenkins.library.utils.Logger
|
import ru.pulsar.jenkins.library.utils.Logger
|
||||||
|
import ru.pulsar.jenkins.library.utils.StringJoiner
|
||||||
import ru.pulsar.jenkins.library.utils.VRunner
|
import ru.pulsar.jenkins.library.utils.VRunner
|
||||||
|
|
||||||
class SmokeTest implements Serializable {
|
class SmokeTest implements Serializable {
|
||||||
@ -61,14 +62,14 @@ class SmokeTest implements Serializable {
|
|||||||
FilePath pathToAllureReport = FileUtils.getFilePath("$env.WORKSPACE/$allureReport")
|
FilePath pathToAllureReport = FileUtils.getFilePath("$env.WORKSPACE/$allureReport")
|
||||||
String allureReportDir = FileUtils.getLocalPath(pathToAllureReport.getParent())
|
String allureReportDir = FileUtils.getLocalPath(pathToAllureReport.getParent())
|
||||||
|
|
||||||
StringBuilder reportsConfigConstructor = new StringBuilder()
|
StringJoiner reportsConfigConstructor = new StringJoiner(";")
|
||||||
|
|
||||||
if (options.publishToJUnitReport) {
|
if (options.publishToJUnitReport) {
|
||||||
steps.createDir(junitReportDir)
|
steps.createDir(junitReportDir)
|
||||||
|
|
||||||
String junitReportCommand = "ГенераторОтчетаJUnitXML{$junitReport}"
|
String junitReportCommand = "ГенераторОтчетаJUnitXML{$junitReport}"
|
||||||
|
|
||||||
reportsConfigConstructor.append(junitReportCommand)
|
reportsConfigConstructor.add(junitReportCommand)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.publishToAllureReport) {
|
if (options.publishToAllureReport) {
|
||||||
@ -76,10 +77,7 @@ class SmokeTest implements Serializable {
|
|||||||
|
|
||||||
String allureReportCommand = "ГенераторОтчетаAllureXMLВерсия2{$allureReport}"
|
String allureReportCommand = "ГенераторОтчетаAllureXMLВерсия2{$allureReport}"
|
||||||
|
|
||||||
if (reportsConfigConstructor.length() > 0) {
|
reportsConfigConstructor.add(allureReportCommand)
|
||||||
reportsConfigConstructor.append(';')
|
|
||||||
}
|
|
||||||
reportsConfigConstructor.append(allureReportCommand)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reportsConfigConstructor.length() > 0) {
|
if (reportsConfigConstructor.length() > 0) {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package ru.pulsar.jenkins.library.steps
|
package ru.pulsar.jenkins.library.steps
|
||||||
|
|
||||||
import ru.pulsar.jenkins.library.IStepExecutor
|
import ru.pulsar.jenkins.library.IStepExecutor
|
||||||
|
import ru.pulsar.jenkins.library.configuration.BranchAnalysisConfiguration
|
||||||
import ru.pulsar.jenkins.library.configuration.JobConfiguration
|
import ru.pulsar.jenkins.library.configuration.JobConfiguration
|
||||||
import ru.pulsar.jenkins.library.configuration.SourceFormat
|
import ru.pulsar.jenkins.library.configuration.SourceFormat
|
||||||
import ru.pulsar.jenkins.library.ioc.ContextRegistry
|
import ru.pulsar.jenkins.library.ioc.ContextRegistry
|
||||||
@ -36,7 +37,20 @@ class SonarScanner implements Serializable {
|
|||||||
sonarScannerBinary = "$scannerHome/bin/sonar-scanner"
|
sonarScannerBinary = "$scannerHome/bin/sonar-scanner"
|
||||||
}
|
}
|
||||||
|
|
||||||
String sonarCommand = "$sonarScannerBinary -Dsonar.branch.name=$env.BRANCH_NAME"
|
String sonarCommand = "$sonarScannerBinary"
|
||||||
|
|
||||||
|
def branchAnalysisConfiguration = config.sonarQubeOptions.branchAnalysisConfiguration
|
||||||
|
if (branchAnalysisConfiguration == BranchAnalysisConfiguration.FROM_ENV) {
|
||||||
|
if (env.CHANGE_ID){
|
||||||
|
sonarCommand += " -Dsonar.pullrequest.key=$env.CHANGE_ID"
|
||||||
|
sonarCommand += " -Dsonar.pullrequest.branch=$env.CHANGE_BRANCH"
|
||||||
|
sonarCommand += " -Dsonar.pullrequest.base=$env.CHANGE_TARGET"
|
||||||
|
} else {
|
||||||
|
sonarCommand += " -Dsonar.branch.name=$env.BRANCH_NAME"
|
||||||
|
}
|
||||||
|
} else (branchAnalysisConfiguration == BranchAnalysisConfiguration.AUTO) {
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
|
|
||||||
String projectVersion = computeProjectVersion()
|
String projectVersion = computeProjectVersion()
|
||||||
if (projectVersion) {
|
if (projectVersion) {
|
||||||
@ -48,6 +62,12 @@ class SonarScanner implements Serializable {
|
|||||||
sonarCommand += " -Dsonar.externalIssuesReportPaths=build/out/edt-generic-issue.json"
|
sonarCommand += " -Dsonar.externalIssuesReportPaths=build/out/edt-generic-issue.json"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (config.sonarQubeOptions.waitForQualityGate) {
|
||||||
|
def timeoutInSeconds = config.timeoutOptions.sonarqube * 60
|
||||||
|
sonarCommand += ' -Dsonar.qualitygate.wait=true'
|
||||||
|
sonarCommand += " -Dsonar.qualitygate.timeout=${timeoutInSeconds}"
|
||||||
|
}
|
||||||
|
|
||||||
def sonarQubeInstallation = config.sonarQubeOptions.sonarQubeInstallation
|
def sonarQubeInstallation = config.sonarQubeOptions.sonarQubeInstallation
|
||||||
if (sonarQubeInstallation == '') {
|
if (sonarQubeInstallation == '') {
|
||||||
sonarQubeInstallation = null
|
sonarQubeInstallation = null
|
||||||
|
251
src/ru/pulsar/jenkins/library/steps/TelegramNotification.groovy
Normal file
251
src/ru/pulsar/jenkins/library/steps/TelegramNotification.groovy
Normal file
@ -0,0 +1,251 @@
|
|||||||
|
package ru.pulsar.jenkins.library.steps
|
||||||
|
|
||||||
|
import com.cloudbees.groovy.cps.NonCPS
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper
|
||||||
|
import hudson.model.Result
|
||||||
|
import hudson.scm.ChangeLogSet
|
||||||
|
import io.jenkins.blueocean.rest.impl.pipeline.FlowNodeWrapper
|
||||||
|
import io.jenkins.blueocean.rest.impl.pipeline.PipelineNodeGraphVisitor
|
||||||
|
import io.jenkins.blueocean.rest.model.BlueRun
|
||||||
|
import io.jenkins.cli.shaded.org.apache.commons.lang.time.DurationFormatUtils
|
||||||
|
import jenkins.plugins.http_request.HttpMode
|
||||||
|
import jenkins.plugins.http_request.MimeType
|
||||||
|
import org.jenkinsci.plugins.workflow.actions.TimingAction
|
||||||
|
import org.jenkinsci.plugins.workflow.graph.BlockStartNode
|
||||||
|
import org.jenkinsci.plugins.workflow.job.WorkflowRun
|
||||||
|
import org.jenkinsci.plugins.workflow.support.steps.build.RunWrapper
|
||||||
|
import ru.pulsar.jenkins.library.IStepExecutor
|
||||||
|
import ru.pulsar.jenkins.library.configuration.JobConfiguration
|
||||||
|
import ru.pulsar.jenkins.library.configuration.Secrets
|
||||||
|
import ru.pulsar.jenkins.library.ioc.ContextRegistry
|
||||||
|
import ru.pulsar.jenkins.library.utils.Logger
|
||||||
|
import ru.pulsar.jenkins.library.utils.RepoUtils
|
||||||
|
import ru.pulsar.jenkins.library.utils.StringJoiner
|
||||||
|
|
||||||
|
import static ru.pulsar.jenkins.library.configuration.Secrets.UNKNOWN_ID
|
||||||
|
|
||||||
|
class TelegramNotification implements Serializable {
|
||||||
|
|
||||||
|
private final JobConfiguration config;
|
||||||
|
|
||||||
|
TelegramNotification(JobConfiguration config) {
|
||||||
|
this.config = config
|
||||||
|
}
|
||||||
|
|
||||||
|
def run() {
|
||||||
|
|
||||||
|
Logger.printLocation()
|
||||||
|
|
||||||
|
if (!config.stageFlags.telegram) {
|
||||||
|
Logger.println("Telegram notifications are disabled")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
IStepExecutor steps = ContextRegistry.getContext().getStepExecutor()
|
||||||
|
|
||||||
|
def options = config.notificationsOptions.telegramNotificationOptions
|
||||||
|
|
||||||
|
def currentBuild = steps.currentBuild()
|
||||||
|
def currentResult = Result.fromString(currentBuild.getCurrentResult())
|
||||||
|
|
||||||
|
String message = getMessage(currentBuild)
|
||||||
|
|
||||||
|
if (options.onAlways) {
|
||||||
|
sendMessage(message)
|
||||||
|
} else if (options.onFailure && (currentResult == Result.FAILURE || currentResult == Result.ABORTED)) {
|
||||||
|
sendMessage(message)
|
||||||
|
} else if (options.onUnstable && currentResult == Result.UNSTABLE) {
|
||||||
|
sendMessage(message)
|
||||||
|
} else if (options.onSuccess && currentResult == Result.SUCCESS) {
|
||||||
|
sendMessage(message)
|
||||||
|
} else {
|
||||||
|
Logger.println("Unknown build result! Can't send a message to telegram")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendMessage(message) {
|
||||||
|
IStepExecutor steps = ContextRegistry.getContext().getStepExecutor()
|
||||||
|
def env = steps.env();
|
||||||
|
|
||||||
|
String repoSlug = RepoUtils.getRepoSlug()
|
||||||
|
|
||||||
|
Secrets secrets = config.secrets
|
||||||
|
|
||||||
|
String telegramChatIdCredentials = secrets.telegramChatId == UNKNOWN_ID ? repoSlug + "_TELEGRAM_CHAT_ID" : secrets.telegramChatId
|
||||||
|
String telegramBotTokenCredentials = secrets.telegramBotToken == UNKNOWN_ID ? "TELEGRAM_BOT_TOKEN" : secrets.telegramBotToken
|
||||||
|
|
||||||
|
steps.withCredentials([
|
||||||
|
steps.string(telegramBotTokenCredentials, 'TOKEN'),
|
||||||
|
steps.string(telegramChatIdCredentials, 'CHAT_ID')
|
||||||
|
]) {
|
||||||
|
|
||||||
|
def mapper = new ObjectMapper()
|
||||||
|
|
||||||
|
def body = [
|
||||||
|
chat_id : env.CHAT_ID,
|
||||||
|
text : message,
|
||||||
|
disable_web_page_preview: true,
|
||||||
|
parse_mode : 'MarkdownV2'
|
||||||
|
]
|
||||||
|
|
||||||
|
def bodyString = mapper.writeValueAsString(body)
|
||||||
|
String url = "https://api.telegram.org/bot${env.TOKEN}/sendMessage"
|
||||||
|
|
||||||
|
steps.echo(message)
|
||||||
|
steps.echo(bodyString)
|
||||||
|
|
||||||
|
steps.httpRequest(
|
||||||
|
url,
|
||||||
|
HttpMode.POST,
|
||||||
|
MimeType.APPLICATION_JSON_UTF8,
|
||||||
|
bodyString,
|
||||||
|
'200',
|
||||||
|
true
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getMessage(RunWrapper currentBuild) {
|
||||||
|
|
||||||
|
IStepExecutor steps = ContextRegistry.getContext().getStepExecutor()
|
||||||
|
def env = steps.env();
|
||||||
|
|
||||||
|
def currentResult = Result.fromString(currentBuild.getCurrentResult())
|
||||||
|
|
||||||
|
def messageJoiner = new StringJoiner('\n\n')
|
||||||
|
|
||||||
|
def displayName = escapeStringForMarkdownV2(currentBuild.fullDisplayName)
|
||||||
|
String header = "[$displayName]($env.BUILD_URL)"
|
||||||
|
messageJoiner.add(header)
|
||||||
|
|
||||||
|
String result = ""
|
||||||
|
if (currentResult == Result.SUCCESS) {
|
||||||
|
result = "✅ Сборка прошла успешно!"
|
||||||
|
} else if (currentResult == Result.FAILURE) {
|
||||||
|
result = "❌ Сборка завершилась с ошибкой!"
|
||||||
|
} else if (currentResult == Result.ABORTED) {
|
||||||
|
result = "🛑 Сборка прервана!"
|
||||||
|
} else if (currentResult == Result.UNSTABLE) {
|
||||||
|
result = "💩 Есть упавшие тесты!"
|
||||||
|
}
|
||||||
|
|
||||||
|
result = escapeStringForMarkdownV2(result)
|
||||||
|
messageJoiner.add(result)
|
||||||
|
|
||||||
|
String stageResults = getStageResultsMessage(currentBuild)
|
||||||
|
if (stageResults.length() > 0) {
|
||||||
|
stageResults = escapeStringForMarkdownV2(stageResults)
|
||||||
|
messageJoiner.add(stageResults)
|
||||||
|
}
|
||||||
|
|
||||||
|
def duration = "Длительность сборки: ${currentBuild.getDurationString()}".replace(" and counting", "")
|
||||||
|
duration = escapeStringForMarkdownV2(duration)
|
||||||
|
messageJoiner.add(duration)
|
||||||
|
|
||||||
|
def changeSet = getChangeSet(currentBuild)
|
||||||
|
steps.echo(changeSet)
|
||||||
|
if (changeSet.length() > 0) {
|
||||||
|
changeSet = 'Изменения с последней сборки:\n\n' + changeSet
|
||||||
|
messageJoiner.add(changeSet)
|
||||||
|
}
|
||||||
|
|
||||||
|
String buildUrl = "[Лог сборки](${env.BUILD_URL}console)"
|
||||||
|
messageJoiner.add(buildUrl)
|
||||||
|
|
||||||
|
steps.echo(messageJoiner.toString())
|
||||||
|
|
||||||
|
return messageJoiner.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonCPS
|
||||||
|
private static String getChangeSet(RunWrapper currentBuild) {
|
||||||
|
String changeSetText = ''
|
||||||
|
|
||||||
|
int counter = 0
|
||||||
|
currentBuild.changeSets.each { changeSet ->
|
||||||
|
changeSetText += "Набор изменений \\#${++counter}:\n"
|
||||||
|
changeSet.items.each { ChangeLogSet.Entry entry ->
|
||||||
|
String commit = ''
|
||||||
|
def commitId = entry.commitId;
|
||||||
|
if (commitId != null) {
|
||||||
|
if (isValidSHA1(commitId)) {
|
||||||
|
commitId = commitId.substring(0, 7)
|
||||||
|
}
|
||||||
|
|
||||||
|
def link = changeSet.browser?.getChangeSetLink(entry)
|
||||||
|
if (link != null) {
|
||||||
|
commit = "[$commitId]($link)"
|
||||||
|
} else {
|
||||||
|
commit = commitId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def author = escapeStringForMarkdownV2(entry.author.displayName)
|
||||||
|
def authorLink = entry.author.absoluteUrl
|
||||||
|
|
||||||
|
def message = escapeStringForMarkdownV2(entry.getMsgAnnotated())
|
||||||
|
changeSetText += "\\* $commit $message \\([$author]($authorLink)\\)\n"
|
||||||
|
}
|
||||||
|
changeSetText += '\n'
|
||||||
|
}
|
||||||
|
return changeSetText.trim()
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonCPS
|
||||||
|
private static String getStageResultsMessage(RunWrapper currentBuild) {
|
||||||
|
def visitor = new PipelineNodeGraphVisitor(currentBuild.rawBuild as WorkflowRun)
|
||||||
|
def stages = visitor.pipelineNodes.findAll { it.type != FlowNodeWrapper.NodeType.STEP }
|
||||||
|
|
||||||
|
def stageResultMessage = ""
|
||||||
|
for (FlowNodeWrapper stage in stages) {
|
||||||
|
if (stage.status.result == BlueRun.BlueRunResult.SUCCESS || stage.status.result == BlueRun.BlueRunResult.NOT_BUILT) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
long duration
|
||||||
|
def endNode = stage.node.getExecution().getEndNode(stage.node as BlockStartNode)
|
||||||
|
if (endNode != null) {
|
||||||
|
def startTime = TimingAction.getStartTime(stage.node)
|
||||||
|
def endTime = TimingAction.getStartTime(endNode)
|
||||||
|
|
||||||
|
duration = endTime - startTime
|
||||||
|
} else {
|
||||||
|
duration = stage.timing.totalDurationMillis
|
||||||
|
}
|
||||||
|
|
||||||
|
def time = DurationFormatUtils.formatDuration(duration, "H:mm:ss")
|
||||||
|
stageResultMessage += "$stage.displayName: $stage.status.result, затрачено времени $time \n"
|
||||||
|
}
|
||||||
|
|
||||||
|
return stageResultMessage.trim()
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonCPS
|
||||||
|
private static String escapeStringForMarkdownV2(String incoming) {
|
||||||
|
return incoming.replace('_', '\\_')
|
||||||
|
.replace('*', '\\*')
|
||||||
|
.replace('[', '\\[')
|
||||||
|
.replace(']', '\\]')
|
||||||
|
.replace('(', '\\(')
|
||||||
|
.replace(')', '\\)')
|
||||||
|
.replace('~', '\\~')
|
||||||
|
.replace('`', '\\`')
|
||||||
|
.replace('>', '\\>')
|
||||||
|
.replace('#', '\\#')
|
||||||
|
.replace('+', '\\+')
|
||||||
|
.replace('-', '\\-')
|
||||||
|
.replace('=', '\\=')
|
||||||
|
.replace('|', '\\|')
|
||||||
|
.replace('{', '\\{')
|
||||||
|
.replace('}', '\\}')
|
||||||
|
.replace('.', '\\.')
|
||||||
|
.replace('!', '\\!')
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonCPS
|
||||||
|
private static boolean isValidSHA1(String s) {
|
||||||
|
return s.matches('^[a-fA-F0-9]{40}$');
|
||||||
|
}
|
||||||
|
}
|
12
src/ru/pulsar/jenkins/library/utils/EDT.groovy
Normal file
12
src/ru/pulsar/jenkins/library/utils/EDT.groovy
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package ru.pulsar.jenkins.library.utils
|
||||||
|
|
||||||
|
import ru.pulsar.jenkins.library.configuration.JobConfiguration
|
||||||
|
|
||||||
|
final class EDT {
|
||||||
|
|
||||||
|
static String ringModule(JobConfiguration config) {
|
||||||
|
return config.edtAgentLabel()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
24
src/ru/pulsar/jenkins/library/utils/RepoUtils.groovy
Normal file
24
src/ru/pulsar/jenkins/library/utils/RepoUtils.groovy
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package ru.pulsar.jenkins.library.utils
|
||||||
|
|
||||||
|
import com.cloudbees.groovy.cps.NonCPS
|
||||||
|
|
||||||
|
class RepoUtils implements Serializable {
|
||||||
|
|
||||||
|
private final static REPO_SLUG_REGEXP = ~/(?m)^(?:[^:\/?#\n]+:)?(?:\/+[^\/?#\n]*)?\/?([^?\n]*)/
|
||||||
|
private static String REPO_SLUG;
|
||||||
|
|
||||||
|
@NonCPS
|
||||||
|
static void computeRepoSlug(String text) {
|
||||||
|
def matcher = text =~ REPO_SLUG_REGEXP
|
||||||
|
String repoSlug = matcher != null && matcher.getCount() == 1 ? matcher[0][1] : ""
|
||||||
|
if (repoSlug.endsWith(".git")) {
|
||||||
|
repoSlug = repoSlug[0..-5]
|
||||||
|
}
|
||||||
|
|
||||||
|
REPO_SLUG = repoSlug.replace('/', '_')
|
||||||
|
}
|
||||||
|
|
||||||
|
static String getRepoSlug() {
|
||||||
|
return REPO_SLUG
|
||||||
|
}
|
||||||
|
}
|
37
src/ru/pulsar/jenkins/library/utils/StringJoiner.groovy
Normal file
37
src/ru/pulsar/jenkins/library/utils/StringJoiner.groovy
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
package ru.pulsar.jenkins.library.utils
|
||||||
|
|
||||||
|
class StringJoiner implements Serializable {
|
||||||
|
private final String delimiter
|
||||||
|
private StringBuilder value
|
||||||
|
|
||||||
|
StringJoiner(CharSequence delimiter) {
|
||||||
|
this.delimiter = delimiter
|
||||||
|
}
|
||||||
|
|
||||||
|
StringJoiner add(CharSequence newElement) {
|
||||||
|
prepareBuilder().append(newElement)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
int length() {
|
||||||
|
return (value != null ? value.length() : 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
String toString() {
|
||||||
|
if (value == null) {
|
||||||
|
return ""
|
||||||
|
} else {
|
||||||
|
return value.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private StringBuilder prepareBuilder() {
|
||||||
|
if (value != null) {
|
||||||
|
value.append(delimiter)
|
||||||
|
} else {
|
||||||
|
value = new StringBuilder()
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,7 @@ package ru.pulsar.jenkins.library.configuration;
|
|||||||
|
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Disabled;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import ru.pulsar.jenkins.library.utils.TestUtils;
|
import ru.pulsar.jenkins.library.utils.TestUtils;
|
||||||
|
|
||||||
@ -9,6 +10,7 @@ import java.io.IOException;
|
|||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static ru.pulsar.jenkins.library.configuration.BranchAnalysisConfiguration.AUTO;
|
||||||
|
|
||||||
class ConfigurationReaderTest {
|
class ConfigurationReaderTest {
|
||||||
|
|
||||||
@ -31,10 +33,12 @@ class ConfigurationReaderTest {
|
|||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(jobConfiguration.getV8version()).isEqualTo("8.3.14.1944");
|
assertThat(jobConfiguration.getV8version()).isEqualTo("8.3.14.1944");
|
||||||
|
assertThat(jobConfiguration.getEdtVersion()).isEqualTo("2021.3.4:x86_64");
|
||||||
|
|
||||||
assertThat(jobConfiguration.getSonarQubeOptions().getSonarScannerToolName()).isEqualTo("sonar-scanner");
|
assertThat(jobConfiguration.getSonarQubeOptions().getSonarScannerToolName()).isEqualTo("sonar-scanner");
|
||||||
assertThat(jobConfiguration.getSonarQubeOptions().getSonarQubeInstallation()).isEqualTo("qa");
|
assertThat(jobConfiguration.getSonarQubeOptions().getSonarQubeInstallation()).isEqualTo("qa");
|
||||||
assertThat(jobConfiguration.getSonarQubeOptions().getUseSonarScannerFromPath()).isTrue();
|
assertThat(jobConfiguration.getSonarQubeOptions().getUseSonarScannerFromPath()).isTrue();
|
||||||
|
assertThat(jobConfiguration.getSonarQubeOptions().getBranchAnalysisConfiguration()).isEqualTo(AUTO);
|
||||||
|
|
||||||
assertThat(jobConfiguration.getSecrets())
|
assertThat(jobConfiguration.getSecrets())
|
||||||
.hasFieldOrPropertyWithValue("storage", "1234")
|
.hasFieldOrPropertyWithValue("storage", "1234")
|
||||||
@ -59,6 +63,66 @@ class ConfigurationReaderTest {
|
|||||||
|
|
||||||
assertThat(jobConfiguration.getTimeoutOptions().getBdd()).isEqualTo(120);
|
assertThat(jobConfiguration.getTimeoutOptions().getBdd()).isEqualTo(120);
|
||||||
assertThat(jobConfiguration.getTimeoutOptions().getZipInfoBase()).isEqualTo(123);
|
assertThat(jobConfiguration.getTimeoutOptions().getZipInfoBase()).isEqualTo(123);
|
||||||
|
|
||||||
|
assertThat(jobConfiguration.getNotificationsOptions().getEmailNotificationOptions().getOnAlways()).isTrue();
|
||||||
|
assertThat(jobConfiguration.getNotificationsOptions().getEmailNotificationOptions().getOnSuccess()).isFalse();
|
||||||
|
assertThat(jobConfiguration.getNotificationsOptions().getEmailNotificationOptions().getAlwaysEmailOptions().getAttachLog()).isTrue();
|
||||||
|
assertThat(jobConfiguration.getNotificationsOptions().getEmailNotificationOptions().getAlwaysEmailOptions().getRecipientProviders()).hasSize(2);
|
||||||
|
assertThat(jobConfiguration.getNotificationsOptions().getEmailNotificationOptions().getAlwaysEmailOptions().getDirectRecipients()).hasSize(2);
|
||||||
|
|
||||||
|
assertThat(jobConfiguration.getNotificationsOptions().getEmailNotificationOptions().getFailureEmailOptions().getDirectRecipients()).isEmpty();
|
||||||
|
assertThat(jobConfiguration.getNotificationsOptions().getEmailNotificationOptions().getFailureEmailOptions().getRecipientProviders()).hasSize(1);
|
||||||
|
|
||||||
|
assertThat(jobConfiguration.getNotificationsOptions().getTelegramNotificationOptions().getOnAlways()).isFalse();
|
||||||
|
assertThat(jobConfiguration.getNotificationsOptions().getTelegramNotificationOptions().getOnFailure()).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testV8AgentLabel() throws IOException {
|
||||||
|
// given
|
||||||
|
String config = IOUtils.resourceToString(
|
||||||
|
"jobConfiguration.json",
|
||||||
|
StandardCharsets.UTF_8,
|
||||||
|
this.getClass().getClassLoader()
|
||||||
|
);
|
||||||
|
|
||||||
|
// when
|
||||||
|
JobConfiguration jobConfiguration = ConfigurationReader.create(config);
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(jobConfiguration.v8AgentLabel()).isEqualTo("8.3.14.1944");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testEdtAgentLabel() throws IOException {
|
||||||
|
// given
|
||||||
|
String config = IOUtils.resourceToString(
|
||||||
|
"jobConfiguration.json",
|
||||||
|
StandardCharsets.UTF_8,
|
||||||
|
this.getClass().getClassLoader()
|
||||||
|
);
|
||||||
|
|
||||||
|
// when
|
||||||
|
JobConfiguration jobConfiguration = ConfigurationReader.create(config);
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(jobConfiguration.edtAgentLabel()).isEqualTo("edt@2021.3.4:x86_64");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Disabled
|
||||||
|
void testInfoBaseFromFiles() throws IOException {
|
||||||
|
// given
|
||||||
|
String config = IOUtils.resourceToString(
|
||||||
|
"jobConfiguration.json",
|
||||||
|
StandardCharsets.UTF_8,
|
||||||
|
this.getClass().getClassLoader()
|
||||||
|
);
|
||||||
|
|
||||||
|
// when
|
||||||
|
JobConfiguration jobConfiguration = ConfigurationReader.create(config);
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(jobConfiguration.infoBaseFromFiles()).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
package ru.pulsar.jenkins.library.utils;
|
||||||
|
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import ru.pulsar.jenkins.library.configuration.ConfigurationReader;
|
||||||
|
import ru.pulsar.jenkins.library.configuration.JobConfiguration;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
class EDTTest {
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() {
|
||||||
|
TestUtils.setupMockedContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testRingModule() throws IOException {
|
||||||
|
|
||||||
|
// given
|
||||||
|
String config = IOUtils.resourceToString(
|
||||||
|
"jobConfiguration.json",
|
||||||
|
StandardCharsets.UTF_8,
|
||||||
|
this.getClass().getClassLoader()
|
||||||
|
);
|
||||||
|
|
||||||
|
// when
|
||||||
|
JobConfiguration jobConfiguration = ConfigurationReader.create(config);
|
||||||
|
String edtModule = EDT.ringModule(jobConfiguration);
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(edtModule).isEqualTo("edt@2021.3.4:x86_64");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"v8version": "8.3.14.1944",
|
"v8version": "8.3.14.1944",
|
||||||
|
"edtVersion": "2021.3.4:x86_64",
|
||||||
"secrets": {
|
"secrets": {
|
||||||
"storage": "1234"
|
"storage": "1234"
|
||||||
},
|
},
|
||||||
@ -16,7 +17,8 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"sonarqube": {
|
"sonarqube": {
|
||||||
"sonarQubeInstallation": "qa"
|
"sonarQubeInstallation": "qa",
|
||||||
|
"branchAnalysisConfiguration": "auto"
|
||||||
},
|
},
|
||||||
"syntaxCheck": {
|
"syntaxCheck": {
|
||||||
"checkModes": ["-ThinClient"]
|
"checkModes": ["-ThinClient"]
|
||||||
@ -29,5 +31,26 @@
|
|||||||
"publishToAllureReport": false,
|
"publishToAllureReport": false,
|
||||||
"publishToJUnitReport": true
|
"publishToJUnitReport": true
|
||||||
},
|
},
|
||||||
|
"notifications": {
|
||||||
|
"email": {
|
||||||
|
"onAlways": true,
|
||||||
|
"alwaysOptions": {
|
||||||
|
"attachLog": true,
|
||||||
|
"directRecipients": [
|
||||||
|
"1@1.com",
|
||||||
|
"2@1.com"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"failureOptions": {
|
||||||
|
"recipientProviders": [
|
||||||
|
"developers"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"telegram": {
|
||||||
|
"onAlways": false,
|
||||||
|
"onFailure": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"logosConfig": "logger.rootLogger=DEBUG"
|
"logosConfig": "logger.rootLogger=DEBUG"
|
||||||
}
|
}
|
@ -2,6 +2,7 @@
|
|||||||
import groovy.transform.Field
|
import groovy.transform.Field
|
||||||
import ru.pulsar.jenkins.library.configuration.JobConfiguration
|
import ru.pulsar.jenkins.library.configuration.JobConfiguration
|
||||||
import ru.pulsar.jenkins.library.configuration.SourceFormat
|
import ru.pulsar.jenkins.library.configuration.SourceFormat
|
||||||
|
import ru.pulsar.jenkins.library.utils.RepoUtils
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
@ -11,6 +12,9 @@ JobConfiguration config
|
|||||||
@Field
|
@Field
|
||||||
String agent1C
|
String agent1C
|
||||||
|
|
||||||
|
@Field
|
||||||
|
String agentEdt
|
||||||
|
|
||||||
void call() {
|
void call() {
|
||||||
|
|
||||||
//noinspection GroovyAssignabilityCheck
|
//noinspection GroovyAssignabilityCheck
|
||||||
@ -35,7 +39,9 @@ void call() {
|
|||||||
steps {
|
steps {
|
||||||
script {
|
script {
|
||||||
config = jobConfiguration() as JobConfiguration
|
config = jobConfiguration() as JobConfiguration
|
||||||
agent1C = config.v8version
|
agent1C = config.v8AgentLabel()
|
||||||
|
agentEdt = config.edtAgentLabel()
|
||||||
|
RepoUtils.computeRepoSlug(env.GIT_URL)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -54,7 +60,7 @@ void call() {
|
|||||||
stages {
|
stages {
|
||||||
stage('Трансформация из формата EDT') {
|
stage('Трансформация из формата EDT') {
|
||||||
agent {
|
agent {
|
||||||
label 'edt'
|
label agentEdt
|
||||||
}
|
}
|
||||||
when {
|
when {
|
||||||
beforeAgent true
|
beforeAgent true
|
||||||
@ -114,7 +120,7 @@ void call() {
|
|||||||
|
|
||||||
stage('Трансформация в формат EDT') {
|
stage('Трансформация в формат EDT') {
|
||||||
agent {
|
agent {
|
||||||
label 'edt'
|
label agentEdt
|
||||||
}
|
}
|
||||||
when {
|
when {
|
||||||
beforeAgent true
|
beforeAgent true
|
||||||
@ -139,7 +145,7 @@ void call() {
|
|||||||
stages {
|
stages {
|
||||||
stage('Валидация EDT') {
|
stage('Валидация EDT') {
|
||||||
agent {
|
agent {
|
||||||
label 'edt'
|
label agentEdt
|
||||||
}
|
}
|
||||||
steps {
|
steps {
|
||||||
timeout(time: config.timeoutOptions.edtValidate, unit: TimeUnit.MINUTES) {
|
timeout(time: config.timeoutOptions.edtValidate, unit: TimeUnit.MINUTES) {
|
||||||
@ -232,6 +238,7 @@ void call() {
|
|||||||
always {
|
always {
|
||||||
node('agent') {
|
node('agent') {
|
||||||
saveResults config
|
saveResults config
|
||||||
|
sendNotifications(config)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
10
vars/sendNotifications.groovy
Normal file
10
vars/sendNotifications.groovy
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import ru.pulsar.jenkins.library.configuration.JobConfiguration
|
||||||
|
import ru.pulsar.jenkins.library.ioc.ContextRegistry
|
||||||
|
import ru.pulsar.jenkins.library.steps.SendNotifications
|
||||||
|
|
||||||
|
def call(JobConfiguration config) {
|
||||||
|
ContextRegistry.registerDefaultContext(this)
|
||||||
|
|
||||||
|
def sendNotifications = new SendNotifications(config)
|
||||||
|
sendNotifications.run()
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user