mirror of
https://github.com/firstBitMarksistskaya/jenkins-lib.git
synced 2024-12-13 11:27:08 +02:00
Merge branch 'release/v0.3.0'
This commit is contained in:
commit
d39e9d1cf8
37
README.md
37
README.md
@ -23,18 +23,23 @@
|
||||
1. Для запуска шага анализа SonarQube требуется агент с меткой `sonar`.
|
||||
1. Для запуска шага валидации EDT требуется агент с меткой `edt` (для собственно валидации) и агент с меткой `oscript` (для трансформации результатов с помощью библиотеки [stebi](https://github.com/Stepa86/stebi)).
|
||||
1. Для запуска шагов, работающих с 1С (подготовка, синтаксический контроль и т.д.) требуется агент с меткой, совпадающей со значением в поле `v8version` файла конфигурации.
|
||||
1. В качестве ИБ используется файловая база, создаваемая в `./build/ib`, без данных авторизации. Переопределение "в следующих сериях".
|
||||
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. Запуск ИБ в режиме выполнения обработчиков обновления БСП.
|
||||
1. Дополнительные шаги инициализации данных в ИБ.
|
||||
1. Трансформация кода из формата конфигуратора в формат EDT (только если включен шаг `edtValidate`).
|
||||
1. Запуск BDD сценариев с сохранением результатов в формате Allure.
|
||||
1. Запуск синтаксического контроля средствами конфигуратора и сохранение результатов в виде отчета jUnit.
|
||||
1. Запуск валидации проекта средствами EDT и конвертация отчета в формате generic issues.
|
||||
1. Запуск статического анализа для SonarQube
|
||||
1. Запуск статического анализа для SonarQube.
|
||||
1. Публикация результатов junit и Allure в интерфейс Jenkins.
|
||||
1. Конфигурирование логгера запускаемых oscript-приложений.
|
||||
|
||||
## Подключение
|
||||
|
||||
@ -60,7 +65,7 @@ pipeline1C()
|
||||
|
||||
## Внешний вид пайплайна в интерфейсе Blue Ocean
|
||||
|
||||
![image](https://user-images.githubusercontent.com/1132840/80956084-27b14400-8e09-11ea-9e92-683818a14503.png)
|
||||
![image](https://user-images.githubusercontent.com/1132840/121659170-b67f9e00-caaa-11eb-91be-107a689e893d.png)
|
||||
|
||||
## Конфигурирование
|
||||
|
||||
@ -89,3 +94,27 @@ pipeline1C()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Параметры по умолчанию
|
||||
|
||||
В библиотеке применяется принцип "соглашения по конфигурации" (convention over configuration): конфигурационный файл
|
||||
содержит ряд настроек "по умолчанию". При соблюдении определенных правил структуры репозитория можно сократить
|
||||
количество переопределений конфигурационного файла до минимума.
|
||||
|
||||
* Общее:
|
||||
* Исходники конфигурации ожидаются в каталоге `src/cf`.
|
||||
* TODO: Имена "секретов" (jenkins credentials) по умолчанию высчитываются как `GROUP_REPO_KEY`, где `GROUP` и `REPO` - это группа проектов и имя проектов (например, `firstBitSemenovskaya` и `jenkins-lib`), а `KEY` - ключ секрета:
|
||||
* `STORAGE_PATH` - путь к хранилищу конфигурации;
|
||||
* `STORAGE_USER` - параметры авторизации в хранилище вида "username with password".
|
||||
* Все "шаги" по умолчанию выключены.
|
||||
* Результаты в формате `allure` ожидаются в каталоге `build/out/allure` или его подкаталогах.
|
||||
* Инициализация:
|
||||
* Если включен шаг `initSteps`, то будет выполняться запуск ИБ с целью запуска обработчиков обновления из БСП. (`initInfobase` -> `runMigration`)
|
||||
* Если в настройках шага инициализации не заполнен массив дополнительных шагов миграции (`initInfobase` -> `additionalInitializationSteps`), но в каталоге `tools` присутствуют файлы с именами, удовлетворяющими шаблону `vrunner.init*.json`, то автоматически выполняется запуск `vrunner vanessa` с передачей найденных файлов в качестве значения настроек (параметр `--settings`) в порядке лексиграфической сортировки имен файлов.
|
||||
* BDD:
|
||||
* Если в конфигурационном файле проекта не заполнена настройка `bdd` -> `vrunnerSteps`, то автоматически выполняется запуск `vrunner vanessa --settings tools/vrunner.json`.
|
||||
* Синтаксический контроль:
|
||||
* Если в репозитории существует файл `tools/vrunner.json`, то синтаксический контроль конфигурации с помощью конфигуратора будет выполняться с передачей файла в параметры запуска `vrunner syntax-check --settings tools/vrunner.json`.
|
||||
* TODO: Значение параметра `--mode` из конфигурационного файла vrunner имеют приоритет над `syntaxCheck` -> `checkModes`. Значение из `jobConfiguration.json` передается только в том случае, если параметр отсутствует в конфигурационном файле `vrunner`.
|
||||
* Трансформация результатов валидации EDT:
|
||||
* По умолчанию из результатов анализа исключаются замечания, сработавшие на модулях с включенным запретом редактирования (желтый куб с замком)
|
@ -78,7 +78,10 @@ sharedLibrary {
|
||||
// TODO: retrieve downloaded plugin resource
|
||||
pluginDependencies {
|
||||
dependency("org.jenkins-ci.plugins", "pipeline-build-step", "2.12")
|
||||
dependency("org.jenkins-ci.plugins", "pipeline-utility-steps", "2.8.0")
|
||||
dependency("org.jenkins-ci.plugins", "git", "4.4.4")
|
||||
dependency("org.6wind.jenkins", "lockable-resources", "2.7")
|
||||
dependency("ru.yandex.qatools.allure", "allure-jenkins-plugin", "2.28.1")
|
||||
val declarativePluginsVersion = "1.6.0"
|
||||
dependency("org.jenkinsci.plugins", "pipeline-model-api", declarativePluginsVersion)
|
||||
dependency("org.jenkinsci.plugins", "pipeline-model-declarative-agent", "1.1.1")
|
||||
|
@ -6,11 +6,22 @@
|
||||
"storage": "UNKNOWN_ID"
|
||||
},
|
||||
"stages": {
|
||||
"initSteps": false,
|
||||
"sonarqube": false,
|
||||
"bdd": false,
|
||||
"syntaxCheck": false,
|
||||
"edtValidate": false,
|
||||
"smoke": false
|
||||
},
|
||||
"initInfobase": {
|
||||
"runMigration": true,
|
||||
"additionalInitializationSteps": []
|
||||
},
|
||||
"bdd": {
|
||||
"vrunnerSteps": [
|
||||
"vanessa --settings ./tools/vrunner.json"
|
||||
]
|
||||
},
|
||||
"sonarqube": {
|
||||
"sonarQubeInstallation": "",
|
||||
"useSonarScannerFromPath": true,
|
||||
@ -18,7 +29,7 @@
|
||||
},
|
||||
"syntaxCheck": {
|
||||
"groupErrorsByMetadata": true,
|
||||
"pathToJUnitReport": "build/out/jUnit/syntax.xml",
|
||||
"pathToJUnitReport": "./build/out/jUnit/syntax.xml",
|
||||
"checkModes": [
|
||||
"-ThinClient",
|
||||
"-WebClient",
|
||||
@ -31,10 +42,12 @@
|
||||
"-CheckUseModality",
|
||||
"-CheckUseSynchronousCalls",
|
||||
"-DistributiveModules"
|
||||
]
|
||||
],
|
||||
"vrunnerSettings": "./tools/vrunner.json"
|
||||
},
|
||||
"resultsTransform": {
|
||||
"removeSupport": false,
|
||||
"removeSupport": true,
|
||||
"supportLevel": 0
|
||||
}
|
||||
},
|
||||
"logosConfig": ""
|
||||
}
|
||||
|
@ -45,6 +45,46 @@
|
||||
"smoke" : {
|
||||
"type" : "boolean",
|
||||
"description" : "Дымовые тесты включены"
|
||||
},
|
||||
"initSteps" : {
|
||||
"type" : "boolean",
|
||||
"description" : "Предварительные шаги инициализации включены"
|
||||
},
|
||||
"bdd" : {
|
||||
"type" : "boolean",
|
||||
"description" : "Запуск BDD сценариев включен"
|
||||
}
|
||||
}
|
||||
},
|
||||
"initInfobase" : {
|
||||
"type" : "object",
|
||||
"id" : "urn:jsonschema:ru:pulsar:jenkins:library:configuration:InitInfobaseOptions",
|
||||
"description" : "Настройки шага инициализации ИБ",
|
||||
"properties" : {
|
||||
"runMigration" : {
|
||||
"type" : "boolean",
|
||||
"description" : "Запустить миграцию ИБ"
|
||||
},
|
||||
"additionalInitializationSteps" : {
|
||||
"type" : "array",
|
||||
"description" : "Дополнительные шаги, запускаемые через vrunner.\n В каждой строке передается отдельная команда \n vrunner и ее аргументы (например, \"vanessa --settings ./tools/vrunner.first.json\")\n ",
|
||||
"items" : {
|
||||
"type" : "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"bdd" : {
|
||||
"type" : "object",
|
||||
"id" : "urn:jsonschema:ru:pulsar:jenkins:library:configuration:BddOptions",
|
||||
"description" : "Настройки шага запуска BDD сценариев",
|
||||
"properties" : {
|
||||
"vrunnerSteps" : {
|
||||
"type" : "array",
|
||||
"description" : "Шаги, запускаемые через vrunner.\n В каждой строке передается отдельная команда \n vrunner и ее аргументы (например, \"vanessa --settings ./tools/vrunner.json\").\n По умолчанию содержит одну команду \"vanessa --settings ./tools/vrunner.json\".\n ",
|
||||
"items" : {
|
||||
"type" : "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -74,11 +114,11 @@
|
||||
"properties" : {
|
||||
"pathToJUnitReport" : {
|
||||
"type" : "string",
|
||||
"description" : "Путь к файлу отчета jUnit"
|
||||
"description" : "Путь к файлу отчета jUnit\n По умолчанию содержит значение \"./build/out/jUnit/syntax.xml\"\n "
|
||||
},
|
||||
"groupErrorsByMetadata" : {
|
||||
"type" : "boolean",
|
||||
"description" : "Группировать выявленные ошибки по объектам метаданных"
|
||||
"description" : "Группировать выявленные ошибки по объектам метаданных.\n По умолчанию включено.\n "
|
||||
},
|
||||
"checkModes" : {
|
||||
"type" : "array",
|
||||
@ -86,6 +126,10 @@
|
||||
"items" : {
|
||||
"type" : "string"
|
||||
}
|
||||
},
|
||||
"vrunnerSettings" : {
|
||||
"type" : "string",
|
||||
"description" : "Путь к конфигурационному файлу vanessa-runner.\n По умолчанию содержит значение \"./tools/vrunner.json\".\n "
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -96,13 +140,17 @@
|
||||
"properties" : {
|
||||
"removeSupport" : {
|
||||
"type" : "boolean",
|
||||
"description" : "Фильтровать замечания по уровню поддержки модуля"
|
||||
"description" : "Фильтровать замечания по уровню поддержки модуля. По умолчанию включено."
|
||||
},
|
||||
"supportLevel" : {
|
||||
"type" : "integer",
|
||||
"description" : "Настройка фильтрации замечаний по уровню поддержки.\n 0 - удалить файлы на замке;\n 1 - удалить файлы на замке и на поддержке;\n 2 - удалить файлы на замке, на поддержке и снятые с поддержки.\n "
|
||||
}
|
||||
}
|
||||
},
|
||||
"logosConfig" : {
|
||||
"type" : "string",
|
||||
"description" : "Конфигурация библиотеки logos. Применяется перед запуском каждой стадии сборки"
|
||||
}
|
||||
}
|
||||
}
|
@ -21,7 +21,7 @@ public class JobConfigurationSchemaGenerator {
|
||||
File jsonSchemaFile = new File("./resources/schema.json");
|
||||
mapper.writeValue(jsonSchemaFile, jsonSchema);
|
||||
|
||||
System.out.println(json.toString());
|
||||
System.out.println(json);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package ru.pulsar.jenkins.library
|
||||
|
||||
import org.jenkinsci.plugins.pipeline.utility.steps.fs.FileWrapper
|
||||
import org.jenkinsci.plugins.workflow.support.actions.EnvironmentAction
|
||||
|
||||
interface IStepExecutor {
|
||||
@ -12,6 +13,10 @@ interface IStepExecutor {
|
||||
|
||||
String libraryResource(String path)
|
||||
|
||||
FileWrapper[] findFiles(String glob)
|
||||
|
||||
FileWrapper[] findFiles(String glob, String excludes)
|
||||
|
||||
String readFile(String file, String encoding)
|
||||
|
||||
void echo(message)
|
||||
@ -34,6 +39,8 @@ interface IStepExecutor {
|
||||
|
||||
def stash(String name, String includes)
|
||||
|
||||
def stash(String name, String includes, boolean allowEmpty)
|
||||
|
||||
def unstash(String name)
|
||||
|
||||
def zip(String dir, String zipFile)
|
||||
@ -45,4 +52,12 @@ interface IStepExecutor {
|
||||
def unzip(String dir, String zipFile, quiet)
|
||||
|
||||
def catchError(Closure body)
|
||||
|
||||
def httpRequest(String url, String outputFile, String responseHandle, boolean wrapAsMultipart)
|
||||
|
||||
def error(String errorMessage)
|
||||
|
||||
def allure(List<String> results)
|
||||
|
||||
def installLocalDependencies()
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
package ru.pulsar.jenkins.library
|
||||
|
||||
import org.jenkinsci.plugins.pipeline.utility.steps.fs.FileWrapper
|
||||
import org.jenkinsci.plugins.workflow.support.actions.EnvironmentAction
|
||||
import ru.yandex.qatools.allure.jenkins.config.ResultsConfig
|
||||
|
||||
class StepExecutor implements IStepExecutor {
|
||||
|
||||
@ -35,6 +37,11 @@ class StepExecutor implements IStepExecutor {
|
||||
steps.readFile encoding: encoding, file: file
|
||||
}
|
||||
|
||||
@Override
|
||||
FileWrapper[] findFiles(String glob, String excludes = '') {
|
||||
steps.findFiles glob: glob, excludes: excludes
|
||||
}
|
||||
|
||||
@Override
|
||||
void echo(Object message) {
|
||||
steps.echo message
|
||||
@ -80,8 +87,8 @@ class StepExecutor implements IStepExecutor {
|
||||
}
|
||||
|
||||
@Override
|
||||
def stash(String name, String includes) {
|
||||
steps.stash name: name, includes: includes
|
||||
def stash(String name, String includes, boolean allowEmpty = false) {
|
||||
steps.stash name: name, includes: includes, allowEmpty: allowEmpty
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -103,4 +110,31 @@ class StepExecutor implements IStepExecutor {
|
||||
def catchError(Closure body) {
|
||||
steps.catchError body
|
||||
}
|
||||
|
||||
@Override
|
||||
def httpRequest(String url, String outputFile, String responseHandle = 'NONE', boolean wrapAsMultipart = false) {
|
||||
steps.httpRequest responseHandle: responseHandle, outputFile: outputFile, url: url, wrapAsMultipart: wrapAsMultipart
|
||||
}
|
||||
|
||||
@Override
|
||||
def error(String errorMessage) {
|
||||
steps.error errorMessage
|
||||
}
|
||||
|
||||
@Override
|
||||
def allure(List<String> results) {
|
||||
steps.allure([
|
||||
commandline: 'allure',
|
||||
includeProperties: false,
|
||||
jdk: '',
|
||||
properties: [],
|
||||
reportBuildPolicy: 'ALWAYS',
|
||||
results: ResultsConfig.convertPaths(results)
|
||||
])
|
||||
}
|
||||
|
||||
@Override
|
||||
def installLocalDependencies() {
|
||||
steps.installLocalDependencies()
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,26 @@
|
||||
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 BddOptions implements Serializable {
|
||||
|
||||
@JsonPropertyDescription("""Шаги, запускаемые через vrunner.
|
||||
В каждой строке передается отдельная команда
|
||||
vrunner и ее аргументы (например, "vanessa --settings ./tools/vrunner.json").
|
||||
По умолчанию содержит одну команду "vanessa --settings ./tools/vrunner.json".
|
||||
""")
|
||||
String[] vrunnerSteps = [
|
||||
'vanessa --settings ./tools/vrunner.json'
|
||||
]
|
||||
|
||||
@Override
|
||||
@NonCPS
|
||||
String toString() {
|
||||
return "BddOptions{" +
|
||||
"vrunnerSteps=" + vrunnerSteps +
|
||||
'}';
|
||||
}
|
||||
}
|
@ -7,6 +7,8 @@ import org.apache.commons.beanutils.BeanUtils
|
||||
import ru.pulsar.jenkins.library.IStepExecutor
|
||||
import ru.pulsar.jenkins.library.ioc.ContextRegistry
|
||||
|
||||
import javax.annotation.CheckForNull
|
||||
|
||||
class ConfigurationReader implements Serializable {
|
||||
|
||||
private static ObjectMapper mapper
|
||||
@ -41,12 +43,16 @@ class ConfigurationReader implements Serializable {
|
||||
def nonMergeableSettings = Arrays.asList(
|
||||
"secrets",
|
||||
"stageFlags",
|
||||
"initInfobaseOptions",
|
||||
"bddOptions",
|
||||
"sonarQubeOptions",
|
||||
"syntaxCheckOptions",
|
||||
"resultsTransformOptions"
|
||||
).toSet()
|
||||
|
||||
mergeObjects(baseConfiguration, configurationToMerge, nonMergeableSettings)
|
||||
mergeInitInfobaseOptions(baseConfiguration.initInfobaseOptions, configurationToMerge.initInfobaseOptions);
|
||||
mergeBddOptions(baseConfiguration.bddOptions, configurationToMerge.bddOptions);
|
||||
|
||||
return baseConfiguration;
|
||||
}
|
||||
@ -70,4 +76,20 @@ class ConfigurationReader implements Serializable {
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
@NonCPS
|
||||
private static void mergeInitInfobaseOptions(InitInfobaseOptions baseObject, @CheckForNull InitInfobaseOptions objectToMerge) {
|
||||
if (objectToMerge == null || objectToMerge.additionalInitializationSteps == null) {
|
||||
return
|
||||
}
|
||||
baseObject.additionalInitializationSteps = objectToMerge.additionalInitializationSteps.clone()
|
||||
}
|
||||
|
||||
@NonCPS
|
||||
private static void mergeBddOptions(BddOptions baseObject, @CheckForNull BddOptions objectToMerge) {
|
||||
if (objectToMerge == null || objectToMerge.vrunnerSteps == null) {
|
||||
return
|
||||
}
|
||||
baseObject.vrunnerSteps = objectToMerge.vrunnerSteps.clone()
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,27 @@
|
||||
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 InitInfobaseOptions implements Serializable {
|
||||
|
||||
@JsonPropertyDescription("Запустить миграцию ИБ")
|
||||
boolean runMigration = true
|
||||
|
||||
@JsonPropertyDescription("""Дополнительные шаги, запускаемые через vrunner.
|
||||
В каждой строке передается отдельная команда
|
||||
vrunner и ее аргументы (например, "vanessa --settings ./tools/vrunner.first.json")
|
||||
""")
|
||||
String[] additionalInitializationSteps
|
||||
|
||||
@Override
|
||||
@NonCPS
|
||||
String toString() {
|
||||
return "InitInfobaseOptions{" +
|
||||
"runMigration=" + runMigration +
|
||||
", additionalInitializationSteps=" + additionalInitializationSteps +
|
||||
'}';
|
||||
}
|
||||
}
|
@ -20,6 +20,14 @@ class JobConfiguration implements Serializable {
|
||||
@JsonPropertyDescription("Идентификаторы сохраненных секретов")
|
||||
Secrets secrets;
|
||||
|
||||
@JsonProperty("initInfobase")
|
||||
@JsonPropertyDescription("Настройки шага инициализации ИБ")
|
||||
InitInfobaseOptions initInfobaseOptions;
|
||||
|
||||
@JsonProperty("bdd")
|
||||
@JsonPropertyDescription("Настройки шага запуска BDD сценариев")
|
||||
BddOptions bddOptions;
|
||||
|
||||
@JsonProperty("sonarqube")
|
||||
@JsonPropertyDescription("Настройки анализа SonarQube")
|
||||
SonarQubeOptions sonarQubeOptions;
|
||||
@ -32,6 +40,10 @@ class JobConfiguration implements Serializable {
|
||||
@JsonPropertyDescription("Настройки трансформации результатов анализа")
|
||||
ResultsTransformOptions resultsTransformOptions;
|
||||
|
||||
@JsonProperty("logosConfig")
|
||||
@JsonPropertyDescription("Конфигурация библиотеки logos. Применяется перед запуском каждой стадии сборки")
|
||||
String logosConfig;
|
||||
|
||||
@Override
|
||||
@NonCPS
|
||||
String toString() {
|
||||
@ -40,9 +52,12 @@ class JobConfiguration implements Serializable {
|
||||
", srcDir='" + srcDir + '\'' +
|
||||
", stageFlags=" + stageFlags +
|
||||
", secrets=" + secrets +
|
||||
", initInfobaseOptions=" + initInfobaseOptions +
|
||||
", bddOptions=" + bddOptions +
|
||||
", sonarQubeOptions=" + sonarQubeOptions +
|
||||
", syntaxCheckOptions=" + syntaxCheckOptions +
|
||||
", resultsTransformOptions=" + resultsTransformOptions +
|
||||
", logosConfig=" + logosConfig +
|
||||
'}';
|
||||
}
|
||||
}
|
@ -7,8 +7,8 @@ import com.fasterxml.jackson.annotation.JsonPropertyDescription
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
class ResultsTransformOptions implements Serializable {
|
||||
|
||||
@JsonPropertyDescription("Фильтровать замечания по уровню поддержки модуля")
|
||||
boolean removeSupport
|
||||
@JsonPropertyDescription("Фильтровать замечания по уровню поддержки модуля. По умолчанию включено.")
|
||||
boolean removeSupport = true
|
||||
|
||||
@JsonPropertyDescription("""Настройка фильтрации замечаний по уровню поддержки.
|
||||
0 - удалить файлы на замке;
|
||||
|
@ -18,6 +18,12 @@ class StageFlags implements Serializable {
|
||||
@JsonPropertyDescription("Дымовые тесты включены")
|
||||
boolean smoke
|
||||
|
||||
@JsonPropertyDescription("Предварительные шаги инициализации включены")
|
||||
boolean initSteps
|
||||
|
||||
@JsonPropertyDescription("Запуск BDD сценариев включен")
|
||||
boolean bdd
|
||||
|
||||
@Override
|
||||
@NonCPS
|
||||
String toString() {
|
||||
@ -26,10 +32,12 @@ class StageFlags implements Serializable {
|
||||
", syntaxCheck=" + syntaxCheck +
|
||||
", edtValidate=" + edtValidate +
|
||||
", smoke=" + smoke +
|
||||
", initSteps=" + initSteps +
|
||||
", bdd=" + bdd +
|
||||
'}';
|
||||
}
|
||||
|
||||
boolean needInfobase() {
|
||||
return smoke || syntaxCheck
|
||||
return smoke || syntaxCheck || initSteps || bdd
|
||||
}
|
||||
}
|
||||
|
@ -7,14 +7,23 @@ import com.fasterxml.jackson.annotation.JsonPropertyDescription
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
class SyntaxCheckOptions implements Serializable {
|
||||
|
||||
@JsonPropertyDescription("Путь к файлу отчета jUnit")
|
||||
String pathToJUnitReport
|
||||
@JsonPropertyDescription("""Путь к файлу отчета jUnit
|
||||
По умолчанию содержит значение "./build/out/jUnit/syntax.xml"
|
||||
""")
|
||||
String pathToJUnitReport = "./build/out/jUnit/syntax.xml"
|
||||
|
||||
@JsonPropertyDescription("Группировать выявленные ошибки по объектам метаданных")
|
||||
boolean groupErrorsByMetadata;
|
||||
@JsonPropertyDescription("""Группировать выявленные ошибки по объектам метаданных.
|
||||
По умолчанию включено.
|
||||
""")
|
||||
boolean groupErrorsByMetadata = true
|
||||
|
||||
@JsonPropertyDescription("Режимы проверки конфигурации")
|
||||
String[] checkModes;
|
||||
String[] checkModes
|
||||
|
||||
@JsonPropertyDescription("""Путь к конфигурационному файлу vanessa-runner.
|
||||
По умолчанию содержит значение "./tools/vrunner.json".
|
||||
""")
|
||||
String vrunnerSettings = "./tools/vrunner.json"
|
||||
|
||||
@Override
|
||||
@NonCPS
|
||||
@ -23,6 +32,7 @@ class SyntaxCheckOptions implements Serializable {
|
||||
"pathToJUnitReport='" + pathToJUnitReport + '\'' +
|
||||
", groupErrorsByMetadata=" + groupErrorsByMetadata +
|
||||
", checkModes=" + checkModes +
|
||||
", vrunnerSettings=" + vrunnerSettings +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
49
src/ru/pulsar/jenkins/library/steps/Bdd.groovy
Normal file
49
src/ru/pulsar/jenkins/library/steps/Bdd.groovy
Normal file
@ -0,0 +1,49 @@
|
||||
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 Bdd implements Serializable {
|
||||
|
||||
private final JobConfiguration config;
|
||||
|
||||
Bdd(JobConfiguration config) {
|
||||
this.config = config
|
||||
}
|
||||
|
||||
def run() {
|
||||
IStepExecutor steps = ContextRegistry.getContext().getStepExecutor()
|
||||
|
||||
Logger.printLocation()
|
||||
|
||||
if (!config.stageFlags.bdd) {
|
||||
Logger.println("BDD step is disabled")
|
||||
return
|
||||
}
|
||||
|
||||
List<String> logosConfig = ["LOGOS_CONFIG=$config.logosConfig"]
|
||||
steps.withEnv(logosConfig) {
|
||||
steps.installLocalDependencies()
|
||||
|
||||
steps.createDir('build/out')
|
||||
|
||||
// TODO: удалить после выхода VAS 1.0.35
|
||||
steps.httpRequest(
|
||||
'https://cloud.svc.pulsar.ru/index.php/s/WKwmqpFXSjfYjAH/download',
|
||||
'oscript_modules/vanessa-automation-single/vanessa-automation-single.epf'
|
||||
)
|
||||
|
||||
steps.catchError {
|
||||
config.bddOptions.vrunnerSteps.each {
|
||||
Logger.println("Шаг запуска сценариев командой ${it}")
|
||||
steps.cmd("oscript_modules/bin/vrunner ${it} --ibconnection \"/F./build/ib\"")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
steps.stash('bdd-allure', 'build/out/allure/**', true)
|
||||
steps.stash('bdd-cucumber', 'build/out/cucumber/**', true)
|
||||
}
|
||||
}
|
@ -1,5 +1,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
|
||||
@ -47,4 +48,5 @@ class EdtTransform implements Serializable {
|
||||
steps.zip(WORKSPACE, WORKSPACE_ZIP)
|
||||
steps.stash(WORKSPACE_ZIP_STASH, WORKSPACE_ZIP)
|
||||
}
|
||||
|
||||
}
|
||||
|
69
src/ru/pulsar/jenkins/library/steps/InitInfobase.groovy
Normal file
69
src/ru/pulsar/jenkins/library/steps/InitInfobase.groovy
Normal file
@ -0,0 +1,69 @@
|
||||
package ru.pulsar.jenkins.library.steps
|
||||
|
||||
import org.jenkinsci.plugins.pipeline.utility.steps.fs.FileWrapper
|
||||
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 InitInfobase implements Serializable {
|
||||
|
||||
private final JobConfiguration config;
|
||||
|
||||
InitInfobase(JobConfiguration config) {
|
||||
this.config = config
|
||||
}
|
||||
|
||||
def run() {
|
||||
IStepExecutor steps = ContextRegistry.getContext().getStepExecutor()
|
||||
|
||||
Logger.printLocation()
|
||||
|
||||
steps.createDir('build/out')
|
||||
|
||||
if (!config.stageFlags.initSteps) {
|
||||
Logger.println("Init step is disabled")
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: удалить после выхода VAS 1.0.35
|
||||
steps.httpRequest(
|
||||
'https://cloud.svc.pulsar.ru/index.php/s/WKwmqpFXSjfYjAH/download',
|
||||
'oscript_modules/vanessa-automation-single/vanessa-automation-single.epf'
|
||||
)
|
||||
|
||||
List<String> logosConfig = ["LOGOS_CONFIG=$config.logosConfig"]
|
||||
steps.withEnv(logosConfig) {
|
||||
|
||||
if (config.initInfobaseOptions.runMigration) {
|
||||
Logger.println("Запуск миграции ИБ")
|
||||
|
||||
// Запуск миграции
|
||||
steps.catchError {
|
||||
steps.cmd('oscript_modules/bin/vrunner run --command "ЗапуститьОбновлениеИнформационнойБазы;ЗавершитьРаботуСистемы;" --execute \\$runnerRoot/epf/ЗакрытьПредприятие.epf --ibconnection "/F./build/ib"')
|
||||
}
|
||||
} else {
|
||||
Logger.println("Шаг миграции ИБ выключен")
|
||||
}
|
||||
|
||||
steps.catchError {
|
||||
if (config.initInfobaseOptions.additionalInitializationSteps.length == 0) {
|
||||
FileWrapper[] files = steps.findFiles("tools/vrunner.init*.json")
|
||||
files = files.sort new OrderBy( { it.name })
|
||||
files.each {
|
||||
Logger.println("Первичная инициализация файлом ${it.path}")
|
||||
steps.cmd("oscript_modules/bin/vrunner vanessa --settings ${it.path} --ibconnection \"/F./build/ib\"")
|
||||
}
|
||||
} else {
|
||||
config.initInfobaseOptions.additionalInitializationSteps.each {
|
||||
Logger.println("Первичная инициализация командой ${it}")
|
||||
steps.cmd("oscript_modules/bin/vrunner ${it} --ibconnection \"/F./build/ib\"")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
steps.stash('init-allure', 'build/out/allure/**', true)
|
||||
steps.stash('init-cucumber', 'build/out/cucumber/**', true)
|
||||
}
|
||||
}
|
54
src/ru/pulsar/jenkins/library/steps/PublishAllure.groovy
Normal file
54
src/ru/pulsar/jenkins/library/steps/PublishAllure.groovy
Normal file
@ -0,0 +1,54 @@
|
||||
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
|
||||
|
||||
class PublishAllure implements Serializable {
|
||||
|
||||
private final JobConfiguration config;
|
||||
private IStepExecutor steps;
|
||||
|
||||
PublishAllure(JobConfiguration config) {
|
||||
this.config = config
|
||||
}
|
||||
|
||||
def run() {
|
||||
steps = ContextRegistry.getContext().getStepExecutor()
|
||||
|
||||
Logger.printLocation()
|
||||
|
||||
safeUnstash('init-allure')
|
||||
safeUnstash('bdd-allure')
|
||||
|
||||
def env = steps.env();
|
||||
|
||||
FilePath allurePath = FileUtils.getFilePath("$env.WORKSPACE/build/out/allure")
|
||||
if (!allurePath.exists()) {
|
||||
Logger.println("Отсутствуют результаты allure для публикации")
|
||||
return
|
||||
}
|
||||
|
||||
List<String> results = new ArrayList<>();
|
||||
|
||||
allurePath.listDirectories().each { FilePath filePath ->
|
||||
results.add(FileUtils.getLocalPath(filePath))
|
||||
}
|
||||
if (results.isEmpty()) {
|
||||
results.add(FileUtils.getLocalPath(allurePath))
|
||||
}
|
||||
|
||||
steps.allure(results)
|
||||
}
|
||||
|
||||
private void safeUnstash(String stashName) {
|
||||
try {
|
||||
steps.unstash(stashName)
|
||||
} catch (Exception ex) {
|
||||
Logger.println("Can't unstash $stashName")
|
||||
}
|
||||
}
|
||||
}
|
35
src/ru/pulsar/jenkins/library/utils/FileUtils.groovy
Normal file
35
src/ru/pulsar/jenkins/library/utils/FileUtils.groovy
Normal file
@ -0,0 +1,35 @@
|
||||
package ru.pulsar.jenkins.library.utils
|
||||
|
||||
import hudson.FilePath
|
||||
import jenkins.model.Jenkins
|
||||
import ru.pulsar.jenkins.library.IStepExecutor
|
||||
import ru.pulsar.jenkins.library.ioc.ContextRegistry
|
||||
|
||||
class FileUtils {
|
||||
|
||||
static FilePath getFilePath(String path) {
|
||||
|
||||
IStepExecutor steps = ContextRegistry.getContext().getStepExecutor()
|
||||
|
||||
def env = steps.env();
|
||||
|
||||
String nodeName = env.NODE_NAME;
|
||||
if (nodeName == null) {
|
||||
steps.error 'Переменная среды NODE_NAME не задана. Запуск вне node или без agent?'
|
||||
}
|
||||
|
||||
if (nodeName == "master") {
|
||||
return new FilePath(new File(path));
|
||||
} else {
|
||||
return new FilePath(Jenkins.getInstanceOrNull().getComputer(nodeName).getChannel(), path);
|
||||
}
|
||||
}
|
||||
|
||||
static String getLocalPath(FilePath filePath) {
|
||||
IStepExecutor steps = ContextRegistry.getContext().getStepExecutor()
|
||||
|
||||
def env = steps.env();
|
||||
|
||||
return filePath.getRemote().replaceAll("^$env.WORKSPACE/", "").toString()
|
||||
}
|
||||
}
|
@ -31,14 +31,25 @@ class ConfigurationReaderTest {
|
||||
|
||||
// then
|
||||
assertThat(jobConfiguration.getV8version()).isEqualTo("8.3.14.1944");
|
||||
|
||||
assertThat(jobConfiguration.getSonarQubeOptions().getSonarScannerToolName()).isEqualTo("sonar-scanner");
|
||||
|
||||
assertThat(jobConfiguration.getSecrets())
|
||||
.hasFieldOrPropertyWithValue("storage", "1234")
|
||||
.hasFieldOrPropertyWithValue("storagePath", "UNKNOWN_ID")
|
||||
;
|
||||
|
||||
assertThat(jobConfiguration.getSyntaxCheckOptions().getCheckModes()).hasSize(1);
|
||||
assertThat(jobConfiguration.getResultsTransformOptions().isRemoveSupport()).isTrue();
|
||||
assertThat(jobConfiguration.getResultsTransformOptions().getSupportLevel()).isEqualTo(0);
|
||||
|
||||
assertThat(jobConfiguration.getResultsTransformOptions().isRemoveSupport()).isFalse();
|
||||
assertThat(jobConfiguration.getResultsTransformOptions().getSupportLevel()).isZero();
|
||||
|
||||
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.getLogosConfig()).isEqualTo("logger.rootLogger=DEBUG");
|
||||
}
|
||||
|
||||
}
|
@ -6,10 +6,17 @@
|
||||
"stages": {
|
||||
"syntaxCheck": true
|
||||
},
|
||||
"initInfobase": {
|
||||
"runMigration": false,
|
||||
"additionalInitializationSteps": [
|
||||
"vanessa --settings ./tools/vrunner.first.json"
|
||||
]
|
||||
},
|
||||
"syntaxCheck": {
|
||||
"checkModes": ["-ThinClient"]
|
||||
},
|
||||
"resultsTransform": {
|
||||
"removeSupport": true
|
||||
}
|
||||
"removeSupport": false
|
||||
},
|
||||
"logosConfig": "logger.rootLogger=DEBUG"
|
||||
}
|
10
vars/bdd.groovy
Normal file
10
vars/bdd.groovy
Normal file
@ -0,0 +1,10 @@
|
||||
import ru.pulsar.jenkins.library.configuration.JobConfiguration
|
||||
import ru.pulsar.jenkins.library.ioc.ContextRegistry
|
||||
import ru.pulsar.jenkins.library.steps.Bdd
|
||||
|
||||
def call(JobConfiguration config) {
|
||||
ContextRegistry.registerDefaultContext(this)
|
||||
|
||||
def bdd = new Bdd(config)
|
||||
bdd.run()
|
||||
}
|
10
vars/initInfobase.groovy
Normal file
10
vars/initInfobase.groovy
Normal file
@ -0,0 +1,10 @@
|
||||
import ru.pulsar.jenkins.library.configuration.JobConfiguration
|
||||
import ru.pulsar.jenkins.library.ioc.ContextRegistry
|
||||
import ru.pulsar.jenkins.library.steps.InitInfobase
|
||||
|
||||
def call(JobConfiguration config) {
|
||||
ContextRegistry.registerDefaultContext(this)
|
||||
|
||||
def initInfobase = new InitInfobase(config)
|
||||
initInfobase.run()
|
||||
}
|
@ -27,6 +27,7 @@ void call() {
|
||||
agent {
|
||||
label 'agent'
|
||||
}
|
||||
|
||||
steps {
|
||||
script {
|
||||
config = jobConfiguration() as JobConfiguration
|
||||
@ -46,18 +47,41 @@ void call() {
|
||||
expression { config.stageFlags.needInfobase() }
|
||||
}
|
||||
|
||||
steps {
|
||||
printLocation()
|
||||
stages {
|
||||
stage('Создание ИБ') {
|
||||
steps {
|
||||
printLocation()
|
||||
|
||||
installLocalDependencies()
|
||||
installLocalDependencies()
|
||||
|
||||
dir("build/out") { echo '' }
|
||||
createDir('build/out')
|
||||
|
||||
// Создание базы загрузкой конфигурации из хранилища
|
||||
initFromStorage config
|
||||
// Создание базы загрузкой конфигурации из хранилища
|
||||
initFromStorage config
|
||||
}
|
||||
}
|
||||
|
||||
zipInfobase()
|
||||
stage('Инициализация ИБ') {
|
||||
when {
|
||||
beforeAgent true
|
||||
expression { config.stageFlags.initSteps }
|
||||
}
|
||||
steps {
|
||||
// Инициализация и первичная миграция
|
||||
initInfobase config
|
||||
}
|
||||
}
|
||||
|
||||
stage('Архивация ИБ') {
|
||||
steps {
|
||||
printLocation()
|
||||
|
||||
zipInfobase()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
stage('Трансформация в формат EDT') {
|
||||
@ -90,6 +114,21 @@ void call() {
|
||||
}
|
||||
}
|
||||
|
||||
stage('BDD сценарии') {
|
||||
agent {
|
||||
label agent1C
|
||||
}
|
||||
when {
|
||||
beforeAgent true
|
||||
expression { config.stageFlags.bdd }
|
||||
}
|
||||
steps {
|
||||
unzipInfobase()
|
||||
|
||||
bdd config
|
||||
}
|
||||
}
|
||||
|
||||
stage('Синтаксический контроль') {
|
||||
agent {
|
||||
label agent1C
|
||||
@ -144,6 +183,14 @@ void call() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
post('post-stage') {
|
||||
always {
|
||||
node('agent') {
|
||||
saveResults config
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
32
vars/saveResults.groovy
Normal file
32
vars/saveResults.groovy
Normal file
@ -0,0 +1,32 @@
|
||||
import ru.pulsar.jenkins.library.configuration.JobConfiguration
|
||||
import ru.pulsar.jenkins.library.ioc.ContextRegistry
|
||||
import ru.pulsar.jenkins.library.steps.PublishAllure
|
||||
|
||||
def call(JobConfiguration config) {
|
||||
ContextRegistry.registerDefaultContext(this)
|
||||
|
||||
def publishAllure = new PublishAllure(config)
|
||||
publishAllure.run()
|
||||
|
||||
// step([
|
||||
// $class: 'CucumberReportPublisher',
|
||||
// fileIncludePattern: '*.json',
|
||||
// jsonReportDirectory: 'build/out/cucumber'
|
||||
// ])
|
||||
//
|
||||
// step([
|
||||
// $class: 'CukedoctorPublisher',
|
||||
// featuresDir: 'build/out/cucumber',
|
||||
// format: 'HTML',
|
||||
// hideFeaturesSection: false,
|
||||
// hideScenarioKeyword: false,
|
||||
// hideStepTime: false,
|
||||
// hideSummary: false,
|
||||
// hideTags: false,
|
||||
// numbered: true,
|
||||
// sectAnchors: true,
|
||||
// title: 'Living Documentation',
|
||||
// toc: 'LEFT'
|
||||
// ])
|
||||
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
import hudson.FilePath
|
||||
import ru.pulsar.jenkins.library.configuration.JobConfiguration
|
||||
import ru.pulsar.jenkins.library.ioc.ContextRegistry
|
||||
import ru.pulsar.jenkins.library.utils.FileUtils
|
||||
|
||||
def call(JobConfiguration config) {
|
||||
|
||||
@ -20,27 +22,37 @@ def call(JobConfiguration config) {
|
||||
|
||||
unzipInfobase()
|
||||
|
||||
def outPath = new File(options.pathToJUnitReport).getParent()
|
||||
FilePath pathToJUnitReport = FileUtils.getFilePath("$env.WORKSPACE/$options.pathToJUnitReport")
|
||||
|
||||
String outPath = pathToJUnitReport.getParent()
|
||||
createDir(outPath)
|
||||
|
||||
String command = "oscript_modules/bin/vrunner syntax-check --ibconnection \"/F./build/ib\""
|
||||
String command = 'oscript_modules/bin/vrunner syntax-check --ibconnection "/F./build/ib"'
|
||||
|
||||
// Временно убрал передачу параметра.
|
||||
// См. https://github.com/vanessa-opensource/vanessa-runner/issues/361
|
||||
// command += " --workspace $env.WORKSPACE"
|
||||
|
||||
if (options.groupErrorsByMetadata) {
|
||||
command += " --groupbymetadata"
|
||||
command += ' --groupbymetadata'
|
||||
}
|
||||
|
||||
command += " --junitpath " + options.pathToJUnitReport;
|
||||
command += " --junitpath $pathToJUnitReport";
|
||||
|
||||
command += " --mode " + options.checkModes.join(" ")
|
||||
FilePath vrunnerSettings = FileUtils.getFilePath("$env.WORKSPACE/$options.vrunnerSettings")
|
||||
if (vrunnerSettings.exists()) {
|
||||
command += " --settings $vrunnerSettings";
|
||||
}
|
||||
|
||||
if (options.checkModes.length > 0) {
|
||||
def checkModes = options.checkModes.join(" ")
|
||||
command += " --mode $checkModes"
|
||||
}
|
||||
|
||||
// Запуск синтакс-проверки
|
||||
cmd(command, true)
|
||||
|
||||
junit allowEmptyResults: true, testResults: options.pathToJUnitReport
|
||||
junit allowEmptyResults: true, testResults: FileUtils.getLocalPath(pathToJUnitReport)
|
||||
|
||||
archiveArtifacts options.pathToJUnitReport
|
||||
archiveArtifacts FileUtils.getLocalPath(pathToJUnitReport)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user