# Jenkins shared library for 1C:Enterprise 8 ## Цель Создание библиотеки (или плагина) для Jenkins, позволяющей: * максимально упростить написание Jenkinsfile для процесса CI в условиях платформы 1С:Предприятие 8 * иметь схожий и контролируемый пайплайн для всех проектов * дать пользователю в руки простой декларативный конфигурационный файл, вместо требования описывать всю сложную логику по работе с 1С ## Общие положения * в активной разработке и поиске "своего пути" по разработке библиотеки; * формат конфигурационного файла **не** стабилизирован; * обратная совместимость **пока** не гарантируется, внимательно читайте changelog; * количество stage будет со временем увеличиваться; * использовать на свой страх и риск; * любая помощь приветствуется. ## Ограничения 1. Для шага подготовки требуется любой агент с меткой `agent`. 1. Для запуска шага анализа SonarQube требуется агент с меткой `sonar`. 1. Для запуска шагов, работающих с EDT (валидация, трансформация формата исходников) требуется агент с меткой `edt` (если используется несколько версий EDT необходимо к метке добавить версию, например `edt@2021.3.4:x86_64`) и агент с меткой `oscript`, на котором глобально установлена библиотека [stebi](https://github.com/Stepa86/stebi) версии 1.9.1 или новее. 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 и конвертация отчета в формате generic issues. 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: * По умолчанию из результатов анализа исключаются замечания, сработавшие на модулях с включенным запретом редактирования (желтый куб с замком) (параметры `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, результаты валидации в формате `generic issues` передаются утилите `sonar-scanner` как значение параметра `sonar.externalIssuesReportPaths`. * Рассылка уведомлений: * Электронная почта: * Для отправки используется плагин [`email-ext`](https://plugins.jenkins.io/email-ext). Шаблоны сообщений конфигурируются в настройках плагина. * Уведомления о результатах сборки по умолчанию рассылаются только при полном падении сборочной линии (`notifications` -> `email` -> `onAlways`, `onFailure`, `onUnstable`, `onSuccess`). * Лог сборки прикладывается к письму при полном падении сборочной линии и при отправке в режиме "всегда отправлять" (`notifications` -> `email` -> `*options` -> `attachLog`). * В качестве получателей писем (`notifications` -> `email` -> `*options` -> `recipientProviders`) в различных режимах отправки используются: * всегда - разработчики и запустивший сборку; * при падении - разработчики, запустивший сборку и подозреваемый в причине падения сборки; * при успехе - разработчики и запустивший сборку; * при нестабильной сборке (упавшие тесты) - разработчики и запустивший сборку. * Прямые получатели уведомлений не заполнены (`notifications` -> `email` -> `*options` -> `directRecipients`). * Telegram: * Уведомления о результатах сборки по умолчанию рассылаются всегда (`notifications` -> `telegram` -> `onAlways`, `onFailure`, `onUnstable`, `onSuccess`). ## Настройка загрузки расширений Если у вас есть расширения которые необходимо загрузить в базу для проведения тестов и проверок, это можно сделать на этапе подготовки базы. * При загрузке из исходников расширения должны быть в том же формате(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" } ] } ``` ## Настройка шага YAXUnit * Добавить расширение `YAXUnit` и дополнительные расширения с тестами можно в `jobConfiguration.json` -> `initInfobase` -> `extensions`. Они будут загружены при инициализации ИБ. * Если ваши тесты размещены в отдельных расширениях, скопируйте файл `./resources/yaxunit.json` из текущей библиотеки в свой репозиторий (`./tools/yaxunit.json`) и перечислите в нем имена ваших расширений. * Если используется собственный файл `tools/yaxunit.json`, то значение параметра reportPath в нем должно быть равно `./build/out/yaxunit/junit.xml`