1
0

Merge pull request #118 from firstBitMarksistskaya/develop

Sync
This commit is contained in:
Nikita Fedkin
2024-05-08 19:29:58 +03:00
committed by GitHub
28 changed files with 855 additions and 340 deletions

View File

@@ -36,6 +36,7 @@
1. Трансформация кода из формата конфигуратора в формат EDT. 1. Трансформация кода из формата конфигуратора в формат EDT.
1. Трансформация кода из формата EDT в формат конфигуратора. 1. Трансформация кода из формата EDT в формат конфигуратора.
1. Запуск BDD сценариев с сохранением результатов в формате Allure. 1. Запуск BDD сценариев с сохранением результатов в формате Allure.
1. Запуск юнит-тестов с помощью фреймворка YAXUnit с сохранением результатов в формате jUnit и Allure.
1. Запуск синтаксического контроля средствами конфигуратора и сохранение результатов в виде отчета jUnit. 1. Запуск синтаксического контроля средствами конфигуратора и сохранение результатов в виде отчета jUnit.
1. Запуск валидации проекта средствами EDT и конвертация отчета в формате generic issues. 1. Запуск валидации проекта средствами EDT и конвертация отчета в формате generic issues.
1. Запуск статического анализа для SonarQube. 1. Запуск статического анализа для SonarQube.
@@ -67,7 +68,8 @@ pipeline1C()
## Внешний вид пайплайна в интерфейсе Blue Ocean ## Внешний вид пайплайна в интерфейсе Blue Ocean
![image](https://github.com/firstBitMarksistskaya/jenkins-lib/assets/80944823/a8d5bdff-3267-4744-a613-8c3d445b767f) ![image](https://github.com/ovcharenko-di/jenkins-lib/assets/24920942/19eabbc3-e33e-44f5-8f23-142f44817628)
## Конфигурирование ## Конфигурирование
@@ -107,7 +109,7 @@ pipeline1C()
* Общее: * Общее:
* В качестве маски версии платформы используется строка "8.3" (`v8version`). * В качестве маски версии платформы используется строка "8.3" (`v8version`).
* По-умолчанию версия модуля EDT не заполнена, т.к. в случае единственной версии для утилиты ring дополнительного указания не требуется (`edtVersion`). * По умолчанию версия модуля EDT не заполнена, т.к. в случае единственной версии для утилиты ring дополнительного указания не требуется (`edtVersion`).
* Исходники конфигурации ожидаются в каталоге `src/cf` (`srcDir`). * Исходники конфигурации ожидаются в каталоге `src/cf` (`srcDir`).
* Формат исходников - выгрузка из Конфигуратора (`sourceFormat`). * Формат исходников - выгрузка из Конфигуратора (`sourceFormat`).
* Ветка по умолчанию (для комбинированного режима загрузки конфигурации) - "main" (`defaultBranch`). * Ветка по умолчанию (для комбинированного режима загрузки конфигурации) - "main" (`defaultBranch`).
@@ -131,6 +133,8 @@ pipeline1C()
* Если в настройках шага инициализации не заполнен массив дополнительных шагов миграции (`initInfobase` -> `additionalInitializationSteps`), но в каталоге `tools` присутствуют файлы с именами, удовлетворяющими шаблону `vrunner.init*.json`, то автоматически выполняется запуск `vrunner vanessa` с передачей найденных файлов в качестве значения настроек (параметр `--settings`) в порядке лексикографической сортировки имен файлов. * Если в настройках шага инициализации не заполнен массив дополнительных шагов миграции (`initInfobase` -> `additionalInitializationSteps`), но в каталоге `tools` присутствуют файлы с именами, удовлетворяющими шаблону `vrunner.init*.json`, то автоматически выполняется запуск `vrunner vanessa` с передачей найденных файлов в качестве значения настроек (параметр `--settings`) в порядке лексикографической сортировки имен файлов.
* BDD: * BDD:
* Если в конфигурационном файле проекта не заполнена настройка `bdd` -> `vrunnerSteps`, то автоматически выполняется запуск `vrunner vanessa --settings tools/vrunner.json`. * Если в конфигурационном файле проекта не заполнена настройка `bdd` -> `vrunnerSteps`, то автоматически выполняется запуск `vrunner vanessa --settings tools/vrunner.json`.
* YAXUnit:
* Если в репозитории существует файл `tools/yaxunit.json`, то он будет передан в качестве параметра для YAXUnit при запуске тестов. Если файла с таким именем нет, то в YAXUnit будет передан файл из текущей библиотеки `resources/yaxunit.json`. Он содержит минимально необходимые параметры и настроен на поиск сценариев в расширении с именем `YAXUnit`.
* Дымовые тесты: * Дымовые тесты:
* Если в репозитории существует файл `tools/vrunner.json`, то запуск дымовых тестов будет выполняться с передачей файла в параметры запуска `vrunner xunit --settings tools/vrunner.json` (`smoke` -> `vrunnerSettings`). * Если в репозитории существует файл `tools/vrunner.json`, то запуск дымовых тестов будет выполняться с передачей файла в параметры запуска `vrunner xunit --settings tools/vrunner.json` (`smoke` -> `vrunnerSettings`).
* Если установка локальных зависимостей `opm` установит пакет `add`, то будет использоваться обработка `xddTestRunner.epf` из локальных зависимостей. * Если установка локальных зависимостей `opm` установит пакет `add`, то будет использоваться обработка `xddTestRunner.epf` из локальных зависимостей.
@@ -167,7 +171,7 @@ pipeline1C()
* Telegram: * Telegram:
* Уведомления о результатах сборки по умолчанию рассылаются всегда (`notifications` -> `telegram` -> `onAlways`, `onFailure`, `onUnstable`, `onSuccess`). * Уведомления о результатах сборки по умолчанию рассылаются всегда (`notifications` -> `telegram` -> `onAlways`, `onFailure`, `onUnstable`, `onSuccess`).
## Конфигурирование загрузки расширений ## Настройка загрузки расширений
Если у вас есть расширения которые необходимо загрузить в базу для проведения тестов и проверок, это можно сделать на этапе подготовки базы. Если у вас есть расширения которые необходимо загрузить в базу для проведения тестов и проверок, это можно сделать на этапе подготовки базы.
* При загрузке из исходников расширения должны быть в том же формате(edt или конфигуратора) что и основная конфигурация. * При загрузке из исходников расширения должны быть в том же формате(edt или конфигуратора) что и основная конфигурация.
@@ -199,4 +203,10 @@ pipeline1C()
} }
] ]
} }
``` ```
## Настройка шага YAXUnit
* Добавить расширение `YAXUnit` и дополнительные расширения с тестами можно в `jobConfiguration.json` -> `initInfobase` -> `extensions`. Они будут загружены при инициализации ИБ.
* Если ваши тесты размещены в отдельных расширениях, скопируйте файл `./resources/yaxunit.json` из текущей библиотеки в свой репозиторий (`./tools/yaxunit.json`) и перечислите в нем имена ваших расширений.
* Если используется собственный файл `tools/yaxunit.json`, то значение параметра reportPath в нем должно быть равно `./build/out/yaxunit/junit.xml`

View File

