Skip to content

Commit

Permalink
Merge pull request #149 from ovcharenko-di/feature/save-dt
Browse files Browse the repository at this point in the history
Сохранение ИБ в виде артефакта после выполнения всех шагов инциализации
  • Loading branch information
nixel2007 authored Jan 24, 2025
2 parents 4c73fcd + a6aad1b commit 482a600
Show file tree
Hide file tree
Showing 16 changed files with 223 additions and 15 deletions.
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,12 @@
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. Замер покрытия при выполнении тестов.
1. Возможность сохранить информационную базу в виде артефакта сборки после выполнения шагов инициализации и\или после выполнения сценарных тестов.

## Подключение

Expand Down Expand Up @@ -168,6 +168,7 @@ pipeline1C()
* Если разработка ведется с использованием подсистемы [БСП "Обновление версии ИБ"](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). Шаблоны сообщений конфигурируются в настройках плагина.
Expand Down Expand Up @@ -312,3 +313,12 @@ jobConfiguration.json

* При изменении портов отладки в jobConfiguration.json не забывайте менять порты в настройках соответствующих шагов (и наоборот)
* Настоятельно рекомендуется использовать не "постоянные" агенты Jenkins, а контейнеры docker. При выполнении билдов в контейнерах можно использовать исключительно стандартный порт 1550.

## Сохранение ИБ в виде артефакта сборки

Параметры `initInfobase` -> `archiveInfobase` и `bdd` -> `archiveInfobase` отвечают за сохранение информационной базы в виде артефакта сборки после выполнения соответствующих этапов.
Можно управлять тем, при каких статусах сборки ИБ будет сохранена, см. `onAlways`, `onFailure`, `onUnstable`, `onSuccess`.

