From 3d63e5706d4c9c74c5c64f60ede5cc43a425e48c Mon Sep 17 00:00:00 2001 From: Dima Date: Sat, 3 Jun 2023 08:24:19 +0300 Subject: [PATCH 001/112] add coverage --- resources/globalConfiguration.json | 10 +++++-- resources/schema.json | 25 ++++++++++++++++ .../jenkins/library/IStepExecutor.groovy | 2 ++ .../jenkins/library/StepExecutor.groovy | 5 ++++ .../library/configuration/BddOptions.groovy | 4 +++ .../configuration/ConfigurationReader.groovy | 18 ++++++++++++ .../configuration/CoverageOptions.groovy | 29 +++++++++++++++++++ .../configuration/JobConfiguration.groovy | 5 ++++ .../configuration/SmokeTestOptions.groovy | 4 +++ .../pulsar/jenkins/library/steps/Bdd.groovy | 19 ++++++++++++ .../jenkins/library/steps/SmokeTest.groovy | 17 +++++++++++ .../jenkins/library/steps/SonarScanner.groovy | 22 ++++++++++++++ .../pulsar/jenkins/library/steps/Start.groovy | 28 ++++++++++++++++++ .../groovy/jobConfigurationTest.groovy | 2 ++ .../resources/jobConfiguration.json | 5 ++++ .../ConfigurationReaderTest.java | 5 ++++ vars/start.groovy | 9 ++++++ 17 files changed, 207 insertions(+), 2 deletions(-) create mode 100644 src/ru/pulsar/jenkins/library/configuration/CoverageOptions.groovy create mode 100644 src/ru/pulsar/jenkins/library/steps/Start.groovy create mode 100644 vars/start.groovy diff --git a/resources/globalConfiguration.json b/resources/globalConfiguration.json index aa1af975..0032ea0b 100644 --- a/resources/globalConfiguration.json +++ b/resources/globalConfiguration.json @@ -50,7 +50,8 @@ "bdd": { "vrunnerSteps": [ "vanessa --settings ./tools/vrunner.json" - ] + ], + "coverage": false }, "sonarqube": { "sonarQubeInstallation": "", @@ -83,7 +84,12 @@ "vrunnerSettings": "./tools/vrunner.json", "xddConfigPath": "./tools/xUnitParams.json", "publishToAllureReport": false, - "publishToJUnitReport": true + "publishToJUnitReport": true, + "coverage": false + }, + "coverage": { + "dbgsPath": "/opt/1cv8/current/dbgs", + "coverage41CPath": "Coverage41C" }, "yaxunit": { "vrunnerSettings": "./tools/vrunner.json", diff --git a/resources/schema.json b/resources/schema.json index a1c89a0f..50a80c06 100644 --- a/resources/schema.json +++ b/resources/schema.json @@ -81,6 +81,10 @@ "items" : { "type" : "string" } + }, + "coverage" : { + "type" : "boolean", + "description" : "Выполнять замер покрытия" } } } @@ -231,6 +235,27 @@ "type" : "boolean", "description" : "Выполнять публикацию результатов в отчет JUnit.\n По умолчанию включено.\n " }, + "coverage" : { + "type" : "boolean", + "description" : "Выполнять замер покрытия" + } + } + }, + "coverage" : { + "type" : "object", + "id" : "urn:jsonschema:ru:pulsar:jenkins:library:configuration:CoverageOptions", + "description" : "Настройки замеров покрытия", + "properties" : { + "dbgsPath" : { + "type" : "string", + "description" : "Путь к исполняемому файлу dbgs.\n По умолчанию равен /opt/1cv8/current/dbgs.\n " + }, + "coverage41CPath" : { + "type" : "string", + "description" : "Путь к исполняемому файлу Coverage41C\n По умолчанию равен Coverage41C.\n " + } + } + }, "vrunnerSettings" : { "type" : "string", "description" : "Путь к конфигурационному файлу vanessa-runner.\n По умолчанию содержит значение \"./tools/vrunner.json\".\n " diff --git a/src/ru/pulsar/jenkins/library/IStepExecutor.groovy b/src/ru/pulsar/jenkins/library/IStepExecutor.groovy index acf5baca..503ba5c7 100644 --- a/src/ru/pulsar/jenkins/library/IStepExecutor.groovy +++ b/src/ru/pulsar/jenkins/library/IStepExecutor.groovy @@ -40,6 +40,8 @@ interface IStepExecutor { def ringCommand(String script) + void start(String script, boolean returnStatus) + void tool(String toolName) def withCredentials(List bindings, Closure body) diff --git a/src/ru/pulsar/jenkins/library/StepExecutor.groovy b/src/ru/pulsar/jenkins/library/StepExecutor.groovy index e2599343..8315bf09 100644 --- a/src/ru/pulsar/jenkins/library/StepExecutor.groovy +++ b/src/ru/pulsar/jenkins/library/StepExecutor.groovy @@ -72,6 +72,11 @@ class StepExecutor implements IStepExecutor { return steps.ringCommand(script) } + @Override + void start(String script, boolean returnStatus = false) { + steps.start(script, returnStatus) + } + @Override void tool(String toolName) { steps.tool toolName diff --git a/src/ru/pulsar/jenkins/library/configuration/BddOptions.groovy b/src/ru/pulsar/jenkins/library/configuration/BddOptions.groovy index 95e74586..3cab3461 100644 --- a/src/ru/pulsar/jenkins/library/configuration/BddOptions.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/BddOptions.groovy @@ -16,11 +16,15 @@ class BddOptions implements Serializable { 'vanessa --settings ./tools/vrunner.json' ] + @JsonPropertyDescription("Выполнять замер покрытия") + Boolean coverage = false + @Override @NonCPS String toString() { return "BddOptions{" + "vrunnerSteps=" + vrunnerSteps + + "coverage=" + coverage + '}'; } } diff --git a/src/ru/pulsar/jenkins/library/configuration/ConfigurationReader.groovy b/src/ru/pulsar/jenkins/library/configuration/ConfigurationReader.groovy index 51465af4..ba56695b 100644 --- a/src/ru/pulsar/jenkins/library/configuration/ConfigurationReader.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/ConfigurationReader.groovy @@ -65,6 +65,7 @@ class ConfigurationReader implements Serializable { "bddOptions", "sonarQubeOptions", "smokeTestOptions", + "coverageOptions", "yaxunitOptions", "syntaxCheckOptions", "resultsTransformOptions", @@ -81,6 +82,7 @@ class ConfigurationReader implements Serializable { mergeObjects(baseConfiguration, configurationToMerge, nonMergeableSettings) mergeInitInfoBaseOptions(baseConfiguration.initInfoBaseOptions, configurationToMerge.initInfoBaseOptions) mergeBddOptions(baseConfiguration.bddOptions, configurationToMerge.bddOptions) + mergeCoverageOptions(baseConfiguration.coverageOptions, configurationToMerge.coverageOptions) mergeSyntaxCheckOptions(baseConfiguration.syntaxCheckOptions, configurationToMerge.syntaxCheckOptions) mergeNotificationsOptions(baseConfiguration.notificationsOptions, configurationToMerge.notificationsOptions) @@ -147,6 +149,22 @@ class ConfigurationReader implements Serializable { baseObject.vrunnerSteps = objectToMerge.vrunnerSteps.clone() } + @NonCPS + private static void mergeCoverageOptions(CoverageOptions baseObject, CoverageOptions objectToMerge) { + + if (objectToMerge == null) { + return + } + + if (objectToMerge.dbgsPath != null) { + baseObject.dbgsPath = objectToMerge.dbgsPath + } + + if (objectToMerge.coverage41CPath != null) { + baseObject.coverage41CPath = objectToMerge.coverage41CPath + } + } + @NonCPS private static void mergeSyntaxCheckOptions(SyntaxCheckOptions baseObject, SyntaxCheckOptions objectToMerge) { if (objectToMerge == null || objectToMerge.checkModes == null) { diff --git a/src/ru/pulsar/jenkins/library/configuration/CoverageOptions.groovy b/src/ru/pulsar/jenkins/library/configuration/CoverageOptions.groovy new file mode 100644 index 00000000..ef865029 --- /dev/null +++ b/src/ru/pulsar/jenkins/library/configuration/CoverageOptions.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 CoverageOptions implements Serializable { + + @JsonPropertyDescription('''Путь к исполняемому файлу dbgs. + По умолчанию равен /opt/1cv8/current/dbgs. + ''') + String dbgsPath + + @JsonPropertyDescription('''Путь к исполняемому файлу Coverage41C + По умолчанию равен Coverage41C. + ''') + 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..accba947 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("Настройки замеров покрытия") + CoverageOptions 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..dede2a71 100644 --- a/src/ru/pulsar/jenkins/library/configuration/SmokeTestOptions.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/SmokeTestOptions.groovy @@ -27,6 +27,9 @@ class SmokeTestOptions implements Serializable { """) boolean publishToJUnitReport + @JsonPropertyDescription("Выполнять замер покрытия") + Boolean coverage = false + @Override @NonCPS String toString() { @@ -35,6 +38,7 @@ class SmokeTestOptions implements Serializable { ", xddConfigPath='" + xddConfigPath + '\'' + ", publishToAllureReport=" + publishToAllureReport + ", publishToJUnitReport=" + publishToJUnitReport + + "coverage=" + coverage + '}' } } diff --git a/src/ru/pulsar/jenkins/library/steps/Bdd.groovy b/src/ru/pulsar/jenkins/library/steps/Bdd.groovy index 8bb41c26..a1c2eda5 100644 --- a/src/ru/pulsar/jenkins/library/steps/Bdd.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Bdd.groovy @@ -24,11 +24,22 @@ class Bdd implements Serializable { return } + def env = steps.env(); + def srcDir = config.srcDir + def projectDir = new File("$env.WORKSPACE").getCanonicalPath() + List logosConfig = ["LOGOS_CONFIG=$config.logosConfig"] steps.withEnv(logosConfig) { steps.installLocalDependencies() steps.createDir('build/out') List returnStatuses = [] + + def coverageOpts = config.coverageOptions; + if (options.coverage) { + steps.start("${coverageOpts.dbgsPath} --addr=127.0.0.1 --port=1550") + steps.start("${coverageOpts.coverage41CPath} start -i DefAlias -u http://127.0.0.1:1550 -P $projectDir -s $srcDir -o build/out/bdd-coverage.xml") + } + config.bddOptions.vrunnerSteps.each { Logger.println("Шаг запуска сценариев командой ${it}") String vrunnerPath = VRunner.getVRunnerPath() @@ -43,9 +54,17 @@ class Bdd implements Serializable { } else { Logger.println("Тестирование сценариев завершилось успешно") } + + if (options.coverage) { + steps.cmd("${coverageOpts.coverage41CPath} stop -i DefAlias -u http://127.0.0.1:1550") + } } steps.stash('bdd-allure', 'build/out/allure/**', true) steps.stash('bdd-cucumber', 'build/out/cucumber/**', true) + if (options.coverage) { + steps.stash('bdd-coverage', 'build/out/bdd-coverage.xml', true) + } + } } diff --git a/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy b/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy index 6b1f946b..b3d306b3 100644 --- a/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy +++ b/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy @@ -37,6 +37,9 @@ class SmokeTest implements Serializable { def options = config.smokeTestOptions def env = steps.env() + def srcDir = config.srcDir + def projectDir = new File("$env.WORKSPACE").getCanonicalPath() + String vrunnerPath = VRunner.getVRunnerPath() String command = "$vrunnerPath xunit --ibconnection \"/F./build/ib\"" @@ -100,10 +103,20 @@ class SmokeTest implements Serializable { command += " $testsPath" } + def coverageOpts = config.coverageOptions; + if (options.coverage) { + steps.start("${coverageOpts.dbgsPath} --addr=127.0.0.1 --port=1550") + steps.start("${coverageOpts.coverage41CPath} start -i DefAlias -u http://127.0.0.1:1550 -P $projectDir -s $srcDir -o build/out/smoketest-coverage.xml") + } + steps.withEnv(logosConfig) { VRunner.exec(command, true) } + if (options.coverage) { + steps.cmd("${coverageOpts.coverage41CPath} stop -i DefAlias -u http://127.0.0.1:1550") + } + if (options.publishToAllureReport) { steps.stash(SMOKE_ALLURE_STASH, "$allureReportDir/**", true) steps.archiveArtifacts("$allureReportDir/**") @@ -114,5 +127,9 @@ class SmokeTest implements Serializable { steps.archiveArtifacts("$junitReportDir/**") } + if (options.coverage) { + steps.stash('smoketest-coverage', 'build/out/smoketest-coverage.xml', true) + } + } } diff --git a/src/ru/pulsar/jenkins/library/steps/SonarScanner.groovy b/src/ru/pulsar/jenkins/library/steps/SonarScanner.groovy index 5b9808b2..a83ad68c 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,27 @@ class SonarScanner implements Serializable { } } + if (config.stageFlags.bdd && config.bddOptions.coverage + || config.stageFlags.smoke && config.smokeTestOptions.coverage) { + + StringJoiner coveragePathsConstructor = new StringJoiner(",") + + if (config.stageFlags.bdd && config.bddOptions.coverage) { + steps.unstash("bdd-coverage") + coveragePathsConstructor.add("build/out/bdd-coverage.xml") + } + + if (config.stageFlags.smoke && config.smokeTestOptions.coverage) { + steps.unstash("smoketest-coverage") + coveragePathsConstructor.add("build/out/smoketest-coverage.xml") + } + + String coveragePaths = coveragePathsConstructor.toString() + + 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..4d3e2393 --- /dev/null +++ b/src/ru/pulsar/jenkins/library/steps/Start.groovy @@ -0,0 +1,28 @@ +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 script; + private boolean returnStatus + private String encoding = 'UTF-8' + + Start(String script, boolean returnStatus = false) { + this.script = script + this.returnStatus = returnStatus + }; + + int run() { + IStepExecutor steps = ContextRegistry.getContext().getStepExecutor() + + int returnValue + + if (steps.isUnix()) { + returnValue = steps.sh("$script &", returnStatus, encoding) + } else { + returnValue = steps.bat("chcp 65001 > nul \nstart $script", returnStatus, encoding) + } + } +} 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..6886e7a0 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,13 @@ 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()).isFalse(); 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"); diff --git a/vars/start.groovy b/vars/start.groovy new file mode 100644 index 00000000..3e4acf01 --- /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 script, boolean returnStatus = false) { + ContextRegistry.registerDefaultContext(this) + + Start start = new Start(script, returnStatus) + start.run() +} From 265854454f4408fd2141541bf8746a45c97e8d0e Mon Sep 17 00:00:00 2001 From: Dima Date: Sat, 3 Jun 2023 09:09:40 +0300 Subject: [PATCH 002/112] upd README --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 3a20bba0..ddf9fef3 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ * максимально упростить написание Jenkinsfile для процесса CI в условиях платформы 1С:Предприятие 8 * иметь схожий и контролируемый пайплайн для всех проектов -* дать пользователю в руки простой декларативный конфигурационный файл, вместо требования описывать всю сложную логику по работе с 1С +* дать пользователю в руки простой декларативный конфигурационный файл, вместо требования описывать всю сложную логику по работе с 1С ## Общие положения @@ -26,6 +26,7 @@ 1. При использовании EDT версии 2024.1.0 и выше вместо ring используется 1cedtcli, который должен быть прописан в PATH на агенте. 1. Для запуска шагов, работающих с 1С (подготовка, синтаксический контроль и т.д.) требуется агент с меткой, совпадающей со значением в поле `v8version` файла конфигурации. 1. В качестве ИБ используется файловая база, создаваемая в каталоге `./build/ib`. При необходимости вы можете создать пользователей на фазе инициализации ИБ. +1. Для замеров покрытия на агентах должны быть установлены [Coverage41C](https://github.com/1c-syntax/Coverage41C), EDT и сервер отладки dbgs. ## Возможности @@ -46,6 +47,7 @@ 1. Публикация результатов junit и Allure в интерфейс Jenkins. 1. Рассылка результатов сборки на почту и в Telegram. 1. Конфигурирование логгера запускаемых oscript-приложений. +1. Замер покрытия при выполнении тестов. ## Подключение @@ -116,7 +118,7 @@ pipeline1C() * Исходники конфигурации ожидаются в каталоге `src/cf` (`srcDir`). * Формат исходников - выгрузка из Конфигуратора (`sourceFormat`). * Ветка по умолчанию (для комбинированного режима загрузки конфигурации) - "main" (`defaultBranch`). - * Имена большинства "секретов" (jenkins credentials, `secrets`) по умолчанию высчитываются из пути к git-репозиторию (без учета домена, с заменой `/` на `_`) с прибавлением ключа секрета. Например, для репозитория https://github.com/firstBitSemenovskaya/jenkins-lib секрет с адресом хранилища будет выглядеть как `firstBitSemenovskaya_jenkins-lib_STORAGE_PATH`. Ключи секретов: + * Имена большинства "секретов" (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`). @@ -125,7 +127,7 @@ pipeline1C() * Если в корне репозитория существует файл `packagedef`, то в шагах, работающих с информационной базой, будет выполнена попытка установки локальных зависимостей средствами `opm`. * Если после установки локальных зависимостей в каталоге `oscript_modules/bin` существует файл `vrunner`, то для выполнения команд работы с информационной базой будет использоваться он, а не глобально установленный `vrunner` из `PATH`. * Результаты в формате `allure` ожидаются в каталоге `build/out/allure` или его подкаталогах. - * Каждый шаг имеет свой таймаут в минутах (от 10 до 240 в зависимости от "тяжёлости" шага сборки), но может быть переопределен в секции настроек `timeout`. + * Каждый шаг имеет свой таймаут в минутах (от 10 до 240 в зависимости от "тяжёлости" шага сборки), но может быть переопределен в секции настроек `timeout`. * Инициализация: * Информационная база инициализируется только в том случае, если в сборочной линии включены шаги, работающие с базой (например, `bdd` или `syntaxCheck`). * Информационная база инициализируется конфигурацией из хранилища конфигурации (`initInfobase` -> `initMethod`). From ca8c10093463fcaf1e1ffb37305c72ed3900bd73 Mon Sep 17 00:00:00 2001 From: Dima Ovcharenko Date: Sat, 3 Jun 2023 10:00:38 +0300 Subject: [PATCH 003/112] Update src/ru/pulsar/jenkins/library/configuration/SmokeTestOptions.groovy Co-authored-by: Nikita Fedkin --- .../jenkins/library/configuration/SmokeTestOptions.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ru/pulsar/jenkins/library/configuration/SmokeTestOptions.groovy b/src/ru/pulsar/jenkins/library/configuration/SmokeTestOptions.groovy index dede2a71..78fca0fd 100644 --- a/src/ru/pulsar/jenkins/library/configuration/SmokeTestOptions.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/SmokeTestOptions.groovy @@ -38,7 +38,7 @@ class SmokeTestOptions implements Serializable { ", xddConfigPath='" + xddConfigPath + '\'' + ", publishToAllureReport=" + publishToAllureReport + ", publishToJUnitReport=" + publishToJUnitReport + - "coverage=" + coverage + + ", coverage=" + coverage + '}' } } From 1f6c27fd2ffad8591fdc56c304017bef850ae68d Mon Sep 17 00:00:00 2001 From: Dima Date: Sat, 3 Jun 2023 11:52:35 +0300 Subject: [PATCH 004/112] fix paths --- src/ru/pulsar/jenkins/library/steps/Bdd.groovy | 4 +++- src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/ru/pulsar/jenkins/library/steps/Bdd.groovy b/src/ru/pulsar/jenkins/library/steps/Bdd.groovy index a1c2eda5..41b52c21 100644 --- a/src/ru/pulsar/jenkins/library/steps/Bdd.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Bdd.groovy @@ -1,8 +1,10 @@ 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 @@ -26,7 +28,7 @@ class Bdd implements Serializable { def env = steps.env(); def srcDir = config.srcDir - def projectDir = new File("$env.WORKSPACE").getCanonicalPath() + FilePath projectDir = FileUtils.getFilePath("$env.WORKSPACE/$srcDir") List logosConfig = ["LOGOS_CONFIG=$config.logosConfig"] steps.withEnv(logosConfig) { diff --git a/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy b/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy index b3d306b3..0463e85a 100644 --- a/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy +++ b/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy @@ -38,7 +38,7 @@ class SmokeTest implements Serializable { def env = steps.env() def srcDir = config.srcDir - def projectDir = new File("$env.WORKSPACE").getCanonicalPath() + FilePath projectDir = FileUtils.getFilePath("$env.WORKSPACE/$srcDir") String vrunnerPath = VRunner.getVRunnerPath() String command = "$vrunnerPath xunit --ibconnection \"/F./build/ib\"" From 4930715ec746b085fd53c4713d0d36d233932a18 Mon Sep 17 00:00:00 2001 From: Dima Date: Sat, 3 Jun 2023 13:33:04 +0300 Subject: [PATCH 005/112] fix bdd --- src/ru/pulsar/jenkins/library/steps/Bdd.groovy | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ru/pulsar/jenkins/library/steps/Bdd.groovy b/src/ru/pulsar/jenkins/library/steps/Bdd.groovy index 41b52c21..5993cb5b 100644 --- a/src/ru/pulsar/jenkins/library/steps/Bdd.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Bdd.groovy @@ -26,6 +26,7 @@ class Bdd implements Serializable { return } + def options = config.bddOptions def env = steps.env(); def srcDir = config.srcDir FilePath projectDir = FileUtils.getFilePath("$env.WORKSPACE/$srcDir") From 87cbb2c16cb50c5448ac54ad415a03bf430cb731 Mon Sep 17 00:00:00 2001 From: Dima Date: Sat, 3 Jun 2023 14:37:31 +0300 Subject: [PATCH 006/112] fix paths --- src/ru/pulsar/jenkins/library/steps/Bdd.groovy | 4 ++-- src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ru/pulsar/jenkins/library/steps/Bdd.groovy b/src/ru/pulsar/jenkins/library/steps/Bdd.groovy index 5993cb5b..4e93d61b 100644 --- a/src/ru/pulsar/jenkins/library/steps/Bdd.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Bdd.groovy @@ -29,7 +29,7 @@ class Bdd implements Serializable { def options = config.bddOptions def env = steps.env(); def srcDir = config.srcDir - FilePath projectDir = FileUtils.getFilePath("$env.WORKSPACE/$srcDir") + def workspaceDir = FileUtils.getFilePath("$env.WORKSPACE/$WORKSPACE") List logosConfig = ["LOGOS_CONFIG=$config.logosConfig"] steps.withEnv(logosConfig) { @@ -40,7 +40,7 @@ class Bdd implements Serializable { def coverageOpts = config.coverageOptions; if (options.coverage) { steps.start("${coverageOpts.dbgsPath} --addr=127.0.0.1 --port=1550") - steps.start("${coverageOpts.coverage41CPath} start -i DefAlias -u http://127.0.0.1:1550 -P $projectDir -s $srcDir -o build/out/bdd-coverage.xml") + steps.start("${coverageOpts.coverage41CPath} start -i DefAlias -u http://127.0.0.1:1550 -P $workspaceDir -s $srcDir -o build/out/bdd-coverage.xml") } config.bddOptions.vrunnerSteps.each { diff --git a/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy b/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy index 0463e85a..2d100ec8 100644 --- a/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy +++ b/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy @@ -38,7 +38,7 @@ class SmokeTest implements Serializable { def env = steps.env() def srcDir = config.srcDir - FilePath projectDir = FileUtils.getFilePath("$env.WORKSPACE/$srcDir") + def workspaceDir = FileUtils.getFilePath("$env.WORKSPACE/$WORKSPACE") String vrunnerPath = VRunner.getVRunnerPath() String command = "$vrunnerPath xunit --ibconnection \"/F./build/ib\"" @@ -106,7 +106,7 @@ class SmokeTest implements Serializable { def coverageOpts = config.coverageOptions; if (options.coverage) { steps.start("${coverageOpts.dbgsPath} --addr=127.0.0.1 --port=1550") - steps.start("${coverageOpts.coverage41CPath} start -i DefAlias -u http://127.0.0.1:1550 -P $projectDir -s $srcDir -o build/out/smoketest-coverage.xml") + steps.start("${coverageOpts.coverage41CPath} start -i DefAlias -u http://127.0.0.1:1550 -P $workspaceDir -s $srcDir -o build/out/smoketest-coverage.xml") } steps.withEnv(logosConfig) { From ab10d28da1215752baa56363033c72fd0c54a8a6 Mon Sep 17 00:00:00 2001 From: Dima Date: Sat, 3 Jun 2023 15:20:21 +0300 Subject: [PATCH 007/112] another fix --- src/ru/pulsar/jenkins/library/steps/Bdd.groovy | 2 +- src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ru/pulsar/jenkins/library/steps/Bdd.groovy b/src/ru/pulsar/jenkins/library/steps/Bdd.groovy index 4e93d61b..310541b3 100644 --- a/src/ru/pulsar/jenkins/library/steps/Bdd.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Bdd.groovy @@ -29,7 +29,7 @@ class Bdd implements Serializable { def options = config.bddOptions def env = steps.env(); def srcDir = config.srcDir - def workspaceDir = FileUtils.getFilePath("$env.WORKSPACE/$WORKSPACE") + def workspaceDir = FileUtils.getFilePath("$env.WORKSPACE") List logosConfig = ["LOGOS_CONFIG=$config.logosConfig"] steps.withEnv(logosConfig) { diff --git a/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy b/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy index 2d100ec8..7b58fcf0 100644 --- a/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy +++ b/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy @@ -38,7 +38,7 @@ class SmokeTest implements Serializable { def env = steps.env() def srcDir = config.srcDir - def workspaceDir = FileUtils.getFilePath("$env.WORKSPACE/$WORKSPACE") + def workspaceDir = FileUtils.getFilePath("$env.WORKSPACE") String vrunnerPath = VRunner.getVRunnerPath() String command = "$vrunnerPath xunit --ibconnection \"/F./build/ib\"" From 694b0d095726465073cf94ec04743cd541161c14 Mon Sep 17 00:00:00 2001 From: Dima Date: Mon, 12 Jun 2023 09:55:33 +0300 Subject: [PATCH 008/112] pick unused port for dbgs --- src/ru/pulsar/jenkins/library/steps/Bdd.groovy | 4 ++-- src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/ru/pulsar/jenkins/library/steps/Bdd.groovy b/src/ru/pulsar/jenkins/library/steps/Bdd.groovy index 310541b3..3313165c 100644 --- a/src/ru/pulsar/jenkins/library/steps/Bdd.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Bdd.groovy @@ -1,6 +1,5 @@ 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 @@ -39,7 +38,8 @@ class Bdd implements Serializable { def coverageOpts = config.coverageOptions; if (options.coverage) { - steps.start("${coverageOpts.dbgsPath} --addr=127.0.0.1 --port=1550") + ServerSocket s = new ServerSocket(0) + steps.start("${coverageOpts.dbgsPath} --addr=127.0.0.1 --port=${s.getLocalPort()}") steps.start("${coverageOpts.coverage41CPath} start -i DefAlias -u http://127.0.0.1:1550 -P $workspaceDir -s $srcDir -o build/out/bdd-coverage.xml") } diff --git a/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy b/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy index 7b58fcf0..6350ab0e 100644 --- a/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy +++ b/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy @@ -105,7 +105,8 @@ class SmokeTest implements Serializable { def coverageOpts = config.coverageOptions; if (options.coverage) { - steps.start("${coverageOpts.dbgsPath} --addr=127.0.0.1 --port=1550") + ServerSocket s = new ServerSocket(0) + steps.start("${coverageOpts.dbgsPath} --addr=127.0.0.1 --port=${s.getLocalPort()}") steps.start("${coverageOpts.coverage41CPath} start -i DefAlias -u http://127.0.0.1:1550 -P $workspaceDir -s $srcDir -o build/out/smoketest-coverage.xml") } From 3c0bb34225a6a031e983dc083551425711d1399f Mon Sep 17 00:00:00 2001 From: Dima Date: Mon, 12 Jun 2023 10:15:45 +0300 Subject: [PATCH 009/112] fix? --- src/ru/pulsar/jenkins/library/steps/Bdd.groovy | 2 +- src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ru/pulsar/jenkins/library/steps/Bdd.groovy b/src/ru/pulsar/jenkins/library/steps/Bdd.groovy index 3313165c..dbd805ef 100644 --- a/src/ru/pulsar/jenkins/library/steps/Bdd.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Bdd.groovy @@ -39,7 +39,7 @@ class Bdd implements Serializable { def coverageOpts = config.coverageOptions; if (options.coverage) { ServerSocket s = new ServerSocket(0) - steps.start("${coverageOpts.dbgsPath} --addr=127.0.0.1 --port=${s.getLocalPort()}") + steps.start("${coverageOpts.dbgsPath} --addr=127.0.0.1 --port=${s.getLocalPort().toString()}") steps.start("${coverageOpts.coverage41CPath} start -i DefAlias -u http://127.0.0.1:1550 -P $workspaceDir -s $srcDir -o build/out/bdd-coverage.xml") } diff --git a/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy b/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy index 6350ab0e..6682b8b8 100644 --- a/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy +++ b/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy @@ -106,7 +106,7 @@ class SmokeTest implements Serializable { def coverageOpts = config.coverageOptions; if (options.coverage) { ServerSocket s = new ServerSocket(0) - steps.start("${coverageOpts.dbgsPath} --addr=127.0.0.1 --port=${s.getLocalPort()}") + steps.start("${coverageOpts.dbgsPath} --addr=127.0.0.1 --port=${s.getLocalPort().toString()}") steps.start("${coverageOpts.coverage41CPath} start -i DefAlias -u http://127.0.0.1:1550 -P $workspaceDir -s $srcDir -o build/out/smoketest-coverage.xml") } From 271dbf75e27cb24da84cc83d27c3a11782c5051b Mon Sep 17 00:00:00 2001 From: Dima Date: Mon, 12 Jun 2023 10:41:18 +0300 Subject: [PATCH 010/112] fix --- src/ru/pulsar/jenkins/library/steps/Bdd.groovy | 4 ++-- .../pulsar/jenkins/library/steps/SmokeTest.groovy | 4 ++-- .../pulsar/jenkins/library/utils/PortPicker.java | 14 ++++++++++++++ 3 files changed, 18 insertions(+), 4 deletions(-) create mode 100644 src/ru/pulsar/jenkins/library/utils/PortPicker.java diff --git a/src/ru/pulsar/jenkins/library/steps/Bdd.groovy b/src/ru/pulsar/jenkins/library/steps/Bdd.groovy index dbd805ef..59d86521 100644 --- a/src/ru/pulsar/jenkins/library/steps/Bdd.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Bdd.groovy @@ -5,6 +5,7 @@ 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.PortPicker import ru.pulsar.jenkins.library.utils.VRunner class Bdd implements Serializable { @@ -38,8 +39,7 @@ class Bdd implements Serializable { def coverageOpts = config.coverageOptions; if (options.coverage) { - ServerSocket s = new ServerSocket(0) - steps.start("${coverageOpts.dbgsPath} --addr=127.0.0.1 --port=${s.getLocalPort().toString()}") + steps.start("${coverageOpts.dbgsPath} --addr=127.0.0.1 --port=${PortPicker.port()}") steps.start("${coverageOpts.coverage41CPath} start -i DefAlias -u http://127.0.0.1:1550 -P $workspaceDir -s $srcDir -o build/out/bdd-coverage.xml") } diff --git a/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy b/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy index 6682b8b8..61ccc574 100644 --- a/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy +++ b/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy @@ -6,6 +6,7 @@ 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.PortPicker import ru.pulsar.jenkins.library.utils.StringJoiner import ru.pulsar.jenkins.library.utils.VRunner @@ -105,8 +106,7 @@ class SmokeTest implements Serializable { def coverageOpts = config.coverageOptions; if (options.coverage) { - ServerSocket s = new ServerSocket(0) - steps.start("${coverageOpts.dbgsPath} --addr=127.0.0.1 --port=${s.getLocalPort().toString()}") + steps.start("${coverageOpts.dbgsPath} --addr=127.0.0.1 --port=${PortPicker.port()}") steps.start("${coverageOpts.coverage41CPath} start -i DefAlias -u http://127.0.0.1:1550 -P $workspaceDir -s $srcDir -o build/out/smoketest-coverage.xml") } diff --git a/src/ru/pulsar/jenkins/library/utils/PortPicker.java b/src/ru/pulsar/jenkins/library/utils/PortPicker.java new file mode 100644 index 00000000..ab6efb6e --- /dev/null +++ b/src/ru/pulsar/jenkins/library/utils/PortPicker.java @@ -0,0 +1,14 @@ +package ru.pulsar.jenkins.library.utils; + +import com.cloudbees.groovy.cps.NonCPS; + +import java.io.IOException; +import java.net.ServerSocket; + +public class PortPicker { + @NonCPS + static int port() throws IOException { + int result = new ServerSocket(0).getLocalPort(); + return result; + } +} From 5e2aedb3c62e61d18951d32a79806beaa6311341 Mon Sep 17 00:00:00 2001 From: Dima Date: Mon, 12 Jun 2023 11:08:01 +0300 Subject: [PATCH 011/112] fix class --- src/ru/pulsar/jenkins/library/steps/Bdd.groovy | 2 +- .../pulsar/jenkins/library/steps/SmokeTest.groovy | 2 +- .../pulsar/jenkins/library/utils/PortPicker.java | 14 -------------- 3 files changed, 2 insertions(+), 16 deletions(-) delete mode 100644 src/ru/pulsar/jenkins/library/utils/PortPicker.java diff --git a/src/ru/pulsar/jenkins/library/steps/Bdd.groovy b/src/ru/pulsar/jenkins/library/steps/Bdd.groovy index 59d86521..379e7e4d 100644 --- a/src/ru/pulsar/jenkins/library/steps/Bdd.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Bdd.groovy @@ -39,7 +39,7 @@ class Bdd implements Serializable { def coverageOpts = config.coverageOptions; if (options.coverage) { - steps.start("${coverageOpts.dbgsPath} --addr=127.0.0.1 --port=${PortPicker.port()}") + steps.start("${coverageOpts.dbgsPath} --addr=127.0.0.1 --port=${PortPicker.getPort()}") steps.start("${coverageOpts.coverage41CPath} start -i DefAlias -u http://127.0.0.1:1550 -P $workspaceDir -s $srcDir -o build/out/bdd-coverage.xml") } diff --git a/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy b/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy index 61ccc574..9c8bb6ad 100644 --- a/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy +++ b/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy @@ -106,7 +106,7 @@ class SmokeTest implements Serializable { def coverageOpts = config.coverageOptions; if (options.coverage) { - steps.start("${coverageOpts.dbgsPath} --addr=127.0.0.1 --port=${PortPicker.port()}") + steps.start("${coverageOpts.dbgsPath} --addr=127.0.0.1 --port=${PortPicker.getPort()}") steps.start("${coverageOpts.coverage41CPath} start -i DefAlias -u http://127.0.0.1:1550 -P $workspaceDir -s $srcDir -o build/out/smoketest-coverage.xml") } diff --git a/src/ru/pulsar/jenkins/library/utils/PortPicker.java b/src/ru/pulsar/jenkins/library/utils/PortPicker.java deleted file mode 100644 index ab6efb6e..00000000 --- a/src/ru/pulsar/jenkins/library/utils/PortPicker.java +++ /dev/null @@ -1,14 +0,0 @@ -package ru.pulsar.jenkins.library.utils; - -import com.cloudbees.groovy.cps.NonCPS; - -import java.io.IOException; -import java.net.ServerSocket; - -public class PortPicker { - @NonCPS - static int port() throws IOException { - int result = new ServerSocket(0).getLocalPort(); - return result; - } -} From 1b724e0077b44a0971ca38cb1d03c262acddd9b4 Mon Sep 17 00:00:00 2001 From: Dima Date: Mon, 12 Jun 2023 11:36:17 +0300 Subject: [PATCH 012/112] fix --- src/ru/pulsar/jenkins/library/steps/Start.groovy | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ru/pulsar/jenkins/library/steps/Start.groovy b/src/ru/pulsar/jenkins/library/steps/Start.groovy index 4d3e2393..11b4f0a1 100644 --- a/src/ru/pulsar/jenkins/library/steps/Start.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Start.groovy @@ -20,9 +20,9 @@ class Start implements Serializable { int returnValue if (steps.isUnix()) { - returnValue = steps.sh("$script &", returnStatus, encoding) + returnStatus = steps.sh("$script &", returnStatus, encoding) } else { - returnValue = steps.bat("chcp 65001 > nul \nstart $script", returnStatus, encoding) + returnStatus = steps.bat("chcp 65001 > nul \nstart $script", returnStatus, encoding) } } } From 85bd8e98741dac860818301d2926561482d32ed7 Mon Sep 17 00:00:00 2001 From: Dima Date: Mon, 12 Jun 2023 11:37:26 +0300 Subject: [PATCH 013/112] add class --- src/ru/pulsar/jenkins/library/utils/PortPicker.groovy | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/ru/pulsar/jenkins/library/utils/PortPicker.groovy diff --git a/src/ru/pulsar/jenkins/library/utils/PortPicker.groovy b/src/ru/pulsar/jenkins/library/utils/PortPicker.groovy new file mode 100644 index 00000000..552ea98a --- /dev/null +++ b/src/ru/pulsar/jenkins/library/utils/PortPicker.groovy @@ -0,0 +1,11 @@ +package ru.pulsar.jenkins.library.utils + +import com.cloudbees.groovy.cps.NonCPS + +class PortPicker { + + @NonCPS + static int getPort() { + return new ServerSocket(0).getLocalPort() + } +} From 48f9d26a88f903bdfc22025da3b7170f88a26a24 Mon Sep 17 00:00:00 2001 From: Dima Date: Mon, 12 Jun 2023 11:57:12 +0300 Subject: [PATCH 014/112] fix returns --- src/ru/pulsar/jenkins/library/steps/Start.groovy | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/ru/pulsar/jenkins/library/steps/Start.groovy b/src/ru/pulsar/jenkins/library/steps/Start.groovy index 11b4f0a1..6f62c86b 100644 --- a/src/ru/pulsar/jenkins/library/steps/Start.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Start.groovy @@ -5,7 +5,7 @@ import ru.pulsar.jenkins.library.ioc.ContextRegistry class Start implements Serializable { - private String script; + private String script private boolean returnStatus private String encoding = 'UTF-8' @@ -14,15 +14,13 @@ class Start implements Serializable { this.returnStatus = returnStatus }; - int run() { + void run() { IStepExecutor steps = ContextRegistry.getContext().getStepExecutor() - int returnValue - if (steps.isUnix()) { - returnStatus = steps.sh("$script &", returnStatus, encoding) + steps.sh("$script &", returnStatus, encoding) } else { - returnStatus = steps.bat("chcp 65001 > nul \nstart $script", returnStatus, encoding) + steps.bat("chcp 65001 > nul \nstart $script", returnStatus, encoding) } } } From 5d808f4ab51e487d99c619e48ddc45e3bb25a930 Mon Sep 17 00:00:00 2001 From: Dima Date: Mon, 12 Jun 2023 12:08:32 +0300 Subject: [PATCH 015/112] fix ports --- src/ru/pulsar/jenkins/library/steps/Bdd.groovy | 7 ++++--- src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/ru/pulsar/jenkins/library/steps/Bdd.groovy b/src/ru/pulsar/jenkins/library/steps/Bdd.groovy index 379e7e4d..ccd3212a 100644 --- a/src/ru/pulsar/jenkins/library/steps/Bdd.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Bdd.groovy @@ -38,9 +38,10 @@ class Bdd implements Serializable { List returnStatuses = [] def coverageOpts = config.coverageOptions; + def port = PortPicker.getPort(); if (options.coverage) { - steps.start("${coverageOpts.dbgsPath} --addr=127.0.0.1 --port=${PortPicker.getPort()}") - steps.start("${coverageOpts.coverage41CPath} start -i DefAlias -u http://127.0.0.1:1550 -P $workspaceDir -s $srcDir -o build/out/bdd-coverage.xml") + steps.start("${coverageOpts.dbgsPath} --addr=127.0.0.1 --port=$port") + steps.start("${coverageOpts.coverage41CPath} start -i DefAlias -u http://127.0.0.1:$port -P $workspaceDir -s $srcDir -o build/out/bdd-coverage.xml") } config.bddOptions.vrunnerSteps.each { @@ -59,7 +60,7 @@ class Bdd implements Serializable { } if (options.coverage) { - steps.cmd("${coverageOpts.coverage41CPath} stop -i DefAlias -u http://127.0.0.1:1550") + steps.cmd("${coverageOpts.coverage41CPath} stop -i DefAlias -u http://127.0.0.1:$port") } } diff --git a/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy b/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy index 9c8bb6ad..71ea4611 100644 --- a/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy +++ b/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy @@ -105,9 +105,10 @@ class SmokeTest implements Serializable { } def coverageOpts = config.coverageOptions; + def port = PortPicker.getPort(); if (options.coverage) { - steps.start("${coverageOpts.dbgsPath} --addr=127.0.0.1 --port=${PortPicker.getPort()}") - steps.start("${coverageOpts.coverage41CPath} start -i DefAlias -u http://127.0.0.1:1550 -P $workspaceDir -s $srcDir -o build/out/smoketest-coverage.xml") + steps.start("${coverageOpts.dbgsPath} --addr=127.0.0.1 --port=$port") + steps.start("${coverageOpts.coverage41CPath} start -i DefAlias -u http://127.0.0.1:$port -P $workspaceDir -s $srcDir -o build/out/smoketest-coverage.xml") } steps.withEnv(logosConfig) { @@ -115,7 +116,7 @@ class SmokeTest implements Serializable { } if (options.coverage) { - steps.cmd("${coverageOpts.coverage41CPath} stop -i DefAlias -u http://127.0.0.1:1550") + steps.cmd("${coverageOpts.coverage41CPath} stop -i DefAlias -u http://127.0.0.1:$port") } if (options.publishToAllureReport) { From 9af1df968689953308f19f8a8a977d864e33e555 Mon Sep 17 00:00:00 2001 From: Dima Date: Mon, 12 Jun 2023 17:45:12 +0300 Subject: [PATCH 016/112] make dbgs port const --- src/ru/pulsar/jenkins/library/steps/Bdd.groovy | 1 + src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy | 1 + 2 files changed, 2 insertions(+) diff --git a/src/ru/pulsar/jenkins/library/steps/Bdd.groovy b/src/ru/pulsar/jenkins/library/steps/Bdd.groovy index ccd3212a..1a137184 100644 --- a/src/ru/pulsar/jenkins/library/steps/Bdd.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Bdd.groovy @@ -39,6 +39,7 @@ class Bdd implements Serializable { def coverageOpts = config.coverageOptions; def port = PortPicker.getPort(); + port = 1550; if (options.coverage) { steps.start("${coverageOpts.dbgsPath} --addr=127.0.0.1 --port=$port") steps.start("${coverageOpts.coverage41CPath} start -i DefAlias -u http://127.0.0.1:$port -P $workspaceDir -s $srcDir -o build/out/bdd-coverage.xml") diff --git a/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy b/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy index 71ea4611..27dbb289 100644 --- a/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy +++ b/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy @@ -106,6 +106,7 @@ class SmokeTest implements Serializable { def coverageOpts = config.coverageOptions; def port = PortPicker.getPort(); + port = 1550; if (options.coverage) { steps.start("${coverageOpts.dbgsPath} --addr=127.0.0.1 --port=$port") steps.start("${coverageOpts.coverage41CPath} start -i DefAlias -u http://127.0.0.1:$port -P $workspaceDir -s $srcDir -o build/out/smoketest-coverage.xml") From 1185844dd7783648b715df3172c4fd8c5ad756a8 Mon Sep 17 00:00:00 2001 From: Dima Date: Thu, 6 Jul 2023 11:49:33 +0300 Subject: [PATCH 017/112] add Coverage41C check --- src/ru/pulsar/jenkins/library/steps/Bdd.groovy | 1 + src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy | 1 + 2 files changed, 2 insertions(+) diff --git a/src/ru/pulsar/jenkins/library/steps/Bdd.groovy b/src/ru/pulsar/jenkins/library/steps/Bdd.groovy index 1a137184..bb4ad2e7 100644 --- a/src/ru/pulsar/jenkins/library/steps/Bdd.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Bdd.groovy @@ -43,6 +43,7 @@ class Bdd implements Serializable { if (options.coverage) { steps.start("${coverageOpts.dbgsPath} --addr=127.0.0.1 --port=$port") steps.start("${coverageOpts.coverage41CPath} start -i DefAlias -u http://127.0.0.1:$port -P $workspaceDir -s $srcDir -o build/out/bdd-coverage.xml") + steps.cmd("${coverageOpts.coverage41CPath} check -i DefAlias -u http://127.0.0.1:$port") } config.bddOptions.vrunnerSteps.each { diff --git a/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy b/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy index 27dbb289..5a1d6fd8 100644 --- a/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy +++ b/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy @@ -110,6 +110,7 @@ class SmokeTest implements Serializable { if (options.coverage) { steps.start("${coverageOpts.dbgsPath} --addr=127.0.0.1 --port=$port") steps.start("${coverageOpts.coverage41CPath} start -i DefAlias -u http://127.0.0.1:$port -P $workspaceDir -s $srcDir -o build/out/smoketest-coverage.xml") + steps.cmd("${coverageOpts.coverage41CPath} check -i DefAlias -u http://127.0.0.1:$port") } steps.withEnv(logosConfig) { From d6edb83444338640d2f7ab5995daa26b7d3422e4 Mon Sep 17 00:00:00 2001 From: Dima Date: Mon, 17 Jul 2023 15:38:09 +0300 Subject: [PATCH 018/112] add lockable resources in bdd --- resources/schema.json | 4 +++ .../jenkins/library/IStepExecutor.groovy | 2 ++ .../jenkins/library/StepExecutor.groovy | 7 ++++ .../configuration/ConfigurationReader.groovy | 33 +++++-------------- .../configuration/CoverageOptions.groovy | 8 ++++- .../pulsar/jenkins/library/steps/Bdd.groovy | 30 +++++++++++------ .../groovy/jobConfigurationTest.groovy | 1 + .../resources/jobConfiguration.json | 1 + 8 files changed, 50 insertions(+), 36 deletions(-) diff --git a/resources/schema.json b/resources/schema.json index 50a80c06..acada369 100644 --- a/resources/schema.json +++ b/resources/schema.json @@ -250,6 +250,10 @@ "type" : "string", "description" : "Путь к исполняемому файлу dbgs.\n По умолчанию равен /opt/1cv8/current/dbgs.\n " }, + "dbgsPort" : { + "type" : "integer", + "description" : "Порт сервера отладки.\n По умолчанию равен 1550.\n " + }, "coverage41CPath" : { "type" : "string", "description" : "Путь к исполняемому файлу Coverage41C\n По умолчанию равен Coverage41C.\n " diff --git a/src/ru/pulsar/jenkins/library/IStepExecutor.groovy b/src/ru/pulsar/jenkins/library/IStepExecutor.groovy index 503ba5c7..cd9765e0 100644 --- a/src/ru/pulsar/jenkins/library/IStepExecutor.groovy +++ b/src/ru/pulsar/jenkins/library/IStepExecutor.groovy @@ -66,6 +66,8 @@ interface IStepExecutor { def withEnv(List strings, Closure body) + def lock(String label, int quantity, String resource, Closure objectClosure) + def archiveArtifacts(String path) def stash(String name, String includes) diff --git a/src/ru/pulsar/jenkins/library/StepExecutor.groovy b/src/ru/pulsar/jenkins/library/StepExecutor.groovy index 8315bf09..c1ca77b2 100644 --- a/src/ru/pulsar/jenkins/library/StepExecutor.groovy +++ b/src/ru/pulsar/jenkins/library/StepExecutor.groovy @@ -149,6 +149,13 @@ class StepExecutor implements IStepExecutor { } } + @Override + def lock(String label, int quantity, String resource, Closure body) { + steps.lock(label, quantity, resource) { + body() + } + } + @Override def archiveArtifacts(String path) { steps.archiveArtifacts path diff --git a/src/ru/pulsar/jenkins/library/configuration/ConfigurationReader.groovy b/src/ru/pulsar/jenkins/library/configuration/ConfigurationReader.groovy index ba56695b..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( @@ -82,11 +82,10 @@ class ConfigurationReader implements Serializable { mergeObjects(baseConfiguration, configurationToMerge, nonMergeableSettings) mergeInitInfoBaseOptions(baseConfiguration.initInfoBaseOptions, configurationToMerge.initInfoBaseOptions) mergeBddOptions(baseConfiguration.bddOptions, configurationToMerge.bddOptions) - mergeCoverageOptions(baseConfiguration.coverageOptions, configurationToMerge.coverageOptions) mergeSyntaxCheckOptions(baseConfiguration.syntaxCheckOptions, configurationToMerge.syntaxCheckOptions) mergeNotificationsOptions(baseConfiguration.notificationsOptions, configurationToMerge.notificationsOptions) - return baseConfiguration; + return baseConfiguration } @NonCPS @@ -97,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 -> @@ -149,22 +148,6 @@ class ConfigurationReader implements Serializable { baseObject.vrunnerSteps = objectToMerge.vrunnerSteps.clone() } - @NonCPS - private static void mergeCoverageOptions(CoverageOptions baseObject, CoverageOptions objectToMerge) { - - if (objectToMerge == null) { - return - } - - if (objectToMerge.dbgsPath != null) { - baseObject.dbgsPath = objectToMerge.dbgsPath - } - - if (objectToMerge.coverage41CPath != null) { - baseObject.coverage41CPath = objectToMerge.coverage41CPath - } - } - @NonCPS private static void mergeSyntaxCheckOptions(SyntaxCheckOptions baseObject, SyntaxCheckOptions objectToMerge) { if (objectToMerge == null || objectToMerge.checkModes == null) { diff --git a/src/ru/pulsar/jenkins/library/configuration/CoverageOptions.groovy b/src/ru/pulsar/jenkins/library/configuration/CoverageOptions.groovy index ef865029..dbb677ca 100644 --- a/src/ru/pulsar/jenkins/library/configuration/CoverageOptions.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/CoverageOptions.groovy @@ -12,6 +12,11 @@ class CoverageOptions implements Serializable { ''') String dbgsPath + @JsonPropertyDescription('''Порт сервера отладки. + По умолчанию равен 1550. + ''') + int dbgsPort = 1550 + @JsonPropertyDescription('''Путь к исполняемому файлу Coverage41C По умолчанию равен Coverage41C. ''') @@ -22,8 +27,9 @@ class CoverageOptions implements Serializable { String toString() { return "coverageOptions{" + "dbgsPath=" + dbgsPath + + "dbgsPort=" + dbgsPort + ", coverage41CPath=" + coverage41CPath + - '}'; + '}' } } diff --git a/src/ru/pulsar/jenkins/library/steps/Bdd.groovy b/src/ru/pulsar/jenkins/library/steps/Bdd.groovy index bb4ad2e7..35b3f667 100644 --- a/src/ru/pulsar/jenkins/library/steps/Bdd.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Bdd.groovy @@ -5,7 +5,7 @@ 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.PortPicker +import org.apache.commons.lang.RandomStringUtils import ru.pulsar.jenkins.library.utils.VRunner class Bdd implements Serializable { @@ -27,7 +27,7 @@ class Bdd implements Serializable { } def options = config.bddOptions - def env = steps.env(); + def env = steps.env() def srcDir = config.srcDir def workspaceDir = FileUtils.getFilePath("$env.WORKSPACE") @@ -37,15 +37,21 @@ class Bdd implements Serializable { steps.createDir('build/out') List returnStatuses = [] - def coverageOpts = config.coverageOptions; - def port = PortPicker.getPort(); - port = 1550; + def coverageOpts = config.coverageOptions + def port = coverageOpts.dbgsPort + def lockable_resource = RandomStringUtils.random(9, true, false) + if (options.coverage) { - steps.start("${coverageOpts.dbgsPath} --addr=127.0.0.1 --port=$port") - steps.start("${coverageOpts.coverage41CPath} start -i DefAlias -u http://127.0.0.1:$port -P $workspaceDir -s $srcDir -o build/out/bdd-coverage.xml") - steps.cmd("${coverageOpts.coverage41CPath} check -i DefAlias -u http://127.0.0.1:$port") + lockable_resource = "${env.NODE_NAME}_$port" } + steps.lock("label", 1, lockable_resource) { + if (options.coverage) { + steps.start("${coverageOpts.dbgsPath} --addr=127.0.0.1 --port=$port") + steps.start("${coverageOpts.coverage41CPath} start -i DefAlias -u http://127.0.0.1:$port -P $workspaceDir -s $srcDir -o build/out/bdd-coverage.xml") + steps.cmd("${coverageOpts.coverage41CPath} check -i DefAlias -u http://127.0.0.1:$port") + } + config.bddOptions.vrunnerSteps.each { Logger.println("Шаг запуска сценариев командой ${it}") String vrunnerPath = VRunner.getVRunnerPath() @@ -61,8 +67,12 @@ class Bdd implements Serializable { Logger.println("Тестирование сценариев завершилось успешно") } - if (options.coverage) { - steps.cmd("${coverageOpts.coverage41CPath} stop -i DefAlias -u http://127.0.0.1:$port") + if (options.coverage) { + steps.cmd("${coverageOpts.coverage41CPath} stop -i DefAlias -u http://127.0.0.1:$port") + } + + return 0 + } } diff --git a/test/integration/groovy/jobConfigurationTest.groovy b/test/integration/groovy/jobConfigurationTest.groovy index c77feecf..b1788e32 100644 --- a/test/integration/groovy/jobConfigurationTest.groovy +++ b/test/integration/groovy/jobConfigurationTest.groovy @@ -75,6 +75,7 @@ class jobConfigurationTest { 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("dbgsPort=4543", 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 ebd5e6fd..82c836c7 100644 --- a/test/integration/resources/jobConfiguration.json +++ b/test/integration/resources/jobConfiguration.json @@ -13,6 +13,7 @@ }, "coverage": { "dbgsPath": "C:\\\\Program files\\\\1cv8\\\\8.3.12.1500\\\\bin\\\\dbgs.exe", + "dbgsPort": 4543, "coverage41CPath": "C:\\\\coverage\\\\Coverage41C.exe" } } \ No newline at end of file From ffe504b6b1ef7b9c9adc132ce6c73e9aefc0539a Mon Sep 17 00:00:00 2001 From: Dima Date: Mon, 17 Jul 2023 16:21:20 +0300 Subject: [PATCH 019/112] fix --- src/ru/pulsar/jenkins/library/StepExecutor.groovy | 2 +- src/ru/pulsar/jenkins/library/steps/Bdd.groovy | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ru/pulsar/jenkins/library/StepExecutor.groovy b/src/ru/pulsar/jenkins/library/StepExecutor.groovy index c1ca77b2..d5b9e269 100644 --- a/src/ru/pulsar/jenkins/library/StepExecutor.groovy +++ b/src/ru/pulsar/jenkins/library/StepExecutor.groovy @@ -151,7 +151,7 @@ class StepExecutor implements IStepExecutor { @Override def lock(String label, int quantity, String resource, Closure body) { - steps.lock(label, quantity, resource) { + steps.lock(label: label, quantity: quantity, resource: resource) { body() } } diff --git a/src/ru/pulsar/jenkins/library/steps/Bdd.groovy b/src/ru/pulsar/jenkins/library/steps/Bdd.groovy index 35b3f667..42d692e8 100644 --- a/src/ru/pulsar/jenkins/library/steps/Bdd.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Bdd.groovy @@ -45,7 +45,7 @@ class Bdd implements Serializable { lockable_resource = "${env.NODE_NAME}_$port" } - steps.lock("label", 1, lockable_resource) { + steps.lock("bdd-dbgs-port", 1, lockable_resource) { if (options.coverage) { steps.start("${coverageOpts.dbgsPath} --addr=127.0.0.1 --port=$port") steps.start("${coverageOpts.coverage41CPath} start -i DefAlias -u http://127.0.0.1:$port -P $workspaceDir -s $srcDir -o build/out/bdd-coverage.xml") From b5586b68a0753c561de34ceedcc325320b508c4f Mon Sep 17 00:00:00 2001 From: Dima Date: Mon, 17 Jul 2023 16:27:59 +0300 Subject: [PATCH 020/112] fix params --- src/ru/pulsar/jenkins/library/steps/Bdd.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ru/pulsar/jenkins/library/steps/Bdd.groovy b/src/ru/pulsar/jenkins/library/steps/Bdd.groovy index 42d692e8..0348f0c7 100644 --- a/src/ru/pulsar/jenkins/library/steps/Bdd.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Bdd.groovy @@ -45,7 +45,7 @@ class Bdd implements Serializable { lockable_resource = "${env.NODE_NAME}_$port" } - steps.lock("bdd-dbgs-port", 1, lockable_resource) { + steps.lock(lockable_resource, 1, null) { if (options.coverage) { steps.start("${coverageOpts.dbgsPath} --addr=127.0.0.1 --port=$port") steps.start("${coverageOpts.coverage41CPath} start -i DefAlias -u http://127.0.0.1:$port -P $workspaceDir -s $srcDir -o build/out/bdd-coverage.xml") From c956cb0d858be6f09fd32fcaa6dfcaabd9bd48d1 Mon Sep 17 00:00:00 2001 From: Dima Date: Mon, 17 Jul 2023 16:35:40 +0300 Subject: [PATCH 021/112] fix params --- src/ru/pulsar/jenkins/library/steps/Bdd.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ru/pulsar/jenkins/library/steps/Bdd.groovy b/src/ru/pulsar/jenkins/library/steps/Bdd.groovy index 0348f0c7..780be88d 100644 --- a/src/ru/pulsar/jenkins/library/steps/Bdd.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Bdd.groovy @@ -45,7 +45,7 @@ class Bdd implements Serializable { lockable_resource = "${env.NODE_NAME}_$port" } - steps.lock(lockable_resource, 1, null) { + steps.lock(null, 1, lockable_resource) { if (options.coverage) { steps.start("${coverageOpts.dbgsPath} --addr=127.0.0.1 --port=$port") steps.start("${coverageOpts.coverage41CPath} start -i DefAlias -u http://127.0.0.1:$port -P $workspaceDir -s $srcDir -o build/out/bdd-coverage.xml") From a527a241735687f31ed3355736c130527b9929a2 Mon Sep 17 00:00:00 2001 From: Dima Date: Mon, 17 Jul 2023 18:04:16 +0300 Subject: [PATCH 022/112] finalize --- README.md | 3 +- resources/schema.json | 12 ++++-- .../library/configuration/BddOptions.groovy | 6 ++- .../configuration/CoverageOptions.groovy | 6 --- .../configuration/SmokeTestOptions.groovy | 6 ++- .../pulsar/jenkins/library/steps/Bdd.groovy | 21 +++++----- .../library/steps/PublishAllure.groovy | 4 +- .../jenkins/library/steps/SmokeTest.groovy | 38 +++++++++++-------- .../jenkins/library/steps/SonarScanner.groovy | 8 ++-- .../groovy/jobConfigurationTest.groovy | 1 - .../resources/jobConfiguration.json | 1 - 11 files changed, 60 insertions(+), 46 deletions(-) diff --git a/README.md b/README.md index ddf9fef3..c5cff354 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,8 @@ 1. При использовании EDT версии 2024.1.0 и выше вместо ring используется 1cedtcli, который должен быть прописан в PATH на агенте. 1. Для запуска шагов, работающих с 1С (подготовка, синтаксический контроль и т.д.) требуется агент с меткой, совпадающей со значением в поле `v8version` файла конфигурации. 1. В качестве ИБ используется файловая база, создаваемая в каталоге `./build/ib`. При необходимости вы можете создать пользователей на фазе инициализации ИБ. -1. Для замеров покрытия на агентах должны быть установлены [Coverage41C](https://github.com/1c-syntax/Coverage41C), EDT и сервер отладки dbgs. +1. Для замеров покрытия на агентах должны быть установлены [Coverage41C](https://github.com/1c-syntax/Coverage41C), EDT и сервер отладки dbgs. Вместо установки EDT целиком можно использовать только отдельные ее компоненты, см. [Coverage41C/README.md](https://github.com/1c-syntax/Coverage41C). +1. Для параллельного выполнения шагов `bdd` и `smoke` с включенными замерами покрытия на одной ноде необходимо, чтобы в `jobConfiguration.json` были указаны **разные** порты сервера отладки для каждого шага. Параллельные билды с замерами покрытия на одной ноде не поддерживаются. ## Возможности diff --git a/resources/schema.json b/resources/schema.json index acada369..ee65310e 100644 --- a/resources/schema.json +++ b/resources/schema.json @@ -85,6 +85,10 @@ "coverage" : { "type" : "boolean", "description" : "Выполнять замер покрытия" + }, + "dbgsPort" : { + "type" : "boolean", + "description" : "Порт, на котором будет запущен сервер отладки для замера покрытия" } } } @@ -238,6 +242,10 @@ "coverage" : { "type" : "boolean", "description" : "Выполнять замер покрытия" + }, + "dbgsPort" : { + "type" : "boolean", + "description" : "Порт, на котором будет запущен сервер отладки для замера покрытия" } } }, @@ -250,10 +258,6 @@ "type" : "string", "description" : "Путь к исполняемому файлу dbgs.\n По умолчанию равен /opt/1cv8/current/dbgs.\n " }, - "dbgsPort" : { - "type" : "integer", - "description" : "Порт сервера отладки.\n По умолчанию равен 1550.\n " - }, "coverage41CPath" : { "type" : "string", "description" : "Путь к исполняемому файлу Coverage41C\n По умолчанию равен Coverage41C.\n " diff --git a/src/ru/pulsar/jenkins/library/configuration/BddOptions.groovy b/src/ru/pulsar/jenkins/library/configuration/BddOptions.groovy index 3cab3461..d86bdb42 100644 --- a/src/ru/pulsar/jenkins/library/configuration/BddOptions.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/BddOptions.groovy @@ -19,12 +19,16 @@ class BddOptions implements Serializable { @JsonPropertyDescription("Выполнять замер покрытия") Boolean coverage = false + @JsonPropertyDescription("Порт, на котором будет запущен сервер отладки для замера покрытия") + Boolean dbgsPort = 1550 + @Override @NonCPS String toString() { return "BddOptions{" + "vrunnerSteps=" + vrunnerSteps + "coverage=" + coverage + - '}'; + "dbgsPort=" + dbgsPort + + '}' } } diff --git a/src/ru/pulsar/jenkins/library/configuration/CoverageOptions.groovy b/src/ru/pulsar/jenkins/library/configuration/CoverageOptions.groovy index dbb677ca..665f3dca 100644 --- a/src/ru/pulsar/jenkins/library/configuration/CoverageOptions.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/CoverageOptions.groovy @@ -12,11 +12,6 @@ class CoverageOptions implements Serializable { ''') String dbgsPath - @JsonPropertyDescription('''Порт сервера отладки. - По умолчанию равен 1550. - ''') - int dbgsPort = 1550 - @JsonPropertyDescription('''Путь к исполняемому файлу Coverage41C По умолчанию равен Coverage41C. ''') @@ -27,7 +22,6 @@ class CoverageOptions implements Serializable { String toString() { return "coverageOptions{" + "dbgsPath=" + dbgsPath + - "dbgsPort=" + dbgsPort + ", coverage41CPath=" + coverage41CPath + '}' } diff --git a/src/ru/pulsar/jenkins/library/configuration/SmokeTestOptions.groovy b/src/ru/pulsar/jenkins/library/configuration/SmokeTestOptions.groovy index 78fca0fd..a9ca3721 100644 --- a/src/ru/pulsar/jenkins/library/configuration/SmokeTestOptions.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/SmokeTestOptions.groovy @@ -15,7 +15,7 @@ class SmokeTestOptions implements Serializable { @JsonPropertyDescription("""Путь к конфигурационному файлу для xddTestRunner. По умолчанию содержит значение "./tools/xUnitParams.json". """) - String xddConfigPath; + String xddConfigPath @JsonPropertyDescription("""Выполнять публикацию результатов в отчет Allure. По умолчанию выключено. @@ -30,6 +30,9 @@ class SmokeTestOptions implements Serializable { @JsonPropertyDescription("Выполнять замер покрытия") Boolean coverage = false + @JsonPropertyDescription("Порт, на котором будет запущен сервер отладки для замера покрытия") + Boolean dbgsPort = 1650 + @Override @NonCPS String toString() { @@ -39,6 +42,7 @@ class SmokeTestOptions implements Serializable { ", 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 780be88d..c365a75d 100644 --- a/src/ru/pulsar/jenkins/library/steps/Bdd.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Bdd.groovy @@ -12,6 +12,10 @@ class Bdd implements Serializable { 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' + Bdd(JobConfiguration config) { this.config = config } @@ -38,17 +42,17 @@ class Bdd implements Serializable { List returnStatuses = [] def coverageOpts = config.coverageOptions - def port = coverageOpts.dbgsPort - def lockable_resource = RandomStringUtils.random(9, true, false) + def port = options.dbgsPort + def lockableResource = RandomStringUtils.random(9, true, false) if (options.coverage) { - lockable_resource = "${env.NODE_NAME}_$port" + lockableResource = "${env.NODE_NAME}_$port" } - steps.lock(null, 1, lockable_resource) { + steps.lock(null, 1, lockableResource) { if (options.coverage) { steps.start("${coverageOpts.dbgsPath} --addr=127.0.0.1 --port=$port") - steps.start("${coverageOpts.coverage41CPath} start -i DefAlias -u http://127.0.0.1:$port -P $workspaceDir -s $srcDir -o build/out/bdd-coverage.xml") + steps.start("${coverageOpts.coverage41CPath} start -i DefAlias -u http://127.0.0.1:$port -P $workspaceDir -s $srcDir -o $COVERAGE_STASH_PATH") steps.cmd("${coverageOpts.coverage41CPath} check -i DefAlias -u http://127.0.0.1:$port") } @@ -70,16 +74,13 @@ class Bdd implements Serializable { if (options.coverage) { steps.cmd("${coverageOpts.coverage41CPath} stop -i DefAlias -u http://127.0.0.1:$port") } - - return 0 - } } - steps.stash('bdd-allure', 'build/out/allure/**', true) + steps.stash(ALLURE_STASH, 'build/out/allure/**', true) steps.stash('bdd-cucumber', 'build/out/cucumber/**', true) if (options.coverage) { - steps.stash('bdd-coverage', 'build/out/bdd-coverage.xml', true) + steps.stash(COVERAGE_STASH_NAME, COVERAGE_STASH_PATH, true) } } 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 5a1d6fd8..24571f2a 100644 --- a/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy +++ b/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy @@ -1,18 +1,20 @@ package ru.pulsar.jenkins.library.steps import hudson.FilePath +import org.apache.commons.lang.RandomStringUtils 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.PortPicker import ru.pulsar.jenkins.library.utils.StringJoiner import ru.pulsar.jenkins.library.utils.VRunner class SmokeTest implements Serializable { - 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' private final JobConfiguration config @@ -104,25 +106,31 @@ class SmokeTest implements Serializable { command += " $testsPath" } - def coverageOpts = config.coverageOptions; - def port = PortPicker.getPort(); - port = 1550; + def coverageOpts = config.coverageOptions + def port = options.dbgsPort + def lockableResource = RandomStringUtils.random(9, true, false) if (options.coverage) { - steps.start("${coverageOpts.dbgsPath} --addr=127.0.0.1 --port=$port") - steps.start("${coverageOpts.coverage41CPath} start -i DefAlias -u http://127.0.0.1:$port -P $workspaceDir -s $srcDir -o build/out/smoketest-coverage.xml") - steps.cmd("${coverageOpts.coverage41CPath} check -i DefAlias -u http://127.0.0.1:$port") + lockableResource = "${env.NODE_NAME}_$port" } - steps.withEnv(logosConfig) { - VRunner.exec(command, true) - } + steps.lock(null, 1, lockableResource) { + if (options.coverage) { + steps.start("${coverageOpts.dbgsPath} --addr=127.0.0.1 --port=$port") + steps.start("${coverageOpts.coverage41CPath} start -i DefAlias -u http://127.0.0.1:$port -P $workspaceDir -s $srcDir -o $COVERAGE_STASH_PATH") + steps.cmd("${coverageOpts.coverage41CPath} check -i DefAlias -u http://127.0.0.1:$port") + } - if (options.coverage) { - steps.cmd("${coverageOpts.coverage41CPath} stop -i DefAlias -u http://127.0.0.1:$port") + steps.withEnv(logosConfig) { + VRunner.exec(command, true) + } + + if (options.coverage) { + steps.cmd("${coverageOpts.coverage41CPath} stop -i DefAlias -u http://127.0.0.1:$port") + } } if (options.publishToAllureReport) { - steps.stash(SMOKE_ALLURE_STASH, "$allureReportDir/**", true) + steps.stash(ALLURE_STASH, "$allureReportDir/**", true) steps.archiveArtifacts("$allureReportDir/**") } @@ -132,7 +140,7 @@ class SmokeTest implements Serializable { } if (options.coverage) { - steps.stash('smoketest-coverage', 'build/out/smoketest-coverage.xml', true) + steps.stash(COVERAGE_STASH_NAME, COVERAGE_STASH_PATH, true) } } diff --git a/src/ru/pulsar/jenkins/library/steps/SonarScanner.groovy b/src/ru/pulsar/jenkins/library/steps/SonarScanner.groovy index a83ad68c..84f64e6d 100644 --- a/src/ru/pulsar/jenkins/library/steps/SonarScanner.groovy +++ b/src/ru/pulsar/jenkins/library/steps/SonarScanner.groovy @@ -75,13 +75,13 @@ class SonarScanner implements Serializable { StringJoiner coveragePathsConstructor = new StringJoiner(",") if (config.stageFlags.bdd && config.bddOptions.coverage) { - steps.unstash("bdd-coverage") - coveragePathsConstructor.add("build/out/bdd-coverage.xml") + steps.unstash(Bdd.COVERAGE_STASH_NAME) + coveragePathsConstructor.add(Bdd.COVERAGE_STASH_PATH) } if (config.stageFlags.smoke && config.smokeTestOptions.coverage) { - steps.unstash("smoketest-coverage") - coveragePathsConstructor.add("build/out/smoketest-coverage.xml") + steps.unstash(SmokeTest.COVERAGE_STASH_NAME) + coveragePathsConstructor.add(SmokeTest.COVERAGE_STASH_PATH) } String coveragePaths = coveragePathsConstructor.toString() diff --git a/test/integration/groovy/jobConfigurationTest.groovy b/test/integration/groovy/jobConfigurationTest.groovy index b1788e32..c77feecf 100644 --- a/test/integration/groovy/jobConfigurationTest.groovy +++ b/test/integration/groovy/jobConfigurationTest.groovy @@ -75,7 +75,6 @@ class jobConfigurationTest { 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("dbgsPort=4543", 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 82c836c7..ebd5e6fd 100644 --- a/test/integration/resources/jobConfiguration.json +++ b/test/integration/resources/jobConfiguration.json @@ -13,7 +13,6 @@ }, "coverage": { "dbgsPath": "C:\\\\Program files\\\\1cv8\\\\8.3.12.1500\\\\bin\\\\dbgs.exe", - "dbgsPort": 4543, "coverage41CPath": "C:\\\\coverage\\\\Coverage41C.exe" } } \ No newline at end of file From 98386df5daae481a1a9d191b8fb8ea8d994fa82e Mon Sep 17 00:00:00 2001 From: Dima Date: Mon, 17 Jul 2023 18:50:02 +0300 Subject: [PATCH 023/112] fix type --- resources/schema.json | 4 ++-- src/ru/pulsar/jenkins/library/configuration/BddOptions.groovy | 2 +- .../jenkins/library/configuration/SmokeTestOptions.groovy | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/resources/schema.json b/resources/schema.json index ee65310e..331e7041 100644 --- a/resources/schema.json +++ b/resources/schema.json @@ -87,7 +87,7 @@ "description" : "Выполнять замер покрытия" }, "dbgsPort" : { - "type" : "boolean", + "type" : "integer", "description" : "Порт, на котором будет запущен сервер отладки для замера покрытия" } } @@ -244,7 +244,7 @@ "description" : "Выполнять замер покрытия" }, "dbgsPort" : { - "type" : "boolean", + "type" : "integer", "description" : "Порт, на котором будет запущен сервер отладки для замера покрытия" } } diff --git a/src/ru/pulsar/jenkins/library/configuration/BddOptions.groovy b/src/ru/pulsar/jenkins/library/configuration/BddOptions.groovy index d86bdb42..47f0547b 100644 --- a/src/ru/pulsar/jenkins/library/configuration/BddOptions.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/BddOptions.groovy @@ -20,7 +20,7 @@ class BddOptions implements Serializable { Boolean coverage = false @JsonPropertyDescription("Порт, на котором будет запущен сервер отладки для замера покрытия") - Boolean dbgsPort = 1550 + int dbgsPort = 1550 @Override @NonCPS diff --git a/src/ru/pulsar/jenkins/library/configuration/SmokeTestOptions.groovy b/src/ru/pulsar/jenkins/library/configuration/SmokeTestOptions.groovy index a9ca3721..c84df883 100644 --- a/src/ru/pulsar/jenkins/library/configuration/SmokeTestOptions.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/SmokeTestOptions.groovy @@ -31,7 +31,7 @@ class SmokeTestOptions implements Serializable { Boolean coverage = false @JsonPropertyDescription("Порт, на котором будет запущен сервер отладки для замера покрытия") - Boolean dbgsPort = 1650 + int dbgsPort = 1650 @Override @NonCPS From 41ff0eb1304ec4427bacce21adef56d7b3ff9116 Mon Sep 17 00:00:00 2001 From: Dima Date: Mon, 17 Jul 2023 23:16:37 +0300 Subject: [PATCH 024/112] rm unused class --- src/ru/pulsar/jenkins/library/utils/PortPicker.groovy | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 src/ru/pulsar/jenkins/library/utils/PortPicker.groovy diff --git a/src/ru/pulsar/jenkins/library/utils/PortPicker.groovy b/src/ru/pulsar/jenkins/library/utils/PortPicker.groovy deleted file mode 100644 index 552ea98a..00000000 --- a/src/ru/pulsar/jenkins/library/utils/PortPicker.groovy +++ /dev/null @@ -1,11 +0,0 @@ -package ru.pulsar.jenkins.library.utils - -import com.cloudbees.groovy.cps.NonCPS - -class PortPicker { - - @NonCPS - static int getPort() { - return new ServerSocket(0).getLocalPort() - } -} From 611dbc83ba35a827b3f5a907105f163a88cb9c74 Mon Sep 17 00:00:00 2001 From: Dima Date: Sat, 24 Aug 2024 14:21:19 +0300 Subject: [PATCH 025/112] rm start return status --- src/ru/pulsar/jenkins/library/IStepExecutor.groovy | 2 +- src/ru/pulsar/jenkins/library/StepExecutor.groovy | 4 ++-- src/ru/pulsar/jenkins/library/steps/Start.groovy | 8 +++----- vars/start.groovy | 4 ++-- 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/ru/pulsar/jenkins/library/IStepExecutor.groovy b/src/ru/pulsar/jenkins/library/IStepExecutor.groovy index cd9765e0..ae6d680e 100644 --- a/src/ru/pulsar/jenkins/library/IStepExecutor.groovy +++ b/src/ru/pulsar/jenkins/library/IStepExecutor.groovy @@ -40,7 +40,7 @@ interface IStepExecutor { def ringCommand(String script) - void start(String script, boolean returnStatus) + void start(String script) void tool(String toolName) diff --git a/src/ru/pulsar/jenkins/library/StepExecutor.groovy b/src/ru/pulsar/jenkins/library/StepExecutor.groovy index d5b9e269..d337aab6 100644 --- a/src/ru/pulsar/jenkins/library/StepExecutor.groovy +++ b/src/ru/pulsar/jenkins/library/StepExecutor.groovy @@ -73,8 +73,8 @@ class StepExecutor implements IStepExecutor { } @Override - void start(String script, boolean returnStatus = false) { - steps.start(script, returnStatus) + void start(String script) { + steps.start(script) } @Override diff --git a/src/ru/pulsar/jenkins/library/steps/Start.groovy b/src/ru/pulsar/jenkins/library/steps/Start.groovy index 6f62c86b..8d8c99e0 100644 --- a/src/ru/pulsar/jenkins/library/steps/Start.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Start.groovy @@ -6,21 +6,19 @@ import ru.pulsar.jenkins.library.ioc.ContextRegistry class Start implements Serializable { private String script - private boolean returnStatus private String encoding = 'UTF-8' - Start(String script, boolean returnStatus = false) { + Start(String script) { this.script = script - this.returnStatus = returnStatus }; void run() { IStepExecutor steps = ContextRegistry.getContext().getStepExecutor() if (steps.isUnix()) { - steps.sh("$script &", returnStatus, encoding) + steps.sh("$script &", false, false , encoding) } else { - steps.bat("chcp 65001 > nul \nstart $script", returnStatus, encoding) + steps.bat("chcp 65001 > nul \nstart $script", false, false, encoding) } } } diff --git a/vars/start.groovy b/vars/start.groovy index 3e4acf01..2727ee1b 100644 --- a/vars/start.groovy +++ b/vars/start.groovy @@ -1,9 +1,9 @@ import ru.pulsar.jenkins.library.steps.Start import ru.pulsar.jenkins.library.ioc.ContextRegistry -void call(String script, boolean returnStatus = false) { +void call(String script) { ContextRegistry.registerDefaultContext(this) - Start start = new Start(script, returnStatus) + Start start = new Start(script) start.run() } From 4f400968ec12dd68100a786bb3605ec86d57b9ac Mon Sep 17 00:00:00 2001 From: Dima Date: Sun, 25 Aug 2024 12:52:19 +0300 Subject: [PATCH 026/112] add coverage for yaxunit, fix smoke dbgs port --- resources/schema.json | 19 ++++++++++- .../configuration/SmokeTestOptions.groovy | 2 +- .../configuration/YaxunitOptions.groovy | 8 +++++ .../jenkins/library/steps/SonarScanner.groovy | 16 +++++++--- .../jenkins/library/steps/Yaxunit.groovy | 32 +++++++++++++++++-- 5 files changed, 68 insertions(+), 9 deletions(-) diff --git a/resources/schema.json b/resources/schema.json index 331e7041..2b6be480 100644 --- a/resources/schema.json +++ b/resources/schema.json @@ -270,7 +270,24 @@ }, "xddConfigPath" : { "type" : "string", - "description" : "Путь к конфигурационному файлу для xddTestRunner.\n По умолчанию содержит значение \"./tools/xUnitParams.json\".\n " + "description" : "Путь к конфигурационному файлу YAXUnit.\n По умолчанию содержит значение \"./tools/yaxunit.json\".\n " + }, + "publishToAllureReport" : { + "type" : "boolean", + "description" : "Выполнять публикацию результатов в отчет Allure.\n По умолчанию выключено.\n " + }, + "publishToJUnitReport" : { + "type" : "boolean", + "description" : "Выполнять публикацию результатов в отчет JUnit.\n По умолчанию включено.\n " + }, + "coverage" : { + "type" : "boolean", + "description" : "Выполнять замер покрытия" + }, + "dbgsPort" : { + "type" : "integer", + "description" : "Порт, на котором будет запущен сервер отладки для замера покрытия" + } } }, "description" : "Настройки дымового тестирования" diff --git a/src/ru/pulsar/jenkins/library/configuration/SmokeTestOptions.groovy b/src/ru/pulsar/jenkins/library/configuration/SmokeTestOptions.groovy index c84df883..562678c3 100644 --- a/src/ru/pulsar/jenkins/library/configuration/SmokeTestOptions.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/SmokeTestOptions.groovy @@ -31,7 +31,7 @@ class SmokeTestOptions implements Serializable { Boolean coverage = false @JsonPropertyDescription("Порт, на котором будет запущен сервер отладки для замера покрытия") - int dbgsPort = 1650 + int dbgsPort = 1550 @Override @NonCPS diff --git a/src/ru/pulsar/jenkins/library/configuration/YaxunitOptions.groovy b/src/ru/pulsar/jenkins/library/configuration/YaxunitOptions.groovy index c285fa1a..c45ae2cc 100644 --- a/src/ru/pulsar/jenkins/library/configuration/YaxunitOptions.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/YaxunitOptions.groovy @@ -27,6 +27,12 @@ class YaxunitOptions implements Serializable { """) boolean publishToJUnitReport + @JsonPropertyDescription("Выполнять замер покрытия") + Boolean coverage = false + + @JsonPropertyDescription("Порт, на котором будет запущен сервер отладки для замера покрытия") + int dbgsPort = 1550 + @Override @NonCPS String toString() { @@ -35,6 +41,8 @@ class YaxunitOptions implements Serializable { ", configPath='" + configPath + ", publishToAllureReport='" + publishToAllureReport + ", publishToJUnitReport='" + publishToJUnitReport + + ", coverage='" + coverage + + ", dbgsPort='" + dbgsPort + '}' } } diff --git a/src/ru/pulsar/jenkins/library/steps/SonarScanner.groovy b/src/ru/pulsar/jenkins/library/steps/SonarScanner.groovy index 84f64e6d..8dcf1589 100644 --- a/src/ru/pulsar/jenkins/library/steps/SonarScanner.groovy +++ b/src/ru/pulsar/jenkins/library/steps/SonarScanner.groovy @@ -69,21 +69,29 @@ class SonarScanner implements Serializable { } } - if (config.stageFlags.bdd && config.bddOptions.coverage - || config.stageFlags.smoke && config.smokeTestOptions.coverage) { + def stageFlags = config.stageFlags + + if (stageFlags.bdd && config.bddOptions.coverage + || stageFlags.smoke && config.smokeTestOptions.coverage + || stageFlags.yaxunit && config.yaxunitOptions.coverage) { StringJoiner coveragePathsConstructor = new StringJoiner(",") - if (config.stageFlags.bdd && config.bddOptions.coverage) { + if (stageFlags.bdd && config.bddOptions.coverage) { steps.unstash(Bdd.COVERAGE_STASH_NAME) coveragePathsConstructor.add(Bdd.COVERAGE_STASH_PATH) } - if (config.stageFlags.smoke && config.smokeTestOptions.coverage) { + 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() sonarCommand += " -Dsonar.coverageReportPaths=${coveragePaths}" diff --git a/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy b/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy index 2587d0bb..2220c67b 100644 --- a/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy @@ -1,6 +1,7 @@ package ru.pulsar.jenkins.library.steps import hudson.FilePath +import org.apache.commons.lang.RandomStringUtils import ru.pulsar.jenkins.library.IStepExecutor import ru.pulsar.jenkins.library.configuration.JobConfiguration @@ -16,6 +17,8 @@ class Yaxunit implements Serializable { private 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' Yaxunit(JobConfiguration config) { this.config = config @@ -62,9 +65,28 @@ class Yaxunit implements Serializable { } - // Выполяем команды - steps.withEnv(logosConfig) { - VRunner.exec(runTestsCommand, true) + def coverageOpts = config.coverageOptions + def port = options.dbgsPort + def lockableResource = RandomStringUtils.random(9, true, false) + if (options.coverage) { + lockableResource = "${env.NODE_NAME}_$port" + } + + steps.lock(null, 1, lockableResource) { + if (options.coverage) { + steps.start("${coverageOpts.dbgsPath} --addr=127.0.0.1 --port=$port") + steps.start("${coverageOpts.coverage41CPath} start -i DefAlias -u http://127.0.0.1:$port -P $workspaceDir -s $srcDir -o $COVERAGE_STASH_PATH") + steps.cmd("${coverageOpts.coverage41CPath} check -i DefAlias -u http://127.0.0.1:$port") + } + + // Выполняем команды + steps.withEnv(logosConfig) { + VRunner.exec(runTestsCommand, true) + } + + if (options.coverage) { + steps.cmd("${coverageOpts.coverage41CPath} stop -i DefAlias -u http://127.0.0.1:$port") + } } // Сохраняем результаты @@ -86,5 +108,9 @@ class Yaxunit implements Serializable { steps.stash(YAXUNIT_ALLURE_STASH, "$allureReportDir/**", true) } + + if (options.coverage) { + steps.stash(COVERAGE_STASH_NAME, COVERAGE_STASH_PATH, true) + } } } From 47049add37151ae854456d91edebe462fd6a3d76 Mon Sep 17 00:00:00 2001 From: Dima Date: Sun, 25 Aug 2024 13:26:43 +0300 Subject: [PATCH 027/112] fix yaxunit coverage --- src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy b/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy index 2220c67b..629e4286 100644 --- a/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy @@ -42,6 +42,9 @@ class Yaxunit implements Serializable { def options = config.yaxunitOptions def env = steps.env() + def srcDir = config.srcDir + def workspaceDir = FileUtils.getFilePath("$env.WORKSPACE") + String vrunnerPath = VRunner.getVRunnerPath() String ibConnection = ' --ibconnection "/F./build/ib"' From d89a61520de662e25d16c60a1c3bd0c6569e2597 Mon Sep 17 00:00:00 2001 From: Dima Date: Sun, 17 Nov 2024 14:03:06 +0300 Subject: [PATCH 028/112] upd schema.json --- resources/schema.json | 86 +++++++++++++++++++------------------------ 1 file changed, 37 insertions(+), 49 deletions(-) diff --git a/resources/schema.json b/resources/schema.json index 2b6be480..689da43f 100644 --- a/resources/schema.json +++ b/resources/schema.json @@ -28,6 +28,14 @@ "bdd" : { "type" : "object", "properties" : { + "coverage" : { + "type" : "boolean", + "description" : "Выполнять замер покрытия" + }, + "dbgsPort" : { + "type" : "integer", + "description" : "Порт, на котором будет запущен сервер отладки для замера покрытия" + }, "vrunnerSteps" : { "description" : "Шаги, запускаемые через vrunner.\n В каждой строке передается отдельная команда \n vrunner и ее аргументы (например, \"vanessa --settings ./tools/vrunner.json\").\n По умолчанию содержит одну команду \"vanessa --settings ./tools/vrunner.json\".\n ", "type" : "array", @@ -38,6 +46,20 @@ }, "description" : "Настройки шага запуска BDD сценариев" }, + "coverage" : { + "type" : "object", + "properties" : { + "coverage41CPath" : { + "type" : "string", + "description" : "Путь к исполняемому файлу Coverage41C\n По умолчанию равен Coverage41C.\n " + }, + "dbgsPath" : { + "type" : "string", + "description" : "Путь к исполняемому файлу dbgs.\n По умолчанию равен /opt/1cv8/current/dbgs.\n " + } + }, + "description" : "Настройки замеров покрытия" + }, "defaultBranch" : { "type" : "string", "description" : "Имя ветки по умолчанию. Значение по умолчанию - main." @@ -81,14 +103,6 @@ "items" : { "type" : "string" } - }, - "coverage" : { - "type" : "boolean", - "description" : "Выполнять замер покрытия" - }, - "dbgsPort" : { - "type" : "integer", - "description" : "Порт, на котором будет запущен сервер отладки для замера покрытия" } } } @@ -231,14 +245,6 @@ "smoke" : { "type" : "object", "properties" : { - "publishToAllureReport" : { - "type" : "boolean", - "description" : "Выполнять публикацию результатов в отчет Allure.\n По умолчанию выключено.\n " - }, - "publishToJUnitReport" : { - "type" : "boolean", - "description" : "Выполнять публикацию результатов в отчет JUnit.\n По умолчанию включено.\n " - }, "coverage" : { "type" : "boolean", "description" : "Выполнять замер покрытия" @@ -246,31 +252,6 @@ "dbgsPort" : { "type" : "integer", "description" : "Порт, на котором будет запущен сервер отладки для замера покрытия" - } - } - }, - "coverage" : { - "type" : "object", - "id" : "urn:jsonschema:ru:pulsar:jenkins:library:configuration:CoverageOptions", - "description" : "Настройки замеров покрытия", - "properties" : { - "dbgsPath" : { - "type" : "string", - "description" : "Путь к исполняемому файлу dbgs.\n По умолчанию равен /opt/1cv8/current/dbgs.\n " - }, - "coverage41CPath" : { - "type" : "string", - "description" : "Путь к исполняемому файлу Coverage41C\n По умолчанию равен Coverage41C.\n " - } - } - }, - "vrunnerSettings" : { - "type" : "string", - "description" : "Путь к конфигурационному файлу vanessa-runner.\n По умолчанию содержит значение \"./tools/vrunner.json\".\n " - }, - "xddConfigPath" : { - "type" : "string", - "description" : "Путь к конфигурационному файлу YAXUnit.\n По умолчанию содержит значение \"./tools/yaxunit.json\".\n " }, "publishToAllureReport" : { "type" : "boolean", @@ -280,14 +261,13 @@ "type" : "boolean", "description" : "Выполнять публикацию результатов в отчет JUnit.\n По умолчанию включено.\n " }, - "coverage" : { - "type" : "boolean", - "description" : "Выполнять замер покрытия" + "vrunnerSettings" : { + "type" : "string", + "description" : "Путь к конфигурационному файлу vanessa-runner.\n По умолчанию содержит значение \"./tools/vrunner.json\".\n " }, - "dbgsPort" : { - "type" : "integer", - "description" : "Порт, на котором будет запущен сервер отладки для замера покрытия" - } + "xddConfigPath" : { + "type" : "string", + "description" : "Путь к конфигурационному файлу для xddTestRunner.\n По умолчанию содержит значение \"./tools/xUnitParams.json\".\n " } }, "description" : "Настройки дымового тестирования" @@ -299,7 +279,7 @@ "type" : "string", "enum" : [ "auto", "fromEnv" ], "description" : "Вариант конфигурации branch plugin.\n Поддерживаемые варианты:\n * auto - применяется автоконфигурация sonar-scanner силами branchplugin. Так же может применяться для отключения конфигурирования, если branch plugin отсутствует;\n * fromEnv - применяется ручная конфигурация sonar-scanner на основе переменных среды.\n Значение по умолчанию: fromEnv.", - "default" : "auto" + "default" : "fromEnv" }, "infoBaseUpdateModuleName" : { "type" : "string", @@ -482,6 +462,14 @@ "type" : "string", "description" : "Путь к конфигурационному файлу YAXUnit.\n По умолчанию содержит значение \"./tools/yaxunit.json\".\n " }, + "coverage" : { + "type" : "boolean", + "description" : "Выполнять замер покрытия" + }, + "dbgsPort" : { + "type" : "integer", + "description" : "Порт, на котором будет запущен сервер отладки для замера покрытия" + }, "publishToAllureReport" : { "type" : "boolean", "description" : "Выполнять публикацию результатов в отчет Allure.\n По умолчанию выключено.\n " From dad3bad395a9213a567d7dfc4768ae2a5c3a4015 Mon Sep 17 00:00:00 2001 From: Dima Date: Tue, 19 Nov 2024 17:08:08 +0300 Subject: [PATCH 029/112] upd global conf --- resources/globalConfiguration.json | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/resources/globalConfiguration.json b/resources/globalConfiguration.json index 0032ea0b..f1c2c21b 100644 --- a/resources/globalConfiguration.json +++ b/resources/globalConfiguration.json @@ -51,7 +51,8 @@ "vrunnerSteps": [ "vanessa --settings ./tools/vrunner.json" ], - "coverage": false + "coverage": false, + "dbgsPort": 1550 }, "sonarqube": { "sonarQubeInstallation": "", @@ -85,7 +86,8 @@ "xddConfigPath": "./tools/xUnitParams.json", "publishToAllureReport": false, "publishToJUnitReport": true, - "coverage": false + "coverage": false, + "dbgsPort": 1551 }, "coverage": { "dbgsPath": "/opt/1cv8/current/dbgs", @@ -95,7 +97,9 @@ "vrunnerSettings": "./tools/vrunner.json", "configPath": "./tools/yaxunit.json", "publishToAllureReport": false, - "publishToJUnitReport": true + "publishToJUnitReport": true, + "coverage": false, + "dbgsPort": 1552 }, "resultsTransform": { "transformer": "stebi", From d653ea01dd70b7737bc53162c1c17d96f1e37f0d Mon Sep 17 00:00:00 2001 From: Dima Date: Tue, 19 Nov 2024 17:08:21 +0300 Subject: [PATCH 030/112] fix --- src/ru/pulsar/jenkins/library/IStepExecutor.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ru/pulsar/jenkins/library/IStepExecutor.groovy b/src/ru/pulsar/jenkins/library/IStepExecutor.groovy index ae6d680e..18264408 100644 --- a/src/ru/pulsar/jenkins/library/IStepExecutor.groovy +++ b/src/ru/pulsar/jenkins/library/IStepExecutor.groovy @@ -66,7 +66,7 @@ interface IStepExecutor { def withEnv(List strings, Closure body) - def lock(String label, int quantity, String resource, Closure objectClosure) + def lock(String label, int quantity, String resource, Closure body) def archiveArtifacts(String path) From cc0c3fbf9ef964afa7f5f03be88c15f9c219d1af Mon Sep 17 00:00:00 2001 From: Dima Date: Sat, 3 Jun 2023 08:24:19 +0300 Subject: [PATCH 031/112] add coverage --- .../configuration/ConfigurationReader.groovy | 17 +++++++++++++++ .../configuration/JobConfiguration.groovy | 4 ++++ .../jenkins/library/steps/SonarScanner.groovy | 21 +++++++++++++++++++ 3 files changed, 42 insertions(+) diff --git a/src/ru/pulsar/jenkins/library/configuration/ConfigurationReader.groovy b/src/ru/pulsar/jenkins/library/configuration/ConfigurationReader.groovy index 477fbfa3..acea3cc3 100644 --- a/src/ru/pulsar/jenkins/library/configuration/ConfigurationReader.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/ConfigurationReader.groovy @@ -82,6 +82,7 @@ class ConfigurationReader implements Serializable { mergeObjects(baseConfiguration, configurationToMerge, nonMergeableSettings) mergeInitInfoBaseOptions(baseConfiguration.initInfoBaseOptions, configurationToMerge.initInfoBaseOptions) mergeBddOptions(baseConfiguration.bddOptions, configurationToMerge.bddOptions) + mergeCoverageOptions(baseConfiguration.coverageOptions, configurationToMerge.coverageOptions) mergeSyntaxCheckOptions(baseConfiguration.syntaxCheckOptions, configurationToMerge.syntaxCheckOptions) mergeNotificationsOptions(baseConfiguration.notificationsOptions, configurationToMerge.notificationsOptions) @@ -148,6 +149,22 @@ class ConfigurationReader implements Serializable { baseObject.vrunnerSteps = objectToMerge.vrunnerSteps.clone() } + @NonCPS + private static void mergeCoverageOptions(CoverageOptions baseObject, CoverageOptions objectToMerge) { + + if (objectToMerge == null) { + return + } + + if (objectToMerge.dbgsPath != null) { + baseObject.dbgsPath = objectToMerge.dbgsPath + } + + if (objectToMerge.coverage41CPath != null) { + baseObject.coverage41CPath = objectToMerge.coverage41CPath + } + } + @NonCPS private static void mergeSyntaxCheckOptions(SyntaxCheckOptions baseObject, SyntaxCheckOptions objectToMerge) { if (objectToMerge == null || objectToMerge.checkModes == null) { diff --git a/src/ru/pulsar/jenkins/library/configuration/JobConfiguration.groovy b/src/ru/pulsar/jenkins/library/configuration/JobConfiguration.groovy index accba947..8e4468e8 100644 --- a/src/ru/pulsar/jenkins/library/configuration/JobConfiguration.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/JobConfiguration.groovy @@ -60,6 +60,10 @@ class JobConfiguration implements Serializable { @JsonPropertyDescription("Настройки замеров покрытия") CoverageOptions coverageOptions; + @JsonProperty("coverage") + @JsonPropertyDescription("Настройки замеров покрытия") + CoverageOptions coverageOptions; + @JsonProperty("yaxunit") @JsonPropertyDescription("Настройки YAXUnit") YaxunitOptions yaxunitOptions diff --git a/src/ru/pulsar/jenkins/library/steps/SonarScanner.groovy b/src/ru/pulsar/jenkins/library/steps/SonarScanner.groovy index 8dcf1589..21e7b87a 100644 --- a/src/ru/pulsar/jenkins/library/steps/SonarScanner.groovy +++ b/src/ru/pulsar/jenkins/library/steps/SonarScanner.groovy @@ -98,6 +98,27 @@ class SonarScanner implements Serializable { } + if (config.stageFlags.bdd && config.bddOptions.coverage + || config.stageFlags.smoke && config.smokeTestOptions.coverage) { + + StringJoiner coveragePathsConstructor = new StringJoiner(",") + + if (config.stageFlags.bdd && config.bddOptions.coverage) { + steps.unstash("bdd-coverage") + coveragePathsConstructor.add("build/out/bdd-coverage.xml") + } + + if (config.stageFlags.smoke && config.smokeTestOptions.coverage) { + steps.unstash("smoketest-coverage") + coveragePathsConstructor.add("build/out/smoketest-coverage.xml") + } + + String coveragePaths = coveragePathsConstructor.toString() + + sonarCommand += " -Dsonar.coverageReportPaths=${coveragePaths}" + + } + if (config.sonarQubeOptions.waitForQualityGate) { def timeoutInSeconds = config.timeoutOptions.sonarqube * 60 sonarCommand += ' -Dsonar.qualitygate.wait=true' From 79572e74eb77c1dcb6bcd8febc4b4556b4e65767 Mon Sep 17 00:00:00 2001 From: Dima Date: Mon, 12 Jun 2023 10:41:18 +0300 Subject: [PATCH 032/112] fix --- .../pulsar/jenkins/library/utils/PortPicker.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 src/ru/pulsar/jenkins/library/utils/PortPicker.java diff --git a/src/ru/pulsar/jenkins/library/utils/PortPicker.java b/src/ru/pulsar/jenkins/library/utils/PortPicker.java new file mode 100644 index 00000000..ab6efb6e --- /dev/null +++ b/src/ru/pulsar/jenkins/library/utils/PortPicker.java @@ -0,0 +1,14 @@ +package ru.pulsar.jenkins.library.utils; + +import com.cloudbees.groovy.cps.NonCPS; + +import java.io.IOException; +import java.net.ServerSocket; + +public class PortPicker { + @NonCPS + static int port() throws IOException { + int result = new ServerSocket(0).getLocalPort(); + return result; + } +} From 8a892bc67676e085a12b956855d943378e9948de Mon Sep 17 00:00:00 2001 From: Dima Date: Mon, 12 Jun 2023 11:08:01 +0300 Subject: [PATCH 033/112] fix class --- .../pulsar/jenkins/library/utils/PortPicker.java | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 src/ru/pulsar/jenkins/library/utils/PortPicker.java diff --git a/src/ru/pulsar/jenkins/library/utils/PortPicker.java b/src/ru/pulsar/jenkins/library/utils/PortPicker.java deleted file mode 100644 index ab6efb6e..00000000 --- a/src/ru/pulsar/jenkins/library/utils/PortPicker.java +++ /dev/null @@ -1,14 +0,0 @@ -package ru.pulsar.jenkins.library.utils; - -import com.cloudbees.groovy.cps.NonCPS; - -import java.io.IOException; -import java.net.ServerSocket; - -public class PortPicker { - @NonCPS - static int port() throws IOException { - int result = new ServerSocket(0).getLocalPort(); - return result; - } -} From 29520e7467b7e4a9682569caa46c43903dfc3f85 Mon Sep 17 00:00:00 2001 From: Dima Date: Mon, 12 Jun 2023 11:37:26 +0300 Subject: [PATCH 034/112] add class --- src/ru/pulsar/jenkins/library/utils/PortPicker.groovy | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/ru/pulsar/jenkins/library/utils/PortPicker.groovy diff --git a/src/ru/pulsar/jenkins/library/utils/PortPicker.groovy b/src/ru/pulsar/jenkins/library/utils/PortPicker.groovy new file mode 100644 index 00000000..552ea98a --- /dev/null +++ b/src/ru/pulsar/jenkins/library/utils/PortPicker.groovy @@ -0,0 +1,11 @@ +package ru.pulsar.jenkins.library.utils + +import com.cloudbees.groovy.cps.NonCPS + +class PortPicker { + + @NonCPS + static int getPort() { + return new ServerSocket(0).getLocalPort() + } +} From a830c68f7e8ac68dba0b16e0f73536f803179f54 Mon Sep 17 00:00:00 2001 From: Dima Date: Mon, 17 Jul 2023 15:38:09 +0300 Subject: [PATCH 035/112] add lockable resources in bdd --- .../configuration/ConfigurationReader.groovy | 17 ----------------- .../configuration/CoverageOptions.groovy | 6 ++++++ .../groovy/jobConfigurationTest.groovy | 1 + .../integration/resources/jobConfiguration.json | 1 + 4 files changed, 8 insertions(+), 17 deletions(-) diff --git a/src/ru/pulsar/jenkins/library/configuration/ConfigurationReader.groovy b/src/ru/pulsar/jenkins/library/configuration/ConfigurationReader.groovy index acea3cc3..477fbfa3 100644 --- a/src/ru/pulsar/jenkins/library/configuration/ConfigurationReader.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/ConfigurationReader.groovy @@ -82,7 +82,6 @@ class ConfigurationReader implements Serializable { mergeObjects(baseConfiguration, configurationToMerge, nonMergeableSettings) mergeInitInfoBaseOptions(baseConfiguration.initInfoBaseOptions, configurationToMerge.initInfoBaseOptions) mergeBddOptions(baseConfiguration.bddOptions, configurationToMerge.bddOptions) - mergeCoverageOptions(baseConfiguration.coverageOptions, configurationToMerge.coverageOptions) mergeSyntaxCheckOptions(baseConfiguration.syntaxCheckOptions, configurationToMerge.syntaxCheckOptions) mergeNotificationsOptions(baseConfiguration.notificationsOptions, configurationToMerge.notificationsOptions) @@ -149,22 +148,6 @@ class ConfigurationReader implements Serializable { baseObject.vrunnerSteps = objectToMerge.vrunnerSteps.clone() } - @NonCPS - private static void mergeCoverageOptions(CoverageOptions baseObject, CoverageOptions objectToMerge) { - - if (objectToMerge == null) { - return - } - - if (objectToMerge.dbgsPath != null) { - baseObject.dbgsPath = objectToMerge.dbgsPath - } - - if (objectToMerge.coverage41CPath != null) { - baseObject.coverage41CPath = objectToMerge.coverage41CPath - } - } - @NonCPS private static void mergeSyntaxCheckOptions(SyntaxCheckOptions baseObject, SyntaxCheckOptions objectToMerge) { if (objectToMerge == null || objectToMerge.checkModes == null) { diff --git a/src/ru/pulsar/jenkins/library/configuration/CoverageOptions.groovy b/src/ru/pulsar/jenkins/library/configuration/CoverageOptions.groovy index 665f3dca..dbb677ca 100644 --- a/src/ru/pulsar/jenkins/library/configuration/CoverageOptions.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/CoverageOptions.groovy @@ -12,6 +12,11 @@ class CoverageOptions implements Serializable { ''') String dbgsPath + @JsonPropertyDescription('''Порт сервера отладки. + По умолчанию равен 1550. + ''') + int dbgsPort = 1550 + @JsonPropertyDescription('''Путь к исполняемому файлу Coverage41C По умолчанию равен Coverage41C. ''') @@ -22,6 +27,7 @@ class CoverageOptions implements Serializable { String toString() { return "coverageOptions{" + "dbgsPath=" + dbgsPath + + "dbgsPort=" + dbgsPort + ", coverage41CPath=" + coverage41CPath + '}' } diff --git a/test/integration/groovy/jobConfigurationTest.groovy b/test/integration/groovy/jobConfigurationTest.groovy index c77feecf..b1788e32 100644 --- a/test/integration/groovy/jobConfigurationTest.groovy +++ b/test/integration/groovy/jobConfigurationTest.groovy @@ -75,6 +75,7 @@ class jobConfigurationTest { 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("dbgsPort=4543", 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 ebd5e6fd..82c836c7 100644 --- a/test/integration/resources/jobConfiguration.json +++ b/test/integration/resources/jobConfiguration.json @@ -13,6 +13,7 @@ }, "coverage": { "dbgsPath": "C:\\\\Program files\\\\1cv8\\\\8.3.12.1500\\\\bin\\\\dbgs.exe", + "dbgsPort": 4543, "coverage41CPath": "C:\\\\coverage\\\\Coverage41C.exe" } } \ No newline at end of file From f893c11527d2c3bb048b7fed5656a149e8a5ea7f Mon Sep 17 00:00:00 2001 From: Dima Date: Mon, 17 Jul 2023 18:04:16 +0300 Subject: [PATCH 036/112] finalize --- .../jenkins/library/configuration/CoverageOptions.groovy | 6 ------ src/ru/pulsar/jenkins/library/steps/SonarScanner.groovy | 8 ++++---- test/integration/groovy/jobConfigurationTest.groovy | 1 - test/integration/resources/jobConfiguration.json | 1 - 4 files changed, 4 insertions(+), 12 deletions(-) diff --git a/src/ru/pulsar/jenkins/library/configuration/CoverageOptions.groovy b/src/ru/pulsar/jenkins/library/configuration/CoverageOptions.groovy index dbb677ca..665f3dca 100644 --- a/src/ru/pulsar/jenkins/library/configuration/CoverageOptions.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/CoverageOptions.groovy @@ -12,11 +12,6 @@ class CoverageOptions implements Serializable { ''') String dbgsPath - @JsonPropertyDescription('''Порт сервера отладки. - По умолчанию равен 1550. - ''') - int dbgsPort = 1550 - @JsonPropertyDescription('''Путь к исполняемому файлу Coverage41C По умолчанию равен Coverage41C. ''') @@ -27,7 +22,6 @@ class CoverageOptions implements Serializable { String toString() { return "coverageOptions{" + "dbgsPath=" + dbgsPath + - "dbgsPort=" + dbgsPort + ", coverage41CPath=" + coverage41CPath + '}' } diff --git a/src/ru/pulsar/jenkins/library/steps/SonarScanner.groovy b/src/ru/pulsar/jenkins/library/steps/SonarScanner.groovy index 21e7b87a..9103e795 100644 --- a/src/ru/pulsar/jenkins/library/steps/SonarScanner.groovy +++ b/src/ru/pulsar/jenkins/library/steps/SonarScanner.groovy @@ -104,13 +104,13 @@ class SonarScanner implements Serializable { StringJoiner coveragePathsConstructor = new StringJoiner(",") if (config.stageFlags.bdd && config.bddOptions.coverage) { - steps.unstash("bdd-coverage") - coveragePathsConstructor.add("build/out/bdd-coverage.xml") + steps.unstash(Bdd.COVERAGE_STASH_NAME) + coveragePathsConstructor.add(Bdd.COVERAGE_STASH_PATH) } if (config.stageFlags.smoke && config.smokeTestOptions.coverage) { - steps.unstash("smoketest-coverage") - coveragePathsConstructor.add("build/out/smoketest-coverage.xml") + steps.unstash(SmokeTest.COVERAGE_STASH_NAME) + coveragePathsConstructor.add(SmokeTest.COVERAGE_STASH_PATH) } String coveragePaths = coveragePathsConstructor.toString() diff --git a/test/integration/groovy/jobConfigurationTest.groovy b/test/integration/groovy/jobConfigurationTest.groovy index b1788e32..c77feecf 100644 --- a/test/integration/groovy/jobConfigurationTest.groovy +++ b/test/integration/groovy/jobConfigurationTest.groovy @@ -75,7 +75,6 @@ class jobConfigurationTest { 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("dbgsPort=4543", 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 82c836c7..ebd5e6fd 100644 --- a/test/integration/resources/jobConfiguration.json +++ b/test/integration/resources/jobConfiguration.json @@ -13,7 +13,6 @@ }, "coverage": { "dbgsPath": "C:\\\\Program files\\\\1cv8\\\\8.3.12.1500\\\\bin\\\\dbgs.exe", - "dbgsPort": 4543, "coverage41CPath": "C:\\\\coverage\\\\Coverage41C.exe" } } \ No newline at end of file From 92f1dce4643f792a695fc58f77a4bd88bf9929d1 Mon Sep 17 00:00:00 2001 From: Dima Date: Mon, 17 Jul 2023 23:16:37 +0300 Subject: [PATCH 037/112] rm unused class --- src/ru/pulsar/jenkins/library/utils/PortPicker.groovy | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 src/ru/pulsar/jenkins/library/utils/PortPicker.groovy diff --git a/src/ru/pulsar/jenkins/library/utils/PortPicker.groovy b/src/ru/pulsar/jenkins/library/utils/PortPicker.groovy deleted file mode 100644 index 552ea98a..00000000 --- a/src/ru/pulsar/jenkins/library/utils/PortPicker.groovy +++ /dev/null @@ -1,11 +0,0 @@ -package ru.pulsar.jenkins.library.utils - -import com.cloudbees.groovy.cps.NonCPS - -class PortPicker { - - @NonCPS - static int getPort() { - return new ServerSocket(0).getLocalPort() - } -} From aa4aaa271d925c04d576558743be335828a3f0df Mon Sep 17 00:00:00 2001 From: Dima Date: Sun, 25 Aug 2024 12:52:19 +0300 Subject: [PATCH 038/112] add coverage for yaxunit, fix smoke dbgs port --- .../jenkins/library/steps/SonarScanner.groovy | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/ru/pulsar/jenkins/library/steps/SonarScanner.groovy b/src/ru/pulsar/jenkins/library/steps/SonarScanner.groovy index 9103e795..56c56c96 100644 --- a/src/ru/pulsar/jenkins/library/steps/SonarScanner.groovy +++ b/src/ru/pulsar/jenkins/library/steps/SonarScanner.groovy @@ -98,21 +98,29 @@ class SonarScanner implements Serializable { } - if (config.stageFlags.bdd && config.bddOptions.coverage - || config.stageFlags.smoke && config.smokeTestOptions.coverage) { + def stageFlags = config.stageFlags + + if (stageFlags.bdd && config.bddOptions.coverage + || stageFlags.smoke && config.smokeTestOptions.coverage + || stageFlags.yaxunit && config.yaxunitOptions.coverage) { StringJoiner coveragePathsConstructor = new StringJoiner(",") - if (config.stageFlags.bdd && config.bddOptions.coverage) { + if (stageFlags.bdd && config.bddOptions.coverage) { steps.unstash(Bdd.COVERAGE_STASH_NAME) coveragePathsConstructor.add(Bdd.COVERAGE_STASH_PATH) } - if (config.stageFlags.smoke && config.smokeTestOptions.coverage) { + 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() sonarCommand += " -Dsonar.coverageReportPaths=${coveragePaths}" From e6fdfc1151f9326494501d04d65eccdffec95a81 Mon Sep 17 00:00:00 2001 From: Dima Date: Sun, 1 Sep 2024 13:13:32 +0300 Subject: [PATCH 039/112] yaxunit coverage cleanup --- .../library/steps/CoverageCleanup.groovy | 31 +++++++++++++++++++ vars/coverageCleanup.groovy | 11 +++++++ vars/pipeline1C.groovy | 5 +++ 3 files changed, 47 insertions(+) create mode 100644 src/ru/pulsar/jenkins/library/steps/CoverageCleanup.groovy create mode 100644 vars/coverageCleanup.groovy diff --git a/src/ru/pulsar/jenkins/library/steps/CoverageCleanup.groovy b/src/ru/pulsar/jenkins/library/steps/CoverageCleanup.groovy new file mode 100644 index 00000000..e53dbdae --- /dev/null +++ b/src/ru/pulsar/jenkins/library/steps/CoverageCleanup.groovy @@ -0,0 +1,31 @@ +package ru.pulsar.jenkins.library.steps + +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.Logger + +class CoverageCleanup implements Serializable { + + private final JobConfiguration config; + + private String encoding = 'UTF-8' + + CoverageCleanup(JobConfiguration config) { + this.config = config + } + + def run() { + IStepExecutor steps = ContextRegistry.getContext().getStepExecutor() + + Logger.printLocation() + + if (steps.isUnix()) { + def command = "pkill Coverage41C && pkill dbgs" + steps.sh(command, false, false, encoding) + } else { + def command = "taskkill /IM Coverage41C /F & taskkill /IM dbgs /F" + steps.sh(command, false, false, encoding) + } + } +} diff --git a/vars/coverageCleanup.groovy b/vars/coverageCleanup.groovy new file mode 100644 index 00000000..34991c13 --- /dev/null +++ b/vars/coverageCleanup.groovy @@ -0,0 +1,11 @@ +import ru.pulsar.jenkins.library.configuration.JobConfiguration +import ru.pulsar.jenkins.library.ioc.ContextRegistry +import ru.pulsar.jenkins.library.steps.CoverageCleanup + +def call(JobConfiguration config) { + ContextRegistry.registerDefaultContext(this) + + def coverageCleanup = new CoverageCleanup(config); + coverageCleanup.run() + +} \ No newline at end of file diff --git a/vars/pipeline1C.groovy b/vars/pipeline1C.groovy index 867e3830..ac36a19d 100644 --- a/vars/pipeline1C.groovy +++ b/vars/pipeline1C.groovy @@ -325,6 +325,11 @@ void call() { yaxunit config } } + post('yaxunit-coverage-cleanup') { + always { + coverageCleanup config + } + } } } } From 5c7a6e0a4503bcf2a6b49d6fb00c6fff5594e01a Mon Sep 17 00:00:00 2001 From: Dima Date: Sun, 1 Sep 2024 15:48:47 +0300 Subject: [PATCH 040/112] fix --- .../pulsar/jenkins/library/steps/CoverageCleanup.groovy | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ru/pulsar/jenkins/library/steps/CoverageCleanup.groovy b/src/ru/pulsar/jenkins/library/steps/CoverageCleanup.groovy index e53dbdae..3a0c8bbd 100644 --- a/src/ru/pulsar/jenkins/library/steps/CoverageCleanup.groovy +++ b/src/ru/pulsar/jenkins/library/steps/CoverageCleanup.groovy @@ -7,7 +7,7 @@ import ru.pulsar.jenkins.library.utils.Logger class CoverageCleanup implements Serializable { - private final JobConfiguration config; + private final JobConfiguration config private String encoding = 'UTF-8' @@ -21,11 +21,11 @@ class CoverageCleanup implements Serializable { Logger.printLocation() if (steps.isUnix()) { - def command = "pkill Coverage41C && pkill dbgs" - steps.sh(command, false, false, encoding) + def command = "pkill Coverage41C ; pkill dbgs" + steps.sh(command, true, false, encoding) } else { def command = "taskkill /IM Coverage41C /F & taskkill /IM dbgs /F" - steps.sh(command, false, false, encoding) + steps.sh(command, true, false, encoding) } } } From a7e4d3b29051c433c15c333142bcdde351583571 Mon Sep 17 00:00:00 2001 From: Dima Date: Mon, 2 Sep 2024 16:06:02 +0300 Subject: [PATCH 041/112] add smart cleanup in yaxunit --- .../library/steps/CoverageCleanup.groovy | 12 +++++++-- .../jenkins/library/steps/Yaxunit.groovy | 25 ++++++++++++++++++- vars/pipeline1C.groovy | 8 ++++-- 3 files changed, 40 insertions(+), 5 deletions(-) diff --git a/src/ru/pulsar/jenkins/library/steps/CoverageCleanup.groovy b/src/ru/pulsar/jenkins/library/steps/CoverageCleanup.groovy index 3a0c8bbd..d4206644 100644 --- a/src/ru/pulsar/jenkins/library/steps/CoverageCleanup.groovy +++ b/src/ru/pulsar/jenkins/library/steps/CoverageCleanup.groovy @@ -20,11 +20,19 @@ class CoverageCleanup implements Serializable { Logger.printLocation() + String dbgsPIDS = env.YAXUNIT_DBGS_PIDS + String coverage41CPIDS = env.YAXUNIT_COVERAGE41C_PIDS + + def combined = dbgsPIDS + " " + coverage41CPIDS + if (steps.isUnix()) { - def command = "pkill Coverage41C ; pkill dbgs" + def command = "pkill $combined" steps.sh(command, true, false, encoding) } else { - def command = "taskkill /IM Coverage41C /F & taskkill /IM dbgs /F" + def winCommand = combined.split(" ") + .each { it -> "/PID $it" } + .join(" ") + def command = "taskkill $winCommand /F" steps.sh(command, true, false, encoding) } } diff --git a/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy b/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy index 629e4286..8a73fe8f 100644 --- a/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy @@ -14,7 +14,7 @@ class Yaxunit implements Serializable { 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' @@ -71,6 +71,8 @@ class Yaxunit implements Serializable { def coverageOpts = config.coverageOptions def port = options.dbgsPort def lockableResource = RandomStringUtils.random(9, true, false) + def currentDbgsPids = getPIDs("dbgs") + def currentCoverage41CPids = getPIDs("Coverage41C") if (options.coverage) { lockableResource = "${env.NODE_NAME}_$port" } @@ -80,6 +82,13 @@ class Yaxunit implements Serializable { steps.start("${coverageOpts.dbgsPath} --addr=127.0.0.1 --port=$port") steps.start("${coverageOpts.coverage41CPath} start -i DefAlias -u http://127.0.0.1:$port -P $workspaceDir -s $srcDir -o $COVERAGE_STASH_PATH") steps.cmd("${coverageOpts.coverage41CPath} check -i DefAlias -u http://127.0.0.1:$port") + + def newDbgsPids = getPIDs("dbgs") + def newCoverage41CPids = getPIDs("Coverage41C") + + env.YAXUNIT_DBGS_PIDS = (newDbgsPids - currentDbgsPids).join(" ") + env.YAXUNIT_COVERAGE41C_PIDS = (newCoverage41CPids - currentCoverage41CPids).join(" ") + } // Выполняем команды @@ -116,4 +125,18 @@ class Yaxunit implements Serializable { steps.stash(COVERAGE_STASH_NAME, COVERAGE_STASH_PATH, true) } } + + private static ArrayList getPIDs(String name) { + + IStepExecutor steps = ContextRegistry.getContext().getStepExecutor() + + String pids + + if (steps.isUnix()) { + pids = steps.sh("pidof $name", false, true, 'UTF-8') + } else { + pids = steps.bat("chcp 65001 > nul \nfor /f \"tokens=2\" %a in ('tasklist ^| findstr $name') do @echo %a", false, true, 'UTF-8') + } + return pids.split('\n').collect{it as String} + } } diff --git a/vars/pipeline1C.groovy b/vars/pipeline1C.groovy index ac36a19d..f45b7d01 100644 --- a/vars/pipeline1C.groovy +++ b/vars/pipeline1C.groovy @@ -320,13 +320,17 @@ void call() { } stage('Выполнение YAXUnit тестов') { + environment { + YAXUNIT_DBGS_PIDS = "" + YAXUNIT_COVERAGE41C_PIDS = "" + } steps { timeout(time: config.timeoutOptions.yaxunit, unit: TimeUnit.MINUTES) { yaxunit config } } - post('yaxunit-coverage-cleanup') { - always { + post { + cleanup { coverageCleanup config } } From ea2b4036524932a6afd5ef400a54fc2323099382 Mon Sep 17 00:00:00 2001 From: Dima Date: Mon, 2 Sep 2024 17:02:10 +0300 Subject: [PATCH 042/112] fix pids --- src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy b/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy index 8a73fe8f..225ea7ac 100644 --- a/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy @@ -133,7 +133,7 @@ class Yaxunit implements Serializable { String pids if (steps.isUnix()) { - pids = steps.sh("pidof $name", false, true, 'UTF-8') + pids = steps.sh("ps -aux | grep '$name' | awk '{print \$2}'", false, true, 'UTF-8') } else { pids = steps.bat("chcp 65001 > nul \nfor /f \"tokens=2\" %a in ('tasklist ^| findstr $name') do @echo %a", false, true, 'UTF-8') } From 3cbc4046c5afe41e455393f3380e3726523d1968 Mon Sep 17 00:00:00 2001 From: Dima Date: Mon, 2 Sep 2024 17:07:08 +0300 Subject: [PATCH 043/112] fix pids --- .../jenkins/library/steps/CoverageCleanup.groovy | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/ru/pulsar/jenkins/library/steps/CoverageCleanup.groovy b/src/ru/pulsar/jenkins/library/steps/CoverageCleanup.groovy index d4206644..4cdd3bb8 100644 --- a/src/ru/pulsar/jenkins/library/steps/CoverageCleanup.groovy +++ b/src/ru/pulsar/jenkins/library/steps/CoverageCleanup.groovy @@ -20,13 +20,18 @@ class CoverageCleanup implements Serializable { Logger.printLocation() - String dbgsPIDS = env.YAXUNIT_DBGS_PIDS - String coverage41CPIDS = env.YAXUNIT_COVERAGE41C_PIDS + def env = steps.env(); + String dbgsPIDS = env.YAXUNIT_DBGS_PIDS // space-delimited string + String coverage41CPIDS = env.YAXUNIT_COVERAGE41C_PIDS // space-delimited string - def combined = dbgsPIDS + " " + coverage41CPIDS + def combined = (dbgsPIDS + " " + coverage41CPIDS).trim() + + if (combined.isEmpty()) { + return + } if (steps.isUnix()) { - def command = "pkill $combined" + def command = "kill $combined" steps.sh(command, true, false, encoding) } else { def winCommand = combined.split(" ") From 8c1a119f220b0cbb58ca2a093bf35134c477f2c6 Mon Sep 17 00:00:00 2001 From: Dima Date: Mon, 2 Sep 2024 18:05:02 +0300 Subject: [PATCH 044/112] diagnostic message and fixes --- src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy b/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy index 225ea7ac..ef243956 100644 --- a/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy @@ -86,8 +86,13 @@ class Yaxunit implements Serializable { def newDbgsPids = getPIDs("dbgs") def newCoverage41CPids = getPIDs("Coverage41C") - env.YAXUNIT_DBGS_PIDS = (newDbgsPids - currentDbgsPids).join(" ") - env.YAXUNIT_COVERAGE41C_PIDS = (newCoverage41CPids - currentCoverage41CPids).join(" ") + newDbgsPids.removeAll(currentDbgsPids) + newCoverage41CPids.removeAll(currentCoverage41CPids) + + env.YAXUNIT_DBGS_PIDS = newDbgsPids.join(" ") + steps.echo("YAXUNIT_DBGS_PIDS = $env.YAXUNIT_DBGS_PIDS") + env.YAXUNIT_COVERAGE41C_PIDS = newCoverage41CPids.join(" ") + steps.echo("YAXUNIT_COVERAGE41C_PIDS = $env.YAXUNIT_COVERAGE41C_PIDS") } @@ -137,6 +142,6 @@ class Yaxunit implements Serializable { } else { pids = steps.bat("chcp 65001 > nul \nfor /f \"tokens=2\" %a in ('tasklist ^| findstr $name') do @echo %a", false, true, 'UTF-8') } - return pids.split('\n').collect{it as String} + return pids.split('\n') } } From c147ebb924e9423c53095bd2069b98476c2907a6 Mon Sep 17 00:00:00 2001 From: Dima Date: Mon, 2 Sep 2024 19:48:53 +0300 Subject: [PATCH 045/112] toList --- src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy b/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy index ef243956..347b626d 100644 --- a/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy @@ -142,6 +142,6 @@ class Yaxunit implements Serializable { } else { pids = steps.bat("chcp 65001 > nul \nfor /f \"tokens=2\" %a in ('tasklist ^| findstr $name') do @echo %a", false, true, 'UTF-8') } - return pids.split('\n') + return pids.split('\n').toList() } } From 14268a1a2913c90f0700731255c029af971a5cbb Mon Sep 17 00:00:00 2001 From: Dima Date: Tue, 3 Sep 2024 10:29:27 +0300 Subject: [PATCH 046/112] switch pids from env to the file --- .../library/steps/CoverageCleanup.groovy | 25 +++++++++++++------ .../jenkins/library/steps/Yaxunit.groovy | 11 +++++--- vars/coverageCleanup.groovy | 4 +-- vars/pipeline1C.groovy | 6 +---- 4 files changed, 27 insertions(+), 19 deletions(-) diff --git a/src/ru/pulsar/jenkins/library/steps/CoverageCleanup.groovy b/src/ru/pulsar/jenkins/library/steps/CoverageCleanup.groovy index 4cdd3bb8..4a66f576 100644 --- a/src/ru/pulsar/jenkins/library/steps/CoverageCleanup.groovy +++ b/src/ru/pulsar/jenkins/library/steps/CoverageCleanup.groovy @@ -8,11 +8,13 @@ import ru.pulsar.jenkins.library.utils.Logger class CoverageCleanup implements Serializable { private final JobConfiguration config + private final String stageName private String encoding = 'UTF-8' - CoverageCleanup(JobConfiguration config) { + CoverageCleanup(JobConfiguration config, String stageName = "") { this.config = config + this.stageName = stageName } def run() { @@ -20,21 +22,28 @@ class CoverageCleanup implements Serializable { Logger.printLocation() - def env = steps.env(); - String dbgsPIDS = env.YAXUNIT_DBGS_PIDS // space-delimited string - String coverage41CPIDS = env.YAXUNIT_COVERAGE41C_PIDS // space-delimited string + String pidsFilePath = "" + if (stageName == 'yaxunit') { + pidsFilePath = Yaxunit.COVERAGE_PIDS_PATH + } - def combined = (dbgsPIDS + " " + coverage41CPIDS).trim() + def pids = "" + if (steps.fileExists(pidsFilePath)) { + pids = steps.readFile(pidsFilePath) + } - if (combined.isEmpty()) { + if (pids.isEmpty()) { + Logger.println("Нет запущенных процессов dbgs и Coverage41C") return } + Logger.println("Завершение процессов dbgs и Coverage41C с pid: $pids") + if (steps.isUnix()) { - def command = "kill $combined" + def command = "kill $pids" steps.sh(command, true, false, encoding) } else { - def winCommand = combined.split(" ") + def winCommand = pids.split(" ") .each { it -> "/PID $it" } .join(" ") def command = "taskkill $winCommand /F" diff --git a/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy b/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy index 347b626d..6b02daa8 100644 --- a/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy @@ -19,6 +19,7 @@ class Yaxunit implements Serializable { 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 @@ -89,10 +90,12 @@ class Yaxunit implements Serializable { newDbgsPids.removeAll(currentDbgsPids) newCoverage41CPids.removeAll(currentCoverage41CPids) - env.YAXUNIT_DBGS_PIDS = newDbgsPids.join(" ") - steps.echo("YAXUNIT_DBGS_PIDS = $env.YAXUNIT_DBGS_PIDS") - env.YAXUNIT_COVERAGE41C_PIDS = newCoverage41CPids.join(" ") - steps.echo("YAXUNIT_COVERAGE41C_PIDS = $env.YAXUNIT_COVERAGE41C_PIDS") + newDbgsPids.addAll(newCoverage41CPids) + def pids = newDbgsPids.join(" ") + + steps.writeFile(COVERAGE_PIDS_PATH, pids, 'UTF-8') + + Logger.println("Coverage PIDs for cleanup: $pids") } diff --git a/vars/coverageCleanup.groovy b/vars/coverageCleanup.groovy index 34991c13..92fe3458 100644 --- a/vars/coverageCleanup.groovy +++ b/vars/coverageCleanup.groovy @@ -2,10 +2,10 @@ import ru.pulsar.jenkins.library.configuration.JobConfiguration import ru.pulsar.jenkins.library.ioc.ContextRegistry import ru.pulsar.jenkins.library.steps.CoverageCleanup -def call(JobConfiguration config) { +def call(JobConfiguration config, String stageName) { ContextRegistry.registerDefaultContext(this) - def coverageCleanup = new CoverageCleanup(config); + def coverageCleanup = new CoverageCleanup(config, stageName) coverageCleanup.run() } \ No newline at end of file diff --git a/vars/pipeline1C.groovy b/vars/pipeline1C.groovy index f45b7d01..627bedf2 100644 --- a/vars/pipeline1C.groovy +++ b/vars/pipeline1C.groovy @@ -320,10 +320,6 @@ void call() { } stage('Выполнение YAXUnit тестов') { - environment { - YAXUNIT_DBGS_PIDS = "" - YAXUNIT_COVERAGE41C_PIDS = "" - } steps { timeout(time: config.timeoutOptions.yaxunit, unit: TimeUnit.MINUTES) { yaxunit config @@ -331,7 +327,7 @@ void call() { } post { cleanup { - coverageCleanup config + coverageCleanup config, 'yaxunit' } } } From 494a53586e566f5b4b022af95799c66dd9454033 Mon Sep 17 00:00:00 2001 From: Dima Date: Tue, 3 Sep 2024 13:19:01 +0300 Subject: [PATCH 047/112] refactor --- .../jenkins/library/steps/Yaxunit.groovy | 22 +++++-------------- .../library/utils/CoverageUtils.groovy | 20 +++++++++++++++++ 2 files changed, 25 insertions(+), 17 deletions(-) create mode 100644 src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy diff --git a/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy b/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy index 6b02daa8..4a50a5f3 100644 --- a/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy @@ -6,6 +6,7 @@ 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.CoverageUtils import ru.pulsar.jenkins.library.utils.FileUtils import ru.pulsar.jenkins.library.utils.Logger import ru.pulsar.jenkins.library.utils.VRunner @@ -72,8 +73,8 @@ class Yaxunit implements Serializable { def coverageOpts = config.coverageOptions def port = options.dbgsPort def lockableResource = RandomStringUtils.random(9, true, false) - def currentDbgsPids = getPIDs("dbgs") - def currentCoverage41CPids = getPIDs("Coverage41C") + def currentDbgsPids = CoverageUtils.getPIDs("dbgs") + def currentCoverage41CPids = CoverageUtils.getPIDs("Coverage41C") if (options.coverage) { lockableResource = "${env.NODE_NAME}_$port" } @@ -84,8 +85,8 @@ class Yaxunit implements Serializable { steps.start("${coverageOpts.coverage41CPath} start -i DefAlias -u http://127.0.0.1:$port -P $workspaceDir -s $srcDir -o $COVERAGE_STASH_PATH") steps.cmd("${coverageOpts.coverage41CPath} check -i DefAlias -u http://127.0.0.1:$port") - def newDbgsPids = getPIDs("dbgs") - def newCoverage41CPids = getPIDs("Coverage41C") + def newDbgsPids = CoverageUtils.getPIDs("dbgs") + def newCoverage41CPids = CoverageUtils.getPIDs("Coverage41C") newDbgsPids.removeAll(currentDbgsPids) newCoverage41CPids.removeAll(currentCoverage41CPids) @@ -134,17 +135,4 @@ class Yaxunit implements Serializable { } } - private static ArrayList getPIDs(String name) { - - IStepExecutor steps = ContextRegistry.getContext().getStepExecutor() - - String pids - - if (steps.isUnix()) { - pids = steps.sh("ps -aux | grep '$name' | awk '{print \$2}'", false, true, 'UTF-8') - } else { - pids = steps.bat("chcp 65001 > nul \nfor /f \"tokens=2\" %a in ('tasklist ^| findstr $name') do @echo %a", false, true, 'UTF-8') - } - return pids.split('\n').toList() - } } diff --git a/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy b/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy new file mode 100644 index 00000000..e897ae46 --- /dev/null +++ b/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy @@ -0,0 +1,20 @@ +package ru.pulsar.jenkins.library.utils + +import ru.pulsar.jenkins.library.IStepExecutor +import ru.pulsar.jenkins.library.ioc.ContextRegistry + +class CoverageUtils { + static ArrayList getPIDs(String name) { + + IStepExecutor steps = ContextRegistry.getContext().getStepExecutor() + + String pids + + if (steps.isUnix()) { + pids = steps.sh("ps -aux | grep '$name' | awk '{print \$2}'", false, true, 'UTF-8') + } else { + pids = steps.bat("chcp 65001 > nul \nfor /f \"tokens=2\" %a in ('tasklist ^| findstr $name') do @echo %a", false, true, 'UTF-8') + } + return pids.split('\n').toList() + } +} From 7a5669e86d6255f8c1a6b1bfe35de9c7d4f99212 Mon Sep 17 00:00:00 2001 From: Dima Date: Wed, 27 Nov 2024 12:53:08 +0300 Subject: [PATCH 048/112] fix merge --- .../configuration/JobConfiguration.groovy | 4 --- .../jenkins/library/steps/SonarScanner.groovy | 29 ------------------- .../jenkins/library/steps/Yaxunit.groovy | 3 +- 3 files changed, 1 insertion(+), 35 deletions(-) diff --git a/src/ru/pulsar/jenkins/library/configuration/JobConfiguration.groovy b/src/ru/pulsar/jenkins/library/configuration/JobConfiguration.groovy index 8e4468e8..accba947 100644 --- a/src/ru/pulsar/jenkins/library/configuration/JobConfiguration.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/JobConfiguration.groovy @@ -60,10 +60,6 @@ class JobConfiguration implements Serializable { @JsonPropertyDescription("Настройки замеров покрытия") CoverageOptions coverageOptions; - @JsonProperty("coverage") - @JsonPropertyDescription("Настройки замеров покрытия") - CoverageOptions coverageOptions; - @JsonProperty("yaxunit") @JsonPropertyDescription("Настройки YAXUnit") YaxunitOptions yaxunitOptions diff --git a/src/ru/pulsar/jenkins/library/steps/SonarScanner.groovy b/src/ru/pulsar/jenkins/library/steps/SonarScanner.groovy index 56c56c96..8dcf1589 100644 --- a/src/ru/pulsar/jenkins/library/steps/SonarScanner.groovy +++ b/src/ru/pulsar/jenkins/library/steps/SonarScanner.groovy @@ -98,35 +98,6 @@ class SonarScanner implements Serializable { } - def stageFlags = config.stageFlags - - if (stageFlags.bdd && config.bddOptions.coverage - || stageFlags.smoke && config.smokeTestOptions.coverage - || stageFlags.yaxunit && config.yaxunitOptions.coverage) { - - 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() - - 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/Yaxunit.groovy b/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy index 4a50a5f3..35fb9cfc 100644 --- a/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy @@ -121,7 +121,7 @@ class Yaxunit implements Serializable { } if (options.publishToAllureReport) { - String allureReport = "./build/out/allure/yaxunit/junit.xml" + String allureReport = "./build/out/yaxunit/junit.xml" FilePath pathToAllureReport = FileUtils.getFilePath("$env.WORKSPACE/$allureReport") String allureReportDir = FileUtils.getLocalPath(pathToAllureReport.getParent()) @@ -134,5 +134,4 @@ class Yaxunit implements Serializable { steps.stash(COVERAGE_STASH_NAME, COVERAGE_STASH_PATH, true) } } - } From 4b0bb1f086b20036113f41e34c6200a870207f76 Mon Sep 17 00:00:00 2001 From: Dima Date: Wed, 27 Nov 2024 13:09:59 +0300 Subject: [PATCH 049/112] fixes --- .gitattributes | 1 + src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitattributes b/.gitattributes index 6d0bb27e..e69dd181 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1,2 @@ *.groovy eol=lf +*.md eol=lf \ No newline at end of file diff --git a/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy b/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy index 35fb9cfc..caf1e18c 100644 --- a/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy @@ -121,7 +121,7 @@ class Yaxunit implements Serializable { } if (options.publishToAllureReport) { - String allureReport = "./build/out/yaxunit/junit.xml" + String allureReport = "./build/out/allure/yaxunit/junit.xml" FilePath pathToAllureReport = FileUtils.getFilePath("$env.WORKSPACE/$allureReport") String allureReportDir = FileUtils.getLocalPath(pathToAllureReport.getParent()) From ab88f8f9ce0714669d764f4f551fcbed7b4670b9 Mon Sep 17 00:00:00 2001 From: Dima Date: Wed, 27 Nov 2024 13:49:26 +0300 Subject: [PATCH 050/112] add archive artifacts, logging, fix path to config --- src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy b/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy index caf1e18c..7a55688b 100644 --- a/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy @@ -53,10 +53,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" @@ -130,6 +131,8 @@ class Yaxunit implements Serializable { steps.stash(YAXUNIT_ALLURE_STASH, "$allureReportDir/**", true) } + steps.archiveArtifacts("build/out/yaxunit/log.txt") + if (options.coverage) { steps.stash(COVERAGE_STASH_NAME, COVERAGE_STASH_PATH, true) } From d53ae8d6203c9b90c4adab00079f0229b0b08166 Mon Sep 17 00:00:00 2001 From: Dima Date: Wed, 27 Nov 2024 14:22:33 +0300 Subject: [PATCH 051/112] fix path --- src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy b/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy index 7a55688b..70f2477f 100644 --- a/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy @@ -131,7 +131,7 @@ class Yaxunit implements Serializable { steps.stash(YAXUNIT_ALLURE_STASH, "$allureReportDir/**", true) } - steps.archiveArtifacts("build/out/yaxunit/log.txt") + steps.archiveArtifacts("build/out/yaxunit/junit.xml") if (options.coverage) { steps.stash(COVERAGE_STASH_NAME, COVERAGE_STASH_PATH, true) From 719dac8df33f964c1108353463d3f17391d3d63d Mon Sep 17 00:00:00 2001 From: Dima Date: Wed, 27 Nov 2024 17:25:58 +0300 Subject: [PATCH 052/112] default info logging to console for yaxunit --- resources/yaxunit.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 From 3b87b093b67b3bcd830feb2f7680fb170bb51bb3 Mon Sep 17 00:00:00 2001 From: Dima Date: Wed, 27 Nov 2024 17:26:14 +0300 Subject: [PATCH 053/112] fix lf --- .gitattributes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitattributes b/.gitattributes index e69dd181..c23f200f 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,2 @@ -*.groovy eol=lf +*.groovy eol=lf *.md eol=lf \ No newline at end of file From 8c6d6559fc534ef79cfc8fc43ec96a7780c36d10 Mon Sep 17 00:00:00 2001 From: Dima Date: Wed, 27 Nov 2024 17:26:32 +0300 Subject: [PATCH 054/112] refactoring --- .../jenkins/library/steps/SonarScanner.groovy | 34 ++++++++----------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/src/ru/pulsar/jenkins/library/steps/SonarScanner.groovy b/src/ru/pulsar/jenkins/library/steps/SonarScanner.groovy index 8dcf1589..4c0494a7 100644 --- a/src/ru/pulsar/jenkins/library/steps/SonarScanner.groovy +++ b/src/ru/pulsar/jenkins/library/steps/SonarScanner.groovy @@ -71,31 +71,27 @@ class SonarScanner implements Serializable { def stageFlags = config.stageFlags - if (stageFlags.bdd && config.bddOptions.coverage - || stageFlags.smoke && config.smokeTestOptions.coverage - || stageFlags.yaxunit && config.yaxunitOptions.coverage) { + StringJoiner coveragePathsConstructor = new StringJoiner(",") - StringJoiner coveragePathsConstructor = new StringJoiner(",") - - if (stageFlags.bdd && config.bddOptions.coverage) { - steps.unstash(Bdd.COVERAGE_STASH_NAME) - coveragePathsConstructor.add(Bdd.COVERAGE_STASH_PATH) - } + 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.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) - } + if (stageFlags.yaxunit && config.yaxunitOptions.coverage) { + steps.unstash(Yaxunit.COVERAGE_STASH_NAME) + coveragePathsConstructor.add(Yaxunit.COVERAGE_STASH_PATH) + } - String coveragePaths = coveragePathsConstructor.toString() + String coveragePaths = coveragePathsConstructor.toString() + if (!coveragePaths.isEmpty()) { sonarCommand += " -Dsonar.coverageReportPaths=${coveragePaths}" - } if (config.sonarQubeOptions.waitForQualityGate) { From a9eee5a9e380b674f8a0ae44fc4b5bfec9592dc9 Mon Sep 17 00:00:00 2001 From: Dima Date: Wed, 27 Nov 2024 17:27:13 +0300 Subject: [PATCH 055/112] add coverage cleanup in bdd, smoke --- .../pulsar/jenkins/library/steps/Bdd.groovy | 44 +++++++++++++------ .../library/steps/CoverageCleanup.groovy | 5 +-- .../jenkins/library/steps/SmokeTest.groovy | 18 ++++++++ .../jenkins/library/steps/Yaxunit.groovy | 2 +- vars/pipeline1C.groovy | 10 +++++ 5 files changed, 61 insertions(+), 18 deletions(-) diff --git a/src/ru/pulsar/jenkins/library/steps/Bdd.groovy b/src/ru/pulsar/jenkins/library/steps/Bdd.groovy index c365a75d..e19cc4dd 100644 --- a/src/ru/pulsar/jenkins/library/steps/Bdd.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Bdd.groovy @@ -3,6 +3,7 @@ package ru.pulsar.jenkins.library.steps import ru.pulsar.jenkins.library.IStepExecutor import ru.pulsar.jenkins.library.configuration.JobConfiguration import ru.pulsar.jenkins.library.ioc.ContextRegistry +import ru.pulsar.jenkins.library.utils.CoverageUtils import ru.pulsar.jenkins.library.utils.FileUtils import ru.pulsar.jenkins.library.utils.Logger import org.apache.commons.lang.RandomStringUtils @@ -15,6 +16,7 @@ class Bdd implements Serializable { 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 @@ -43,6 +45,8 @@ class Bdd implements Serializable { def coverageOpts = config.coverageOptions def port = options.dbgsPort + def currentDbgsPids = CoverageUtils.getPIDs("dbgs") + def currentCoverage41CPids = CoverageUtils.getPIDs("Coverage41C") def lockableResource = RandomStringUtils.random(9, true, false) if (options.coverage) { @@ -54,22 +58,36 @@ class Bdd implements Serializable { steps.start("${coverageOpts.dbgsPath} --addr=127.0.0.1 --port=$port") steps.start("${coverageOpts.coverage41CPath} start -i DefAlias -u http://127.0.0.1:$port -P $workspaceDir -s $srcDir -o $COVERAGE_STASH_PATH") steps.cmd("${coverageOpts.coverage41CPath} check -i DefAlias -u http://127.0.0.1:$port") + + def newDbgsPids = CoverageUtils.getPIDs("dbgs") + def newCoverage41CPids = CoverageUtils.getPIDs("Coverage41C") + + newDbgsPids.removeAll(currentDbgsPids) + newCoverage41CPids.removeAll(currentCoverage41CPids) + + newDbgsPids.addAll(newCoverage41CPids) + def pids = newDbgsPids.join(" ") + + steps.writeFile(COVERAGE_PIDS_PATH, pids, 'UTF-8') + + Logger.println("Coverage PIDs for cleanup: $pids") + } - 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) - } + 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("Тестирование сценариев завершилось успешно") - } + if (Collections.max(returnStatuses) > 2) { + steps.error("Получен неожиданный/неверный результат работы. Возможно, работа 1С:Предприятие завершилась некорректно, или возникла ошибка при запуске") + } else if (returnStatuses.contains(1)) { + steps.unstable("Тестирование сценариев завершилось, но часть фич/сценариев упала") + } else { + Logger.println("Тестирование сценариев завершилось успешно") + } if (options.coverage) { steps.cmd("${coverageOpts.coverage41CPath} stop -i DefAlias -u http://127.0.0.1:$port") diff --git a/src/ru/pulsar/jenkins/library/steps/CoverageCleanup.groovy b/src/ru/pulsar/jenkins/library/steps/CoverageCleanup.groovy index 4a66f576..ff73203a 100644 --- a/src/ru/pulsar/jenkins/library/steps/CoverageCleanup.groovy +++ b/src/ru/pulsar/jenkins/library/steps/CoverageCleanup.groovy @@ -22,10 +22,7 @@ class CoverageCleanup implements Serializable { Logger.printLocation() - String pidsFilePath = "" - if (stageName == 'yaxunit') { - pidsFilePath = Yaxunit.COVERAGE_PIDS_PATH - } + String pidsFilePath = "build/$stageName-pids" def pids = "" if (steps.fileExists(pidsFilePath)) { diff --git a/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy b/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy index 24571f2a..55ac5e5a 100644 --- a/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy +++ b/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy @@ -5,6 +5,7 @@ import org.apache.commons.lang.RandomStringUtils 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.CoverageUtils import ru.pulsar.jenkins.library.utils.FileUtils import ru.pulsar.jenkins.library.utils.Logger import ru.pulsar.jenkins.library.utils.StringJoiner @@ -15,6 +16,7 @@ class SmokeTest implements Serializable { 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 @@ -108,6 +110,8 @@ class SmokeTest implements Serializable { def coverageOpts = config.coverageOptions def port = options.dbgsPort + def currentDbgsPids = CoverageUtils.getPIDs("dbgs") + def currentCoverage41CPids = CoverageUtils.getPIDs("Coverage41C") def lockableResource = RandomStringUtils.random(9, true, false) if (options.coverage) { lockableResource = "${env.NODE_NAME}_$port" @@ -118,6 +122,20 @@ class SmokeTest implements Serializable { steps.start("${coverageOpts.dbgsPath} --addr=127.0.0.1 --port=$port") steps.start("${coverageOpts.coverage41CPath} start -i DefAlias -u http://127.0.0.1:$port -P $workspaceDir -s $srcDir -o $COVERAGE_STASH_PATH") steps.cmd("${coverageOpts.coverage41CPath} check -i DefAlias -u http://127.0.0.1:$port") + + def newDbgsPids = CoverageUtils.getPIDs("dbgs") + def newCoverage41CPids = CoverageUtils.getPIDs("Coverage41C") + + newDbgsPids.removeAll(currentDbgsPids) + newCoverage41CPids.removeAll(currentCoverage41CPids) + + newDbgsPids.addAll(newCoverage41CPids) + def pids = newDbgsPids.join(" ") + + steps.writeFile(COVERAGE_PIDS_PATH, pids, 'UTF-8') + + Logger.println("Coverage PIDs for cleanup: $pids") + } steps.withEnv(logosConfig) { diff --git a/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy b/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy index 70f2477f..ffffe60c 100644 --- a/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy @@ -73,9 +73,9 @@ class Yaxunit implements Serializable { def coverageOpts = config.coverageOptions def port = options.dbgsPort - def lockableResource = RandomStringUtils.random(9, true, false) def currentDbgsPids = CoverageUtils.getPIDs("dbgs") def currentCoverage41CPids = CoverageUtils.getPIDs("Coverage41C") + def lockableResource = RandomStringUtils.random(9, true, false) if (options.coverage) { lockableResource = "${env.NODE_NAME}_$port" } diff --git a/vars/pipeline1C.groovy b/vars/pipeline1C.groovy index 627bedf2..fd2e5e21 100644 --- a/vars/pipeline1C.groovy +++ b/vars/pipeline1C.groovy @@ -236,6 +236,11 @@ void call() { bdd config } } + post { + cleanup { + coverageCleanup config, 'bdd' + } + } } } } @@ -288,6 +293,11 @@ void call() { smoke config } } + post { + cleanup { + coverageCleanup config, 'smoke' + } + } } } } From fd5fcae72ca8e18c5d2e4a3569d216bf242231d5 Mon Sep 17 00:00:00 2001 From: Dima Date: Thu, 28 Nov 2024 11:25:35 +0300 Subject: [PATCH 056/112] upd rm --- README.md | 498 +++++++++++++++++++++++++++--------------------------- 1 file changed, 249 insertions(+), 249 deletions(-) diff --git a/README.md b/README.md index c5cff354..237085f6 100644 --- a/README.md +++ b/README.md @@ -1,249 +1,249 @@ -# 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. Для замеров покрытия на агентах должны быть установлены [Coverage41C](https://github.com/1c-syntax/Coverage41C), EDT и сервер отладки dbgs. Вместо установки EDT целиком можно использовать только отдельные ее компоненты, см. [Coverage41C/README.md](https://github.com/1c-syntax/Coverage41C). -1. Для параллельного выполнения шагов `bdd` и `smoke` с включенными замерами покрытия на одной ноде необходимо, чтобы в `jobConfiguration.json` были указаны **разные** порты сервера отладки для каждого шага. Параллельные билды с замерами покрытия на одной ноде не поддерживаются. - -## Возможности - -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. +# 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. Для замеров покрытия на агентах должны быть установлены [Coverage41C](https://github.com/1c-syntax/Coverage41C), EDT и сервер отладки dbgs. Вместо установки EDT целиком можно использовать только отдельные ее компоненты, см. [Coverage41C/README.md](https://github.com/1c-syntax/Coverage41C). +1. Для параллельного выполнения шагов `bdd` и `smoke` с включенными замерами покрытия на одной ноде необходимо, чтобы в `jobConfiguration.json` были указаны **разные** порты сервера отладки для каждого шага. Параллельные билды с замерами покрытия на одной ноде не поддерживаются. + +## Возможности + +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. From d16b6ac1c13609fcf28d6ff1607a625f59b75709 Mon Sep 17 00:00:00 2001 From: Dima Date: Thu, 28 Nov 2024 11:36:46 +0300 Subject: [PATCH 057/112] revert --- .gitattributes | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitattributes b/.gitattributes index c23f200f..8055835c 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1 @@ *.groovy eol=lf -*.md eol=lf \ No newline at end of file From 6353e93998bd69187f486e7857c6379daa28a492 Mon Sep 17 00:00:00 2001 From: Dima Date: Thu, 28 Nov 2024 11:48:06 +0300 Subject: [PATCH 058/112] bump --- src/ru/pulsar/jenkins/library/steps/Bdd.groovy | 2 +- src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy | 2 +- src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ru/pulsar/jenkins/library/steps/Bdd.groovy b/src/ru/pulsar/jenkins/library/steps/Bdd.groovy index e19cc4dd..68241e3c 100644 --- a/src/ru/pulsar/jenkins/library/steps/Bdd.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Bdd.groovy @@ -6,7 +6,7 @@ import ru.pulsar.jenkins.library.ioc.ContextRegistry import ru.pulsar.jenkins.library.utils.CoverageUtils import ru.pulsar.jenkins.library.utils.FileUtils import ru.pulsar.jenkins.library.utils.Logger -import org.apache.commons.lang.RandomStringUtils +import org.apache.commons.lang3.RandomStringUtils import ru.pulsar.jenkins.library.utils.VRunner class Bdd implements Serializable { diff --git a/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy b/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy index 55ac5e5a..9578e434 100644 --- a/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy +++ b/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy @@ -1,7 +1,7 @@ package ru.pulsar.jenkins.library.steps import hudson.FilePath -import org.apache.commons.lang.RandomStringUtils +import org.apache.commons.lang3.RandomStringUtils import ru.pulsar.jenkins.library.IStepExecutor import ru.pulsar.jenkins.library.configuration.JobConfiguration import ru.pulsar.jenkins.library.ioc.ContextRegistry diff --git a/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy b/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy index ffffe60c..83fc8f60 100644 --- a/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy @@ -1,7 +1,7 @@ package ru.pulsar.jenkins.library.steps import hudson.FilePath -import org.apache.commons.lang.RandomStringUtils +import org.apache.commons.lang3.RandomStringUtils import ru.pulsar.jenkins.library.IStepExecutor import ru.pulsar.jenkins.library.configuration.JobConfiguration From bcd8f2821ff8538fe11f750ee741ee9331a10520 Mon Sep 17 00:00:00 2001 From: Dima Date: Fri, 29 Nov 2024 13:55:27 +0300 Subject: [PATCH 059/112] add md eol --- .gitattributes | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitattributes b/.gitattributes index 8055835c..71b9a47f 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1,2 @@ *.groovy eol=lf +*.md eol=lf From 049951030e0806c07c63dfd07329df7aeebad036 Mon Sep 17 00:00:00 2001 From: Dima Date: Fri, 29 Nov 2024 13:56:20 +0300 Subject: [PATCH 060/112] simplify optional unstash --- vars/unzipInfobase.groovy | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/vars/unzipInfobase.groovy b/vars/unzipInfobase.groovy index 342e1be8..eb60d8ab 100644 --- a/vars/unzipInfobase.groovy +++ b/vars/unzipInfobase.groovy @@ -3,9 +3,8 @@ import ru.pulsar.jenkins.library.steps.GetExtensions def call() { unstash '1Cv8.1CD.zip' unzip dir: 'build/ib', zipFile: '1Cv8.1CD.zip' - try { + catchError { + // extensions are optional unstash GetExtensions.EXTENSIONS_STASH - } catch (Exception e) { - echo e.toString() } } \ No newline at end of file From a7b557e76a574a5e073191a00482659ccff7f0f8 Mon Sep 17 00:00:00 2001 From: Dima Date: Fri, 29 Nov 2024 13:56:39 +0300 Subject: [PATCH 061/112] simplify lock step --- src/ru/pulsar/jenkins/library/IStepExecutor.groovy | 2 +- src/ru/pulsar/jenkins/library/StepExecutor.groovy | 4 ++-- src/ru/pulsar/jenkins/library/steps/Bdd.groovy | 2 +- src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy | 2 +- src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/ru/pulsar/jenkins/library/IStepExecutor.groovy b/src/ru/pulsar/jenkins/library/IStepExecutor.groovy index 18264408..0619e0c5 100644 --- a/src/ru/pulsar/jenkins/library/IStepExecutor.groovy +++ b/src/ru/pulsar/jenkins/library/IStepExecutor.groovy @@ -66,7 +66,7 @@ interface IStepExecutor { def withEnv(List strings, Closure body) - def lock(String label, int quantity, String resource, Closure body) + def lock(String resource, Closure body) def archiveArtifacts(String path) diff --git a/src/ru/pulsar/jenkins/library/StepExecutor.groovy b/src/ru/pulsar/jenkins/library/StepExecutor.groovy index d337aab6..6a22d7fe 100644 --- a/src/ru/pulsar/jenkins/library/StepExecutor.groovy +++ b/src/ru/pulsar/jenkins/library/StepExecutor.groovy @@ -150,8 +150,8 @@ class StepExecutor implements IStepExecutor { } @Override - def lock(String label, int quantity, String resource, Closure body) { - steps.lock(label: label, quantity: quantity, resource: resource) { + def lock(String resource, Closure body) { + steps.lock(resource: resource) { body() } } diff --git a/src/ru/pulsar/jenkins/library/steps/Bdd.groovy b/src/ru/pulsar/jenkins/library/steps/Bdd.groovy index 68241e3c..68200476 100644 --- a/src/ru/pulsar/jenkins/library/steps/Bdd.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Bdd.groovy @@ -53,7 +53,7 @@ class Bdd implements Serializable { lockableResource = "${env.NODE_NAME}_$port" } - steps.lock(null, 1, lockableResource) { + steps.lock(lockableResource) { if (options.coverage) { steps.start("${coverageOpts.dbgsPath} --addr=127.0.0.1 --port=$port") steps.start("${coverageOpts.coverage41CPath} start -i DefAlias -u http://127.0.0.1:$port -P $workspaceDir -s $srcDir -o $COVERAGE_STASH_PATH") diff --git a/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy b/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy index 9578e434..74e220e3 100644 --- a/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy +++ b/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy @@ -117,7 +117,7 @@ class SmokeTest implements Serializable { lockableResource = "${env.NODE_NAME}_$port" } - steps.lock(null, 1, lockableResource) { + steps.lock(lockableResource) { if (options.coverage) { steps.start("${coverageOpts.dbgsPath} --addr=127.0.0.1 --port=$port") steps.start("${coverageOpts.coverage41CPath} start -i DefAlias -u http://127.0.0.1:$port -P $workspaceDir -s $srcDir -o $COVERAGE_STASH_PATH") diff --git a/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy b/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy index 83fc8f60..d704731c 100644 --- a/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy @@ -80,7 +80,7 @@ class Yaxunit implements Serializable { lockableResource = "${env.NODE_NAME}_$port" } - steps.lock(null, 1, lockableResource) { + steps.lock(lockableResource) { if (options.coverage) { steps.start("${coverageOpts.dbgsPath} --addr=127.0.0.1 --port=$port") steps.start("${coverageOpts.coverage41CPath} start -i DefAlias -u http://127.0.0.1:$port -P $workspaceDir -s $srcDir -o $COVERAGE_STASH_PATH") From e8e3db5a594b3b8e0b4d04d3c60249b8db982fdd Mon Sep 17 00:00:00 2001 From: Dima Date: Fri, 29 Nov 2024 19:09:51 +0300 Subject: [PATCH 062/112] refactoring --- README.md | 1 + .../library/configuration/BddOptions.groovy | 2 +- ...ns.groovy => GlobalCoverageOptions.groovy} | 2 +- .../configuration/JobConfiguration.groovy | 2 +- .../configuration/SmokeTestOptions.groovy | 2 +- .../configuration/StepCoverageOptions.groovy | 13 +++++ .../configuration/YaxunitOptions.groovy | 2 +- .../pulsar/jenkins/library/steps/Bdd.groovy | 46 ++++++----------- .../jenkins/library/steps/Coverable.groovy | 8 +++ .../library/steps/CoverageContext.groovy | 23 +++++++++ .../library/steps/GetExtensions.groovy | 8 +-- .../jenkins/library/steps/SmokeTest.groovy | 45 ++++++----------- .../jenkins/library/steps/Yaxunit.groovy | 48 +++++++----------- .../library/utils/CoverageUtils.groovy | 49 +++++++++++++++++++ 14 files changed, 150 insertions(+), 101 deletions(-) rename src/ru/pulsar/jenkins/library/configuration/{CoverageOptions.groovy => GlobalCoverageOptions.groovy} (93%) create mode 100644 src/ru/pulsar/jenkins/library/configuration/StepCoverageOptions.groovy create mode 100644 src/ru/pulsar/jenkins/library/steps/Coverable.groovy create mode 100644 src/ru/pulsar/jenkins/library/steps/CoverageContext.groovy diff --git a/README.md b/README.md index 237085f6..e4b0225d 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,7 @@ 1. Для запуска шагов, работающих с 1С (подготовка, синтаксический контроль и т.д.) требуется агент с меткой, совпадающей со значением в поле `v8version` файла конфигурации. 1. В качестве ИБ используется файловая база, создаваемая в каталоге `./build/ib`. При необходимости вы можете создать пользователей на фазе инициализации ИБ. 1. Для замеров покрытия на агентах должны быть установлены [Coverage41C](https://github.com/1c-syntax/Coverage41C), EDT и сервер отладки dbgs. Вместо установки EDT целиком можно использовать только отдельные ее компоненты, см. [Coverage41C/README.md](https://github.com/1c-syntax/Coverage41C). +1. На данный момент ошибка в [vanessa-add](https://github.com/vanessa-opensource/add/issues/1152) не позволяет собирать замеры производительности в дымовых тестах по открытию всех форм на клиенте тестирования. 1. Для параллельного выполнения шагов `bdd` и `smoke` с включенными замерами покрытия на одной ноде необходимо, чтобы в `jobConfiguration.json` были указаны **разные** порты сервера отладки для каждого шага. Параллельные билды с замерами покрытия на одной ноде не поддерживаются. ## Возможности diff --git a/src/ru/pulsar/jenkins/library/configuration/BddOptions.groovy b/src/ru/pulsar/jenkins/library/configuration/BddOptions.groovy index 47f0547b..88d10f61 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. В каждой строке передается отдельная команда diff --git a/src/ru/pulsar/jenkins/library/configuration/CoverageOptions.groovy b/src/ru/pulsar/jenkins/library/configuration/GlobalCoverageOptions.groovy similarity index 93% rename from src/ru/pulsar/jenkins/library/configuration/CoverageOptions.groovy rename to src/ru/pulsar/jenkins/library/configuration/GlobalCoverageOptions.groovy index 665f3dca..9a4fcda7 100644 --- a/src/ru/pulsar/jenkins/library/configuration/CoverageOptions.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/GlobalCoverageOptions.groovy @@ -5,7 +5,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties import com.fasterxml.jackson.annotation.JsonPropertyDescription @JsonIgnoreProperties(ignoreUnknown = true) -class CoverageOptions implements Serializable { +class GlobalCoverageOptions implements Serializable { @JsonPropertyDescription('''Путь к исполняемому файлу dbgs. По умолчанию равен /opt/1cv8/current/dbgs. diff --git a/src/ru/pulsar/jenkins/library/configuration/JobConfiguration.groovy b/src/ru/pulsar/jenkins/library/configuration/JobConfiguration.groovy index accba947..cfedcede 100644 --- a/src/ru/pulsar/jenkins/library/configuration/JobConfiguration.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/JobConfiguration.groovy @@ -58,7 +58,7 @@ class JobConfiguration implements Serializable { @JsonProperty("coverage") @JsonPropertyDescription("Настройки замеров покрытия") - CoverageOptions coverageOptions; + GlobalCoverageOptions coverageOptions @JsonProperty("yaxunit") @JsonPropertyDescription("Настройки YAXUnit") diff --git a/src/ru/pulsar/jenkins/library/configuration/SmokeTestOptions.groovy b/src/ru/pulsar/jenkins/library/configuration/SmokeTestOptions.groovy index 562678c3..58514e7f 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". 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..fbffe09c --- /dev/null +++ b/src/ru/pulsar/jenkins/library/configuration/StepCoverageOptions.groovy @@ -0,0 +1,13 @@ +package ru.pulsar.jenkins.library.configuration + +import com.fasterxml.jackson.annotation.JsonPropertyDescription + +class StepCoverageOptions { + + @JsonPropertyDescription("Выполнять замер покрытия") + Boolean coverage = false + + @JsonPropertyDescription("Порт, на котором будет запущен сервер отладки для замера покрытия") + int dbgsPort = 1550 + +} diff --git a/src/ru/pulsar/jenkins/library/configuration/YaxunitOptions.groovy b/src/ru/pulsar/jenkins/library/configuration/YaxunitOptions.groovy index c45ae2cc..86d8e183 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". diff --git a/src/ru/pulsar/jenkins/library/steps/Bdd.groovy b/src/ru/pulsar/jenkins/library/steps/Bdd.groovy index 68200476..165c2bf0 100644 --- a/src/ru/pulsar/jenkins/library/steps/Bdd.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Bdd.groovy @@ -6,10 +6,9 @@ import ru.pulsar.jenkins.library.ioc.ContextRegistry import ru.pulsar.jenkins.library.utils.CoverageUtils import ru.pulsar.jenkins.library.utils.FileUtils import ru.pulsar.jenkins.library.utils.Logger -import org.apache.commons.lang3.RandomStringUtils import ru.pulsar.jenkins.library.utils.VRunner -class Bdd implements Serializable { +class Bdd implements Serializable, Coverable { private final JobConfiguration config @@ -44,34 +43,11 @@ class Bdd implements Serializable { List returnStatuses = [] def coverageOpts = config.coverageOptions - def port = options.dbgsPort - def currentDbgsPids = CoverageUtils.getPIDs("dbgs") - def currentCoverage41CPids = CoverageUtils.getPIDs("Coverage41C") - def lockableResource = RandomStringUtils.random(9, true, false) - - if (options.coverage) { - lockableResource = "${env.NODE_NAME}_$port" - } - - steps.lock(lockableResource) { - if (options.coverage) { - steps.start("${coverageOpts.dbgsPath} --addr=127.0.0.1 --port=$port") - steps.start("${coverageOpts.coverage41CPath} start -i DefAlias -u http://127.0.0.1:$port -P $workspaceDir -s $srcDir -o $COVERAGE_STASH_PATH") - steps.cmd("${coverageOpts.coverage41CPath} check -i DefAlias -u http://127.0.0.1:$port") - - def newDbgsPids = CoverageUtils.getPIDs("dbgs") - def newCoverage41CPids = CoverageUtils.getPIDs("Coverage41C") - - newDbgsPids.removeAll(currentDbgsPids) - newCoverage41CPids.removeAll(currentCoverage41CPids) - - newDbgsPids.addAll(newCoverage41CPids) - def pids = newDbgsPids.join(" ") - - steps.writeFile(COVERAGE_PIDS_PATH, pids, 'UTF-8') - - Logger.println("Coverage PIDs for cleanup: $pids") + def coverageContext = CoverageUtils.prepareContext(config, options) + steps.lock(coverageContext.lockableResource) { + if (coverageContext != null) { + CoverageUtils.startCoverage(steps, coverageOpts, coverageContext, workspaceDir, srcDir, this) } config.bddOptions.vrunnerSteps.each { @@ -89,8 +65,8 @@ class Bdd implements Serializable { Logger.println("Тестирование сценариев завершилось успешно") } - if (options.coverage) { - steps.cmd("${coverageOpts.coverage41CPath} stop -i DefAlias -u http://127.0.0.1:$port") + if (coverageContext != null) { + CoverageUtils.stopCoverage(steps, coverageOpts, coverageContext) } } } @@ -102,4 +78,12 @@ class Bdd implements Serializable { } } + + String getCoverageStashPath() { + return COVERAGE_STASH_PATH + } + + 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..54271bb8 --- /dev/null +++ b/src/ru/pulsar/jenkins/library/steps/Coverable.groovy @@ -0,0 +1,8 @@ +package ru.pulsar.jenkins.library.steps + +interface Coverable { + + String getCoverageStashPath(); + 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..36d47286 --- /dev/null +++ b/src/ru/pulsar/jenkins/library/steps/CoverageContext.groovy @@ -0,0 +1,23 @@ +package ru.pulsar.jenkins.library.steps + +import ru.pulsar.jenkins.library.configuration.GlobalCoverageOptions + +class CoverageContext { + + String lockableResource + GlobalCoverageOptions coverageOptions + int port + ArrayList pids + ArrayList dbgsPids + ArrayList coverage41CPids + + CoverageContext(String lockableResource, GlobalCoverageOptions coverageOptions, int port, ArrayList dbgsPids, ArrayList coverage41CPids) { + this.lockableResource = lockableResource + 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/SmokeTest.groovy b/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy index 74e220e3..aeab4e5d 100644 --- a/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy +++ b/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy @@ -1,7 +1,6 @@ package ru.pulsar.jenkins.library.steps import hudson.FilePath -import org.apache.commons.lang3.RandomStringUtils import ru.pulsar.jenkins.library.IStepExecutor import ru.pulsar.jenkins.library.configuration.JobConfiguration import ru.pulsar.jenkins.library.ioc.ContextRegistry @@ -11,7 +10,7 @@ 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 ALLURE_STASH = 'smoke-allure' public static final String COVERAGE_STASH_NAME = 'smoke-coverage' @@ -109,41 +108,19 @@ class SmokeTest implements Serializable { } def coverageOpts = config.coverageOptions - def port = options.dbgsPort - def currentDbgsPids = CoverageUtils.getPIDs("dbgs") - def currentCoverage41CPids = CoverageUtils.getPIDs("Coverage41C") - def lockableResource = RandomStringUtils.random(9, true, false) - if (options.coverage) { - lockableResource = "${env.NODE_NAME}_$port" - } - - steps.lock(lockableResource) { - if (options.coverage) { - steps.start("${coverageOpts.dbgsPath} --addr=127.0.0.1 --port=$port") - steps.start("${coverageOpts.coverage41CPath} start -i DefAlias -u http://127.0.0.1:$port -P $workspaceDir -s $srcDir -o $COVERAGE_STASH_PATH") - steps.cmd("${coverageOpts.coverage41CPath} check -i DefAlias -u http://127.0.0.1:$port") - - def newDbgsPids = CoverageUtils.getPIDs("dbgs") - def newCoverage41CPids = CoverageUtils.getPIDs("Coverage41C") - - newDbgsPids.removeAll(currentDbgsPids) - newCoverage41CPids.removeAll(currentCoverage41CPids) - - newDbgsPids.addAll(newCoverage41CPids) - def pids = newDbgsPids.join(" ") - - steps.writeFile(COVERAGE_PIDS_PATH, pids, 'UTF-8') - - Logger.println("Coverage PIDs for cleanup: $pids") + def coverageContext = CoverageUtils.prepareContext(config, options) + steps.lock(coverageContext.lockableResource) { + if (coverageContext != null) { + CoverageUtils.startCoverage(steps, coverageOpts, coverageContext, workspaceDir, srcDir, this) } steps.withEnv(logosConfig) { VRunner.exec(command, true) } - if (options.coverage) { - steps.cmd("${coverageOpts.coverage41CPath} stop -i DefAlias -u http://127.0.0.1:$port") + if (coverageContext != null) { + CoverageUtils.stopCoverage(steps, coverageOpts, coverageContext) } } @@ -162,4 +139,12 @@ class SmokeTest implements Serializable { } } + + String getCoverageStashPath() { + return COVERAGE_STASH_PATH + } + + String getCoveragePidsPath() { + return COVERAGE_PIDS_PATH + } } diff --git a/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy b/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy index d704731c..624fe20c 100644 --- a/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy @@ -1,9 +1,7 @@ package ru.pulsar.jenkins.library.steps import hudson.FilePath -import org.apache.commons.lang3.RandomStringUtils 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.CoverageUtils @@ -11,7 +9,7 @@ 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 @@ -72,33 +70,11 @@ class Yaxunit implements Serializable { } def coverageOpts = config.coverageOptions - def port = options.dbgsPort - def currentDbgsPids = CoverageUtils.getPIDs("dbgs") - def currentCoverage41CPids = CoverageUtils.getPIDs("Coverage41C") - def lockableResource = RandomStringUtils.random(9, true, false) - if (options.coverage) { - lockableResource = "${env.NODE_NAME}_$port" - } - - steps.lock(lockableResource) { - if (options.coverage) { - steps.start("${coverageOpts.dbgsPath} --addr=127.0.0.1 --port=$port") - steps.start("${coverageOpts.coverage41CPath} start -i DefAlias -u http://127.0.0.1:$port -P $workspaceDir -s $srcDir -o $COVERAGE_STASH_PATH") - steps.cmd("${coverageOpts.coverage41CPath} check -i DefAlias -u http://127.0.0.1:$port") - - def newDbgsPids = CoverageUtils.getPIDs("dbgs") - def newCoverage41CPids = CoverageUtils.getPIDs("Coverage41C") - - newDbgsPids.removeAll(currentDbgsPids) - newCoverage41CPids.removeAll(currentCoverage41CPids) - - newDbgsPids.addAll(newCoverage41CPids) - def pids = newDbgsPids.join(" ") - - steps.writeFile(COVERAGE_PIDS_PATH, pids, 'UTF-8') - - Logger.println("Coverage PIDs for cleanup: $pids") + def coverageContext = CoverageUtils.prepareContext(config, options) + steps.lock(coverageContext.lockableResource) { + if (coverageContext != null) { + CoverageUtils.startCoverage(steps, coverageOpts, coverageContext, workspaceDir, srcDir, this) } // Выполняем команды @@ -106,8 +82,8 @@ class Yaxunit implements Serializable { VRunner.exec(runTestsCommand, true) } - if (options.coverage) { - steps.cmd("${coverageOpts.coverage41CPath} stop -i DefAlias -u http://127.0.0.1:$port") + if (coverageContext != null) { + CoverageUtils.stopCoverage(steps, coverageOpts, coverageContext) } } @@ -137,4 +113,14 @@ class Yaxunit implements Serializable { steps.stash(COVERAGE_STASH_NAME, COVERAGE_STASH_PATH, true) } } + + String getCoverageStashPath() { + return COVERAGE_STASH_PATH + } + + String getCoveragePidsPath() { + return COVERAGE_PIDS_PATH + } + + } diff --git a/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy b/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy index e897ae46..71624cff 100644 --- a/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy +++ b/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy @@ -1,7 +1,14 @@ package ru.pulsar.jenkins.library.utils +import hudson.FilePath +import org.apache.commons.lang3.RandomStringUtils import ru.pulsar.jenkins.library.IStepExecutor +import ru.pulsar.jenkins.library.configuration.GlobalCoverageOptions +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.CoverageContext class CoverageUtils { static ArrayList getPIDs(String name) { @@ -17,4 +24,46 @@ class CoverageUtils { } return pids.split('\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 = RandomStringUtils.random(9, true, false) + if (options.coverage) { + lockableResource = "${env.NODE_NAME}_$port" + } + + return new CoverageContext(lockableResource, coverageOpts, port, currentDbgsPids, currentCoverage41CPids) + + } + + static void startCoverage(IStepExecutor steps, GlobalCoverageOptions coverageOpts, CoverageContext coverageContext, FilePath workspaceDir, String srcDir, Coverable coverable) { + steps.start("${coverageOpts.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 ${coverable.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(coverable.getCoveragePidsPath(), pids, 'UTF-8') + + Logger.println("Coverage PIDs for cleanup: $pids") + } + + static void stopCoverage(IStepExecutor steps, GlobalCoverageOptions coverageOpts, CoverageContext coverageContext) { + steps.cmd("${coverageOpts.coverage41CPath} stop -i DefAlias -u http://127.0.0.1:$coverageContext.port") + } + } From 77130fb70d43bf29fcafa86c35594e484d65a864 Mon Sep 17 00:00:00 2001 From: Dima Date: Sat, 30 Nov 2024 12:53:10 +0300 Subject: [PATCH 063/112] revert catchError --- vars/unzipInfobase.groovy | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/vars/unzipInfobase.groovy b/vars/unzipInfobase.groovy index eb60d8ab..342e1be8 100644 --- a/vars/unzipInfobase.groovy +++ b/vars/unzipInfobase.groovy @@ -3,8 +3,9 @@ import ru.pulsar.jenkins.library.steps.GetExtensions def call() { unstash '1Cv8.1CD.zip' unzip dir: 'build/ib', zipFile: '1Cv8.1CD.zip' - catchError { - // extensions are optional + try { unstash GetExtensions.EXTENSIONS_STASH + } catch (Exception e) { + echo e.toString() } } \ No newline at end of file From dcf36045765b0f4ec470e73ae65611ed61bc54ef Mon Sep 17 00:00:00 2001 From: Dima Date: Sat, 30 Nov 2024 13:49:31 +0300 Subject: [PATCH 064/112] refactoring --- .../configuration/StepCoverageOptions.groovy | 4 ++-- src/ru/pulsar/jenkins/library/steps/Bdd.groovy | 6 +++--- .../jenkins/library/steps/CoverageCleanup.groovy | 13 ++++++------- .../pulsar/jenkins/library/steps/SmokeTest.groovy | 6 +++--- src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy | 6 +++--- 5 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/ru/pulsar/jenkins/library/configuration/StepCoverageOptions.groovy b/src/ru/pulsar/jenkins/library/configuration/StepCoverageOptions.groovy index fbffe09c..63c0b24f 100644 --- a/src/ru/pulsar/jenkins/library/configuration/StepCoverageOptions.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/StepCoverageOptions.groovy @@ -2,12 +2,12 @@ package ru.pulsar.jenkins.library.configuration import com.fasterxml.jackson.annotation.JsonPropertyDescription -class StepCoverageOptions { +class StepCoverageOptions implements Serializable { @JsonPropertyDescription("Выполнять замер покрытия") Boolean coverage = false @JsonPropertyDescription("Порт, на котором будет запущен сервер отладки для замера покрытия") - int dbgsPort = 1550 + Integer dbgsPort = 1550 } diff --git a/src/ru/pulsar/jenkins/library/steps/Bdd.groovy b/src/ru/pulsar/jenkins/library/steps/Bdd.groovy index 165c2bf0..e7737870 100644 --- a/src/ru/pulsar/jenkins/library/steps/Bdd.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Bdd.groovy @@ -46,8 +46,8 @@ class Bdd implements Serializable, Coverable { def coverageContext = CoverageUtils.prepareContext(config, options) steps.lock(coverageContext.lockableResource) { - if (coverageContext != null) { - CoverageUtils.startCoverage(steps, coverageOpts, coverageContext, workspaceDir, srcDir, this) + if (options.coverage) { + CoverageContext.startCoverage(steps, coverageOpts, coverageContext, workspaceDir, srcDir, this) } config.bddOptions.vrunnerSteps.each { @@ -65,7 +65,7 @@ class Bdd implements Serializable, Coverable { Logger.println("Тестирование сценариев завершилось успешно") } - if (coverageContext != null) { + if (options.coverage) { CoverageUtils.stopCoverage(steps, coverageOpts, coverageContext) } } diff --git a/src/ru/pulsar/jenkins/library/steps/CoverageCleanup.groovy b/src/ru/pulsar/jenkins/library/steps/CoverageCleanup.groovy index ff73203a..7f3ee668 100644 --- a/src/ru/pulsar/jenkins/library/steps/CoverageCleanup.groovy +++ b/src/ru/pulsar/jenkins/library/steps/CoverageCleanup.groovy @@ -22,7 +22,7 @@ class CoverageCleanup implements Serializable { Logger.printLocation() - String pidsFilePath = "build/$stageName-pids" + String pidsFilePath = "build${File.separator}${stageName}-pids" def pids = "" if (steps.fileExists(pidsFilePath)) { @@ -35,16 +35,15 @@ class CoverageCleanup implements Serializable { } Logger.println("Завершение процессов dbgs и Coverage41C с pid: $pids") - + def command if (steps.isUnix()) { - def command = "kill $pids" - steps.sh(command, true, false, encoding) + command = "kill $pids" } else { - def winCommand = pids.split(" ") + def pidsForCmd = pids.split(" ") .each { it -> "/PID $it" } .join(" ") - def command = "taskkill $winCommand /F" - steps.sh(command, true, false, encoding) + command = "taskkill $pidsForCmd /F" } + steps.cmd(command, true, false) } } diff --git a/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy b/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy index aeab4e5d..3bed18ac 100644 --- a/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy +++ b/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy @@ -111,15 +111,15 @@ class SmokeTest implements Serializable, Coverable { def coverageContext = CoverageUtils.prepareContext(config, options) steps.lock(coverageContext.lockableResource) { - if (coverageContext != null) { - CoverageUtils.startCoverage(steps, coverageOpts, coverageContext, workspaceDir, srcDir, this) + if (options.coverage) { + CoverageContext.startCoverage(steps, coverageOpts, coverageContext, workspaceDir, srcDir, this) } steps.withEnv(logosConfig) { VRunner.exec(command, true) } - if (coverageContext != null) { + if (options.coverage) { CoverageUtils.stopCoverage(steps, coverageOpts, coverageContext) } } diff --git a/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy b/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy index 624fe20c..2be4ffb0 100644 --- a/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy @@ -73,8 +73,8 @@ class Yaxunit implements Serializable, Coverable { def coverageContext = CoverageUtils.prepareContext(config, options) steps.lock(coverageContext.lockableResource) { - if (coverageContext != null) { - CoverageUtils.startCoverage(steps, coverageOpts, coverageContext, workspaceDir, srcDir, this) + if (options.coverage) { + CoverageContext.startCoverage(steps, coverageOpts, coverageContext, workspaceDir, srcDir, this) } // Выполняем команды @@ -82,7 +82,7 @@ class Yaxunit implements Serializable, Coverable { VRunner.exec(runTestsCommand, true) } - if (coverageContext != null) { + if (options.coverage) { CoverageUtils.stopCoverage(steps, coverageOpts, coverageContext) } } From a004277b2efee9ac65c4ed1d29af791f0732af71 Mon Sep 17 00:00:00 2001 From: Dima Date: Sun, 1 Dec 2024 13:59:28 +0300 Subject: [PATCH 065/112] int to Integer --- src/ru/pulsar/jenkins/library/configuration/BddOptions.groovy | 2 +- .../jenkins/library/configuration/SmokeTestOptions.groovy | 2 +- .../pulsar/jenkins/library/configuration/YaxunitOptions.groovy | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ru/pulsar/jenkins/library/configuration/BddOptions.groovy b/src/ru/pulsar/jenkins/library/configuration/BddOptions.groovy index 88d10f61..cef79aa5 100644 --- a/src/ru/pulsar/jenkins/library/configuration/BddOptions.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/BddOptions.groovy @@ -20,7 +20,7 @@ class BddOptions extends StepCoverageOptions implements Serializable { Boolean coverage = false @JsonPropertyDescription("Порт, на котором будет запущен сервер отладки для замера покрытия") - int dbgsPort = 1550 + Integer dbgsPort = 1550 @Override @NonCPS diff --git a/src/ru/pulsar/jenkins/library/configuration/SmokeTestOptions.groovy b/src/ru/pulsar/jenkins/library/configuration/SmokeTestOptions.groovy index 58514e7f..5e844f1e 100644 --- a/src/ru/pulsar/jenkins/library/configuration/SmokeTestOptions.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/SmokeTestOptions.groovy @@ -31,7 +31,7 @@ class SmokeTestOptions extends StepCoverageOptions implements Serializable { Boolean coverage = false @JsonPropertyDescription("Порт, на котором будет запущен сервер отладки для замера покрытия") - int dbgsPort = 1550 + Integer dbgsPort = 1550 @Override @NonCPS diff --git a/src/ru/pulsar/jenkins/library/configuration/YaxunitOptions.groovy b/src/ru/pulsar/jenkins/library/configuration/YaxunitOptions.groovy index 86d8e183..840c0065 100644 --- a/src/ru/pulsar/jenkins/library/configuration/YaxunitOptions.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/YaxunitOptions.groovy @@ -31,7 +31,7 @@ class YaxunitOptions extends StepCoverageOptions implements Serializable { Boolean coverage = false @JsonPropertyDescription("Порт, на котором будет запущен сервер отладки для замера покрытия") - int dbgsPort = 1550 + Integer dbgsPort = 1550 @Override @NonCPS From 20d0b056190d868e938d805b68c2e97f5fe9530c Mon Sep 17 00:00:00 2001 From: Dima Date: Sun, 1 Dec 2024 14:18:06 +0300 Subject: [PATCH 066/112] refactoring --- .../jenkins/library/IStepExecutor.groovy | 9 +++ .../jenkins/library/StepExecutor.groovy | 8 +++ .../pulsar/jenkins/library/steps/Bdd.groovy | 25 ++------ .../jenkins/library/steps/Coverable.groovy | 1 + .../library/steps/CoverageContext.groovy | 4 +- .../jenkins/library/steps/SmokeTest.groovy | 41 ++++--------- .../jenkins/library/steps/WithCoverage.groovy | 47 ++++++++++++++ .../jenkins/library/steps/Yaxunit.groovy | 61 +++++++------------ .../library/utils/CoverageUtils.groovy | 22 ++++--- vars/withCoverage.groovy | 12 ++++ 10 files changed, 137 insertions(+), 93 deletions(-) create mode 100644 src/ru/pulsar/jenkins/library/steps/WithCoverage.groovy create mode 100644 vars/withCoverage.groovy diff --git a/src/ru/pulsar/jenkins/library/IStepExecutor.groovy b/src/ru/pulsar/jenkins/library/IStepExecutor.groovy index 0619e0c5..b8d0c500 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) @@ -66,6 +70,8 @@ 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) @@ -80,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 6a22d7fe..81c29a51 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 { @@ -149,6 +152,11 @@ 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) { diff --git a/src/ru/pulsar/jenkins/library/steps/Bdd.groovy b/src/ru/pulsar/jenkins/library/steps/Bdd.groovy index e7737870..057bbad7 100644 --- a/src/ru/pulsar/jenkins/library/steps/Bdd.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Bdd.groovy @@ -3,8 +3,6 @@ package ru.pulsar.jenkins.library.steps 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.CoverageUtils -import ru.pulsar.jenkins.library.utils.FileUtils import ru.pulsar.jenkins.library.utils.Logger import ru.pulsar.jenkins.library.utils.VRunner @@ -32,9 +30,6 @@ class Bdd implements Serializable, Coverable { } def options = config.bddOptions - def env = steps.env() - def srcDir = config.srcDir - def workspaceDir = FileUtils.getFilePath("$env.WORKSPACE") List logosConfig = ["LOGOS_CONFIG=$config.logosConfig"] steps.withEnv(logosConfig) { @@ -42,13 +37,7 @@ class Bdd implements Serializable, Coverable { steps.createDir('build/out') List returnStatuses = [] - def coverageOpts = config.coverageOptions - def coverageContext = CoverageUtils.prepareContext(config, options) - - steps.lock(coverageContext.lockableResource) { - if (options.coverage) { - CoverageContext.startCoverage(steps, coverageOpts, coverageContext, workspaceDir, srcDir, this) - } + steps.withCoverage(config, this, options) { config.bddOptions.vrunnerSteps.each { Logger.println("Шаг запуска сценариев командой ${it}") @@ -64,18 +53,11 @@ class Bdd implements Serializable, Coverable { } else { Logger.println("Тестирование сценариев завершилось успешно") } - - if (options.coverage) { - CoverageUtils.stopCoverage(steps, coverageOpts, coverageContext) - } } } steps.stash(ALLURE_STASH, 'build/out/allure/**', true) steps.stash('bdd-cucumber', 'build/out/cucumber/**', true) - if (options.coverage) { - steps.stash(COVERAGE_STASH_NAME, COVERAGE_STASH_PATH, true) - } } @@ -83,6 +65,11 @@ class Bdd implements Serializable, Coverable { return COVERAGE_STASH_PATH } + @Override + String getCoverageStashName() { + return COVERAGE_STASH_NAME + } + 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 index 54271bb8..0dbfdd92 100644 --- a/src/ru/pulsar/jenkins/library/steps/Coverable.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Coverable.groovy @@ -3,6 +3,7 @@ package ru.pulsar.jenkins.library.steps interface Coverable { 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 index 36d47286..5d7d9eec 100644 --- a/src/ru/pulsar/jenkins/library/steps/CoverageContext.groovy +++ b/src/ru/pulsar/jenkins/library/steps/CoverageContext.groovy @@ -5,14 +5,16 @@ import ru.pulsar.jenkins.library.configuration.GlobalCoverageOptions class CoverageContext { String lockableResource + String srcDir GlobalCoverageOptions coverageOptions int port ArrayList pids ArrayList dbgsPids ArrayList coverage41CPids - CoverageContext(String lockableResource, GlobalCoverageOptions coverageOptions, int port, ArrayList dbgsPids, ArrayList coverage41CPids) { + CoverageContext(String lockableResource, String srcDir, GlobalCoverageOptions coverageOptions, int port, ArrayList dbgsPids, ArrayList coverage41CPids) { this.lockableResource = lockableResource + this.srcDir = srcDir this.coverageOptions = coverageOptions this.port = port this.pids = dbgsPids + coverage41CPids diff --git a/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy b/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy index 3bed18ac..f2f86137 100644 --- a/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy +++ b/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy @@ -4,7 +4,6 @@ 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.CoverageUtils import ru.pulsar.jenkins.library.utils.FileUtils import ru.pulsar.jenkins.library.utils.Logger import ru.pulsar.jenkins.library.utils.StringJoiner @@ -41,9 +40,6 @@ class SmokeTest implements Serializable, Coverable { def options = config.smokeTestOptions def env = steps.env() - def srcDir = config.srcDir - def workspaceDir = FileUtils.getFilePath("$env.WORKSPACE") - String vrunnerPath = VRunner.getVRunnerPath() String command = "$vrunnerPath xunit --ibconnection \"/F./build/ib\"" @@ -107,43 +103,32 @@ class SmokeTest implements Serializable, Coverable { command += " $testsPath" } - def coverageOpts = config.coverageOptions - def coverageContext = CoverageUtils.prepareContext(config, options) - - steps.lock(coverageContext.lockableResource) { - if (options.coverage) { - CoverageContext.startCoverage(steps, coverageOpts, coverageContext, workspaceDir, srcDir, this) - } + steps.withEnv(logosConfig) { - steps.withEnv(logosConfig) { + steps.withCoverage(config, this, options) { VRunner.exec(command, true) } - if (options.coverage) { - CoverageUtils.stopCoverage(steps, coverageOpts, coverageContext) + if (options.publishToAllureReport) { + steps.stash(ALLURE_STASH, "$allureReportDir/**", true) + steps.archiveArtifacts("$allureReportDir/**") } - } - - if (options.publishToAllureReport) { - steps.stash(ALLURE_STASH, "$allureReportDir/**", true) - steps.archiveArtifacts("$allureReportDir/**") - } - if (options.publishToJUnitReport) { - steps.junit("$junitReportDir/*.xml", true) - steps.archiveArtifacts("$junitReportDir/**") - } - - if (options.coverage) { - steps.stash(COVERAGE_STASH_NAME, COVERAGE_STASH_PATH, true) + if (options.publishToJUnitReport) { + steps.junit("$junitReportDir/*.xml", true) + steps.archiveArtifacts("$junitReportDir/**") + } } - } String getCoverageStashPath() { return COVERAGE_STASH_PATH } + String getCoverageStashName() { + return COVERAGE_STASH_NAME + } + String getCoveragePidsPath() { return COVERAGE_PIDS_PATH } 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..c7f83127 --- /dev/null +++ b/src/ru/pulsar/jenkins/library/steps/WithCoverage.groovy @@ -0,0 +1,47 @@ +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.CoverageUtils + +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() { + + def context = CoverageUtils.prepareContext(config, coverageOptions) + + IStepExecutor steps = ContextRegistry.getContext().getStepExecutor() + + //noinspection GroovyMissingReturnStatement + steps.lock(context.lockableResource) { + if (coverageOptions.coverage) { + CoverageUtils.startCoverage(steps, config, context, stage) + } + + body() + + if (coverageOptions.coverage) { + CoverageUtils.stopCoverage(steps, config, context) + } + } + + if (coverageOptions.coverage) { + steps.stash(stage.getCoverageStashName(), stage.getCoverageStashPath(), true) + } + + } +} diff --git a/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy b/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy index 2be4ffb0..e6f657a9 100644 --- a/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy @@ -4,7 +4,6 @@ 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.CoverageUtils import ru.pulsar.jenkins.library.utils.FileUtils import ru.pulsar.jenkins.library.utils.Logger import ru.pulsar.jenkins.library.utils.VRunner @@ -42,9 +41,6 @@ class Yaxunit implements Serializable, Coverable { def options = config.yaxunitOptions def env = steps.env() - def srcDir = config.srcDir - def workspaceDir = FileUtils.getFilePath("$env.WORKSPACE") - String vrunnerPath = VRunner.getVRunnerPath() String ibConnection = ' --ibconnection "/F./build/ib"' @@ -69,48 +65,34 @@ class Yaxunit implements Serializable, Coverable { } - def coverageOpts = config.coverageOptions - def coverageContext = CoverageUtils.prepareContext(config, options) - - steps.lock(coverageContext.lockableResource) { - if (options.coverage) { - CoverageContext.startCoverage(steps, coverageOpts, coverageContext, workspaceDir, srcDir, this) - } + steps.withEnv(logosConfig) { - // Выполняем команды - steps.withEnv(logosConfig) { + steps.withCoverage(config, this, options) { VRunner.exec(runTestsCommand, true) } - if (options.coverage) { - CoverageUtils.stopCoverage(steps, coverageOpts, coverageContext) - } - } + // Сохраняем результаты + String junitReport = "./build/out/yaxunit/junit.xml" + FilePath pathToJUnitReport = FileUtils.getFilePath("$env.WORKSPACE/$junitReport") + String junitReportDir = FileUtils.getLocalPath(pathToJUnitReport.getParent()) - // Сохраняем результаты - 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.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) + } - steps.archiveArtifacts("build/out/yaxunit/junit.xml") + steps.archiveArtifacts("build/out/yaxunit/junit.xml") - if (options.coverage) { - steps.stash(COVERAGE_STASH_NAME, COVERAGE_STASH_PATH, true) } } @@ -118,9 +100,12 @@ class Yaxunit implements Serializable, Coverable { return COVERAGE_STASH_PATH } + @Override + String getCoverageStashName() { + return COVERAGE_STASH_NAME + } + String getCoveragePidsPath() { return COVERAGE_PIDS_PATH } - - } diff --git a/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy b/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy index 71624cff..99ab4366 100644 --- a/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy +++ b/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy @@ -1,9 +1,7 @@ package ru.pulsar.jenkins.library.utils -import hudson.FilePath import org.apache.commons.lang3.RandomStringUtils import ru.pulsar.jenkins.library.IStepExecutor -import ru.pulsar.jenkins.library.configuration.GlobalCoverageOptions import ru.pulsar.jenkins.library.configuration.JobConfiguration import ru.pulsar.jenkins.library.configuration.StepCoverageOptions import ru.pulsar.jenkins.library.ioc.ContextRegistry @@ -39,13 +37,20 @@ class CoverageUtils { lockableResource = "${env.NODE_NAME}_$port" } - return new CoverageContext(lockableResource, coverageOpts, port, currentDbgsPids, currentCoverage41CPids) + return new CoverageContext(lockableResource, config.srcDir, coverageOpts, port, currentDbgsPids, currentCoverage41CPids) } - static void startCoverage(IStepExecutor steps, GlobalCoverageOptions coverageOpts, CoverageContext coverageContext, FilePath workspaceDir, String srcDir, Coverable coverable) { + 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 + steps.start("${coverageOpts.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 ${coverable.getCoverageStashPath()}") + 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") @@ -57,12 +62,15 @@ class CoverageUtils { newDbgsPids.addAll(newCoverage41CPids) def pids = newDbgsPids.join(" ") - steps.writeFile(coverable.getCoveragePidsPath(), pids, 'UTF-8') + steps.writeFile(stage.getCoveragePidsPath(), pids, 'UTF-8') Logger.println("Coverage PIDs for cleanup: $pids") } - static void stopCoverage(IStepExecutor steps, GlobalCoverageOptions coverageOpts, CoverageContext coverageContext) { + 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") } 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 From f758456114c23f4b6d12c49e5d29da2a6989cf45 Mon Sep 17 00:00:00 2001 From: Dima Date: Sun, 1 Dec 2024 17:04:49 +0300 Subject: [PATCH 067/112] fixes --- README.md | 4 ++-- resources/globalConfiguration.json | 2 +- resources/schema.json | 4 ++-- .../pulsar/jenkins/library/configuration/BddOptions.groovy | 6 ------ .../library/configuration/GlobalCoverageOptions.groovy | 4 ++-- .../jenkins/library/configuration/SmokeTestOptions.groovy | 6 ------ .../jenkins/library/configuration/YaxunitOptions.groovy | 6 ------ test/unit/resources/jobConfiguration.json | 3 +++ 8 files changed, 10 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index e4b0225d..5f316d79 100644 --- a/README.md +++ b/README.md @@ -246,5 +246,5 @@ pipeline1C() ## Настройка трансформации результата валидации EDT - * При использовании SonarQube версии <10.3 и `stebi` формат отчета должен быть `Generic_Issue` (параметр `resultsTransform` -> `genericIssueFormat`) - * Трансформацию результатов может выполнять `edt-ripper` (параметр `resultsTransform` -> `transformer`). В этом случае замечания будут загружены в SonarQube в формате BSL LS, что позволяет полноценно управлять ими в SonarQube. +* При использовании SonarQube версии <10.3 и `stebi` формат отчета должен быть `Generic_Issue` (параметр `resultsTransform` -> `genericIssueFormat`) +* Трансформацию результатов может выполнять `edt-ripper` (параметр `resultsTransform` -> `transformer`). В этом случае замечания будут загружены в SonarQube в формате BSL LS, что позволяет полноценно управлять ими в SonarQube. diff --git a/resources/globalConfiguration.json b/resources/globalConfiguration.json index f1c2c21b..62bdce51 100644 --- a/resources/globalConfiguration.json +++ b/resources/globalConfiguration.json @@ -90,7 +90,7 @@ "dbgsPort": 1551 }, "coverage": { - "dbgsPath": "/opt/1cv8/current/dbgs", + "dbgsPath": "dbgs", "coverage41CPath": "Coverage41C" }, "yaxunit": { diff --git a/resources/schema.json b/resources/schema.json index 689da43f..32351145 100644 --- a/resources/schema.json +++ b/resources/schema.json @@ -51,11 +51,11 @@ "properties" : { "coverage41CPath" : { "type" : "string", - "description" : "Путь к исполняемому файлу Coverage41C\n По умолчанию равен Coverage41C.\n " + "description" : "Путь к исполняемому файлу Coverage41C\n По умолчанию ищется в PATH.\n " }, "dbgsPath" : { "type" : "string", - "description" : "Путь к исполняемому файлу dbgs.\n По умолчанию равен /opt/1cv8/current/dbgs.\n " + "description" : "Путь к исполняемому файлу dbgs.\n По умолчанию ищется в PATH.\n " } }, "description" : "Настройки замеров покрытия" diff --git a/src/ru/pulsar/jenkins/library/configuration/BddOptions.groovy b/src/ru/pulsar/jenkins/library/configuration/BddOptions.groovy index cef79aa5..d82a1788 100644 --- a/src/ru/pulsar/jenkins/library/configuration/BddOptions.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/BddOptions.groovy @@ -16,12 +16,6 @@ class BddOptions extends StepCoverageOptions implements Serializable { 'vanessa --settings ./tools/vrunner.json' ] - @JsonPropertyDescription("Выполнять замер покрытия") - Boolean coverage = false - - @JsonPropertyDescription("Порт, на котором будет запущен сервер отладки для замера покрытия") - Integer dbgsPort = 1550 - @Override @NonCPS String toString() { diff --git a/src/ru/pulsar/jenkins/library/configuration/GlobalCoverageOptions.groovy b/src/ru/pulsar/jenkins/library/configuration/GlobalCoverageOptions.groovy index 9a4fcda7..a631ff65 100644 --- a/src/ru/pulsar/jenkins/library/configuration/GlobalCoverageOptions.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/GlobalCoverageOptions.groovy @@ -8,12 +8,12 @@ import com.fasterxml.jackson.annotation.JsonPropertyDescription class GlobalCoverageOptions implements Serializable { @JsonPropertyDescription('''Путь к исполняемому файлу dbgs. - По умолчанию равен /opt/1cv8/current/dbgs. + По умолчанию ищется в PATH. ''') String dbgsPath @JsonPropertyDescription('''Путь к исполняемому файлу Coverage41C - По умолчанию равен Coverage41C. + По умолчанию ищется в PATH. ''') String coverage41CPath diff --git a/src/ru/pulsar/jenkins/library/configuration/SmokeTestOptions.groovy b/src/ru/pulsar/jenkins/library/configuration/SmokeTestOptions.groovy index 5e844f1e..563acb6a 100644 --- a/src/ru/pulsar/jenkins/library/configuration/SmokeTestOptions.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/SmokeTestOptions.groovy @@ -27,12 +27,6 @@ class SmokeTestOptions extends StepCoverageOptions implements Serializable { """) boolean publishToJUnitReport - @JsonPropertyDescription("Выполнять замер покрытия") - Boolean coverage = false - - @JsonPropertyDescription("Порт, на котором будет запущен сервер отладки для замера покрытия") - Integer dbgsPort = 1550 - @Override @NonCPS String toString() { diff --git a/src/ru/pulsar/jenkins/library/configuration/YaxunitOptions.groovy b/src/ru/pulsar/jenkins/library/configuration/YaxunitOptions.groovy index 840c0065..eae18a79 100644 --- a/src/ru/pulsar/jenkins/library/configuration/YaxunitOptions.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/YaxunitOptions.groovy @@ -27,12 +27,6 @@ class YaxunitOptions extends StepCoverageOptions implements Serializable { """) boolean publishToJUnitReport - @JsonPropertyDescription("Выполнять замер покрытия") - Boolean coverage = false - - @JsonPropertyDescription("Порт, на котором будет запущен сервер отладки для замера покрытия") - Integer dbgsPort = 1550 - @Override @NonCPS String toString() { diff --git a/test/unit/resources/jobConfiguration.json b/test/unit/resources/jobConfiguration.json index 3b3dcbc5..c7682c79 100644 --- a/test/unit/resources/jobConfiguration.json +++ b/test/unit/resources/jobConfiguration.json @@ -4,6 +4,9 @@ "secrets": { "storage": "1234" }, + "coverage": { + "dbgsPath": "/opt/1cv8/current/dbgs" + }, "stages": { "syntaxCheck": true }, From f17c9ae4b7c435547b3b578cf7849f099869adc3 Mon Sep 17 00:00:00 2001 From: Nikita Fedkin Date: Sun, 1 Dec 2024 19:08:57 +0100 Subject: [PATCH 068/112] Update src/ru/pulsar/jenkins/library/steps/WithCoverage.groovy Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- .../jenkins/library/steps/WithCoverage.groovy | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/ru/pulsar/jenkins/library/steps/WithCoverage.groovy b/src/ru/pulsar/jenkins/library/steps/WithCoverage.groovy index c7f83127..7a5aec8f 100644 --- a/src/ru/pulsar/jenkins/library/steps/WithCoverage.groovy +++ b/src/ru/pulsar/jenkins/library/steps/WithCoverage.groovy @@ -28,14 +28,16 @@ class WithCoverage implements Serializable { //noinspection GroovyMissingReturnStatement steps.lock(context.lockableResource) { - if (coverageOptions.coverage) { - CoverageUtils.startCoverage(steps, config, context, stage) - } - - body() - - if (coverageOptions.coverage) { - CoverageUtils.stopCoverage(steps, config, context) + try { + if (coverageOptions.coverage) { + CoverageUtils.startCoverage(steps, config, context, stage) + } + + body() + } finally { + if (coverageOptions.coverage) { + CoverageUtils.stopCoverage(steps, config, context) + } } } From e711f86749f67215988d5fe6b74d740aafcea2fa Mon Sep 17 00:00:00 2001 From: Dima Date: Mon, 2 Dec 2024 13:32:08 +0300 Subject: [PATCH 069/112] refactoring and fixes --- .gitattributes | 1 + resources/dbgs.os | 3 +++ resources/globalConfiguration.json | 6 ++--- resources/schema.json | 20 +++++++++----- .../GlobalCoverageOptions.groovy | 2 +- .../configuration/StepCoverageOptions.groovy | 3 +++ .../jenkins/library/steps/WithCoverage.groovy | 9 ++++--- .../library/utils/CoverageUtils.groovy | 27 ++++++++++++++++--- 8 files changed, 53 insertions(+), 18 deletions(-) create mode 100644 resources/dbgs.os diff --git a/.gitattributes b/.gitattributes index 71b9a47f..37ebb32a 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,3 @@ *.groovy eol=lf *.md eol=lf +*.os eol=lf 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 62bdce51..58db158c 100644 --- a/resources/globalConfiguration.json +++ b/resources/globalConfiguration.json @@ -87,10 +87,10 @@ "publishToAllureReport": false, "publishToJUnitReport": true, "coverage": false, - "dbgsPort": 1551 + "dbgsPort": 1550 }, "coverage": { - "dbgsPath": "dbgs", + "dbgsPath": "", "coverage41CPath": "Coverage41C" }, "yaxunit": { @@ -99,7 +99,7 @@ "publishToAllureReport": false, "publishToJUnitReport": true, "coverage": false, - "dbgsPort": 1552 + "dbgsPort": 1550 }, "resultsTransform": { "transformer": "stebi", diff --git a/resources/schema.json b/resources/schema.json index 32351145..dd9fdb67 100644 --- a/resources/schema.json +++ b/resources/schema.json @@ -30,11 +30,13 @@ "properties" : { "coverage" : { "type" : "boolean", - "description" : "Выполнять замер покрытия" + "description" : "Выполнять замер покрытия", + "default" : "false" }, "dbgsPort" : { "type" : "integer", - "description" : "Порт, на котором будет запущен сервер отладки для замера покрытия" + "description" : "Порт, на котором будет запущен сервер отладки для замера покрытия", + "default" : "1550" }, "vrunnerSteps" : { "description" : "Шаги, запускаемые через vrunner.\n В каждой строке передается отдельная команда \n vrunner и ее аргументы (например, \"vanessa --settings ./tools/vrunner.json\").\n По умолчанию содержит одну команду \"vanessa --settings ./tools/vrunner.json\".\n ", @@ -55,7 +57,7 @@ }, "dbgsPath" : { "type" : "string", - "description" : "Путь к исполняемому файлу dbgs.\n По умолчанию ищется в PATH.\n " + "description" : "Путь к исполняемому файлу dbgs.\n По умолчанию ищется с помощью v8find для указанной версии платформы (v8version).\n " } }, "description" : "Настройки замеров покрытия" @@ -247,11 +249,13 @@ "properties" : { "coverage" : { "type" : "boolean", - "description" : "Выполнять замер покрытия" + "description" : "Выполнять замер покрытия", + "default" : "false" }, "dbgsPort" : { "type" : "integer", - "description" : "Порт, на котором будет запущен сервер отладки для замера покрытия" + "description" : "Порт, на котором будет запущен сервер отладки для замера покрытия", + "default" : "1550" }, "publishToAllureReport" : { "type" : "boolean", @@ -464,11 +468,13 @@ }, "coverage" : { "type" : "boolean", - "description" : "Выполнять замер покрытия" + "description" : "Выполнять замер покрытия", + "default" : "false" }, "dbgsPort" : { "type" : "integer", - "description" : "Порт, на котором будет запущен сервер отладки для замера покрытия" + "description" : "Порт, на котором будет запущен сервер отладки для замера покрытия", + "default" : "1550" }, "publishToAllureReport" : { "type" : "boolean", diff --git a/src/ru/pulsar/jenkins/library/configuration/GlobalCoverageOptions.groovy b/src/ru/pulsar/jenkins/library/configuration/GlobalCoverageOptions.groovy index a631ff65..925f8191 100644 --- a/src/ru/pulsar/jenkins/library/configuration/GlobalCoverageOptions.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/GlobalCoverageOptions.groovy @@ -8,7 +8,7 @@ import com.fasterxml.jackson.annotation.JsonPropertyDescription class GlobalCoverageOptions implements Serializable { @JsonPropertyDescription('''Путь к исполняемому файлу dbgs. - По умолчанию ищется в PATH. + По умолчанию ищется с помощью v8find для указанной версии платформы (v8version). ''') String dbgsPath diff --git a/src/ru/pulsar/jenkins/library/configuration/StepCoverageOptions.groovy b/src/ru/pulsar/jenkins/library/configuration/StepCoverageOptions.groovy index 63c0b24f..47f95b6c 100644 --- a/src/ru/pulsar/jenkins/library/configuration/StepCoverageOptions.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/StepCoverageOptions.groovy @@ -1,13 +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/steps/WithCoverage.groovy b/src/ru/pulsar/jenkins/library/steps/WithCoverage.groovy index 7a5aec8f..f78be6cd 100644 --- a/src/ru/pulsar/jenkins/library/steps/WithCoverage.groovy +++ b/src/ru/pulsar/jenkins/library/steps/WithCoverage.groovy @@ -34,16 +34,17 @@ class WithCoverage implements Serializable { } body() + } catch (Exception e) { + throw new Exception("При выполнении блока произошла ошибка: ${e}") } finally { if (coverageOptions.coverage) { CoverageUtils.stopCoverage(steps, config, context) } } - } - if (coverageOptions.coverage) { - steps.stash(stage.getCoverageStashName(), stage.getCoverageStashPath(), true) + if (coverageOptions.coverage) { + steps.stash(stage.getCoverageStashName(), stage.getCoverageStashPath(), true) + } } - } } diff --git a/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy b/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy index 99ab4366..b691ab7e 100644 --- a/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy +++ b/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy @@ -49,9 +49,11 @@ class CoverageUtils { def coverageOpts = config.coverageOptions - steps.start("${coverageOpts.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") + 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") @@ -74,4 +76,23 @@ class CoverageUtils { steps.cmd("${coverageOpts.coverage41CPath} stop -i DefAlias -u http://127.0.0.1:$coverageContext.port") } + static String findDbgs(IStepExecutor steps, JobConfiguration config) { + + String dbgsPath = config.coverageOptions.dbgsPath + if (dbgsPath.isEmpty()) { + def osResourcePath = steps.libraryResource "dbgs.os" + final osResultPath = "build/dbgs.os" + steps.writeFile(osResultPath, osResourcePath, 'UTF-8') + + dbgsPath = steps.cmd("oscript ${osResultPath} ${config.v8version}", false, true) + } + + if (dbgsPath.isEmpty()) { + steps.error("Не удалось найти путь к dbgs") + } + + return dbgsPath.strip() + + } + } From 24231f9aab655fbf8ccb6d0dcd69c611154913e3 Mon Sep 17 00:00:00 2001 From: Dima Ovcharenko Date: Wed, 11 Dec 2024 15:42:11 +0300 Subject: [PATCH 070/112] fix bat --- src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy b/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy index b691ab7e..beb27d7b 100644 --- a/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy +++ b/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy @@ -18,7 +18,7 @@ class CoverageUtils { if (steps.isUnix()) { pids = steps.sh("ps -aux | grep '$name' | awk '{print \$2}'", false, true, 'UTF-8') } else { - pids = steps.bat("chcp 65001 > nul \nfor /f \"tokens=2\" %a in ('tasklist ^| findstr $name') do @echo %a", false, true, 'UTF-8') + pids = steps.bat('chcp 65001 > nul \nfor /f \"tokens=2\" %a in (\'tasklist ^| findstr $name\') do @echo %a', false, true, 'UTF-8') } return pids.split('\n').toList() } From 49c1f789ebd40ca887d4b8cc4bdd9a818646c38d Mon Sep 17 00:00:00 2001 From: Dima Ovcharenko Date: Wed, 11 Dec 2024 16:00:36 +0300 Subject: [PATCH 071/112] fix bat --- src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy b/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy index beb27d7b..4239403c 100644 --- a/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy +++ b/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy @@ -18,7 +18,7 @@ class CoverageUtils { if (steps.isUnix()) { pids = steps.sh("ps -aux | grep '$name' | awk '{print \$2}'", false, true, 'UTF-8') } else { - pids = steps.bat('chcp 65001 > nul \nfor /f \"tokens=2\" %a in (\'tasklist ^| findstr $name\') do @echo %a', false, true, 'UTF-8') + pids = steps.bat("chcp 65001 > nul \nfor /f \"tokens=2\" %%a in ('tasklist ^| findstr $name') do @echo %%a", false, true, 'UTF-8') } return pids.split('\n').toList() } From 5d8f71069bcb8a52492e67911202c7808418a94d Mon Sep 17 00:00:00 2001 From: Dima Ovcharenko Date: Wed, 11 Dec 2024 16:56:16 +0300 Subject: [PATCH 072/112] fix crlf --- src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy b/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy index 4239403c..f99376af 100644 --- a/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy +++ b/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy @@ -20,7 +20,7 @@ class CoverageUtils { } else { pids = steps.bat("chcp 65001 > nul \nfor /f \"tokens=2\" %%a in ('tasklist ^| findstr $name') do @echo %%a", false, true, 'UTF-8') } - return pids.split('\n').toList() + return pids.split('\r?\n').toList() } static CoverageContext prepareContext(JobConfiguration config, StepCoverageOptions options) { From 91b66209df6b15df076a64e0526d8e1973004022 Mon Sep 17 00:00:00 2001 From: Nikita Fedkin Date: Wed, 11 Dec 2024 15:22:08 +0100 Subject: [PATCH 073/112] Fix returned value --- src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy b/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy index f99376af..ec0260e3 100644 --- a/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy +++ b/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy @@ -9,7 +9,7 @@ import ru.pulsar.jenkins.library.steps.Coverable import ru.pulsar.jenkins.library.steps.CoverageContext class CoverageUtils { - static ArrayList getPIDs(String name) { + static List getPIDs(String name) { IStepExecutor steps = ContextRegistry.getContext().getStepExecutor() From 6780bc6581508704872dc8a0ed4c32e91a569369 Mon Sep 17 00:00:00 2001 From: Dima Date: Wed, 11 Dec 2024 18:55:58 +0300 Subject: [PATCH 074/112] escape caret --- src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy b/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy index ec0260e3..9851c8fa 100644 --- a/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy +++ b/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy @@ -18,7 +18,7 @@ class CoverageUtils { if (steps.isUnix()) { pids = steps.sh("ps -aux | grep '$name' | awk '{print \$2}'", false, true, 'UTF-8') } else { - pids = steps.bat("chcp 65001 > nul \nfor /f \"tokens=2\" %%a in ('tasklist ^| findstr $name') do @echo %%a", false, true, 'UTF-8') + pids = steps.bat("chcp 65001 > nul \nfor /f \"tokens=2\" %%a in ('tasklist ^^| findstr $name') do @echo %%a", false, true, 'UTF-8') } return pids.split('\r?\n').toList() } From ce26f4139e9c8b652362b03776a808af0cf7b51e Mon Sep 17 00:00:00 2001 From: Dima Date: Wed, 11 Dec 2024 19:17:49 +0300 Subject: [PATCH 075/112] escape expr --- src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy b/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy index 9851c8fa..00aab65c 100644 --- a/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy +++ b/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy @@ -18,7 +18,7 @@ class CoverageUtils { if (steps.isUnix()) { pids = steps.sh("ps -aux | grep '$name' | awk '{print \$2}'", false, true, 'UTF-8') } else { - pids = steps.bat("chcp 65001 > nul \nfor /f \"tokens=2\" %%a in ('tasklist ^^| findstr $name') do @echo %%a", false, true, 'UTF-8') + pids = steps.bat("chcp 65001 > nul \nfor /f \"tokens=2\" %%a in (\"tasklist ^^| findstr $name\") do @echo %%a", false, true, 'UTF-8') } return pids.split('\r?\n').toList() } From 7f4b7fae69d6e74eeb6b908f174ff4334a32e43e Mon Sep 17 00:00:00 2001 From: Dima Date: Wed, 11 Dec 2024 19:18:12 +0300 Subject: [PATCH 076/112] revert ^^ --- src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy b/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy index 00aab65c..c23288cd 100644 --- a/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy +++ b/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy @@ -18,7 +18,7 @@ class CoverageUtils { if (steps.isUnix()) { pids = steps.sh("ps -aux | grep '$name' | awk '{print \$2}'", false, true, 'UTF-8') } else { - pids = steps.bat("chcp 65001 > nul \nfor /f \"tokens=2\" %%a in (\"tasklist ^^| findstr $name\") do @echo %%a", false, true, 'UTF-8') + pids = steps.bat("chcp 65001 > nul \nfor /f \"tokens=2\" %%a in (\"tasklist ^| findstr $name\") do @echo %%a", false, true, 'UTF-8') } return pids.split('\r?\n').toList() } From bbd523827720d55acf49c008bf0e63541581072b Mon Sep 17 00:00:00 2001 From: Dima Date: Thu, 12 Dec 2024 09:15:23 +0300 Subject: [PATCH 077/112] fix start step --- src/ru/pulsar/jenkins/library/IStepExecutor.groovy | 2 +- src/ru/pulsar/jenkins/library/StepExecutor.groovy | 4 ++-- src/ru/pulsar/jenkins/library/steps/Start.groovy | 12 +++++++----- .../jenkins/library/utils/CoverageUtils.groovy | 4 ++-- vars/start.groovy | 4 ++-- 5 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/ru/pulsar/jenkins/library/IStepExecutor.groovy b/src/ru/pulsar/jenkins/library/IStepExecutor.groovy index b8d0c500..8a2f6e8c 100644 --- a/src/ru/pulsar/jenkins/library/IStepExecutor.groovy +++ b/src/ru/pulsar/jenkins/library/IStepExecutor.groovy @@ -44,7 +44,7 @@ interface IStepExecutor { def ringCommand(String script) - void start(String script) + void start(String executable, String params) void tool(String toolName) diff --git a/src/ru/pulsar/jenkins/library/StepExecutor.groovy b/src/ru/pulsar/jenkins/library/StepExecutor.groovy index 81c29a51..8309af63 100644 --- a/src/ru/pulsar/jenkins/library/StepExecutor.groovy +++ b/src/ru/pulsar/jenkins/library/StepExecutor.groovy @@ -76,8 +76,8 @@ class StepExecutor implements IStepExecutor { } @Override - void start(String script) { - steps.start(script) + void start(String executable, String params) { + steps.start(executable, params) } @Override diff --git a/src/ru/pulsar/jenkins/library/steps/Start.groovy b/src/ru/pulsar/jenkins/library/steps/Start.groovy index 8d8c99e0..a3ede2d8 100644 --- a/src/ru/pulsar/jenkins/library/steps/Start.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Start.groovy @@ -5,20 +5,22 @@ import ru.pulsar.jenkins.library.ioc.ContextRegistry class Start implements Serializable { - private String script + private String executable + private String params private String encoding = 'UTF-8' - Start(String script) { - this.script = script + Start(String executable, String params) { + this.executable = executable + this.params = params }; void run() { IStepExecutor steps = ContextRegistry.getContext().getStepExecutor() if (steps.isUnix()) { - steps.sh("$script &", false, false , encoding) + steps.sh("$executable $params &", false, false , encoding) } else { - steps.bat("chcp 65001 > nul \nstart $script", false, false, encoding) + steps.bat("chcp 65001 > nul \nstart \"\" /B \"$executable\" \"$params\"", false, false, encoding) } } } diff --git a/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy b/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy index c23288cd..a8a8d787 100644 --- a/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy +++ b/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy @@ -51,8 +51,8 @@ class CoverageUtils { 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.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") diff --git a/vars/start.groovy b/vars/start.groovy index 2727ee1b..dc10d29b 100644 --- a/vars/start.groovy +++ b/vars/start.groovy @@ -1,9 +1,9 @@ import ru.pulsar.jenkins.library.steps.Start import ru.pulsar.jenkins.library.ioc.ContextRegistry -void call(String script) { +void call(String executable, String params) { ContextRegistry.registerDefaultContext(this) - Start start = new Start(script) + Start start = new Start(executable, params) start.run() } From 408bc1e05b9af7b17eff0f8952318477b2fef7db Mon Sep 17 00:00:00 2001 From: Dima Date: Thu, 12 Dec 2024 16:50:30 +0300 Subject: [PATCH 078/112] add logging in findDbgs --- .../library/utils/CoverageUtils.groovy | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy b/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy index a8a8d787..5334c10a 100644 --- a/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy +++ b/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy @@ -79,19 +79,24 @@ class CoverageUtils { static String findDbgs(IStepExecutor steps, JobConfiguration config) { String dbgsPath = config.coverageOptions.dbgsPath - if (dbgsPath.isEmpty()) { - def osResourcePath = steps.libraryResource "dbgs.os" - final osResultPath = "build/dbgs.os" - steps.writeFile(osResultPath, osResourcePath, 'UTF-8') - - dbgsPath = steps.cmd("oscript ${osResultPath} ${config.v8version}", false, true) + if (!dbgsPath.isEmpty()) { + Logger.println("Using dbgsPath from config: $dbgsPath") + return dbgsPath.strip() } + def osResourcePath = steps.libraryResource "dbgs.os" + final osResultPath = "build/dbgs.os" + steps.writeFile(osResultPath, osResourcePath, 'UTF-8') + + dbgsPath = steps.cmd("oscript ${osResultPath} ${config.v8version}", false, true) + dbgsPath = dbgsPath.strip() + if (dbgsPath.isEmpty()) { steps.error("Не удалось найти путь к dbgs") } - return dbgsPath.strip() + Logger.println("Found dbgs: ${dbgsPath}") + return dbgsPath } From b44f4c67e3f5328e45fbd3aa4bb1bcbe3214e7e1 Mon Sep 17 00:00:00 2001 From: Dima Date: Thu, 12 Dec 2024 17:14:44 +0300 Subject: [PATCH 079/112] find dbgs through file --- .../jenkins/library/utils/CoverageUtils.groovy | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy b/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy index 5334c10a..858ca58c 100644 --- a/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy +++ b/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy @@ -84,12 +84,14 @@ class CoverageUtils { return dbgsPath.strip() } - def osResourcePath = steps.libraryResource "dbgs.os" - final osResultPath = "build/dbgs.os" - steps.writeFile(osResultPath, osResourcePath, 'UTF-8') + def dbgsFindScript = steps.libraryResource("dbgs.os") + final dbgsFindScriptPath = "build/dbgs.os" + final dbgsPathResult = "build/dbgsPath" + steps.writeFile(dbgsFindScriptPath, dbgsFindScript, 'UTF-8') - dbgsPath = steps.cmd("oscript ${osResultPath} ${config.v8version}", false, true) - dbgsPath = dbgsPath.strip() + steps.cmd("oscript ${dbgsFindScriptPath} ${config.v8version} > ${dbgsPathResult}", false, false) + + dbgsPath = steps.readFile(dbgsPathResult).strip() if (dbgsPath.isEmpty()) { steps.error("Не удалось найти путь к dbgs") From e00e0575736af439930925529b55be791e886177 Mon Sep 17 00:00:00 2001 From: Dima Date: Thu, 12 Dec 2024 19:00:03 +0300 Subject: [PATCH 080/112] pass start params as is --- src/ru/pulsar/jenkins/library/steps/Start.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ru/pulsar/jenkins/library/steps/Start.groovy b/src/ru/pulsar/jenkins/library/steps/Start.groovy index a3ede2d8..03343ef5 100644 --- a/src/ru/pulsar/jenkins/library/steps/Start.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Start.groovy @@ -20,7 +20,7 @@ class Start implements Serializable { if (steps.isUnix()) { steps.sh("$executable $params &", false, false , encoding) } else { - steps.bat("chcp 65001 > nul \nstart \"\" /B \"$executable\" \"$params\"", false, false, encoding) + steps.bat("chcp 65001 > nul \nstart \"\" /B \"$executable\" $params", false, false, encoding) } } } From 89422b026824db5769da599faa81e18418805e34 Mon Sep 17 00:00:00 2001 From: Dima Date: Fri, 13 Dec 2024 10:38:28 +0300 Subject: [PATCH 081/112] fix getPIDs commands --- src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy b/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy index 858ca58c..4eb647d8 100644 --- a/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy +++ b/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy @@ -14,11 +14,14 @@ class CoverageUtils { IStepExecutor steps = ContextRegistry.getContext().getStepExecutor() String pids + def script if (steps.isUnix()) { - pids = steps.sh("ps -aux | grep '$name' | awk '{print \$2}'", false, true, 'UTF-8') + script = "ps -aux | grep '$name' | grep -v grep | awk '{print \$2}'" + pids = steps.sh(script, false, true, 'UTF-8') } else { - pids = steps.bat("chcp 65001 > nul \nfor /f \"tokens=2\" %%a in (\"tasklist ^| findstr $name\") do @echo %%a", false, true, 'UTF-8') + script = "@echo off\nchcp 65001 > nul\nfor /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() } From d8cd62f49617e8d68b1d1a691f53a3192024bed7 Mon Sep 17 00:00:00 2001 From: Dima Date: Fri, 13 Dec 2024 11:05:31 +0300 Subject: [PATCH 082/112] revert quotes --- src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy b/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy index 4eb647d8..88978c57 100644 --- a/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy +++ b/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy @@ -20,7 +20,7 @@ class CoverageUtils { script = "ps -aux | grep '$name' | grep -v grep | awk '{print \$2}'" pids = steps.sh(script, false, true, 'UTF-8') } else { - script = "@echo off\nchcp 65001 > nul\nfor /f \"tokens=2\" %%a in (\'tasklist ^| findstr $name\') do (@echo %%a)" + script = "@echo off\nchcp 65001 > nul\nfor /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() From 0a78703449ba9c0b87b9e481ebdbc8b2eaf2a9c5 Mon Sep 17 00:00:00 2001 From: Dima Date: Fri, 13 Dec 2024 11:55:03 +0300 Subject: [PATCH 083/112] add logging to start step --- .../pulsar/jenkins/library/steps/Start.groovy | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/ru/pulsar/jenkins/library/steps/Start.groovy b/src/ru/pulsar/jenkins/library/steps/Start.groovy index 03343ef5..3c193b6b 100644 --- a/src/ru/pulsar/jenkins/library/steps/Start.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Start.groovy @@ -16,11 +16,31 @@ class Start implements Serializable { void run() { IStepExecutor steps = ContextRegistry.getContext().getStepExecutor() + def env = steps.env() + def executable_name = getExecutableName(executable) if (steps.isUnix()) { - steps.sh("$executable $params &", false, false , encoding) + 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", false, false, encoding) + 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 + } } From 8e4e76a60e84c92a6424b2100d7a7f3d906559d3 Mon Sep 17 00:00:00 2001 From: Dima Date: Fri, 13 Dec 2024 13:31:57 +0300 Subject: [PATCH 084/112] fix getPIDs again --- src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy b/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy index 88978c57..c984ab69 100644 --- a/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy +++ b/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy @@ -20,7 +20,7 @@ class CoverageUtils { script = "ps -aux | grep '$name' | grep -v grep | awk '{print \$2}'" pids = steps.sh(script, false, true, 'UTF-8') } else { - script = "@echo off\nchcp 65001 > nul\nfor /f \"tokens=2\" %%a in (\"tasklist ^| findstr $name\") do (@echo %%a)" + script = "@echo off\nchcp 65001 > nul\nfor /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() From 1653b127a5b8cd56aceea9886f4efda8f398a065 Mon Sep 17 00:00:00 2001 From: Dima Date: Fri, 13 Dec 2024 14:05:07 +0300 Subject: [PATCH 085/112] add /C --- src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy b/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy index c984ab69..76b1f472 100644 --- a/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy +++ b/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy @@ -20,7 +20,7 @@ class CoverageUtils { script = "ps -aux | grep '$name' | grep -v grep | awk '{print \$2}'" pids = steps.sh(script, false, true, 'UTF-8') } else { - script = "@echo off\nchcp 65001 > nul\nfor /f \"tokens=2\" %%a in ('tasklist ^| findstr \"$name\"') do (@echo %%a)" + script = "@echo off\nchcp 65001 > nul\nfor /f \"tokens=2\" %%a in ('tasklist ^| findstr /C:\"$name\"') do (@echo %%a)" pids = steps.bat(script, false, true, 'UTF-8') } return pids.split('\r?\n').toList() From 21265421fa84dd28b21c637c5d0144d655a69827 Mon Sep 17 00:00:00 2001 From: Dima Date: Fri, 13 Dec 2024 14:53:05 +0300 Subject: [PATCH 086/112] always exit 0 --- src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy b/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy index 76b1f472..fd8c5e3d 100644 --- a/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy +++ b/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy @@ -20,7 +20,7 @@ class CoverageUtils { script = "ps -aux | grep '$name' | grep -v grep | awk '{print \$2}'" pids = steps.sh(script, false, true, 'UTF-8') } else { - script = "@echo off\nchcp 65001 > nul\nfor /f \"tokens=2\" %%a in ('tasklist ^| findstr /C:\"$name\"') do (@echo %%a)" + script = "@echo off\nchcp 65001 > nul\nfor /f \"tokens=2\" %%a in ('tasklist ^| findstr \"$name\" || exit 0') do (@echo %%a)" pids = steps.bat(script, false, true, 'UTF-8') } return pids.split('\r?\n').toList() From 5327243e9f785672eef81fc50861342ed9ee99e4 Mon Sep 17 00:00:00 2001 From: Dima Date: Fri, 13 Dec 2024 15:30:36 +0300 Subject: [PATCH 087/112] modify pid command --- src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy b/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy index fd8c5e3d..46acc729 100644 --- a/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy +++ b/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy @@ -20,7 +20,14 @@ class CoverageUtils { script = "ps -aux | grep '$name' | grep -v grep | awk '{print \$2}'" pids = steps.sh(script, false, true, 'UTF-8') } else { - script = "@echo off\nchcp 65001 > nul\nfor /f \"tokens=2\" %%a in ('tasklist ^| findstr \"$name\" || exit 0') do (@echo %%a)" + 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() From 13763309066777f8e3815dd9d194b3315c69b8c3 Mon Sep 17 00:00:00 2001 From: Dima Date: Fri, 13 Dec 2024 16:00:14 +0300 Subject: [PATCH 088/112] fix lambda --- .../jenkins/library/steps/CoverageCleanup.groovy | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/ru/pulsar/jenkins/library/steps/CoverageCleanup.groovy b/src/ru/pulsar/jenkins/library/steps/CoverageCleanup.groovy index 7f3ee668..7d7c9332 100644 --- a/src/ru/pulsar/jenkins/library/steps/CoverageCleanup.groovy +++ b/src/ru/pulsar/jenkins/library/steps/CoverageCleanup.groovy @@ -10,8 +10,6 @@ class CoverageCleanup implements Serializable { private final JobConfiguration config private final String stageName - private String encoding = 'UTF-8' - CoverageCleanup(JobConfiguration config, String stageName = "") { this.config = config this.stageName = stageName @@ -39,9 +37,14 @@ class CoverageCleanup implements Serializable { if (steps.isUnix()) { command = "kill $pids" } else { - def pidsForCmd = pids.split(" ") - .each { it -> "/PID $it" } - .join(" ") + def pidsForCmd = '' + def pidsArray = pids.split(" ") + + pidsArray.each { + pidsForCmd += "/PID $it" + } + pidsForCmd = pidsForCmd.trim() + command = "taskkill $pidsForCmd /F" } steps.cmd(command, true, false) From ad3b37e840ad65d85f7dfdb2b5fdbf655a36fc2f Mon Sep 17 00:00:00 2001 From: Dima Date: Sun, 15 Dec 2024 15:34:54 +0300 Subject: [PATCH 089/112] upd README.md --- README.md | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5f316d79..6aa2fff0 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,6 @@ 1. При использовании EDT версии 2024.1.0 и выше вместо ring используется 1cedtcli, который должен быть прописан в PATH на агенте. 1. Для запуска шагов, работающих с 1С (подготовка, синтаксический контроль и т.д.) требуется агент с меткой, совпадающей со значением в поле `v8version` файла конфигурации. 1. В качестве ИБ используется файловая база, создаваемая в каталоге `./build/ib`. При необходимости вы можете создать пользователей на фазе инициализации ИБ. -1. Для замеров покрытия на агентах должны быть установлены [Coverage41C](https://github.com/1c-syntax/Coverage41C), EDT и сервер отладки dbgs. Вместо установки EDT целиком можно использовать только отдельные ее компоненты, см. [Coverage41C/README.md](https://github.com/1c-syntax/Coverage41C). 1. На данный момент ошибка в [vanessa-add](https://github.com/vanessa-opensource/add/issues/1152) не позволяет собирать замеры производительности в дымовых тестах по открытию всех форм на клиенте тестирования. 1. Для параллельного выполнения шагов `bdd` и `smoke` с включенными замерами покрытия на одной ноде необходимо, чтобы в `jobConfiguration.json` были указаны **разные** порты сервера отладки для каждого шага. Параллельные билды с замерами покрытия на одной ноде не поддерживаются. @@ -248,3 +247,61 @@ pipeline1C() * При использовании 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`: +``` +"default": { + "--additional": "/debug -http -attach /debuggerURL http://localhost:1550" +} +``` + +Для `smoke` (после исправления ошибки в vanessa-add): +``` +"xunit": { + "--testclient-additional": "/debug -http -attach /debuggerURL http://localhost:1550" +} +``` + +* При изменении портов отладки в jobConfiguration.json не забывайте менять порты в настройках соответствующих шагов (и наоборот) +* Настоятельно рекомендуется использовать не "постоянные" агенты Jenkins, а контейнеры docker. При выполнении билдов в контейнерах можно использовать исключительно стандартный порт 1550. From db2f14381b38fff44f86e17592099a09967b017a Mon Sep 17 00:00:00 2001 From: Dima Ovcharenko Date: Sun, 15 Dec 2024 15:51:32 +0300 Subject: [PATCH 090/112] Apply suggestions from code review Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- .../jenkins/library/StepExecutor.groovy | 9 +++- .../library/utils/CoverageUtils.groovy | 45 ++++++++++++------- 2 files changed, 37 insertions(+), 17 deletions(-) diff --git a/src/ru/pulsar/jenkins/library/StepExecutor.groovy b/src/ru/pulsar/jenkins/library/StepExecutor.groovy index 8309af63..d02bbfc9 100644 --- a/src/ru/pulsar/jenkins/library/StepExecutor.groovy +++ b/src/ru/pulsar/jenkins/library/StepExecutor.groovy @@ -77,7 +77,14 @@ class StepExecutor implements IStepExecutor { @Override void start(String executable, String params) { - steps.start(executable, 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 diff --git a/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy b/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy index 46acc729..c9fd3a64 100644 --- a/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy +++ b/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy @@ -17,7 +17,7 @@ class CoverageUtils { def script if (steps.isUnix()) { - script = "ps -aux | grep '$name' | grep -v grep | awk '{print \$2}'" + script = "ps -C '$name' -o pid=" pids = steps.sh(script, false, true, 'UTF-8') } else { script = """@echo off @@ -87,6 +87,9 @@ class CoverageUtils { } static String findDbgs(IStepExecutor steps, JobConfiguration config) { + if (steps == null || config == null) { + throw new IllegalArgumentException("Некорректные параметры поиска dbgs") + } String dbgsPath = config.coverageOptions.dbgsPath if (!dbgsPath.isEmpty()) { @@ -94,22 +97,32 @@ class CoverageUtils { return dbgsPath.strip() } - def dbgsFindScript = steps.libraryResource("dbgs.os") - final dbgsFindScriptPath = "build/dbgs.os" - final dbgsPathResult = "build/dbgsPath" - steps.writeFile(dbgsFindScriptPath, dbgsFindScript, 'UTF-8') - - steps.cmd("oscript ${dbgsFindScriptPath} ${config.v8version} > ${dbgsPathResult}", false, false) - - dbgsPath = steps.readFile(dbgsPathResult).strip() - - if (dbgsPath.isEmpty()) { - steps.error("Не удалось найти путь к dbgs") + final dbgsFindScriptPath = "build/tmp/dbgs_${System.currentTimeMillis()}.os" + final dbgsPathResult = "build/tmp/dbgsPath_${System.currentTimeMillis()}" + + try { + def dbgsFindScript = steps.libraryResource("dbgs.os") + if (!steps.writeFile(dbgsFindScriptPath, dbgsFindScript, 'UTF-8')) { + throw new IOException("Не удалось записать скрипт поиска dbgs") + } + + steps.cmd("oscript ${dbgsFindScriptPath} ${config.v8version} > ${dbgsPathResult}") + dbgsPath = steps.readFile(dbgsPathResult).strip() + + if (dbgsPath.isEmpty()) { + steps.error("Не удалось найти путь к dbgs") + } + + Logger.println("Found dbgs: ${dbgsPath}") + return dbgsPath + } finally { + try { + steps.deleteFile(dbgsFindScriptPath) + steps.deleteFile(dbgsPathResult) + } catch (Exception e) { + Logger.println("Не удалось удалить временные файлы: ${e.message}") + } } - - Logger.println("Found dbgs: ${dbgsPath}") - return dbgsPath - } } From 326abf1ede102bcf93c135464f7e1fc9da6e6c03 Mon Sep 17 00:00:00 2001 From: Dima Date: Sun, 15 Dec 2024 16:15:16 +0300 Subject: [PATCH 091/112] always return 0 --- src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy b/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy index c9fd3a64..cb53b4a4 100644 --- a/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy +++ b/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy @@ -17,7 +17,7 @@ class CoverageUtils { def script if (steps.isUnix()) { - script = "ps -C '$name' -o pid=" + script = "ps -C '$name' -o pid= || true" pids = steps.sh(script, false, true, 'UTF-8') } else { script = """@echo off From 9f816d69316f2dab518d32c510d30b1141aadb39 Mon Sep 17 00:00:00 2001 From: Dima Date: Sun, 15 Dec 2024 16:40:03 +0300 Subject: [PATCH 092/112] revert deletion of tmp files, translate log messages --- .../library/utils/CoverageUtils.groovy | 37 +++++++------------ 1 file changed, 14 insertions(+), 23 deletions(-) diff --git a/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy b/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy index cb53b4a4..cc73017c 100644 --- a/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy +++ b/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy @@ -93,36 +93,27 @@ class CoverageUtils { String dbgsPath = config.coverageOptions.dbgsPath if (!dbgsPath.isEmpty()) { - Logger.println("Using dbgsPath from config: $dbgsPath") + Logger.println("Использую путь к dbgs и параметра dbgsPath: $dbgsPath") return dbgsPath.strip() } final dbgsFindScriptPath = "build/tmp/dbgs_${System.currentTimeMillis()}.os" final dbgsPathResult = "build/tmp/dbgsPath_${System.currentTimeMillis()}" - try { - def dbgsFindScript = steps.libraryResource("dbgs.os") - if (!steps.writeFile(dbgsFindScriptPath, dbgsFindScript, 'UTF-8')) { - throw new IOException("Не удалось записать скрипт поиска dbgs") - } - - steps.cmd("oscript ${dbgsFindScriptPath} ${config.v8version} > ${dbgsPathResult}") - dbgsPath = steps.readFile(dbgsPathResult).strip() - - if (dbgsPath.isEmpty()) { - steps.error("Не удалось найти путь к dbgs") - } - - Logger.println("Found dbgs: ${dbgsPath}") - return dbgsPath - } finally { - try { - steps.deleteFile(dbgsFindScriptPath) - steps.deleteFile(dbgsPathResult) - } catch (Exception e) { - Logger.println("Не удалось удалить временные файлы: ${e.message}") - } + def dbgsFindScript = steps.libraryResource("dbgs.os") + if (!steps.writeFile(dbgsFindScriptPath, dbgsFindScript, 'UTF-8')) { + throw new IOException("Не удалось записать скрипт поиска dbgs") } + + steps.cmd("oscript ${dbgsFindScriptPath} ${config.v8version} > ${dbgsPathResult}") + dbgsPath = steps.readFile(dbgsPathResult).strip() + + if (dbgsPath.isEmpty()) { + steps.error("Не удалось найти путь к dbgs") + } + + Logger.println("Найден путь к dbgs: ${dbgsPath}") + return dbgsPath } } From 4d82101846bec9d6a1153cd0e4a282e636bc846b Mon Sep 17 00:00:00 2001 From: Nikita Fedkin Date: Sun, 15 Dec 2024 15:58:49 +0100 Subject: [PATCH 093/112] Update src/ru/pulsar/jenkins/library/steps/CoverageContext.groovy --- src/ru/pulsar/jenkins/library/steps/CoverageContext.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ru/pulsar/jenkins/library/steps/CoverageContext.groovy b/src/ru/pulsar/jenkins/library/steps/CoverageContext.groovy index 5d7d9eec..f018dfac 100644 --- a/src/ru/pulsar/jenkins/library/steps/CoverageContext.groovy +++ b/src/ru/pulsar/jenkins/library/steps/CoverageContext.groovy @@ -12,7 +12,7 @@ class CoverageContext { ArrayList dbgsPids ArrayList coverage41CPids - CoverageContext(String lockableResource, String srcDir, GlobalCoverageOptions coverageOptions, int port, ArrayList dbgsPids, ArrayList coverage41CPids) { + CoverageContext(String lockableResource, String srcDir, GlobalCoverageOptions coverageOptions, int port, List dbgsPids, List coverage41CPids) { this.lockableResource = lockableResource this.srcDir = srcDir this.coverageOptions = coverageOptions From c7cb9796b15ba54fc83651ca4fc7c2e72ddae52e Mon Sep 17 00:00:00 2001 From: Nikita Fedkin Date: Sun, 15 Dec 2024 16:00:38 +0100 Subject: [PATCH 094/112] Apply suggestions from code review --- src/ru/pulsar/jenkins/library/steps/CoverageContext.groovy | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ru/pulsar/jenkins/library/steps/CoverageContext.groovy b/src/ru/pulsar/jenkins/library/steps/CoverageContext.groovy index f018dfac..06e1ca7d 100644 --- a/src/ru/pulsar/jenkins/library/steps/CoverageContext.groovy +++ b/src/ru/pulsar/jenkins/library/steps/CoverageContext.groovy @@ -8,9 +8,9 @@ class CoverageContext { String srcDir GlobalCoverageOptions coverageOptions int port - ArrayList pids - ArrayList dbgsPids - ArrayList coverage41CPids + List pids + List dbgsPids + List coverage41CPids CoverageContext(String lockableResource, String srcDir, GlobalCoverageOptions coverageOptions, int port, List dbgsPids, List coverage41CPids) { this.lockableResource = lockableResource From c01f42dd22cdfc2850ce34fe923377096661af6d Mon Sep 17 00:00:00 2001 From: Dima Date: Sun, 15 Dec 2024 18:28:55 +0300 Subject: [PATCH 095/112] rm exception --- src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy b/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy index cc73017c..9054292e 100644 --- a/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy +++ b/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy @@ -93,7 +93,7 @@ class CoverageUtils { String dbgsPath = config.coverageOptions.dbgsPath if (!dbgsPath.isEmpty()) { - Logger.println("Использую путь к dbgs и параметра dbgsPath: $dbgsPath") + Logger.println("Использую путь к dbgs из параметра dbgsPath: $dbgsPath") return dbgsPath.strip() } @@ -101,9 +101,7 @@ class CoverageUtils { final dbgsPathResult = "build/tmp/dbgsPath_${System.currentTimeMillis()}" def dbgsFindScript = steps.libraryResource("dbgs.os") - if (!steps.writeFile(dbgsFindScriptPath, dbgsFindScript, 'UTF-8')) { - throw new IOException("Не удалось записать скрипт поиска dbgs") - } + steps.writeFile(dbgsFindScriptPath, dbgsFindScript, 'UTF-8') steps.cmd("oscript ${dbgsFindScriptPath} ${config.v8version} > ${dbgsPathResult}") dbgsPath = steps.readFile(dbgsPathResult).strip() From 25dc5e412ca883ed1c9f3b3a121427c02fea7072 Mon Sep 17 00:00:00 2001 From: Dima Date: Sun, 15 Dec 2024 21:01:01 +0300 Subject: [PATCH 096/112] fix quotes --- src/ru/pulsar/jenkins/library/steps/Start.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ru/pulsar/jenkins/library/steps/Start.groovy b/src/ru/pulsar/jenkins/library/steps/Start.groovy index 3c193b6b..5636ceaa 100644 --- a/src/ru/pulsar/jenkins/library/steps/Start.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Start.groovy @@ -20,7 +20,7 @@ class Start implements Serializable { 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) + 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) } From ba1dd4606da94ebbb0afc572177eefe569b88a42 Mon Sep 17 00:00:00 2001 From: Dima Date: Mon, 16 Dec 2024 10:18:51 +0300 Subject: [PATCH 097/112] refactor coverage cleanup --- .../pulsar/jenkins/library/steps/Bdd.groovy | 4 ++ .../jenkins/library/steps/Coverable.groovy | 1 + .../library/steps/CoverageCleanup.groovy | 52 ------------------- .../jenkins/library/steps/SmokeTest.groovy | 4 ++ .../jenkins/library/steps/WithCoverage.groovy | 51 ++++++++++++++---- .../jenkins/library/steps/Yaxunit.groovy | 4 ++ .../library/utils/CoverageUtils.groovy | 8 +-- vars/coverageCleanup.groovy | 11 ---- vars/pipeline1C.groovy | 15 ------ 9 files changed, 56 insertions(+), 94 deletions(-) delete mode 100644 src/ru/pulsar/jenkins/library/steps/CoverageCleanup.groovy delete mode 100644 vars/coverageCleanup.groovy diff --git a/src/ru/pulsar/jenkins/library/steps/Bdd.groovy b/src/ru/pulsar/jenkins/library/steps/Bdd.groovy index 057bbad7..66810844 100644 --- a/src/ru/pulsar/jenkins/library/steps/Bdd.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Bdd.groovy @@ -61,6 +61,10 @@ class Bdd implements Serializable, Coverable { } + String getStageSlug() { + return "bdd" + } + String getCoverageStashPath() { return COVERAGE_STASH_PATH } diff --git a/src/ru/pulsar/jenkins/library/steps/Coverable.groovy b/src/ru/pulsar/jenkins/library/steps/Coverable.groovy index 0dbfdd92..ca6473e2 100644 --- a/src/ru/pulsar/jenkins/library/steps/Coverable.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Coverable.groovy @@ -2,6 +2,7 @@ package ru.pulsar.jenkins.library.steps interface Coverable { + String getStageSlug(); String getCoverageStashPath(); String getCoverageStashName(); String getCoveragePidsPath(); diff --git a/src/ru/pulsar/jenkins/library/steps/CoverageCleanup.groovy b/src/ru/pulsar/jenkins/library/steps/CoverageCleanup.groovy deleted file mode 100644 index 7d7c9332..00000000 --- a/src/ru/pulsar/jenkins/library/steps/CoverageCleanup.groovy +++ /dev/null @@ -1,52 +0,0 @@ -package ru.pulsar.jenkins.library.steps - -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.Logger - -class CoverageCleanup implements Serializable { - - private final JobConfiguration config - private final String stageName - - CoverageCleanup(JobConfiguration config, String stageName = "") { - this.config = config - this.stageName = stageName - } - - def run() { - IStepExecutor steps = ContextRegistry.getContext().getStepExecutor() - - Logger.printLocation() - - String pidsFilePath = "build${File.separator}${stageName}-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" - } else { - def pidsForCmd = '' - def pidsArray = pids.split(" ") - - pidsArray.each { - pidsForCmd += "/PID $it" - } - pidsForCmd = pidsForCmd.trim() - - command = "taskkill $pidsForCmd /F" - } - steps.cmd(command, true, false) - } -} diff --git a/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy b/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy index f2f86137..31fa236c 100644 --- a/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy +++ b/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy @@ -121,6 +121,10 @@ class SmokeTest implements Serializable, Coverable { } } + String getStageSlug() { + return "bdd" + } + String getCoverageStashPath() { return COVERAGE_STASH_PATH } diff --git a/src/ru/pulsar/jenkins/library/steps/WithCoverage.groovy b/src/ru/pulsar/jenkins/library/steps/WithCoverage.groovy index f78be6cd..a1a34ce5 100644 --- a/src/ru/pulsar/jenkins/library/steps/WithCoverage.groovy +++ b/src/ru/pulsar/jenkins/library/steps/WithCoverage.groovy @@ -5,6 +5,7 @@ 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.CoverageUtils +import ru.pulsar.jenkins.library.utils.Logger class WithCoverage implements Serializable { @@ -22,28 +23,58 @@ class WithCoverage implements Serializable { def run() { - def context = CoverageUtils.prepareContext(config, coverageOptions) + if (!coverageOptions.coverage) { + body() + return + } + def context = CoverageUtils.prepareContext(config, coverageOptions) IStepExecutor steps = ContextRegistry.getContext().getStepExecutor() - //noinspection GroovyMissingReturnStatement steps.lock(context.lockableResource) { try { - if (coverageOptions.coverage) { - CoverageUtils.startCoverage(steps, config, context, stage) - } + + CoverageUtils.startCoverage(steps, config, context, stage) body() + + steps.stash(stage.getCoverageStashName(), stage.getCoverageStashPath(), true) + } catch (Exception e) { throw new Exception("При выполнении блока произошла ошибка: ${e}") } finally { - if (coverageOptions.coverage) { - CoverageUtils.stopCoverage(steps, config, context) + + CoverageUtils.stopCoverage(steps, config, context) + + String pidsFilePath = "build/${stage.getStageSlug()}-pids" + + def pids = "" + if (steps.fileExists(pidsFilePath)) { + pids = steps.readFile(pidsFilePath) } - } - if (coverageOptions.coverage) { - steps.stash(stage.getCoverageStashName(), stage.getCoverageStashPath(), true) + 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) } } } diff --git a/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy b/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy index e6f657a9..fb24ec5e 100644 --- a/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy @@ -96,6 +96,10 @@ class Yaxunit implements Serializable, Coverable { } } + String getStageSlug() { + return "yaxunit" + } + String getCoverageStashPath() { return COVERAGE_STASH_PATH } diff --git a/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy b/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy index 9054292e..28700eef 100644 --- a/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy +++ b/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy @@ -1,6 +1,5 @@ package ru.pulsar.jenkins.library.utils -import org.apache.commons.lang3.RandomStringUtils import ru.pulsar.jenkins.library.IStepExecutor import ru.pulsar.jenkins.library.configuration.JobConfiguration import ru.pulsar.jenkins.library.configuration.StepCoverageOptions @@ -42,10 +41,7 @@ class CoverageUtils { def port = options.dbgsPort def currentDbgsPids = getPIDs("dbgs") def currentCoverage41CPids = getPIDs("Coverage41C") - def lockableResource = RandomStringUtils.random(9, true, false) - if (options.coverage) { - lockableResource = "${env.NODE_NAME}_$port" - } + def lockableResource = "${env.NODE_NAME}_$port" return new CoverageContext(lockableResource, config.srcDir, coverageOpts, port, currentDbgsPids, currentCoverage41CPids) @@ -76,7 +72,7 @@ class CoverageUtils { steps.writeFile(stage.getCoveragePidsPath(), pids, 'UTF-8') - Logger.println("Coverage PIDs for cleanup: $pids") + Logger.println("PID процессов dbgs и Coverage41C для ${stage.getStageSlug()}: $pids") } static void stopCoverage(IStepExecutor steps, JobConfiguration config, CoverageContext coverageContext) { diff --git a/vars/coverageCleanup.groovy b/vars/coverageCleanup.groovy deleted file mode 100644 index 92fe3458..00000000 --- a/vars/coverageCleanup.groovy +++ /dev/null @@ -1,11 +0,0 @@ -import ru.pulsar.jenkins.library.configuration.JobConfiguration -import ru.pulsar.jenkins.library.ioc.ContextRegistry -import ru.pulsar.jenkins.library.steps.CoverageCleanup - -def call(JobConfiguration config, String stageName) { - ContextRegistry.registerDefaultContext(this) - - def coverageCleanup = new CoverageCleanup(config, stageName) - coverageCleanup.run() - -} \ No newline at end of file diff --git a/vars/pipeline1C.groovy b/vars/pipeline1C.groovy index fd2e5e21..867e3830 100644 --- a/vars/pipeline1C.groovy +++ b/vars/pipeline1C.groovy @@ -236,11 +236,6 @@ void call() { bdd config } } - post { - cleanup { - coverageCleanup config, 'bdd' - } - } } } } @@ -293,11 +288,6 @@ void call() { smoke config } } - post { - cleanup { - coverageCleanup config, 'smoke' - } - } } } } @@ -335,11 +325,6 @@ void call() { yaxunit config } } - post { - cleanup { - coverageCleanup config, 'yaxunit' - } - } } } } From 28e38baf831fff963a9cbfeb59fa6dc320966508 Mon Sep 17 00:00:00 2001 From: Dima Date: Mon, 16 Dec 2024 13:35:03 +0300 Subject: [PATCH 098/112] fix stop --- src/ru/pulsar/jenkins/library/steps/WithCoverage.groovy | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ru/pulsar/jenkins/library/steps/WithCoverage.groovy b/src/ru/pulsar/jenkins/library/steps/WithCoverage.groovy index a1a34ce5..d1a6b800 100644 --- a/src/ru/pulsar/jenkins/library/steps/WithCoverage.groovy +++ b/src/ru/pulsar/jenkins/library/steps/WithCoverage.groovy @@ -38,14 +38,14 @@ class WithCoverage implements Serializable { body() + CoverageUtils.stopCoverage(steps, config, context) + steps.stash(stage.getCoverageStashName(), stage.getCoverageStashPath(), true) } catch (Exception e) { throw new Exception("При выполнении блока произошла ошибка: ${e}") } finally { - CoverageUtils.stopCoverage(steps, config, context) - String pidsFilePath = "build/${stage.getStageSlug()}-pids" def pids = "" From f670490e2ebfb2f09d3abe73a19e732c53c9257c Mon Sep 17 00:00:00 2001 From: Dima Date: Mon, 16 Dec 2024 18:13:04 +0300 Subject: [PATCH 099/112] fix slug --- src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy b/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy index 31fa236c..b19a1f08 100644 --- a/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy +++ b/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy @@ -122,7 +122,7 @@ class SmokeTest implements Serializable, Coverable { } String getStageSlug() { - return "bdd" + return "smoke" } String getCoverageStashPath() { From ed94c8449d1eb043b0c9d8a938d1462972b0a384 Mon Sep 17 00:00:00 2001 From: Dima Date: Mon, 16 Dec 2024 18:16:19 +0300 Subject: [PATCH 100/112] rm archiveArtifacts --- src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy b/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy index fb24ec5e..5f84a499 100644 --- a/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy @@ -91,8 +91,6 @@ class Yaxunit implements Serializable, Coverable { steps.stash(YAXUNIT_ALLURE_STASH, "$allureReportDir/**", true) } - steps.archiveArtifacts("build/out/yaxunit/junit.xml") - } } From 102ad0a624fa12c03b73c56acf9107188d931c93 Mon Sep 17 00:00:00 2001 From: Dima Date: Mon, 16 Dec 2024 18:18:31 +0300 Subject: [PATCH 101/112] upd README.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 6aa2fff0..7111902d 100644 --- a/README.md +++ b/README.md @@ -290,6 +290,8 @@ jobConfiguration.json ``` Для `yaxunit`: + +./tools/vrunner.json ``` "default": { "--additional": "/debug -http -attach /debuggerURL http://localhost:1550" @@ -297,6 +299,8 @@ jobConfiguration.json ``` Для `smoke` (после исправления ошибки в vanessa-add): + +./tools/vrunner.json ``` "xunit": { "--testclient-additional": "/debug -http -attach /debuggerURL http://localhost:1550" From bcc368cb054c1693fe834a142102ac2ece34b394 Mon Sep 17 00:00:00 2001 From: Dima Date: Mon, 16 Dec 2024 18:22:41 +0300 Subject: [PATCH 102/112] merge classes --- .../jenkins/library/steps/WithCoverage.groovy | 114 +++++++++++++++++- .../library/utils/CoverageUtils.groovy | 113 ----------------- 2 files changed, 109 insertions(+), 118 deletions(-) delete mode 100644 src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy diff --git a/src/ru/pulsar/jenkins/library/steps/WithCoverage.groovy b/src/ru/pulsar/jenkins/library/steps/WithCoverage.groovy index d1a6b800..f1542a75 100644 --- a/src/ru/pulsar/jenkins/library/steps/WithCoverage.groovy +++ b/src/ru/pulsar/jenkins/library/steps/WithCoverage.groovy @@ -4,7 +4,7 @@ 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.CoverageUtils +import ru.pulsar.jenkins.library.utils.FileUtils import ru.pulsar.jenkins.library.utils.Logger class WithCoverage implements Serializable { @@ -28,22 +28,23 @@ class WithCoverage implements Serializable { return } - def context = CoverageUtils.prepareContext(config, coverageOptions) + def context = prepareContext(config, coverageOptions) IStepExecutor steps = ContextRegistry.getContext().getStepExecutor() steps.lock(context.lockableResource) { try { - CoverageUtils.startCoverage(steps, config, context, stage) + startCoverage(steps, config, context, stage) body() - CoverageUtils.stopCoverage(steps, config, context) + stopCoverage(steps, config, context) steps.stash(stage.getCoverageStashName(), stage.getCoverageStashPath(), true) } catch (Exception e) { - throw new Exception("При выполнении блока произошла ошибка: ${e}") + Logger.println("При выполнении блока произошла ошибка: ${e.message}") + throw e } finally { String pidsFilePath = "build/${stage.getStageSlug()}-pids" @@ -78,4 +79,107 @@ class WithCoverage implements Serializable { } } } + + 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/utils/CoverageUtils.groovy b/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy deleted file mode 100644 index 28700eef..00000000 --- a/src/ru/pulsar/jenkins/library/utils/CoverageUtils.groovy +++ /dev/null @@ -1,113 +0,0 @@ -package ru.pulsar.jenkins.library.utils - -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.steps.Coverable -import ru.pulsar.jenkins.library.steps.CoverageContext - -class CoverageUtils { - 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 - } - -} From 92bff7aabb7a2045692641940f612ea570b16e5d Mon Sep 17 00:00:00 2001 From: Dima Ovcharenko Date: Mon, 16 Dec 2024 18:43:52 +0300 Subject: [PATCH 103/112] Update src/ru/pulsar/jenkins/library/steps/WithCoverage.groovy Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- src/ru/pulsar/jenkins/library/steps/WithCoverage.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ru/pulsar/jenkins/library/steps/WithCoverage.groovy b/src/ru/pulsar/jenkins/library/steps/WithCoverage.groovy index f1542a75..2909a3f1 100644 --- a/src/ru/pulsar/jenkins/library/steps/WithCoverage.groovy +++ b/src/ru/pulsar/jenkins/library/steps/WithCoverage.groovy @@ -68,7 +68,7 @@ class WithCoverage implements Serializable { def pidsArray = pids.split(" ") pidsArray.each { - pidsForCmd += "/PID $it" + pidsForCmd += " /PID $it" } pidsForCmd = pidsForCmd.trim() From 1650db1596c0217994e03a23c61b33913445fa63 Mon Sep 17 00:00:00 2001 From: Dima Ovcharenko Date: Mon, 16 Dec 2024 19:04:48 +0300 Subject: [PATCH 104/112] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 7111902d..91a0fbfb 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,7 @@ 1. В качестве ИБ используется файловая база, создаваемая в каталоге `./build/ib`. При необходимости вы можете создать пользователей на фазе инициализации ИБ. 1. На данный момент ошибка в [vanessa-add](https://github.com/vanessa-opensource/add/issues/1152) не позволяет собирать замеры производительности в дымовых тестах по открытию всех форм на клиенте тестирования. 1. Для параллельного выполнения шагов `bdd` и `smoke` с включенными замерами покрытия на одной ноде необходимо, чтобы в `jobConfiguration.json` были указаны **разные** порты сервера отладки для каждого шага. Параллельные билды с замерами покрытия на одной ноде не поддерживаются. +1. Coverage41C не запускается в Windows на мастер-ноде Jenkins, для его корректной работы нужно запустить и настроить агент Jenkins и выполнять сборки на нем. ## Возможности From 8d98e1db42a4dc7e5433729eff1439c306585143 Mon Sep 17 00:00:00 2001 From: Dima Ovcharenko Date: Mon, 16 Dec 2024 20:43:56 +0300 Subject: [PATCH 105/112] Update README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 91a0fbfb..2e5d13bb 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,9 @@ 1. В качестве ИБ используется файловая база, создаваемая в каталоге `./build/ib`. При необходимости вы можете создать пользователей на фазе инициализации ИБ. 1. На данный момент ошибка в [vanessa-add](https://github.com/vanessa-opensource/add/issues/1152) не позволяет собирать замеры производительности в дымовых тестах по открытию всех форм на клиенте тестирования. 1. Для параллельного выполнения шагов `bdd` и `smoke` с включенными замерами покрытия на одной ноде необходимо, чтобы в `jobConfiguration.json` были указаны **разные** порты сервера отладки для каждого шага. Параллельные билды с замерами покрытия на одной ноде не поддерживаются. -1. Coverage41C не запускается в Windows на мастер-ноде Jenkins, для его корректной работы нужно запустить и настроить агент Jenkins и выполнять сборки на нем. +1. Для сборов замеров покрытия в ОС Windows на мастер-ноде Jenkins, который запущен как служба под учетной записью LOCAL SYSTEM, необходимо использовать версию Coverage41C > 2.7.2. Обратите внимание, именно `больше`, а не `больше или равно`. На данный момент такой сборки не существует. Другие варианты обхода проблемы: + 1. запустить службу Jenkins под обычной учетной записью + 1. запретить выполнение сборок на мастер-ноде и настроить их выполнение на агенте, который запущен интерактивно под обычной учетной записью (рекомендуется). ## Возможности From fd34d56da596abd931badaf30ccebcd30b6ca1d9 Mon Sep 17 00:00:00 2001 From: Dima Ovcharenko Date: Mon, 16 Dec 2024 22:49:22 +0300 Subject: [PATCH 106/112] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2e5d13bb..f9a7e4d3 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ 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.2. Обратите внимание, именно `больше`, а не `больше или равно`. На данный момент такой сборки не существует. Другие варианты обхода проблемы: +1. Для сборов замеров покрытия в ОС Windows на мастер-ноде Jenkins, который запущен как служба под учетной записью LOCAL SYSTEM, необходимо использовать версию Coverage41C >= 2.7.3. Другие варианты обхода проблемы: 1. запустить службу Jenkins под обычной учетной записью 1. запретить выполнение сборок на мастер-ноде и настроить их выполнение на агенте, который запущен интерактивно под обычной учетной записью (рекомендуется). From 07409878ee83c8e6db35a036704ec6c18e71d675 Mon Sep 17 00:00:00 2001 From: Nikita Fedkin Date: Thu, 19 Dec 2024 23:16:11 +0100 Subject: [PATCH 107/112] Update gdsl --- src/idea.gdsl | 629 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 474 insertions(+), 155 deletions(-) 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() +} From 917b5d77905f50ebe5c2a789cd7f02cd91abbe77 Mon Sep 17 00:00:00 2001 From: Nikita Fedkin Date: Thu, 19 Dec 2024 23:16:49 +0100 Subject: [PATCH 108/112] JSON lf --- .gitattributes | 1 + resources/schema.json | 988 +++++++++++++++++++++--------------------- 2 files changed, 495 insertions(+), 494 deletions(-) diff --git a/.gitattributes b/.gitattributes index 37ebb32a..df0797a4 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,3 +1,4 @@ *.groovy eol=lf +*.json eol=lf *.md eol=lf *.os eol=lf diff --git a/resources/schema.json b/resources/schema.json index dd9fdb67..5e03b5db 100644 --- a/resources/schema.json +++ b/resources/schema.json @@ -1,495 +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" : { - "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" - } - } +{ + "$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 From 62d6b3beae2c771620643e31a89f70d0628c2d0e Mon Sep 17 00:00:00 2001 From: Nikita Fedkin Date: Thu, 19 Dec 2024 23:17:01 +0100 Subject: [PATCH 109/112] @Override --- src/ru/pulsar/jenkins/library/steps/Bdd.groovy | 3 +++ src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy | 4 ++++ src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy | 3 +++ 3 files changed, 10 insertions(+) diff --git a/src/ru/pulsar/jenkins/library/steps/Bdd.groovy b/src/ru/pulsar/jenkins/library/steps/Bdd.groovy index 66810844..510980c4 100644 --- a/src/ru/pulsar/jenkins/library/steps/Bdd.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Bdd.groovy @@ -61,10 +61,12 @@ class Bdd implements Serializable, Coverable { } + @Override String getStageSlug() { return "bdd" } + @Override String getCoverageStashPath() { return COVERAGE_STASH_PATH } @@ -74,6 +76,7 @@ class Bdd implements Serializable, Coverable { return COVERAGE_STASH_NAME } + @Override String getCoveragePidsPath() { return COVERAGE_PIDS_PATH } diff --git a/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy b/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy index b19a1f08..40764c53 100644 --- a/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy +++ b/src/ru/pulsar/jenkins/library/steps/SmokeTest.groovy @@ -121,18 +121,22 @@ class SmokeTest implements Serializable, Coverable { } } + @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/Yaxunit.groovy b/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy index 5f84a499..317059e0 100644 --- a/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy @@ -94,10 +94,12 @@ class Yaxunit implements Serializable, Coverable { } } + @Override String getStageSlug() { return "yaxunit" } + @Override String getCoverageStashPath() { return COVERAGE_STASH_PATH } @@ -107,6 +109,7 @@ class Yaxunit implements Serializable, Coverable { return COVERAGE_STASH_NAME } + @Override String getCoveragePidsPath() { return COVERAGE_PIDS_PATH } From 4d1ce5425bf2a2dfc36f2ff478375ac8c353e848 Mon Sep 17 00:00:00 2001 From: Nikita Fedkin Date: Thu, 19 Dec 2024 23:17:15 +0100 Subject: [PATCH 110/112] Cleanup --- src/JobConfigurationSchemaGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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)); From 42bbfc7fbc6c79ecb1b7cf0ad68ba5448e23e8a7 Mon Sep 17 00:00:00 2001 From: Nikita Fedkin Date: Thu, 19 Dec 2024 23:17:26 +0100 Subject: [PATCH 111/112] More tests --- .../ConfigurationReaderTest.java | 7 +- .../jenkins/library/utils/EnvUtils.java | 1 + test/unit/resources/jobConfiguration.json | 188 +++++++++--------- 3 files changed, 104 insertions(+), 92 deletions(-) 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 6886e7a0..07e5c37a 100644 --- a/test/unit/groovy/ru/pulsar/jenkins/library/configuration/ConfigurationReaderTest.java +++ b/test/unit/groovy/ru/pulsar/jenkins/library/configuration/ConfigurationReaderTest.java @@ -60,7 +60,10 @@ 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()).isFalse(); + 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"); @@ -118,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 c7682c79..48dfb6fd 100644 --- a/test/unit/resources/jobConfiguration.json +++ b/test/unit/resources/jobConfiguration.json @@ -1,91 +1,99 @@ -{ - "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 - }, - "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 From c8d5012b777c67210eb6cc596136d9becc68e057 Mon Sep 17 00:00:00 2001 From: Nikita Fedkin Date: Thu, 19 Dec 2024 23:27:35 +0100 Subject: [PATCH 112/112] LF --- resources/globalConfiguration.json | 316 +++++++++--------- .../resources/jobConfiguration.json | 34 +- 2 files changed, 175 insertions(+), 175 deletions(-) diff --git a/resources/globalConfiguration.json b/resources/globalConfiguration.json index 58db158c..7e0e6e01 100644 --- a/resources/globalConfiguration.json +++ b/resources/globalConfiguration.json @@ -1,158 +1,158 @@ -{ - "$schema": "schema.json", - "v8version": "8.3", - "edtVersion": "", - "srcDir": "src/cf", - "sourceFormat": "designer", - "defaultBranch": "main", - "secrets": { - "storagePath": "UNKNOWN_ID", - "storage": "UNKNOWN_ID", - "telegramBotToken": "UNKNOWN_ID", - "telegramChatId": "UNKNOWN_ID" - }, - "stages": { - "initSteps": false, - "sonarqube": false, - "bdd": false, - "syntaxCheck": false, - "edtValidate": false, - "smoke": false, - "yaxunit": false, - "email": false, - "telegram": false - }, - "timeout": { - "smoke": 240, - "yaxunit": 240, - "bdd": 120, - "getBinaries": 60, - "createInfoBase": 60, - "loadConfiguration": 60, - "designerToEdtFormatTransformation": 60, - "edtToDesignerFormatTransformation": 60, - "edtValidate": 240, - "initInfoBase": 60, - "loadExtensions": 60, - "resultTransformation": 10, - "sonarqube": 90, - "syntaxCheck": 240, - "zipInfoBase": 60 - }, - "initInfobase": { - "initMethod": "fromStorage", - "runMigration": true, - "additionalInitializationSteps": [], - "templateDBPath": "", - "vrunnerSettings": "./tools/vrunner.json", - "extensions": [] - }, - "bdd": { - "vrunnerSteps": [ - "vanessa --settings ./tools/vrunner.json" - ], - "coverage": false, - "dbgsPort": 1550 - }, - "sonarqube": { - "sonarQubeInstallation": "", - "useSonarScannerFromPath": true, - "sonarScannerToolName": "sonar-scanner", - "infoBaseUpdateModuleName" : "", - "branchAnalysisConfiguration": "fromEnv", - "waitForQualityGate": false - }, - "syntaxCheck": { - "groupErrorsByMetadata": true, - "pathToJUnitReport": "./build/out/jUnit/syntax.xml", - "exceptionFile": "./tools/syntax-check-exception-file.txt", - "checkModes": [ - "-ThinClient", - "-WebClient", - "-Server", - "-ExtendedModulesCheck", - "-IncorrectReferences", - "-UnreferenceProcedures", - "-HandlersExistence", - "-EmptyHandlers", - "-CheckUseModality", - "-CheckUseSynchronousCalls", - "-DistributiveModules" - ], - "vrunnerSettings": "./tools/vrunner.json" - }, - "smoke": { - "vrunnerSettings": "./tools/vrunner.json", - "xddConfigPath": "./tools/xUnitParams.json", - "publishToAllureReport": false, - "publishToJUnitReport": true, - "coverage": false, - "dbgsPort": 1550 - }, - "coverage": { - "dbgsPath": "", - "coverage41CPath": "Coverage41C" - }, - "yaxunit": { - "vrunnerSettings": "./tools/vrunner.json", - "configPath": "./tools/yaxunit.json", - "publishToAllureReport": false, - "publishToJUnitReport": true, - "coverage": false, - "dbgsPort": 1550 - }, - "resultsTransform": { - "transformer": "stebi", - "genericIssueFormat": "Generic_Issue_10_3", - "removeSupport": true, - "supportLevel": 0 - }, - "notifications": { - "email": { - "onAlways": false, - "onFailure": true, - "onUnstable": false, - "onSuccess": false, - "alwaysOptions": { - "attachLog": true, - "directRecipients": [], - "recipientProviders": [ - "developers", - "requestor" - ] - }, - "failureOptions": { - "attachLog": true, - "directRecipients": [], - "recipientProviders": [ - "developers", - "requestor", - "brokenBuildSuspects" - ] - }, - "successOptions": { - "attachLog": false, - "directRecipients": [], - "recipientProviders": [ - "developers", - "requestor" - ] - }, - "unstableOptions": { - "attachLog": false, - "directRecipients": [], - "recipientProviders": [ - "developers", - "requestor" - ] - } - }, - "telegram": { - "onAlways": true, - "onFailure": false, - "onUnstable": false, - "onSuccess": false - } - }, - "logosConfig": "" -} +{ + "$schema": "schema.json", + "v8version": "8.3", + "edtVersion": "", + "srcDir": "src/cf", + "sourceFormat": "designer", + "defaultBranch": "main", + "secrets": { + "storagePath": "UNKNOWN_ID", + "storage": "UNKNOWN_ID", + "telegramBotToken": "UNKNOWN_ID", + "telegramChatId": "UNKNOWN_ID" + }, + "stages": { + "initSteps": false, + "sonarqube": false, + "bdd": false, + "syntaxCheck": false, + "edtValidate": false, + "smoke": false, + "yaxunit": false, + "email": false, + "telegram": false + }, + "timeout": { + "smoke": 240, + "yaxunit": 240, + "bdd": 120, + "getBinaries": 60, + "createInfoBase": 60, + "loadConfiguration": 60, + "designerToEdtFormatTransformation": 60, + "edtToDesignerFormatTransformation": 60, + "edtValidate": 240, + "initInfoBase": 60, + "loadExtensions": 60, + "resultTransformation": 10, + "sonarqube": 90, + "syntaxCheck": 240, + "zipInfoBase": 60 + }, + "initInfobase": { + "initMethod": "fromStorage", + "runMigration": true, + "additionalInitializationSteps": [], + "templateDBPath": "", + "vrunnerSettings": "./tools/vrunner.json", + "extensions": [] + }, + "bdd": { + "vrunnerSteps": [ + "vanessa --settings ./tools/vrunner.json" + ], + "coverage": false, + "dbgsPort": 1550 + }, + "sonarqube": { + "sonarQubeInstallation": "", + "useSonarScannerFromPath": true, + "sonarScannerToolName": "sonar-scanner", + "infoBaseUpdateModuleName" : "", + "branchAnalysisConfiguration": "fromEnv", + "waitForQualityGate": false + }, + "syntaxCheck": { + "groupErrorsByMetadata": true, + "pathToJUnitReport": "./build/out/jUnit/syntax.xml", + "exceptionFile": "./tools/syntax-check-exception-file.txt", + "checkModes": [ + "-ThinClient", + "-WebClient", + "-Server", + "-ExtendedModulesCheck", + "-IncorrectReferences", + "-UnreferenceProcedures", + "-HandlersExistence", + "-EmptyHandlers", + "-CheckUseModality", + "-CheckUseSynchronousCalls", + "-DistributiveModules" + ], + "vrunnerSettings": "./tools/vrunner.json" + }, + "smoke": { + "vrunnerSettings": "./tools/vrunner.json", + "xddConfigPath": "./tools/xUnitParams.json", + "publishToAllureReport": false, + "publishToJUnitReport": true, + "coverage": false, + "dbgsPort": 1550 + }, + "coverage": { + "dbgsPath": "", + "coverage41CPath": "Coverage41C" + }, + "yaxunit": { + "vrunnerSettings": "./tools/vrunner.json", + "configPath": "./tools/yaxunit.json", + "publishToAllureReport": false, + "publishToJUnitReport": true, + "coverage": false, + "dbgsPort": 1550 + }, + "resultsTransform": { + "transformer": "stebi", + "genericIssueFormat": "Generic_Issue_10_3", + "removeSupport": true, + "supportLevel": 0 + }, + "notifications": { + "email": { + "onAlways": false, + "onFailure": true, + "onUnstable": false, + "onSuccess": false, + "alwaysOptions": { + "attachLog": true, + "directRecipients": [], + "recipientProviders": [ + "developers", + "requestor" + ] + }, + "failureOptions": { + "attachLog": true, + "directRecipients": [], + "recipientProviders": [ + "developers", + "requestor", + "brokenBuildSuspects" + ] + }, + "successOptions": { + "attachLog": false, + "directRecipients": [], + "recipientProviders": [ + "developers", + "requestor" + ] + }, + "unstableOptions": { + "attachLog": false, + "directRecipients": [], + "recipientProviders": [ + "developers", + "requestor" + ] + } + }, + "telegram": { + "onAlways": true, + "onFailure": false, + "onUnstable": false, + "onSuccess": false + } + }, + "logosConfig": "" +} diff --git a/test/integration/resources/jobConfiguration.json b/test/integration/resources/jobConfiguration.json index ebd5e6fd..d0739126 100644 --- a/test/integration/resources/jobConfiguration.json +++ b/test/integration/resources/jobConfiguration.json @@ -1,18 +1,18 @@ -{ - "v8version": "8.3.12.1500", - "initInfobase": { - "initMethod": "fromSource", - "extensions": [{ - "name": "Тест", - "initMethod": "fromSource", - "path": "/src/cfe/тест" - }] - }, - "yaxunit": { - "initMethod": "fromSource" - }, - "coverage": { - "dbgsPath": "C:\\\\Program files\\\\1cv8\\\\8.3.12.1500\\\\bin\\\\dbgs.exe", - "coverage41CPath": "C:\\\\coverage\\\\Coverage41C.exe" - } +{ + "v8version": "8.3.12.1500", + "initInfobase": { + "initMethod": "fromSource", + "extensions": [{ + "name": "Тест", + "initMethod": "fromSource", + "path": "/src/cfe/тест" + }] + }, + "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