diff --git a/README.md b/README.md index 0dd12c5c..3faa810c 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,7 @@ 1. Все шаги можно запустить на базе docker-образов из https://github.com/firstBitMarksistskaya/onec-docker. См. [памятку по слоям и последовательности сборки](https://github.com/firstBitMarksistskaya/onec-docker/blob/feature/first-bit/Layers.md). 1. Поддержка как формата выгрузки из Конфигуратора, так и формата EDT. 1. Подготовка информационной базы по версии из хранилища конфигурации, из исходных файлов конфигурации, комбинированный режим (основная ветка - из хранилища, остальные - из исходников). +1. Подготовка и загрузка расширений конфигурации из исходных файлов расширения, из cfe-файлов. 1. Запуск ИБ в режиме выполнения обработчиков обновления БСП. 1. Дополнительные шаги инициализации данных в ИБ. 1. Трансформация кода из формата конфигуратора в формат EDT. @@ -66,7 +67,7 @@ pipeline1C() ## Внешний вид пайплайна в интерфейсе Blue Ocean -![image](https://user-images.githubusercontent.com/1132840/140793320-d0856afe-0864-4f0e-8964-6a9d6d5822b4.png) +![image](https://github.com/firstBitMarksistskaya/jenkins-lib/assets/80944823/e34a0112-2fe5-4116-92ac-8fcca08bba43) ## Конфигурирование @@ -165,3 +166,37 @@ pipeline1C() * Прямые получатели уведомлений не заполнены (`notifications` -> `email` -> `*options` -> `directRecipients`). * Telegram: * Уведомления о результатах сборки по умолчанию рассылаются всегда (`notifications` -> `telegram` -> `onAlways`, `onFailure`, `onUnstable`, `onSuccess`). + +## Конфигурирование загрузки расширений + +Если у вас есть расширения которые необходимо загрузить в базу для проведения тестов и проверок, это можно сделать на этапе подготовки базы. +* При загрузке из исходников расширения должны быть в том же формате(edt или конфигуратора) что и основная конфигурация. +* Для загрузки расширений необходимо описать каждое из них в массиве (`initInfobase` -> `extensions`) + +Для загрузки расширений в информационную базу необходимо выполнить следующие шаги: + +1. Укажите имя расширения(`extensions` -> `name`). +1. Определите метод загрузки для каждого расширения(`extensions` -> `initMethod`). Поддерживаются два метода загрузки: + - `fromSource` - загрузка из исходников; + - `fromFile` - загрузка cfe-файла. +1. Укажите путь до расширения или URL для скачивания cfe-файла(`extensions` -> `path`). + - В случае загрузки из исходников - необходимо указать путь к исходникам расширения + - В случае загрузки cfe - Укажите путь по которому будет скачан cfe. На данный момент можно указывать как локальный путь, так и url для скачивания cfe(Прим.: https://github.com/bia-technologies/yaxunit/releases/download/23.05/YAXUNIT-23.05.cfe) + +Пример конфигурации для загрузки расширений: +```json +"initInfobase": { + "extensions": [ + { + "name": "ИмяРасширения1", + "initMethod": "fromSource", + "path": "путь/до/исходников/расширения" + }, + { + "name": "ИмяРасширения2", + "initMethod": "fromFile", + "path": "https://example.com/path/to/extension.cfe" + } + ] +} +``` \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 0d3667d7..2de8c201 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -52,7 +52,7 @@ dependencies { testImplementation("org.slf4j", "slf4j-api", slf4jVersion) testImplementation("org.slf4j", "slf4j-simple", slf4jVersion) - + // integration-tests integrationTestImplementation("org.spockframework", "spock-core", spockVersion) integrationTestImplementation("org.codehaus.groovy", "groovy-all", groovyVersion) diff --git a/resources/globalConfiguration.json b/resources/globalConfiguration.json index 5fcd3eb7..45936811 100644 --- a/resources/globalConfiguration.json +++ b/resources/globalConfiguration.json @@ -24,11 +24,13 @@ "timeout": { "smoke": 240, "bdd": 120, + "getBinaries": 60, "createInfoBase": 60, "designerToEdtFormatTransformation": 60, "edtToDesignerFormatTransformation": 60, "edtValidate": 240, "initInfoBase": 60, + "loadExtensions": 60, "resultTransformation": 10, "sonarqube": 90, "syntaxCheck": 240, @@ -37,7 +39,8 @@ "initInfobase": { "initMethod": "fromStorage", "runMigration": true, - "additionalInitializationSteps": [] + "additionalInitializationSteps": [], + "extensions": [] }, "bdd": { "vrunnerSteps": [ diff --git a/resources/schema.json b/resources/schema.json index fbeb0dd8..f3c942c0 100644 --- a/resources/schema.json +++ b/resources/schema.json @@ -1,368 +1,405 @@ { - "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": "Дымовые тесты включены" + }, + "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 " - }, - "createInfoBase" : { - "type" : "integer", - "description" : "Таймаут шага создания информационной базы, в минутах.\n По умолчанию содержит значение 60.\n " - }, - "initInfoBase" : { - "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 " + }, + "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": "Имя расширения с которым оно грузится в конфигурацию" + }, + "initMethod": { + "type": "string", + "description": "\n Способ инициализации расширения.\n Поддерживается два варианта:\n * fromSource - инициализация расширения из исходников;\n * fromFile - использование скомпилированного cfe.", + "enum": ["fromSource", "fromFile"] + }, + "path": { + "type": "string", + "description": "Хранит в себе путь к расширению.\n * В случае если выбран initMethod - указывается путь к исходникам расширения.\n * В случае если выбран initMethod - указывается путь к cfe-файлу" + } + } } } } }, - "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 " } } }, - "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/src/ru/pulsar/jenkins/library/configuration/ConfigurationReader.groovy b/src/ru/pulsar/jenkins/library/configuration/ConfigurationReader.groovy index a7f2c1c8..395da027 100644 --- a/src/ru/pulsar/jenkins/library/configuration/ConfigurationReader.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/ConfigurationReader.groovy @@ -61,6 +61,7 @@ class ConfigurationReader implements Serializable { "stageFlags", "timeoutOptions", "initInfoBaseOptions", + "extensions", "bddOptions", "sonarQubeOptions", "smokeTestOptions", @@ -113,12 +114,30 @@ class ConfigurationReader implements Serializable { @NonCPS private static void mergeInitInfoBaseOptions(InitInfoBaseOptions baseObject, InitInfoBaseOptions objectToMerge) { - if (objectToMerge == null || objectToMerge.additionalInitializationSteps == null) { + if (objectToMerge == null) { + return + } + mergeInitInfoBaseAdditionalInitializationSteps(baseObject, objectToMerge) + mergeInitInfoBaseExtensions(baseObject, objectToMerge) + } + + @NonCPS + private static void mergeInitInfoBaseAdditionalInitializationSteps(InitInfoBaseOptions baseObject, InitInfoBaseOptions objectToMerge) { + if (objectToMerge.additionalInitializationSteps == null) { return } baseObject.additionalInitializationSteps = objectToMerge.additionalInitializationSteps.clone() } + + @NonCPS + private static void mergeInitInfoBaseExtensions(InitInfoBaseOptions baseObject, InitInfoBaseOptions objectToMerge) { + if (objectToMerge.extensions == null) { + return + } + baseObject.extensions = objectToMerge.extensions.clone() + } + @NonCPS private static void mergeBddOptions(BddOptions baseObject, BddOptions objectToMerge) { if (objectToMerge == null || objectToMerge.vrunnerSteps == null) { diff --git a/src/ru/pulsar/jenkins/library/configuration/InitExtensionMethod.groovy b/src/ru/pulsar/jenkins/library/configuration/InitExtensionMethod.groovy new file mode 100644 index 00000000..fc98ad2c --- /dev/null +++ b/src/ru/pulsar/jenkins/library/configuration/InitExtensionMethod.groovy @@ -0,0 +1,12 @@ +package ru.pulsar.jenkins.library.configuration + +import com.fasterxml.jackson.annotation.JsonProperty + +enum InitExtensionMethod { + @JsonProperty("fromSource") + SOURCE, + + @JsonProperty("fromFile") + FILE + +} \ No newline at end of file diff --git a/src/ru/pulsar/jenkins/library/configuration/InitInfoBaseOptions.groovy b/src/ru/pulsar/jenkins/library/configuration/InitInfoBaseOptions.groovy index f0874a60..b6614983 100644 --- a/src/ru/pulsar/jenkins/library/configuration/InitInfoBaseOptions.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/InitInfoBaseOptions.groovy @@ -25,6 +25,30 @@ class InitInfoBaseOptions implements Serializable { """) String[] additionalInitializationSteps + @JsonPropertyDescription("Массив расширений для загрузки в конфигурацию.") + Extension[] extensions; + + @JsonIgnoreProperties(ignoreUnknown = true) + static class Extension implements Serializable { + @JsonPropertyDescription("Имя расширения, используемое при его загрузке в конфигурацию.") + String name = "extension"; + + @JsonPropertyDescription(""" + Способ инициализации расширения. + Поддерживается два варианта: + * fromSource - инициализация расширения из исходников; + * fromFile - скачивание скомпилированного cfe по ссылке. + """) + InitExtensionMethod initMethod = InitExtensionMethod.SOURCE; + + @JsonPropertyDescription(""" + Хранит в себе путь к расширению. + * В случае если выбран initMethod - указывается путь к исходникам расширения. + * В случае если выбран initMethod - указывается путь к cfe-файлу + """) + String path = "src/cfe/extension"; + } + @Override @NonCPS String toString() { @@ -32,6 +56,7 @@ class InitInfoBaseOptions implements Serializable { "initMethod=" + initMethod + ", 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 75932fd9..8c1d331c 100644 --- a/src/ru/pulsar/jenkins/library/configuration/JobConfiguration.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/JobConfiguration.groovy @@ -100,6 +100,10 @@ class JobConfiguration implements Serializable { (initMethod == InitInfoBaseMethod.DEFAULT_BRANCH_FROM_STORAGE && branchName != defaultBranch) } + boolean needLoadExtensions() { + return initInfoBaseOptions.extensions.length != 0 + } + String v8AgentLabel() { return v8version } diff --git a/src/ru/pulsar/jenkins/library/configuration/TimeoutOptions.groovy b/src/ru/pulsar/jenkins/library/configuration/TimeoutOptions.groovy index 4def6ec1..612dc2b6 100644 --- a/src/ru/pulsar/jenkins/library/configuration/TimeoutOptions.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/TimeoutOptions.groovy @@ -11,6 +11,11 @@ class TimeoutOptions implements Serializable { ''') Integer edtToDesignerFormatTransformation + @JsonPropertyDescription('''Таймаут шага получения бинарников, в минутах. + По умолчанию содержит значение 60. + ''') + Integer getBinaries + @JsonPropertyDescription('''Таймаут шага создания информационной базы, в минутах. По умолчанию содержит значение 60. ''') @@ -21,6 +26,11 @@ class TimeoutOptions implements Serializable { ''') Integer initInfoBase + @JsonPropertyDescription('''Таймаут шага загрузки расширений в базу, в минутах. + По умолчанию содержит значение 60. + ''') + Integer loadExtensions + @JsonPropertyDescription('''Таймаут шага архивирования информационной базы, в минутах. По умолчанию содержит значение 60. ''') diff --git a/src/ru/pulsar/jenkins/library/steps/EdtToDesignerFormatTransformation.groovy b/src/ru/pulsar/jenkins/library/steps/EdtToDesignerFormatTransformation.groovy index 2dfa3908..672168ff 100644 --- a/src/ru/pulsar/jenkins/library/steps/EdtToDesignerFormatTransformation.groovy +++ b/src/ru/pulsar/jenkins/library/steps/EdtToDesignerFormatTransformation.groovy @@ -4,6 +4,7 @@ package ru.pulsar.jenkins.library.steps import ru.pulsar.jenkins.library.IStepExecutor import ru.pulsar.jenkins.library.configuration.JobConfiguration import ru.pulsar.jenkins.library.configuration.SourceFormat +import ru.pulsar.jenkins.library.configuration.InitExtensionMethod import ru.pulsar.jenkins.library.ioc.ContextRegistry import ru.pulsar.jenkins.library.utils.EDT import ru.pulsar.jenkins.library.utils.FileUtils @@ -15,6 +16,9 @@ class EdtToDesignerFormatTransformation implements Serializable { public static final String CONFIGURATION_DIR = 'build/cfg' public static final String CONFIGURATION_ZIP = 'build/cfg.zip' public static final String CONFIGURATION_ZIP_STASH = 'cfg-zip' + public static final String EXTENSION_DIR = 'build/cfe_src' + public static final String EXTENSION_ZIP = 'build/cfe_src.zip' + public static final String EXTENSION_ZIP_STASH = 'cfe_src-zip' private final JobConfiguration config; @@ -34,18 +38,29 @@ class EdtToDesignerFormatTransformation implements Serializable { def env = steps.env(); - def srcDir = config.srcDir - def projectDir = FileUtils.getFilePath("$env.WORKSPACE/$srcDir") - def workspaceDir = FileUtils.getFilePath("$env.WORKSPACE/$WORKSPACE") - def configurationRoot = FileUtils.getFilePath("$env.WORKSPACE/$CONFIGURATION_DIR") + String srcDir = config.srcDir + String workspaceDir = FileUtils.getFilePath("$env.WORKSPACE/$WORKSPACE").getRemote() + + String projectWorkspaceDir = FileUtils.getFilePath("$workspaceDir/cf").getRemote() + String projectDir = FileUtils.getFilePath("$env.WORKSPACE/$srcDir").getRemote() + String configurationRoot = FileUtils.getFilePath("$env.WORKSPACE/$CONFIGURATION_DIR").getRemote() + + + String extensionRoot = FileUtils.getFilePath("$env.WORKSPACE/$EXTENSION_DIR").getRemote() def edtVersionForRing = EDT.ringModule(config) steps.deleteDir(workspaceDir) - steps.deleteDir(configurationRoot) - Logger.println("Конвертация исходников из формата EDT в формат Конфигуратора") + transformConfiguration(steps, projectDir, projectWorkspaceDir, configurationRoot, edtVersionForRing) + transformExtensions(steps, workspaceDir, extensionRoot, edtVersionForRing) + } - def ringCommand = "ring $edtVersionForRing workspace export --workspace-location \"$workspaceDir\" --project \"$projectDir\" --configuration-files \"$configurationRoot\"" + private void transformConfiguration(IStepExecutor steps, String projectDir, String projectWorkspaceDir, String configurationRoot, String edtVersionForRing) { + + Logger.println("Конвертация исходников конфигурации из формата EDT в формат Конфигуратора") + steps.deleteDir(configurationRoot) + + def ringCommand = "ring $edtVersionForRing workspace export --workspace-location \"$projectWorkspaceDir\" --project \"$projectDir\" --configuration-files \"$configurationRoot\"" steps.ringCommand(ringCommand) @@ -53,4 +68,27 @@ class EdtToDesignerFormatTransformation implements Serializable { steps.stash(CONFIGURATION_ZIP_STASH, CONFIGURATION_ZIP) } + private void transformExtensions(IStepExecutor steps, String workspaceDir, String extensionRoot, String edtVersionForRing) { + steps.deleteDir(extensionRoot) + + config.initInfoBaseOptions.extensions.each { + + if (it.initMethod != InitExtensionMethod.SOURCE) { + return + } + + Logger.println("Конвертация исходников расширения ${it.name} из формата EDT в формат Конфигуратора") + + def env = steps.env(); + def projectDir = FileUtils.getFilePath("$env.WORKSPACE/${it.path}") + def currentExtensionWorkspaceDir = FileUtils.getFilePath("$workspaceDir/cfe/${it.name}") + + def ringCommand = "ring $edtVersionForRing workspace export --workspace-location \"$currentExtensionWorkspaceDir\" --project \"$projectDir\" --configuration-files \"$extensionRoot/${it.name}\"" + + steps.ringCommand(ringCommand) + } + steps.zip(EXTENSION_DIR, EXTENSION_ZIP) + steps.stash(EXTENSION_ZIP_STASH, EXTENSION_ZIP) + } + } diff --git a/src/ru/pulsar/jenkins/library/steps/GetExtensions.groovy b/src/ru/pulsar/jenkins/library/steps/GetExtensions.groovy new file mode 100644 index 00000000..cf52e90a --- /dev/null +++ b/src/ru/pulsar/jenkins/library/steps/GetExtensions.groovy @@ -0,0 +1,124 @@ +package ru.pulsar.jenkins.library.steps + +import ru.pulsar.jenkins.library.IStepExecutor +import ru.pulsar.jenkins.library.configuration.JobConfiguration +import ru.pulsar.jenkins.library.configuration.SourceFormat +import ru.pulsar.jenkins.library.configuration.InitExtensionMethod +import ru.pulsar.jenkins.library.configuration.InitInfoBaseOptions.Extension +import ru.pulsar.jenkins.library.ioc.ContextRegistry +import ru.pulsar.jenkins.library.utils.Logger +import ru.pulsar.jenkins.library.utils.VRunner +import hudson.FilePath +import ru.pulsar.jenkins.library.utils.FileUtils + +class GetExtensions implements Serializable { + + public static final String EXTENSIONS_OUT_DIR = 'build/out/cfe' + + private final JobConfiguration config; + + GetExtensions(JobConfiguration config) { + this.config = config + } + + def run() { + IStepExecutor steps = ContextRegistry.getContext().getStepExecutor() + + Logger.printLocation() + + def env = steps.env() + + steps.installLocalDependencies(); + + String vrunnerPath = initVRunnerPath(); + + Logger.println("Сборка расширений") + + String sourceDirName = "" + if (config.sourceFormat == SourceFormat.EDT) { + sourceDirName = "$env.WORKSPACE/$EdtToDesignerFormatTransformation.EXTENSION_DIR" + } else { + sourceDirName = "$env.WORKSPACE" + } + extractConvertedExtensions(sourceDirName, steps) + + String pathToExtensionDir = "$env.WORKSPACE/${EXTENSIONS_OUT_DIR}/" + FilePath localPathToExtensionDir = FileUtils.getFilePath(pathToExtensionDir) + localPathToExtensionDir.mkdirs() + + config.initInfoBaseOptions.extensions.each { + if (it.initMethod == InitExtensionMethod.SOURCE) { + Logger.println("Сборка расширения ${it.name} из исходников") + String srcDir = getSrcDir(it, sourceDirName) + buildExtension(it, srcDir, vrunnerPath, steps) + } else if (it.initMethod == InitExtensionMethod.FILE){ + Logger.println("Загрузка расширения ${it.name} из ${it.path}") + loadExtension(it, env) + } else { + Logger.println("Неизвестный метод инициализации расширения ${it.name}") + } + } + } + + private void buildExtension(Extension extension, String srcDir, String vrunnerPath, IStepExecutor steps) { + + def compileExtCommand = "$vrunnerPath compileexttocfe --src ${srcDir} --out $EXTENSIONS_OUT_DIR/${extension.name}.cfe" + List logosConfig = ["LOGOS_CONFIG=$config.logosConfig"] + steps.withEnv(logosConfig) { + VRunner.exec(compileExtCommand) + } + } + + private void loadExtension(Extension extension, def env) { + String pathToExtension = "$env.WORKSPACE/${EXTENSIONS_OUT_DIR}/${extension.name}.cfe" + FilePath localPathToExtension = FileUtils.getFilePath(pathToExtension) + + if (isValidUrl(extension.path)) { + // If the path is a URL, download the file + localPathToExtension.copyFrom(new URL(extension.path)) + } else { + // If the path is a local file, copy the file + String localPath = getAbsolutePath(extension.path, env) + FilePath localFilePath = FileUtils.getFilePath(localPath) + localPathToExtension.copyFrom(localFilePath) + } + } + + + private String initVRunnerPath() { + return VRunner.getVRunnerPath() + } + + private String getSrcDir(Extension extension, String sourceDirName) { + if (config.sourceFormat == SourceFormat.EDT) { + return "${sourceDirName}/${extension.name}" + } else { + return "${sourceDirName}/${extension.path}" + } + } + + private void extractConvertedExtensions(String sourceDirName, IStepExecutor steps) { + if (config.sourceFormat == SourceFormat.EDT) { + // usntash and unzip the edt to designer format transformation + steps.unstash(EdtToDesignerFormatTransformation.EXTENSION_ZIP_STASH) + steps.unzip(sourceDirName, EdtToDesignerFormatTransformation.EXTENSION_ZIP) + } + } + + private static boolean isValidUrl(String url) { + try { + new URL(url) + return true + } catch (MalformedURLException e) { + return false + } + } + + private static String getAbsolutePath(String path, def env) { + if (path.startsWith("/") || path.startsWith("\\") || path.matches("^[A-Za-z]:.*")) { + return path + } else { + return "${env.WORKSPACE}/${path}" + } + } +} diff --git a/src/ru/pulsar/jenkins/library/steps/LoadExtensions.groovy b/src/ru/pulsar/jenkins/library/steps/LoadExtensions.groovy new file mode 100644 index 00000000..53be96c6 --- /dev/null +++ b/src/ru/pulsar/jenkins/library/steps/LoadExtensions.groovy @@ -0,0 +1,55 @@ +package ru.pulsar.jenkins.library.steps + +import ru.pulsar.jenkins.library.IStepExecutor +import ru.pulsar.jenkins.library.configuration.JobConfiguration +import ru.pulsar.jenkins.library.configuration.InitInfoBaseOptions.Extension +import ru.pulsar.jenkins.library.ioc.ContextRegistry +import ru.pulsar.jenkins.library.utils.Logger +import ru.pulsar.jenkins.library.utils.VRunner +import hudson.FilePath +import ru.pulsar.jenkins.library.utils.FileUtils + +class LoadExtensions implements Serializable { + + private final JobConfiguration config; + + LoadExtensions(JobConfiguration config) { + this.config = config + } + + def run() { + IStepExecutor steps = ContextRegistry.getContext().getStepExecutor() + + Logger.printLocation() + + def env = steps.env(); + String cfeDir = "$env.WORKSPACE/$GetExtensions.EXTENSIONS_OUT_DIR" + + String vrunnerPath = VRunner.getVRunnerPath(); + + config.initInfoBaseOptions.extensions.each { + Logger.println("Установим расширение ${it.name}") + loadExtension(it, vrunnerPath, steps, cfeDir) + } + } + + private void loadExtension (Extension extension, String vrunnerPath, IStepExecutor steps, String cfeDir) { + + String pathToExt = "$cfeDir/${extension.name}.cfe" + FilePath localPathToExt = FileUtils.getFilePath(pathToExt) + + // Команда загрузки расширения + String loadCommand = vrunnerPath + ' run --command "Путь=' + localPathToExt + ';ЗавершитьРаботуСистемы;" --execute ' + String executeParameter = '$runnerRoot/epf/ЗагрузитьРасширениеВРежимеПредприятия.epf' + if (steps.isUnix()) { + executeParameter = '\\' + executeParameter + } + loadCommand += executeParameter + loadCommand += ' --ibconnection "/F./build/ib"' + + List logosConfig = ["LOGOS_CONFIG=$config.logosConfig"] + steps.withEnv(logosConfig) { + VRunner.exec(loadCommand) + } + } +} diff --git a/test/integration/resources/jobConfiguration.json b/test/integration/resources/jobConfiguration.json index e027b9f9..38b207a9 100644 --- a/test/integration/resources/jobConfiguration.json +++ b/test/integration/resources/jobConfiguration.json @@ -1,6 +1,11 @@ { "v8version": "8.3.12.1500", "initInfobase": { - "initMethod": "fromSource" + "initMethod": "fromSource", + "extensions": [{ + "name": "Тест", + "initMethod": "fromSource", + "path": "/src/cfe/тест" + }] } } \ No newline at end of file diff --git a/vars/getExtensions.groovy b/vars/getExtensions.groovy new file mode 100644 index 00000000..12a79c82 --- /dev/null +++ b/vars/getExtensions.groovy @@ -0,0 +1,10 @@ +import ru.pulsar.jenkins.library.configuration.JobConfiguration +import ru.pulsar.jenkins.library.ioc.ContextRegistry +import ru.pulsar.jenkins.library.steps.GetExtensions + +def call(JobConfiguration config) { + ContextRegistry.registerDefaultContext(this) + + def getExtensions = new GetExtensions(config) + getExtensions.run() +} \ No newline at end of file diff --git a/vars/loadExtensions.groovy b/vars/loadExtensions.groovy new file mode 100644 index 00000000..78e8b766 --- /dev/null +++ b/vars/loadExtensions.groovy @@ -0,0 +1,10 @@ +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) { + ContextRegistry.registerDefaultContext(this) + + def loadExtensions = new LoadExtensions(config) + loadExtensions.run() +} \ No newline at end of file diff --git a/vars/pipeline1C.groovy b/vars/pipeline1C.groovy index 89faa801..f5d8ee8a 100644 --- a/vars/pipeline1C.groovy +++ b/vars/pipeline1C.groovy @@ -76,10 +76,22 @@ void call() { } stages { + stage('Сборка расширений из исходников') { + when { + expression { config.needLoadExtensions() } + } + steps { + timeout(time: config.timeoutOptions.getBinaries, unit: TimeUnit.MINUTES) { + createDir('build/out/cfe') + // Соберем или загрузим cfe из исходников и положим их в папку build/out/cfe + getExtensions config + } + } + } stage('Создание ИБ') { steps { timeout(time: config.timeoutOptions.createInfoBase, unit: TimeUnit.MINUTES) { - createDir('build/out') + createDir('build/out/') script { if (config.infoBaseFromFiles()) { @@ -107,6 +119,18 @@ void call() { } } + stage('Загрузка расширений в конфигурацию'){ + when { + beforeAgent true + expression { config.needLoadExtensions() } + } + steps { + timeout(time: config.timeoutOptions.loadExtensions, unit: TimeUnit.MINUTES) { + loadExtensions config + } + } + } + stage('Архивация ИБ') { steps { timeout(time: config.timeoutOptions.zipInfoBase, unit: TimeUnit.MINUTES) {