Имя файла формируется следующим образом:
* для шага `initInfoBase`: '1Cv8.1CD.zip'
* для шага `bdd`: '1Cv8.1CD.bdd.zip'
14 changes: 13 additions & 1 deletion resources/globalConfiguration.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,20 +45,32 @@
"additionalInitializationSteps": [],
"templateDBPath": "",
"vrunnerSettings": "./tools/vrunner.json",
"archiveInfobase": {
"onAlways": false,
"onFailure": false,
"onUnstable": false,
"onSuccess": false
},
"extensions": []
},
"bdd": {
"vrunnerSteps": [
"vanessa --settings ./tools/vrunner.json"
],
"archiveInfobase": {
"onAlways": false,
"onFailure": false,
"onUnstable": false,
"onSuccess": false
},
"coverage": false,
"dbgsPort": 1550
},
"sonarqube": {
"sonarQubeInstallation": "",
"useSonarScannerFromPath": true,
"sonarScannerToolName": "sonar-scanner",
"infoBaseUpdateModuleName" : "",
"infoBaseUpdateModuleName": "",
"branchAnalysisConfiguration": "fromEnv",
"waitForQualityGate": false
},
Expand Down
39 changes: 37 additions & 2 deletions resources/schema.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,27 @@
{
"$schema" : "http://json-schema.org/draft-07/schema#",
"definitions" : {
"ArchiveInfobaseOptions" : {
"type" : "object",
"properties" : {
"onAlways" : {
"type" : "boolean",
"description" : "Сохранять всегда"
},
"onFailure" : {
"type" : "boolean",
"description" : "Сохранять при падении сборки"
},
"onSuccess" : {
"type" : "boolean",
"description" : "Сохранять при успешной сборке"
},
"onUnstable" : {
"type" : "boolean",
"description" : "Сохранять при нестабильной сборке"
}
}
},
"EmailExtConfiguration" : {
"type" : "object",
"properties" : {
Expand Down Expand Up @@ -28,6 +49,13 @@
"bdd" : {
"type" : "object",
"properties" : {
"archiveInfobase" : {
"allOf" : [ {
"$ref" : "#/definitions/ArchiveInfobaseOptions"
}, {
"description" : "Настройки сохранения базы после выполнения всех шагов\n "
} ]
},
"coverage" : {
"type" : "boolean",
"description" : "Выполнять замер покрытия",
Expand Down Expand Up @@ -80,6 +108,13 @@
"type" : "string"
}
},
"archiveInfobase" : {
"allOf" : [ {
"$ref" : "#/definitions/ArchiveInfobaseOptions"
}, {
"description" : "Настройки сохранения базы после выполнения всех шагов\n "
} ]
},
"extensions" : {
"description" : "Массив расширений для загрузки в конфигурацию.",
"type" : "array",
Expand Down Expand Up @@ -381,12 +416,12 @@
"publishToAllureReport" : {
"type" : "boolean",
"description" : "Выполнять публикацию результатов в отчет Allure.\n По умолчанию выключено.\n ",
"default": false
"default" : false
},
"publishToJUnitReport" : {
"type" : "boolean",
"description" : "Выполнять публикацию результатов в отчет JUnit.\n По умолчанию включено.\n ",
"default": true
"default" : true
},
"vrunnerSettings" : {
"type" : "string",
Expand Down
3 changes: 2 additions & 1 deletion src/JobConfigurationSchemaGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ public static void main(String[] args) {
writer.write(jsonSchema.toPrettyString());
System.out.println(jsonSchema.toPrettyString());
} catch (IOException e) {
e.printStackTrace();
//noinspection CallToPrintStackTrace
e.printStackTrace();
}
}

Expand Down
8 changes: 8 additions & 0 deletions src/ru/pulsar/jenkins/library/IStepExecutor.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ 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 sp.sd.fileoperations.FileOperation

interface IStepExecutor {

Expand All @@ -34,6 +35,10 @@ interface IStepExecutor {

boolean fileExists(String file)

void fileOperations(List<FileOperation> fileOperations)

void fileDeleteOperation(String includes)

void echo(message)

def cmd(String script, boolean returnStatus, boolean returnStdout)
Expand Down Expand Up @@ -89,6 +94,8 @@ interface IStepExecutor {
@SuppressWarnings('unused')
def zip(String dir, String zipFile, String glob)

def zip(String dir, String zipFile, String glob, boolean archive)

def unzip(String dir, String zipFile)

@SuppressWarnings('unused')
Expand Down Expand Up @@ -120,4 +127,5 @@ interface IStepExecutor {
def brokenTestsSuspects()

RunWrapper currentBuild()

}
16 changes: 16 additions & 0 deletions src/ru/pulsar/jenkins/library/StepExecutor.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ 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
import sp.sd.fileoperations.FileOperation

class StepExecutor implements IStepExecutor {

Expand Down Expand Up @@ -55,6 +56,16 @@ class StepExecutor implements IStepExecutor {
steps.fileExists file
}

@Override
void fileOperations(List<FileOperation> fileOperations) {
steps.fileOperations fileOperations
}

@Override
void fileDeleteOperation(String includes) {
steps.fileDeleteOperation includes: includes, excludes: '', useDefaultExcludes: true
}

@Override
FileWrapper[] findFiles(String glob, String excludes = '') {
steps.findFiles glob: glob, excludes: excludes
Expand Down Expand Up @@ -196,6 +207,11 @@ class StepExecutor implements IStepExecutor {
steps.zip dir: dir, zipFile: zipFile, glob: glob, overwrite: true
}

@Override
def zip(String dir, String zipFile, String glob = '', boolean archive) {
steps.zip dir: dir, zipFile: zipFile, glob: glob, overwrite: true, archive: archive
}

@Override
def unzip(String dir, String zipFile, quiet = true) {
steps.unzip dir: dir, zipFile: zipFile, quiet: quiet
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
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 ArchiveInfobaseOptions implements Serializable {

@JsonPropertyDescription("Сохранять всегда")
Boolean onAlways = false
@JsonPropertyDescription("Сохранять при успешной сборке")
Boolean onSuccess = false
@JsonPropertyDescription("Сохранять при падении сборки")
Boolean onFailure = false
@JsonPropertyDescription("Сохранять при нестабильной сборке")
Boolean onUnstable = false

@Override
@NonCPS
String toString() {
return "ArchiveInfobaseOptions{" +
"onAlways=" + onAlways +
", onSuccess=" + onSuccess +
", onFailure=" + onFailure +
", onUnstable=" + onUnstable +
'}';
}
}


5 changes: 5 additions & 0 deletions src/ru/pulsar/jenkins/library/configuration/BddOptions.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,16 @@ class BddOptions extends StepCoverageOptions implements Serializable {
'vanessa --settings ./tools/vrunner.json'
]

@JsonPropertyDescription("""Настройки сохранения базы после выполнения всех шагов
""")
ArchiveInfobaseOptions archiveInfobase

@Override
@NonCPS
String toString() {
return "BddOptions{" +
"vrunnerSteps=" + vrunnerSteps +
"archiveInfobase=" + archiveInfobase +
"coverage=" + coverage +
"dbgsPort=" + dbgsPort +
'}'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ class ConfigurationReader implements Serializable {
"yaxunitOptions",
"syntaxCheckOptions",
"resultsTransformOptions",
"archiveInfobase",
"notificationsOptions",
"emailNotificationOptions",
"alwaysEmailOptions",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ class InitInfoBaseOptions implements Serializable {
""")
String templateDBPath

@JsonPropertyDescription("""Настройки сохранения базы после выполнения всех шагов
""")
ArchiveInfobaseOptions archiveInfobase

@JsonPropertyDescription("Массив расширений для загрузки в конфигурацию.")
Extension[] extensions

Expand Down Expand Up @@ -80,6 +84,7 @@ class InitInfoBaseOptions implements Serializable {
", vrunnerSettings=" + vrunnerSettings +
", templateDBPath=" + templateDBPath +
", additionalInitializationSteps=" + additionalInitializationSteps +
", archiveInfobase=" + archiveInfobase +
", extensions=" + extensions +
'}'
}
Expand Down
2 changes: 1 addition & 1 deletion src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ class Yaxunit implements Serializable, Coverable {
}

if (options.publishToAllureReport) {
String allureReport = "./build/out/allure/yaxunit/junit.xml"
String allureReport = "./build/out/allure/yaxunit/allure.xml"
FilePath pathToAllureReport = FileUtils.getFilePath("$env.WORKSPACE/$allureReport")
String allureReportDir = FileUtils.getLocalPath(pathToAllureReport.getParent())

Expand Down
68 changes: 68 additions & 0 deletions src/ru/pulsar/jenkins/library/steps/ZipInfobase.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package ru.pulsar.jenkins.library.steps

import hudson.model.Result
import ru.pulsar.jenkins.library.IStepExecutor
import ru.pulsar.jenkins.library.configuration.ArchiveInfobaseOptions
import ru.pulsar.jenkins.library.configuration.JobConfiguration
import ru.pulsar.jenkins.library.ioc.ContextRegistry
import ru.pulsar.jenkins.library.utils.Logger

class ZipInfobase implements Serializable {

private final JobConfiguration config
private final String stage

ZipInfobase(JobConfiguration config, String stage) {
this.config = config
this.stage = stage
}

def run() {
IStepExecutor steps = ContextRegistry.getContext().getStepExecutor()

Logger.printLocation()

def currentBuild = steps.currentBuild()
def currentResult = Result.fromString(currentBuild.getCurrentResult())

def archiveInfobaseOptions = getArchiveInfobaseOptionsForStage(config, stage)

def archiveName
if (stage == 'initInfoBase') {
archiveName = "1Cv8.1CD.zip"
} else {
archiveName = "1Cv8.1CD.${stage}.zip"
}

// опция отвечает только за то, будет ли файл сохранен в виде артефакта
def archiveInfobase = false
if (archiveInfobaseOptions.onAlways
|| (archiveInfobaseOptions.onFailure && (currentResult == Result.FAILURE || currentResult == Result.ABORTED))
|| (archiveInfobaseOptions.onUnstable && currentResult == Result.UNSTABLE)
|| (archiveInfobaseOptions.onSuccess && currentResult == Result.SUCCESS)) {
archiveInfobase = true
}

if (steps.fileExists(archiveName)) {
steps.fileOperations([steps.fileDeleteOperation(archiveName)])
}
steps.zip('build/ib', archiveName, '1Cv8.1CD', archiveInfobase)
steps.stash(archiveName, archiveName, false)
}

private static ArchiveInfobaseOptions getArchiveInfobaseOptionsForStage(JobConfiguration config, String stageName) {

def defaultOptions = new ArchiveInfobaseOptions()
if (!stageName) {
return defaultOptions
}

try {
return config."${stageName}Options".archiveInfobase
} catch(MissingPropertyException | NullPointerException e) {
Logger.println("Ошибка при получении настроек архивации для этапа ${stageName}: ${e.message}")
Logger.println(e.toString())
return defaultOptions
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import org.apache.commons.io.IOUtils;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import ru.pulsar.jenkins.library.configuration.sonarqube.GenericIssueFormat;
import ru.pulsar.jenkins.library.utils.TestUtils;
Expand Down Expand Up @@ -66,6 +65,7 @@ void testCreateJobConfigurationObject() throws IOException {
assertThat(jobConfiguration.getYaxunitOptions().getDbgsPort()).isEqualTo(1550);

assertThat(jobConfiguration.getInitInfoBaseOptions().getRunMigration()).isFalse();
assertThat(jobConfiguration.getInitInfoBaseOptions().getArchiveInfobase().getOnAlways()).isTrue();
assertThat(jobConfiguration.getInitInfoBaseOptions().getAdditionalInitializationSteps()).contains("vanessa --settings ./tools/vrunner.first.json");

assertThat(jobConfiguration.getBddOptions().getVrunnerSteps()).contains("vanessa --settings ./tools/vrunner.json");
Expand Down
Loading

0 comments on commit 482a600

Please sign in to comment.