@@ -48,7 +48,7 @@ dependencies {
testRuntimeOnly("org.junit.jupiter", "junit-jupiter-engine", junitVersion) testRuntimeOnly("org.junit.jupiter", "junit-jupiter-engine", junitVersion)
testImplementation("org.assertj", "assertj-core", "3.15.0") testImplementation("org.assertj", "assertj-core", "3.15.0")
testImplementation("org.mockito", "mockito-core", "3.3.3") testImplementation("org.mockito", "mockito-core", "5.11.0")
testImplementation("org.slf4j", "slf4j-api", slf4jVersion) testImplementation("org.slf4j", "slf4j-api", slf4jVersion)
testImplementation("org.slf4j", "slf4j-simple", slf4jVersion) testImplementation("org.slf4j", "slf4j-simple", slf4jVersion)
@@ -61,6 +61,7 @@ dependencies {
integrationTestImplementation("org.slf4j", "slf4j-api", slf4jVersion) integrationTestImplementation("org.slf4j", "slf4j-api", slf4jVersion)
integrationTestImplementation("org.slf4j", "slf4j-simple", slf4jVersion) integrationTestImplementation("org.slf4j", "slf4j-simple", slf4jVersion)
} }
tasks.test { tasks.test {
@@ -105,6 +106,8 @@ sharedLibrary {
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"
dependency("org.jenkinsci.plugins", "pipeline-model-api", declarativePluginsVersion) dependency("org.jenkinsci.plugins", "pipeline-model-api", declarativePluginsVersion)
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)

View File

@@ -18,11 +18,13 @@
"syntaxCheck": false, "syntaxCheck": false,
"edtValidate": false, "edtValidate": false,
"smoke": false, "smoke": false,
"yaxunit": false,
"email": false, "email": false,
"telegram": false "telegram": false
}, },
"timeout": { "timeout": {
"smoke": 240, "smoke": 240,
"yaxunit": 240,
"bdd": 120, "bdd": 120,
"getBinaries": 60, "getBinaries": 60,
"createInfoBase": 60, "createInfoBase": 60,
@@ -80,6 +82,12 @@
"publishToAllureReport": false, "publishToAllureReport": false,
"publishToJUnitReport": true "publishToJUnitReport": true
}, },
"yaxunit": {
"vrunnerSettings": "./tools/vrunner.json",
"configPath": "./tools/yaxunit.json",
"publishToAllureReport": false,
"publishToJUnitReport": true
},
"resultsTransform": { "resultsTransform": {
"removeSupport": true, "removeSupport": true,
"supportLevel": 0 "supportLevel": 0

View File

@@ -1,405 +1,437 @@
{ {
"type": "object", "type" : "object",
"id": "urn:jsonschema:ru:pulsar:jenkins:library:configuration:JobConfiguration", "id" : "urn:jsonschema:ru:pulsar:jenkins:library:configuration:JobConfiguration",
"properties": { "properties" : {
"v8version": { "v8version" : {
"type": "string", "type" : "string",
"description": "Версия платформы 1С:Предприятие в формате 8.3.хх.хххх." "description" : "Версия платформы 1С:Предприятие в формате 8.3.хх.хххх."
}, },
"edtVersion": { "edtVersion" : {
"type": "string", "type" : "string",
"description": "Версия модуля 1C:Enterprise Development Tools формате xxxx.x.x:x86_64" "description" : "Версия модуля 1C:Enterprise Development Tools формате xxxx.x.x:x86_64"
}, },
"srcDir": { "srcDir" : {
"type": "string", "type" : "string",
"description": "Путь к корневому каталогу с исходниками конфигурации, в случае хранения исходников в формате EDT, необходимо указать путь к проекту" "description" : "Путь к корневому каталогу с исходниками конфигурации, в случае хранения исходников в формате EDT, необходимо указать путь к проекту"
}, },
"sourceFormat": { "sourceFormat" : {
"type": "string", "type" : "string",
"description": "Формат исходников конфигурации", "description" : "Формат исходников конфигурации",
"enum": ["edt", "designer"] "enum" : [ "edt", "designer" ]
}, },
"defaultBranch": { "defaultBranch" : {
"type": "string", "type" : "string",
"description": "Имя ветки по умолчанию. Значение по умолчанию - main." "description" : "Имя ветки по умолчанию. Значение по умолчанию - main."
}, },
"secrets": { "secrets" : {
"type": "object", "type" : "object",
"id": "urn:jsonschema:ru:pulsar:jenkins:library:configuration:Secrets", "id" : "urn:jsonschema:ru:pulsar:jenkins:library:configuration:Secrets",
"description": "Идентификаторы сохраненных секретов", "description" : "Идентификаторы сохраненных секретов",
"properties": { "properties" : {
"storagePath": { "storagePath" : {
"type": "string", "type" : "string",
"description": "Путь к хранилищу конфигурации" "description" : "Путь к хранилищу конфигурации"
}, },
"storage": { "storage" : {
"type": "string", "type" : "string",
"description": "Данные авторизации в хранилище конфигурации" "description" : "Данные авторизации в хранилище конфигурации"
}, },
"telegramChatId": { "telegramChatId" : {
"type": "string", "type" : "string",
"description": "Идентификатор telegram-чата для отправки уведомлений" "description" : "Идентификатор telegram-чата для отправки уведомлений"
}, },
"telegramBotToken": { "telegramBotToken" : {
"type": "string", "type" : "string",
"description": "Токен авторизации telegram-бота для отправки уведомлений" "description" : "Токен авторизации telegram-бота для отправки уведомлений"
} }
} }
}, },
"stages": { "stages" : {
"type": "object", "type" : "object",
"id": "urn:jsonschema:ru:pulsar:jenkins:library:configuration:StageFlags", "id" : "urn:jsonschema:ru:pulsar:jenkins:library:configuration:StageFlags",
"description": "Включение этапов сборок", "description" : "Включение этапов сборок",
"properties": { "properties" : {
"sonarqube": { "sonarqube" : {
"type": "boolean", "type" : "boolean",
"description": "Анализ SonarQube включен" "description" : "Анализ SonarQube включен"
}, },
"syntaxCheck": { "syntaxCheck" : {
"type": "boolean", "type" : "boolean",
"description": "Синтаксический контроль включен" "description" : "Синтаксический контроль включен"
}, },
"edtValidate": { "edtValidate" : {
"type": "boolean", "type" : "boolean",
"description": "Валидация EDT включена" "description" : "Валидация EDT включена"
}, },
"smoke": { "smoke" : {
"type": "boolean", "type" : "boolean",
"description": "Дымовые тесты включены" "description" : "Дымовые тесты включены"
}, },
"initSteps": { "yaxunit" : {
"type": "boolean", "type" : "boolean",
"description": "Предварительные шаги инициализации включены" "description" : "Запуск YAXUnit тестов включен"
}, },
"bdd": { "initSteps" : {
"type": "boolean", "type" : "boolean",
"description": "Запуск BDD сценариев включен" "description" : "Предварительные шаги инициализации включены"
}, },
"email": { "bdd" : {
"type": "boolean", "type" : "boolean",
"description": "Выполнять рассылку результатов сборки на email" "description" : "Запуск BDD сценариев включен"
}, },
"telegram": { "email" : {
"type": "boolean", "type" : "boolean",
"description": "Выполнять рассылку результатов сборки в telegram" "description" : "Выполнять рассылку результатов сборки на email"
},
"telegram" : {
"type" : "boolean",
"description" : "Выполнять рассылку результатов сборки в telegram"
} }
} }
}, },
"timeout": { "timeout" : {
"type": "object", "type" : "object",
"id": "urn:jsonschema:ru:pulsar:jenkins:library:configuration:TimeoutOptions", "id" : "urn:jsonschema:ru:pulsar:jenkins:library:configuration:TimeoutOptions",
"description": "Настройка таймаутов для шагов", "description" : "Настройка таймаутов для шагов",
"properties": { "properties" : {
"edtToDesignerFormatTransformation": { "edtToDesignerFormatTransformation" : {
"type": "integer", "type" : "integer",
"description": "Таймаут шага трансформации исходников из формата EDT в формат Конфигуратора, в минутах.\n По умолчанию содержит значение 60.\n " "description" : "Таймаут шага трансформации исходников из формата EDT в формат Конфигуратора, в минутах.\n По умолчанию содержит значение 60.\n "
}, },
"getBinaries": { "getBinaries" : {
"type": "integer", "type" : "integer",
"description": "Таймаут шага получения бинарников, в минутах.\n По умолчанию содержит значение 60.\n " "description" : "Таймаут шага получения бинарников, в минутах.\n По умолчанию содержит значение 60.\n "
}, },
"createInfoBase": { "createInfoBase" : {
"type": "integer", "type" : "integer",
"description": "Таймаут шага создания информационной базы, в минутах.\n По умолчанию содержит значение 60.\n " "description" : "Таймаут шага создания информационной базы, в минутах.\n По умолчанию содержит значение 60.\n "
}, },
"initInfoBase": { "initInfoBase" : {
"type": "integer", "type" : "integer",
"description": "Таймаут шага инициализации информационной базы, в минутах.\n По умолчанию содержит значение 60.\n " "description" : "Таймаут шага инициализации информационной базы, в минутах.\n По умолчанию содержит значение 60.\n "
}, },
"loadExtensions": { "loadExtensions" : {
"type": "integer", "type" : "integer",
"description": "Таймаут шага загрузки расширений в базу, в минутах.\n По умолчанию содержит значение 60.\n " "description" : "Таймаут шага загрузки расширений в базу, в минутах.\n По умолчанию содержит значение 60.\n "
}, },
"zipInfoBase": { "zipInfoBase" : {
"type": "integer", "type" : "integer",
"description": "Таймаут шага архивирования информационной базы, в минутах.\n По умолчанию содержит значение 60.\n " "description" : "Таймаут шага архивирования информационной базы, в минутах.\n По умолчанию содержит значение 60.\n "
}, },
"designerToEdtFormatTransformation": { "designerToEdtFormatTransformation" : {
"type": "integer", "type" : "integer",
"description": "Таймаут шага трансформации исходников из формата Конфигуратора в формат EDT, в минутах.\n По умолчанию содержит значение 60.\n " "description" : "Таймаут шага трансформации исходников из формата Конфигуратора в формат EDT, в минутах.\n По умолчанию содержит значение 60.\n "
}, },
"edtValidate": { "edtValidate" : {
"type": "integer", "type" : "integer",
"description": "Таймаут шага валидации EDT, в минутах.\n По умолчанию содержит значение 240.\n " "description" : "Таймаут шага валидации EDT, в минутах.\n По умолчанию содержит значение 240.\n "
}, },
"resultTransformation": { "resultTransformation" : {
"type": "integer", "type" : "integer",
"description": "Таймаут шага трансформации результатов EDT, в минутах.\n По умолчанию содержит значение 10.\n " "description" : "Таймаут шага трансформации результатов EDT, в минутах.\n По умолчанию содержит значение 10.\n "
}, },
"bdd": { "bdd" : {
"type": "integer", "type" : "integer",
"description": "Таймаут шага проверки сценариев поведения, в минутах.\n По умолчанию содержит значение 120.\n " "description" : "Таймаут шага проверки сценариев поведения, в минутах.\n По умолчанию содержит значение 120.\n "
}, },
"syntaxCheck": { "syntaxCheck" : {
"type": "integer", "type" : "integer",
"description": "Таймаут шага синтаксического контроля, в минутах.\n По умолчанию содержит значение 240.\n " "description" : "Таймаут шага синтаксического контроля, в минутах.\n По умолчанию содержит значение 240.\n "
}, },
"smoke": { "smoke" : {
"type": "integer", "type" : "integer",
"description": "Таймаут шага дымовых тестов, в минутах.\n По умолчанию содержит значение 240.\n " "description" : "Таймаут шага дымовых тестов, в минутах.\n По умолчанию содержит значение 240.\n "
}, },
"sonarqube": { "yaxunit" : {
"type": "integer", "type" : "integer",
"description": "Таймаут шага статического анализа SonarQube, в минутах.\n По умолчанию содержит значение 90.\n " "description" : "Таймаут шага YAXUnit тестов, в минутах.\n По умолчанию содержит значение 240.\n "
},
"sonarqube" : {
"type" : "integer",
"description" : "Таймаут шага статического анализа SonarQube, в минутах.\n По умолчанию содержит значение 90.\n "
} }
} }
}, },
"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" : {
"type": "string", "type" : "string",
"description": "\n Способ инициализации информационной базы.\n Поддерживается три варианта:\n * fromStorage - инициализация информационной базы из хранилища конфигурации;\n * fromSource - инициализация информационной базы из исходников конфигурации;\n * defaultBranchFromStorage - инициализация основной ветки из хранилища конфигурации, остальных - из исходников конфигурации.\n По умолчанию содержит значение \"fromStorage\".", "description" : "\n Способ инициализации информационной базы.\n Поддерживается три варианта:\n * fromStorage - инициализация информационной базы из хранилища конфигурации;\n * fromSource - инициализация информационной базы из исходников конфигурации;\n * defaultBranchFromStorage - инициализация основной ветки из хранилища конфигурации, остальных - из исходников конфигурации.\n По умолчанию содержит значение \"fromStorage\".",
"enum": ["fromStorage", "fromSource", "defaultBranchFromStorage"] "enum" : [ "fromStorage", "fromSource", "defaultBranchFromStorage" ]
}, },
"runMigration": { "runMigration" : {
"type": "boolean", "type" : "boolean",
"description": "Запустить миграцию ИБ" "description" : "Запустить миграцию ИБ"
}, },
"additionalInitializationSteps": { "additionalInitializationSteps" : {
"type": "array", "type" : "array",
"description": "Дополнительные шаги, запускаемые через vrunner.\n В каждой строке передается отдельная команда \n vrunner и ее аргументы (например, \"vanessa --settings ./tools/vrunner.first.json\")\n ", "description" : "Дополнительные шаги, запускаемые через vrunner.\n В каждой строке передается отдельная команда \n vrunner и ее аргументы (например, \"vanessa --settings ./tools/vrunner.first.json\")\n ",
"items": { "items" : {
"type": "string" "type" : "string"
} }
}, },
"extensions": { "extensions" : {
"type": "array", "type" : "array",
"description": "Массив расширений для загрузки в конфигурацию.", "description" : "Массив расширений для загрузки в конфигурацию.",
"items": { "items" : {
"type": "object", "type" : "object",
"id": "urn:jsonschema:ru:pulsar:jenkins:library:configuration:InitInfoBaseOptions:extensions:exception", "id" : "urn:jsonschema:ru:pulsar:jenkins:library:configuration:InitInfoBaseOptions:Extension",
"description": "Информация о расширении для загрузки", "properties" : {
"properties": { "name" : {
"name": { "type" : "string",
"type": "string", "description" : "Имя расширения, используемое при его загрузке в конфигурацию."
"description": "Имя расширения с которым оно грузится в конфигурацию"
}, },
"initMethod": { "initMethod" : {
"type": "string", "type" : "string",
"description": "\n Способ инициализации расширения.\n Поддерживается два варианта:\n * fromSource - инициализация расширения из исходников;\n * fromFile - использование скомпилированного cfe.", "description" : "\n Способ инициализации расширения.\n Поддерживается два варианта:\n * fromSource - инициализация расширения из исходников;\n * fromFile - скачивание скомпилированного cfe по ссылке.\n ",
"enum": ["fromSource", "fromFile"] "enum" : [ "fromSource", "fromFile" ]
}, },
"path": { "path" : {
"type": "string", "type" : "string",
"description": "Хранит в себе путь к расширению.\n * В случае если выбран initMethod <fromSource> - указывается путь к исходникам расширения.\n * В случае если выбран initMethod <fromFile> - указывается путь к cfe-файлу" "description" : "\n Путь к расширению.\n * В случае если выбран initMethod <fromSource> - указывается путь к исходникам расширения.\n * В случае если выбран initMethod <fromFile> - указывается путь к cfe-файлу\n "
},
"stages" : {
"type" : "array",
"description" : "\n Шаги, на которых необходимо использовать расширение\n * Если не заполнено, то расширение будет подключено при инициализации базы и останется в базе на всех последующих шагах.\n * Если заполнено, то расширение будет подключено только на соответствующих шагах.\n ",
"items" : {
"type" : "string"
}
} }
} }
} }
} }
} }
}, },
"bdd": { "bdd" : {
"type": "object", "type" : "object",
"id": "urn:jsonschema:ru:pulsar:jenkins:library:configuration:BddOptions", "id" : "urn:jsonschema:ru:pulsar:jenkins:library:configuration:BddOptions",
"description": "Настройки шага запуска BDD сценариев", "description" : "Настройки шага запуска BDD сценариев",
"properties": { "properties" : {
"vrunnerSteps": { "vrunnerSteps" : {
"type": "array", "type" : "array",
"description": "Шаги, запускаемые через vrunner.\n В каждой строке передается отдельная команда \n vrunner и ее аргументы (например, \"vanessa --settings ./tools/vrunner.json\").\n По умолчанию содержит одну команду \"vanessa --settings ./tools/vrunner.json\".\n ", "description" : "Шаги, запускаемые через vrunner.\n В каждой строке передается отдельная команда \n vrunner и ее аргументы (например, \"vanessa --settings ./tools/vrunner.json\").\n По умолчанию содержит одну команду \"vanessa --settings ./tools/vrunner.json\".\n ",
"items": { "items" : {
"type": "string" "type" : "string"
} }
} }
} }
}, },
"sonarqube": { "sonarqube" : {
"type": "object", "type" : "object",
"id": "urn:jsonschema:ru:pulsar:jenkins:library:configuration:SonarQubeOptions", "id" : "urn:jsonschema:ru:pulsar:jenkins:library:configuration:SonarQubeOptions",
"description": "Настройки анализа SonarQube", "description" : "Настройки анализа SonarQube",
"properties": { "properties" : {
"sonarQubeInstallation": { "sonarQubeInstallation" : {
"type": "string", "type" : "string",
"description": "Имя настроенного SonarQube-сервера (SonarQube installations).\nЕсли настроен только один сервер, то может быть оставлено пустым." "description" : "Имя настроенного SonarQube-сервера (SonarQube installations).\nЕсли настроен только один сервер, то может быть оставлено пустым."
}, },
"useSonarScannerFromPath": { "useSonarScannerFromPath" : {
"type": "boolean", "type" : "boolean",
"description": "Использовать sonar-scanner, доступный в PATH" "description" : "Использовать sonar-scanner, доступный в PATH"
}, },
"sonarScannerToolName": { "sonarScannerToolName" : {
"type": "string", "type" : "string",
"description": "Имя настроенной утилиты sonar-scanner.\nПрименяется, если useSonarScannerFromPath установлено в false." "description" : "Имя настроенной утилиты sonar-scanner.\nПрименяется, если useSonarScannerFromPath установлено в false."
}, },
"infoBaseUpdateModuleName": { "infoBaseUpdateModuleName" : {
"type": "string", "type" : "string",
"description": "Имя общего модуля (например, ОбновлениеИнформационнойБазыXXX), в котором указана версия библиотеки.\n Версия должна задаваться в виде присвоения `Описание.Версия = \"ваш номер версии\";`\n " "description" : "Имя общего модуля (например, ОбновлениеИнформационнойБазыXXX), в котором указана версия библиотеки.\n Версия должна задаваться в виде присвоения `Описание.Версия = \"ваш номер версии\";`\n "
}, },
"branchAnalysisConfiguration": { "branchAnalysisConfiguration" : {
"type": "string", "type" : "string",
"description": "Вариант конфигурации branch plugin.\n Поддерживаемые варианты:\n * auto - применяется автоконфигурация sonar-scanner силами branchplugin. Так же может применяться для отключения конфигурирования, если branch plugin отсутствует;\n * fromEnv - применяется ручная конфигурация sonar-scanner на основе переменных среды.\n Значение по умолчанию: fromEnv.", "description" : "Вариант конфигурации branch plugin.\n Поддерживаемые варианты:\n * auto - применяется автоконфигурация sonar-scanner силами branchplugin. Так же может применяться для отключения конфигурирования, если branch plugin отсутствует;\n * fromEnv - применяется ручная конфигурация sonar-scanner на основе переменных среды.\n Значение по умолчанию: fromEnv.",
"enum": ["auto", "fromEnv"] "enum" : [ "auto", "fromEnv" ]
}, },
"waitForQualityGate": { "waitForQualityGate" : {
"type": "boolean", "type" : "boolean",
"description": "Ожидать состояние Quality Gate от SonarQube после загрузки анализа. По умолчанию `false`.\n Таймаут ожидания состояния равен таймауту шага.\n " "description" : "Ожидать состояние Quality Gate от SonarQube после загрузки анализа. По умолчанию `false`.\n Таймаут ожидания состояния равен таймауту шага.\n "
} }
} }
}, },
"syntaxCheck": { "syntaxCheck" : {
"type": "object", "type" : "object",
"id": "urn:jsonschema:ru:pulsar:jenkins:library:configuration:SyntaxCheckOptions", "id" : "urn:jsonschema:ru:pulsar:jenkins:library:configuration:SyntaxCheckOptions",
"description": "Настройки синтаксического контроля", "description" : "Настройки синтаксического контроля",
"properties": { "properties" : {
"pathToJUnitReport": { "pathToJUnitReport" : {
"type": "string", "type" : "string",
"description": "Путь к файлу отчета jUnit\n По умолчанию содержит значение \"./build/out/jUnit/syntax.xml\"\n " "description" : "Путь к файлу отчета jUnit\n По умолчанию содержит значение \"./build/out/jUnit/syntax.xml\"\n "
}, },
"groupErrorsByMetadata": { "groupErrorsByMetadata" : {
"type": "boolean", "type" : "boolean",
"description": "Группировать выявленные ошибки по объектам метаданных.\n По умолчанию включено.\n " "description" : "Группировать выявленные ошибки по объектам метаданных.\n По умолчанию включено.\n "
}, },
"checkModes": { "checkModes" : {
"type": "array", "type" : "array",
"description": "Режимы проверки конфигурации", "description" : "Режимы проверки конфигурации",
"items": { "items" : {
"type": "string" "type" : "string"
} }
}, },
"exceptionFile": { "exceptionFile" : {
"type": "string", "type" : "string",
"description": "Путь к файлу с указанием пропускаемых ошибок.\n Формат файла: в каждой строке файла указан текст пропускаемого исключения или его часть\n Кодировка: UTF-8\n " "description" : "Путь к файлу с указанием пропускаемых ошибок.\n Формат файла: в каждой строке файла указан текст пропускаемого исключения или его часть\n Кодировка: UTF-8\n "
}, },
"vrunnerSettings": { "vrunnerSettings" : {
"type": "string", "type" : "string",
"description": "Путь к конфигурационному файлу vanessa-runner.\n По умолчанию содержит значение \"./tools/vrunner.json\".\n " "description" : "Путь к конфигурационному файлу vanessa-runner.\n По умолчанию содержит значение \"./tools/vrunner.json\".\n "
} }
} }
}, },
"smoke": { "smoke" : {
"type": "object", "type" : "object",
"id": "urn:jsonschema:ru:pulsar:jenkins:library:configuration:SmokeTestOptions", "id" : "urn:jsonschema:ru:pulsar:jenkins:library:configuration:SmokeTestOptions",
"description": "Настройки дымового тестирования", "description" : "Настройки дымового тестирования",
"properties": { "properties" : {
"vrunnerSettings": { "vrunnerSettings" : {
"type": "string", "type" : "string",
"description": "Путь к конфигурационному файлу vanessa-runner.\n По умолчанию содержит значение \"./tools/vrunner.json\".\n " "description" : "Путь к конфигурационному файлу vanessa-runner.\n По умолчанию содержит значение \"./tools/vrunner.json\".\n "
}, },
"xddConfigPath": { "xddConfigPath" : {
"type": "string", "type" : "string",
"description": "Путь к конфигурационному файлу для xddTestRunner.\n По умолчанию содержит значение \"./tools/xUnitParams.json\".\n " "description" : "Путь к конфигурационному файлу для xddTestRunner.\n По умолчанию содержит значение \"./tools/xUnitParams.json\".\n "
}, },
"publishToAllureReport": { "publishToAllureReport" : {
"type": "boolean", "type" : "boolean",
"description": "Выполнять публикацию результатов в отчет Allure.\n По умолчанию выключено.\n " "description" : "Выполнять публикацию результатов в отчет Allure.\n По умолчанию выключено.\n "
}, },
"publishToJUnitReport": { "publishToJUnitReport" : {
"type": "boolean", "type" : "boolean",
"description": "Выполнять публикацию результатов в отчет JUnit.\n По умолчанию включено.\n " "description" : "Выполнять публикацию результатов в отчет JUnit.\n По умолчанию включено.\n "
} }
} }
}, },
"resultsTransform": { "yaxunit" : {
"type": "object", "type" : "object",
"id": "urn:jsonschema:ru:pulsar:jenkins:library:configuration:ResultsTransformOptions", "id" : "urn:jsonschema:ru:pulsar:jenkins:library:configuration:YaxunitOptions",
"description": "Настройки трансформации результатов анализа", "description" : "Настройки YAXUnit",
"properties": { "properties" : {
"removeSupport": { "vrunnerSettings" : {
"type": "boolean", "type" : "string",
"description": "Фильтровать замечания по уровню поддержки модуля. По умолчанию включено." "description" : "Путь к конфигурационному файлу vanessa-runner.\n По умолчанию содержит значение \"./tools/vrunner.json\".\n "
}, },
"supportLevel": { "configPath" : {
"type": "integer", "type" : "string",
"description": "Настройка фильтрации замечаний по уровню поддержки.\n 0 - удалить файлы на замке;\n 1 - удалить файлы на замке и на поддержке;\n 2 - удалить файлы на замке, на поддержке и снятые с поддержки.\n " "description" : "Путь к конфигурационному файлу YAXUnit.\n По умолчанию содержит значение \"./tools/yaxunit.json\".\n "
},
"publishToAllureReport" : {
"type" : "boolean",
"description" : "Выполнять публикацию результатов в отчет Allure.\n По умолчанию выключено.\n "
},
"publishToJUnitReport" : {
"type" : "boolean",
"description" : "Выполнять публикацию результатов в отчет JUnit.\n По умолчанию включено.\n "
} }
} }
}, },
"notifications": { "resultsTransform" : {
"type": "object", "type" : "object",
"id": "urn:jsonschema:ru:pulsar:jenkins:library:configuration:NotificationsOptions", "id" : "urn:jsonschema:ru:pulsar:jenkins:library:configuration:ResultsTransformOptions",
"description": "Настройки рассылки результатов сборки", "description" : "Настройки трансформации результатов анализа",
"properties": { "properties" : {
"email": { "removeSupport" : {
"type": "object", "type" : "boolean",
"id": "urn:jsonschema:ru:pulsar:jenkins:library:configuration:notification:EmailNotificationOptions", "description" : "Фильтровать замечания по уровню поддержки модуля. По умолчанию включено."
"description": "Настройки рассылки результатов сборки через email", },
"properties": { "supportLevel" : {
"onAlways": { "type" : "integer",
"type": "boolean", "description" : "Настройка фильтрации замечаний по уровню поддержки.\n 0 - удалить файлы на замке;\n 1 - удалить файлы на замке и на поддержке;\n 2 - удалить файлы на замке, на поддержке и снятые с поддержки.\n "
"description": "Отправлять всегда" }
}
},
"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": { "onSuccess" : {
"type": "boolean", "type" : "boolean",
"description": "Отправлять при успешной сборке" "description" : "Отправлять при успешной сборке"
}, },
"onFailure": { "onFailure" : {
"type": "boolean", "type" : "boolean",
"description": "Отправлять при падении сборки" "description" : "Отправлять при падении сборки"
}, },
"onUnstable": { "onUnstable" : {
"type": "boolean", "type" : "boolean",
"description": "Отправлять при нестабильной сборке" "description" : "Отправлять при нестабильной сборке"
}, },
"alwaysOptions": { "alwaysOptions" : {
"type": "object", "type" : "object",
"id": "urn:jsonschema:ru:pulsar:jenkins:library:configuration:notification:email:EmailExtConfiguration", "id" : "urn:jsonschema:ru:pulsar:jenkins:library:configuration:notification:email:EmailExtConfiguration",
"properties": { "properties" : {
"attachLog": { "attachLog" : {
"type": "boolean" "type" : "boolean"
}, },
"directRecipients": { "directRecipients" : {
"type": "array", "type" : "array",
"items": { "items" : {
"type": "string" "type" : "string"
} }
}, },
"recipientProviders": { "recipientProviders" : {
"type": "array", "type" : "array",
"items": { "items" : {
"type": "string", "type" : "string",
"enum": [ "enum" : [ "developers", "requestor", "brokenBuildSuspects", "brokenTestsSuspects" ]
"developers",
"requestor",
"brokenBuildSuspects",
"brokenTestsSuspects"
]
} }
} }
} }
}, },
"successOptions": { "successOptions" : {
"type": "object", "type" : "object",
"$ref": "urn:jsonschema:ru:pulsar:jenkins:library:configuration:notification:email:EmailExtConfiguration" "$ref" : "urn:jsonschema:ru:pulsar:jenkins:library:configuration:notification:email:EmailExtConfiguration"
}, },
"failureOptions": { "failureOptions" : {
"type": "object", "type" : "object",
"$ref": "urn:jsonschema:ru:pulsar:jenkins:library:configuration:notification:email:EmailExtConfiguration" "$ref" : "urn:jsonschema:ru:pulsar:jenkins:library:configuration:notification:email:EmailExtConfiguration"
}, },
"unstableOptions": { "unstableOptions" : {
"type": "object", "type" : "object",
"$ref": "urn:jsonschema:ru:pulsar:jenkins:library:configuration:notification:email:EmailExtConfiguration" "$ref" : "urn:jsonschema:ru:pulsar:jenkins:library:configuration:notification:email:EmailExtConfiguration"
} }
} }
}, },
"telegram": { "telegram" : {
"type": "object", "type" : "object",
"id": "urn:jsonschema:ru:pulsar:jenkins:library:configuration:notification:TelegramNotificationOptions", "id" : "urn:jsonschema:ru:pulsar:jenkins:library:configuration:notification:TelegramNotificationOptions",
"description": "Настройки рассылки результатов сборки через telegram", "description" : "Настройки рассылки результатов сборки через telegram",
"properties": { "properties" : {
"onAlways": { "onAlways" : {
"type": "boolean", "type" : "boolean",
"description": "Отправлять всегда" "description" : "Отправлять всегда"
}, },
"onSuccess": { "onSuccess" : {
"type": "boolean", "type" : "boolean",
"description": "Отправлять при успешной сборке" "description" : "Отправлять при успешной сборке"
}, },
"onFailure": { "onFailure" : {
"type": "boolean", "type" : "boolean",
"description": "Отправлять при падении сборки" "description" : "Отправлять при падении сборки"
}, },
"onUnstable": { "onUnstable" : {
"type": "boolean", "type" : "boolean",
"description": "Отправлять при нестабильной сборке" "description" : "Отправлять при нестабильной сборке"
} }
} }
} }
} }
}, },
"logosConfig": { "logosConfig" : {
"type": "string", "type" : "string",
"description": "Конфигурация библиотеки logos. Применяется перед запуском каждой стадии сборки" "description" : "Конфигурация библиотеки logos. Применяется перед запуском каждой стадии сборки"
} }
} }
} }

