diff --git a/README.md b/README.md index de1f1a90..d9f27e27 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,7 @@ 1. Трансформация кода из формата конфигуратора в формат EDT. 1. Трансформация кода из формата EDT в формат конфигуратора. 1. Запуск BDD сценариев с сохранением результатов в формате Allure. +1. Запуск юнит-тестов с помощью фреймворка YAXUnit с сохранением результатов в формате jUnit и Allure. 1. Запуск синтаксического контроля средствами конфигуратора и сохранение результатов в виде отчета jUnit. 1. Запуск валидации проекта средствами EDT и конвертация отчета в формате generic issues. 1. Запуск статического анализа для SonarQube. @@ -67,7 +68,8 @@ pipeline1C() ## Внешний вид пайплайна в интерфейсе 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`). - * По-умолчанию версия модуля EDT не заполнена, т.к. в случае единственной версии для утилиты ring дополнительного указания не требуется (`edtVersion`). + * По умолчанию версия модуля EDT не заполнена, т.к. в случае единственной версии для утилиты ring дополнительного указания не требуется (`edtVersion`). * Исходники конфигурации ожидаются в каталоге `src/cf` (`srcDir`). * Формат исходников - выгрузка из Конфигуратора (`sourceFormat`). * Ветка по умолчанию (для комбинированного режима загрузки конфигурации) - "main" (`defaultBranch`). @@ -131,6 +133,8 @@ pipeline1C() * Если в настройках шага инициализации не заполнен массив дополнительных шагов миграции (`initInfobase` -> `additionalInitializationSteps`), но в каталоге `tools` присутствуют файлы с именами, удовлетворяющими шаблону `vrunner.init*.json`, то автоматически выполняется запуск `vrunner vanessa` с передачей найденных файлов в качестве значения настроек (параметр `--settings`) в порядке лексикографической сортировки имен файлов. * BDD: * Если в конфигурационном файле проекта не заполнена настройка `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`). * Если установка локальных зависимостей `opm` установит пакет `add`, то будет использоваться обработка `xddTestRunner.epf` из локальных зависимостей. @@ -167,7 +171,7 @@ pipeline1C() * Telegram: * Уведомления о результатах сборки по умолчанию рассылаются всегда (`notifications` -> `telegram` -> `onAlways`, `onFailure`, `onUnstable`, `onSuccess`). -## Конфигурирование загрузки расширений +## Настройка загрузки расширений Если у вас есть расширения которые необходимо загрузить в базу для проведения тестов и проверок, это можно сделать на этапе подготовки базы. * При загрузке из исходников расширения должны быть в том же формате(edt или конфигуратора) что и основная конфигурация. @@ -199,4 +203,10 @@ pipeline1C() } ] } -``` \ No newline at end of file +``` + +## Настройка шага YAXUnit + + * Добавить расширение `YAXUnit` и дополнительные расширения с тестами можно в `jobConfiguration.json` -> `initInfobase` -> `extensions`. Они будут загружены при инициализации ИБ. + * Если ваши тесты размещены в отдельных расширениях, скопируйте файл `./resources/yaxunit.json` из текущей библиотеки в свой репозиторий (`./tools/yaxunit.json`) и перечислите в нем имена ваших расширений. + * Если используется собственный файл `tools/yaxunit.json`, то значение параметра reportPath в нем должно быть равно `./build/out/yaxunit/junit.xml` diff --git a/build.gradle.kts b/build.gradle.kts index 2de8c201..afd047aa 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -48,7 +48,7 @@ dependencies { testRuntimeOnly("org.junit.jupiter", "junit-jupiter-engine", junitVersion) 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-simple", slf4jVersion) @@ -61,6 +61,7 @@ dependencies { integrationTestImplementation("org.slf4j", "slf4j-api", slf4jVersion) integrationTestImplementation("org.slf4j", "slf4j-simple", slf4jVersion) + } tasks.test { @@ -105,6 +106,8 @@ sharedLibrary { dependency("org.6wind.jenkins", "lockable-resources", "2.7") dependency("ru.yandex.qatools.allure", "allure-jenkins-plugin", "2.28.1") val declarativePluginsVersion = "1.6.0" + + 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-definition", declarativePluginsVersion) diff --git a/resources/globalConfiguration.json b/resources/globalConfiguration.json index 45936811..693f5544 100644 --- a/resources/globalConfiguration.json +++ b/resources/globalConfiguration.json @@ -18,11 +18,13 @@ "syntaxCheck": false, "edtValidate": false, "smoke": false, + "yaxunit": false, "email": false, "telegram": false }, "timeout": { "smoke": 240, + "yaxunit": 240, "bdd": 120, "getBinaries": 60, "createInfoBase": 60, @@ -80,6 +82,12 @@ "publishToAllureReport": false, "publishToJUnitReport": true }, + "yaxunit": { + "vrunnerSettings": "./tools/vrunner.json", + "configPath": "./tools/yaxunit.json", + "publishToAllureReport": false, + "publishToJUnitReport": true + }, "resultsTransform": { "removeSupport": true, "supportLevel": 0 diff --git a/resources/schema.json b/resources/schema.json index f3c942c0..326c1e0a 100644 --- a/resources/schema.json +++ b/resources/schema.json @@ -1,405 +1,437 @@ { - "type": "object", - "id": "urn:jsonschema:ru:pulsar:jenkins:library:configuration:JobConfiguration", - "properties": { - "v8version": { - "type": "string", - "description": "Версия платформы 1С:Предприятие в формате 8.3.хх.хххх." + "type" : "object", + "id" : "urn:jsonschema:ru:pulsar:jenkins:library:configuration:JobConfiguration", + "properties" : { + "v8version" : { + "type" : "string", + "description" : "Версия платформы 1С:Предприятие в формате 8.3.хх.хххх." }, - "edtVersion": { - "type": "string", - "description": "Версия модуля 1C:Enterprise Development Tools формате xxxx.x.x:x86_64" + "edtVersion" : { + "type" : "string", + "description" : "Версия модуля 1C:Enterprise Development Tools формате xxxx.x.x:x86_64" }, - "srcDir": { - "type": "string", - "description": "Путь к корневому каталогу с исходниками конфигурации, в случае хранения исходников в формате EDT, необходимо указать путь к проекту" + "srcDir" : { + "type" : "string", + "description" : "Путь к корневому каталогу с исходниками конфигурации, в случае хранения исходников в формате EDT, необходимо указать путь к проекту" }, - "sourceFormat": { - "type": "string", - "description": "Формат исходников конфигурации", - "enum": ["edt", "designer"] + "sourceFormat" : { + "type" : "string", + "description" : "Формат исходников конфигурации", + "enum" : [ "edt", "designer" ] }, - "defaultBranch": { - "type": "string", - "description": "Имя ветки по умолчанию. Значение по умолчанию - main." + "defaultBranch" : { + "type" : "string", + "description" : "Имя ветки по умолчанию. Значение по умолчанию - main." }, - "secrets": { - "type": "object", - "id": "urn:jsonschema:ru:pulsar:jenkins:library:configuration:Secrets", - "description": "Идентификаторы сохраненных секретов", - "properties": { - "storagePath": { - "type": "string", - "description": "Путь к хранилищу конфигурации" - }, - "storage": { - "type": "string", - "description": "Данные авторизации в хранилище конфигурации" - }, - "telegramChatId": { - "type": "string", - "description": "Идентификатор telegram-чата для отправки уведомлений" - }, - "telegramBotToken": { - "type": "string", - "description": "Токен авторизации telegram-бота для отправки уведомлений" + "secrets" : { + "type" : "object", + "id" : "urn:jsonschema:ru:pulsar:jenkins:library:configuration:Secrets", + "description" : "Идентификаторы сохраненных секретов", + "properties" : { + "storagePath" : { + "type" : "string", + "description" : "Путь к хранилищу конфигурации" + }, + "storage" : { + "type" : "string", + "description" : "Данные авторизации в хранилище конфигурации" + }, + "telegramChatId" : { + "type" : "string", + "description" : "Идентификатор telegram-чата для отправки уведомлений" + }, + "telegramBotToken" : { + "type" : "string", + "description" : "Токен авторизации telegram-бота для отправки уведомлений" } } }, - "stages": { - "type": "object", - "id": "urn:jsonschema:ru:pulsar:jenkins:library:configuration:StageFlags", - "description": "Включение этапов сборок", - "properties": { - "sonarqube": { - "type": "boolean", - "description": "Анализ SonarQube включен" - }, - "syntaxCheck": { - "type": "boolean", - "description": "Синтаксический контроль включен" - }, - "edtValidate": { - "type": "boolean", - "description": "Валидация EDT включена" - }, - "smoke": { - "type": "boolean", - "description": "Дымовые тесты включены" - }, - "initSteps": { - "type": "boolean", - "description": "Предварительные шаги инициализации включены" - }, - "bdd": { - "type": "boolean", - "description": "Запуск BDD сценариев включен" - }, - "email": { - "type": "boolean", - "description": "Выполнять рассылку результатов сборки на email" - }, - "telegram": { - "type": "boolean", - "description": "Выполнять рассылку результатов сборки в telegram" + "stages" : { + "type" : "object", + "id" : "urn:jsonschema:ru:pulsar:jenkins:library:configuration:StageFlags", + "description" : "Включение этапов сборок", + "properties" : { + "sonarqube" : { + "type" : "boolean", + "description" : "Анализ SonarQube включен" + }, + "syntaxCheck" : { + "type" : "boolean", + "description" : "Синтаксический контроль включен" + }, + "edtValidate" : { + "type" : "boolean", + "description" : "Валидация EDT включена" + }, + "smoke" : { + "type" : "boolean", + "description" : "Дымовые тесты включены" + }, + "yaxunit" : { + "type" : "boolean", + "description" : "Запуск YAXUnit тестов включен" + }, + "initSteps" : { + "type" : "boolean", + "description" : "Предварительные шаги инициализации включены" + }, + "bdd" : { + "type" : "boolean", + "description" : "Запуск BDD сценариев включен" + }, + "email" : { + "type" : "boolean", + "description" : "Выполнять рассылку результатов сборки на email" + }, + "telegram" : { + "type" : "boolean", + "description" : "Выполнять рассылку результатов сборки в telegram" } } }, - "timeout": { - "type": "object", - "id": "urn:jsonschema:ru:pulsar:jenkins:library:configuration:TimeoutOptions", - "description": "Настройка таймаутов для шагов", - "properties": { - "edtToDesignerFormatTransformation": { - "type": "integer", - "description": "Таймаут шага трансформации исходников из формата EDT в формат Конфигуратора, в минутах.\n По умолчанию содержит значение 60.\n " - }, - "getBinaries": { - "type": "integer", - "description": "Таймаут шага получения бинарников, в минутах.\n По умолчанию содержит значение 60.\n " - }, - "createInfoBase": { - "type": "integer", - "description": "Таймаут шага создания информационной базы, в минутах.\n По умолчанию содержит значение 60.\n " - }, - "initInfoBase": { - "type": "integer", - "description": "Таймаут шага инициализации информационной базы, в минутах.\n По умолчанию содержит значение 60.\n " - }, - "loadExtensions": { - "type": "integer", - "description": "Таймаут шага загрузки расширений в базу, в минутах.\n По умолчанию содержит значение 60.\n " - }, - "zipInfoBase": { - "type": "integer", - "description": "Таймаут шага архивирования информационной базы, в минутах.\n По умолчанию содержит значение 60.\n " - }, - "designerToEdtFormatTransformation": { - "type": "integer", - "description": "Таймаут шага трансформации исходников из формата Конфигуратора в формат EDT, в минутах.\n По умолчанию содержит значение 60.\n " - }, - "edtValidate": { - "type": "integer", - "description": "Таймаут шага валидации EDT, в минутах.\n По умолчанию содержит значение 240.\n " - }, - "resultTransformation": { - "type": "integer", - "description": "Таймаут шага трансформации результатов EDT, в минутах.\n По умолчанию содержит значение 10.\n " - }, - "bdd": { - "type": "integer", - "description": "Таймаут шага проверки сценариев поведения, в минутах.\n По умолчанию содержит значение 120.\n " - }, - "syntaxCheck": { - "type": "integer", - "description": "Таймаут шага синтаксического контроля, в минутах.\n По умолчанию содержит значение 240.\n " - }, - "smoke": { - "type": "integer", - "description": "Таймаут шага дымовых тестов, в минутах.\n По умолчанию содержит значение 240.\n " - }, - "sonarqube": { - "type": "integer", - "description": "Таймаут шага статического анализа SonarQube, в минутах.\n По умолчанию содержит значение 90.\n " + "timeout" : { + "type" : "object", + "id" : "urn:jsonschema:ru:pulsar:jenkins:library:configuration:TimeoutOptions", + "description" : "Настройка таймаутов для шагов", + "properties" : { + "edtToDesignerFormatTransformation" : { + "type" : "integer", + "description" : "Таймаут шага трансформации исходников из формата EDT в формат Конфигуратора, в минутах.\n По умолчанию содержит значение 60.\n " + }, + "getBinaries" : { + "type" : "integer", + "description" : "Таймаут шага получения бинарников, в минутах.\n По умолчанию содержит значение 60.\n " + }, + "createInfoBase" : { + "type" : "integer", + "description" : "Таймаут шага создания информационной базы, в минутах.\n По умолчанию содержит значение 60.\n " + }, + "initInfoBase" : { + "type" : "integer", + "description" : "Таймаут шага инициализации информационной базы, в минутах.\n По умолчанию содержит значение 60.\n " + }, + "loadExtensions" : { + "type" : "integer", + "description" : "Таймаут шага загрузки расширений в базу, в минутах.\n По умолчанию содержит значение 60.\n " + }, + "zipInfoBase" : { + "type" : "integer", + "description" : "Таймаут шага архивирования информационной базы, в минутах.\n По умолчанию содержит значение 60.\n " + }, + "designerToEdtFormatTransformation" : { + "type" : "integer", + "description" : "Таймаут шага трансформации исходников из формата Конфигуратора в формат EDT, в минутах.\n По умолчанию содержит значение 60.\n " + }, + "edtValidate" : { + "type" : "integer", + "description" : "Таймаут шага валидации EDT, в минутах.\n По умолчанию содержит значение 240.\n " + }, + "resultTransformation" : { + "type" : "integer", + "description" : "Таймаут шага трансформации результатов EDT, в минутах.\n По умолчанию содержит значение 10.\n " + }, + "bdd" : { + "type" : "integer", + "description" : "Таймаут шага проверки сценариев поведения, в минутах.\n По умолчанию содержит значение 120.\n " + }, + "syntaxCheck" : { + "type" : "integer", + "description" : "Таймаут шага синтаксического контроля, в минутах.\n По умолчанию содержит значение 240.\n " + }, + "smoke" : { + "type" : "integer", + "description" : "Таймаут шага дымовых тестов, в минутах.\n По умолчанию содержит значение 240.\n " + }, + "yaxunit" : { + "type" : "integer", + "description" : "Таймаут шага YAXUnit тестов, в минутах.\n По умолчанию содержит значение 240.\n " + }, + "sonarqube" : { + "type" : "integer", + "description" : "Таймаут шага статического анализа SonarQube, в минутах.\n По умолчанию содержит значение 90.\n " } } }, - "initInfobase": { - "type": "object", - "id": "urn:jsonschema:ru:pulsar:jenkins:library:configuration:InitInfoBaseOptions", - "description": "Настройки шага инициализации ИБ", - "properties": { - "initMethod": { - "type": "string", - "description": "\n Способ инициализации информационной базы.\n Поддерживается три варианта:\n * fromStorage - инициализация информационной базы из хранилища конфигурации;\n * fromSource - инициализация информационной базы из исходников конфигурации;\n * defaultBranchFromStorage - инициализация основной ветки из хранилища конфигурации, остальных - из исходников конфигурации.\n По умолчанию содержит значение \"fromStorage\".", - "enum": ["fromStorage", "fromSource", "defaultBranchFromStorage"] - }, - "runMigration": { - "type": "boolean", - "description": "Запустить миграцию ИБ" - }, - "additionalInitializationSteps": { - "type": "array", - "description": "Дополнительные шаги, запускаемые через vrunner.\n В каждой строке передается отдельная команда \n vrunner и ее аргументы (например, \"vanessa --settings ./tools/vrunner.first.json\")\n ", - "items": { - "type": "string" + "initInfobase" : { + "type" : "object", + "id" : "urn:jsonschema:ru:pulsar:jenkins:library:configuration:InitInfoBaseOptions", + "description" : "Настройки шага инициализации ИБ", + "properties" : { + "initMethod" : { + "type" : "string", + "description" : "\n Способ инициализации информационной базы.\n Поддерживается три варианта:\n * fromStorage - инициализация информационной базы из хранилища конфигурации;\n * fromSource - инициализация информационной базы из исходников конфигурации;\n * defaultBranchFromStorage - инициализация основной ветки из хранилища конфигурации, остальных - из исходников конфигурации.\n По умолчанию содержит значение \"fromStorage\".", + "enum" : [ "fromStorage", "fromSource", "defaultBranchFromStorage" ] + }, + "runMigration" : { + "type" : "boolean", + "description" : "Запустить миграцию ИБ" + }, + "additionalInitializationSteps" : { + "type" : "array", + "description" : "Дополнительные шаги, запускаемые через vrunner.\n В каждой строке передается отдельная команда \n vrunner и ее аргументы (например, \"vanessa --settings ./tools/vrunner.first.json\")\n ", + "items" : { + "type" : "string" } }, - "extensions": { - "type": "array", - "description": "Массив расширений для загрузки в конфигурацию.", - "items": { - "type": "object", - "id": "urn:jsonschema:ru:pulsar:jenkins:library:configuration:InitInfoBaseOptions:extensions:exception", - "description": "Информация о расширении для загрузки", - "properties": { - "name": { - "type": "string", - "description": "Имя расширения с которым оно грузится в конфигурацию" + "extensions" : { + "type" : "array", + "description" : "Массив расширений для загрузки в конфигурацию.", + "items" : { + "type" : "object", + "id" : "urn:jsonschema:ru:pulsar:jenkins:library:configuration:InitInfoBaseOptions:Extension", + "properties" : { + "name" : { + "type" : "string", + "description" : "Имя расширения, используемое при его загрузке в конфигурацию." }, - "initMethod": { - "type": "string", - "description": "\n Способ инициализации расширения.\n Поддерживается два варианта:\n * fromSource - инициализация расширения из исходников;\n * fromFile - использование скомпилированного cfe.", - "enum": ["fromSource", "fromFile"] + "initMethod" : { + "type" : "string", + "description" : "\n Способ инициализации расширения.\n Поддерживается два варианта:\n * fromSource - инициализация расширения из исходников;\n * fromFile - скачивание скомпилированного cfe по ссылке.\n ", + "enum" : [ "fromSource", "fromFile" ] }, - "path": { - "type": "string", - "description": "Хранит в себе путь к расширению.\n * В случае если выбран initMethod - указывается путь к исходникам расширения.\n * В случае если выбран initMethod - указывается путь к cfe-файлу" + "path" : { + "type" : "string", + "description" : "\n Путь к расширению.\n * В случае если выбран initMethod - указывается путь к исходникам расширения.\n * В случае если выбран initMethod - указывается путь к cfe-файлу\n " + }, + "stages" : { + "type" : "array", + "description" : "\n Шаги, на которых необходимо использовать расширение\n * Если не заполнено, то расширение будет подключено при инициализации базы и останется в базе на всех последующих шагах.\n * Если заполнено, то расширение будет подключено только на соответствующих шагах.\n ", + "items" : { + "type" : "string" + } } } } } } }, - "bdd": { - "type": "object", - "id": "urn:jsonschema:ru:pulsar:jenkins:library:configuration:BddOptions", - "description": "Настройки шага запуска BDD сценариев", - "properties": { - "vrunnerSteps": { - "type": "array", - "description": "Шаги, запускаемые через vrunner.\n В каждой строке передается отдельная команда \n vrunner и ее аргументы (например, \"vanessa --settings ./tools/vrunner.json\").\n По умолчанию содержит одну команду \"vanessa --settings ./tools/vrunner.json\".\n ", - "items": { - "type": "string" + "bdd" : { + "type" : "object", + "id" : "urn:jsonschema:ru:pulsar:jenkins:library:configuration:BddOptions", + "description" : "Настройки шага запуска BDD сценариев", + "properties" : { + "vrunnerSteps" : { + "type" : "array", + "description" : "Шаги, запускаемые через vrunner.\n В каждой строке передается отдельная команда \n vrunner и ее аргументы (например, \"vanessa --settings ./tools/vrunner.json\").\n По умолчанию содержит одну команду \"vanessa --settings ./tools/vrunner.json\".\n ", + "items" : { + "type" : "string" } } } }, - "sonarqube": { - "type": "object", - "id": "urn:jsonschema:ru:pulsar:jenkins:library:configuration:SonarQubeOptions", - "description": "Настройки анализа SonarQube", - "properties": { - "sonarQubeInstallation": { - "type": "string", - "description": "Имя настроенного SonarQube-сервера (SonarQube installations).\nЕсли настроен только один сервер, то может быть оставлено пустым." - }, - "useSonarScannerFromPath": { - "type": "boolean", - "description": "Использовать sonar-scanner, доступный в PATH" - }, - "sonarScannerToolName": { - "type": "string", - "description": "Имя настроенной утилиты sonar-scanner.\nПрименяется, если useSonarScannerFromPath установлено в false." - }, - "infoBaseUpdateModuleName": { - "type": "string", - "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 " + "sonarqube" : { + "type" : "object", + "id" : "urn:jsonschema:ru:pulsar:jenkins:library:configuration:SonarQubeOptions", + "description" : "Настройки анализа SonarQube", + "properties" : { + "sonarQubeInstallation" : { + "type" : "string", + "description" : "Имя настроенного SonarQube-сервера (SonarQube installations).\nЕсли настроен только один сервер, то может быть оставлено пустым." + }, + "useSonarScannerFromPath" : { + "type" : "boolean", + "description" : "Использовать sonar-scanner, доступный в PATH" + }, + "sonarScannerToolName" : { + "type" : "string", + "description" : "Имя настроенной утилиты sonar-scanner.\nПрименяется, если useSonarScannerFromPath установлено в false." + }, + "infoBaseUpdateModuleName" : { + "type" : "string", + "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 " } } }, - "syntaxCheck": { - "type": "object", - "id": "urn:jsonschema:ru:pulsar:jenkins:library:configuration:SyntaxCheckOptions", - "description": "Настройки синтаксического контроля", - "properties": { - "pathToJUnitReport": { - "type": "string", - "description": "Путь к файлу отчета jUnit\n По умолчанию содержит значение \"./build/out/jUnit/syntax.xml\"\n " - }, - "groupErrorsByMetadata": { - "type": "boolean", - "description": "Группировать выявленные ошибки по объектам метаданных.\n По умолчанию включено.\n " - }, - "checkModes": { - "type": "array", - "description": "Режимы проверки конфигурации", - "items": { - "type": "string" + "syntaxCheck" : { + "type" : "object", + "id" : "urn:jsonschema:ru:pulsar:jenkins:library:configuration:SyntaxCheckOptions", + "description" : "Настройки синтаксического контроля", + "properties" : { + "pathToJUnitReport" : { + "type" : "string", + "description" : "Путь к файлу отчета jUnit\n По умолчанию содержит значение \"./build/out/jUnit/syntax.xml\"\n " + }, + "groupErrorsByMetadata" : { + "type" : "boolean", + "description" : "Группировать выявленные ошибки по объектам метаданных.\n По умолчанию включено.\n " + }, + "checkModes" : { + "type" : "array", + "description" : "Режимы проверки конфигурации", + "items" : { + "type" : "string" } }, - "exceptionFile": { - "type": "string", - "description": "Путь к файлу с указанием пропускаемых ошибок.\n Формат файла: в каждой строке файла указан текст пропускаемого исключения или его часть\n Кодировка: UTF-8\n " + "exceptionFile" : { + "type" : "string", + "description" : "Путь к файлу с указанием пропускаемых ошибок.\n Формат файла: в каждой строке файла указан текст пропускаемого исключения или его часть\n Кодировка: UTF-8\n " }, - "vrunnerSettings": { - "type": "string", - "description": "Путь к конфигурационному файлу vanessa-runner.\n По умолчанию содержит значение \"./tools/vrunner.json\".\n " + "vrunnerSettings" : { + "type" : "string", + "description" : "Путь к конфигурационному файлу vanessa-runner.\n По умолчанию содержит значение \"./tools/vrunner.json\".\n " + } + } + }, + "smoke" : { + "type" : "object", + "id" : "urn:jsonschema:ru:pulsar:jenkins:library:configuration:SmokeTestOptions", + "description" : "Настройки дымового тестирования", + "properties" : { + "vrunnerSettings" : { + "type" : "string", + "description" : "Путь к конфигурационному файлу vanessa-runner.\n По умолчанию содержит значение \"./tools/vrunner.json\".\n " + }, + "xddConfigPath" : { + "type" : "string", + "description" : "Путь к конфигурационному файлу для xddTestRunner.\n По умолчанию содержит значение \"./tools/xUnitParams.json\".\n " + }, + "publishToAllureReport" : { + "type" : "boolean", + "description" : "Выполнять публикацию результатов в отчет Allure.\n По умолчанию выключено.\n " + }, + "publishToJUnitReport" : { + "type" : "boolean", + "description" : "Выполнять публикацию результатов в отчет JUnit.\n По умолчанию включено.\n " } } }, - "smoke": { - "type": "object", - "id": "urn:jsonschema:ru:pulsar:jenkins:library:configuration:SmokeTestOptions", - "description": "Настройки дымового тестирования", - "properties": { - "vrunnerSettings": { - "type": "string", - "description": "Путь к конфигурационному файлу vanessa-runner.\n По умолчанию содержит значение \"./tools/vrunner.json\".\n " - }, - "xddConfigPath": { - "type": "string", - "description": "Путь к конфигурационному файлу для xddTestRunner.\n По умолчанию содержит значение \"./tools/xUnitParams.json\".\n " - }, - "publishToAllureReport": { - "type": "boolean", - "description": "Выполнять публикацию результатов в отчет Allure.\n По умолчанию выключено.\n " - }, - "publishToJUnitReport": { - "type": "boolean", - "description": "Выполнять публикацию результатов в отчет JUnit.\n По умолчанию включено.\n " + "yaxunit" : { + "type" : "object", + "id" : "urn:jsonschema:ru:pulsar:jenkins:library:configuration:YaxunitOptions", + "description" : "Настройки YAXUnit", + "properties" : { + "vrunnerSettings" : { + "type" : "string", + "description" : "Путь к конфигурационному файлу vanessa-runner.\n По умолчанию содержит значение \"./tools/vrunner.json\".\n " + }, + "configPath" : { + "type" : "string", + "description" : "Путь к конфигурационному файлу YAXUnit.\n По умолчанию содержит значение \"./tools/yaxunit.json\".\n " + }, + "publishToAllureReport" : { + "type" : "boolean", + "description" : "Выполнять публикацию результатов в отчет Allure.\n По умолчанию выключено.\n " + }, + "publishToJUnitReport" : { + "type" : "boolean", + "description" : "Выполнять публикацию результатов в отчет JUnit.\n По умолчанию включено.\n " } } }, - "resultsTransform": { - "type": "object", - "id": "urn:jsonschema:ru:pulsar:jenkins:library:configuration:ResultsTransformOptions", - "description": "Настройки трансформации результатов анализа", - "properties": { - "removeSupport": { - "type": "boolean", - "description": "Фильтровать замечания по уровню поддержки модуля. По умолчанию включено." - }, - "supportLevel": { - "type": "integer", - "description": "Настройка фильтрации замечаний по уровню поддержки.\n 0 - удалить файлы на замке;\n 1 - удалить файлы на замке и на поддержке;\n 2 - удалить файлы на замке, на поддержке и снятые с поддержки.\n " + "resultsTransform" : { + "type" : "object", + "id" : "urn:jsonschema:ru:pulsar:jenkins:library:configuration:ResultsTransformOptions", + "description" : "Настройки трансформации результатов анализа", + "properties" : { + "removeSupport" : { + "type" : "boolean", + "description" : "Фильтровать замечания по уровню поддержки модуля. По умолчанию включено." + }, + "supportLevel" : { + "type" : "integer", + "description" : "Настройка фильтрации замечаний по уровню поддержки.\n 0 - удалить файлы на замке;\n 1 - удалить файлы на замке и на поддержке;\n 2 - удалить файлы на замке, на поддержке и снятые с поддержки.\n " } } }, - "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": "Отправлять всегда" + "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": "Отправлять при успешной сборке" + "onSuccess" : { + "type" : "boolean", + "description" : "Отправлять при успешной сборке" }, - "onFailure": { - "type": "boolean", - "description": "Отправлять при падении сборки" + "onFailure" : { + "type" : "boolean", + "description" : "Отправлять при падении сборки" }, - "onUnstable": { - "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" + "alwaysOptions" : { + "type" : "object", + "id" : "urn:jsonschema:ru:pulsar:jenkins:library:configuration:notification:email:EmailExtConfiguration", + "properties" : { + "attachLog" : { + "type" : "boolean" }, - "directRecipients": { - "type": "array", - "items": { - "type": "string" + "directRecipients" : { + "type" : "array", + "items" : { + "type" : "string" } }, - "recipientProviders": { - "type": "array", - "items": { - "type": "string", - "enum": [ - "developers", - "requestor", - "brokenBuildSuspects", - "brokenTestsSuspects" - ] + "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" + "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" + "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" + "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": "Отправлять всегда" + "telegram" : { + "type" : "object", + "id" : "urn:jsonschema:ru:pulsar:jenkins:library:configuration:notification:TelegramNotificationOptions", + "description" : "Настройки рассылки результатов сборки через telegram", + "properties" : { + "onAlways" : { + "type" : "boolean", + "description" : "Отправлять всегда" }, - "onSuccess": { - "type": "boolean", - "description": "Отправлять при успешной сборке" + "onSuccess" : { + "type" : "boolean", + "description" : "Отправлять при успешной сборке" }, - "onFailure": { - "type": "boolean", - "description": "Отправлять при падении сборки" + "onFailure" : { + "type" : "boolean", + "description" : "Отправлять при падении сборки" }, - "onUnstable": { - "type": "boolean", - "description": "Отправлять при нестабильной сборке" + "onUnstable" : { + "type" : "boolean", + "description" : "Отправлять при нестабильной сборке" } } } } }, - "logosConfig": { - "type": "string", - "description": "Конфигурация библиотеки logos. Применяется перед запуском каждой стадии сборки" + "logosConfig" : { + "type" : "string", + "description" : "Конфигурация библиотеки logos. Применяется перед запуском каждой стадии сборки" } } -} +} \ No newline at end of file diff --git a/resources/yaxunit.json b/resources/yaxunit.json new file mode 100644 index 00000000..b5910455 --- /dev/null +++ b/resources/yaxunit.json @@ -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" +} \ No newline at end of file diff --git a/src/ru/pulsar/jenkins/library/IStepExecutor.groovy b/src/ru/pulsar/jenkins/library/IStepExecutor.groovy index d56ddf57..acf5baca 100644 --- a/src/ru/pulsar/jenkins/library/IStepExecutor.groovy +++ b/src/ru/pulsar/jenkins/library/IStepExecutor.groovy @@ -26,6 +26,8 @@ interface IStepExecutor { String readFile(String file, String encoding) + void writeFile(String file, String text, String encoding) + boolean fileExists(String file) void echo(message) diff --git a/src/ru/pulsar/jenkins/library/StepExecutor.groovy b/src/ru/pulsar/jenkins/library/StepExecutor.groovy index fb8c2127..e2599343 100644 --- a/src/ru/pulsar/jenkins/library/StepExecutor.groovy +++ b/src/ru/pulsar/jenkins/library/StepExecutor.groovy @@ -42,6 +42,11 @@ class StepExecutor implements IStepExecutor { 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 boolean fileExists(String file) { steps.fileExists file diff --git a/src/ru/pulsar/jenkins/library/configuration/ConfigurationReader.groovy b/src/ru/pulsar/jenkins/library/configuration/ConfigurationReader.groovy index 395da027..51465af4 100644 --- a/src/ru/pulsar/jenkins/library/configuration/ConfigurationReader.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/ConfigurationReader.groovy @@ -65,6 +65,7 @@ class ConfigurationReader implements Serializable { "bddOptions", "sonarQubeOptions", "smokeTestOptions", + "yaxunitOptions", "syntaxCheckOptions", "resultsTransformOptions", "notificationsOptions", diff --git a/src/ru/pulsar/jenkins/library/configuration/InitInfoBaseOptions.groovy b/src/ru/pulsar/jenkins/library/configuration/InitInfoBaseOptions.groovy index b6614983..f1b7e1aa 100644 --- a/src/ru/pulsar/jenkins/library/configuration/InitInfoBaseOptions.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/InitInfoBaseOptions.groovy @@ -14,7 +14,7 @@ class InitInfoBaseOptions implements Serializable { * fromSource - инициализация информационной базы из исходников конфигурации; * defaultBranchFromStorage - инициализация основной ветки из хранилища конфигурации, остальных - из исходников конфигурации. По умолчанию содержит значение "fromStorage".""") - InitInfoBaseMethod initMethod = InitInfoBaseMethod.FROM_STORAGE; + InitInfoBaseMethod initMethod = InitInfoBaseMethod.FROM_STORAGE @JsonPropertyDescription("Запустить миграцию ИБ") Boolean runMigration = true @@ -26,12 +26,12 @@ class InitInfoBaseOptions implements Serializable { String[] additionalInitializationSteps @JsonPropertyDescription("Массив расширений для загрузки в конфигурацию.") - Extension[] extensions; + Extension[] extensions @JsonIgnoreProperties(ignoreUnknown = true) static class Extension implements Serializable { @JsonPropertyDescription("Имя расширения, используемое при его загрузке в конфигурацию.") - String name = "extension"; + String name = "extension" @JsonPropertyDescription(""" Способ инициализации расширения. @@ -39,14 +39,21 @@ class InitInfoBaseOptions implements Serializable { * fromSource - инициализация расширения из исходников; * fromFile - скачивание скомпилированного cfe по ссылке. """) - InitExtensionMethod initMethod = InitExtensionMethod.SOURCE; + InitExtensionMethod initMethod = InitExtensionMethod.SOURCE @JsonPropertyDescription(""" - Хранит в себе путь к расширению. + Путь к расширению. * В случае если выбран initMethod - указывается путь к исходникам расширения. * В случае если выбран initMethod - указывается путь к cfe-файлу """) - String path = "src/cfe/extension"; + String path = "src/cfe/extension" + + @JsonPropertyDescription(""" + Шаги, на которых необходимо использовать расширение + * Если не заполнено, то расширение будет подключено при инициализации базы и останется в базе на всех последующих шагах. + * Если заполнено, то расширение будет подключено только на соответствующих шагах. + """) + String[] stages = ["initInfoBase"] } @Override @@ -57,6 +64,6 @@ class InitInfoBaseOptions implements Serializable { ", runMigration=" + runMigration + ", additionalInitializationSteps=" + additionalInitializationSteps + ", extensions=" + extensions + - '}'; + '}' } } diff --git a/src/ru/pulsar/jenkins/library/configuration/JobConfiguration.groovy b/src/ru/pulsar/jenkins/library/configuration/JobConfiguration.groovy index 8c1d331c..080bc23a 100644 --- a/src/ru/pulsar/jenkins/library/configuration/JobConfiguration.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/JobConfiguration.groovy @@ -55,6 +55,10 @@ class JobConfiguration implements Serializable { @JsonPropertyDescription("Настройки дымового тестирования") SmokeTestOptions smokeTestOptions; + @JsonProperty("yaxunit") + @JsonPropertyDescription("Настройки YAXUnit") + YaxunitOptions yaxunitOptions; + @JsonProperty("resultsTransform") @JsonPropertyDescription("Настройки трансформации результатов анализа") ResultsTransformOptions resultsTransformOptions; @@ -84,6 +88,7 @@ class JobConfiguration implements Serializable { ", sonarQubeOptions=" + sonarQubeOptions + ", syntaxCheckOptions=" + syntaxCheckOptions + ", smokeTestOptions=" + smokeTestOptions + + ", yaxunitOptions=" + yaxunitOptions + ", resultsTransformOptions=" + resultsTransformOptions + ", notificationOptions=" + notificationsOptions + ", logosConfig='" + logosConfig + '\'' + @@ -100,8 +105,14 @@ class JobConfiguration implements Serializable { (initMethod == InitInfoBaseMethod.DEFAULT_BRANCH_FROM_STORAGE && branchName != defaultBranch) } - boolean needLoadExtensions() { - return initInfoBaseOptions.extensions.length != 0 + boolean needLoadExtensions(String stageName = "") { + if (stageName.isEmpty()) { + return initInfoBaseOptions.extensions.length != 0 + } else { + return initInfoBaseOptions.extensions.any { extension -> + extension.stages.contains(stageName) + } + } } String v8AgentLabel() { diff --git a/src/ru/pulsar/jenkins/library/configuration/StageFlags.groovy b/src/ru/pulsar/jenkins/library/configuration/StageFlags.groovy index 28f23adf..1d8c21c9 100644 --- a/src/ru/pulsar/jenkins/library/configuration/StageFlags.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/StageFlags.groovy @@ -18,6 +18,9 @@ class StageFlags implements Serializable { @JsonPropertyDescription("Дымовые тесты включены") Boolean smoke + @JsonPropertyDescription("Запуск YAXUnit тестов включен") + Boolean yaxunit + @JsonPropertyDescription("Предварительные шаги инициализации включены") Boolean initSteps @@ -46,6 +49,6 @@ class StageFlags implements Serializable { } boolean needInfoBase() { - return smoke || syntaxCheck || initSteps || bdd + return smoke || syntaxCheck || initSteps || bdd || yaxunit } } diff --git a/src/ru/pulsar/jenkins/library/configuration/TimeoutOptions.groovy b/src/ru/pulsar/jenkins/library/configuration/TimeoutOptions.groovy index 612dc2b6..900f6a90 100644 --- a/src/ru/pulsar/jenkins/library/configuration/TimeoutOptions.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/TimeoutOptions.groovy @@ -66,6 +66,11 @@ class TimeoutOptions implements Serializable { ''') Integer smoke + @JsonPropertyDescription('''Таймаут шага YAXUnit тестов, в минутах. + По умолчанию содержит значение 240. + ''') + Integer yaxunit + @JsonPropertyDescription('''Таймаут шага статического анализа SonarQube, в минутах. По умолчанию содержит значение 90. ''') diff --git a/src/ru/pulsar/jenkins/library/configuration/YaxunitOptions.groovy b/src/ru/pulsar/jenkins/library/configuration/YaxunitOptions.groovy new file mode 100644 index 00000000..c285fa1a --- /dev/null +++ b/src/ru/pulsar/jenkins/library/configuration/YaxunitOptions.groovy @@ -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 + + '}' + } +} diff --git a/src/ru/pulsar/jenkins/library/steps/GetExtensions.groovy b/src/ru/pulsar/jenkins/library/steps/GetExtensions.groovy index cf52e90a..68bd9502 100644 --- a/src/ru/pulsar/jenkins/library/steps/GetExtensions.groovy +++ b/src/ru/pulsar/jenkins/library/steps/GetExtensions.groovy @@ -13,6 +13,7 @@ import ru.pulsar.jenkins.library.utils.FileUtils class GetExtensions implements Serializable { + public static final String EXTENSIONS_STASH = 'extensions' public static final String EXTENSIONS_OUT_DIR = 'build/out/cfe' private final JobConfiguration config; @@ -58,6 +59,9 @@ class GetExtensions implements Serializable { Logger.println("Неизвестный метод инициализации расширения ${it.name}") } } + + steps.stash(EXTENSIONS_STASH, "$EXTENSIONS_OUT_DIR/**", true) + } private void buildExtension(Extension extension, String srcDir, String vrunnerPath, IStepExecutor steps) { diff --git a/src/ru/pulsar/jenkins/library/steps/LoadExtensions.groovy b/src/ru/pulsar/jenkins/library/steps/LoadExtensions.groovy index 53be96c6..ced8c88b 100644 --- a/src/ru/pulsar/jenkins/library/steps/LoadExtensions.groovy +++ b/src/ru/pulsar/jenkins/library/steps/LoadExtensions.groovy @@ -11,10 +11,18 @@ import ru.pulsar.jenkins.library.utils.FileUtils 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.stageName = stageName + } + + Extension[] getExtensionsFiltered() { + return extensionsFiltered } def run() { @@ -22,12 +30,23 @@ class LoadExtensions implements Serializable { 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 vrunnerPath = VRunner.getVRunnerPath(); - - config.initInfoBaseOptions.extensions.each { + String vrunnerPath = VRunner.getVRunnerPath() + + this.extensionsFiltered.each { Logger.println("Установим расширение ${it.name}") loadExtension(it, vrunnerPath, steps, cfeDir) } @@ -47,9 +66,31 @@ class LoadExtensions implements Serializable { loadCommand += executeParameter loadCommand += ' --ibconnection "/F./build/ib"' + String vrunnerSettings = getVrunnerSettingsForStage(this.config, this.stageName) + if (vrunnerSettings && steps.fileExists(vrunnerSettings)) { + loadCommand += " --settings $vrunnerSettings" + } + List logosConfig = ["LOGOS_CONFIG=$config.logosConfig"] steps.withEnv(logosConfig) { 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 "" + } + } } diff --git a/src/ru/pulsar/jenkins/library/steps/PublishAllure.groovy b/src/ru/pulsar/jenkins/library/steps/PublishAllure.groovy index aaf7046c..f3fb372f 100644 --- a/src/ru/pulsar/jenkins/library/steps/PublishAllure.groovy +++ b/src/ru/pulsar/jenkins/library/steps/PublishAllure.groovy @@ -9,8 +9,8 @@ import ru.pulsar.jenkins.library.utils.Logger class PublishAllure implements Serializable { - private final JobConfiguration config; - private IStepExecutor steps; + private final JobConfiguration config + private IStepExecutor steps PublishAllure(JobConfiguration config) { this.config = config @@ -33,11 +33,14 @@ class PublishAllure implements Serializable { if (config.stageFlags.bdd) { safeUnstash('bdd-allure') } + if (config.stageFlags.yaxunit && config.yaxunitOptions.publishToAllureReport) { + safeUnstash(Yaxunit.YAXUNIT_ALLURE_STASH) + } if (config.stageFlags.smoke && config.smokeTestOptions.publishToAllureReport) { safeUnstash(SmokeTest.SMOKE_ALLURE_STASH) } - def env = steps.env(); + def env = steps.env() FilePath allurePath = FileUtils.getFilePath("$env.WORKSPACE/build/out/allure") if (!allurePath.exists()) { @@ -45,7 +48,7 @@ class PublishAllure implements Serializable { return } - List results = new ArrayList<>(); + List results = new ArrayList<>() allurePath.listDirectories().each { FilePath filePath -> results.add(FileUtils.getLocalPath(filePath)) diff --git a/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy b/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy new file mode 100644 index 00000000..2587d0bb --- /dev/null +++ b/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy @@ -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 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) + } + } +} diff --git a/src/ru/pulsar/jenkins/library/utils/VRunner.groovy b/src/ru/pulsar/jenkins/library/utils/VRunner.groovy index fdf37e2f..ebce6fe4 100644 --- a/src/ru/pulsar/jenkins/library/utils/VRunner.groovy +++ b/src/ru/pulsar/jenkins/library/utils/VRunner.groovy @@ -11,13 +11,13 @@ class VRunner { IStepExecutor steps = ContextRegistry.getContext().getStepExecutor() - String vrunnerBinary = steps.isUnix() ? "vrunner" : "vrunner.bat"; - String vrunnerPath = "oscript_modules/bin/$vrunnerBinary"; + String vrunnerBinary = steps.isUnix() ? "vrunner" : "vrunner.bat" + String vrunnerPath = "oscript_modules/bin/$vrunnerBinary" if (!steps.fileExists(vrunnerPath)) { - vrunnerPath = vrunnerBinary; + vrunnerPath = vrunnerBinary } - return vrunnerPath; + return vrunnerPath } static int exec(String command, boolean returnStatus = false) { @@ -38,4 +38,5 @@ class VRunner { String fileContent = steps.readFile(configPath) return fileContent.contains("\"$settingName\"") } + } diff --git a/test/integration/groovy/jobConfigurationTest.groovy b/test/integration/groovy/jobConfigurationTest.groovy index e3ded0b8..b2a671ec 100644 --- a/test/integration/groovy/jobConfigurationTest.groovy +++ b/test/integration/groovy/jobConfigurationTest.groovy @@ -47,7 +47,7 @@ class jobConfigurationTest { 'jobConfiguration.json', StandardCharsets.UTF_8, this.getClass().getClassLoader() - ); + ) def writeFile = """ writeFile text: \"\"\"$file\"\"\", file: 'jobConfiguration.json' diff --git a/test/integration/resources/jobConfiguration.json b/test/integration/resources/jobConfiguration.json index 38b207a9..6b3e9d10 100644 --- a/test/integration/resources/jobConfiguration.json +++ b/test/integration/resources/jobConfiguration.json @@ -7,5 +7,7 @@ "initMethod": "fromSource", "path": "/src/cfe/тест" }] + }, + "yaxunit": { } } \ No newline at end of file diff --git a/test/unit/groovy/ru/pulsar/jenkins/library/steps/LoadExtensionsTest.java b/test/unit/groovy/ru/pulsar/jenkins/library/steps/LoadExtensionsTest.java new file mode 100644 index 00000000..d4eb1271 --- /dev/null +++ b/test/unit/groovy/ru/pulsar/jenkins/library/steps/LoadExtensionsTest.java @@ -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 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"); + } + } +} diff --git a/test/unit/groovy/ru/pulsar/jenkins/library/utils/EnvUtils.java b/test/unit/groovy/ru/pulsar/jenkins/library/utils/EnvUtils.java new file mode 100644 index 00000000..d621c3e6 --- /dev/null +++ b/test/unit/groovy/ru/pulsar/jenkins/library/utils/EnvUtils.java @@ -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; + } +} diff --git a/test/unit/groovy/ru/pulsar/jenkins/library/utils/TestUtils.java b/test/unit/groovy/ru/pulsar/jenkins/library/utils/TestUtils.java index 92f5a4b4..3c1999d5 100644 --- a/test/unit/groovy/ru/pulsar/jenkins/library/utils/TestUtils.java +++ b/test/unit/groovy/ru/pulsar/jenkins/library/utils/TestUtils.java @@ -28,6 +28,8 @@ public static IStepExecutor getMockedStepExecutor() { ); }); + when(steps.env()).thenAnswer(invocation -> new EnvUtils()); + when(steps.readFile(anyString(), anyString())).thenAnswer(invocation -> { String file = invocation.getArgument(0); String encoding = invocation.getArgument(1); diff --git a/test/unit/resources/jobConfiguration.json b/test/unit/resources/jobConfiguration.json index b49569d0..803b75ea 100644 --- a/test/unit/resources/jobConfiguration.json +++ b/test/unit/resources/jobConfiguration.json @@ -14,6 +14,31 @@ "runMigration": false, "additionalInitializationSteps": [ "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": { diff --git a/vars/loadExtensions.groovy b/vars/loadExtensions.groovy index 78e8b766..6c6d4699 100644 --- a/vars/loadExtensions.groovy +++ b/vars/loadExtensions.groovy @@ -2,9 +2,9 @@ import ru.pulsar.jenkins.library.configuration.JobConfiguration import ru.pulsar.jenkins.library.ioc.ContextRegistry import ru.pulsar.jenkins.library.steps.LoadExtensions -def call(JobConfiguration config) { +def call(JobConfiguration config, String stageName = "") { ContextRegistry.registerDefaultContext(this) - def loadExtensions = new LoadExtensions(config) + def loadExtensions = new LoadExtensions(config, stageName) loadExtensions.run() } \ No newline at end of file diff --git a/vars/pipeline1C.groovy b/vars/pipeline1C.groovy index f358a8cd..731e9eeb 100644 --- a/vars/pipeline1C.groovy +++ b/vars/pipeline1C.groovy @@ -204,11 +204,31 @@ void call() { beforeAgent true expression { config.stageFlags.bdd } } - steps { - timeout(time: config.timeoutOptions.bdd, unit: TimeUnit.MINUTES) { - unzipInfobase() + stages { + stage('Распаковка ИБ') { + 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 expression { config.stageFlags.smoke } } - steps { - timeout(time: config.timeoutOptions.smoke, unit: TimeUnit.MINUTES) { - unzipInfobase() + stages { + stage('Распаковка ИБ') { + steps { + unzipInfobase() + } + } + + stage('Загрузка расширений в конфигурацию') { + when { + beforeAgent true + expression { config.needLoadExtensions('smoke') } + } + steps { + timeout(time: config.timeoutOptions.loadExtensions, unit: TimeUnit.MINUTES) { + loadExtensions config, 'smoke' + } + } + } - smoke config + 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 + } + } } } } diff --git a/vars/unzipInfobase.groovy b/vars/unzipInfobase.groovy index cb3fdfda..342e1be8 100644 --- a/vars/unzipInfobase.groovy +++ b/vars/unzipInfobase.groovy @@ -1,4 +1,11 @@ +import ru.pulsar.jenkins.library.steps.GetExtensions + def call() { unstash '1Cv8.1CD.zip' unzip dir: 'build/ib', zipFile: '1Cv8.1CD.zip' + try { + unstash GetExtensions.EXTENSIONS_STASH + } catch (Exception e) { + echo e.toString() + } } \ No newline at end of file diff --git a/vars/yaxunit.groovy b/vars/yaxunit.groovy new file mode 100644 index 00000000..8d1183c9 --- /dev/null +++ b/vars/yaxunit.groovy @@ -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() + +}