Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
nixel2007 committed Apr 30, 2020
2 parents 9936871 + c4ac74b commit fb6f0e1
Show file tree
Hide file tree
Showing 26 changed files with 507 additions and 46 deletions.
20 changes: 16 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
Создание библиотеки (или плагина) для Jenkins, позволяющей:

* максимально упростить написание Jenkinsfile для процесса CI в условиях платформы 1С:Предприятие 8
* иметь схожий и контроллируемый пайплайн для всех проектов
* иметь схожий и контролируемый пайплайн для всех проектов
* дать пользователю в руки простой декларативный конфигурационный файл, вместо требования описывать всю сложную логику по работе с 1С

## Общие положения
Expand All @@ -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
Expand All @@ -48,7 +58,7 @@ pipeline1C()

> Да, вот и весь пайплайн. Конфигурирование через json.
## Конфигуирование
## Конфигурирование

По умолчанию применяется [файл конфигурации из ресурсов библиотеки](resources/globalConfiguration.json)

Expand All @@ -57,18 +67,20 @@ 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",
"storage" : "c1fc5f33-67d4-493f-a2a4-97d3040e4b8c"
},
"stages": {
"sonarqube": true,
"edtValidation": true,
"syntaxCheck": true
}
}
Expand Down
9 changes: 8 additions & 1 deletion resources/globalConfiguration.json
Original file line number Diff line number Diff line change
@@ -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": "",
Expand All @@ -29,5 +32,9 @@
"-CheckUseSynchronousCalls",
"-DistributiveModules"
]
},
"resultsTransform": {
"removeSupport": false,
"supportLevel": 0
}
}
27 changes: 27 additions & 0 deletions resources/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -33,6 +37,14 @@
"syntaxCheck" : {
"type" : "boolean",
"description" : "Синтаксический контроль включен"
},
"edtValidate" : {
"type" : "boolean",
"description" : "Валидация EDT включена"
},
"smoke" : {
"type" : "boolean",
"description" : "Дымовые тесты включены"
}
}
},
Expand Down Expand Up @@ -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 "
}
}
}
}
}
24 changes: 22 additions & 2 deletions src/ru/pulsar/jenkins/library/IStepExecutor.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -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<String> 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)
}
46 changes: 44 additions & 2 deletions src/ru/pulsar/jenkins/library/StepExecutor.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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<String> 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
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ class ConfigurationReader implements Serializable {
"secrets",
"stageFlags",
"sonarQubeOptions",
"syntaxCheckOptions"
"syntaxCheckOptions",
"resultsTransformOptions"
).toSet()

mergeObjects(baseConfiguration, configurationToMerge, nonMergeableSettings)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ class JobConfiguration implements Serializable {
@JsonPropertyDescription("Версия платформы 1С:Предприятие в формате 8.3.хх.хххх.")
String v8version

@JsonPropertyDescription("Путь к корневому каталогу с исходниками конфигурации")
String srcDir

@JsonProperty("stages")
@JsonPropertyDescription("Включение этапов сборок")
StageFlags stageFlags;
Expand All @@ -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 +
'}';
}
}
Original file line number Diff line number Diff line change
@@ -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 +
'}';
}
}
14 changes: 13 additions & 1 deletion src/ru/pulsar/jenkins/library/configuration/StageFlags.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
50 changes: 50 additions & 0 deletions src/ru/pulsar/jenkins/library/steps/EdtTransform.groovy
Original file line number Diff line number Diff line change
@@ -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)
}
}
Loading

0 comments on commit fb6f0e1

Please sign in to comment.