26
resources/yaxunit.json Normal file
View File

@@ -0,0 +1,26 @@
{
"reportPath": "./build/out/yaxunit/junit.xml",
"closeAfterTests": true,
"filter": {
"extensions": [
"YAXUNIT"
],
"modules": null,
"suites": null,
"tags": null,
"contexts": null,
"paths": null,
"tests": null
},
"settings": {
"ВТранзакции": true
},
"reportFormat": "jUnit",
"showReport": false,
"logging": {
"file": "./build/out/yaxunit/log.txt",
"enable": false,
"level": "debug"
},
"exitCode": "./build/out/yaxunit/result.txt"
}

View File

@@ -26,6 +26,8 @@ interface IStepExecutor {
String readFile(String file, String encoding) String readFile(String file, String encoding)
void writeFile(String file, String text, String encoding)
boolean fileExists(String file) boolean fileExists(String file)
void echo(message) void echo(message)

View File

@@ -42,6 +42,11 @@ class StepExecutor implements IStepExecutor {
steps.readFile encoding: encoding, file: file steps.readFile encoding: encoding, file: file
} }
@Override
void writeFile(String file, String text, String encoding = 'UTF-8') {
steps.writeFile encoding: encoding, file: file, text: text
}
@Override @Override
boolean fileExists(String file) { boolean fileExists(String file) {
steps.fileExists file steps.fileExists file

View File

@@ -65,6 +65,7 @@ class ConfigurationReader implements Serializable {
"bddOptions", "bddOptions",
"sonarQubeOptions", "sonarQubeOptions",
"smokeTestOptions", "smokeTestOptions",
"yaxunitOptions",
"syntaxCheckOptions", "syntaxCheckOptions",
"resultsTransformOptions", "resultsTransformOptions",
"notificationsOptions", "notificationsOptions",

View File

@@ -14,7 +14,7 @@ class InitInfoBaseOptions implements Serializable {
* fromSource - инициализация информационной базы из исходников конфигурации; * fromSource - инициализация информационной базы из исходников конфигурации;
* defaultBranchFromStorage - инициализация основной ветки из хранилища конфигурации, остальных - из исходников конфигурации. * defaultBranchFromStorage - инициализация основной ветки из хранилища конфигурации, остальных - из исходников конфигурации.
По умолчанию содержит значение "fromStorage".""") По умолчанию содержит значение "fromStorage".""")
InitInfoBaseMethod initMethod = InitInfoBaseMethod.FROM_STORAGE; InitInfoBaseMethod initMethod = InitInfoBaseMethod.FROM_STORAGE
@JsonPropertyDescription("Запустить миграцию ИБ") @JsonPropertyDescription("Запустить миграцию ИБ")
Boolean runMigration = true Boolean runMigration = true
@@ -26,12 +26,12 @@ class InitInfoBaseOptions implements Serializable {
String[] additionalInitializationSteps String[] additionalInitializationSteps
@JsonPropertyDescription("Массив расширений для загрузки в конфигурацию.") @JsonPropertyDescription("Массив расширений для загрузки в конфигурацию.")
Extension[] extensions; Extension[] extensions
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
static class Extension implements Serializable { static class Extension implements Serializable {
@JsonPropertyDescription("Имя расширения, используемое при его загрузке в конфигурацию.") @JsonPropertyDescription("Имя расширения, используемое при его загрузке в конфигурацию.")
String name = "extension"; String name = "extension"
@JsonPropertyDescription(""" @JsonPropertyDescription("""
Способ инициализации расширения. Способ инициализации расширения.
@@ -39,14 +39,21 @@ class InitInfoBaseOptions implements Serializable {
* fromSource - инициализация расширения из исходников; * fromSource - инициализация расширения из исходников;
* fromFile - скачивание скомпилированного cfe по ссылке. * fromFile - скачивание скомпилированного cfe по ссылке.
""") """)
InitExtensionMethod initMethod = InitExtensionMethod.SOURCE; InitExtensionMethod initMethod = InitExtensionMethod.SOURCE
@JsonPropertyDescription(""" @JsonPropertyDescription("""
Хранит в себе путь к расширению. Путь к расширению.
* В случае если выбран initMethod <fromSource> - указывается путь к исходникам расширения. * В случае если выбран initMethod <fromSource> - указывается путь к исходникам расширения.
* В случае если выбран initMethod <fromFile> - указывается путь к cfe-файлу * В случае если выбран initMethod <fromFile> - указывается путь к cfe-файлу
""") """)
String path = "src/cfe/extension"; String path = "src/cfe/extension"
@JsonPropertyDescription("""
Шаги, на которых необходимо использовать расширение
* Если не заполнено, то расширение будет подключено при инициализации базы и останется в базе на всех последующих шагах.
* Если заполнено, то расширение будет подключено только на соответствующих шагах.
""")
String[] stages = ["initInfoBase"]
} }
@Override @Override
@@ -57,6 +64,6 @@ class InitInfoBaseOptions implements Serializable {
", runMigration=" + runMigration + ", runMigration=" + runMigration +
", additionalInitializationSteps=" + additionalInitializationSteps + ", additionalInitializationSteps=" + additionalInitializationSteps +
", extensions=" + extensions + ", extensions=" + extensions +
'}'; '}'
} }
} }

View File

@@ -55,6 +55,10 @@ class JobConfiguration implements Serializable {
@JsonPropertyDescription("Настройки дымового тестирования") @JsonPropertyDescription("Настройки дымового тестирования")
SmokeTestOptions smokeTestOptions; SmokeTestOptions smokeTestOptions;
@JsonProperty("yaxunit")
@JsonPropertyDescription("Настройки YAXUnit")
YaxunitOptions yaxunitOptions;
@JsonProperty("resultsTransform") @JsonProperty("resultsTransform")
@JsonPropertyDescription("Настройки трансформации результатов анализа") @JsonPropertyDescription("Настройки трансформации результатов анализа")
ResultsTransformOptions resultsTransformOptions; ResultsTransformOptions resultsTransformOptions;
@@ -84,6 +88,7 @@ class JobConfiguration implements Serializable {
", sonarQubeOptions=" + sonarQubeOptions + ", sonarQubeOptions=" + sonarQubeOptions +
", syntaxCheckOptions=" + syntaxCheckOptions + ", syntaxCheckOptions=" + syntaxCheckOptions +
", smokeTestOptions=" + smokeTestOptions + ", smokeTestOptions=" + smokeTestOptions +
", yaxunitOptions=" + yaxunitOptions +
", resultsTransformOptions=" + resultsTransformOptions + ", resultsTransformOptions=" + resultsTransformOptions +
", notificationOptions=" + notificationsOptions + ", notificationOptions=" + notificationsOptions +
", logosConfig='" + logosConfig + '\'' + ", logosConfig='" + logosConfig + '\'' +
@@ -100,8 +105,14 @@ class JobConfiguration implements Serializable {
(initMethod == InitInfoBaseMethod.DEFAULT_BRANCH_FROM_STORAGE && branchName != defaultBranch) (initMethod == InitInfoBaseMethod.DEFAULT_BRANCH_FROM_STORAGE && branchName != defaultBranch)
} }
boolean needLoadExtensions() { boolean needLoadExtensions(String stageName = "") {
return initInfoBaseOptions.extensions.length != 0 if (stageName.isEmpty()) {
return initInfoBaseOptions.extensions.length != 0
} else {
return initInfoBaseOptions.extensions.any { extension ->
extension.stages.contains(stageName)
}
}
} }
String v8AgentLabel() { String v8AgentLabel() {

View File

@@ -18,6 +18,9 @@ class StageFlags implements Serializable {
@JsonPropertyDescription("Дымовые тесты включены") @JsonPropertyDescription("Дымовые тесты включены")
Boolean smoke Boolean smoke
@JsonPropertyDescription("Запуск YAXUnit тестов включен")
Boolean yaxunit
@JsonPropertyDescription("Предварительные шаги инициализации включены") @JsonPropertyDescription("Предварительные шаги инициализации включены")
Boolean initSteps Boolean initSteps
@@ -46,6 +49,6 @@ class StageFlags implements Serializable {
} }
boolean needInfoBase() { boolean needInfoBase() {
return smoke || syntaxCheck || initSteps || bdd return smoke || syntaxCheck || initSteps || bdd || yaxunit
} }
} }

View File

@@ -66,6 +66,11 @@ class TimeoutOptions implements Serializable {
''') ''')
Integer smoke Integer smoke
@JsonPropertyDescription('''Таймаут шага YAXUnit тестов, в минутах.
По умолчанию содержит значение 240.
''')
Integer yaxunit
@JsonPropertyDescription('''Таймаут шага статического анализа SonarQube, в минутах. @JsonPropertyDescription('''Таймаут шага статического анализа SonarQube, в минутах.
По умолчанию содержит значение 90. По умолчанию содержит значение 90.
''') ''')

View File

@@ -0,0 +1,40 @@
package ru.pulsar.jenkins.library.configuration
import com.cloudbees.groovy.cps.NonCPS
import com.fasterxml.jackson.annotation.JsonIgnoreProperties
import com.fasterxml.jackson.annotation.JsonPropertyDescription
@JsonIgnoreProperties(ignoreUnknown = true)
class YaxunitOptions implements Serializable {
@JsonPropertyDescription("""Путь к конфигурационному файлу vanessa-runner.
По умолчанию содержит значение "./tools/vrunner.json".
""")
String vrunnerSettings = "./tools/vrunner.json"
@JsonPropertyDescription("""Путь к конфигурационному файлу YAXUnit.
По умолчанию содержит значение "./tools/yaxunit.json".
""")
String configPath = "./tools/yaxunit.json"
@JsonPropertyDescription("""Выполнять публикацию результатов в отчет Allure.
По умолчанию выключено.
""")
boolean publishToAllureReport
@JsonPropertyDescription("""Выполнять публикацию результатов в отчет JUnit.
По умолчанию включено.
""")
boolean publishToJUnitReport
@Override
@NonCPS
String toString() {
return "YaxunitOptions{" +
"vrunnerSettings='" + vrunnerSettings + '\'' +
", configPath='" + configPath +
", publishToAllureReport='" + publishToAllureReport +
", publishToJUnitReport='" + publishToJUnitReport +
'}'
}
}

View File

@@ -13,6 +13,7 @@ import ru.pulsar.jenkins.library.utils.FileUtils
class GetExtensions implements Serializable { class GetExtensions implements Serializable {
public static final String EXTENSIONS_STASH = 'extensions'
public static final String EXTENSIONS_OUT_DIR = 'build/out/cfe' public static final String EXTENSIONS_OUT_DIR = 'build/out/cfe'
private final JobConfiguration config; private final JobConfiguration config;
@@ -58,6 +59,9 @@ class GetExtensions implements Serializable {
Logger.println("Неизвестный метод инициализации расширения ${it.name}") Logger.println("Неизвестный метод инициализации расширения ${it.name}")
} }
} }
steps.stash(EXTENSIONS_STASH, "$EXTENSIONS_OUT_DIR/**", true)
} }
private void buildExtension(Extension extension, String srcDir, String vrunnerPath, IStepExecutor steps) { private void buildExtension(Extension extension, String srcDir, String vrunnerPath, IStepExecutor steps) {

View File

@@ -11,10 +11,18 @@ import ru.pulsar.jenkins.library.utils.FileUtils
class LoadExtensions implements Serializable { class LoadExtensions implements Serializable {
private final JobConfiguration config; private final JobConfiguration config
private final String stageName
LoadExtensions(JobConfiguration config) { private Extension[] extensionsFiltered
LoadExtensions(JobConfiguration config, String stageName = "") {
this.config = config this.config = config
this.stageName = stageName
}
Extension[] getExtensionsFiltered() {
return extensionsFiltered
} }
def run() { def run() {
@@ -22,12 +30,23 @@ class LoadExtensions implements Serializable {
Logger.printLocation() Logger.printLocation()
def env = steps.env(); def extensions = this.config.initInfoBaseOptions.extensions
if (this.stageName) {
this.extensionsFiltered = extensions.findAll { extension ->
extension.stages.contains(this.stageName)
}
}
else {
this.extensionsFiltered = extensions.findAll { extension -> extension.stages.length == 0 || extension.stages.contains("initInfoBase") }
}
def env = steps.env()
String cfeDir = "$env.WORKSPACE/$GetExtensions.EXTENSIONS_OUT_DIR" String cfeDir = "$env.WORKSPACE/$GetExtensions.EXTENSIONS_OUT_DIR"
String vrunnerPath = VRunner.getVRunnerPath(); String vrunnerPath = VRunner.getVRunnerPath()
config.initInfoBaseOptions.extensions.each { this.extensionsFiltered.each {
Logger.println("Установим расширение ${it.name}") Logger.println("Установим расширение ${it.name}")
loadExtension(it, vrunnerPath, steps, cfeDir) loadExtension(it, vrunnerPath, steps, cfeDir)
} }
@@ -47,9 +66,31 @@ class LoadExtensions implements Serializable {
loadCommand += executeParameter loadCommand += executeParameter
loadCommand += ' --ibconnection "/F./build/ib"' loadCommand += ' --ibconnection "/F./build/ib"'
String vrunnerSettings = getVrunnerSettingsForStage(this.config, this.stageName)
if (vrunnerSettings && steps.fileExists(vrunnerSettings)) {
loadCommand += " --settings $vrunnerSettings"
}
List<String> logosConfig = ["LOGOS_CONFIG=$config.logosConfig"] List<String> logosConfig = ["LOGOS_CONFIG=$config.logosConfig"]
steps.withEnv(logosConfig) { steps.withEnv(logosConfig) {
VRunner.exec(loadCommand) VRunner.exec(loadCommand)
} }
} }
private static String getVrunnerSettingsForStage(JobConfiguration config, String stageName) {
if (!stageName) {
return ""
}
String optionsName = "${stageName.toLowerCase()}Options"
def optionsInstance = config."$optionsName"
if (optionsInstance) {
return optionsInstance."vrunnerSettings"
} else {
return ""
}
}
} }

View File

@@ -9,8 +9,8 @@ import ru.pulsar.jenkins.library.utils.Logger
class PublishAllure implements Serializable { class PublishAllure implements Serializable {
private final JobConfiguration config; private final JobConfiguration config
private IStepExecutor steps; private IStepExecutor steps
PublishAllure(JobConfiguration config) { PublishAllure(JobConfiguration config) {
this.config = config this.config = config
@@ -33,11 +33,14 @@ class PublishAllure implements Serializable {
if (config.stageFlags.bdd) { if (config.stageFlags.bdd) {
safeUnstash('bdd-allure') safeUnstash('bdd-allure')
} }
if (config.stageFlags.yaxunit && config.yaxunitOptions.publishToAllureReport) {
safeUnstash(Yaxunit.YAXUNIT_ALLURE_STASH)
}
if (config.stageFlags.smoke && config.smokeTestOptions.publishToAllureReport) { if (config.stageFlags.smoke && config.smokeTestOptions.publishToAllureReport) {
safeUnstash(SmokeTest.SMOKE_ALLURE_STASH) safeUnstash(SmokeTest.SMOKE_ALLURE_STASH)
} }
def env = steps.env(); def env = steps.env()
FilePath allurePath = FileUtils.getFilePath("$env.WORKSPACE/build/out/allure") FilePath allurePath = FileUtils.getFilePath("$env.WORKSPACE/build/out/allure")
if (!allurePath.exists()) { if (!allurePath.exists()) {
@@ -45,7 +48,7 @@ class PublishAllure implements Serializable {
return return
} }
List<String> results = new ArrayList<>(); List<String> results = new ArrayList<>()
allurePath.listDirectories().each { FilePath filePath -> allurePath.listDirectories().each { FilePath filePath ->
results.add(FileUtils.getLocalPath(filePath)) results.add(FileUtils.getLocalPath(filePath))

View File

@@ -0,0 +1,90 @@
package ru.pulsar.jenkins.library.steps
import hudson.FilePath
import ru.pulsar.jenkins.library.IStepExecutor
import ru.pulsar.jenkins.library.configuration.JobConfiguration
import ru.pulsar.jenkins.library.ioc.ContextRegistry
import ru.pulsar.jenkins.library.utils.FileUtils
import ru.pulsar.jenkins.library.utils.Logger
import ru.pulsar.jenkins.library.utils.VRunner
class Yaxunit implements Serializable {
private final JobConfiguration config
private final String DEFAULT_YAXUNIT_CONFIGURATION_RESOURCE = 'yaxunit.json'
public static final String YAXUNIT_ALLURE_STASH = 'yaxunit-allure'
Yaxunit(JobConfiguration config) {
this.config = config
}
def run() {
IStepExecutor steps = ContextRegistry.getContext().getStepExecutor()
Logger.printLocation()
if (!config.stageFlags.yaxunit) {
Logger.println("Yaxunit test step is disabled")
return
}
List<String> logosConfig = ["LOGOS_CONFIG=$config.logosConfig"]
steps.withEnv(logosConfig) {
steps.installLocalDependencies()
}
def options = config.yaxunitOptions
def env = steps.env()
String vrunnerPath = VRunner.getVRunnerPath()
String ibConnection = ' --ibconnection "/F./build/ib"'
// Готовим конфиг для yaxunit
String yaxunitConfigPath = options.configPath
if (!steps.fileExists(yaxunitConfigPath)) {
def defaultYaxunitConfig = steps.libraryResource DEFAULT_YAXUNIT_CONFIGURATION_RESOURCE
steps.writeFile(options.configPath, defaultYaxunitConfig, 'UTF-8')
}
def yaxunitConfig = FileUtils.getFilePath(yaxunitConfigPath)
// Команда запуска тестов
String runTestsCommand = "$vrunnerPath run --command RunUnitTests=$yaxunitConfig $ibConnection"
// Переопределяем настройки vrunner
String vrunnerSettings = options.vrunnerSettings
if (steps.fileExists(vrunnerSettings)) {
String vrunnerSettingsParam = " --settings $vrunnerSettings"
runTestsCommand += vrunnerSettingsParam
}
// Выполяем команды
steps.withEnv(logosConfig) {
VRunner.exec(runTestsCommand, true)
}
// Сохраняем результаты
String junitReport = "./build/out/yaxunit/junit.xml"
FilePath pathToJUnitReport = FileUtils.getFilePath("$env.WORKSPACE/$junitReport")
String junitReportDir = FileUtils.getLocalPath(pathToJUnitReport.getParent())
if (options.publishToJUnitReport) {
steps.junit("$junitReportDir/*.xml", true)
steps.archiveArtifacts("$junitReportDir/**")
}
if (options.publishToAllureReport) {
String allureReport = "./build/out/allure/yaxunit/junit.xml"
FilePath pathToAllureReport = FileUtils.getFilePath("$env.WORKSPACE/$allureReport")
String allureReportDir = FileUtils.getLocalPath(pathToAllureReport.getParent())
pathToJUnitReport.copyTo(pathToAllureReport)
steps.stash(YAXUNIT_ALLURE_STASH, "$allureReportDir/**", true)
}
}
}

View File

@@ -11,13 +11,13 @@ class VRunner {
IStepExecutor steps = ContextRegistry.getContext().getStepExecutor() IStepExecutor steps = ContextRegistry.getContext().getStepExecutor()
String vrunnerBinary = steps.isUnix() ? "vrunner" : "vrunner.bat"; String vrunnerBinary = steps.isUnix() ? "vrunner" : "vrunner.bat"
String vrunnerPath = "oscript_modules/bin/$vrunnerBinary"; String vrunnerPath = "oscript_modules/bin/$vrunnerBinary"
if (!steps.fileExists(vrunnerPath)) { if (!steps.fileExists(vrunnerPath)) {
vrunnerPath = vrunnerBinary; vrunnerPath = vrunnerBinary
} }
return vrunnerPath; return vrunnerPath
} }
static int exec(String command, boolean returnStatus = false) { static int exec(String command, boolean returnStatus = false) {
@@ -38,4 +38,5 @@ class VRunner {
String fileContent = steps.readFile(configPath) String fileContent = steps.readFile(configPath)
return fileContent.contains("\"$settingName\"") return fileContent.contains("\"$settingName\"")
} }
} }

View File

@@ -47,7 +47,7 @@ class jobConfigurationTest {
'jobConfiguration.json', 'jobConfiguration.json',
StandardCharsets.UTF_8, StandardCharsets.UTF_8,
this.getClass().getClassLoader() this.getClass().getClassLoader()
); )
def writeFile = """ def writeFile = """
writeFile text: \"\"\"$file\"\"\", file: 'jobConfiguration.json' writeFile text: \"\"\"$file\"\"\", file: 'jobConfiguration.json'

View File

@@ -7,5 +7,7 @@
"initMethod": "fromSource", "initMethod": "fromSource",
"path": "/src/cfe/тест" "path": "/src/cfe/тест"
}] }]
},
"yaxunit": {
} }
} }

View File

@@ -0,0 +1,66 @@
package ru.pulsar.jenkins.library.steps;
import hudson.FilePath;
import org.apache.commons.io.IOUtils;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import ru.pulsar.jenkins.library.configuration.ConfigurationReader;
import ru.pulsar.jenkins.library.configuration.InitInfoBaseOptions;
import ru.pulsar.jenkins.library.configuration.JobConfiguration;
import ru.pulsar.jenkins.library.utils.FileUtils;
import ru.pulsar.jenkins.library.utils.TestUtils;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.anyString;
class LoadExtensionsTest {
@BeforeEach
void setUp() {
TestUtils.setupMockedContext();
}
@Test
void runYaxunit() throws IOException {
try (MockedStatic<FileUtils> fu = Mockito.mockStatic(FileUtils.class)) {
fu.when(() -> FileUtils.getFilePath(anyString()))
.thenReturn(new FilePath(new File("/")));
// given
// файл содержит 4 расширения для разных стейджей
String config = IOUtils.resourceToString(
"jobConfiguration.json",
StandardCharsets.UTF_8,
this.getClass().getClassLoader()
);
JobConfiguration jobConfiguration = ConfigurationReader.create(config);
// when
LoadExtensions loadExtensions = new LoadExtensions(jobConfiguration);
loadExtensions.run();
// then
InitInfoBaseOptions.Extension[] extensions = loadExtensions.getExtensionsFiltered();
assertThat(extensions.length).isEqualTo(2);
assertThat(extensions[0].getName()).isEqualTo("mods");
assertThat(extensions[1].getName()).isEqualTo("mods2");
// when
LoadExtensions loadExtensionsWithStage = new LoadExtensions(jobConfiguration, "yaxunit");
loadExtensionsWithStage.run();
// then
extensions = loadExtensionsWithStage.getExtensionsFiltered();
assertThat(extensions.length).isEqualTo(1);
assertThat(extensions[0].getName()).isEqualTo("YAXUnit");
}
}
}

View File

@@ -0,0 +1,32 @@
package ru.pulsar.jenkins.library.utils;
import hudson.EnvVars;
import org.jenkinsci.plugins.workflow.support.actions.EnvironmentAction;
import java.io.IOException;
public class EnvUtils implements EnvironmentAction {
public String NODE_NAME = "node";
public String WORKSPACE = "ws";
@Override
public EnvVars getEnvironment() throws IOException, InterruptedException {
return null;
}
@Override
public String getIconFileName() {
return null;
}
@Override
public String getDisplayName() {
return null;
}
@Override
public String getUrlName() {
return null;
}
}

View File

@@ -28,6 +28,8 @@ public class TestUtils {
); );
}); });
when(steps.env()).thenAnswer(invocation -> new EnvUtils());
when(steps.readFile(anyString(), anyString())).thenAnswer(invocation -> { when(steps.readFile(anyString(), anyString())).thenAnswer(invocation -> {
String file = invocation.getArgument(0); String file = invocation.getArgument(0);
String encoding = invocation.getArgument(1); String encoding = invocation.getArgument(1);

View File

@@ -14,6 +14,31 @@
"runMigration": false, "runMigration": false,
"additionalInitializationSteps": [ "additionalInitializationSteps": [
"vanessa --settings ./tools/vrunner.first.json" "vanessa --settings ./tools/vrunner.first.json"
],
"extensions": [
{
"name": "YAXUnit",
"initMethod": "fromSource",
"path": "./src/cfe/YAXUnit",
"stages": ["yaxunit"]
},
{
"name": "BDD",
"initMethod": "fromSource",
"path": "./src/cfe/bdd",
"stages": ["bdd"]
},
{
"name": "mods",
"initMethod": "fromSource",
"path": "./src/cfe/mods"
},
{
"name": "mods2",
"initMethod": "fromSource",
"path": "./src/cfe/mods2",
"stages": ["initInfoBase"]
}
] ]
}, },
"sonarqube": { "sonarqube": {

View File

@@ -2,9 +2,9 @@ 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.steps.LoadExtensions import ru.pulsar.jenkins.library.steps.LoadExtensions
def call(JobConfiguration config) { def call(JobConfiguration config, String stageName = "") {
ContextRegistry.registerDefaultContext(this) ContextRegistry.registerDefaultContext(this)
def loadExtensions = new LoadExtensions(config) def loadExtensions = new LoadExtensions(config, stageName)
loadExtensions.run() loadExtensions.run()
} }

View File

@@ -204,11 +204,31 @@ void call() {
beforeAgent true beforeAgent true
expression { config.stageFlags.bdd } expression { config.stageFlags.bdd }
} }
steps { stages {
timeout(time: config.timeoutOptions.bdd, unit: TimeUnit.MINUTES) { stage('Распаковка ИБ') {
unzipInfobase() steps {
unzipInfobase()
}
}
bdd config stage('Загрузка расширений в конфигурацию') {
when {
beforeAgent true
expression { config.needLoadExtensions('bdd') }
}
steps {
timeout(time: config.timeoutOptions.loadExtensions, unit: TimeUnit.MINUTES) {
loadExtensions config, 'bdd'
}
}
}
stage('Выполнение BDD сценариев') {
steps {
timeout(time: config.timeoutOptions.bdd, unit: TimeUnit.MINUTES) {
bdd config
}
}
} }
} }
} }
@@ -236,11 +256,68 @@ void call() {
beforeAgent true beforeAgent true
expression { config.stageFlags.smoke } expression { config.stageFlags.smoke }
} }
steps { stages {
timeout(time: config.timeoutOptions.smoke, unit: TimeUnit.MINUTES) { stage('Распаковка ИБ') {
unzipInfobase() steps {
unzipInfobase()
}
}
smoke config stage('Загрузка расширений в конфигурацию') {
when {
beforeAgent true
expression { config.needLoadExtensions('smoke') }
}
steps {
timeout(time: config.timeoutOptions.loadExtensions, unit: TimeUnit.MINUTES) {
loadExtensions config, 'smoke'
}
}
}
stage('Выполнение дымовых тестов') {
steps {
timeout(time: config.timeoutOptions.smoke, unit: TimeUnit.MINUTES) {
smoke config
}
}
}
}
}
stage('YAXUnit тесты') {
agent {
label agent1C
}
when {
beforeAgent true
expression { config.stageFlags.yaxunit }
}
stages {
stage('Распаковка ИБ') {
steps {
unzipInfobase()
}
}
stage('Загрузка расширений в конфигурацию') {
when {
beforeAgent true
expression { config.needLoadExtensions('yaxunit') }
}
steps {
timeout(time: config.timeoutOptions.loadExtensions, unit: TimeUnit.MINUTES) {
loadExtensions config, 'yaxunit'
}
}
}
stage('Выполнение YAXUnit тестов') {
steps {
timeout(time: config.timeoutOptions.yaxunit, unit: TimeUnit.MINUTES) {
yaxunit config
}
}
} }
} }
} }

View File

@@ -1,4 +1,11 @@
import ru.pulsar.jenkins.library.steps.GetExtensions
def call() { def call() {
unstash '1Cv8.1CD.zip' unstash '1Cv8.1CD.zip'
unzip dir: 'build/ib', zipFile: '1Cv8.1CD.zip' unzip dir: 'build/ib', zipFile: '1Cv8.1CD.zip'
try {
unstash GetExtensions.EXTENSIONS_STASH
} catch (Exception e) {
echo e.toString()
}
} }

12
vars/yaxunit.groovy Normal file
View File

@@ -0,0 +1,12 @@
import ru.pulsar.jenkins.library.configuration.JobConfiguration
import ru.pulsar.jenkins.library.ioc.ContextRegistry
import ru.pulsar.jenkins.library.steps.Yaxunit
def call(JobConfiguration config) {
ContextRegistry.registerDefaultContext(this)
def yaxunit = new Yaxunit(config)
yaxunit.run()
}