diff --git a/.gitattributes b/.gitattributes index 6d0bb27e..df0797a4 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1,4 @@ -*.groovy eol=lf +*.groovy eol=lf +*.json eol=lf +*.md eol=lf +*.os eol=lf diff --git a/README.md b/README.md index 3a20bba0..f9a7e4d3 100644 --- a/README.md +++ b/README.md @@ -1,246 +1,314 @@ -# Jenkins shared library for 1C:Enterprise 8 - -## Цель - -Создание библиотеки (или плагина) для Jenkins, позволяющей: - -* максимально упростить написание Jenkinsfile для процесса CI в условиях платформы 1С:Предприятие 8 -* иметь схожий и контролируемый пайплайн для всех проектов -* дать пользователю в руки простой декларативный конфигурационный файл, вместо требования описывать всю сложную логику по работе с 1С - -## Общие положения - -* в активной разработке и поиске "своего пути" по разработке библиотеки; -* формат конфигурационного файла **не** стабилизирован; -* обратная совместимость **пока** не гарантируется, внимательно читайте changelog; -* количество stage будет со временем увеличиваться; -* использовать на свой страх и риск; -* любая помощь приветствуется. - -## Ограничения - -1. Хранение исходников в корне репозитория или в каталоге первого уровня (например, в `src`) не рекомендуется. -1. Для шага подготовки требуется любой агент с меткой `agent`. -1. Для запуска шага анализа SonarQube требуется агент с меткой `sonar`. -1. Для запуска шагов, работающих с EDT (валидация, трансформация формата исходников) требуется агент с меткой `edt` (если используется несколько версий EDT необходимо к метке добавить версию, например `edt@2021.3.4:x86_64`) и агент с меткой `oscript`, на котором глобально установлена библиотека [stebi](https://github.com/Stepa86/stebi) версии 1.11.1 и выше или [edt-ripper](https://github.com/bia-technologies/edt_ripper). -1. При использовании EDT версии 2024.1.0 и выше вместо ring используется 1cedtcli, который должен быть прописан в PATH на агенте. -1. Для запуска шагов, работающих с 1С (подготовка, синтаксический контроль и т.д.) требуется агент с меткой, совпадающей со значением в поле `v8version` файла конфигурации. -1. В качестве ИБ используется файловая база, создаваемая в каталоге `./build/ib`. При необходимости вы можете создать пользователей на фазе инициализации ИБ. - -## Возможности - -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. -1. Трансформация кода из формата EDT в формат конфигуратора. -1. Запуск BDD сценариев с сохранением результатов в формате Allure. -1. Запуск юнит-тестов с помощью фреймворка YAXUnit с сохранением результатов в формате jUnit и Allure. -1. Запуск синтаксического контроля средствами конфигуратора и сохранение результатов в виде отчета jUnit. -1. Валидация проекта средствами EDT и трансформация отчета EDT в формат BSL LS с помощью `edt-ripper` или Generic Issue с помощью `stebi`. - -1. Запуск статического анализа для SonarQube. -1. Публикация результатов junit и Allure в интерфейс Jenkins. -1. Рассылка результатов сборки на почту и в Telegram. -1. Конфигурирование логгера запускаемых oscript-приложений. - -## Подключение - -Инструкция по подключению библиотеки: https://jenkins.io/doc/book/pipeline/shared-libraries/#using-libraries - -## Примеры Jenkinsfile - -Если в настройках подключения shared-library включен флаг "Load implicitly": - -```groovy -pipeline1C() -``` - -В обратном случае: - -```groovy -@Library('jenkins-lib') _ - -pipeline1C() -``` - -> Да, вот и весь пайплайн. Конфигурирование через json. - -## Внешний вид пайплайна в интерфейсе Blue Ocean - -![image](https://github.com/ovcharenko-di/jenkins-lib/assets/24920942/19eabbc3-e33e-44f5-8f23-142f44817628) - - -## Конфигурирование - -По умолчанию применяется [файл конфигурации из ресурсов библиотеки](resources/globalConfiguration.json) - -Поверх него накладывается конфигурация из файла `jobConfiguration.json` в корне проекта, если он присутствует. - -Пример переопределения: - -* указывается точная версия платформы (и соответственно метка агента, см. ограничения) -* указывается точная версия модуля EDT (и соответственно метка агента, см. ограничения) -* идентификаторы credentials для пути к хранилищу и к паре логин/пароль для авторизации в хранилище (необходимы, если применяются шаги, работающие с информационной базой) -* включаются шаги запуска статического анализа SonarQube, валидации средствами EDT и синтаксического контроля - -```json -{ - "$schema": "https://raw.githubusercontent.com/firstBitMarksistskaya/jenkins-lib/master/resources/schema.json", - "v8version": "8.3.14.1976", - "edtVersion": "2021.3.4:x86_64", - "secrets": { - "storagePath": "f7b21c02-711a-4883-81c5-d429454e3f8b", - "storage" : "c1fc5f33-67d4-493f-a2a4-97d3040e4b8c" - }, - "stages": { - "sonarqube": true, - "edtValidate": true, - "syntaxCheck": true - } -} -``` - -## Параметры по умолчанию - -В библиотеке применяется принцип "соглашения по конфигурации" (convention over configuration): конфигурационный файл -содержит ряд настроек "по умолчанию". При соблюдении определенных правил структуры репозитория можно сократить -количество переопределений конфигурационного файла до минимума. Ниже представлены имеющиеся соглашения и способы их переопределения. - -* Общее: - * В качестве маски версии платформы используется строка "8.3" (`v8version`). - * По умолчанию версия модуля EDT не заполнена, т.к. в случае единственной версии для утилиты ring дополнительного указания не требуется (`edtVersion`). - * Исходники конфигурации ожидаются в каталоге `src/cf` (`srcDir`). - * Формат исходников - выгрузка из Конфигуратора (`sourceFormat`). - * Ветка по умолчанию (для комбинированного режима загрузки конфигурации) - "main" (`defaultBranch`). - * Имена большинства "секретов" (jenkins credentials, `secrets`) по умолчанию высчитываются из пути к git-репозиторию (без учета домена, с заменой `/` на `_`) с прибавлением ключа секрета. Например, для репозитория https://github.com/firstBitSemenovskaya/jenkins-lib секрет с адресом хранилища будет выглядеть как `firstBitSemenovskaya_jenkins-lib_STORAGE_PATH`. Ключи секретов: - * `STORAGE_PATH` - путь к хранилищу конфигурации (для `secrets` -> `storagePath`); - * `STORAGE_USER` - параметры авторизации в хранилище вида "username with password" (для `secrets` -> `storage`). - * `TELEGRAM_CHAT_ID` - идентификатор чата Telegram для рассылки уведомлений и результате сборки вида "secret text" (для `secrets` -> `telegramChatId`). - * Секрет `TELEGRAM_BOT_TOKEN` задается глобально на весь сервер Jenkins, либо может быть переопределен (`secrets` -> `telegramBotToken`) - * Все "шаги" по умолчанию выключены (`stages`). - * Если в корне репозитория существует файл `packagedef`, то в шагах, работающих с информационной базой, будет выполнена попытка установки локальных зависимостей средствами `opm`. - * Если после установки локальных зависимостей в каталоге `oscript_modules/bin` существует файл `vrunner`, то для выполнения команд работы с информационной базой будет использоваться он, а не глобально установленный `vrunner` из `PATH`. - * Результаты в формате `allure` ожидаются в каталоге `build/out/allure` или его подкаталогах. - * Каждый шаг имеет свой таймаут в минутах (от 10 до 240 в зависимости от "тяжёлости" шага сборки), но может быть переопределен в секции настроек `timeout`. -* Инициализация: - * Информационная база инициализируется только в том случае, если в сборочной линии включены шаги, работающие с базой (например, `bdd` или `syntaxCheck`). - * Информационная база инициализируется конфигурацией из хранилища конфигурации (`initInfobase` -> `initMethod`). - * Если выбран метод инициализации ИБ из хранилища конфигурации и в каталоге исходников есть файл `VERSION` (артефакт от работы утилиты `gitsync`), то из хранилища будет загружена версия конфигурации с номером из файла `VERSION`. -* Первичный запуск информационной базы: - * Если информационная база нужна для запуска в режиме "Предприятие" (например, для шагов `bdd` или `smoke`), то будет запущен шаг "Миграция ИБ". - * После загрузки конфигурации в ИБ будет выполняться запуск ИБ с целью запуска обработчиков обновления из БСП (`initInfobase` -> `runMigration`). - * Если в настройках шага инициализации не заполнен массив дополнительных шагов миграции (`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` из локальных зависимостей. - * Если в репозитории существует файл `tools/xUnitParams.json`, то этот путь к файлу будет передан в параметр запуска `vrunner xunit --xddConfig ./tools/xUnitParams.json` (`smoke -> xUnitParams`). - * Если используемый конфигурационный файл (`vrunner.json`) не содержит настройку `testsPath`, то запускается полный комплект дымовых тестов, расположенных в `$addRoot/tests/smoke`. - * По умолчанию включено формирование отчета в формате `jUnit` (`smoke` -> `publishToJUnitReport`) и выключено формирование отчета в формате Allure (`smoke` -> `publishToAllureReport`). -* Синтаксический контроль: - * Если в репозитории существует файл `tools/vrunner.json`, то синтаксический контроль конфигурации с помощью конфигуратора будет выполняться с передачей файла в параметры запуска `vrunner syntax-check --settings tools/vrunner.json` (`syntaxCheck` -> `vrunnerSettings`). - * Применяется группировка ошибок по метаданным (`syntaxCheck` -> `groupErrorsByMetadata`). - * Выгрузка результатов в формат `jUnit` осуществляется в файл `./build/out/jUnit/syntax.xml` (`syntaxCheck` -> `pathToJUnitReport`). - * Если в репозитории существует файл `./tools/syntax-check-exception-file.txt`, то команде запуска синтаксического контроля конфигурации данный файл будет передаваться как файл с исключениями сообщений об ошибках (параметр `--exception-file`) (`syntaxCheck` -> `exceptionFile`). - * Конфигурационный файл по умолчанию уже содержит ряд "режимов проверки" для синтаксического контроля конфигурации (`syntaxCheck` -> `checkModes`). -* Трансформация результатов валидации EDT: - * Используется `stebi` (параметр `resultsTransform` -> `transformer`) - * Формат файла - `generic issues` для SonarQube 10.3+ (параметр `resultsTransform` -> `genericIssueFormat`) - * `stebi` исключает из результатов анализа замечания, сработавшие на модулях с включенным запретом редактирования (желтый куб с замком) (параметры `resultsTransform` -> `removeSupport` и `resultsTransform` -> `supportLevel`). -* Анализ SonarQube: - * Предполагается наличие единственной настройки `SonarQube installation` (`sonarqube` -> `sonarQubeInstallation`). - * Используется `sonar-scanner` из переменной окружения `PATH` (`sonarqube` -> `useSonarScannerFromPath`). - * Если использование `sonar-scanner` из переменной окружения `PATH` выключено, предполагается наличие настроенного глобального инструмента `SonarQube Scanner` с идентификатором инструмента `sonar-scanner` (`sonarqube` -> `sonarScannerToolName`). - * Применяется расчет аргументов командной строки для работы [`branch plugin`](https://github.com/mc1arke/sonarqube-community-branch-plugin) или коммерческих версий SonarQube (`sonarqube` -> `branchAnalysisConfiguration`). - * Если разработка ведется с использованием подсистемы [БСП "Обновление версии ИБ"](https://its.1c.ru/db/bsp315doc#content:4:1:issogl1_обновление_версии_иб), то в значение параметра `sonar.projectVersion=$configurationVersion` утилиты `sonar-scanner` можно передавать версию из созданного общего модуля. Для этого необходимо заполнить параметр (`sonarqube` -> `infoBaseUpdateModuleName`). Если параметр не заполнен, версия передается из корня конфигурации. - * По умолчанию шаг анализа не дожидается окончания фонового задания на сервере SonarQube и не анализирует результат прохождения Порога качества (`sonarqube` -> `waitForQualityGate`). - * Если выполнялась валидация EDT, результаты валидации передаются утилите `sonar-scanner` как значение параметра `sonar.externalIssuesReportPaths` при использовании `stebi` или как значение параметра `sonar.bsl.languageserver.reportPaths` при использовании `edt-ripper`. -* Рассылка уведомлений: - * Электронная почта: - * Для отправки используется плагин [`email-ext`](https://plugins.jenkins.io/email-ext). Шаблоны сообщений конфигурируются в настройках плагина. - * Уведомления о результатах сборки по умолчанию рассылаются только при полном падении сборочной линии (`notifications` -> `email` -> `onAlways`, `onFailure`, `onUnstable`, `onSuccess`). - * Лог сборки прикладывается к письму при полном падении сборочной линии и при отправке в режиме "всегда отправлять" (`notifications` -> `email` -> `*options` -> `attachLog`). - * В качестве получателей писем (`notifications` -> `email` -> `*options` -> `recipientProviders`) в различных режимах отправки используются: - * всегда - разработчики и запустивший сборку; - * при падении - разработчики, запустивший сборку и подозреваемый в причине падения сборки; - * при успехе - разработчики и запустивший сборку; - * при нестабильной сборке (упавшие тесты) - разработчики и запустивший сборку. - * Прямые получатели уведомлений не заполнены (`notifications` -> `email` -> `*options` -> `directRecipients`). - * Telegram: - * Уведомления о результатах сборки по умолчанию рассылаются всегда (`notifications` -> `telegram` -> `onAlways`, `onFailure`, `onUnstable`, `onSuccess`). - -## Настройка загрузки расширений - -Если у вас есть расширения, которые необходимо загрузить в базу для проведения тестов и проверок, это можно сделать на этапе подготовки базы. - -* При загрузке из исходников расширения должны быть в том же формате (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) -1. Укажите этапы сборки, на которых должно быть загружено расширение (`initInfobase` -> `extensions` -> `stages`). Если оставить это поле пустым, то расширение будет загружено на этапе `initInfobase` и будет активно на всех последующих этапах. В противном случае расширение будет использоваться только на перечисленных этапах. - -Пример конфигурации для загрузки расширений: - -```json -"initInfobase": { - "extensions": [ - { - "name": "ИмяРасширения1", - "initMethod": "fromSource", - "path": "путь/до/исходников/расширения", - "stages": ["bdd", "yaxunit"] - }, - { - "name": "ИмяРасширения2", - "initMethod": "fromFile", - "path": "https://example.com/path/to/extension.cfe" - } - ] -} -``` -## Загрузка эталонной базы - -Реализована возможность загрузки эталонной базы на этапе инициализации информационной базы. Для этого необходимо указать в конфигурационном файле параметр `initInfobase` -> `templateDBPath`: - -```json -"initInfobase": { - "templateDBPath": "путь/до/файла/базы.dt" -} -``` - -* Поддерживается загрузка файлов формата `.dt` и `.1CD`. -* Путь к файлу базы может быть как локальным, так и удаленным (URL). -* После загрузки базы для инициализации будет использоваться файл настроек `vanessa-runner` (включая логин и пароль от ИБ), указанный в параметре `initInfobase` -> `vrunnerSettings`. По умолчанию используется файл `tools/vrunner.json`. - -```json -"initInfobase": { - "templateDBPath": "путь/до/файла/базы.dt", - "vrunnerSettings": "tools/vrunner.json" -} -``` - -## Настройка шага YAXUnit - - * Добавить расширение `YAXUnit` и дополнительные расширения с тестами можно в `jobConfiguration.json` -> `initInfobase` -> `extensions`. Они будут загружены при инициализации ИБ. - * Если ваши тесты размещены в отдельных расширениях, скопируйте файл `./resources/yaxunit.json` из текущей библиотеки в свой репозиторий (`./tools/yaxunit.json`) и перечислите в нем имена ваших расширений. - * Если используется собственный файл `tools/yaxunit.json`, то значение параметра `reportPath` в нем должно быть равно `./build/out/yaxunit/junit.xml` - -## Настройка трансформации результата валидации EDT - - * При использовании SonarQube версии <10.3 и `stebi` формат отчета должен быть `Generic_Issue` (параметр `resultsTransform` -> `genericIssueFormat`) - * Трансформацию результатов может выполнять `edt-ripper` (параметр `resultsTransform` -> `transformer`). В этом случае замечания будут загружены в SonarQube в формате BSL LS, что позволяет полноценно управлять ими в SonarQube. +# Jenkins shared library for 1C:Enterprise 8 + +## Цель + +Создание библиотеки (или плагина) для Jenkins, позволяющей: + +* максимально упростить написание Jenkinsfile для процесса CI в условиях платформы 1С:Предприятие 8 +* иметь схожий и контролируемый пайплайн для всех проектов +* дать пользователю в руки простой декларативный конфигурационный файл, вместо требования описывать всю сложную логику по работе с 1С + +## Общие положения + +* в активной разработке и поиске "своего пути" по разработке библиотеки; +* формат конфигурационного файла **не** стабилизирован; +* обратная совместимость **пока** не гарантируется, внимательно читайте changelog; +* количество stage будет со временем увеличиваться; +* использовать на свой страх и риск; +* любая помощь приветствуется. + +## Ограничения + +1. Хранение исходников в корне репозитория или в каталоге первого уровня (например, в `src`) не рекомендуется. +1. Для шага подготовки требуется любой агент с меткой `agent`. +1. Для запуска шага анализа SonarQube требуется агент с меткой `sonar`. +1. Для запуска шагов, работающих с EDT (валидация, трансформация формата исходников) требуется агент с меткой `edt` (если используется несколько версий EDT необходимо к метке добавить версию, например `edt@2021.3.4:x86_64`) и агент с меткой `oscript`, на котором глобально установлена библиотека [stebi](https://github.com/Stepa86/stebi) версии 1.11.1 и выше или [edt-ripper](https://github.com/bia-technologies/edt_ripper). +1. При использовании EDT версии 2024.1.0 и выше вместо ring используется 1cedtcli, который должен быть прописан в PATH на агенте. +1. Для запуска шагов, работающих с 1С (подготовка, синтаксический контроль и т.д.) требуется агент с меткой, совпадающей со значением в поле `v8version` файла конфигурации. +1. В качестве ИБ используется файловая база, создаваемая в каталоге `./build/ib`. При необходимости вы можете создать пользователей на фазе инициализации ИБ. +1. На данный момент ошибка в [vanessa-add](https://github.com/vanessa-opensource/add/issues/1152) не позволяет собирать замеры производительности в дымовых тестах по открытию всех форм на клиенте тестирования. +1. Для параллельного выполнения шагов `bdd` и `smoke` с включенными замерами покрытия на одной ноде необходимо, чтобы в `jobConfiguration.json` были указаны **разные** порты сервера отладки для каждого шага. Параллельные билды с замерами покрытия на одной ноде не поддерживаются. +1. Для сборов замеров покрытия в ОС Windows на мастер-ноде Jenkins, который запущен как служба под учетной записью LOCAL SYSTEM, необходимо использовать версию Coverage41C >= 2.7.3. Другие варианты обхода проблемы: + 1. запустить службу Jenkins под обычной учетной записью + 1. запретить выполнение сборок на мастер-ноде и настроить их выполнение на агенте, который запущен интерактивно под обычной учетной записью (рекомендуется). + +## Возможности + +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. +1. Трансформация кода из формата EDT в формат конфигуратора. +1. Запуск BDD сценариев с сохранением результатов в формате Allure. +1. Запуск юнит-тестов с помощью фреймворка YAXUnit с сохранением результатов в формате jUnit и Allure. +1. Запуск синтаксического контроля средствами конфигуратора и сохранение результатов в виде отчета jUnit. +1. Валидация проекта средствами EDT и трансформация отчета EDT в формат BSL LS с помощью `edt-ripper` или Generic Issue с помощью `stebi`. + +1. Запуск статического анализа для SonarQube. +1. Публикация результатов junit и Allure в интерфейс Jenkins. +1. Рассылка результатов сборки на почту и в Telegram. +1. Конфигурирование логгера запускаемых oscript-приложений. +1. Замер покрытия при выполнении тестов. + +## Подключение + +Инструкция по подключению библиотеки: https://jenkins.io/doc/book/pipeline/shared-libraries/#using-libraries + +## Примеры Jenkinsfile + +Если в настройках подключения shared-library включен флаг "Load implicitly": + +```groovy +pipeline1C() +``` + +В обратном случае: + +```groovy +@Library('jenkins-lib') _ + +pipeline1C() +``` + +> Да, вот и весь пайплайн. Конфигурирование через json. + +## Внешний вид пайплайна в интерфейсе Blue Ocean + +![image](https://github.com/ovcharenko-di/jenkins-lib/assets/24920942/19eabbc3-e33e-44f5-8f23-142f44817628) + + +## Конфигурирование + +По умолчанию применяется [файл конфигурации из ресурсов библиотеки](resources/globalConfiguration.json) + +Поверх него накладывается конфигурация из файла `jobConfiguration.json` в корне проекта, если он присутствует. + +Пример переопределения: + +* указывается точная версия платформы (и соответственно метка агента, см. ограничения) +* указывается точная версия модуля EDT (и соответственно метка агента, см. ограничения) +* идентификаторы credentials для пути к хранилищу и к паре логин/пароль для авторизации в хранилище (необходимы, если применяются шаги, работающие с информационной базой) +* включаются шаги запуска статического анализа SonarQube, валидации средствами EDT и синтаксического контроля + +```json +{ + "$schema": "https://raw.githubusercontent.com/firstBitMarksistskaya/jenkins-lib/master/resources/schema.json", + "v8version": "8.3.14.1976", + "edtVersion": "2021.3.4:x86_64", + "secrets": { + "storagePath": "f7b21c02-711a-4883-81c5-d429454e3f8b", + "storage" : "c1fc5f33-67d4-493f-a2a4-97d3040e4b8c" + }, + "stages": { + "sonarqube": true, + "edtValidate": true, + "syntaxCheck": true + } +} +``` + +## Параметры по умолчанию + +В библиотеке применяется принцип "соглашения по конфигурации" (convention over configuration): конфигурационный файл +содержит ряд настроек "по умолчанию". При соблюдении определенных правил структуры репозитория можно сократить +количество переопределений конфигурационного файла до минимума. Ниже представлены имеющиеся соглашения и способы их переопределения. + +* Общее: + * В качестве маски версии платформы используется строка "8.3" (`v8version`). + * По умолчанию версия модуля EDT не заполнена, т.к. в случае единственной версии для утилиты ring дополнительного указания не требуется (`edtVersion`). + * Исходники конфигурации ожидаются в каталоге `src/cf` (`srcDir`). + * Формат исходников - выгрузка из Конфигуратора (`sourceFormat`). + * Ветка по умолчанию (для комбинированного режима загрузки конфигурации) - "main" (`defaultBranch`). + * Имена большинства "секретов" (jenkins credentials, `secrets`) по умолчанию высчитываются из пути к git-репозиторию (без учета домена, с заменой `/` на `_`) с прибавлением ключа секрета. Например, для репозитория `https://github.com/firstBitSemenovskaya/jenkins-lib` секрет с адресом хранилища будет выглядеть как `firstBitSemenovskaya_jenkins-lib_STORAGE_PATH`. Ключи секретов: + * `STORAGE_PATH` - путь к хранилищу конфигурации (для `secrets` -> `storagePath`); + * `STORAGE_USER` - параметры авторизации в хранилище вида "username with password" (для `secrets` -> `storage`). + * `TELEGRAM_CHAT_ID` - идентификатор чата Telegram для рассылки уведомлений и результате сборки вида "secret text" (для `secrets` -> `telegramChatId`). + * Секрет `TELEGRAM_BOT_TOKEN` задается глобально на весь сервер Jenkins, либо может быть переопределен (`secrets` -> `telegramBotToken`) + * Все "шаги" по умолчанию выключены (`stages`). + * Если в корне репозитория существует файл `packagedef`, то в шагах, работающих с информационной базой, будет выполнена попытка установки локальных зависимостей средствами `opm`. + * Если после установки локальных зависимостей в каталоге `oscript_modules/bin` существует файл `vrunner`, то для выполнения команд работы с информационной базой будет использоваться он, а не глобально установленный `vrunner` из `PATH`. + * Результаты в формате `allure` ожидаются в каталоге `build/out/allure` или его подкаталогах. + * Каждый шаг имеет свой таймаут в минутах (от 10 до 240 в зависимости от "тяжёлости" шага сборки), но может быть переопределен в секции настроек `timeout`. +* Инициализация: + * Информационная база инициализируется только в том случае, если в сборочной линии включены шаги, работающие с базой (например, `bdd` или `syntaxCheck`). + * Информационная база инициализируется конфигурацией из хранилища конфигурации (`initInfobase` -> `initMethod`). + * Если выбран метод инициализации ИБ из хранилища конфигурации и в каталоге исходников есть файл `VERSION` (артефакт от работы утилиты `gitsync`), то из хранилища будет загружена версия конфигурации с номером из файла `VERSION`. +* Первичный запуск информационной базы: + * Если информационная база нужна для запуска в режиме "Предприятие" (например, для шагов `bdd` или `smoke`), то будет запущен шаг "Миграция ИБ". + * После загрузки конфигурации в ИБ будет выполняться запуск ИБ с целью запуска обработчиков обновления из БСП (`initInfobase` -> `runMigration`). + * Если в настройках шага инициализации не заполнен массив дополнительных шагов миграции (`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` из локальных зависимостей. + * Если в репозитории существует файл `tools/xUnitParams.json`, то этот путь к файлу будет передан в параметр запуска `vrunner xunit --xddConfig ./tools/xUnitParams.json` (`smoke -> xUnitParams`). + * Если используемый конфигурационный файл (`vrunner.json`) не содержит настройку `testsPath`, то запускается полный комплект дымовых тестов, расположенных в `$addRoot/tests/smoke`. + * По умолчанию включено формирование отчета в формате `jUnit` (`smoke` -> `publishToJUnitReport`) и выключено формирование отчета в формате Allure (`smoke` -> `publishToAllureReport`). +* Синтаксический контроль: + * Если в репозитории существует файл `tools/vrunner.json`, то синтаксический контроль конфигурации с помощью конфигуратора будет выполняться с передачей файла в параметры запуска `vrunner syntax-check --settings tools/vrunner.json` (`syntaxCheck` -> `vrunnerSettings`). + * Применяется группировка ошибок по метаданным (`syntaxCheck` -> `groupErrorsByMetadata`). + * Выгрузка результатов в формат `jUnit` осуществляется в файл `./build/out/jUnit/syntax.xml` (`syntaxCheck` -> `pathToJUnitReport`). + * Если в репозитории существует файл `./tools/syntax-check-exception-file.txt`, то команде запуска синтаксического контроля конфигурации данный файл будет передаваться как файл с исключениями сообщений об ошибках (параметр `--exception-file`) (`syntaxCheck` -> `exceptionFile`). + * Конфигурационный файл по умолчанию уже содержит ряд "режимов проверки" для синтаксического контроля конфигурации (`syntaxCheck` -> `checkModes`). +* Трансформация результатов валидации EDT: + * Используется `stebi` (параметр `resultsTransform` -> `transformer`) + * Формат файла - `generic issues` для SonarQube 10.3+ (параметр `resultsTransform` -> `genericIssueFormat`) + * `stebi` исключает из результатов анализа замечания, сработавшие на модулях с включенным запретом редактирования (желтый куб с замком) (параметры `resultsTransform` -> `removeSupport` и `resultsTransform` -> `supportLevel`). +* Анализ SonarQube: + * Предполагается наличие единственной настройки `SonarQube installation` (`sonarqube` -> `sonarQubeInstallation`). + * Используется `sonar-scanner` из переменной окружения `PATH` (`sonarqube` -> `useSonarScannerFromPath`). + * Если использование `sonar-scanner` из переменной окружения `PATH` выключено, предполагается наличие настроенного глобального инструмента `SonarQube Scanner` с идентификатором инструмента `sonar-scanner` (`sonarqube` -> `sonarScannerToolName`). + * Применяется расчет аргументов командной строки для работы [`branch plugin`](https://github.com/mc1arke/sonarqube-community-branch-plugin) или коммерческих версий SonarQube (`sonarqube` -> `branchAnalysisConfiguration`). + * Если разработка ведется с использованием подсистемы [БСП "Обновление версии ИБ"](https://its.1c.ru/db/bsp315doc#content:4:1:issogl1_обновление_версии_иб), то в значение параметра `sonar.projectVersion=$configurationVersion` утилиты `sonar-scanner` можно передавать версию из созданного общего модуля. Для этого необходимо заполнить параметр (`sonarqube` -> `infoBaseUpdateModuleName`). Если параметр не заполнен, версия передается из корня конфигурации. + * По умолчанию шаг анализа не дожидается окончания фонового задания на сервере SonarQube и не анализирует результат прохождения Порога качества (`sonarqube` -> `waitForQualityGate`). + * Если выполнялась валидация EDT, результаты валидации передаются утилите `sonar-scanner` как значение параметра `sonar.externalIssuesReportPaths` при использовании `stebi` или как значение параметра `sonar.bsl.languageserver.reportPaths` при использовании `edt-ripper`. +* Рассылка уведомлений: + * Электронная почта: + * Для отправки используется плагин [`email-ext`](https://plugins.jenkins.io/email-ext). Шаблоны сообщений конфигурируются в настройках плагина. + * Уведомления о результатах сборки по умолчанию рассылаются только при полном падении сборочной линии (`notifications` -> `email` -> `onAlways`, `onFailure`, `onUnstable`, `onSuccess`). + * Лог сборки прикладывается к письму при полном падении сборочной линии и при отправке в режиме "всегда отправлять" (`notifications` -> `email` -> `*options` -> `attachLog`). + * В качестве получателей писем (`notifications` -> `email` -> `*options` -> `recipientProviders`) в различных режимах отправки используются: + * всегда - разработчики и запустивший сборку; + * при падении - разработчики, запустивший сборку и подозреваемый в причине падения сборки; + * при успехе - разработчики и запустивший сборку; + * при нестабильной сборке (упавшие тесты) - разработчики и запустивший сборку. + * Прямые получатели уведомлений не заполнены (`notifications` -> `email` -> `*options` -> `directRecipients`). + * Telegram: + * Уведомления о результатах сборки по умолчанию рассылаются всегда (`notifications` -> `telegram` -> `onAlways`, `onFailure`, `onUnstable`, `onSuccess`). + +## Настройка загрузки расширений + +Если у вас есть расширения, которые необходимо загрузить в базу для проведения тестов и проверок, это можно сделать на этапе подготовки базы. + +* При загрузке из исходников расширения должны быть в том же формате (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) +1. Укажите этапы сборки, на которых должно быть загружено расширение (`initInfobase` -> `extensions` -> `stages`). Если оставить это поле пустым, то расширение будет загружено на этапе `initInfobase` и будет активно на всех последующих этапах. В противном случае расширение будет использоваться только на перечисленных этапах. + +Пример конфигурации для загрузки расширений: + +```json +"initInfobase": { + "extensions": [ + { + "name": "ИмяРасширения1", + "initMethod": "fromSource", + "path": "путь/до/исходников/расширения", + "stages": ["bdd", "yaxunit"] + }, + { + "name": "ИмяРасширения2", + "initMethod": "fromFile", + "path": "https://example.com/path/to/extension.cfe" + } + ] +} +``` +## Загрузка эталонной базы + +Реализована возможность загрузки эталонной базы на этапе инициализации информационной базы. Для этого необходимо указать в конфигурационном файле параметр `initInfobase` -> `templateDBPath`: + +```json +"initInfobase": { + "templateDBPath": "путь/до/файла/базы.dt" +} +``` + +* Поддерживается загрузка файлов формата `.dt` и `.1CD`. +* Путь к файлу базы может быть как локальным, так и удаленным (URL). +* После загрузки базы для инициализации будет использоваться файл настроек `vanessa-runner` (включая логин и пароль от ИБ), указанный в параметре `initInfobase` -> `vrunnerSettings`. По умолчанию используется файл `tools/vrunner.json`. + +```json +"initInfobase": { + "templateDBPath": "путь/до/файла/базы.dt", + "vrunnerSettings": "tools/vrunner.json" +} +``` + +## Настройка шага YAXUnit + + * Добавить расширение `YAXUnit` и дополнительные расширения с тестами можно в `jobConfiguration.json` -> `initInfobase` -> `extensions`. Они будут загружены при инициализации ИБ. + * Если ваши тесты размещены в отдельных расширениях, скопируйте файл `./resources/yaxunit.json` из текущей библиотеки в свой репозиторий (`./tools/yaxunit.json`) и перечислите в нем имена ваших расширений. + * Если используется собственный файл `tools/yaxunit.json`, то значение параметра `reportPath` в нем должно быть равно `./build/out/yaxunit/junit.xml` + +## Настройка трансформации результата валидации EDT + +* При использовании SonarQube версии <10.3 и `stebi` формат отчета должен быть `Generic_Issue` (параметр `resultsTransform` -> `genericIssueFormat`) +* Трансформацию результатов может выполнять `edt-ripper` (параметр `resultsTransform` -> `transformer`). В этом случае замечания будут загружены в SonarQube в формате BSL LS, что позволяет полноценно управлять ими в SonarQube. + +## Сбор замеров покрытия + +* Для сбора замеров покрытия на агентах требуется: + * oscript с библиотекой v8find, которая по умолчанию есть в составе дистрибутива oscript + * сервер отладки dbgs, который есть в составе дистрибутива платформы 1С:Предприятие + * [Coverage41C](https://github.com/1c-syntax/Coverage41C), его необходимо установить на агент отдельно + * EDT нужной версии или отдельные jar-файлы из его каталога установки, подробнее см. в [Coverage41C/README.md](https://github.com/1c-syntax/Coverage41C) +* Если на агенте Coverage41C не включен в PATH, необходимо указать полный путь к нему в параметре `coverage41CPath` +* Сбор замеров покрытия активируется для каждого стейджа отдельно с помощью установки параметра `"coverage": true` +* поддерживаются `bdd` и `yaxunit`, для использования замеров на стейже `smoke` ожидается исправление vanessa-add в этом [PR](https://github.com/vanessa-opensource/add/pull/1153) +* Чтобы замеры в `bdd`, `yaxunit`, `smoke` могли выполняться параллельно **на одном агенте**, необходимо указывать для них разные порты отладки в параметре `dbgsPort`. +* Не забудьте настроить подключение клиентов тестирования к серверу отладки. + +Пример настройки подключения для `bdd`: + +jobConfiguration.json +```json +"bdd": { + "vrunnerSteps": [ + "vanessa --settings ./tools/vrunner.json" + ], + "coverage": true, + "dbgsPort": 1550 + }, +``` + +./tools/vrunner.json +```json + "vanessa": { + "--vanessasettings": "tools/VAParams.json", + } +``` + +./tools/VAParams.json +```json +"КлиентТестирования": { + "ЗапускатьТестКлиентВРежимеОтладки": true, + "КлючиОтладки": "-http", + "АдресОтладчика": "http://127.0.0.1:1550", +``` + +Для `yaxunit`: + +./tools/vrunner.json +``` +"default": { + "--additional": "/debug -http -attach /debuggerURL http://localhost:1550" +} +``` + +Для `smoke` (после исправления ошибки в vanessa-add): + +./tools/vrunner.json +``` +"xunit": { + "--testclient-additional": "/debug -http -attach /debuggerURL http://localhost:1550" +} +``` + +* При изменении портов отладки в jobConfiguration.json не забывайте менять порты в настройках соответствующих шагов (и наоборот) +* Настоятельно рекомендуется использовать не "постоянные" агенты Jenkins, а контейнеры docker. При выполнении билдов в контейнерах можно использовать исключительно стандартный порт 1550. diff --git a/resources/dbgs.os b/resources/dbgs.os new file mode 100644 index 00000000..77f0318a --- /dev/null +++ b/resources/dbgs.os @@ -0,0 +1,3 @@ +#Использовать v8find + +Сообщить(Платформа1С.ПутьКDBGS(АргументыКоманднойСтроки[0])); diff --git a/resources/globalConfiguration.json b/resources/globalConfiguration.json index aa1af975..58db158c 100644 --- a/resources/globalConfiguration.json +++ b/resources/globalConfiguration.json @@ -50,7 +50,9 @@ "bdd": { "vrunnerSteps": [ "vanessa --settings ./tools/vrunner.json" - ] + ], + "coverage": false, + "dbgsPort": 1550 }, "sonarqube": { "sonarQubeInstallation": "", @@ -83,13 +85,21 @@ "vrunnerSettings": "./tools/vrunner.json", "xddConfigPath": "./tools/xUnitParams.json", "publishToAllureReport": false, - "publishToJUnitReport": true + "publishToJUnitReport": true, + "coverage": false, + "dbgsPort": 1550 + }, + "coverage": { + "dbgsPath": "", + "coverage41CPath": "Coverage41C" }, "yaxunit": { "vrunnerSettings": "./tools/vrunner.json", "configPath": "./tools/yaxunit.json", "publishToAllureReport": false, - "publishToJUnitReport": true + "publishToJUnitReport": true, + "coverage": false, + "dbgsPort": 1550 }, "resultsTransform": { "transformer": "stebi", diff --git a/resources/schema.json b/resources/schema.json index a1c89a0f..5e03b5db 100644 --- a/resources/schema.json +++ b/resources/schema.json @@ -1,451 +1,495 @@ -{ - "$schema" : "http://json-schema.org/draft-07/schema#", - "definitions" : { - "EmailExtConfiguration" : { - "type" : "object", - "properties" : { - "attachLog" : { - "type" : "boolean" - }, - "directRecipients" : { - "type" : "array", - "items" : { - "type" : "string" - } - }, - "recipientProviders" : { - "type" : "array", - "items" : { - "type" : "string", - "enum" : [ "developers", "requestor", "brokenBuildSuspects", "brokenTestsSuspects" ] - } - } - } - } - }, - "type" : "object", - "properties" : { - "bdd" : { - "type" : "object", - "properties" : { - "vrunnerSteps" : { - "description" : "Шаги, запускаемые через vrunner.\n В каждой строке передается отдельная команда \n vrunner и ее аргументы (например, \"vanessa --settings ./tools/vrunner.json\").\n По умолчанию содержит одну команду \"vanessa --settings ./tools/vrunner.json\".\n ", - "type" : "array", - "items" : { - "type" : "string" - } - } - }, - "description" : "Настройки шага запуска BDD сценариев" - }, - "defaultBranch" : { - "type" : "string", - "description" : "Имя ветки по умолчанию. Значение по умолчанию - main." - }, - "edtVersion" : { - "type" : "string", - "description" : "Версия модуля 1C:Enterprise Development Tools формате xxxx.x.x:x86_64" - }, - "initInfobase" : { - "type" : "object", - "properties" : { - "additionalInitializationSteps" : { - "description" : "Дополнительные шаги, запускаемые через vrunner.\n В каждой строке передается отдельная команда \n vrunner и ее аргументы (например, \"vanessa --settings ./tools/vrunner.first.json\")\n ", - "type" : "array", - "items" : { - "type" : "string" - } - }, - "extensions" : { - "description" : "Массив расширений для загрузки в конфигурацию.", - "type" : "array", - "items" : { - "type" : "object", - "properties" : { - "initMethod" : { - "type" : "string", - "enum" : [ "fromSource", "fromFile" ], - "description" : "\n Способ инициализации расширения.\n Поддерживается два варианта:\n * fromSource - инициализация расширения из исходников;\n * fromFile - скачивание скомпилированного cfe по ссылке.\n " - }, - "name" : { - "type" : "string", - "description" : "Имя расширения, используемое при его загрузке в конфигурацию." - }, - "path" : { - "type" : "string", - "description" : "\n Путь к расширению.\n * В случае если выбран initMethod - указывается путь к исходникам расширения.\n * В случае если выбран initMethod - указывается путь к cfe-файлу\n " - }, - "stages" : { - "description" : "\n Шаги, на которых необходимо использовать расширение\n * Если не заполнено, то расширение будет подключено при инициализации базы и останется в базе на всех последующих шагах.\n * Если заполнено, то расширение будет подключено только на соответствующих шагах.\n ", - "type" : "array", - "items" : { - "type" : "string" - } - } - } - } - }, - "initMethod" : { - "type" : "string", - "enum" : [ "fromStorage", "fromSource", "defaultBranchFromStorage" ], - "description" : "\n Способ инициализации информационной базы.\n Поддерживается три варианта:\n * fromStorage - инициализация информационной базы из хранилища конфигурации;\n * fromSource - инициализация информационной базы из исходников конфигурации;\n * defaultBranchFromStorage - инициализация основной ветки из хранилища конфигурации, остальных - из исходников конфигурации.\n По умолчанию содержит значение \"fromStorage\".", - "default" : "fromStorage" - }, - "runMigration" : { - "type" : "boolean", - "description" : "Запустить миграцию ИБ" - }, - "templateDBPath" : { - "type" : "string", - "description" : "\n Путь к файлу эталонной базы данных.\n * По умолчанию не заполнен;\n * Указывается путь к файлу *.dt или *.1CD.\n " - }, - "vrunnerSettings" : { - "type" : "string", - "description" : "Путь к конфигурационному файлу vanessa-runner.\n По умолчанию содержит значение \"./tools/vrunner.json\"\n Используется, если на этапе подготовки база загружается из эталона. \n " - } - }, - "description" : "Настройки шага инициализации ИБ" - }, - "logosConfig" : { - "type" : "string", - "description" : "Конфигурация библиотеки logos. Применяется перед запуском каждой стадии сборки" - }, - "notifications" : { - "type" : "object", - "properties" : { - "email" : { - "type" : "object", - "properties" : { - "alwaysOptions" : { - "$ref" : "#/definitions/EmailExtConfiguration" - }, - "failureOptions" : { - "$ref" : "#/definitions/EmailExtConfiguration" - }, - "onAlways" : { - "type" : "boolean", - "description" : "Отправлять всегда" - }, - "onFailure" : { - "type" : "boolean", - "description" : "Отправлять при падении сборки" - }, - "onSuccess" : { - "type" : "boolean", - "description" : "Отправлять при успешной сборке" - }, - "onUnstable" : { - "type" : "boolean", - "description" : "Отправлять при нестабильной сборке" - }, - "successOptions" : { - "$ref" : "#/definitions/EmailExtConfiguration" - }, - "unstableOptions" : { - "$ref" : "#/definitions/EmailExtConfiguration" - } - }, - "description" : "Настройки рассылки результатов сборки через email" - }, - "telegram" : { - "type" : "object", - "properties" : { - "onAlways" : { - "type" : "boolean", - "description" : "Отправлять всегда" - }, - "onFailure" : { - "type" : "boolean", - "description" : "Отправлять при падении сборки" - }, - "onSuccess" : { - "type" : "boolean", - "description" : "Отправлять при успешной сборке" - }, - "onUnstable" : { - "type" : "boolean", - "description" : "Отправлять при нестабильной сборке" - } - }, - "description" : "Настройки рассылки результатов сборки через telegram" - } - }, - "description" : "Настройки рассылки результатов сборки" - }, - "resultsTransform" : { - "type" : "object", - "properties" : { - "genericIssueFormat" : { - "type" : "string", - "enum" : [ "Generic_Issue", "Generic_Issue_10_3" ], - "description" : "Формат отчета generic issue. Только для stebi.\n Для SonarQube версии ниже 10.3 необходимо использовать Generic_Issue.\n По умолчанию Generic_Issue_10_3\n ", - "default" : "Generic_Issue_10_3" - }, - "removeSupport" : { - "type" : "boolean", - "description" : "Фильтровать замечания по уровню поддержки модуля. Только для stebi. По умолчанию включено." - }, - "supportLevel" : { - "type" : "integer", - "description" : "Настройка фильтрации замечаний по уровню поддержки. Только для stebi.\n 0 - удалить файлы на замке;\n 1 - удалить файлы на замке и на поддержке;\n 2 - удалить файлы на замке, на поддержке и снятые с поддержки.\n " - }, - "transformer" : { - "type" : "string", - "enum" : [ "stebi", "edt-ripper" ], - "description" : "Способ преобразования замечаний.\n Поддерживается stebi и edt-ripper.\n По умолчанию содержит значение \"stebi\".\n ", - "default" : "stebi" - } - }, - "description" : "Настройки трансформации результатов анализа" - }, - "secrets" : { - "type" : "object", - "properties" : { - "storage" : { - "type" : "string", - "description" : "Данные авторизации в хранилище конфигурации" - }, - "storagePath" : { - "type" : "string", - "description" : "Путь к хранилищу конфигурации" - }, - "telegramBotToken" : { - "type" : "string", - "description" : "Токен авторизации telegram-бота для отправки уведомлений" - }, - "telegramChatId" : { - "type" : "string", - "description" : "Идентификатор telegram-чата для отправки уведомлений" - } - }, - "description" : "Идентификаторы сохраненных секретов" - }, - "smoke" : { - "type" : "object", - "properties" : { - "publishToAllureReport" : { - "type" : "boolean", - "description" : "Выполнять публикацию результатов в отчет Allure.\n По умолчанию выключено.\n " - }, - "publishToJUnitReport" : { - "type" : "boolean", - "description" : "Выполнять публикацию результатов в отчет JUnit.\n По умолчанию включено.\n " - }, - "vrunnerSettings" : { - "type" : "string", - "description" : "Путь к конфигурационному файлу vanessa-runner.\n По умолчанию содержит значение \"./tools/vrunner.json\".\n " - }, - "xddConfigPath" : { - "type" : "string", - "description" : "Путь к конфигурационному файлу для xddTestRunner.\n По умолчанию содержит значение \"./tools/xUnitParams.json\".\n " - } - }, - "description" : "Настройки дымового тестирования" - }, - "sonarqube" : { - "type" : "object", - "properties" : { - "branchAnalysisConfiguration" : { - "type" : "string", - "enum" : [ "auto", "fromEnv" ], - "description" : "Вариант конфигурации branch plugin.\n Поддерживаемые варианты:\n * auto - применяется автоконфигурация sonar-scanner силами branchplugin. Так же может применяться для отключения конфигурирования, если branch plugin отсутствует;\n * fromEnv - применяется ручная конфигурация sonar-scanner на основе переменных среды.\n Значение по умолчанию: fromEnv.", - "default" : "auto" - }, - "infoBaseUpdateModuleName" : { - "type" : "string", - "description" : "Имя общего модуля (например, ОбновлениеИнформационнойБазыXXX), в котором указана версия библиотеки.\n Версия должна задаваться в виде присвоения `Описание.Версия = \"ваш номер версии\";`\n " - }, - "sonarQubeInstallation" : { - "type" : "string", - "description" : "Имя настроенного SonarQube-сервера (SonarQube installations).\nЕсли настроен только один сервер, то может быть оставлено пустым." - }, - "sonarScannerToolName" : { - "type" : "string", - "description" : "Имя настроенной утилиты sonar-scanner.\nПрименяется, если useSonarScannerFromPath установлено в false." - }, - "useSonarScannerFromPath" : { - "type" : "boolean", - "description" : "Использовать sonar-scanner, доступный в PATH" - }, - "waitForQualityGate" : { - "type" : "boolean", - "description" : "Ожидать состояние Quality Gate от SonarQube после загрузки анализа. По умолчанию `false`.\n Таймаут ожидания состояния равен таймауту шага.\n " - } - }, - "description" : "Настройки анализа SonarQube" - }, - "sourceFormat" : { - "type" : "string", - "enum" : [ "edt", "designer" ], - "description" : "Формат исходников конфигурации", - "default" : "designer" - }, - "srcDir" : { - "type" : "string", - "description" : "Путь к корневому каталогу с исходниками конфигурации, в случае хранения исходников в формате EDT, необходимо указать путь к проекту" - }, - "stages" : { - "type" : "object", - "properties" : { - "bdd" : { - "type" : "boolean", - "description" : "Запуск BDD сценариев включен" - }, - "edtValidate" : { - "type" : "boolean", - "description" : "Валидация EDT включена" - }, - "email" : { - "type" : "boolean", - "description" : "Выполнять рассылку результатов сборки на email" - }, - "initSteps" : { - "type" : "boolean", - "description" : "Предварительные шаги инициализации включены" - }, - "smoke" : { - "type" : "boolean", - "description" : "Дымовые тесты включены" - }, - "sonarqube" : { - "type" : "boolean", - "description" : "Анализ SonarQube включен" - }, - "syntaxCheck" : { - "type" : "boolean", - "description" : "Синтаксический контроль включен" - }, - "telegram" : { - "type" : "boolean", - "description" : "Выполнять рассылку результатов сборки в telegram" - }, - "yaxunit" : { - "type" : "boolean", - "description" : "Запуск YAXUnit тестов включен" - } - }, - "description" : "Включение этапов сборок" - }, - "syntaxCheck" : { - "type" : "object", - "properties" : { - "checkModes" : { - "description" : "Режимы проверки конфигурации", - "type" : "array", - "items" : { - "type" : "string" - } - }, - "exceptionFile" : { - "type" : "string", - "description" : "Путь к файлу с указанием пропускаемых ошибок.\n Формат файла: в каждой строке файла указан текст пропускаемого исключения или его часть\n Кодировка: UTF-8\n " - }, - "groupErrorsByMetadata" : { - "type" : "boolean", - "description" : "Группировать выявленные ошибки по объектам метаданных.\n По умолчанию включено.\n " - }, - "pathToJUnitReport" : { - "type" : "string", - "description" : "Путь к файлу отчета jUnit\n По умолчанию содержит значение \"./build/out/jUnit/syntax.xml\"\n " - }, - "vrunnerSettings" : { - "type" : "string", - "description" : "Путь к конфигурационному файлу vanessa-runner.\n По умолчанию содержит значение \"./tools/vrunner.json\".\n " - } - }, - "description" : "Настройки синтаксического контроля" - }, - "timeout" : { - "type" : "object", - "properties" : { - "bdd" : { - "type" : "integer", - "description" : "Таймаут шага проверки сценариев поведения, в минутах.\n По умолчанию содержит значение 120.\n " - }, - "createInfoBase" : { - "type" : "integer", - "description" : "Таймаут шага создания информационной базы, в минутах.\n По умолчанию содержит значение 60.\n " - }, - "designerToEdtFormatTransformation" : { - "type" : "integer", - "description" : "Таймаут шага трансформации исходников из формата Конфигуратора в формат EDT, в минутах.\n По умолчанию содержит значение 60.\n " - }, - "edtToDesignerFormatTransformation" : { - "type" : "integer", - "description" : "Таймаут шага трансформации исходников из формата EDT в формат Конфигуратора, в минутах.\n По умолчанию содержит значение 60.\n " - }, - "edtValidate" : { - "type" : "integer", - "description" : "Таймаут шага валидации EDT, в минутах.\n По умолчанию содержит значение 240.\n " - }, - "getBinaries" : { - "type" : "integer", - "description" : "Таймаут шага получения бинарников, в минутах.\n По умолчанию содержит значение 60.\n " - }, - "initInfoBase" : { - "type" : "integer", - "description" : "Таймаут шага инициализации информационной базы, в минутах.\n По умолчанию содержит значение 60.\n " - }, - "loadConfiguration" : { - "type" : "integer", - "description" : "Таймаут шага загрузки конфигурации в базу, в минутах.\n По умолчанию содержит значение 60.\n " - }, - "loadExtensions" : { - "type" : "integer", - "description" : "Таймаут шага загрузки расширений в базу, в минутах.\n По умолчанию содержит значение 60.\n " - }, - "resultTransformation" : { - "type" : "integer", - "description" : "Таймаут шага трансформации результатов EDT, в минутах.\n По умолчанию содержит значение 10.\n " - }, - "smoke" : { - "type" : "integer", - "description" : "Таймаут шага дымовых тестов, в минутах.\n По умолчанию содержит значение 240.\n " - }, - "sonarqube" : { - "type" : "integer", - "description" : "Таймаут шага статического анализа SonarQube, в минутах.\n По умолчанию содержит значение 90.\n " - }, - "syntaxCheck" : { - "type" : "integer", - "description" : "Таймаут шага синтаксического контроля, в минутах.\n По умолчанию содержит значение 240.\n " - }, - "yaxunit" : { - "type" : "integer", - "description" : "Таймаут шага YAXUnit тестов, в минутах.\n По умолчанию содержит значение 240.\n " - }, - "zipInfoBase" : { - "type" : "integer", - "description" : "Таймаут шага архивирования информационной базы, в минутах.\n По умолчанию содержит значение 60.\n " - } - }, - "description" : "Настройка таймаутов для шагов" - }, - "v8version" : { - "type" : "string", - "description" : "Версия платформы 1С:Предприятие в формате 8.3.хх.хххх." - }, - "yaxunit" : { - "type" : "object", - "properties" : { - "configPath" : { - "type" : "string", - "description" : "Путь к конфигурационному файлу YAXUnit.\n По умолчанию содержит значение \"./tools/yaxunit.json\".\n " - }, - "publishToAllureReport" : { - "type" : "boolean", - "description" : "Выполнять публикацию результатов в отчет Allure.\n По умолчанию выключено.\n " - }, - "publishToJUnitReport" : { - "type" : "boolean", - "description" : "Выполнять публикацию результатов в отчет JUnit.\n По умолчанию включено.\n " - }, - "vrunnerSettings" : { - "type" : "string", - "description" : "Путь к конфигурационному файлу vanessa-runner.\n По умолчанию содержит значение \"./tools/vrunner.json\".\n " - } - }, - "description" : "Настройки YAXUnit" - } - } +{ + "$schema" : "http://json-schema.org/draft-07/schema#", + "definitions" : { + "EmailExtConfiguration" : { + "type" : "object", + "properties" : { + "attachLog" : { + "type" : "boolean" + }, + "directRecipients" : { + "type" : "array", + "items" : { + "type" : "string" + } + }, + "recipientProviders" : { + "type" : "array", + "items" : { + "type" : "string", + "enum" : [ "developers", "requestor", "brokenBuildSuspects", "brokenTestsSuspects" ] + } + } + } + } + }, + "type" : "object", + "properties" : { + "bdd" : { + "type" : "object", + "properties" : { + "coverage" : { + "type" : "boolean", + "description" : "Выполнять замер покрытия", + "default" : "false" + }, + "dbgsPort" : { + "type" : "integer", + "description" : "Порт, на котором будет запущен сервер отладки для замера покрытия", + "default" : "1550" + }, + "vrunnerSteps" : { + "description" : "Шаги, запускаемые через vrunner.\n В каждой строке передается отдельная команда \n vrunner и ее аргументы (например, \"vanessa --settings ./tools/vrunner.json\").\n По умолчанию содержит одну команду \"vanessa --settings ./tools/vrunner.json\".\n ", + "type" : "array", + "items" : { + "type" : "string" + } + } + }, + "description" : "Настройки шага запуска BDD сценариев" + }, + "coverage" : { + "type" : "object", + "properties" : { + "coverage41CPath" : { + "type" : "string", + "description" : "Путь к исполняемому файлу Coverage41C\n По умолчанию ищется в PATH.\n " + }, + "dbgsPath" : { + "type" : "string", + "description" : "Путь к исполняемому файлу dbgs.\n По умолчанию ищется с помощью v8find для указанной версии платформы (v8version).\n " + } + }, + "description" : "Настройки замеров покрытия" + }, + "defaultBranch" : { + "type" : "string", + "description" : "Имя ветки по умолчанию. Значение по умолчанию - main." + }, + "edtVersion" : { + "type" : "string", + "description" : "Версия модуля 1C:Enterprise Development Tools формате xxxx.x.x:x86_64" + }, + "initInfobase" : { + "type" : "object", + "properties" : { + "additionalInitializationSteps" : { + "description" : "Дополнительные шаги, запускаемые через vrunner.\n В каждой строке передается отдельная команда \n vrunner и ее аргументы (например, \"vanessa --settings ./tools/vrunner.first.json\")\n ", + "type" : "array", + "items" : { + "type" : "string" + } + }, + "extensions" : { + "description" : "Массив расширений для загрузки в конфигурацию.", + "type" : "array", + "items" : { + "type" : "object", + "properties" : { + "initMethod" : { + "type" : "string", + "enum" : [ "fromSource", "fromFile" ], + "description" : "\n Способ инициализации расширения.\n Поддерживается два варианта:\n * fromSource - инициализация расширения из исходников;\n * fromFile - скачивание скомпилированного cfe по ссылке.\n " + }, + "name" : { + "type" : "string", + "description" : "Имя расширения, используемое при его загрузке в конфигурацию." + }, + "path" : { + "type" : "string", + "description" : "\n Путь к расширению.\n * В случае если выбран initMethod - указывается путь к исходникам расширения.\n * В случае если выбран initMethod - указывается путь к cfe-файлу\n " + }, + "stages" : { + "description" : "\n Шаги, на которых необходимо использовать расширение\n * Если не заполнено, то расширение будет подключено при инициализации базы и останется в базе на всех последующих шагах.\n * Если заполнено, то расширение будет подключено только на соответствующих шагах.\n ", + "type" : "array", + "items" : { + "type" : "string" + } + } + } + } + }, + "initMethod" : { + "type" : "string", + "enum" : [ "fromStorage", "fromSource", "defaultBranchFromStorage" ], + "description" : "\n Способ инициализации информационной базы.\n Поддерживается три варианта:\n * fromStorage - инициализация информационной базы из хранилища конфигурации;\n * fromSource - инициализация информационной базы из исходников конфигурации;\n * defaultBranchFromStorage - инициализация основной ветки из хранилища конфигурации, остальных - из исходников конфигурации.\n По умолчанию содержит значение \"fromStorage\".", + "default" : "fromStorage" + }, + "runMigration" : { + "type" : "boolean", + "description" : "Запустить миграцию ИБ" + }, + "templateDBPath" : { + "type" : "string", + "description" : "\n Путь к файлу эталонной базы данных.\n * По умолчанию не заполнен;\n * Указывается путь к файлу *.dt или *.1CD.\n " + }, + "vrunnerSettings" : { + "type" : "string", + "description" : "Путь к конфигурационному файлу vanessa-runner.\n По умолчанию содержит значение \"./tools/vrunner.json\"\n Используется, если на этапе подготовки база загружается из эталона. \n " + } + }, + "description" : "Настройки шага инициализации ИБ" + }, + "logosConfig" : { + "type" : "string", + "description" : "Конфигурация библиотеки logos. Применяется перед запуском каждой стадии сборки" + }, + "notifications" : { + "type" : "object", + "properties" : { + "email" : { + "type" : "object", + "properties" : { + "alwaysOptions" : { + "$ref" : "#/definitions/EmailExtConfiguration" + }, + "failureOptions" : { + "$ref" : "#/definitions/EmailExtConfiguration" + }, + "onAlways" : { + "type" : "boolean", + "description" : "Отправлять всегда" + }, + "onFailure" : { + "type" : "boolean", + "description" : "Отправлять при падении сборки" + }, + "onSuccess" : { + "type" : "boolean", + "description" : "Отправлять при успешной сборке" + }, + "onUnstable" : { + "type" : "boolean", + "description" : "Отправлять при нестабильной сборке" + }, + "successOptions" : { + "$ref" : "#/definitions/EmailExtConfiguration" + }, + "unstableOptions" : { + "$ref" : "#/definitions/EmailExtConfiguration" + } + }, + "description" : "Настройки рассылки результатов сборки через email" + }, + "telegram" : { + "type" : "object", + "properties" : { + "onAlways" : { + "type" : "boolean", + "description" : "Отправлять всегда" + }, + "onFailure" : { + "type" : "boolean", + "description" : "Отправлять при падении сборки" + }, + "onSuccess" : { + "type" : "boolean", + "description" : "Отправлять при успешной сборке" + }, + "onUnstable" : { + "type" : "boolean", + "description" : "Отправлять при нестабильной сборке" + } + }, + "description" : "Настройки рассылки результатов сборки через telegram" + } + }, + "description" : "Настройки рассылки результатов сборки" + }, + "resultsTransform" : { + "type" : "object", + "properties" : { + "genericIssueFormat" : { + "type" : "string", + "enum" : [ "Generic_Issue", "Generic_Issue_10_3" ], + "description" : "Формат отчета generic issue. Только для stebi.\n Для SonarQube версии ниже 10.3 необходимо использовать Generic_Issue.\n По умолчанию Generic_Issue_10_3\n ", + "default" : "Generic_Issue_10_3" + }, + "removeSupport" : { + "type" : "boolean", + "description" : "Фильтровать замечания по уровню поддержки модуля. Только для stebi. По умолчанию включено." + }, + "supportLevel" : { + "type" : "integer", + "description" : "Настройка фильтрации замечаний по уровню поддержки. Только для stebi.\n 0 - удалить файлы на замке;\n 1 - удалить файлы на замке и на поддержке;\n 2 - удалить файлы на замке, на поддержке и снятые с поддержки.\n " + }, + "transformer" : { + "type" : "string", + "enum" : [ "stebi", "edt-ripper" ], + "description" : "Способ преобразования замечаний.\n Поддерживается stebi и edt-ripper.\n По умолчанию содержит значение \"stebi\".\n ", + "default" : "stebi" + } + }, + "description" : "Настройки трансформации результатов анализа" + }, + "secrets" : { + "type" : "object", + "properties" : { + "storage" : { + "type" : "string", + "description" : "Данные авторизации в хранилище конфигурации" + }, + "storagePath" : { + "type" : "string", + "description" : "Путь к хранилищу конфигурации" + }, + "telegramBotToken" : { + "type" : "string", + "description" : "Токен авторизации telegram-бота для отправки уведомлений" + }, + "telegramChatId" : { + "type" : "string", + "description" : "Идентификатор telegram-чата для отправки уведомлений" + } + }, + "description" : "Идентификаторы сохраненных секретов" + }, + "smoke" : { + "type" : "object", + "properties" : { + "coverage" : { + "type" : "boolean", + "description" : "Выполнять замер покрытия", + "default" : "false" + }, + "dbgsPort" : { + "type" : "integer", + "description" : "Порт, на котором будет запущен сервер отладки для замера покрытия", + "default" : "1550" + }, + "publishToAllureReport" : { + "type" : "boolean", + "description" : "Выполнять публикацию результатов в отчет Allure.\n По умолчанию выключено.\n " + }, + "publishToJUnitReport" : { + "type" : "boolean", + "description" : "Выполнять публикацию результатов в отчет JUnit.\n По умолчанию включено.\n " + }, + "vrunnerSettings" : { + "type" : "string", + "description" : "Путь к конфигурационному файлу vanessa-runner.\n По умолчанию содержит значение \"./tools/vrunner.json\".\n " + }, + "xddConfigPath" : { + "type" : "string", + "description" : "Путь к конфигурационному файлу для xddTestRunner.\n По умолчанию содержит значение \"./tools/xUnitParams.json\".\n " + } + }, + "description" : "Настройки дымового тестирования" + }, + "sonarqube" : { + "type" : "object", + "properties" : { + "branchAnalysisConfiguration" : { + "type" : "string", + "enum" : [ "auto", "fromEnv" ], + "description" : "Вариант конфигурации branch plugin.\n Поддерживаемые варианты:\n * auto - применяется автоконфигурация sonar-scanner силами branchplugin. Так же может применяться для отключения конфигурирования, если branch plugin отсутствует;\n * fromEnv - применяется ручная конфигурация sonar-scanner на основе переменных среды.\n Значение по умолчанию: fromEnv.", + "default" : "fromEnv" + }, + "infoBaseUpdateModuleName" : { + "type" : "string", + "description" : "Имя общего модуля (например, ОбновлениеИнформационнойБазыXXX), в котором указана версия библиотеки.\n Версия должна задаваться в виде присвоения `Описание.Версия = \"ваш номер версии\";`\n " + }, + "sonarQubeInstallation" : { + "type" : "string", + "description" : "Имя настроенного SonarQube-сервера (SonarQube installations).\nЕсли настроен только один сервер, то может быть оставлено пустым." + }, + "sonarScannerToolName" : { + "type" : "string", + "description" : "Имя настроенной утилиты sonar-scanner.\nПрименяется, если useSonarScannerFromPath установлено в false." + }, + "useSonarScannerFromPath" : { + "type" : "boolean", + "description" : "Использовать sonar-scanner, доступный в PATH" + }, + "waitForQualityGate" : { + "type" : "boolean", + "description" : "Ожидать состояние Quality Gate от SonarQube после загрузки анализа. По умолчанию `false`.\n Таймаут ожидания состояния равен таймауту шага.\n " + } + }, + "description" : "Настройки анализа SonarQube" + }, + "sourceFormat" : { + "type" : "string", + "enum" : [ "edt", "designer" ], + "description" : "Формат исходников конфигурации", + "default" : "designer" + }, + "srcDir" : { + "type" : "string", + "description" : "Путь к корневому каталогу с исходниками конфигурации, в случае хранения исходников в формате EDT, необходимо указать путь к проекту" + }, + "stages" : { + "type" : "object", + "properties" : { + "bdd" : { + "type" : "boolean", + "description" : "Запуск BDD сценариев включен" + }, + "edtValidate" : { + "type" : "boolean", + "description" : "Валидация EDT включена" + }, + "email" : { + "type" : "boolean", + "description" : "Выполнять рассылку результатов сборки на email" + }, + "initSteps" : { + "type" : "boolean", + "description" : "Предварительные шаги инициализации включены" + }, + "smoke" : { + "type" : "boolean", + "description" : "Дымовые тесты включены" + }, + "sonarqube" : { + "type" : "boolean", + "description" : "Анализ SonarQube включен" + }, + "syntaxCheck" : { + "type" : "boolean", + "description" : "Синтаксический контроль включен" + }, + "telegram" : { + "type" : "boolean", + "description" : "Выполнять рассылку результатов сборки в telegram" + }, + "yaxunit" : { + "type" : "boolean", + "description" : "Запуск YAXUnit тестов включен" + } + }, + "description" : "Включение этапов сборок" + }, + "syntaxCheck" : { + "type" : "object", + "properties" : { + "checkModes" : { + "description" : "Режимы проверки конфигурации", + "type" : "array", + "items" : { + "type" : "string" + } + }, + "exceptionFile" : { + "type" : "string", + "description" : "Путь к файлу с указанием пропускаемых ошибок.\n Формат файла: в каждой строке файла указан текст пропускаемого исключения или его часть\n Кодировка: UTF-8\n " + }, + "groupErrorsByMetadata" : { + "type" : "boolean", + "description" : "Группировать выявленные ошибки по объектам метаданных.\n По умолчанию включено.\n " + }, + "pathToJUnitReport" : { + "type" : "string", + "description" : "Путь к файлу отчета jUnit\n По умолчанию содержит значение \"./build/out/jUnit/syntax.xml\"\n " + }, + "vrunnerSettings" : { + "type" : "string", + "description" : "Путь к конфигурационному файлу vanessa-runner.\n По умолчанию содержит значение \"./tools/vrunner.json\".\n " + } + }, + "description" : "Настройки синтаксического контроля" + }, + "timeout" : { + "type" : "object", + "properties" : { + "bdd" : { + "type" : "integer", + "description" : "Таймаут шага проверки сценариев поведения, в минутах.\n По умолчанию содержит значение 120.\n " + }, + "createInfoBase" : { + "type" : "integer", + "description" : "Таймаут шага создания информационной базы, в минутах.\n По умолчанию содержит значение 60.\n " + }, + "designerToEdtFormatTransformation" : { + "type" : "integer", + "description" : "Таймаут шага трансформации исходников из формата Конфигуратора в формат EDT, в минутах.\n По умолчанию содержит значение 60.\n " + }, + "edtToDesignerFormatTransformation" : { + "type" : "integer", + "description" : "Таймаут шага трансформации исходников из формата EDT в формат Конфигуратора, в минутах.\n По умолчанию содержит значение 60.\n " + }, + "edtValidate" : { + "type" : "integer", + "description" : "Таймаут шага валидации EDT, в минутах.\n По умолчанию содержит значение 240.\n " + }, + "getBinaries" : { + "type" : "integer", + "description" : "Таймаут шага получения бинарников, в минутах.\n По умолчанию содержит значение 60.\n " + }, + "initInfoBase" : { + "type" : "integer", + "description" : "Таймаут шага инициализации информационной базы, в минутах.\n По умолчанию содержит значение 60.\n " + }, + "loadConfiguration" : { + "type" : "integer", + "description" : "Таймаут шага загрузки конфигурации в базу, в минутах.\n По умолчанию содержит значение 60.\n " + }, + "loadExtensions" : { + "type" : "integer", + "description" : "Таймаут шага загрузки расширений в базу, в минутах.\n По умолчанию содержит значение 60.\n " + }, + "resultTransformation" : { + "type" : "integer", + "description" : "Таймаут шага трансформации результатов EDT, в минутах.\n По умолчанию содержит значение 10.\n " + }, + "smoke" : { + "type" : "integer", + "description" : "Таймаут шага дымовых тестов, в минутах.\n По умолчанию содержит значение 240.\n " + }, + "sonarqube" : { + "type" : "integer", + "description" : "Таймаут шага статического анализа SonarQube, в минутах.\n По умолчанию содержит значение 90.\n " + }, + "syntaxCheck" : { + "type" : "integer", + "description" : "Таймаут шага синтаксического контроля, в минутах.\n По умолчанию содержит значение 240.\n " + }, + "yaxunit" : { + "type" : "integer", + "description" : "Таймаут шага YAXUnit тестов, в минутах.\n По умолчанию содержит значение 240.\n " + }, + "zipInfoBase" : { + "type" : "integer", + "description" : "Таймаут шага архивирования информационной базы, в минутах.\n По умолчанию содержит значение 60.\n " + } + }, + "description" : "Настройка таймаутов для шагов" + }, + "v8version" : { + "type" : "string", + "description" : "Версия платформы 1С:Предприятие в формате 8.3.хх.хххх." + }, + "yaxunit" : { + "type" : "object", + "properties" : { + "configPath" : { + "type" : "string", + "description" : "Путь к конфигурационному файлу YAXUnit.\n По умолчанию содержит значение \"./tools/yaxunit.json\".\n " + }, + "coverage" : { + "type" : "boolean", + "description" : "Выполнять замер покрытия", + "default" : "false" + }, + "dbgsPort" : { + "type" : "integer", + "description" : "Порт, на котором будет запущен сервер отладки для замера покрытия", + "default" : "1550" + }, + "publishToAllureReport" : { + "type" : "boolean", + "description" : "Выполнять публикацию результатов в отчет Allure.\n По умолчанию выключено.\n " + }, + "publishToJUnitReport" : { + "type" : "boolean", + "description" : "Выполнять публикацию результатов в отчет JUnit.\n По умолчанию включено.\n " + }, + "vrunnerSettings" : { + "type" : "string", + "description" : "Путь к конфигурационному файлу vanessa-runner.\n По умолчанию содержит значение \"./tools/vrunner.json\".\n " + } + }, + "description" : "Настройки YAXUnit" + } + } } \ No newline at end of file diff --git a/resources/yaxunit.json b/resources/yaxunit.json index b5910455..b6e9a1d4 100644 --- a/resources/yaxunit.json +++ b/resources/yaxunit.json @@ -18,9 +18,9 @@ "reportFormat": "jUnit", "showReport": false, "logging": { - "file": "./build/out/yaxunit/log.txt", - "enable": false, - "level": "debug" + "enable": true, + "console": true, + "level": "info" }, "exitCode": "./build/out/yaxunit/result.txt" } \ No newline at end of file diff --git a/src/JobConfigurationSchemaGenerator.java b/src/JobConfigurationSchemaGenerator.java index c272bb58..8a7246e8 100644 --- a/src/JobConfigurationSchemaGenerator.java +++ b/src/JobConfigurationSchemaGenerator.java @@ -15,7 +15,7 @@ public class JobConfigurationSchemaGenerator { - public static void main(String[] args) throws Exception { + public static void main(String[] args) { SchemaGeneratorConfigBuilder configBuilder = new SchemaGeneratorConfigBuilder(SchemaVersion.DRAFT_7, OptionPreset.PLAIN_JSON) .with(new JacksonModule(JacksonOption.FLATTENED_ENUMS_FROM_JSONVALUE, JacksonOption.FLATTENED_ENUMS_FROM_JSONPROPERTY)); diff --git a/src/idea.gdsl b/src/idea.gdsl index b33f99a0..e51bac54 100644 --- a/src/idea.gdsl +++ b/src/idea.gdsl @@ -1,173 +1,492 @@ //The global script scope -def ctx = context(scope: scriptScope()) -//def ctx = context() +def ctx = context(scope: scriptScope(null)) +//What things can be on the script scope contributor(ctx) { - method(name: 'build', type: 'Object', params: [job: 'java.lang.String'], doc: 'Build a job') - method(name: 'build', type: 'Object', namedParams: [parameter(name: 'job', type: 'java.lang.String'), parameter(name: 'parameters', type: 'Map'), parameter(name: 'propagate', type: 'boolean'), parameter(name: 'quietPeriod', type: 'java.lang.Integer'), parameter(name: 'wait', type: 'boolean'),], doc: 'Build a job') - method(name: 'powershell', type: 'Object', params: [script: 'java.lang.String'], doc: 'PowerShell Script') - method(name: 'powershell', type: 'Object', namedParams: [parameter(name: 'script', type: 'java.lang.String'), parameter(name: 'encoding', type: 'java.lang.String'), parameter(name: 'label', type: 'java.lang.String'), parameter(name: 'returnStatus', type: 'boolean'), parameter(name: 'returnStdout', type: 'boolean'),], doc: 'PowerShell Script') - method(name: 'sh', type: 'Object', params: [script: 'java.lang.String'], doc: 'Shell Script') - method(name: 'sh', type: 'Object', namedParams: [parameter(name: 'script', type: 'java.lang.String'), parameter(name: 'encoding', type: 'java.lang.String'), parameter(name: 'label', type: 'java.lang.String'), parameter(name: 'returnStatus', type: 'boolean'), parameter(name: 'returnStdout', type: 'boolean'),], doc: 'Shell Script') - method(name: 'bat', type: 'Object', params: [script: 'java.lang.String'], doc: 'Windows Batch Script') - method(name: 'bat', type: 'Object', namedParams: [parameter(name: 'script', type: 'java.lang.String'), parameter(name: 'encoding', type: 'java.lang.String'), parameter(name: 'label', type: 'java.lang.String'), parameter(name: 'returnStatus', type: 'boolean'), parameter(name: 'returnStdout', type: 'boolean'),], doc: 'Windows Batch Script') - method(name: 'catchError', type: 'Object', params: [body: 'Closure'], doc: 'Catch error and set build result to failure') - method(name: 'catchError', type: 'Object', params: [body: Closure], namedParams: [parameter(name: 'buildResult', type: 'Map'), parameter(name: 'catchInterruptions', type: 'boolean'), parameter(name: 'message', type: 'java.lang.String'), parameter(name: 'stageResult', type: 'Map'),], doc: 'Catch error and set build result to failure') - method(name: 'echo', type: 'Object', params: [message: 'java.lang.String'], doc: 'Print Message') - method(name: 'emailext', type: 'Object', namedParams: [parameter(name: 'subject', type: 'java.lang.String'), parameter(name: 'body', type: 'java.lang.String'), parameter(name: 'attachLog', type: 'boolean'), parameter(name: 'attachmentsPattern', type: 'java.lang.String'), parameter(name: 'compressLog', type: 'boolean'), parameter(name: 'from', type: 'java.lang.String'), parameter(name: 'mimeType', type: 'java.lang.String'), parameter(name: 'postsendScript', type: 'java.lang.String'), parameter(name: 'presendScript', type: 'java.lang.String'), parameter(name: 'recipientProviders', type: 'Map'), parameter(name: 'replyTo', type: 'java.lang.String'), parameter(name: 'to', type: 'java.lang.String'),], doc: 'Extended Email') - method(name: 'emailextrecipients', type: 'Object', params: [recipientProviders: 'Map'], doc: 'Extended Email Recipients') - method(name: 'error', type: 'Object', params: [message: 'java.lang.String'], doc: 'Error signal') - method(name: 'input', type: 'Object', params: [message: 'java.lang.String'], doc: 'Wait for interactive input') - method(name: 'input', type: 'Object', namedParams: [parameter(name: 'message', type: 'java.lang.String'), parameter(name: 'id', type: 'java.lang.String'), parameter(name: 'ok', type: 'java.lang.String'), parameter(name: 'parameters', type: 'Map'), parameter(name: 'submitter', type: 'java.lang.String'), parameter(name: 'submitterParameter', type: 'java.lang.String'),], doc: 'Wait for interactive input') - method(name: 'isUnix', type: 'boolean', params: [:], doc: 'Checks if running on a Unix-like node') - method(name: 'jiraComment', type: 'Object', namedParams: [parameter(name: 'issueKey', type: 'java.lang.String'), parameter(name: 'body', type: 'java.lang.String'),], doc: 'JIRA: Add a comment to issue(s)') - method(name: 'jiraIssueSelector', type: 'Object', params: [:], doc: 'JIRA: Issue selector') - method(name: 'jiraIssueSelector', type: 'Object', namedParams: [parameter(name: 'issueSelector', type: 'Map'),], doc: 'JIRA: Issue selector') - method(name: 'jiraSearch', type: 'Object', params: [jql: 'java.lang.String'], doc: 'JIRA: Search issues') - method(name: 'library', type: 'Object', params: [identifier: 'java.lang.String'], doc: 'Load a shared library on the fly') - method(name: 'library', type: 'Object', namedParams: [parameter(name: 'identifier', type: 'java.lang.String'), parameter(name: 'changelog', type: 'java.lang.Boolean'), parameter(name: 'retriever', type: 'Map'),], doc: 'Load a shared library on the fly') - method(name: 'libraryResource', type: 'Object', params: [resource: 'java.lang.String'], doc: 'Load a resource file from a shared library') - method(name: 'libraryResource', type: 'Object', namedParams: [parameter(name: 'resource', type: 'java.lang.String'), parameter(name: 'encoding', type: 'java.lang.String'),], doc: 'Load a resource file from a shared library') - method(name: 'lock', type: 'Object', params: [resource: String, body: 'Closure'], doc: 'Lock shared resource') - method(name: 'lock', type: 'Object', params: [body: Closure], namedParams: [parameter(name: 'resource', type: 'java.lang.String'), parameter(name: 'extra', type: 'Map'), parameter(name: 'inversePrecedence', type: 'boolean'), parameter(name: 'label', type: 'java.lang.String'), parameter(name: 'quantity', type: 'int'), parameter(name: 'variable', type: 'java.lang.String'),], doc: 'Lock shared resource') - method(name: 'mail', type: 'Object', namedParams: [parameter(name: 'subject', type: 'java.lang.String'), parameter(name: 'body', type: 'java.lang.String'), parameter(name: 'bcc', type: 'java.lang.String'), parameter(name: 'cc', type: 'java.lang.String'), parameter(name: 'charset', type: 'java.lang.String'), parameter(name: 'from', type: 'java.lang.String'), parameter(name: 'mimeType', type: 'java.lang.String'), parameter(name: 'replyTo', type: 'java.lang.String'), parameter(name: 'to', type: 'java.lang.String'),], doc: 'Mail') + method(name: 'pipeline', type: 'Object', params: [body: Closure]) + method(name: 'build', type: 'Object', params: [job: String], doc: 'Build a job') + method(name: 'build', type: 'Object', namedParams: [parameter(name: 'job', type: String), parameter(name: 'parameters', type: Map), parameter(name: 'propagate', type: boolean), parameter(name: 'quietPeriod', type: 'java.lang.Integer'), parameter(name: 'wait', type: boolean),], doc: 'Build a job') + method(name: 'echo', type: 'Object', params: [message: String], doc: 'Print Message') + method(name: 'emailextrecipients', type: 'Object', params: [recipientProviders: Map], doc: 'Extended Email Recipients') + method(name: 'error', type: 'Object', params: [message: String], doc: 'Error signal') + method(name: 'input', type: 'Object', params: [message: String], doc: 'Wait for interactive input') + method(name: 'input', type: 'Object', namedParams: [parameter(name: 'message', type: String), parameter(name: 'id', type: String), parameter(name: 'ok', type: String), parameter(name: 'parameters', type: Map), parameter(name: 'submitter', type: String), parameter(name: 'submitterParameter', type: String),], doc: 'Wait for interactive input') + method(name: 'isUnix', type: 'Object', params: [:], doc: 'Checks if running on a Unix-like node') + method(name: 'library', type: 'Object', params: [identifier: String], doc: 'Load a shared library on the fly') + method(name: 'library', type: 'Object', namedParams: [parameter(name: 'identifier', type: String), parameter(name: 'retriever', type: Map),], doc: 'Load a shared library on the fly') + method(name: 'libraryResource', type: 'Object', params: [resource: String], doc: 'Load a resource file from a shared library') + method(name: 'lock', type: 'Object', params: [resource: String, body: Closure], doc: 'Lock shared resource') + method(name: 'lock', type: 'Object', params: [body: Closure], namedParams: [parameter(name: 'resource', type: String), parameter(name: 'inversePrecedence', type: boolean), parameter(name: 'label', type: String), parameter(name: 'quantity', type: 'int'),], doc: 'Lock shared resource') + method(name: 'mail', type: 'Object', namedParams: [parameter(name: 'subject', type: String), parameter(name: 'body', type: String), parameter(name: 'bcc', type: String), parameter(name: 'cc', type: String), parameter(name: 'charset', type: String), parameter(name: 'from', type: String), parameter(name: 'mimeType', type: String), parameter(name: 'replyTo', type: String), parameter(name: 'to', type: String),], doc: 'Mail') method(name: 'milestone', type: 'Object', params: [ordinal: 'java.lang.Integer'], doc: 'The milestone step forces all builds to go through in order') - method(name: 'milestone', type: 'Object', namedParams: [parameter(name: 'ordinal', type: 'java.lang.Integer'), parameter(name: 'label', type: 'java.lang.String'),], doc: 'The milestone step forces all builds to go through in order') - method(name: 'node', type: 'Object', params: [label: String, body: 'Closure'], doc: 'Allocate node') - method(name: 'nodesByLabel', type: 'Object', params: [label: 'java.lang.String'], doc: 'List of nodes by Label, by default excludes offline nodes.') - method(name: 'nodesByLabel', type: 'Object', namedParams: [parameter(name: 'label', type: 'java.lang.String'), parameter(name: 'offline', type: 'boolean'),], doc: 'List of nodes by Label, by default excludes offline nodes.') - method(name: 'properties', type: 'Object', params: [properties: 'Map'], doc: 'Set job properties') - method(name: 'readCSV', type: 'Object', params: [:], doc: 'Read content from a CSV file in the workspace.') - method(name: 'readCSV', type: 'Object', namedParams: [parameter(name: 'file', type: 'java.lang.String'), parameter(name: 'format', type: 'Map'), parameter(name: 'text', type: 'java.lang.String'),], doc: 'Read content from a CSV file in the workspace.') - method(name: 'readJSON', type: 'Object', params: [:], doc: 'Read JSON from files in the workspace.') - method(name: 'readJSON', type: 'Object', namedParams: [parameter(name: 'file', type: 'java.lang.String'), parameter(name: 'text', type: 'java.lang.String'),], doc: 'Read JSON from files in the workspace.') - method(name: 'readManifest', type: 'Object', params: [:], doc: 'Read a Jar Manifest') - method(name: 'readManifest', type: 'Object', namedParams: [parameter(name: 'file', type: 'java.lang.String'), parameter(name: 'text', type: 'java.lang.String'),], doc: 'Read a Jar Manifest') - method(name: 'readProperties', type: 'Object', params: [:], doc: 'Read properties from files in the workspace or text.') - method(name: 'readProperties', type: 'Object', namedParams: [parameter(name: 'defaults', type: 'java.util.Map'), parameter(name: 'file', type: 'java.lang.String'), parameter(name: 'interpolate', type: 'java.lang.Boolean'), parameter(name: 'text', type: 'java.lang.String'),], doc: 'Read properties from files in the workspace or text.') - method(name: 'readFile', type: 'java.lang.String', params: [file: 'java.lang.String'], doc: 'Read file from workspace') - method(name: 'readFile', type: 'java.lang.String', namedParams: [parameter(name: 'file', type: 'java.lang.String'), parameter(name: 'encoding', type: 'java.lang.String'),], doc: 'Read file from workspace') - method(name: 'fileExists', type: 'Object', params: [file: 'java.lang.String'], doc: 'Verify if file exists in workspace') - method(name: 'readTrusted', type: 'Object', params: [path: 'java.lang.String'], doc: 'Read trusted file from SCM') - method(name: 'readYaml', type: 'Object', params: [:], doc: 'Read yaml from files in the workspace or text.') - method(name: 'readYaml', type: 'Object', namedParams: [parameter(name: 'file', type: 'java.lang.String'), parameter(name: 'text', type: 'java.lang.String'),], doc: 'Read yaml from files in the workspace or text.') - method(name: 'resolveScm', type: 'Object', namedParams: [parameter(name: 'source', type: 'Map'), parameter(name: 'targets', type: 'Map'), parameter(name: 'ignoreErrors', type: 'boolean'),], doc: 'Resolves an SCM from an SCM Source and a list of candidate target branch names') - method(name: 'retry', type: 'Object', params: [count: int, body: 'Closure'], doc: 'Retry the body up to N times') - method(name: 'script', type: 'Object', params: [body: 'Closure'], doc: 'Run arbitrary Pipeline script') + method(name: 'milestone', type: 'Object', namedParams: [parameter(name: 'ordinal', type: 'java.lang.Integer'), parameter(name: 'label', type: String),], doc: 'The milestone step forces all builds to go through in order') + method(name: 'node', type: 'Object', params: [label: String, body: Closure], doc: 'Allocate node') + method(name: 'properties', type: 'Object', params: [properties: Map], doc: 'Set job properties') + method(name: 'readTrusted', type: 'Object', params: [path: String], doc: 'Read trusted file from SCM') + method(name: 'resolveScm', type: 'Object', namedParams: [parameter(name: 'source', type: Map), parameter(name: 'targets', type: Map), parameter(name: 'ignoreErrors', type: boolean),], doc: 'Resolves an SCM from an SCM Source and a list of candidate target branch names') + method(name: 'retry', type: 'Object', params: [count: int, body: Closure], doc: 'Retry the body up to N times') + method(name: 'sauce', type: 'Object', params: [credentialsId: String, body: Closure], doc: 'Sauce') + method(name: 'sauceconnect', type: 'Object', params: [body: Closure], doc: 'Sauce Connect') + method(name: 'sauceconnect', type: 'Object', params: [body: Closure], namedParams: [parameter(name: 'options', type: String), parameter(name: 'sauceConnectPath', type: String), parameter(name: 'useGeneratedTunnelIdentifier', type: 'java.lang.Boolean'), parameter(name: 'verboseLogging', type: 'java.lang.Boolean'),], doc: 'Sauce Connect') + method(name: 'script', type: 'Object', params: [body: Closure], doc: 'Run arbitrary Pipeline script') method(name: 'sleep', type: 'Object', params: [time: 'int'], doc: 'Sleep') method(name: 'sleep', type: 'Object', namedParams: [parameter(name: 'time', type: 'int'), parameter(name: 'unit', type: 'java.util.concurrent.TimeUnit'),], doc: 'Sleep') - method(name: 'stage', type: 'Object', params: [name: String, body: 'Closure'], doc: 'Stage') - method(name: 'stage', type: 'Object', params: [body: Closure], namedParams: [parameter(name: 'name', type: 'java.lang.String'), parameter(name: 'concurrency', type: 'java.lang.Integer'),], doc: 'Stage') - method(name: 'options', type: 'Object', params: [body: 'Closure'], doc: 'Options') - method(name: 'timeout', type: 'Object', params: [time: int, body: 'Closure'], doc: 'Enforce time limit') - method(name: 'timeout', type: 'Object', params: [body: Closure], namedParams: [parameter(name: 'time', type: 'java.lang.Integer'), parameter(name: 'activity', type: 'boolean'), parameter(name: 'unit', type: 'java.util.concurrent.TimeUnit'),], doc: 'Enforce time limit') - method(name: 'timestamps', type: 'Object', params: [body: 'Closure'], doc: 'Timestamps') - method(name: 'tool', type: 'Object', params: [name: 'java.lang.String'], doc: 'Use a tool from a predefined Tool Installation') - method(name: 'tool', type: 'Object', namedParams: [parameter(name: 'name', type: 'java.lang.String'), parameter(name: 'type', type: 'java.lang.String'),], doc: 'Use a tool from a predefined Tool Installation') - method(name: 'unstable', type: 'Object', params: [message: 'java.lang.String'], doc: 'Set stage result to unstable') - method(name: 'waitUntil', type: 'Object', params: [body: 'Closure'], doc: 'Wait for condition') - method(name: 'warnError', type: 'Object', params: [message: String, body: 'Closure'], doc: 'Catch error and set build and stage result to unstable') - method(name: 'warnError', type: 'Object', params: [body: Closure], namedParams: [parameter(name: 'message', type: 'java.lang.String'), parameter(name: 'catchInterruptions', type: 'boolean'),], doc: 'Catch error and set build and stage result to unstable') - method(name: 'withCredentials', type: 'Object', params: [bindings: List, body: 'Closure'], doc: 'Bind credentials to variables') - method(name: 'string', type: 'Object', namedParams: [parameter(name: 'credentialsId', type: String), parameter(name: 'variable', type: String)], doc: 'Bind secret text credentials to variable') - method(name: 'withEnv', type: 'Object', params: [overrides: Map, body: 'Closure'], doc: 'Set environment variables') - method(name: 'ws', type: 'Object', params: [dir: String, body: 'Closure'], doc: 'Allocate workspace') - method(name: 'dockerFingerprintRun', type: 'Object', params: [containerId: 'java.lang.String'], doc: 'Advanced/Deprecated Record trace of a Docker image run in a container') - method(name: 'dockerFingerprintRun', type: 'Object', namedParams: [parameter(name: 'containerId', type: 'java.lang.String'), parameter(name: 'toolName', type: 'java.lang.String'),], doc: 'Record trace of a Docker image run in a container') - method(name: 'envVarsForTool', type: 'Object', namedParams: [parameter(name: 'toolId', type: 'java.lang.String'), parameter(name: 'toolVersion', type: 'java.lang.String'),], doc: 'Fetches the environment variables for a given tool in a list of \'FOO=bar\' strings suitable for the withEnv step.') - method(name: 'getContext', type: 'Object', params: [type: 'Map'], doc: 'Advanced/Deprecated Get contextual object from internal APIs') - method(name: 'podTemplate', type: 'Object', params: [body: Closure], namedParams: [parameter(name: 'label', type: 'java.lang.String'), parameter(name: 'name', type: 'java.lang.String'), parameter(name: 'activeDeadlineSeconds', type: 'int'), parameter(name: 'annotations', type: 'Map'), parameter(name: 'cloud', type: 'java.lang.String'), parameter(name: 'containers', type: 'Map'), parameter(name: 'envVars', type: 'Map'), parameter(name: 'idleMinutes', type: 'int'), parameter(name: 'imagePullSecrets', type: 'Map'), parameter(name: 'inheritFrom', type: 'java.lang.String'), parameter(name: 'instanceCap', type: 'int'), parameter(name: 'namespace', type: 'java.lang.String'), parameter(name: 'nodeSelector', type: 'java.lang.String'), parameter(name: 'nodeUsageMode', type: 'java.lang.String'), parameter(name: 'podRetention', type: 'Map'), parameter(name: 'serviceAccount', type: 'java.lang.String'), parameter(name: 'slaveConnectTimeout', type: 'int'), parameter(name: 'volumes', type: 'Map'), parameter(name: 'workingDir', type: 'java.lang.String'), parameter(name: 'workspaceVolume', type: 'Map'), parameter(name: 'yaml', type: 'java.lang.String'),], doc: 'Define a podTemplate to use in the kubernetes plugin') - method(name: 'withContext', type: 'Object', params: [context: Object, body: 'Closure'], doc: 'Advanced/Deprecated Use contextual object from internal APIs within a block') - method(name: 'httpRequest', type: 'jenkins.plugins.http_request.ResponseContentSupplier', params: [url:'java.lang.String'], doc: 'Perform an HTTP Request and return a response object') - method(name: 'httpRequest', type: 'jenkins.plugins.http_request.ResponseContentSupplier', namedParams: [parameter(name: 'url', type: 'java.lang.String'), parameter(name: 'acceptType', type: 'Map'), parameter(name: 'authentication', type: 'java.lang.String'), parameter(name: 'consoleLogResponseBody', type: 'java.lang.Boolean'), parameter(name: 'contentType', type: 'jenkins.plugins.http_request.MimeType'), parameter(name: 'customHeaders', type: 'java.util.List'), parameter(name: 'formData', type: 'java.util.List'), parameter(name: 'httpMode', type: 'jenkins.plugins.http_request.HttpMode'), parameter(name: 'httpProxy', type: 'java.lang.String'), parameter(name: 'ignoreSslErrors', type: 'boolean'), parameter(name: 'multipartName', type: 'java.lang.String'), parameter(name: 'outputFile', type: 'java.lang.String'), parameter(name: 'proxyAuthentication', type: 'java.lang.String'), parameter(name: 'quiet', type: 'java.lang.Boolean'), parameter(name: 'requestBody', type: 'java.lang.String'), parameter(name: 'responseHandle', type: 'Map'), parameter(name: 'timeout', type: 'java.lang.Integer'), parameter(name: 'uploadFile', type: 'java.lang.String'), parameter(name: 'useNtlm', type: 'boolean'), parameter(name: 'useSystemProperties', type: 'java.lang.Boolean'), parameter(name: 'validResponseCodes', type: 'java.lang.String'), parameter(name: 'validResponseContent', type: 'java.lang.String'), parameter(name: 'wrapAsMultipart', type: 'boolean'), ], doc: 'Perform an HTTP Request and return a response object') + method(name: 'stage', type: 'Object', params: [name: String, body: Closure], doc: 'Stage') + method(name: 'stage', type: 'Object', params: [body: Closure], namedParams: [parameter(name: 'name', type: String), parameter(name: 'concurrency', type: 'java.lang.Integer'),], doc: 'Stage') + method(name: 'timeout', type: 'Object', params: [time: 'java.lang.Integer', body: Closure], doc: 'Enforce time limit') + method(name: 'timeout', type: 'Object', params: [body: Closure], namedParams: [parameter(name: 'time', type: 'java.lang.Integer'), parameter(name: 'unit', type: 'java.util.concurrent.TimeUnit'),], doc: 'Enforce time limit') + method(name: 'tool', type: 'Object', params: [name: String], doc: 'Use a tool from a predefined Tool Installation') + method(name: 'tool', type: 'Object', namedParams: [parameter(name: 'name', type: String), parameter(name: 'type', type: String),], doc: 'Use a tool from a predefined Tool Installation') + method(name: 'waitUntil', type: 'Object', params: [body: Closure], doc: 'Wait for condition') + method(name: 'withEnv', type: 'Object', params: [overrides: List, body: Closure], doc: 'Set environment variables') + method(name: 'ws', type: 'Object', params: [dir: String, body: Closure], doc: 'Allocate workspace') + method(name: 'artifactoryPromoteBuild', type: 'Object', namedParams: [parameter(name: 'promotionConfig', type: Map), parameter(name: 'server', type: Map),], doc: 'Promote build') + method(name: 'catchError', type: 'Object', params: [body:'Closure'], doc: 'Catch error and set build result to failure') + method(name: 'catchError', type: 'Object', params: [body:Closure], namedParams: [parameter(name: 'buildResult', type: 'java.lang.String'), parameter(name: 'catchInterruptions', type: 'boolean'), parameter(name: 'message', type: 'java.lang.String'), parameter(name: 'stageResult', type: 'java.lang.String'), ], doc: 'Catch error and set build result to failure') + method(name: 'collectEnv', type: 'Object', params: [env: Map], doc: 'Advanced/Deprecated Collect environment variables and system properties') + method(name: 'dockerFingerprintRun', type: 'Object', params: [containerId: String], doc: 'Advanced/Deprecated Record trace of a Docker image run in a container') + method(name: 'dockerFingerprintRun', type: 'Object', namedParams: [parameter(name: 'containerId', type: String), parameter(name: 'toolName', type: String),], doc: 'Record trace of a Docker image run in a container') + method(name: 'envVarsForTool', type: 'Object', namedParams: [parameter(name: 'toolId', type: String), parameter(name: 'toolVersion', type: String),], doc: 'Fetches the environment variables for a given tool in a list of \'FOO=bar\' strings suitable for the withEnv step.') + method(name: 'getArtifactoryServer', type: 'Object', params: [artifactoryServerID: String], doc: 'Advanced/Deprecated Get Artifactory server from Jenkins config') + method(name: 'getContext', type: 'Object', params: [type: Map], doc: 'Advanced/Deprecated Get contextual object from internal APIs') + method(name: 'newBuildInfo', type: 'Object', params: [:], doc: 'Advanced/Deprecated New buildInfo') + method(name: 'newGradleBuild', type: 'Object', params: [:], doc: 'Advanced/Deprecated New Artifactory gradle executor') + method(name: 'newMavenBuild', type: 'Object', params: [:], doc: 'Advanced/Deprecated New Artifactory maven') + method(name: 'podTemplate', type: 'Object', params: [body: Closure], namedParams: [parameter(name: 'label', type: String), parameter(name: 'name', type: String), parameter(name: 'cloud', type: String), parameter(name: 'containers', type: Map), parameter(name: 'inheritFrom', type: String), parameter(name: 'instanceCap', type: 'int'), parameter(name: 'nodeSelector', type: String), parameter(name: 'serviceAccount', type: String), parameter(name: 'volumes', type: Map), parameter(name: 'workingDir', type: String),], doc: 'Define a podTemplate to use in the kubernetes plugin') + method(name: 'withContext', type: 'Object', params: [context: Object, body: Closure], doc: 'Advanced/Deprecated Use contextual object from internal APIs within a block') + method(name: 'xrayScanBuild', type: 'Object', namedParams: [parameter(name: 'xrayScanConfig', type: Map), parameter(name: 'server', type: Map),], doc: 'Xray build scanning') + property(name: 'openshift', type: 'com.openshift.jenkins.plugins.pipeline.OpenShiftGlobalVariable') property(name: 'docker', type: 'org.jenkinsci.plugins.docker.workflow.DockerDSL') property(name: 'pipeline', type: 'org.jenkinsci.plugins.pipeline.modeldefinition.ModelStepLoader') property(name: 'env', type: 'org.jenkinsci.plugins.workflow.cps.EnvActionImpl.Binder') property(name: 'params', type: 'org.jenkinsci.plugins.workflow.cps.ParamsVariable') property(name: 'currentBuild', type: 'org.jenkinsci.plugins.workflow.cps.RunWrapperBinder') property(name: 'scm', type: 'org.jenkinsci.plugins.workflow.multibranch.SCMVar') + property(name: 'Artifactory', type: 'org.jfrog.hudson.pipeline.dsl.ArtifactoryDSL') + property(name: 'cleanPreNonProdAppFromOse', type: 'org.jenkinsci.plugins.workflow.cps.global.UserDefinedGlobalVariable') + property(name: 'cleanPreNonProdAppFromOseNoCreds', type: 'org.jenkinsci.plugins.workflow.cps.global.UserDefinedGlobalVariable') + property(name: 'dtrDeleteCurrentBuildImageTag', type: 'org.jenkinsci.plugins.workflow.cps.global.UserDefinedGlobalVariable') + property(name: 'dtrDeleteOldImageTags', type: 'org.jenkinsci.plugins.workflow.cps.global.UserDefinedGlobalVariable') + property(name: 'getOseServiceRoute', type: 'org.jenkinsci.plugins.workflow.cps.global.UserDefinedGlobalVariable') + property(name: 'oseDeleteOldReplicationControllers', type: 'org.jenkinsci.plugins.workflow.cps.global.UserDefinedGlobalVariable') + property(name: 'setupJavaMavenOseDockerBuildEnvironment', type: 'org.jenkinsci.plugins.workflow.cps.global.UserDefinedGlobalVariable') + property(name: 'updatePath', type: 'org.jenkinsci.plugins.workflow.cps.global.UserDefinedGlobalVariable') + property(name: 'verifyApplicationIsInitialized', type: 'org.jenkinsci.plugins.workflow.cps.global.UserDefinedGlobalVariable') + property(name: 'verifyApplicationIsInitializedNoCreds', type: 'org.jenkinsci.plugins.workflow.cps.global.UserDefinedGlobalVariable') } +//Steps that require a node context +def closures = context(scope: closureScope(null)) +contributor(closures) { + // What thinpollgs can be inside a node or pipeline + if (enclosingCall('node') || enclosingCall("pipeline")) { + method(name: '_OcAction', type: 'Object', namedParams: [parameter(name: 'server', type: String), parameter(name: 'project', type: String), parameter(name: 'verb', type: String), parameter(name: 'verbArgs', type: 'java.util.List'), parameter(name: 'userArgs', type: 'java.util.List'), parameter(name: 'options', type: 'java.util.List'), parameter(name: 'verboseOptions', type: 'java.util.List'), parameter(name: 'token', type: String), parameter(name: 'streamStdOutToConsolePrefix', type: String), parameter(name: 'reference', type: Map), parameter(name: 'logLevel', type: 'int'),], doc: 'Internal utility function for OpenShift DSL') + method(name: '_OcContextInit', type: 'Object', params: [:], doc: 'Advanced/Deprecated Internal utility function for OpenShift DSL') + method(name: '_OcWatch', type: 'Object', params: [body: Closure], namedParams: [parameter(name: 'server', type: String), parameter(name: 'project', type: String), parameter(name: 'verb', type: String), parameter(name: 'verbArgs', type: 'java.util.List'), parameter(name: 'userArgs', type: 'java.util.List'), parameter(name: 'options', type: 'java.util.List'), parameter(name: 'verboseOptions', type: 'java.util.List'), parameter(name: 'token', type: String), parameter(name: 'logLevel', type: 'int'),], doc: 'Internal utility function for OpenShift DSL') + method(name: 'agent', type: 'Object', params: [body: Closure], doc: 'Label expression to select agents') + method(name: 'archive', type: 'Object', namedParams: [parameter(name: 'includes', type: String), parameter(name: 'excludes', type: String),], doc: 'Archive artifacts') + method(name: 'archive', type: 'Object', params: [includes: String], doc: 'Advanced/Deprecated Archive artifacts') + method(name: 'artifactoryDownload', type: 'Object', namedParams: [parameter(name: 'spec', type: String), parameter(name: 'buildInfo', type: Map), parameter(name: 'server', type: Map),], doc: 'Download artifacts') + method(name: 'ArtifactoryGradleBuild', type: 'Object', namedParams: [parameter(name: 'gradleBuild', type: Map), parameter(name: 'tool', type: String), parameter(name: 'rootDir', type: String), parameter(name: 'buildFile', type: String), parameter(name: 'tasks', type: String), parameter(name: 'switches', type: String), parameter(name: 'useWrapper', type: boolean), parameter(name: 'buildInfo', type: Map), parameter(name: 'usesPlugin', type: boolean),], doc: 'run Artifactory gradle') + method(name: 'ArtifactoryMavenBuild', type: 'Object', namedParams: [parameter(name: 'mavenBuild', type: Map), parameter(name: 'tool', type: String), parameter(name: 'pom', type: String), parameter(name: 'goals', type: String), parameter(name: 'opts', type: String), parameter(name: 'buildInfo', type: Map),], doc: 'run Artifactory maven') + method(name: 'artifactoryUpload', type: 'Object', namedParams: [parameter(name: 'spec', type: String), parameter(name: 'buildInfo', type: Map), parameter(name: 'server', type: Map),], doc: 'Upload artifacts') + method(name: 'bat', type: 'Object', namedParams: [parameter(name: 'script', type: String), parameter(name: 'encoding', type: String), parameter(name: 'returnStatus', type: boolean), parameter(name: 'returnStdout', type: boolean),], doc: 'Windows Batch Script') + method(name: 'build', type: 'Object', namedParams: [parameter(name: 'job', type: String), parameter(name: 'parameters', type: Map), parameter(name: 'propagate', type: boolean), parameter(name: 'quietPeriod', type: 'java.lang.Integer'), parameter(name: 'wait', type: boolean),], doc: 'Build a job') + method(name: 'catchError', type: 'Object', params: [body: Closure], doc: 'Advanced/Deprecated Catch error and set build result') + method(name: 'checkout', type: 'Object', namedParams: [parameter(name: 'scm', type: Map), parameter(name: 'changelog', type: boolean), parameter(name: 'poll', type: boolean),], doc: 'General SCM') + method(name: 'container', type: 'Object', params: [body: Closure], namedParams: [parameter(name: 'name', type: String), parameter(name: 'cloud', type: String),], doc: 'Run build steps in a container') + method(name: 'deleteDir', type: 'Object', params: [:], doc: 'Recursively delete the current directory from the workspace') + method(name: 'dir', type: 'Object', params: [path: String, body: Closure], doc: 'Change current directory') + method(name: 'dockerFingerprintFrom', type: 'Object', namedParams: [parameter(name: 'dockerfile', type: String), parameter(name: 'image', type: String), parameter(name: 'toolName', type: String),], doc: 'Record trace of a Docker image used in FROM') + method(name: 'dockerFingerprintRun', type: 'Object', params: [containerId: String], doc: 'Advanced/Deprecated Record trace of a Docker image run in a container') + method(name: 'dockerPullStep', type: 'Object', namedParams: [parameter(name: 'image', type: String), parameter(name: 'credentialsConfig', type: Map), parameter(name: 'host', type: String), parameter(name: 'buildInfo', type: Map),], doc: 'Artifactory docker pull') + method(name: 'dockerPushStep', type: 'Object', namedParams: [parameter(name: 'image', type: String), parameter(name: 'credentialsConfig', type: Map), parameter(name: 'host', type: String), parameter(name: 'targetRepo', type: String), parameter(name: 'buildInfo', type: Map),], doc: 'Artifactory docker push') + method(name: 'ec2', type: 'Object', namedParams: [parameter(name: 'cloud', type: String), parameter(name: 'template', type: String),], doc: 'Cloud template provisioning') + method(name: 'echo', type: 'Object', params: [message: String], doc: 'Print Message') + method(name: 'emailext', type: 'Object', namedParams: [parameter(name: 'subject', type: String), parameter(name: 'body', type: String), parameter(name: 'attachLog', type: boolean), parameter(name: 'attachmentsPattern', type: String), parameter(name: 'compressLog', type: boolean), parameter(name: 'mimeType', type: String), parameter(name: 'recipientProviders', type: Map), parameter(name: 'replyTo', type: String), parameter(name: 'to', type: String),], doc: 'Extended Email') + method(name: 'environment', type: 'Object', params: [body: Closure]) + method(name: 'envVarsForTool', type: 'Object', namedParams: [parameter(name: 'toolId', type: String), parameter(name: 'toolVersion', type: String),], doc: 'Fetches the environment variables for a given tool in a list of \'FOO=bar\' strings suitable for the withEnv step.') + method(name: 'error', type: 'Object', params: [message: String], doc: 'Error signal') + method(name: 'fileExists', type: 'Object', params: [file: String], doc: 'Verify if file exists in workspace') + method(name: 'findFiles', type: 'Object', namedParams: [parameter(name: 'glob', type: String),], doc: 'Find files in the workspace') + method(name: 'getContext', type: 'Object', params: [type: Map], doc: 'Advanced/Deprecated Get contextual object from internal APIs') + method(name: 'git', type: 'Object', namedParams: [parameter(name: 'url', type: String), parameter(name: 'branch', type: String), parameter(name: 'changelog', type: boolean), parameter(name: 'credentialsId', type: String), parameter(name: 'poll', type: boolean),], doc: 'Git') + method(name: 'input', type: 'Object', namedParams: [parameter(name: 'message', type: String), parameter(name: 'id', type: String), parameter(name: 'ok', type: String), parameter(name: 'parameters', type: Map), parameter(name: 'submitter', type: String), parameter(name: 'submitterParameter', type: String),], doc: 'Wait for interactive input') + method(name: 'isUnix', type: 'Object', params: [:], doc: 'Checks if running on a Unix-like node') + method(name: 'jiraAddComment', type: 'Object', namedParams: [parameter(name: 'idOrKey', type: 'java.lang.String'), parameter(name: 'comment', type: 'java.lang.String'), parameter(name: 'auditLog', type: 'boolean'), parameter(name: 'failOnError', type: 'boolean'), parameter(name: 'input', type: 'java.lang.Object'), parameter(name: 'queryParams', type: 'java.util.Map'), parameter(name: 'site', type: 'java.lang.String'), ], doc: 'JIRA Steps: Add Comment') + method(name: 'jiraAddWatcher', type: 'Object', namedParams: [parameter(name: 'idOrKey', type: 'java.lang.String'), parameter(name: 'userName', type: 'java.lang.String'), parameter(name: 'auditLog', type: 'boolean'), parameter(name: 'failOnError', type: 'boolean'), parameter(name: 'queryParams', type: 'java.util.Map'), parameter(name: 'site', type: 'java.lang.String'), ], doc: 'JIRA Steps: Add Watcher') + method(name: 'jiraAssignIssue', type: 'Object', namedParams: [parameter(name: 'idOrKey', type: 'java.lang.String'), parameter(name: 'userName', type: 'java.lang.String'), parameter(name: 'accountId', type: 'java.lang.String'), parameter(name: 'auditLog', type: 'boolean'), parameter(name: 'failOnError', type: 'boolean'), parameter(name: 'queryParams', type: 'java.util.Map'), parameter(name: 'site', type: 'java.lang.String'), ], doc: 'JIRA Steps: Assign Issue') + method(name: 'jiraAssignableUserSearch', type: 'Object', namedParams: [parameter(name: 'project', type: 'java.lang.String'), parameter(name: 'issueKey', type: 'java.lang.String'), parameter(name: 'auditLog', type: 'boolean'), parameter(name: 'failOnError', type: 'boolean'), parameter(name: 'maxResults', type: 'int'), parameter(name: 'queryParams', type: 'java.util.Map'), parameter(name: 'queryStr', type: 'java.lang.String'), parameter(name: 'site', type: 'java.lang.String'), parameter(name: 'startAt', type: 'int'), ], doc: 'JIRA Steps: Searches assignable JIRA Users by username, name or email address for the given project/issueKey') + method(name: 'jiraComment', type: 'Object', namedParams: [parameter(name: 'issueKey', type: 'java.lang.String'), parameter(name: 'body', type: 'java.lang.String'), ], doc: 'Jira: Add a comment to issue(s)') + method(name: 'jiraDeleteAttachment', type: 'Object', params: [id:'java.lang.String'], doc: 'JIRA Steps: Delete Attachment') + method(name: 'jiraDeleteAttachment', type: 'Object', namedParams: [parameter(name: 'id', type: 'java.lang.String'), parameter(name: 'auditLog', type: 'boolean'), parameter(name: 'failOnError', type: 'boolean'), parameter(name: 'queryParams', type: 'java.util.Map'), parameter(name: 'site', type: 'java.lang.String'), ], doc: 'JIRA Steps: Delete Attachment') + method(name: 'jiraDeleteIssueLink', type: 'Object', params: [id:'java.lang.String'], doc: 'JIRA Steps: Delete IssueLink') + method(name: 'jiraDeleteIssueLink', type: 'Object', namedParams: [parameter(name: 'id', type: 'java.lang.String'), parameter(name: 'auditLog', type: 'boolean'), parameter(name: 'failOnError', type: 'boolean'), parameter(name: 'queryParams', type: 'java.util.Map'), parameter(name: 'site', type: 'java.lang.String'), ], doc: 'JIRA Steps: Delete IssueLink') + method(name: 'jiraDeleteIssueRemoteLink', type: 'Object', namedParams: [parameter(name: 'idOrKey', type: 'java.lang.String'), parameter(name: 'linkId', type: 'java.lang.String'), parameter(name: 'auditLog', type: 'boolean'), parameter(name: 'failOnError', type: 'boolean'), parameter(name: 'queryParams', type: 'java.util.Map'), parameter(name: 'site', type: 'java.lang.String'), ], doc: 'JIRA Steps: Delete Issue\'s Remote Link by linkId.') + method(name: 'jiraDeleteIssueRemoteLinks', type: 'Object', namedParams: [parameter(name: 'idOrKey', type: 'java.lang.String'), parameter(name: 'globalId', type: 'java.lang.String'), parameter(name: 'auditLog', type: 'boolean'), parameter(name: 'failOnError', type: 'boolean'), parameter(name: 'queryParams', type: 'java.util.Map'), parameter(name: 'site', type: 'java.lang.String'), ], doc: 'JIRA Steps: Delete Issue\'s Remote Links by globalId.') + method(name: 'jiraDownloadAttachment', type: 'Object', namedParams: [parameter(name: 'id', type: 'java.lang.String'), parameter(name: 'file', type: 'java.lang.String'), parameter(name: 'override', type: 'boolean'), parameter(name: 'auditLog', type: 'boolean'), parameter(name: 'failOnError', type: 'boolean'), parameter(name: 'queryParams', type: 'java.util.Map'), parameter(name: 'site', type: 'java.lang.String'), ], doc: 'JIRA Steps: Download a file to workspace (directory is optional)') + method(name: 'jiraEditComment', type: 'Object', namedParams: [parameter(name: 'idOrKey', type: 'java.lang.String'), parameter(name: 'commentId', type: 'java.lang.String'), parameter(name: 'comment', type: 'java.lang.String'), parameter(name: 'auditLog', type: 'boolean'), parameter(name: 'failOnError', type: 'boolean'), parameter(name: 'input', type: 'java.lang.Object'), parameter(name: 'queryParams', type: 'java.util.Map'), parameter(name: 'site', type: 'java.lang.String'), ], doc: 'JIRA Steps: Edit Issue Comment') + method(name: 'jiraEditComponent', type: 'Object', namedParams: [parameter(name: 'id', type: 'java.lang.String'), parameter(name: 'component', type: 'java.lang.Object'), parameter(name: 'auditLog', type: 'boolean'), parameter(name: 'failOnError', type: 'boolean'), parameter(name: 'queryParams', type: 'java.util.Map'), parameter(name: 'site', type: 'java.lang.String'), ], doc: 'JIRA Steps: Edit Component') + method(name: 'jiraEditIssue', type: 'Object', namedParams: [parameter(name: 'idOrKey', type: 'java.lang.String'), parameter(name: 'issue', type: 'java.lang.Object'), parameter(name: 'auditLog', type: 'boolean'), parameter(name: 'failOnError', type: 'boolean'), parameter(name: 'queryParams', type: 'java.util.Map'), parameter(name: 'site', type: 'java.lang.String'), ], doc: 'JIRA Steps: Edit Issue') + method(name: 'jiraEditVersion', type: 'Object', namedParams: [parameter(name: 'id', type: 'java.lang.String'), parameter(name: 'version', type: 'java.lang.Object'), parameter(name: 'auditLog', type: 'boolean'), parameter(name: 'failOnError', type: 'boolean'), parameter(name: 'queryParams', type: 'java.util.Map'), parameter(name: 'site', type: 'java.lang.String'), ], doc: 'JIRA Steps: Edit Version') + method(name: 'jiraGetAttachmentInfo', type: 'Object', params: [id:'java.lang.String'], doc: 'JIRA Steps: Get Attachment Info') + method(name: 'jiraGetAttachmentInfo', type: 'Object', namedParams: [parameter(name: 'id', type: 'java.lang.String'), parameter(name: 'auditLog', type: 'boolean'), parameter(name: 'failOnError', type: 'boolean'), parameter(name: 'queryParams', type: 'java.util.Map'), parameter(name: 'site', type: 'java.lang.String'), ], doc: 'JIRA Steps: Get Attachment Info') + method(name: 'jiraGetComment', type: 'Object', namedParams: [parameter(name: 'idOrKey', type: 'java.lang.String'), parameter(name: 'commentId', type: 'java.lang.String'), parameter(name: 'auditLog', type: 'boolean'), parameter(name: 'failOnError', type: 'boolean'), parameter(name: 'queryParams', type: 'java.util.Map'), parameter(name: 'site', type: 'java.lang.String'), ], doc: 'JIRA Steps: Get Issue Comment') + method(name: 'jiraGetComments', type: 'Object', params: [idOrKey:'java.lang.String'], doc: 'JIRA Steps: Get Issue Comments') + method(name: 'jiraGetComments', type: 'Object', namedParams: [parameter(name: 'idOrKey', type: 'java.lang.String'), parameter(name: 'auditLog', type: 'boolean'), parameter(name: 'failOnError', type: 'boolean'), parameter(name: 'queryParams', type: 'java.util.Map'), parameter(name: 'site', type: 'java.lang.String'), ], doc: 'JIRA Steps: Get Issue Comments') + method(name: 'jiraGetComponent', type: 'Object', params: [id:'java.lang.String'], doc: 'JIRA Steps: Get Component') + method(name: 'jiraGetComponent', type: 'Object', namedParams: [parameter(name: 'id', type: 'java.lang.String'), parameter(name: 'auditLog', type: 'boolean'), parameter(name: 'failOnError', type: 'boolean'), parameter(name: 'queryParams', type: 'java.util.Map'), parameter(name: 'site', type: 'java.lang.String'), ], doc: 'JIRA Steps: Get Component') + method(name: 'jiraGetComponentIssueCount', type: 'Object', params: [id:'java.lang.String'], doc: 'JIRA Steps: Get Component Issue Count') + method(name: 'jiraGetComponentIssueCount', type: 'Object', namedParams: [parameter(name: 'id', type: 'java.lang.String'), parameter(name: 'auditLog', type: 'boolean'), parameter(name: 'failOnError', type: 'boolean'), parameter(name: 'queryParams', type: 'java.util.Map'), parameter(name: 'site', type: 'java.lang.String'), ], doc: 'JIRA Steps: Get Component Issue Count') + method(name: 'jiraGetFields', type: 'Object', params: [:], doc: 'JIRA Steps: Get Fields') + method(name: 'jiraGetFields', type: 'Object', namedParams: [parameter(name: 'auditLog', type: 'boolean'), parameter(name: 'failOnError', type: 'boolean'), parameter(name: 'queryParams', type: 'java.util.Map'), parameter(name: 'site', type: 'java.lang.String'), ], doc: 'JIRA Steps: Get Fields') + method(name: 'jiraGetIssue', type: 'Object', params: [idOrKey:'java.lang.String'], doc: 'JIRA Steps: Get Issue') + method(name: 'jiraGetIssue', type: 'Object', namedParams: [parameter(name: 'idOrKey', type: 'java.lang.String'), parameter(name: 'auditLog', type: 'boolean'), parameter(name: 'failOnError', type: 'boolean'), parameter(name: 'queryParams', type: 'java.util.Map'), parameter(name: 'site', type: 'java.lang.String'), ], doc: 'JIRA Steps: Get Issue') + method(name: 'jiraGetIssueLink', type: 'Object', params: [id:'java.lang.String'], doc: 'JIRA Steps: Get IssueLink') + method(name: 'jiraGetIssueLink', type: 'Object', namedParams: [parameter(name: 'id', type: 'java.lang.String'), parameter(name: 'auditLog', type: 'boolean'), parameter(name: 'failOnError', type: 'boolean'), parameter(name: 'queryParams', type: 'java.util.Map'), parameter(name: 'site', type: 'java.lang.String'), ], doc: 'JIRA Steps: Get IssueLink') + method(name: 'jiraGetIssueLinkTypes', type: 'Object', params: [:], doc: 'JIRA Steps: Get Issue Link Types') + method(name: 'jiraGetIssueLinkTypes', type: 'Object', namedParams: [parameter(name: 'auditLog', type: 'boolean'), parameter(name: 'failOnError', type: 'boolean'), parameter(name: 'queryParams', type: 'java.util.Map'), parameter(name: 'site', type: 'java.lang.String'), ], doc: 'JIRA Steps: Get Issue Link Types') + method(name: 'jiraGetIssueRemoteLink', type: 'Object', namedParams: [parameter(name: 'idOrKey', type: 'java.lang.String'), parameter(name: 'linkId', type: 'java.lang.String'), parameter(name: 'auditLog', type: 'boolean'), parameter(name: 'failOnError', type: 'boolean'), parameter(name: 'queryParams', type: 'java.util.Map'), parameter(name: 'site', type: 'java.lang.String'), ], doc: 'JIRA Steps: Get Issue\'s Remote Link by linkId.') + method(name: 'jiraGetIssueRemoteLinks', type: 'Object', namedParams: [parameter(name: 'idOrKey', type: 'java.lang.String'), parameter(name: 'globalId', type: 'java.lang.String'), parameter(name: 'auditLog', type: 'boolean'), parameter(name: 'failOnError', type: 'boolean'), parameter(name: 'queryParams', type: 'java.util.Map'), parameter(name: 'site', type: 'java.lang.String'), ], doc: 'JIRA Steps: Get Issue\'s Remote Links by globalId.') + method(name: 'jiraGetIssueTransitions', type: 'Object', params: [idOrKey:'java.lang.String'], doc: 'JIRA Steps: Get Issue Transitions') + method(name: 'jiraGetIssueTransitions', type: 'Object', namedParams: [parameter(name: 'idOrKey', type: 'java.lang.String'), parameter(name: 'auditLog', type: 'boolean'), parameter(name: 'failOnError', type: 'boolean'), parameter(name: 'queryParams', type: 'java.util.Map'), parameter(name: 'site', type: 'java.lang.String'), ], doc: 'JIRA Steps: Get Issue Transitions') + method(name: 'jiraGetIssueWatches', type: 'Object', params: [idOrKey:'java.lang.String'], doc: 'JIRA Steps: Get Issue Watches') + method(name: 'jiraGetIssueWatches', type: 'Object', namedParams: [parameter(name: 'idOrKey', type: 'java.lang.String'), parameter(name: 'auditLog', type: 'boolean'), parameter(name: 'failOnError', type: 'boolean'), parameter(name: 'queryParams', type: 'java.util.Map'), parameter(name: 'site', type: 'java.lang.String'), ], doc: 'JIRA Steps: Get Issue Watches') + method(name: 'jiraGetProject', type: 'Object', params: [idOrKey:'java.lang.String'], doc: 'JIRA Steps: Get Project') + method(name: 'jiraGetProject', type: 'Object', namedParams: [parameter(name: 'idOrKey', type: 'java.lang.String'), parameter(name: 'auditLog', type: 'boolean'), parameter(name: 'failOnError', type: 'boolean'), parameter(name: 'queryParams', type: 'java.util.Map'), parameter(name: 'site', type: 'java.lang.String'), ], doc: 'JIRA Steps: Get Project') + method(name: 'jiraGetProjectComponents', type: 'Object', params: [idOrKey:'java.lang.String'], doc: 'JIRA Steps: Get Project Components') + method(name: 'jiraGetProjectComponents', type: 'Object', namedParams: [parameter(name: 'idOrKey', type: 'java.lang.String'), parameter(name: 'auditLog', type: 'boolean'), parameter(name: 'failOnError', type: 'boolean'), parameter(name: 'queryParams', type: 'java.util.Map'), parameter(name: 'site', type: 'java.lang.String'), ], doc: 'JIRA Steps: Get Project Components') + method(name: 'jiraGetProjectStatuses', type: 'Object', params: [idOrKey:'java.lang.String'], doc: 'JIRA Steps: Get Project Statuses') + method(name: 'jiraGetProjectStatuses', type: 'Object', namedParams: [parameter(name: 'idOrKey', type: 'java.lang.String'), parameter(name: 'auditLog', type: 'boolean'), parameter(name: 'failOnError', type: 'boolean'), parameter(name: 'queryParams', type: 'java.util.Map'), parameter(name: 'site', type: 'java.lang.String'), ], doc: 'JIRA Steps: Get Project Statuses') + method(name: 'jiraGetProjectVersions', type: 'Object', params: [idOrKey:'java.lang.String'], doc: 'JIRA Steps: Get Project Versions') + method(name: 'jiraGetProjectVersions', type: 'Object', namedParams: [parameter(name: 'idOrKey', type: 'java.lang.String'), parameter(name: 'auditLog', type: 'boolean'), parameter(name: 'failOnError', type: 'boolean'), parameter(name: 'queryParams', type: 'java.util.Map'), parameter(name: 'site', type: 'java.lang.String'), ], doc: 'JIRA Steps: Get Project Versions') + method(name: 'jiraGetProjects', type: 'Object', params: [:], doc: 'JIRA Steps: Get Projects') + method(name: 'jiraGetProjects', type: 'Object', namedParams: [parameter(name: 'auditLog', type: 'boolean'), parameter(name: 'failOnError', type: 'boolean'), parameter(name: 'queryParams', type: 'java.util.Map'), parameter(name: 'site', type: 'java.lang.String'), ], doc: 'JIRA Steps: Get Projects') + method(name: 'jiraGetServerInfo', type: 'Object', params: [:], doc: 'JIRA Steps: Get Server Info') + method(name: 'jiraGetServerInfo', type: 'Object', namedParams: [parameter(name: 'auditLog', type: 'boolean'), parameter(name: 'failOnError', type: 'boolean'), parameter(name: 'queryParams', type: 'java.util.Map'), parameter(name: 'site', type: 'java.lang.String'), ], doc: 'JIRA Steps: Get Server Info') + method(name: 'jiraGetVersion', type: 'Object', params: [id:'java.lang.String'], doc: 'JIRA Steps: Get Version') + method(name: 'jiraGetVersion', type: 'Object', namedParams: [parameter(name: 'id', type: 'java.lang.String'), parameter(name: 'auditLog', type: 'boolean'), parameter(name: 'failOnError', type: 'boolean'), parameter(name: 'queryParams', type: 'java.util.Map'), parameter(name: 'site', type: 'java.lang.String'), ], doc: 'JIRA Steps: Get Version') + method(name: 'jiraIssueSelector', type: 'Object', params: [:], doc: 'Jira: Issue selector') + method(name: 'jiraIssueSelector', type: 'Object', namedParams: [parameter(name: 'issueSelector', type: 'Map'), ], doc: 'Jira: Issue selector') + method(name: 'jiraJqlSearch', type: 'Object', params: [jql:'java.lang.String'], doc: 'JIRA Steps: JQL Search') + method(name: 'jiraJqlSearch', type: 'Object', namedParams: [parameter(name: 'jql', type: 'java.lang.String'), parameter(name: 'auditLog', type: 'boolean'), parameter(name: 'failOnError', type: 'boolean'), parameter(name: 'fields', type: 'java.lang.Object'), parameter(name: 'maxResults', type: 'int'), parameter(name: 'queryParams', type: 'java.util.Map'), parameter(name: 'site', type: 'java.lang.String'), parameter(name: 'startAt', type: 'int'), ], doc: 'JIRA Steps: JQL Search') + method(name: 'jiraLinkIssues', type: 'Object', namedParams: [parameter(name: 'type', type: 'java.lang.String'), parameter(name: 'inwardKey', type: 'java.lang.String'), parameter(name: 'outwardKey', type: 'java.lang.String'), parameter(name: 'auditLog', type: 'boolean'), parameter(name: 'comment', type: 'java.lang.String'), parameter(name: 'failOnError', type: 'boolean'), parameter(name: 'queryParams', type: 'java.util.Map'), parameter(name: 'site', type: 'java.lang.String'), ], doc: 'JIRA Steps: Link Issues') + method(name: 'jiraNewComponent', type: 'Object', params: [component:'java.lang.Object'], doc: 'JIRA Steps: Create New Component') + method(name: 'jiraNewComponent', type: 'Object', namedParams: [parameter(name: 'component', type: 'java.lang.Object'), parameter(name: 'auditLog', type: 'boolean'), parameter(name: 'failOnError', type: 'boolean'), parameter(name: 'queryParams', type: 'java.util.Map'), parameter(name: 'site', type: 'java.lang.String'), ], doc: 'JIRA Steps: Create New Component') + method(name: 'jiraNewIssue', type: 'Object', params: [issue:'Map'], doc: 'JIRA Steps: Create New Issue') + method(name: 'jiraNewIssue', type: 'Object', namedParams: [parameter(name: 'issue', type: 'Map'), parameter(name: 'auditLog', type: 'boolean'), parameter(name: 'failOnError', type: 'boolean'), parameter(name: 'queryParams', type: 'java.util.Map'), parameter(name: 'site', type: 'java.lang.String'), ], doc: 'JIRA Steps: Create New Issue') + method(name: 'jiraNewIssueRemoteLink', type: 'Object', namedParams: [parameter(name: 'idOrKey', type: 'java.lang.String'), parameter(name: 'remoteLink', type: 'java.lang.Object'), parameter(name: 'auditLog', type: 'boolean'), parameter(name: 'failOnError', type: 'boolean'), parameter(name: 'queryParams', type: 'java.util.Map'), parameter(name: 'site', type: 'java.lang.String'), ], doc: 'JIRA Steps: Create new remote link for given issue.') + method(name: 'jiraNewIssues', type: 'Object', params: [issues:'Map'], doc: 'JIRA Steps: Create New Issues') + method(name: 'jiraNewIssues', type: 'Object', namedParams: [parameter(name: 'issues', type: 'Map'), parameter(name: 'auditLog', type: 'boolean'), parameter(name: 'failOnError', type: 'boolean'), parameter(name: 'queryParams', type: 'java.util.Map'), parameter(name: 'site', type: 'java.lang.String'), ], doc: 'JIRA Steps: Create New Issues') + method(name: 'jiraNewVersion', type: 'Object', params: [version:'java.lang.Object'], doc: 'JIRA Steps: Create New Version') + method(name: 'jiraNewVersion', type: 'Object', namedParams: [parameter(name: 'version', type: 'java.lang.Object'), parameter(name: 'auditLog', type: 'boolean'), parameter(name: 'failOnError', type: 'boolean'), parameter(name: 'queryParams', type: 'java.util.Map'), parameter(name: 'site', type: 'java.lang.String'), ], doc: 'JIRA Steps: Create New Version') + method(name: 'jiraNotifyIssue', type: 'Object', namedParams: [parameter(name: 'idOrKey', type: 'java.lang.String'), parameter(name: 'notify', type: 'java.lang.Object'), parameter(name: 'auditLog', type: 'boolean'), parameter(name: 'failOnError', type: 'boolean'), parameter(name: 'queryParams', type: 'java.util.Map'), parameter(name: 'site', type: 'java.lang.String'), ], doc: 'JIRA Steps: Notify Issue') + method(name: 'jiraSearch', type: 'Object', params: [jql:'java.lang.String'], doc: 'Jira: Search issues') + method(name: 'jiraTransitionIssue', type: 'Object', namedParams: [parameter(name: 'idOrKey', type: 'java.lang.String'), parameter(name: 'input', type: 'java.lang.Object'), parameter(name: 'auditLog', type: 'boolean'), parameter(name: 'failOnError', type: 'boolean'), parameter(name: 'queryParams', type: 'java.util.Map'), parameter(name: 'site', type: 'java.lang.String'), ], doc: 'JIRA Steps: Transition Issue') + method(name: 'jiraUploadAttachment', type: 'Object', namedParams: [parameter(name: 'idOrKey', type: 'java.lang.String'), parameter(name: 'file', type: 'java.lang.String'), parameter(name: 'auditLog', type: 'boolean'), parameter(name: 'failOnError', type: 'boolean'), parameter(name: 'queryParams', type: 'java.util.Map'), parameter(name: 'site', type: 'java.lang.String'), ], doc: 'JIRA Steps: Attach a file from workspace to an issue') + method(name: 'jiraUserSearch', type: 'Object', params: [queryStr:'java.lang.String'], doc: 'JIRA Steps: Search Active JIRA Users by username, name or email address.') + method(name: 'jiraUserSearch', type: 'Object', namedParams: [parameter(name: 'queryStr', type: 'java.lang.String'), parameter(name: 'auditLog', type: 'boolean'), parameter(name: 'failOnError', type: 'boolean'), parameter(name: 'maxResults', type: 'int'), parameter(name: 'queryParams', type: 'java.util.Map'), parameter(name: 'site', type: 'java.lang.String'), parameter(name: 'startAt', type: 'int'), ], doc: 'JIRA Steps: Search Active JIRA Users by username, name or email address.') + method(name: 'library', type: 'Object', namedParams: [parameter(name: 'identifier', type: String), parameter(name: 'changelog', type: 'java.lang.Boolean'), parameter(name: 'retriever', type: Map),], doc: 'Load a shared library on the fly') + method(name: 'libraryResource', type: 'Object', params: [resource: String], doc: 'Load a resource file from a shared library') + method(name: 'load', type: 'Object', params: [path: String], doc: 'Evaluate a Groovy source file into the Pipeline script') + method(name: 'mail', type: 'Object', namedParams: [parameter(name: 'subject', type: String), parameter(name: 'body', type: String), parameter(name: 'bcc', type: String), parameter(name: 'cc', type: String), parameter(name: 'charset', type: String), parameter(name: 'from', type: String), parameter(name: 'mimeType', type: String), parameter(name: 'replyTo', type: String), parameter(name: 'to', type: String),], doc: 'Mail') + method(name: 'MavenDescriptorStep', type: 'Object', namedParams: [parameter(name: 'pomFile', type: String), parameter(name: 'version', type: String), parameter(name: 'versionPerModule', type: Map), parameter(name: 'failOnSnapshot', type: boolean), parameter(name: 'dryRun', type: boolean),], doc: 'Get Artifactory Maven descriptor') + method(name: 'milestone', type: 'Object', namedParams: [parameter(name: 'ordinal', type: 'java.lang.Integer'), parameter(name: 'label', type: String),], doc: 'The milestone step forces all builds to go through in order') + method(name: 'newArtifactoryServer', type: 'Object', namedParams: [parameter(name: 'url', type: String), parameter(name: 'username', type: String), parameter(name: 'password', type: String), parameter(name: 'credentialsId', type: String),], doc: 'Returns new Artifactory server') + method(name: 'node', type: 'Object', params: [label: String, body: Closure], doc: 'Allocate node') + method(name: 'openshiftBuild', type: 'Object', namedParams: [parameter(name: 'bldCfg', type: String), parameter(name: 'apiURL', type: String), parameter(name: 'authToken', type: String), parameter(name: 'buildName', type: String), parameter(name: 'checkForTriggeredDeployments', type: String), parameter(name: 'commitID', type: String), parameter(name: 'env', type: Map), parameter(name: 'namespace', type: String), parameter(name: 'showBuildLogs', type: String), parameter(name: 'verbose', type: String), parameter(name: 'waitTime', type: String), parameter(name: 'waitUnit', type: String),], doc: 'Trigger OpenShift Build') + method(name: 'openshiftCreateResource', type: 'Object', namedParams: [parameter(name: 'jsonyaml', type: String), parameter(name: 'apiURL', type: String), parameter(name: 'authToken', type: String), parameter(name: 'namespace', type: String), parameter(name: 'verbose', type: String),], doc: 'Create OpenShift Resource(s)') + method(name: 'openshiftDeleteResourceByJsonYaml', type: 'Object', namedParams: [parameter(name: 'jsonyaml', type: String), parameter(name: 'apiURL', type: String), parameter(name: 'authToken', type: String), parameter(name: 'namespace', type: String), parameter(name: 'verbose', type: String),], doc: 'Delete OpenShift Resource(s) from JSON/YAML') + method(name: 'openshiftDeleteResourceByKey', type: 'Object', namedParams: [parameter(name: 'types', type: String), parameter(name: 'keys', type: String), parameter(name: 'apiURL', type: String), parameter(name: 'authToken', type: String), parameter(name: 'namespace', type: String), parameter(name: 'verbose', type: String),], doc: 'Delete OpenShift Resource(s) by Key') + method(name: 'openshiftDeleteResourceByLabels', type: 'Object', namedParams: [parameter(name: 'types', type: String), parameter(name: 'keys', type: String), parameter(name: 'values', type: String), parameter(name: 'apiURL', type: String), parameter(name: 'authToken', type: String), parameter(name: 'namespace', type: String), parameter(name: 'verbose', type: String),], doc: 'Delete OpenShift Resource(s) using Labels') + method(name: 'openshiftDeploy', type: 'Object', namedParams: [parameter(name: 'depCfg', type: String), parameter(name: 'apiURL', type: String), parameter(name: 'authToken', type: String), parameter(name: 'namespace', type: String), parameter(name: 'verbose', type: String), parameter(name: 'waitTime', type: String), parameter(name: 'waitUnit', type: String),], doc: 'Trigger OpenShift Deployment') + method(name: 'openshiftExec', type: 'Object', namedParams: [parameter(name: 'pod', type: String), parameter(name: 'apiURL', type: String), parameter(name: 'arguments', type: Map), parameter(name: 'authToken', type: String), parameter(name: 'command', type: String), parameter(name: 'container', type: String), parameter(name: 'namespace', type: String), parameter(name: 'verbose', type: String), parameter(name: 'waitTime', type: String), parameter(name: 'waitUnit', type: String),], doc: 'OpenShift Exec') + method(name: 'openshiftExec', type: 'Object', params: [pod: String], doc: 'OpenShift Exec') + method(name: 'openshiftImageStream', type: 'Object', namedParams: [parameter(name: 'name', type: String), parameter(name: 'tag', type: String), parameter(name: 'namespace', type: String), parameter(name: 'apiURL', type: String), parameter(name: 'authToken', type: String), parameter(name: 'changelog', type: boolean), parameter(name: 'poll', type: boolean), parameter(name: 'verbose', type: String),], doc: 'OpenShift ImageStreams') + method(name: 'openshiftScale', type: 'Object', namedParams: [parameter(name: 'depCfg', type: String), parameter(name: 'replicaCount', type: String), parameter(name: 'apiURL', type: String), parameter(name: 'authToken', type: String), parameter(name: 'namespace', type: String), parameter(name: 'verbose', type: String), parameter(name: 'verifyReplicaCount', type: String), parameter(name: 'waitTime', type: String), parameter(name: 'waitUnit', type: String),], doc: 'Scale OpenShift Deployment') + method(name: 'openshiftTag', type: 'Object', namedParams: [parameter(name: 'srcStream', type: String), parameter(name: 'srcTag', type: String), parameter(name: 'destStream', type: String), parameter(name: 'destTag', type: String), parameter(name: 'alias', type: String), parameter(name: 'apiURL', type: String), parameter(name: 'authToken', type: String), parameter(name: 'destinationAuthToken', type: String), parameter(name: 'destinationNamespace', type: String), parameter(name: 'namespace', type: String), parameter(name: 'verbose', type: String),], doc: 'Tag OpenShift Image') + method(name: 'openshiftVerifyBuild', type: 'Object', namedParams: [parameter(name: 'bldCfg', type: String), parameter(name: 'apiURL', type: String), parameter(name: 'authToken', type: String), parameter(name: 'checkForTriggeredDeployments', type: String), parameter(name: 'namespace', type: String), parameter(name: 'verbose', type: String), parameter(name: 'waitTime', type: String), parameter(name: 'waitUnit', type: String),], doc: 'Verify OpenShift Build') + method(name: 'openshiftVerifyDeployment', type: 'Object', namedParams: [parameter(name: 'depCfg', type: String), parameter(name: 'apiURL', type: String), parameter(name: 'authToken', type: String), parameter(name: 'namespace', type: String), parameter(name: 'replicaCount', type: String), parameter(name: 'verbose', type: String), parameter(name: 'verifyReplicaCount', type: String), parameter(name: 'waitTime', type: String), parameter(name: 'waitUnit', type: String),], doc: 'Verify OpenShift Deployment') + method(name: 'openshiftVerifyService', type: 'Object', namedParams: [parameter(name: 'svcName', type: String), parameter(name: 'apiURL', type: String), parameter(name: 'authToken', type: String), parameter(name: 'namespace', type: String), parameter(name: 'retryCount', type: String), parameter(name: 'verbose', type: String),], doc: 'Verify OpenShift Service') + method(name: 'options', type: 'Object', params: [body: Closure]) + method(name: 'parameters', type: 'Object', params: [body: Closure], doc: 'Job parameters') + method(name: 'post', type: 'Object', params: [name: String, body: Closure], doc: 'Post build actions') + method(name: 'properties', type: 'Object', params: [properties: Map], doc: 'Set job properties') + method(name: 'publishBuildInfo', type: 'Object', namedParams: [parameter(name: 'buildInfo', type: Map), parameter(name: 'server', type: Map),], doc: 'Publish build Info to Artifactory') + method(name: 'publishHTML', type: 'Object', params: [target: Map], doc: 'Publish HTML reports') + method(name: 'pwd', type: 'Object', namedParams: [parameter(name: 'tmp', type: boolean),], doc: 'Determine current directory') + method(name: 'readFile', type: 'Object', namedParams: [parameter(name: 'file', type: String), parameter(name: 'encoding', type: String),], doc: 'Read file from workspace') + method(name: 'readJSON', type: 'Object', namedParams: [parameter(name: 'file', type: String), parameter(name: 'text', type: String),], doc: 'Read JSON from files in the workspace.') + method(name: 'readManifest', type: 'Object', namedParams: [parameter(name: 'file', type: String), parameter(name: 'text', type: String),], doc: 'Read a Jar Manifest') + method(name: 'readMavenPom', type: 'Object', namedParams: [parameter(name: 'file', type: String),], doc: 'Read a maven project file.') + method(name: 'readProperties', type: 'Object', namedParams: [parameter(name: 'defaults', type: Map), parameter(name: 'file', type: String), parameter(name: 'text', type: String),], doc: 'Read properties from files in the workspace or text.') + method(name: 'readTrusted', type: 'Object', params: [path: String], doc: 'Read trusted file from SCM') + method(name: 'readYaml', type: 'Object', namedParams: [parameter(name: 'file', type: String), parameter(name: 'text', type: String),], doc: 'Read yaml from files in the workspace or text.') + method(name: 'resolveScm', type: 'Object', namedParams: [parameter(name: 'source', type: Map), parameter(name: 'targets', type: Map), parameter(name: 'ignoreErrors', type: boolean),], doc: 'Resolves an SCM from an SCM Source and a list of candidate target branch names') + method(name: 'retry', type: 'Object', params: [count: int, body: Closure], doc: 'Retry the body up to N times') + method(name: 'script', type: 'Object', params: [body: Closure], doc: 'Run arbitrary Pipeline script') + method(name: 'sh', type: 'Object', namedParams: [parameter(name: 'script', type: String), parameter(name: 'encoding', type: String), parameter(name: 'returnStatus', type: boolean), parameter(name: 'returnStdout', type: boolean),], doc: 'Shell Script') + method(name: 'sleep', type: 'Object', namedParams: [parameter(name: 'time', type: 'int'), parameter(name: 'unit', type: 'java.util.concurrent.TimeUnit'),], doc: 'Sleep') + method(name: 'sshagent', type: 'Object', params: [credentials: List, body:'Closure'], doc: 'SSH Agent') + method(name: 'sshagent', type: 'Object', params: [body:Closure], namedParams: [parameter(name: 'credentials', type: List), parameter(name: 'ignoreMissing', type: boolean), ], doc: 'SSH Agent') + method(name: 'stages', type: 'Object', params: [body: Closure], doc: 'Stages') + method(name: 'stash', type: 'Object', namedParams: [parameter(name: 'name', type: String), parameter(name: 'excludes', type: String), parameter(name: 'includes', type: String), parameter(name: 'useDefaultExcludes', type: boolean),], doc: 'Stash some files to be used later in the build') + method(name: 'step', type: 'Object', params: [delegate: Map], doc: 'General Build Step') + method(name: 'svn', type: 'Object', namedParams: [parameter(name: 'url', type: String), parameter(name: 'changelog', type: boolean), parameter(name: 'poll', type: boolean),], doc: 'Subversion') + method(name: 'timeout', type: 'Object', params: [body: Closure], namedParams: [parameter(name: 'time', type: 'int'), parameter(name: 'unit', type: 'java.util.concurrent.TimeUnit'),], doc: 'Enforce time limit') + method(name: 'timeout', type: 'Object', params: [time: int, body: Closure], doc: 'Enforce time limit') + method(name: 'tool', type: 'Object', namedParams: [parameter(name: 'name', type: String), parameter(name: 'type', type: String),], doc: 'Use a tool from a predefined Tool Installation') + method(name: 'touch', type: 'Object', namedParams: [parameter(name: 'file', type: String), parameter(name: 'timestamp', type: 'java.lang.Long'),], doc: 'Create a file (if not already exist) in the workspace, and set the timestamp') + method(name: 'triggers', type: 'Object', params: [body: Closure], doc: 'Build triggers') + method(name: 'unarchive', type: 'Object', namedParams: [parameter(name: 'mapping', type: Map),], doc: 'Copy archived artifacts into the workspace') + method(name: 'unstash', type: 'Object', params: [name: String], doc: 'Restore files previously stashed') + method(name: 'unzip', type: 'Object', namedParams: [parameter(name: 'zipFile', type: String), parameter(name: 'charset', type: String), parameter(name: 'dir', type: String), parameter(name: 'glob', type: String), parameter(name: 'read', type: boolean), parameter(name: 'test', type: boolean),], doc: 'Extract Zip file') + method(name: 'validateDeclarativePipeline', type: 'Object', params: [path: String], doc: 'Validate a file containing a Declarative Pipeline') + method(name: 'waitUntil', type: 'Object', params: [body: Closure], doc: 'Wait for condition') + method(name: 'when', type: 'Object', params: [body: Closure]) + method(name: 'withContext', type: 'Object', params: [context: 'Object', body: Closure], doc: 'Advanced/Deprecated Use contextual object from internal APIs within a block') + method(name: 'withCredentials', type: 'Object', params: [bindings: List, body:'Closure'], doc: 'Bind credentials to variables') + method(name: 'withDockerContainer', type: 'Object', params: [body: Closure], namedParams: [parameter(name: 'image', type: String), parameter(name: 'args', type: String), parameter(name: 'toolName', type: String),], doc: 'Run build steps inside a Docker container') + method(name: 'withDockerRegistry', type: 'Object', params: [registry: Map, body: Closure], doc: 'Advanced/Deprecated Sets up Docker registry endpoint') + method(name: 'withDockerServer', type: 'Object', params: [server: Map, body: Closure], doc: 'Advanced/Deprecated Sets up Docker server endpoint') + method(name: 'withEnv', type: 'Object', params: [overrides: Map, body: Closure], doc: 'Set environment variables') + method(name: 'wrap', type: 'Object', params: [delegate: Map, body: Closure], doc: 'General Build Wrapper') + method(name: 'writeFile', type: 'Object', namedParams: [parameter(name: 'file', type: String), parameter(name: 'text', type: String), parameter(name: 'encoding', type: String),], doc: 'Write file to workspace') + method(name: 'writeJSON', type: 'Object', namedParams: [parameter(name: 'file', type: String), parameter(name: 'json', type: Map),], doc: 'Write JSON to a file in the workspace.') + method(name: 'writeMavenPom', type: 'Object', namedParams: [parameter(name: 'model', type: Map), parameter(name: 'file', type: String),], doc: 'Write a maven project file.') + method(name: 'ws', type: 'Object', params: [dir: String, body: Closure], doc: 'Allocate workspace') + method(name: 'zip', type: 'Object', namedParams: [parameter(name: 'zipFile', type: String), parameter(name: 'archive', type: boolean), parameter(name: 'dir', type: String), parameter(name: 'glob', type: String),], doc: 'Create Zip file') + + //The only thing inside agent can be label + if (enclosingCall("agent")) { + property(name: 'any') + property(name: 'none') + method(name: 'label', type: String, params: [expr: String]) + method(name: 'docker', type: String, params: [body: Closure]) + method(name: 'docker', type: String, params: [docker_image: String]) + method(name: 'dockerfile', type: boolean, params: [use_dockerfile: boolean]) + method(name: 'kubernetes', type: String, params: [body: Closure]) + } + + if (enclosingCall("dockerfile")) { + method(name: 'filename', type: String, params: [expr: String]) + method(name: 'dir', type: String, params: [expr: String]) + method(name: 'label', type: String, params: [label: String]) + method(name: 'registryUrl', type: String, params: [registy: String]) + method(name: 'registryCredentialsId', type: String, params: [credentialId: String]) + } + + if (enclosingCall("docker")) { + method(name: 'alwaysPull', type: String, params: [expr: boolean]) + method(name: 'image', type: String, params: [image_name: String]) + method(name: 'args', type: String, params: [args: String]) + method(name: 'label', type: String, params: [label: String]) + method(name: 'registryUrl', type: String, params: [registy: String]) + method(name: 'registryCredentialsId', type: String, params: [credentialId: String]) + } + + if (enclosingCall("kubernetes")) { + method(name: 'label', type: String, params: [expr: String]) + method(name: 'yaml', type: String, params: [expr: String]) + } + + if (enclosingCall("environment")) { + method(name: 'credentials', type: String, params: [credentialId: String]) + } + + if (enclosingCall("when")) { + method(name: 'beforeInput', type: String, params: [expr: boolean]) + method(name: 'beforeWhen', type: String, params: [expr: boolean]) + method(name: 'beforeAgent', type: String, params: [expr: boolean]) + method(name: 'expression', type: String, params: [body: Closure]) + method(name: 'allOf', type: String, params: [body: Closure]) + method(name: 'anyOf', type: String, params: [body: Closure]) + } + + if (enclosingCall("triggers")) { + method(name: 'cron', type: String, params: [expr: String], doc: 'Cron expression can be one of @daily, @hourly, etc') + method(name: 'upstream', type: 'Object', params: [name: String, build_status: 'Object']) + method(name: 'pollSCM', type: String, params: [expr: String]) + method(name: 'bitbucketPush') + } + + // Parameters can only contain + if (enclosingCall("parameters")) { + method(name: 'string', type: 'Object', namedParams: [parameter(name: 'name', type: String), parameter(name: 'defaultValue', type: String), parameter(name: 'description', type: String)]) + method(name: 'booleanParam', type: 'Object', namedParams: [parameter(name: 'name', type: String), parameter(name: 'defaultValue', type: 'java.lang.Boolean'), parameter(name: 'description', type: String)]) + method(name: 'choice', type: 'Object', namedParams: [parameter(name: 'choice', type: String), parameter(name: 'defaultValue', type: 'java.lang.Boolean'), parameter(name: 'description', type: String)]) + } + + // Find the options! + if (enclosingCall("options")) { + method(name: 'ansiColor', type: String, params: [colorMapName: String]) + method(name: 'lock', type: 'Object', params: [resource: String], doc: 'Lock shared resource') + method(name: 'lock', type: 'Object', namedParams: [parameter(name: 'resource', type: 'java.lang.String'), parameter(name: 'extra', type: 'java.util.List'), parameter(name: 'inversePrecedence', type: 'boolean'), parameter(name: 'label', type: 'java.lang.String'), parameter(name: 'quantity', type: 'int'), parameter(name: 'skipIfLocked', type: 'boolean'), parameter(name: 'variable', type: 'java.lang.String'), ], doc: 'Lock shared resource') + method(name: 'skipDefaultCheckout', type: String, params: [expr: boolean]) + method(name: 'timestamps') + method(name: 'buildDiscarder', type: 'Object', params: [logRotator: Object]) + method(name: 'logRotator', type: 'Object', namedParams: [ + parameter(name: 'artifactDaysToKeepStr', type: String), + parameter(name: 'artifactNumToKeepStr', type: String), + parameter(name: 'daysToKeepStr', type: String), + parameter(name: 'numToKeepStr', type: String), + ]) + method(name: 'timeout', type: 'Object', namedParams: [parameter(name: 'time', type: 'java.lang.Integer'), parameter(name: 'unit', type: String)]) + } -//Steps that require a options context -def optionsCtx = context(scope: closureScope()) -contributor(optionsCtx) { - def call = enclosingCall('options') - if (call) { - method(name: 'timestamps', type: 'Object', params: [], doc: 'Timestamps') - method(name: 'timeout', type: 'Object', namedParams: [parameter(name: 'time', type: 'java.lang.Integer'), parameter(name: 'activity', type: 'boolean'), parameter(name: 'unit', type: 'java.util.concurrent.TimeUnit'),], doc: 'Enforce time limit') + // Inside stages can be, stage or stage('Name') + if (enclosingCall("stages")) { + method(name: 'parallel', type: Object, params: [body: Closure]) + method(name: 'stage', type: 'Object', params: [name: String, body: Closure], doc: 'Stage') + method(name: 'stage', type: 'Object', params: [body: Closure], namedParams: [parameter(name: 'name', type: String), parameter(name: 'concurrency', type: 'java.lang.Integer'),], doc: 'Stage') + } + + // Inside steps only steps + if (enclosingCall("stage")) { + method(name: 'agent', type: 'Object', params: [body: Closure], doc: 'Label expression to select agents') + method(name: 'steps', type: 'Object', params: [body: Closure], doc: 'Steps to execute on stage') + method(name: 'post', type: 'Object', params: [body: Closure], doc: 'Post actions can be executed on a per-stage basis as well') + } + + // Only inside steps + if (enclosingCall("steps") || enclosingCall("always") || enclosingCall("success") || + enclosingCall("failure") || enclosingCall("unstable") || enclosingCall("changed")) { + method(name: 'archiveArtifacts', type: 'Object', namedParams: [parameter(name: 'allowEmptyArchive', type: 'boolean'), parameter(name: 'artifacts', type: String), parameter(name: 'caseSensitive', type: boolean), parameter(name: 'defaultExcludes', type: boolean), parameter(name: 'excludes', type: String), parameter(name: 'fingerprint', type: boolean), parameter(name: 'followSymlinks', type: boolean), parameter(name: 'onlyIfSuccessful', type: boolean)], doc: 'Clean workspace') + method(name: 'timestamp', type: 'Object', params: [body: Closure], doc: 'Timestamps') + method(name: 'bat', type: 'Object', params: [script: String], doc: 'Windows Batch Script') + method(name: 'bat', type: 'Object', namedParams: [parameter(name: 'script', type: String), parameter(name: 'encoding', type: String), parameter(name: 'returnStatus', type: boolean), parameter(name: 'returnStdout', type: boolean),], doc: 'Windows Batch Script') + method(name: 'checkout', type: 'Object', params: [scm: Map], doc: 'General SCM') + method(name: 'checkout', type: 'Object', namedParams: [parameter(name: 'scm', type: Map), parameter(name: 'changelog', type: boolean), parameter(name: 'poll', type: boolean),], doc: 'General SCM') + method(name: 'cleanWs', type: 'Object', namedParams: [parameter(name: 'notFailBuild', type: boolean)], doc: 'Clean workspace') + method(name: 'deleteDir', type: 'Object', params: [:], doc: 'Recursively delete the current directory from the workspace') + method(name: 'dir', type: 'Object', params: [path: String, body: Closure], doc: 'Change current directory') + method(name: 'fileExists', type: 'Object', params: [file: String], doc: 'Verify if file exists in workspace') + method(name: 'git', type: 'Object', params: [url: String], doc: 'Git') + method(name: 'git', type: 'Object', namedParams: [parameter(name: 'url', type: String), parameter(name: 'branch', type: String), parameter(name: 'changelog', type: boolean), parameter(name: 'credentialsId', type: String), parameter(name: 'poll', type: boolean),], doc: 'Git') + method(name: 'junit', type: 'Object', params: [testResults: String], doc: 'Archive JUnit-formatted test results') + method(name: 'junit', type: 'Object', namedParams: [parameter(name: 'testResults', type: String), parameter(name: 'allowEmptyResults', type: boolean), parameter(name: 'healthScaleFactor', type: 'double'), parameter(name: 'keepLongStdio', type: boolean), parameter(name: 'testDataPublishers', type: Map),], doc: 'Archive JUnit-formatted test results') + method(name: 'load', type: 'Object', params: [path: String], doc: 'Evaluate a Groovy source file into the Pipeline script') + method(name: 'powershell', type: 'Object', params: [script: String], doc: 'PowerShell Script') + method(name: 'powershell', type: 'Object', namedParams: [parameter(name: 'script', type: String), parameter(name: 'encoding', type: String), parameter(name: 'returnStatus', type: boolean), parameter(name: 'returnStdout', type: boolean),], doc: 'PowerShell Script') + method(name: 'publishHTML', type: 'Object', params: [target: Map], doc: 'Publish HTML reports') + method(name: 'pwd', type: 'Object', params: [:], doc: 'Determine current directory') + method(name: 'pwd', type: 'Object', namedParams: [parameter(name: 'tmp', type: boolean),], doc: 'Determine current directory') + method(name: 'readFile', type: 'Object', params: [file: String], doc: 'Read file from workspace') + method(name: 'readFile', type: 'Object', namedParams: [parameter(name: 'file', type: String), parameter(name: 'encoding', type: String),], doc: 'Read file from workspace') + method(name: 'sh', type: 'Object', params: [script: String], doc: 'Shell Script') + method(name: 'sh', type: 'Object', namedParams: [parameter(name: 'script', type: String), parameter(name: 'encoding', type: String), parameter(name: 'returnStatus', type: boolean), parameter(name: 'returnStdout', type: boolean),], doc: 'Shell Script') + method(name: 'stash', type: 'Object', params: [name: String], doc: 'Stash some files to be used later in the build') + method(name: 'stash', type: 'Object', namedParams: [parameter(name: 'name', type: String), parameter(name: 'allowEmpty', type: boolean), parameter(name: 'excludes', type: String), parameter(name: 'includes', type: String), parameter(name: 'useDefaultExcludes', type: boolean),], doc: 'Stash some files to be used later in the build') + method(name: 'tm', type: 'Object', params: [stringWithMacro: String], doc: 'Expand a string containing macros') + method(name: 'unstash', type: 'Object', params: [name: String], doc: 'Restore files previously stashed') + method(name: 'validateDeclarativePipeline', type: 'Object', params: [path: String], doc: 'Validate a file containing a Declarative Pipeline') + method(name: 'wrap', type: 'Object', params: [delegate: Map, body: Closure], doc: 'General Build Wrapper') + method(name: 'writeFile', type: 'Object', namedParams: [parameter(name: 'file', type: String), parameter(name: 'text', type: String), parameter(name: 'encoding', type: String),], doc: 'Write file to workspace') + method(name: 'archive', type: 'Object', params: [includes: String], doc: 'Advanced/Deprecated Archive artifacts') + method(name: 'archive', type: 'Object', namedParams: [parameter(name: 'includes', type: String), parameter(name: 'excludes', type: String),], doc: 'Archive artifacts') + method(name: 'dockerFingerprintFrom', type: 'Object', namedParams: [parameter(name: 'dockerfile', type: String), parameter(name: 'image', type: String), parameter(name: 'buildArgs', type: Map), parameter(name: 'toolName', type: String),], doc: 'Record trace of a Docker image used in FROM') + method(name: 'unarchive', type: 'Object', params: [:], doc: 'Advanced/Deprecated Copy archived artifacts into the workspace') + method(name: 'unarchive', type: 'Object', namedParams: [parameter(name: 'mapping', type: Map),], doc: 'Copy archived artifacts into the workspace') + method(name: 'withDockerContainer', type: 'Object', params: [image: String, body: Closure], doc: 'Advanced/Deprecated Run build steps inside a Docker container') + method(name: 'withDockerContainer', type: 'Object', params: [body: Closure], namedParams: [parameter(name: 'image', type: String), parameter(name: 'args', type: String), parameter(name: 'toolName', type: String),], doc: 'Run build steps inside a Docker container') + method(name: 'withDockerRegistry', type: 'Object', params: [registry: Map, body: Closure], doc: 'Advanced/Deprecated Sets up Docker registry endpoint') + method(name: 'withDockerServer', type: 'Object', params: [server: Map, body: Closure], doc: 'Advanced/Deprecated Sets up Docker server endpoint') + method(name: 'parallel', type: 'Object', params: [body: Map], doc: 'Run task in parallel') + + method(name: 'unzipInfobase', doc: 'Unzip Infobase') + method(name: 'zipInfobase', doc: 'Zip Infobase') + method(name: 'printLocation', doc: 'Print current node name') + method(name: 'jobConfiguration', type: 'ru.pulsar.jenkins.library.configuration.JobConfiguration', params: [path: String], doc: 'Load job configuration') + method(name: 'jobConfiguration', type: 'ru.pulsar.jenkins.library.configuration.JobConfiguration', params: [:], doc: 'Load job configuration') + method(name: 'bdd', params: [config: 'ru.pulsar.jenkins.library.configuration.JobConfiguration'], doc: 'Run BDD tests') + method(name: 'createDir', params: [path: String], doc: 'Create directory') + method(name: 'createInfobase', params: [config: 'ru.pulsar.jenkins.library.configuration.JobConfiguration'], doc: 'Create infobase') + method(name: 'designerToEdtFormatTransformation', params: [config: 'ru.pulsar.jenkins.library.configuration.JobConfiguration'], doc: 'Convert sources from Designer to EDT format') + method(name: 'edtToDesignerFormatTransformation', params: [config: 'ru.pulsar.jenkins.library.configuration.JobConfiguration'], doc: 'Convert sources from EDT to Designer format') + method(name: 'edtValidate', params: [config: 'ru.pulsar.jenkins.library.configuration.JobConfiguration'], doc: 'Run EDT validation') + method(name: 'getExtensions', params: [config: 'ru.pulsar.jenkins.library.configuration.JobConfiguration'], doc: 'Build or load extensions') + method(name: 'initFromFiles', params: [config: 'ru.pulsar.jenkins.library.configuration.JobConfiguration'], doc: 'Initialize infobase from source files') + method(name: 'initFromStorage', params: [config: 'ru.pulsar.jenkins.library.configuration.JobConfiguration'], doc: 'Initialize infobase from storage') + method(name: 'initInfobase', params: [config: 'ru.pulsar.jenkins.library.configuration.JobConfiguration'], doc: 'Initialize infobase - run migrations and preparation scripts') + method(name: 'transform', params: [config: 'ru.pulsar.jenkins.library.configuration.JobConfiguration'], doc: 'Transform results of tests') + method(name: 'syntaxCheck', params: [config: 'ru.pulsar.jenkins.library.configuration.JobConfiguration'], doc: 'Run syntax check') + method(name: 'smoke', params: [config: 'ru.pulsar.jenkins.library.configuration.JobConfiguration'], doc: 'Run smoke tests') + method(name: 'yaxunit', params: [config: 'ru.pulsar.jenkins.library.configuration.JobConfiguration'], doc: 'Run YaXUnit tests') + method(name: 'sonarScanner', params: [config: 'ru.pulsar.jenkins.library.configuration.JobConfiguration'], doc: 'Run SonarQube analysis') + method(name: 'saveResults', params: [config: 'ru.pulsar.jenkins.library.configuration.JobConfiguration'], doc: 'Archive and publish build results') + method(name: 'sendNotifications', params: [config: 'ru.pulsar.jenkins.library.configuration.JobConfiguration'], doc: 'Send notifications about build results') + method(name: 'loadExtensions', params: [config: 'ru.pulsar.jenkins.library.configuration.JobConfiguration', stageName: String], doc: 'Load extensions into infobase') + } + + // Post actions! + if (enclosingCall("post")) { + method(name: 'always', type: 'Object', params: [body: Closure]) + method(name: 'success', type: 'Object', params: [body: Closure]) + method(name: 'failure', type: 'Object', params: [body: Closure]) + method(name: 'unstable', type: 'Object', params: [body: Closure]) + method(name: 'changed', type: 'Object', params: [body: Closure]) + } + + if (enclosingCall("withCredentials")) { + method(name: 'string', type: Object, params: [credentialId: String, variable: String]) + method(name: 'string', type: Object, namedParams: [parameter(name: 'credentialId', type: String), parameter(name: 'variable', type: String),], doc: 'Determine current directory') + method(name: 'file', type: Object, params: [credentialId: String, variable: String]) + method(name: 'file', type: Object, namedParams: [parameter(name: 'credentialId', type: String), parameter(name: 'variable', type: String),], doc: 'Determine current directory') + } } } -//Steps that require a node context -def nodeCtx = context(scope: closureScope()) -contributor(nodeCtx) { - def call = enclosingCall('node') - if (call) { - method(name: 'checkout', type: 'Object', params: [scm: 'Map'], doc: 'Check out from version control') - method(name: 'checkout', type: 'Object', namedParams: [parameter(name: 'scm', type: 'Map'), parameter(name: 'changelog', type: 'boolean'), parameter(name: 'poll', type: 'boolean'),], doc: 'Check out from version control') - method(name: 'containerLog', type: 'Object', params: [name: 'java.lang.String'], doc: 'Get container log from Kubernetes') - method(name: 'containerLog', type: 'Object', namedParams: [parameter(name: 'name', type: 'java.lang.String'), parameter(name: 'limitBytes', type: 'int'), parameter(name: 'returnLog', type: 'boolean'), parameter(name: 'sinceSeconds', type: 'int'), parameter(name: 'tailingLines', type: 'int'),], doc: 'Get container log from Kubernetes') - method(name: 'deleteDir', type: 'Object', params: [:], doc: 'Recursively delete the current directory from the workspace') - method(name: 'dir', type: 'Object', params: [path: String, body: 'Closure'], doc: 'Change current directory') - method(name: 'fileExists', type: 'Object', params: [file: 'java.lang.String'], doc: 'Verify if file exists in workspace') - method(name: 'findFiles', type: 'Object', params: [:], doc: 'Find files in the workspace') - method(name: 'findFiles', type: 'Object', namedParams: [parameter(name: 'excludes', type: 'java.lang.String'), parameter(name: 'glob', type: 'java.lang.String'),], doc: 'Find files in the workspace') - method(name: 'git', type: 'Object', params: [url: 'java.lang.String'], doc: 'Git') - method(name: 'git', type: 'Object', namedParams: [parameter(name: 'url', type: 'java.lang.String'), parameter(name: 'branch', type: 'java.lang.String'), parameter(name: 'changelog', type: 'boolean'), parameter(name: 'credentialsId', type: 'java.lang.String'), parameter(name: 'poll', type: 'boolean'),], doc: 'Git') - method(name: 'junit', type: 'Object', params: [testResults: 'java.lang.String'], doc: 'Archive JUnit-formatted test results') - method(name: 'junit', type: 'Object', namedParams: [parameter(name: 'testResults', type: 'java.lang.String'), parameter(name: 'allowEmptyResults', type: 'boolean'), parameter(name: 'healthScaleFactor', type: 'double'), parameter(name: 'keepLongStdio', type: 'boolean'), parameter(name: 'testDataPublishers', type: 'Map'),], doc: 'Archive JUnit-formatted test results') - method(name: 'load', type: 'Object', params: [path: 'java.lang.String'], doc: 'Evaluate a Groovy source file into the Pipeline script') - method(name: 'publishHTML', type: 'Object', params: [target: 'Map'], doc: 'Publish HTML reports') - method(name: 'pwd', type: 'Object', params: [:], doc: 'Determine current directory') - method(name: 'pwd', type: 'Object', namedParams: [parameter(name: 'tmp', type: 'boolean'),], doc: 'Determine current directory') - method(name: 'readFile', type: 'java.lang.String', params: [file: 'java.lang.String'], doc: 'Read file from workspace') - method(name: 'readFile', type: 'java.lang.String', namedParams: [parameter(name: 'file', type: 'java.lang.String'), parameter(name: 'encoding', type: 'java.lang.String'),], doc: 'Read file from workspace') - method(name: 'readMavenPom', type: 'Object', params: [:], doc: 'Read a maven project file.') - method(name: 'readMavenPom', type: 'Object', namedParams: [parameter(name: 'file', type: 'java.lang.String'),], doc: 'Read a maven project file.') - method(name: 'powershell', type: 'Object', params: [script: 'java.lang.String'], doc: 'PowerShell Script') - method(name: 'powershell', type: 'Object', namedParams: [parameter(name: 'script', type: 'java.lang.String'), parameter(name: 'encoding', type: 'java.lang.String'), parameter(name: 'label', type: 'java.lang.String'), parameter(name: 'returnStatus', type: 'boolean'), parameter(name: 'returnStdout', type: 'boolean'),], doc: 'PowerShell Script') - method(name: 'sh', type: 'Object', params: [script: 'java.lang.String'], doc: 'Shell Script') - method(name: 'sh', type: 'Object', namedParams: [parameter(name: 'script', type: 'java.lang.String'), parameter(name: 'encoding', type: 'java.lang.String'), parameter(name: 'label', type: 'java.lang.String'), parameter(name: 'returnStatus', type: 'boolean'), parameter(name: 'returnStdout', type: 'boolean'),], doc: 'Shell Script') - method(name: 'bat', type: 'Object', params: [script: 'java.lang.String'], doc: 'Windows Batch Script') - method(name: 'bat', type: 'Object', namedParams: [parameter(name: 'script', type: 'java.lang.String'), parameter(name: 'encoding', type: 'java.lang.String'), parameter(name: 'label', type: 'java.lang.String'), parameter(name: 'returnStatus', type: 'boolean'), parameter(name: 'returnStdout', type: 'boolean'),], doc: 'Windows Batch Script') - method(name: 'sha1', type: 'Object', params: [file: 'java.lang.String'], doc: 'Compute the SHA1 of a given file') - method(name: 'sshagent', type: 'Object', params: [credentials: Map, body: 'Closure'], doc: 'SSH Agent') - method(name: 'sshagent', type: 'Object', params: [body: Closure], namedParams: [parameter(name: 'credentials', type: 'Map'), parameter(name: 'ignoreMissing', type: 'boolean'),], doc: 'SSH Agent') - method(name: 'stash', type: 'Object', params: [name: 'java.lang.String'], doc: 'Stash some files to be used later in the build') - method(name: 'stash', type: 'Object', namedParams: [parameter(name: 'name', type: 'java.lang.String'), parameter(name: 'allowEmpty', type: 'boolean'), parameter(name: 'excludes', type: 'java.lang.String'), parameter(name: 'includes', type: 'java.lang.String'), parameter(name: 'useDefaultExcludes', type: 'boolean'),], doc: 'Stash some files to be used later in the build') - method(name: 'step', type: 'Object', params: [delegate: 'Map'], doc: 'General Build Step') - method(name: 'svn', type: 'Object', params: [url: 'java.lang.String'], doc: 'Subversion') - method(name: 'svn', type: 'Object', namedParams: [parameter(name: 'url', type: 'java.lang.String'), parameter(name: 'changelog', type: 'boolean'), parameter(name: 'poll', type: 'boolean'),], doc: 'Subversion') - method(name: 'tee', type: 'Object', params: [file: String, body: 'Closure'], doc: 'Tee output to file') - method(name: 'tm', type: 'Object', params: [stringWithMacro: 'java.lang.String'], doc: 'Expand a string containing macros') - method(name: 'touch', type: 'Object', params: [file: 'java.lang.String'], doc: 'Create a file (if not already exist) in the workspace, and set the timestamp') - method(name: 'touch', type: 'Object', namedParams: [parameter(name: 'file', type: 'java.lang.String'), parameter(name: 'timestamp', type: 'java.lang.Long'),], doc: 'Create a file (if not already exist) in the workspace, and set the timestamp') - method(name: 'unstash', type: 'Object', params: [name: 'java.lang.String'], doc: 'Restore files previously stashed') - method(name: 'unzip', type: 'Object', params: [zipFile: 'java.lang.String'], doc: 'Extract Zip file') - method(name: 'unzip', type: 'Object', namedParams: [parameter(name: 'zipFile', type: 'java.lang.String'), parameter(name: 'charset', type: 'java.lang.String'), parameter(name: 'dir', type: 'java.lang.String'), parameter(name: 'glob', type: 'java.lang.String'), parameter(name: 'quiet', type: 'boolean'), parameter(name: 'read', type: 'boolean'), parameter(name: 'test', type: 'boolean'),], doc: 'Extract Zip file') - method(name: 'validateDeclarativePipeline', type: 'Object', params: [path: 'java.lang.String'], doc: 'Validate a file containing a Declarative Pipeline') - method(name: 'wrap', type: 'Object', params: [delegate: Map, body: 'Closure'], doc: 'General Build Wrapper') - method(name: 'writeCSV', type: 'Object', namedParams: [parameter(name: 'file', type: 'java.lang.String'), parameter(name: 'records', type: 'Map'), parameter(name: 'format', type: 'Map'),], doc: 'Write content to a CSV file in the workspace.') - method(name: 'writeFile', type: 'Object', namedParams: [parameter(name: 'file', type: 'java.lang.String'), parameter(name: 'text', type: 'java.lang.String'), parameter(name: 'encoding', type: 'java.lang.String'),], doc: 'Write file to workspace') - method(name: 'writeJSON', type: 'Object', namedParams: [parameter(name: 'file', type: 'java.lang.String'), parameter(name: 'json', type: 'Map'), parameter(name: 'pretty', type: 'int'),], doc: 'Write JSON to a file in the workspace.') - method(name: 'writeMavenPom', type: 'Object', params: [model: 'Map'], doc: 'Write a maven project file.') - method(name: 'writeMavenPom', type: 'Object', namedParams: [parameter(name: 'model', type: 'Map'), parameter(name: 'file', type: 'java.lang.String'),], doc: 'Write a maven project file.') - method(name: 'writeYaml', type: 'Object', namedParams: [parameter(name: 'file', type: 'java.lang.String'), parameter(name: 'data', type: 'java.lang.Object'), parameter(name: 'charset', type: 'java.lang.String'),], doc: 'Write a yaml from an object.') - method(name: 'zip', type: 'Object', params: [zipFile: 'java.lang.String'], doc: 'Create Zip file') - method(name: 'zip', type: 'Object', namedParams: [parameter(name: 'zipFile', type: 'java.lang.String'), parameter(name: 'archive', type: 'boolean'), parameter(name: 'dir', type: 'java.lang.String'), parameter(name: 'glob', type: 'java.lang.String'),], doc: 'Create Zip file') - method(name: 'archive', type: 'Object', params: [includes: 'java.lang.String'], doc: 'Advanced/Deprecated Archive artifacts') - method(name: 'archive', type: 'Object', namedParams: [parameter(name: 'includes', type: 'java.lang.String'), parameter(name: 'excludes', type: 'java.lang.String'),], doc: 'Archive artifacts') - method(name: 'container', type: 'Object', params: [name: String, body: 'Closure'], doc: 'Advanced/Deprecated Run build steps in a container') - method(name: 'container', type: 'Object', params: [body: Closure], namedParams: [parameter(name: 'name', type: 'java.lang.String'), parameter(name: 'shell', type: 'java.lang.String'),], doc: 'Run build steps in a container') - method(name: 'dockerFingerprintFrom', type: 'Object', namedParams: [parameter(name: 'dockerfile', type: 'java.lang.String'), parameter(name: 'image', type: 'java.lang.String'), parameter(name: 'commandLine', type: 'java.lang.String'), parameter(name: 'toolName', type: 'java.lang.String'),], doc: 'Record trace of a Docker image used in FROM') - method(name: 'unarchive', type: 'Object', params: [:], doc: 'Advanced/Deprecated Copy archived artifacts into the workspace') - method(name: 'unarchive', type: 'Object', namedParams: [parameter(name: 'mapping', type: 'Map'),], doc: 'Copy archived artifacts into the workspace') - method(name: 'withDockerContainer', type: 'Object', params: [image: String, body: 'Closure'], doc: 'Advanced/Deprecated Run build steps inside a Docker container') - method(name: 'withDockerContainer', type: 'Object', params: [body: Closure], namedParams: [parameter(name: 'image', type: 'java.lang.String'), parameter(name: 'args', type: 'java.lang.String'), parameter(name: 'toolName', type: 'java.lang.String'),], doc: 'Run build steps inside a Docker container') - method(name: 'withDockerRegistry', type: 'Object', params: [registry: Map, body: 'Closure'], doc: 'Advanced/Deprecated Sets up Docker registry endpoint') - method(name: 'withDockerRegistry', type: 'Object', params: [body: Closure], namedParams: [parameter(name: 'registry', type: 'Map'), parameter(name: 'toolName', type: 'java.lang.String'),], doc: 'Sets up Docker registry endpoint') - method(name: 'withDockerServer', type: 'Object', params: [server: Map, body: 'Closure'], doc: 'Advanced/Deprecated Sets up Docker server endpoint') - } +// Define default env vars +def envVars = context(ctype: 'org.jenkinsci.plugins.workflow.cps.EnvActionImpl.Binder') +contributor(envVars) { + property(name: 'BRANCH_NAME', type: String, doc: 'For a multibranch project, this will be set to the name of the branch being built, for example in case you wish to deploy to production from master but not from feature branches; if corresponding to some kind of change request, the name is generally arbitrary (refer to CHANGE_ID and CHANGE_TARGET).') + property(name: 'CHANGE_ID', type: String, doc: 'For a multibranch project corresponding to some kind of change request, this will be set to the change ID, such as a pull request number, if supported; else unset.') + property(name: 'CHANGE_URL', type: 'Strig', doc: 'For a multibranch project corresponding to some kind of change request, this will be set to the change URL, if supported; else unset.') + property(name: 'CHANGE_TITLE', type: String, doc: 'For a multibranch project corresponding to some kind of change request, this will be set to the title of the change, if supported; else unset.') + property(name: 'CHANGE_AUTHOR', type: String, doc: 'For a multibranch project corresponding to some kind of change request, this will be set to the username of the author of the proposed change, if supported; else unset.') + property(name: 'CHANGE_AUTHOR_DISPLAY_NAME', type: String, doc: 'For a multibranch project corresponding to some kind of change request, this will be set to the human name of the author, if supported; else unset.') + property(name: 'CHANGE_AUTHOR_EMAIL', type: String, doc: 'For a multibranch project corresponding to some kind of change request, this will be set to the email address of the author, if supported; else unset.') + property(name: 'CHANGE_TARGET', type: String, doc: 'rFo a multibranch project corresponding to some kind of change request, this will be set to the target or base branch to which the change could be merged, if supported; else unset.') + property(name: 'BUILD_NUMBER', type: String, doc: 'The current build number, such as "153"') + property(name: 'BUILD_ID', type: String, doc: 'The current build ID, identical to BUILD_NUMBER for builds created in 1.597+, but a YYYY-MM-DD_hh-mm-ss timestamp for older builds') + property(name: 'BUILD_DISPLAY_NAME', type: String, doc: 'The display name of the current build, which is something like "#153" by default.') + property(name: 'JOB_NAME', type: String, doc: 'Name of the project of this build, such as "foo" or "foo/bar".') + property(name: 'JOB_BASE_NAME', type: String, doc: 'Short Name of the project of this build stripping off folder paths, such as "foo" for "bar/foo".') + property(name: 'BUILD_TAG', type: String, doc: 'String of "jenkins-${JOB_NAME}-${BUILD_NUMBER}". All forward slashes (/) in the JOB_NAME are replaced with dashes (-). Convenient to put into a resource file, a jar file, etc for easier identification.') + property(name: 'EXECUTOR_NUMBER', type: String, doc: 'The unique number that identifies the current executor (among executors of the same machine) that’s carrying out this build. This is the number you see in the "build executor status", except that the number starts from 0, not 1.') + property(name: 'NODE_NAME', type: String, doc: 'Name of the agent if the build is on an agent, or "master" if run on master') + property(name: 'NODE_LABELS', type: String, doc: 'Whitespace-separated list of labels that the node is assigned.') + property(name: 'WORKSPACE', type: String, doc: 'The absolute path of the directory assigned to the build as a workspace.') + property(name: 'JENKINS_HOME', type: String, doc: 'The absolute path of the directory assigned on the master node for Jenkins to store data.') + property(name: 'JENKINS_URL', type: String, doc: 'Full URL of Jenkins, like http://server:port/jenkins/ (note: only available if Jenkins URL set in system configuration)') + property(name: 'BUILD_URL', type: String, doc: 'Full URL of this build, like http://server:port/jenkins/job/foo/15/ (Jenkins URL must be set)') + property(name: 'JOB_URL', type: String, doc: 'Full URL of this job, like http://server:port/jenkins/job/foo/ (Jenkins URL must be set)') + property(name: 'GIT_URL', type: String, doc: 'The URL to use for cloning the repository') } -// Errors on: -// class org.jenkinsci.plugins.workflow.cps.steps.ParallelStep: There's no @DataBoundConstructor on any constructor of class org.jenkinsci.plugins.workflow.cps.steps.ParallelStep +// Define all the properties in current builds +def currentBuild = context(ctype: 'org.jenkinsci.plugins.workflow.cps.RunWrapperBinder') +contributor(currentBuild) { + method(name: 'resultIsBetterOrEqualTo', type: 'Boolean', params: [buildStatus: String], doc: 'Compares the current build result to the provided result string (SUCCESS, UNSTABLE, or FAILURE) and returns true if the current build result is better than or equal to the provided result.') + method(name: 'resultIsWorseOrEqualTo', type: 'Boolean', params: [buildStatus: String], doc: 'Compares the current build result to the provided result string (SUCCESS, UNSTABLE, or FAILURE) and returns true if the current build result is worse than or equal to the provided result.') + property(name: 'number', type: 'Integer', doc: 'build number') + property(name: 'result', type: String, doc: 'typically SUCCESS, UNSTABLE, or FAILURE (may be null for an ongoing build)') + property(name: 'currentResult', type: String, doc: 'typically SUCCESS, UNSTABLE, or FAILURE (never null)') + property(name: 'displayName', type: String, doc: 'normally #123 but sometimes set to, e.g., an SCM commit identifier') + property(name: 'description', type: String, doc: 'additional information about the build') + property(name: 'id', type: String, doc: 'normally number as a string') + property(name: 'timeInMillis', type: 'long', doc: 'time since the epoch when the build was scheduled') + property(name: 'startTimeInMillis', type: 'long', doc: 'time since the epoch when the build started running') + property(name: 'duration', type: 'long', doc: 'duration of the build in milliseconds') + property(name: 'durationString', type: String, doc: 'a human-readable representation of the build duration') + property(name: 'previousBuild', type: 'org.jenkinsci.plugins.workflow.cps.RunWrapperBinder', doc: 'another similar object, or null') + property(name: 'nextBuild', type: 'org.jenkinsci.plugins.workflow.cps.RunWrapperBinder', doc: 'another similar object, or null') + property(name: 'absoluteUrl', type: String, doc: 'URL of build index page') + property(name: 'buildVariables', type: Map, doc: 'for a non-Pipeline downstream build, offers access to a map of defined build variables; for a Pipeline downstream build, any variables set globally on env') + property(name: 'changeSets', type: String, doc: 'a list of changesets coming from distinct SCM checkouts; each has a kind and is a list of commits; each commit has a commitId, timestamp, msg, author, and affectedFiles each of which has an editType and path; the value will not generally be Serializable so you may only access it inside a method marked @NonCPS') + property(name: 'rawBuild', type: String, doc: 'a hudson.model.Run with further APIs, only for trusted libraries or administrator-approved scripts outside the sandbox; the value will not be Serializable so you may only access it inside a method marked @NonCPS') +} + +// This is a dummy Library annotation for the IntellijIDEA to compile the pipelines code locally +// It is not used in runtime, in the runtime (on the real Jenkins) the Jenkins built-in 'Library' annotation is used +@interface Library { + String value() +} diff --git a/src/ru/pulsar/jenkins/library/IStepExecutor.groovy b/src/ru/pulsar/jenkins/library/IStepExecutor.groovy index acf5baca..8a2f6e8c 100644 --- a/src/ru/pulsar/jenkins/library/IStepExecutor.groovy +++ b/src/ru/pulsar/jenkins/library/IStepExecutor.groovy @@ -7,6 +7,9 @@ import jenkins.plugins.http_request.ResponseContentSupplier import org.jenkinsci.plugins.pipeline.utility.steps.fs.FileWrapper import org.jenkinsci.plugins.workflow.support.actions.EnvironmentAction import org.jenkinsci.plugins.workflow.support.steps.build.RunWrapper +import ru.pulsar.jenkins.library.configuration.JobConfiguration +import ru.pulsar.jenkins.library.configuration.StepCoverageOptions +import ru.pulsar.jenkins.library.steps.Coverable interface IStepExecutor { @@ -20,6 +23,7 @@ interface IStepExecutor { FileWrapper[] findFiles(String glob) + @SuppressWarnings('unused') FileWrapper[] findFiles(String glob, String excludes) String readFile(String file) @@ -40,6 +44,8 @@ interface IStepExecutor { def ringCommand(String script) + void start(String executable, String params) + void tool(String toolName) def withCredentials(List bindings, Closure body) @@ -64,6 +70,10 @@ interface IStepExecutor { def withEnv(List strings, Closure body) + def withCoverage(JobConfiguration config, Coverable stage, StepCoverageOptions options, Closure body) + + def lock(String resource, Closure body) + def archiveArtifacts(String path) def stash(String name, String includes) @@ -76,14 +86,17 @@ interface IStepExecutor { def zip(String dir, String zipFile) + @SuppressWarnings('unused') def zip(String dir, String zipFile, String glob) def unzip(String dir, String zipFile) + @SuppressWarnings('unused') def unzip(String dir, String zipFile, quiet) def catchError(Closure body) + @SuppressWarnings('unused') ResponseContentSupplier httpRequest(String url, String outputFile, String responseHandle, boolean wrapAsMultipart) ResponseContentSupplier httpRequest(String url, HttpMode httpMode, MimeType contentType, String requestBody, String validResponseCodes, boolean consoleLogResponseBody) diff --git a/src/ru/pulsar/jenkins/library/StepExecutor.groovy b/src/ru/pulsar/jenkins/library/StepExecutor.groovy index e2599343..d02bbfc9 100644 --- a/src/ru/pulsar/jenkins/library/StepExecutor.groovy +++ b/src/ru/pulsar/jenkins/library/StepExecutor.groovy @@ -7,6 +7,9 @@ import jenkins.plugins.http_request.ResponseContentSupplier import org.jenkinsci.plugins.pipeline.utility.steps.fs.FileWrapper import org.jenkinsci.plugins.workflow.support.actions.EnvironmentAction import org.jenkinsci.plugins.workflow.support.steps.build.RunWrapper +import ru.pulsar.jenkins.library.configuration.JobConfiguration +import ru.pulsar.jenkins.library.configuration.StepCoverageOptions +import ru.pulsar.jenkins.library.steps.Coverable import ru.yandex.qatools.allure.jenkins.config.ResultsConfig class StepExecutor implements IStepExecutor { @@ -72,6 +75,18 @@ class StepExecutor implements IStepExecutor { return steps.ringCommand(script) } + @Override + void start(String executable, String params) { + if (executable == null || executable.trim().isEmpty()) { + throw new IllegalArgumentException("executable не может быть пустым") + } + try { + steps.start(executable, params) + } catch (Exception e) { + throw new RuntimeException("Ошибка при запуске процесса: ${e.message}", e) + } + } + @Override void tool(String toolName) { steps.tool toolName @@ -144,6 +159,18 @@ class StepExecutor implements IStepExecutor { } } + @Override + def withCoverage(JobConfiguration config, Coverable stage, StepCoverageOptions options, Closure body) { + steps.withCoverage(config, stage, options, body) + } + + @Override + def lock(String resource, Closure body) { + steps.lock(resource: resource) { + body() + } + } + @Override def archiveArtifacts(String path) { steps.archiveArtifacts path diff --git a/src/ru/pulsar/jenkins/library/configuration/BddOptions.groovy b/src/ru/pulsar/jenkins/library/configuration/BddOptions.groovy index 95e74586..d82a1788 100644 --- a/src/ru/pulsar/jenkins/library/configuration/BddOptions.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/BddOptions.groovy @@ -5,7 +5,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties import com.fasterxml.jackson.annotation.JsonPropertyDescription @JsonIgnoreProperties(ignoreUnknown = true) -class BddOptions implements Serializable { +class BddOptions extends StepCoverageOptions implements Serializable { @JsonPropertyDescription("""Шаги, запускаемые через vrunner. В каждой строке передается отдельная команда @@ -21,6 +21,8 @@ class BddOptions implements Serializable { String toString() { return "BddOptions{" + "vrunnerSteps=" + vrunnerSteps + - '}'; + "coverage=" + coverage + + "dbgsPort=" + dbgsPort + + '}' } } diff --git a/src/ru/pulsar/jenkins/library/configuration/ConfigurationReader.groovy b/src/ru/pulsar/jenkins/library/configuration/ConfigurationReader.groovy index 51465af4..477fbfa3 100644 --- a/src/ru/pulsar/jenkins/library/configuration/ConfigurationReader.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/ConfigurationReader.groovy @@ -14,23 +14,23 @@ import static java.util.Collections.emptySet class ConfigurationReader implements Serializable { private static ObjectMapper mapper - private static BeanUtilsBean beanUtilsBean; + private static BeanUtilsBean beanUtilsBean static { mapper = new ObjectMapper() - mapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true); + mapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true) beanUtilsBean = new BeanUtilsBean(new ConvertUtilsBean() { @Override @NonCPS Object convert(String value, Class clazz) { if (clazz.isEnum()) { - return Enum.valueOf(clazz, value); + return Enum.valueOf(clazz, value) } else { - return super.convert(value, clazz); + return super.convert(value, clazz) } } - }); + }) } private static final String DEFAULT_CONFIGURATION_RESOURCE = 'globalConfiguration.json' @@ -49,7 +49,7 @@ class ConfigurationReader implements Serializable { def globalConfiguration = create() def jobConfiguration = mapper.readValue(config, JobConfiguration.class) - return mergeConfigurations(globalConfiguration, jobConfiguration); + return mergeConfigurations(globalConfiguration, jobConfiguration) } private static JobConfiguration mergeConfigurations( @@ -65,6 +65,7 @@ class ConfigurationReader implements Serializable { "bddOptions", "sonarQubeOptions", "smokeTestOptions", + "coverageOptions", "yaxunitOptions", "syntaxCheckOptions", "resultsTransformOptions", @@ -84,7 +85,7 @@ class ConfigurationReader implements Serializable { mergeSyntaxCheckOptions(baseConfiguration.syntaxCheckOptions, configurationToMerge.syntaxCheckOptions) mergeNotificationsOptions(baseConfiguration.notificationsOptions, configurationToMerge.notificationsOptions) - return baseConfiguration; + return baseConfiguration } @NonCPS @@ -95,7 +96,7 @@ class ConfigurationReader implements Serializable { .filter({ e -> e.getKey() != "metaClass" }) .filter({ e -> !nonMergeableSettings.contains(e.getKey()) }) .forEach { e -> - beanUtilsBean.setProperty(baseObject, e.getKey(), e.getValue()); + beanUtilsBean.setProperty(baseObject, e.getKey(), e.getValue()) } nonMergeableSettings.forEach({ key -> diff --git a/src/ru/pulsar/jenkins/library/configuration/GlobalCoverageOptions.groovy b/src/ru/pulsar/jenkins/library/configuration/GlobalCoverageOptions.groovy new file mode 100644 index 00000000..925f8191 --- /dev/null +++ b/src/ru/pulsar/jenkins/library/configuration/GlobalCoverageOptions.groovy @@ -0,0 +1,29 @@ +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 GlobalCoverageOptions implements Serializable { + + @JsonPropertyDescription('''Путь к исполняемому файлу dbgs. + По умолчанию ищется с помощью v8find для указанной версии платформы (v8version). + ''') + String dbgsPath + + @JsonPropertyDescription('''Путь к исполняемому файлу Coverage41C + По умолчанию ищется в PATH. + ''') + String coverage41CPath + + @Override + @NonCPS + String toString() { + return "coverageOptions{" + + "dbgsPath=" + dbgsPath + + ", coverage41CPath=" + coverage41CPath + + '}' + } + +} diff --git a/src/ru/pulsar/jenkins/library/configuration/JobConfiguration.groovy b/src/ru/pulsar/jenkins/library/configuration/JobConfiguration.groovy index 3175d42f..cfedcede 100644 --- a/src/ru/pulsar/jenkins/library/configuration/JobConfiguration.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/JobConfiguration.groovy @@ -56,6 +56,10 @@ class JobConfiguration implements Serializable { @JsonPropertyDescription("Настройки дымового тестирования") SmokeTestOptions smokeTestOptions + @JsonProperty("coverage") + @JsonPropertyDescription("Настройки замеров покрытия") + GlobalCoverageOptions coverageOptions + @JsonProperty("yaxunit") @JsonPropertyDescription("Настройки YAXUnit") YaxunitOptions yaxunitOptions @@ -89,6 +93,7 @@ class JobConfiguration implements Serializable { ", sonarQubeOptions=" + sonarQubeOptions + ", syntaxCheckOptions=" + syntaxCheckOptions + ", smokeTestOptions=" + smokeTestOptions + + ", coverageOptions=" + coverageOptions + ", yaxunitOptions=" + yaxunitOptions + ", resultsTransformOptions=" + resultsTransformOptions + ", notificationOptions=" + notificationsOptions + diff --git a/src/ru/pulsar/jenkins/library/configuration/SmokeTestOptions.groovy b/src/ru/pulsar/jenkins/library/configuration/SmokeTestOptions.groovy index fd07c2ae..563acb6a 100644 --- a/src/ru/pulsar/jenkins/library/configuration/SmokeTestOptions.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/SmokeTestOptions.groovy @@ -5,7 +5,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties import com.fasterxml.jackson.annotation.JsonPropertyDescription @JsonIgnoreProperties(ignoreUnknown = true) -class SmokeTestOptions implements Serializable { +class SmokeTestOptions extends StepCoverageOptions implements Serializable { @JsonPropertyDescription("""Путь к конфигурационному файлу vanessa-runner. По умолчанию содержит значение "./tools/vrunner.json". @@ -15,7 +15,7 @@ class SmokeTestOptions implements Serializable { @JsonPropertyDescription("""Путь к конфигурационному файлу для xddTestRunner. По умолчанию содержит значение "./tools/xUnitParams.json". """) - String xddConfigPath; + String xddConfigPath @JsonPropertyDescription("""Выполнять публикацию результатов в отчет Allure. По умолчанию выключено. @@ -35,6 +35,8 @@ class SmokeTestOptions implements Serializable { ", xddConfigPath='" + xddConfigPath + '\'' + ", publishToAllureReport=" + publishToAllureReport + ", publishToJUnitReport=" + publishToJUnitReport + + ", coverage=" + coverage + + ", dbgsPort=" + dbgsPort + '}' } } diff --git a/src/ru/pulsar/jenkins/library/configuration/StepCoverageOptions.groovy b/src/ru/pulsar/jenkins/library/configuration/StepCoverageOptions.groovy new file mode 100644 index 00000000..47f95b6c --- /dev/null +++ b/src/ru/pulsar/jenkins/library/configuration/StepCoverageOptions.groovy @@ -0,0 +1,16 @@ +package ru.pulsar.jenkins.library.configuration + +import com.fasterxml.jackson.annotation.JsonProperty +import com.fasterxml.jackson.annotation.JsonPropertyDescription + +class StepCoverageOptions implements Serializable { + + @JsonPropertyDescription("Выполнять замер покрытия") + @JsonProperty(defaultValue = "false") + Boolean coverage = false + + @JsonPropertyDescription("Порт, на котором будет запущен сервер отладки для замера покрытия") + @JsonProperty(defaultValue = "1550") + Integer dbgsPort = 1550 + +} diff --git a/src/ru/pulsar/jenkins/library/configuration/YaxunitOptions.groovy b/src/ru/pulsar/jenkins/library/configuration/YaxunitOptions.groovy index c285fa1a..eae18a79 100644 --- a/src/ru/pulsar/jenkins/library/configuration/YaxunitOptions.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/YaxunitOptions.groovy @@ -5,7 +5,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties import com.fasterxml.jackson.annotation.JsonPropertyDescription @JsonIgnoreProperties(ignoreUnknown = true) -class YaxunitOptions implements Serializable { +class YaxunitOptions extends StepCoverageOptions implements Serializable { @JsonPropertyDescription("""Путь к конфигурационному файлу vanessa-runner. По умолчанию содержит значение "./tools/vrunner.json". @@ -35,6 +35,8 @@ class YaxunitOptions implements Serializable { ", configPath='" + configPath + ", publishToAllureReport='" + publishToAllureReport + ", publishToJUnitReport='" + publishToJUnitReport + + ", coverage='" + coverage + + ", dbgsPort='" + dbgsPort + '}' } } diff --git a/src/ru/pulsar/jenkins/library/steps/Bdd.groovy b/src/ru/pulsar/jenkins/library/steps/Bdd.groovy index 8bb41c26..510980c4 100644 --- a/src/ru/pulsar/jenkins/library/steps/Bdd.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Bdd.groovy @@ -6,10 +6,15 @@ import ru.pulsar.jenkins.library.ioc.ContextRegistry import ru.pulsar.jenkins.library.utils.Logger import ru.pulsar.jenkins.library.utils.VRunner -class Bdd implements Serializable { +class Bdd implements Serializable, Coverable { private final JobConfiguration config + public static final String ALLURE_STASH = 'bdd-allure' + public static final String COVERAGE_STASH_NAME = 'bdd-coverage' + public static final String COVERAGE_STASH_PATH = 'build/out/bdd-coverage.xml' + public static final String COVERAGE_PIDS_PATH = 'build/bdd-pids' + Bdd(JobConfiguration config) { this.config = config } @@ -24,28 +29,55 @@ class Bdd implements Serializable { return } + def options = config.bddOptions + List logosConfig = ["LOGOS_CONFIG=$config.logosConfig"] steps.withEnv(logosConfig) { steps.installLocalDependencies() steps.createDir('build/out') List returnStatuses = [] - config.bddOptions.vrunnerSteps.each { - Logger.println("Шаг запуска сценариев командой ${it}") - String vrunnerPath = VRunner.getVRunnerPath() - Integer bddReturnStatus = VRunner.exec("$vrunnerPath ${it} --ibconnection \"/F./build/ib\"", true) - returnStatuses.add(bddReturnStatus) - } - if (Collections.max(returnStatuses) > 2) { - steps.error("Получен неожиданный/неверный результат работы. Возможно, работа 1С:Предприятие завершилась некорректно, или возникла ошибка при запуске") - } else if (returnStatuses.contains(1)) { - steps.unstable("Тестирование сценариев завершилось, но часть фич/сценариев упала") - } else { - Logger.println("Тестирование сценариев завершилось успешно") + steps.withCoverage(config, this, options) { + + config.bddOptions.vrunnerSteps.each { + Logger.println("Шаг запуска сценариев командой ${it}") + String vrunnerPath = VRunner.getVRunnerPath() + Integer bddReturnStatus = VRunner.exec("$vrunnerPath ${it} --ibconnection \"/F./build/ib\"", true) + returnStatuses.add(bddReturnStatus) + } + + if (Collections.max(returnStatuses) > 2) { + steps.error("Получен неожиданный/неверный результат работы. Возможно, работа 1С:Предприятие завершилась некорректно, или возникла ошибка при запуске") + } else if (returnStatuses.contains(1)) { + steps.unstable("Тестирование сценариев завершилось, но часть фич/сценариев упала") + } else { + Logger.println("Тестирование сценариев завершилось успешно") + } } } - steps.stash('bdd-allure', 'build/out/allure/**', true) + steps.stash(ALLURE_STASH, 'build/out/allure/**', true) steps.stash('bdd-cucumber', 'build/out/cucumber/**', true) + + } + + @Override + String getStageSlug() { + return "bdd" + } + + @Override + String getCoverageStashPath() { + return COVERAGE_STASH_PATH + } + + @Override + String getCoverageStashName() { + return COVERAGE_STASH_NAME + } + + @Override + String getCoveragePidsPath() { + return COVERAGE_PIDS_PATH } } diff --git a/src/ru/pulsar/jenkins/library/steps/Coverable.groovy b/src/ru/pulsar/jenkins/library/steps/Coverable.groovy new file mode 100644 index 00000000..ca6473e2 --- /dev/null +++ b/src/ru/pulsar/jenkins/library/steps/Coverable.groovy @@ -0,0 +1,10 @@ +package ru.pulsar.jenkins.library.steps + +interface Coverable { + + String getStageSlug(); + String getCoverageStashPath(); + String getCoverageStashName(); + String getCoveragePidsPath(); + +} \ No newline at end of file diff --git a/src/ru/pulsar/jenkins/library/steps/CoverageContext.groovy b/src/ru/pulsar/jenkins/library/steps/CoverageContext.groovy new file mode 100644 index 00000000..06e1ca7d --- /dev/null +++ b/src/ru/pulsar/jenkins/library/steps/CoverageContext.groovy @@ -0,0 +1,25 @@ +package ru.pulsar.jenkins.library.steps + +import ru.pulsar.jenkins.library.configuration.GlobalCoverageOptions + +class CoverageContext { + + String lockableResource + String srcDir + GlobalCoverageOptions coverageOptions + int port + List pids + List dbgsPids + List coverage41CPids + + CoverageContext(String lockableResource, String srcDir, GlobalCoverageOptions coverageOptions, int port, List dbgsPids, List coverage41CPids) { + this.lockableResource = lockableResource + this.srcDir = srcDir + this.coverageOptions = coverageOptions + this.port = port + this.pids = dbgsPids + coverage41CPids + this.dbgsPids = dbgsPids + this.coverage41CPids = coverage41CPids + } + +} diff --git a/src/ru/pulsar/jenkins/library/steps/GetExtensions.groovy b/src/ru/pulsar/jenkins/library/steps/GetExtensions.groovy index 4fac658e..d0ec31f4 100644 --- a/src/ru/pulsar/jenkins/library/steps/GetExtensions.groovy +++ b/src/ru/pulsar/jenkins/library/steps/GetExtensions.groovy @@ -16,7 +16,7 @@ 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; + private final JobConfiguration config GetExtensions(JobConfiguration config) { this.config = config @@ -29,9 +29,9 @@ class GetExtensions implements Serializable { def env = steps.env() - steps.installLocalDependencies(); + steps.installLocalDependencies() - String vrunnerPath = initVRunnerPath(); + String vrunnerPath = initVRunnerPath() Logger.println("Сборка расширений") @@ -88,7 +88,7 @@ class GetExtensions implements Serializable { private void extractConvertedExtensions(String sourceDirName, IStepExecutor steps) { if (config.sourceFormat == SourceFormat.EDT) { - // usntash and unzip the edt to designer format transformation + // unstash and unzip the edt to designer format transformation steps.unstash(EdtToDesignerFormatTransformation.EXTENSION_ZIP_STASH) steps.unzip(sourceDirName, EdtToDesignerFormatTransformation.EXTENSION_ZIP) } diff --git a/src/ru/pulsar/jenkins/library/steps/PublishAllure.groovy b/src/ru/pulsar/jenkins/library/steps/PublishAllure.groovy index f3fb372f..40a58d6a 100644 --- a/src/ru/pulsar/jenkins/library/steps/PublishAllure.groovy +++ b/src/ru/pulsar/jenkins/library/steps/PublishAllure.groovy @@ -31,13 +31,13 @@ class PublishAllure implements Serializable { safeUnstash('init-allure') } if (config.stageFlags.bdd) { - safeUnstash('bdd-allure') + safeUnstash(Bdd.ALLURE_STASH) } if (config.stageFlags.yaxunit && config.yaxunitOptions.publishToAllureReport) { safeUnstash(Yaxunit.YAXUNIT_ALLURE_STASH) } if (config.stageFlags.smoke && config.smokeTestOptions.publishToAllureReport) { - safeUnstash(SmokeTest.SMOKE_ALLURE_STASH) + safeUnstash(SmokeTest.ALLURE_STASH) } def env = steps.env() diff --git a/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy b/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy index 6b1f946b..40764c53 100644 --- a/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy +++ b/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy @@ -9,9 +9,12 @@ import ru.pulsar.jenkins.library.utils.Logger import ru.pulsar.jenkins.library.utils.StringJoiner import ru.pulsar.jenkins.library.utils.VRunner -class SmokeTest implements Serializable { +class SmokeTest implements Serializable, Coverable { - public static final String SMOKE_ALLURE_STASH = 'smoke-allure' + public static final String ALLURE_STASH = 'smoke-allure' + public static final String COVERAGE_STASH_NAME = 'smoke-coverage' + public static final String COVERAGE_STASH_PATH = 'build/out/smoke-coverage.xml' + public static final String COVERAGE_PIDS_PATH = 'build/smoke-pids' private final JobConfiguration config @@ -101,18 +104,40 @@ class SmokeTest implements Serializable { } steps.withEnv(logosConfig) { - VRunner.exec(command, true) - } - if (options.publishToAllureReport) { - steps.stash(SMOKE_ALLURE_STASH, "$allureReportDir/**", true) - steps.archiveArtifacts("$allureReportDir/**") - } + steps.withCoverage(config, this, options) { + VRunner.exec(command, true) + } - if (options.publishToJUnitReport) { - steps.junit("$junitReportDir/*.xml", true) - steps.archiveArtifacts("$junitReportDir/**") + if (options.publishToAllureReport) { + steps.stash(ALLURE_STASH, "$allureReportDir/**", true) + steps.archiveArtifacts("$allureReportDir/**") + } + + if (options.publishToJUnitReport) { + steps.junit("$junitReportDir/*.xml", true) + steps.archiveArtifacts("$junitReportDir/**") + } } + } + + @Override + String getStageSlug() { + return "smoke" + } + + @Override + String getCoverageStashPath() { + return COVERAGE_STASH_PATH + } + + @Override + String getCoverageStashName() { + return COVERAGE_STASH_NAME + } + @Override + String getCoveragePidsPath() { + return COVERAGE_PIDS_PATH } } diff --git a/src/ru/pulsar/jenkins/library/steps/SonarScanner.groovy b/src/ru/pulsar/jenkins/library/steps/SonarScanner.groovy index 5b9808b2..4c0494a7 100644 --- a/src/ru/pulsar/jenkins/library/steps/SonarScanner.groovy +++ b/src/ru/pulsar/jenkins/library/steps/SonarScanner.groovy @@ -7,6 +7,7 @@ import ru.pulsar.jenkins.library.configuration.ResultsTransformerType import ru.pulsar.jenkins.library.configuration.SourceFormat import ru.pulsar.jenkins.library.ioc.ContextRegistry import ru.pulsar.jenkins.library.utils.Logger +import ru.pulsar.jenkins.library.utils.StringJoiner import ru.pulsar.jenkins.library.utils.VersionParser class SonarScanner implements Serializable { @@ -68,6 +69,31 @@ class SonarScanner implements Serializable { } } + def stageFlags = config.stageFlags + + StringJoiner coveragePathsConstructor = new StringJoiner(",") + + if (stageFlags.bdd && config.bddOptions.coverage) { + steps.unstash(Bdd.COVERAGE_STASH_NAME) + coveragePathsConstructor.add(Bdd.COVERAGE_STASH_PATH) + } + + if (stageFlags.smoke && config.smokeTestOptions.coverage) { + steps.unstash(SmokeTest.COVERAGE_STASH_NAME) + coveragePathsConstructor.add(SmokeTest.COVERAGE_STASH_PATH) + } + + if (stageFlags.yaxunit && config.yaxunitOptions.coverage) { + steps.unstash(Yaxunit.COVERAGE_STASH_NAME) + coveragePathsConstructor.add(Yaxunit.COVERAGE_STASH_PATH) + } + + String coveragePaths = coveragePathsConstructor.toString() + + if (!coveragePaths.isEmpty()) { + sonarCommand += " -Dsonar.coverageReportPaths=${coveragePaths}" + } + if (config.sonarQubeOptions.waitForQualityGate) { def timeoutInSeconds = config.timeoutOptions.sonarqube * 60 sonarCommand += ' -Dsonar.qualitygate.wait=true' diff --git a/src/ru/pulsar/jenkins/library/steps/Start.groovy b/src/ru/pulsar/jenkins/library/steps/Start.groovy new file mode 100644 index 00000000..5636ceaa --- /dev/null +++ b/src/ru/pulsar/jenkins/library/steps/Start.groovy @@ -0,0 +1,46 @@ +package ru.pulsar.jenkins.library.steps + +import ru.pulsar.jenkins.library.IStepExecutor +import ru.pulsar.jenkins.library.ioc.ContextRegistry + +class Start implements Serializable { + + private String executable + private String params + private String encoding = 'UTF-8' + + Start(String executable, String params) { + this.executable = executable + this.params = params + }; + + void run() { + IStepExecutor steps = ContextRegistry.getContext().getStepExecutor() + def env = steps.env() + + def executable_name = getExecutableName(executable) + if (steps.isUnix()) { + steps.sh("$executable $params > \"./build/${env.STAGE_NAME}-start-${executable_name}.log\" 2>&1 &", false, false , encoding) + } else { + steps.bat("chcp 65001 > nul \nstart \"\" /B \"$executable\" $params > \"./build/${env.STAGE_NAME}-start-${executable_name}.log\" 2>&1", false, false, encoding) + } + } + + static String getExecutableName(String executable) { + + IStepExecutor steps = ContextRegistry.getContext().getStepExecutor() + + String normalizedPath = executable.replace("\\", "/") + String executableName = normalizedPath.substring(normalizedPath.lastIndexOf("/") + 1) + + // Remove the file extension if it exists on Windows systems (e.g., .exe, .cmd, .bat) + if (!steps.isUnix()) { + int extensionIndex = executableName.lastIndexOf(".") + if (extensionIndex != -1) { + executableName = executableName.substring(0, extensionIndex) + } + } + + return executableName + } +} diff --git a/src/ru/pulsar/jenkins/library/steps/WithCoverage.groovy b/src/ru/pulsar/jenkins/library/steps/WithCoverage.groovy new file mode 100644 index 00000000..2909a3f1 --- /dev/null +++ b/src/ru/pulsar/jenkins/library/steps/WithCoverage.groovy @@ -0,0 +1,185 @@ +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.StepCoverageOptions +import ru.pulsar.jenkins.library.ioc.ContextRegistry +import ru.pulsar.jenkins.library.utils.FileUtils +import ru.pulsar.jenkins.library.utils.Logger + +class WithCoverage implements Serializable { + + private final JobConfiguration config + private final Coverable stage + private final StepCoverageOptions coverageOptions + private final Closure body + + WithCoverage(JobConfiguration config, Coverable stage, StepCoverageOptions coverageOptions, Closure body) { + this.config = config + this.stage = stage + this.coverageOptions = coverageOptions + this.body = body + } + + def run() { + + if (!coverageOptions.coverage) { + body() + return + } + + def context = prepareContext(config, coverageOptions) + IStepExecutor steps = ContextRegistry.getContext().getStepExecutor() + + steps.lock(context.lockableResource) { + try { + + startCoverage(steps, config, context, stage) + + body() + + stopCoverage(steps, config, context) + + steps.stash(stage.getCoverageStashName(), stage.getCoverageStashPath(), true) + + } catch (Exception e) { + Logger.println("При выполнении блока произошла ошибка: ${e.message}") + throw e + } finally { + + String pidsFilePath = "build/${stage.getStageSlug()}-pids" + + def pids = "" + if (steps.fileExists(pidsFilePath)) { + pids = steps.readFile(pidsFilePath) + } + + if (pids.isEmpty()) { + Logger.println("Нет запущенных процессов dbgs и Coverage41C") + return + } + + Logger.println("Завершение процессов dbgs и Coverage41C с pid: $pids") + def command + if (steps.isUnix()) { + command = "kill $pids || true" + } else { + def pidsForCmd = '' + def pidsArray = pids.split(" ") + + pidsArray.each { + pidsForCmd += " /PID $it" + } + pidsForCmd = pidsForCmd.trim() + + command = "taskkill $pidsForCmd /F > nul" + + } + steps.cmd(command, false, false) + } + } + } + + static List getPIDs(String name) { + + IStepExecutor steps = ContextRegistry.getContext().getStepExecutor() + + String pids + def script + + if (steps.isUnix()) { + script = "ps -C '$name' -o pid= || true" + pids = steps.sh(script, false, true, 'UTF-8') + } else { + script = """@echo off + chcp 65001 > nul + tasklist | findstr "${name}" > nul + if errorlevel 1 ( + exit /b 0 + ) else ( + for /f "tokens=2" %%a in ('tasklist ^| findstr "${name}"') do (@echo %%a) + )""" + pids = steps.bat(script, false, true, 'UTF-8') + } + return pids.split('\r?\n').toList() + } + + static CoverageContext prepareContext(JobConfiguration config, StepCoverageOptions options) { + + IStepExecutor steps = ContextRegistry.getContext().getStepExecutor() + def env = steps.env() + + def coverageOpts = config.coverageOptions + def port = options.dbgsPort + def currentDbgsPids = getPIDs("dbgs") + def currentCoverage41CPids = getPIDs("Coverage41C") + def lockableResource = "${env.NODE_NAME}_$port" + + return new CoverageContext(lockableResource, config.srcDir, coverageOpts, port, currentDbgsPids, currentCoverage41CPids) + + } + + static void startCoverage(IStepExecutor steps, JobConfiguration config, CoverageContext coverageContext, Coverable stage) { + + def env = steps.env() + def srcDir = config.srcDir + def workspaceDir = FileUtils.getFilePath("$env.WORKSPACE") + + def coverageOpts = config.coverageOptions + + String dbgsPath = findDbgs(steps, config) + + steps.start(dbgsPath, "--addr=127.0.0.1 --port=${coverageContext.port}") + steps.start(coverageOpts.coverage41CPath, "start -i DefAlias -u http://127.0.0.1:${coverageContext.port} -P $workspaceDir -s $srcDir -o ${stage.getCoverageStashPath()}") + steps.cmd("${coverageOpts.coverage41CPath} check -i DefAlias -u http://127.0.0.1:${coverageContext.port}") + + def newDbgsPids = getPIDs("dbgs") + def newCoverage41CPids = getPIDs("Coverage41C") + + newDbgsPids.removeAll(coverageContext.dbgsPids) + newCoverage41CPids.removeAll(coverageContext.coverage41CPids) + + newDbgsPids.addAll(newCoverage41CPids) + def pids = newDbgsPids.join(" ") + + steps.writeFile(stage.getCoveragePidsPath(), pids, 'UTF-8') + + Logger.println("PID процессов dbgs и Coverage41C для ${stage.getStageSlug()}: $pids") + } + + static void stopCoverage(IStepExecutor steps, JobConfiguration config, CoverageContext coverageContext) { + + def coverageOpts = config.coverageOptions + + steps.cmd("${coverageOpts.coverage41CPath} stop -i DefAlias -u http://127.0.0.1:$coverageContext.port") + } + + static String findDbgs(IStepExecutor steps, JobConfiguration config) { + if (steps == null || config == null) { + throw new IllegalArgumentException("Некорректные параметры поиска dbgs") + } + + String dbgsPath = config.coverageOptions.dbgsPath + if (!dbgsPath.isEmpty()) { + Logger.println("Использую путь к dbgs из параметра dbgsPath: $dbgsPath") + return dbgsPath.strip() + } + + final dbgsFindScriptPath = "build/tmp/dbgs_${System.currentTimeMillis()}.os" + final dbgsPathResult = "build/tmp/dbgsPath_${System.currentTimeMillis()}" + + def dbgsFindScript = steps.libraryResource("dbgs.os") + steps.writeFile(dbgsFindScriptPath, dbgsFindScript, 'UTF-8') + + steps.cmd("oscript ${dbgsFindScriptPath} ${config.v8version} > ${dbgsPathResult}") + dbgsPath = steps.readFile(dbgsPathResult).strip() + + if (dbgsPath.isEmpty()) { + steps.error("Не удалось найти путь к dbgs") + } + + Logger.println("Найден путь к dbgs: ${dbgsPath}") + return dbgsPath + } + +} diff --git a/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy b/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy index 2587d0bb..317059e0 100644 --- a/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy @@ -2,20 +2,22 @@ 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 { +class Yaxunit implements Serializable, Coverable { private final JobConfiguration config - private final String DEFAULT_YAXUNIT_CONFIGURATION_RESOURCE = 'yaxunit.json' + private static final String DEFAULT_YAXUNIT_CONFIGURATION_RESOURCE = 'yaxunit.json' public static final String YAXUNIT_ALLURE_STASH = 'yaxunit-allure' + public static final String COVERAGE_STASH_NAME = 'yaxunit-coverage' + public static final String COVERAGE_STASH_PATH = 'build/out/yaxunit-coverage.xml' + public static final String COVERAGE_PIDS_PATH = 'build/yaxunit-pids' Yaxunit(JobConfiguration config) { this.config = config @@ -45,10 +47,11 @@ class Yaxunit implements Serializable { // Готовим конфиг для yaxunit String yaxunitConfigPath = options.configPath if (!steps.fileExists(yaxunitConfigPath)) { + Logger.println("Using default yaxunit config") def defaultYaxunitConfig = steps.libraryResource DEFAULT_YAXUNIT_CONFIGURATION_RESOURCE steps.writeFile(options.configPath, defaultYaxunitConfig, 'UTF-8') } - def yaxunitConfig = FileUtils.getFilePath(yaxunitConfigPath) + def yaxunitConfig = FileUtils.getFilePath("$env.WORKSPACE/$yaxunitConfigPath") // Команда запуска тестов String runTestsCommand = "$vrunnerPath run --command RunUnitTests=$yaxunitConfig $ibConnection" @@ -62,29 +65,52 @@ class Yaxunit implements Serializable { } - // Выполяем команды 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()) + steps.withCoverage(config, this, options) { + VRunner.exec(runTestsCommand, true) + } - if (options.publishToJUnitReport) { - steps.junit("$junitReportDir/*.xml", true) - steps.archiveArtifacts("$junitReportDir/**") - } + // Сохраняем результаты + 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()) + 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) + pathToJUnitReport.copyTo(pathToAllureReport) + + steps.stash(YAXUNIT_ALLURE_STASH, "$allureReportDir/**", true) + } - steps.stash(YAXUNIT_ALLURE_STASH, "$allureReportDir/**", true) } } + + @Override + String getStageSlug() { + return "yaxunit" + } + + @Override + String getCoverageStashPath() { + return COVERAGE_STASH_PATH + } + + @Override + String getCoverageStashName() { + return COVERAGE_STASH_NAME + } + + @Override + String getCoveragePidsPath() { + return COVERAGE_PIDS_PATH + } } diff --git a/test/integration/groovy/jobConfigurationTest.groovy b/test/integration/groovy/jobConfigurationTest.groovy index b2a671ec..c77feecf 100644 --- a/test/integration/groovy/jobConfigurationTest.groovy +++ b/test/integration/groovy/jobConfigurationTest.groovy @@ -74,5 +74,7 @@ class jobConfigurationTest { rule.assertLogContains("v8version='8.3.12.1500'", run) rule.assertLogContains("sonarScannerToolName='sonar-scanner'", run) rule.assertLogContains("initMethod=FROM_SOURCE", run) + rule.assertLogContains("dbgsPath=C:\\Program files\\1cv8\\8.3.12.1500\\bin\\dbgs.exe", run) + rule.assertLogContains("coverage41CPath=C:\\coverage\\Coverage41C.exe", run) } } \ No newline at end of file diff --git a/test/integration/resources/jobConfiguration.json b/test/integration/resources/jobConfiguration.json index 6b3e9d10..ebd5e6fd 100644 --- a/test/integration/resources/jobConfiguration.json +++ b/test/integration/resources/jobConfiguration.json @@ -9,5 +9,10 @@ }] }, "yaxunit": { + "initMethod": "fromSource" + }, + "coverage": { + "dbgsPath": "C:\\\\Program files\\\\1cv8\\\\8.3.12.1500\\\\bin\\\\dbgs.exe", + "coverage41CPath": "C:\\\\coverage\\\\Coverage41C.exe" } } \ No newline at end of file diff --git a/test/unit/groovy/ru/pulsar/jenkins/library/configuration/ConfigurationReaderTest.java b/test/unit/groovy/ru/pulsar/jenkins/library/configuration/ConfigurationReaderTest.java index 9200320b..07e5c37a 100644 --- a/test/unit/groovy/ru/pulsar/jenkins/library/configuration/ConfigurationReaderTest.java +++ b/test/unit/groovy/ru/pulsar/jenkins/library/configuration/ConfigurationReaderTest.java @@ -41,6 +41,9 @@ void testCreateJobConfigurationObject() throws IOException { assertThat(jobConfiguration.getSonarQubeOptions().getUseSonarScannerFromPath()).isTrue(); assertThat(jobConfiguration.getSonarQubeOptions().getBranchAnalysisConfiguration()).isEqualTo(AUTO); + assertThat(jobConfiguration.getCoverageOptions().getDbgsPath()).isEqualTo("/opt/1cv8/current/dbgs"); + assertThat(jobConfiguration.getCoverageOptions().getCoverage41CPath()).isEqualTo("Coverage41C"); + assertThat(jobConfiguration.getSecrets()) .hasFieldOrPropertyWithValue("storage", "1234") .hasFieldOrPropertyWithValue("storagePath", "UNKNOWN_ID") @@ -57,11 +60,16 @@ void testCreateJobConfigurationObject() throws IOException { assertThat(jobConfiguration.getSmokeTestOptions().getVrunnerSettings()).contains("./tools/vrunner-smoke.json"); assertThat(jobConfiguration.getSmokeTestOptions().isPublishToAllureReport()).isFalse(); assertThat(jobConfiguration.getSmokeTestOptions().isPublishToJUnitReport()).isTrue(); + assertThat(jobConfiguration.getSmokeTestOptions().getCoverage()).isTrue(); + assertThat(jobConfiguration.getSmokeTestOptions().getDbgsPort()).isEqualTo(1555); + + assertThat(jobConfiguration.getYaxunitOptions().getDbgsPort()).isEqualTo(1550); assertThat(jobConfiguration.getInitInfoBaseOptions().getRunMigration()).isFalse(); assertThat(jobConfiguration.getInitInfoBaseOptions().getAdditionalInitializationSteps()).contains("vanessa --settings ./tools/vrunner.first.json"); assertThat(jobConfiguration.getBddOptions().getVrunnerSteps()).contains("vanessa --settings ./tools/vrunner.json"); + assertThat(jobConfiguration.getBddOptions().getCoverage()).isFalse(); assertThat(jobConfiguration.getLogosConfig()).isEqualTo("logger.rootLogger=DEBUG"); @@ -113,7 +121,7 @@ void testEdtAgentLabel() throws IOException { assertThat(jobConfiguration.edtAgentLabel()).isEqualTo("edt@2021.3.4:x86_64"); } - @Disabled + @Test void testInfoBaseFromFiles() throws IOException { // given String config = IOUtils.resourceToString( diff --git a/test/unit/groovy/ru/pulsar/jenkins/library/utils/EnvUtils.java b/test/unit/groovy/ru/pulsar/jenkins/library/utils/EnvUtils.java index d621c3e6..629c6561 100644 --- a/test/unit/groovy/ru/pulsar/jenkins/library/utils/EnvUtils.java +++ b/test/unit/groovy/ru/pulsar/jenkins/library/utils/EnvUtils.java @@ -9,6 +9,7 @@ public class EnvUtils implements EnvironmentAction { public String NODE_NAME = "node"; public String WORKSPACE = "ws"; + public String BRANCH_NAME = "master"; @Override public EnvVars getEnvironment() throws IOException, InterruptedException { diff --git a/test/unit/resources/jobConfiguration.json b/test/unit/resources/jobConfiguration.json index 3b3dcbc5..48dfb6fd 100644 --- a/test/unit/resources/jobConfiguration.json +++ b/test/unit/resources/jobConfiguration.json @@ -1,88 +1,99 @@ -{ - "v8version": "8.3.14.1944", - "edtVersion": "2021.3.4:x86_64", - "secrets": { - "storage": "1234" - }, - "stages": { - "syntaxCheck": true - }, - "timeout": { - "zipInfoBase": 123 - }, - "initInfobase": { - "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": { - "sonarQubeInstallation": "qa", - "branchAnalysisConfiguration": "auto" - }, - "syntaxCheck": { - "checkModes": [ - "-ThickClient", - "-ThinClient", - "-WebClient", - "-Server" - ] - }, - "resultsTransform": { - "transformer": "stebi", - "genericIssueFormat": "Generic_Issue", - "removeSupport": false - }, - "smoke": { - "vrunnerSettings": "./tools/vrunner-smoke.json", - "publishToAllureReport": false, - "publishToJUnitReport": true - }, - "notifications": { - "email": { - "onAlways": true, - "alwaysOptions": { - "attachLog": true, - "directRecipients": [ - "1@1.com", - "2@1.com" - ] - }, - "failureOptions": { - "recipientProviders": [ - "developers" - ] - } - }, - "telegram": { - "onAlways": false, - "onFailure": true - } - }, - "logosConfig": "logger.rootLogger=DEBUG" +{ + "v8version": "8.3.14.1944", + "edtVersion": "2021.3.4:x86_64", + "secrets": { + "storage": "1234" + }, + "coverage": { + "dbgsPath": "/opt/1cv8/current/dbgs" + }, + "stages": { + "syntaxCheck": true + }, + "timeout": { + "zipInfoBase": 123 + }, + "initInfobase": { + "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": { + "sonarQubeInstallation": "qa", + "branchAnalysisConfiguration": "auto" + }, + "syntaxCheck": { + "checkModes": [ + "-ThickClient", + "-ThinClient", + "-WebClient", + "-Server" + ] + }, + "resultsTransform": { + "transformer": "stebi", + "genericIssueFormat": "Generic_Issue", + "removeSupport": false + }, + "smoke": { + "vrunnerSettings": "./tools/vrunner-smoke.json", + "publishToAllureReport": false, + "publishToJUnitReport": true, + "coverage": true, + "dbgsPort": 1555 + }, + "notifications": { + "email": { + "onAlways": true, + "alwaysOptions": { + "attachLog": true, + "directRecipients": [ + "1@1.com", + "2@1.com" + ] + }, + "failureOptions": { + "recipientProviders": [ + "developers" + ] + } + }, + "telegram": { + "onAlways": false, + "onFailure": true + } + }, + "logosConfig": "logger.rootLogger=DEBUG" } \ No newline at end of file diff --git a/vars/start.groovy b/vars/start.groovy new file mode 100644 index 00000000..dc10d29b --- /dev/null +++ b/vars/start.groovy @@ -0,0 +1,9 @@ +import ru.pulsar.jenkins.library.steps.Start +import ru.pulsar.jenkins.library.ioc.ContextRegistry + +void call(String executable, String params) { + ContextRegistry.registerDefaultContext(this) + + Start start = new Start(executable, params) + start.run() +} diff --git a/vars/withCoverage.groovy b/vars/withCoverage.groovy new file mode 100644 index 00000000..41ef8e12 --- /dev/null +++ b/vars/withCoverage.groovy @@ -0,0 +1,12 @@ +import ru.pulsar.jenkins.library.configuration.JobConfiguration +import ru.pulsar.jenkins.library.configuration.StepCoverageOptions +import ru.pulsar.jenkins.library.ioc.ContextRegistry +import ru.pulsar.jenkins.library.steps.Coverable +import ru.pulsar.jenkins.library.steps.WithCoverage + +def call(JobConfiguration config, Coverable stage, StepCoverageOptions options, Closure body) { + ContextRegistry.registerDefaultContext(this) + + WithCoverage withCoverage = new WithCoverage(config, stage, options, body) + return withCoverage.run() +} \ No newline at end of file