diff --git a/README.md b/README.md index fc0d9c8..b81bb4e 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Создание библиотеки (или плагина) для Jenkins, позволяющей: * максимально упростить написание Jenkinsfile для процесса CI в условиях платформы 1С:Предприятие 8 -* иметь схожий и контроллируемый пайплайн для всех проектов +* иметь схожий и контролируемый пайплайн для всех проектов * дать пользователю в руки простой декларативный конфигурационный файл, вместо требования описывать всю сложную логику по работе с 1С ## Общие положения @@ -21,11 +21,21 @@ 1. Для шага подготовки требуется любой агент с меткой `agent`. 1. Для запуска шага анализа SonarQube требуется агент с меткой `sonar`. +1. Для запуска шага валидации EDT требуется агент с меткой `edt` (для собственно валидации) и агент с меткой `oscript` (для трансформации результатов с помощью библиотеки [stebi](https://github.com/Stepa86/stebi)). 1. Для запуска шагов, работающих с 1С (подготовка, синтаксический контроль и т.д.) требуется агент с меткой, совпадающей со значением в поле `v8version` файла конфигурации. 1. В качестве ИБ используется файловая база, создаваемая в `./build/ib`, без данных авторизации. Переопределение "в следующих сериях". 1. Stage "Дымовые тесты" пока пустой. 1. Запуск `vrunner` на текущий момент происходит из локального каталога `oscript_modules`. Предполагается наличие в корне репозитория файла `packagedef`, в котором бы была указана зависимость от `vanessa-runner` +## Возможности + +1. Все шаги можно запустить на базе docker-образов из форка репозитория onec-docker. См. [памятку по слоям и последовательности сборки](https://github.com/firstBitSemenovskaya/onec-docker/blob/feature/first-bit/Layers.md) +1. Трансформация кода из формата конфигуратора в формат EDT (только если включен шаг `edtValidate`). +1. Подготовка информационной базы по версии из хранилища конфигурации. +1. Запуск синтаксического контроля средствами конфигуратора и сохранение результатов в виде отчета jUnit. +1. Запуск валидации проекта средствами EDT и конвертация отчета в формате generic issues. +1. Запуск статического анализа для SonarQube + ## Подключение Инструкция по подключению библиотеки: https://jenkins.io/doc/book/pipeline/shared-libraries/#using-libraries @@ -48,7 +58,7 @@ pipeline1C() > Да, вот и весь пайплайн. Конфигурирование через json. -## Конфигуирование +## Конфигурирование По умолчанию применяется [файл конфигурации из ресурсов библиотеки](resources/globalConfiguration.json) @@ -57,11 +67,12 @@ pipeline1C() Пример переопределения: * указывается точная версия платформы (и соответственно метка агента, см. ограничения) -* идентификаторы credentials для пути к хранилищу и к паре логин/пароль для авторизации в хранилище -* включаются шаги запуска статического анализа и синтаксического контроля +* идентификаторы credentials для пути к хранилищу и к паре логин/пароль для авторизации в хранилище (необходимы, если применяются шаги, работающие с информационной базой) +* включаются шаги запуска статического анализа SonarQube, валидации средствами EDT и синтаксического контроля ```json { + "$schema": "https://raw.githubusercontent.com/firstBitSemenovskaya/jenkins-lib/master/resources/schema.json", "v8version": "8.3.14.1976", "secrets": { "storagePath": "f7b21c02-711a-4883-81c5-d429454e3f8b", @@ -69,6 +80,7 @@ pipeline1C() }, "stages": { "sonarqube": true, + "edtValidation": true, "syntaxCheck": true } } diff --git a/resources/globalConfiguration.json b/resources/globalConfiguration.json index 87d1e6a..332119d 100644 --- a/resources/globalConfiguration.json +++ b/resources/globalConfiguration.json @@ -1,12 +1,15 @@ { "$schema": "schema.json", + "srcDir": "src/cf", "secrets": { "storagePath": "UNKNOWN_ID", "storage": "UNKNOWN_ID" }, "stages": { "sonarqube": false, - "syntaxCheck": false + "syntaxCheck": false, + "edtValidate": false, + "smoke": false }, "sonarqube": { "sonarQubeInstallation": "", @@ -29,5 +32,9 @@ "-CheckUseSynchronousCalls", "-DistributiveModules" ] + }, + "resultsTransform": { + "removeSupport": false, + "supportLevel": 0 } } diff --git a/resources/schema.json b/resources/schema.json index 7ae4537..40bcd1c 100644 --- a/resources/schema.json +++ b/resources/schema.json @@ -6,6 +6,10 @@ "type" : "string", "description" : "Версия платформы 1С:Предприятие в формате 8.3.хх.хххх." }, + "srcDir" : { + "type" : "string", + "description" : "Путь к корневому каталогу с исходниками конфигурации" + }, "secrets" : { "type" : "object", "id" : "urn:jsonschema:ru:pulsar:jenkins:library:configuration:Secrets", @@ -33,6 +37,14 @@ "syntaxCheck" : { "type" : "boolean", "description" : "Синтаксический контроль включен" + }, + "edtValidate" : { + "type" : "boolean", + "description" : "Валидация EDT включена" + }, + "smoke" : { + "type" : "boolean", + "description" : "Дымовые тесты включены" } } }, @@ -76,6 +88,21 @@ } } } + }, + "resultsTransform" : { + "type" : "object", + "id" : "urn:jsonschema:ru:pulsar:jenkins:library:configuration:ResultsTransformOptions", + "description" : "Настройки трансформации результатов анализа", + "properties" : { + "removeSupport" : { + "type" : "boolean", + "description" : "Фильтровать замечания по уровню поддержки модуля" + }, + "supportLevel" : { + "type" : "integer", + "description" : "Настройка фильтрации замечаний по уровню поддержки.\n 0 - удалить файлы на замке;\n 1 - удалить файлы на замке и на поддержке;\n 2 - удалить файлы на замке, на поддержке и снятые с поддержки.\n " + } + } } } } \ No newline at end of file diff --git a/src/ru/pulsar/jenkins/library/IStepExecutor.groovy b/src/ru/pulsar/jenkins/library/IStepExecutor.groovy index 6cb051f..8942a1c 100644 --- a/src/ru/pulsar/jenkins/library/IStepExecutor.groovy +++ b/src/ru/pulsar/jenkins/library/IStepExecutor.groovy @@ -16,13 +16,33 @@ interface IStepExecutor { void echo(message) - void cmd(String script, boolean returnStatus) + int cmd(String script, boolean returnStatus) - void cmd(String script) + int cmd(String script) void tool(String toolName) void withSonarQubeEnv(String installationName, Closure body) EnvironmentAction env() + + void createDir(String path) + + def withEnv(List strings, Closure body) + + def archiveArtifacts(String path) + + def stash(String name, String includes) + + def unstash(String name) + + def zip(String dir, String zipFile) + + def zip(String dir, String zipFile, String glob) + + def unzip(String dir, String zipFile) + + def unzip(String dir, String zipFile, quiet) + + def catchError(Closure body) } \ No newline at end of file diff --git a/src/ru/pulsar/jenkins/library/StepExecutor.groovy b/src/ru/pulsar/jenkins/library/StepExecutor.groovy index b38f5ce..2b425a5 100644 --- a/src/ru/pulsar/jenkins/library/StepExecutor.groovy +++ b/src/ru/pulsar/jenkins/library/StepExecutor.groovy @@ -41,8 +41,8 @@ class StepExecutor implements IStepExecutor { } @Override - void cmd(String script, boolean returnStatus = false) { - steps.cmd(script, returnStatus) + int cmd(String script, boolean returnStatus = false) { + return steps.cmd(script, returnStatus) } @Override @@ -61,4 +61,46 @@ class StepExecutor implements IStepExecutor { EnvironmentAction env() { return steps.env } + + @Override + void createDir(String path) { + steps.createDir(path) + } + + @Override + def withEnv(List strings, Closure body) { + steps.withEnv(strings) { + body() + } + } + + @Override + def archiveArtifacts(String path) { + steps.archiveArtifacts path + } + + @Override + def stash(String name, String includes) { + steps.stash name: name, includes: includes + } + + @Override + def unstash(String name) { + steps.unstash name + } + + @Override + def zip(String dir, String zipFile, String glob = '') { + steps.zip dir: dir, zipFile: zipFile, glob: glob + } + + @Override + def unzip(String dir, String zipFile, quiet = true) { + steps.unzip dir: dir, zipFile: zipFile, quiet: quiet + } + + @Override + def catchError(Closure body) { + steps.catchError body + } } diff --git a/src/ru/pulsar/jenkins/library/configuration/ConfigurationReader.groovy b/src/ru/pulsar/jenkins/library/configuration/ConfigurationReader.groovy index 159991a..d17ddf5 100644 --- a/src/ru/pulsar/jenkins/library/configuration/ConfigurationReader.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/ConfigurationReader.groovy @@ -42,7 +42,8 @@ class ConfigurationReader implements Serializable { "secrets", "stageFlags", "sonarQubeOptions", - "syntaxCheckOptions" + "syntaxCheckOptions", + "resultsTransformOptions" ).toSet() mergeObjects(baseConfiguration, configurationToMerge, nonMergeableSettings) diff --git a/src/ru/pulsar/jenkins/library/configuration/JobConfiguration.groovy b/src/ru/pulsar/jenkins/library/configuration/JobConfiguration.groovy index 9fbad20..3368d8e 100644 --- a/src/ru/pulsar/jenkins/library/configuration/JobConfiguration.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/JobConfiguration.groovy @@ -10,6 +10,9 @@ class JobConfiguration implements Serializable { @JsonPropertyDescription("Версия платформы 1С:Предприятие в формате 8.3.хх.хххх.") String v8version + @JsonPropertyDescription("Путь к корневому каталогу с исходниками конфигурации") + String srcDir + @JsonProperty("stages") @JsonPropertyDescription("Включение этапов сборок") StageFlags stageFlags; @@ -25,15 +28,21 @@ class JobConfiguration implements Serializable { @JsonPropertyDescription("Настройки синтаксического контроля") SyntaxCheckOptions syntaxCheckOptions; + @JsonProperty("resultsTransform") + @JsonPropertyDescription("Настройки трансформации результатов анализа") + ResultsTransformOptions resultsTransformOptions; + @Override @NonCPS String toString() { return "JobConfiguration{" + "v8version='" + v8version + '\'' + + ", srcDir='" + srcDir + '\'' + ", stageFlags=" + stageFlags + ", secrets=" + secrets + ", sonarQubeOptions=" + sonarQubeOptions + ", syntaxCheckOptions=" + syntaxCheckOptions + + ", resultsTransformOptions=" + resultsTransformOptions + '}'; } } \ No newline at end of file diff --git a/src/ru/pulsar/jenkins/library/configuration/ResultsTransformOptions.groovy b/src/ru/pulsar/jenkins/library/configuration/ResultsTransformOptions.groovy new file mode 100644 index 0000000..c159fd2 --- /dev/null +++ b/src/ru/pulsar/jenkins/library/configuration/ResultsTransformOptions.groovy @@ -0,0 +1,28 @@ +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 ResultsTransformOptions implements Serializable { + + @JsonPropertyDescription("Фильтровать замечания по уровню поддержки модуля") + boolean removeSupport + + @JsonPropertyDescription("""Настройка фильтрации замечаний по уровню поддержки. + 0 - удалить файлы на замке; + 1 - удалить файлы на замке и на поддержке; + 2 - удалить файлы на замке, на поддержке и снятые с поддержки. + """) + int supportLevel + + @Override + @NonCPS + String toString() { + return "ResultsTransformOptions{" + + "removeSupport=" + removeSupport + + ", supportLevel=" + supportLevel + + '}'; + } +} diff --git a/src/ru/pulsar/jenkins/library/configuration/StageFlags.groovy b/src/ru/pulsar/jenkins/library/configuration/StageFlags.groovy index ec1fcab..c73a158 100644 --- a/src/ru/pulsar/jenkins/library/configuration/StageFlags.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/StageFlags.groovy @@ -12,12 +12,24 @@ class StageFlags implements Serializable { @JsonPropertyDescription("Синтаксический контроль включен") boolean syntaxCheck + @JsonPropertyDescription("Валидация EDT включена") + boolean edtValidate + + @JsonPropertyDescription("Дымовые тесты включены") + boolean smoke + @Override @NonCPS String toString() { return "StageFlags{" + - "sonarQube=" + sonarqube + + "sonarqube=" + sonarqube + ", syntaxCheck=" + syntaxCheck + + ", edtValidate=" + edtValidate + + ", smoke=" + smoke + '}'; } + + boolean needInfobase() { + return smoke || syntaxCheck + } } diff --git a/src/ru/pulsar/jenkins/library/steps/EdtTransform.groovy b/src/ru/pulsar/jenkins/library/steps/EdtTransform.groovy new file mode 100644 index 0000000..4b2a065 --- /dev/null +++ b/src/ru/pulsar/jenkins/library/steps/EdtTransform.groovy @@ -0,0 +1,50 @@ +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 EdtTransform implements Serializable { + + public static final String PROJECT_NAME = 'temp' + public static final String WORKSPACE = 'build/edt-workspace' + public static final String WORKSPACE_ZIP = 'build/edt-workspace.zip' + public static final String WORKSPACE_ZIP_STASH = 'edt-workspace-zip' + + private final JobConfiguration config; + + EdtTransform(JobConfiguration config) { + this.config = config + } + + def run() { + IStepExecutor steps = ContextRegistry.getContext().getStepExecutor() + + Logger.printLocation() + + if (!config.stageFlags.edtValidate) { + Logger.println("EDT validate step is disabled. No transform is needed.") + return + } + + def env = steps.env(); + + def workspaceDir = "$env.WORKSPACE/$WORKSPACE" + def configurationRoot = new File(env.WORKSPACE, config.srcDir).getAbsolutePath() + + steps.createDir(workspaceDir) + + Logger.println("Конвертация исходников из формата конфигуратора в формат EDT") + + def ringCommand = "ring edt workspace import --configuration-files '$configurationRoot' --project-name $PROJECT_NAME --workspace-location '$workspaceDir'" + + def ringOpts = ['RING_OPTS=-Dfile.encoding=UTF-8 -Dosgi.nl=ru -Duser.language=ru'] + steps.withEnv(ringOpts) { + steps.cmd(ringCommand) + } + + steps.zip(WORKSPACE, WORKSPACE_ZIP) + steps.stash(WORKSPACE_ZIP_STASH, WORKSPACE_ZIP) + } +} diff --git a/src/ru/pulsar/jenkins/library/steps/EdtValidate.groovy b/src/ru/pulsar/jenkins/library/steps/EdtValidate.groovy new file mode 100644 index 0000000..febc0fc --- /dev/null +++ b/src/ru/pulsar/jenkins/library/steps/EdtValidate.groovy @@ -0,0 +1,52 @@ +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 EdtValidate implements Serializable { + + public static final String RESULT_STASH = 'edt-validate' + public static final String RESULT_FILE = 'build/out/edt-validate.out' + + private final JobConfiguration config; + + EdtValidate(JobConfiguration config) { + this.config = config + } + + def run() { + IStepExecutor steps = ContextRegistry.getContext().getStepExecutor() + + Logger.printLocation() + + if (!config.stageFlags.edtValidate) { + Logger.println("EDT validate step is disabled") + return + } + + steps.unstash(EdtTransform.WORKSPACE_ZIP_STASH) + steps.unzip(EdtTransform.WORKSPACE, EdtTransform.WORKSPACE_ZIP) + + def env = steps.env(); + + def resultFile = "$env.WORKSPACE/$RESULT_FILE" + def workspaceLocation = "$env.WORKSPACE/$EdtTransform.WORKSPACE" + + steps.createDir(new File(resultFile).getParent()) + + Logger.println("Выполнение валидации EDT") + + def ringCommand = "ring edt workspace validate --workspace-location '$workspaceLocation' --file '$resultFile' --project-name-list $EdtTransform.PROJECT_NAME" + def ringOpts = ['RING_OPTS=-Dfile.encoding=UTF-8 -Dosgi.nl=ru -Duser.language=ru'] + steps.withEnv(ringOpts) { + steps.catchError { + steps.cmd(ringCommand) + } + } + steps.archiveArtifacts("$EdtTransform.WORKSPACE/.metadata/.log") + steps.archiveArtifacts(RESULT_FILE) + steps.stash(RESULT_STASH, RESULT_FILE) + } +} diff --git a/src/ru/pulsar/jenkins/library/steps/ResultsTransformer.groovy b/src/ru/pulsar/jenkins/library/steps/ResultsTransformer.groovy new file mode 100644 index 0000000..890466b --- /dev/null +++ b/src/ru/pulsar/jenkins/library/steps/ResultsTransformer.groovy @@ -0,0 +1,48 @@ +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 ResultsTransformer implements Serializable { + + public static final String RESULT_STASH = 'edt-generic-issue' + public static final String RESULT_FILE = 'build/out/edt-generic-issue.json' + + private final JobConfiguration config; + + ResultsTransformer(JobConfiguration config) { + this.config = config + } + + def run() { + IStepExecutor steps = ContextRegistry.getContext().getStepExecutor() + + Logger.printLocation() + + def env = steps.env(); + + if (!config.stageFlags.edtValidate) { + Logger.println("EDT validation is disabled. No transform is needed.") + return + } + + steps.unstash(EdtValidate.RESULT_STASH) + + Logger.println("Конвертация результата EDT в Generic Issue") + + def edtValidateFile = "$env.WORKSPACE/$EdtValidate.RESULT_FILE" + def genericIssueFile = "$env.WORKSPACE/$RESULT_FILE" + + steps.cmd("stebi convert $edtValidateFile $genericIssueFile $config.srcDir") + + if (config.resultsTransformOptions.removeSupport) { + def supportLevel = config.resultsTransformOptions.supportLevel + steps.cmd("stebi transform --remove_support $supportLevel --src $config.srcDir $genericIssueFile") + } + + steps.archiveArtifacts(RESULT_FILE) + steps.stash(RESULT_STASH, RESULT_FILE) + } +} diff --git a/src/ru/pulsar/jenkins/library/steps/SonarScanner.groovy b/src/ru/pulsar/jenkins/library/steps/SonarScanner.groovy index d437abc..a75f6ec 100644 --- a/src/ru/pulsar/jenkins/library/steps/SonarScanner.groovy +++ b/src/ru/pulsar/jenkins/library/steps/SonarScanner.groovy @@ -11,9 +11,9 @@ class SonarScanner implements Serializable { private final JobConfiguration config; private final String rootFile - SonarScanner(JobConfiguration config, String rootFile = 'src/cf/Configuration.xml') { + SonarScanner(JobConfiguration config) { this.config = config - this.rootFile = rootFile + this.rootFile = "$config.srcDir/Configuration.xml" } def run() { @@ -44,6 +44,11 @@ class SonarScanner implements Serializable { sonarCommand += " -Dsonar.projectVersion=$configurationVersion" } + if (config.stageFlags.edtValidate) { + steps.unstash("edt-generic-issue") + sonarCommand += " -Dsonar.externalIssuesReportPaths=build/out/edt-generic-issue.json" + } + def sonarQubeInstallation = config.sonarQubeOptions.sonarQubeInstallation if (sonarQubeInstallation == '') { sonarQubeInstallation = null diff --git a/src/ru/pulsar/jenkins/library/utils/Logger.groovy b/src/ru/pulsar/jenkins/library/utils/Logger.groovy index 3d10a24..b6808ab 100644 --- a/src/ru/pulsar/jenkins/library/utils/Logger.groovy +++ b/src/ru/pulsar/jenkins/library/utils/Logger.groovy @@ -10,4 +10,10 @@ class Logger implements Serializable { def env = steps.env(); steps.echo("Running on node $env.NODE_NAME") } + + static void println(String message) { + IStepExecutor steps = ContextRegistry.getContext().getStepExecutor() + + steps.echo(message) + } } diff --git a/test/integration/groovy/cmdTest.groovy b/test/integration/groovy/cmdTest.groovy index 0d3283b..f9ddc71 100644 --- a/test/integration/groovy/cmdTest.groovy +++ b/test/integration/groovy/cmdTest.groovy @@ -35,4 +35,28 @@ class cmdTest { rule.assertLogContains('helloWorld', rule.buildAndAssertSuccess(workflowJob)) } + + @Test + void "cmd should return status"() { + def pipeline = ''' + pipeline { + agent any + stages { + stage('test') { + steps { + script { + def status = cmd("false", true) + echo "status = $status" + } + } + } + } + } + '''.stripIndent() + final CpsFlowDefinition flow = new CpsFlowDefinition(pipeline, true) + final WorkflowJob workflowJob = rule.createProject(WorkflowJob, 'project') + workflowJob.definition = flow + + rule.assertLogContains('status = 1', rule.buildAndAssertSuccess(workflowJob)) + } } \ 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 b15a3a7..01e4edc 100644 --- a/test/unit/groovy/ru/pulsar/jenkins/library/configuration/ConfigurationReaderTest.java +++ b/test/unit/groovy/ru/pulsar/jenkins/library/configuration/ConfigurationReaderTest.java @@ -37,6 +37,8 @@ class ConfigurationReaderTest { .hasFieldOrPropertyWithValue("storagePath", "UNKNOWN_ID") ; assertThat(jobConfiguration.getSyntaxCheckOptions().getCheckModes()).hasSize(1); + assertThat(jobConfiguration.getResultsTransformOptions().isRemoveSupport()).isTrue(); + assertThat(jobConfiguration.getResultsTransformOptions().getSupportLevel()).isEqualTo(0); } } \ No newline at end of file diff --git a/test/unit/resources/jobConfiguration.json b/test/unit/resources/jobConfiguration.json index 2807098..2cd66f2 100644 --- a/test/unit/resources/jobConfiguration.json +++ b/test/unit/resources/jobConfiguration.json @@ -8,5 +8,8 @@ }, "syntaxCheck": { "checkModes": ["-ThinClient"] + }, + "resultsTransform": { + "removeSupport": true } } \ No newline at end of file diff --git a/vars/cmd.groovy b/vars/cmd.groovy index c924119..b5ad056 100644 --- a/vars/cmd.groovy +++ b/vars/cmd.groovy @@ -5,5 +5,5 @@ int call(String script, boolean returnStatus = false) { ContextRegistry.registerDefaultContext(this) def cmd = new Cmd(script, returnStatus) - cmd.run() + return cmd.run() } diff --git a/vars/createDir.groovy b/vars/createDir.groovy new file mode 100644 index 0000000..56e83da --- /dev/null +++ b/vars/createDir.groovy @@ -0,0 +1,3 @@ +def call(String path) { + dir(path) { echo '' } +} diff --git a/vars/edtTransform.groovy b/vars/edtTransform.groovy new file mode 100644 index 0000000..de901e5 --- /dev/null +++ b/vars/edtTransform.groovy @@ -0,0 +1,10 @@ +import ru.pulsar.jenkins.library.configuration.JobConfiguration +import ru.pulsar.jenkins.library.ioc.ContextRegistry +import ru.pulsar.jenkins.library.steps.EdtTransform + +def call(JobConfiguration config) { + ContextRegistry.registerDefaultContext(this) + + def edtTransform = new EdtTransform(config) + edtTransform.run() +} diff --git a/vars/edtValidate.groovy b/vars/edtValidate.groovy new file mode 100644 index 0000000..df2d26c --- /dev/null +++ b/vars/edtValidate.groovy @@ -0,0 +1,10 @@ +import ru.pulsar.jenkins.library.configuration.JobConfiguration +import ru.pulsar.jenkins.library.ioc.ContextRegistry +import ru.pulsar.jenkins.library.steps.EdtValidate + +def call(JobConfiguration config) { + ContextRegistry.registerDefaultContext(this) + + def edtValidate = new EdtValidate(config) + edtValidate.run() +} diff --git a/vars/pipeline1C.groovy b/vars/pipeline1C.groovy index 7a178d2..d07006f 100644 --- a/vars/pipeline1C.groovy +++ b/vars/pipeline1C.groovy @@ -35,22 +35,17 @@ void call() { } } - stage('SonarQube') { - agent { - label 'sonar' - } - steps { - sonarScanner config - } - } + stage('Подготовка') { + parallel { + stage('Подготовка 1C базы') { + agent { + label agent1C + } + when { + beforeAgent true + expression { config.stageFlags.needInfobase() } + } - stage('1C') { - agent { - label agent1C - } - - stages { - stage('Подготовка базы') { steps { printLocation() @@ -65,27 +60,89 @@ void call() { } } - stage('Проверка качества') { - parallel { - stage('Синтаксический контроль') { - steps { - syntaxCheck config - } - } - - stage('Дымовые тесты') { - steps { - printLocation() - - installLocalDependencies() - - unzipInfobase() - } - } + stage('Трансформация в формат EDT') { + agent { + label 'edt' + } + when { + beforeAgent true + expression { config.stageFlags.edtValidate } + } + steps { + edtTransform config } } } } + + stage('Проверка качества') { + parallel { + stage('EDT контроль') { + agent { + label 'edt' + } + when { + beforeAgent true + expression { config.stageFlags.edtValidate } + } + steps { + edtValidate config + } + } + + stage('Синтаксический контроль') { + agent { + label agent1C + } + when { + beforeAgent true + expression { config.stageFlags.syntaxCheck } + } + steps { + syntaxCheck config + } + } + + stage('Дымовые тесты') { + agent { + label agent1C + } + when { + beforeAgent true + expression { config.stageFlags.smoke } + } + steps { + smoke config + } + } + } + } + + stage('Трансформация результатов') { + agent { + label 'oscript' + } + when { + beforeAgent true + expression { config.stageFlags.edtValidate } + } + steps { + transform config + } + } + + stage('SonarQube') { + agent { + label 'sonar' + } + when { + beforeAgent true + expression { config.stageFlags.sonarqube } + } + steps { + sonarScanner config + } + } } } diff --git a/vars/smoke.groovy b/vars/smoke.groovy new file mode 100644 index 0000000..fc204f6 --- /dev/null +++ b/vars/smoke.groovy @@ -0,0 +1,23 @@ +import ru.pulsar.jenkins.library.configuration.JobConfiguration +import ru.pulsar.jenkins.library.ioc.ContextRegistry + +def call(JobConfiguration config) { + + ContextRegistry.registerDefaultContext(this) + + // TODO: Вынести в отдельный класс по аналогии с SonarScanner + + printLocation() + + if (!config.stageFlags.smoke) { + echo("Smoke tests step is disabled") + return + } + + def options = config.syntaxCheckOptions + + installLocalDependencies() + + unzipInfobase() + +} diff --git a/vars/sonarScanner.groovy b/vars/sonarScanner.groovy index 920799a..e37fafd 100644 --- a/vars/sonarScanner.groovy +++ b/vars/sonarScanner.groovy @@ -2,9 +2,9 @@ import ru.pulsar.jenkins.library.configuration.JobConfiguration import ru.pulsar.jenkins.library.ioc.ContextRegistry import ru.pulsar.jenkins.library.steps.SonarScanner -def call(JobConfiguration config, String rootFile = 'src/cf/Configuration.xml') { +def call(JobConfiguration config) { ContextRegistry.registerDefaultContext(this) - def sonarScanner = new SonarScanner(config, rootFile) + def sonarScanner = new SonarScanner(config) sonarScanner.run() } diff --git a/vars/syntaxCheck.groovy b/vars/syntaxCheck.groovy index 047329a..3d36d25 100644 --- a/vars/syntaxCheck.groovy +++ b/vars/syntaxCheck.groovy @@ -21,7 +21,7 @@ def call(JobConfiguration config) { unzipInfobase() def outPath = new File(options.pathToJUnitReport).getParent() - dir(outPath) { echo '' } + createDir(outPath) String command = "oscript_modules/bin/vrunner syntax-check --ibconnection \"/F./build/ib\"" diff --git a/vars/transform.groovy b/vars/transform.groovy new file mode 100644 index 0000000..f054ce5 --- /dev/null +++ b/vars/transform.groovy @@ -0,0 +1,10 @@ +import ru.pulsar.jenkins.library.configuration.JobConfiguration +import ru.pulsar.jenkins.library.ioc.ContextRegistry +import ru.pulsar.jenkins.library.steps.ResultsTransformer + +def call(JobConfiguration config) { + ContextRegistry.registerDefaultContext(this) + + def transformer = new ResultsTransformer(config) + transformer.run() +} \ No newline at end of file