diff --git a/README.md b/README.md index 89c095ea..3a20bba0 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,7 @@ 1. Для шага подготовки требуется любой агент с меткой `agent`. 1. Для запуска шага анализа SonarQube требуется агент с меткой `sonar`. 1. Для запуска шагов, работающих с EDT (валидация, трансформация формата исходников) требуется агент с меткой `edt` (если используется несколько версий EDT необходимо к метке добавить версию, например `edt@2021.3.4:x86_64`) и агент с меткой `oscript`, на котором глобально установлена библиотека [stebi](https://github.com/Stepa86/stebi) версии 1.11.1 и выше или [edt-ripper](https://github.com/bia-technologies/edt_ripper). +1. При использовании EDT версии 2024.1.0 и выше вместо ring используется 1cedtcli, который должен быть прописан в PATH на агенте. 1. Для запуска шагов, работающих с 1С (подготовка, синтаксический контроль и т.д.) требуется агент с меткой, совпадающей со значением в поле `v8version` файла конфигурации. 1. В качестве ИБ используется файловая база, создаваемая в каталоге `./build/ib`. При необходимости вы можете создать пользователей на фазе инициализации ИБ. diff --git a/src/ru/pulsar/jenkins/library/edt/EdtCliEngineFactory.groovy b/src/ru/pulsar/jenkins/library/edt/EdtCliEngineFactory.groovy new file mode 100644 index 00000000..02ebc8b0 --- /dev/null +++ b/src/ru/pulsar/jenkins/library/edt/EdtCliEngineFactory.groovy @@ -0,0 +1,40 @@ +package ru.pulsar.jenkins.library.edt + +import java.lang.module.ModuleDescriptor + +class EdtCliEngineFactory { + + private static final ModuleDescriptor.Version EDT_CLI_MIN_VERSION = ModuleDescriptor.Version.parse("2024") + + /** + * Создает движок конвертации в зависимости от версии EDT + * @param edtVersion версия EDT в формате YYYY.X.Z, YYYY.X или YYYY + * @return IEdtCliEngine подходящая реализация движка + * @throws IllegalArgumentException если версия имеет некорректный формат + */ + static IEdtCliEngine getEngine(String edtVersion) { + + if (edtVersion == null || edtVersion.trim().empty) { + throw new IllegalArgumentException("Версия EDT не может быть пустой") + } + + try { + def currentVersion = ModuleDescriptor.Version.parse(edtVersion) + + return isEdtCliRequired(currentVersion) + ? new NativeEdtCliConverter() + : new RingConverter() + } catch (IllegalArgumentException e) { + throw new IllegalArgumentException("Некорректный формат версии EDT: ${edtVersion}", e) + } + } + + /** + * Проверяет необходимость использования 1cedtcli + * @param edtVersion текущая версия EDT + * @return true если нужно использовать 1cedtcli + */ + private static boolean isEdtCliRequired (ModuleDescriptor.Version edtVersion) { + return edtVersion >= EDT_CLI_MIN_VERSION + } +} diff --git a/src/ru/pulsar/jenkins/library/edt/IEdtCliEngine.groovy b/src/ru/pulsar/jenkins/library/edt/IEdtCliEngine.groovy new file mode 100644 index 00000000..d5ce6330 --- /dev/null +++ b/src/ru/pulsar/jenkins/library/edt/IEdtCliEngine.groovy @@ -0,0 +1,11 @@ +package ru.pulsar.jenkins.library.edt + +import ru.pulsar.jenkins.library.IStepExecutor +import ru.pulsar.jenkins.library.configuration.JobConfiguration + +interface IEdtCliEngine { + void edtToDesignerTransformConfiguration(IStepExecutor steps, JobConfiguration config); + void edtToDesignerTransformExtensions(IStepExecutor steps, JobConfiguration config); + void designerToEdtTransform(IStepExecutor steps, JobConfiguration config); + void edtValidate(IStepExecutor steps, JobConfiguration config, String projectList); +} diff --git a/src/ru/pulsar/jenkins/library/edt/NativeEdtCliConverter.groovy b/src/ru/pulsar/jenkins/library/edt/NativeEdtCliConverter.groovy new file mode 100644 index 00000000..c553f38d --- /dev/null +++ b/src/ru/pulsar/jenkins/library/edt/NativeEdtCliConverter.groovy @@ -0,0 +1,94 @@ +package ru.pulsar.jenkins.library.edt + +import ru.pulsar.jenkins.library.IStepExecutor +import ru.pulsar.jenkins.library.configuration.InitExtensionMethod +import ru.pulsar.jenkins.library.configuration.JobConfiguration +import ru.pulsar.jenkins.library.steps.DesignerToEdtFormatTransformation +import ru.pulsar.jenkins.library.steps.EdtToDesignerFormatTransformation +import ru.pulsar.jenkins.library.steps.EdtValidate +import ru.pulsar.jenkins.library.utils.FileUtils +import ru.pulsar.jenkins.library.utils.Logger + +class NativeEdtCliConverter implements IEdtCliEngine { + + @Override + void edtToDesignerTransformConfiguration(IStepExecutor steps, JobConfiguration config) { + + def env = steps.env() + + String workspaceDir = FileUtils.getFilePath("$env.WORKSPACE/$EdtToDesignerFormatTransformation.WORKSPACE").getRemote() + String projectWorkspaceDir = FileUtils.getFilePath("$workspaceDir/cf").getRemote() + def configurationRoot = FileUtils.getFilePath("$env.WORKSPACE/$EdtToDesignerFormatTransformation.CONFIGURATION_DIR") + String configurationRootFullPath = configurationRoot.getRemote() + + Logger.println("Конвертация исходников конфигурации из формата EDT в формат Конфигуратора с помощью 1cedtcli") + + steps.deleteDir(configurationRoot) + + def projectName = configurationRoot.getName() + def edtcliCommand = "1cedtcli -data \"$projectWorkspaceDir\" -command export --configuration-files \"$configurationRootFullPath\" --project-name \"$projectName\"" + + steps.cmd(edtcliCommand) + + } + + @Override + void edtToDesignerTransformExtensions(IStepExecutor steps, JobConfiguration config) { + + def env = steps.env() + + String workspaceDir = FileUtils.getFilePath("$env.WORKSPACE/$EdtToDesignerFormatTransformation.WORKSPACE").getRemote() + String extensionRoot = FileUtils.getFilePath("$env.WORKSPACE/$EdtToDesignerFormatTransformation.EXTENSION_DIR").getRemote() + + config.initInfoBaseOptions.extensions.each { + + if (it.initMethod != InitExtensionMethod.SOURCE) { + return + } + + Logger.println("Конвертация исходников расширения ${it.name} из формата EDT в формат Конфигуратора с помощью 1cedtcli") + def currentExtensionWorkspaceDir = FileUtils.getFilePath("$workspaceDir/cfe/${it.name}") + + def edtcliCommand = "1cedtcli -data \"$currentExtensionWorkspaceDir\" -command export --configuration-files \"$extensionRoot/${it.name}\" --project-name ${it.name}" + + steps.cmd(edtcliCommand) + + } + + } + + @Override + void designerToEdtTransform(IStepExecutor steps, JobConfiguration config) { + + def env = steps.env() + + def workspaceDir = FileUtils.getFilePath("$env.WORKSPACE/$DesignerToEdtFormatTransformation.WORKSPACE") + def srcDir = config.srcDir + def configurationRoot = FileUtils.getFilePath("$env.WORKSPACE/$srcDir") + def projectName = configurationRoot.getName() + + steps.deleteDir(workspaceDir) + + Logger.println("Конвертация исходников из формата конфигуратора в формат EDT с помощью 1cedtcli") + + def edtcliCommand = "1cedtcli -data \"$workspaceDir\" -command import --configuration-files \"$configurationRoot\" --project-name \"$projectName\"" + + steps.cmd(edtcliCommand) + + } + + @Override + void edtValidate(IStepExecutor steps, JobConfiguration config, String projectList) { + + def env = steps.env() + + String workspaceLocation = "$env.WORKSPACE/$DesignerToEdtFormatTransformation.WORKSPACE" + def resultFile = "$env.WORKSPACE/$EdtValidate.RESULT_FILE" + + def edtcliCommand = "1cedtcli -data \"$workspaceLocation\" -command validate --file \"$resultFile\" $projectList" + steps.catchError { + steps.cmd(edtcliCommand) + } + + } +} diff --git a/src/ru/pulsar/jenkins/library/edt/RingConverter.groovy b/src/ru/pulsar/jenkins/library/edt/RingConverter.groovy new file mode 100644 index 00000000..8a0658a9 --- /dev/null +++ b/src/ru/pulsar/jenkins/library/edt/RingConverter.groovy @@ -0,0 +1,100 @@ +package ru.pulsar.jenkins.library.edt + +import ru.pulsar.jenkins.library.IStepExecutor +import ru.pulsar.jenkins.library.configuration.InitExtensionMethod +import ru.pulsar.jenkins.library.configuration.JobConfiguration +import ru.pulsar.jenkins.library.steps.DesignerToEdtFormatTransformation +import ru.pulsar.jenkins.library.steps.EdtToDesignerFormatTransformation +import ru.pulsar.jenkins.library.steps.EdtValidate +import ru.pulsar.jenkins.library.utils.EDT +import ru.pulsar.jenkins.library.utils.FileUtils +import ru.pulsar.jenkins.library.utils.Logger + +class RingConverter implements IEdtCliEngine { + + @Override + void edtToDesignerTransformConfiguration(IStepExecutor steps, JobConfiguration config) { + + def env = steps.env() + def edtVersionForRing = EDT.ringModule(config) + def srcDir = config.srcDir + + String workspaceDir = FileUtils.getFilePath("$env.WORKSPACE/$EdtToDesignerFormatTransformation.WORKSPACE").getRemote() + String projectWorkspaceDir = FileUtils.getFilePath("$workspaceDir/cf").getRemote() + String projectDir = FileUtils.getFilePath("$env.WORKSPACE/$srcDir").getRemote() + String configurationRoot = FileUtils.getFilePath("$env.WORKSPACE/$EdtToDesignerFormatTransformation.CONFIGURATION_DIR").getRemote() + + Logger.println("Конвертация исходников конфигурации из формата EDT в формат Конфигуратора с помощью ring") + + steps.deleteDir(configurationRoot) + + def ringCommand = "ring $edtVersionForRing workspace export --workspace-location \"$projectWorkspaceDir\" --project \"$projectDir\" --configuration-files \"$configurationRoot\"" + steps.ringCommand(ringCommand) + + } + + @Override + void edtToDesignerTransformExtensions(IStepExecutor steps, JobConfiguration config) { + + def env = steps.env() + + String workspaceDir = FileUtils.getFilePath("$env.WORKSPACE/$EdtToDesignerFormatTransformation.WORKSPACE").getRemote() + def edtVersionForRing = EDT.ringModule(config) + String extensionRoot = FileUtils.getFilePath("$env.WORKSPACE/$EdtToDesignerFormatTransformation.EXTENSION_DIR").getRemote() + + config.initInfoBaseOptions.extensions.each { + + if (it.initMethod != InitExtensionMethod.SOURCE) { + return + } + + Logger.println("Конвертация исходников расширения ${it.name} из формата EDT в формат Конфигуратора с помощью ring") + + def projectDir = FileUtils.getFilePath("$env.WORKSPACE/${it.path}") + def currentExtensionWorkspaceDir = FileUtils.getFilePath("$workspaceDir/cfe/${it.name}") + def ringCommand = "ring $edtVersionForRing workspace export --workspace-location \"$currentExtensionWorkspaceDir\" --project \"$projectDir\" --configuration-files \"$extensionRoot/${it.name}\"" + steps.ringCommand(ringCommand) + } + } + + @Override + void designerToEdtTransform(IStepExecutor steps, JobConfiguration config) { + + def env = steps.env() + + def workspaceDir = FileUtils.getFilePath("$env.WORKSPACE/$DesignerToEdtFormatTransformation.WORKSPACE") + def srcDir = config.srcDir + def configurationRoot = FileUtils.getFilePath("$env.WORKSPACE/$srcDir") + def projectName = configurationRoot.getName() + + steps.deleteDir(workspaceDir) + steps.deleteDir(configurationRoot) + + Logger.println("Конвертация исходников из формата конфигуратора в формат EDT с помощью ring") + + String edtVersionForRing = EDT.ringModule(config) + String ringCommand = "ring $edtVersionForRing workspace import --configuration-files \"$configurationRoot\" --project-name \"$projectName\" --workspace-location \"$workspaceDir\"" + + steps.ringCommand(ringCommand) + + } + + @Override + void edtValidate(IStepExecutor steps, JobConfiguration config, String projectList) { + + def env = steps.env() + + def edtVersionForRing = EDT.ringModule(config) + String workspaceLocation = "$env.WORKSPACE/$DesignerToEdtFormatTransformation.WORKSPACE" + + def resultFile = "$env.WORKSPACE/$EdtValidate.RESULT_FILE" + + Logger.println("Версия EDT меньше 2024.1.X, для валидации используется ring") + + def ringCommand = "ring $edtVersionForRing workspace validate --workspace-location \"$workspaceLocation\" --file \"$resultFile\" $projectList" + steps.catchError { + steps.ringCommand(ringCommand) + } + + } +} diff --git a/src/ru/pulsar/jenkins/library/steps/DesignerToEdtFormatTransformation.groovy b/src/ru/pulsar/jenkins/library/steps/DesignerToEdtFormatTransformation.groovy index 320fb609..e9aa06f8 100644 --- a/src/ru/pulsar/jenkins/library/steps/DesignerToEdtFormatTransformation.groovy +++ b/src/ru/pulsar/jenkins/library/steps/DesignerToEdtFormatTransformation.groovy @@ -1,11 +1,9 @@ package ru.pulsar.jenkins.library.steps - +import ru.pulsar.jenkins.library.edt.EdtCliEngineFactory 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.EDT -import ru.pulsar.jenkins.library.utils.FileUtils import ru.pulsar.jenkins.library.utils.Logger class DesignerToEdtFormatTransformation implements Serializable { @@ -30,21 +28,8 @@ class DesignerToEdtFormatTransformation implements Serializable { return } - def env = steps.env() - - def workspaceDir = FileUtils.getFilePath("$env.WORKSPACE/$WORKSPACE") - def srcDir = config.srcDir - def configurationRoot = FileUtils.getFilePath("$env.WORKSPACE/$srcDir") - def projectName = configurationRoot.getName() - def edtVersionForRing = EDT.ringModule(config) - - steps.deleteDir(workspaceDir) - - Logger.println("Конвертация исходников из формата конфигуратора в формат EDT") - - def ringCommand = "ring $edtVersionForRing workspace import --configuration-files \"$configurationRoot\" --project-name $projectName --workspace-location \"$workspaceDir\"" - - steps.ringCommand(ringCommand) + def engine = EdtCliEngineFactory.getEngine(config.edtVersion) + engine.designerToEdtTransform(steps, config) steps.zip(WORKSPACE, WORKSPACE_ZIP) steps.stash(WORKSPACE_ZIP_STASH, WORKSPACE_ZIP) diff --git a/src/ru/pulsar/jenkins/library/steps/EdtToDesignerFormatTransformation.groovy b/src/ru/pulsar/jenkins/library/steps/EdtToDesignerFormatTransformation.groovy index 672168ff..13f5af05 100644 --- a/src/ru/pulsar/jenkins/library/steps/EdtToDesignerFormatTransformation.groovy +++ b/src/ru/pulsar/jenkins/library/steps/EdtToDesignerFormatTransformation.groovy @@ -1,12 +1,10 @@ package ru.pulsar.jenkins.library.steps - +import ru.pulsar.jenkins.library.edt.EdtCliEngineFactory import ru.pulsar.jenkins.library.IStepExecutor import ru.pulsar.jenkins.library.configuration.JobConfiguration import ru.pulsar.jenkins.library.configuration.SourceFormat -import ru.pulsar.jenkins.library.configuration.InitExtensionMethod import ru.pulsar.jenkins.library.ioc.ContextRegistry -import ru.pulsar.jenkins.library.utils.EDT import ru.pulsar.jenkins.library.utils.FileUtils import ru.pulsar.jenkins.library.utils.Logger @@ -38,57 +36,19 @@ class EdtToDesignerFormatTransformation implements Serializable { def env = steps.env(); - String srcDir = config.srcDir String workspaceDir = FileUtils.getFilePath("$env.WORKSPACE/$WORKSPACE").getRemote() - - String projectWorkspaceDir = FileUtils.getFilePath("$workspaceDir/cf").getRemote() - String projectDir = FileUtils.getFilePath("$env.WORKSPACE/$srcDir").getRemote() - String configurationRoot = FileUtils.getFilePath("$env.WORKSPACE/$CONFIGURATION_DIR").getRemote() - - - String extensionRoot = FileUtils.getFilePath("$env.WORKSPACE/$EXTENSION_DIR").getRemote() - def edtVersionForRing = EDT.ringModule(config) - steps.deleteDir(workspaceDir) - transformConfiguration(steps, projectDir, projectWorkspaceDir, configurationRoot, edtVersionForRing) - transformExtensions(steps, workspaceDir, extensionRoot, edtVersionForRing) - } - - private void transformConfiguration(IStepExecutor steps, String projectDir, String projectWorkspaceDir, String configurationRoot, String edtVersionForRing) { - - Logger.println("Конвертация исходников конфигурации из формата EDT в формат Конфигуратора") - steps.deleteDir(configurationRoot) - - def ringCommand = "ring $edtVersionForRing workspace export --workspace-location \"$projectWorkspaceDir\" --project \"$projectDir\" --configuration-files \"$configurationRoot\"" - - steps.ringCommand(ringCommand) + def engine = EdtCliEngineFactory.getEngine(config.edtVersion) + engine.edtToDesignerTransformConfiguration(steps, config) steps.zip(CONFIGURATION_DIR, CONFIGURATION_ZIP) steps.stash(CONFIGURATION_ZIP_STASH, CONFIGURATION_ZIP) - } - - private void transformExtensions(IStepExecutor steps, String workspaceDir, String extensionRoot, String edtVersionForRing) { - steps.deleteDir(extensionRoot) - - config.initInfoBaseOptions.extensions.each { - - if (it.initMethod != InitExtensionMethod.SOURCE) { - return - } - - Logger.println("Конвертация исходников расширения ${it.name} из формата EDT в формат Конфигуратора") - def env = steps.env(); - def projectDir = FileUtils.getFilePath("$env.WORKSPACE/${it.path}") - def currentExtensionWorkspaceDir = FileUtils.getFilePath("$workspaceDir/cfe/${it.name}") - - def ringCommand = "ring $edtVersionForRing workspace export --workspace-location \"$currentExtensionWorkspaceDir\" --project \"$projectDir\" --configuration-files \"$extensionRoot/${it.name}\"" - - steps.ringCommand(ringCommand) - } + engine.edtToDesignerTransformExtensions(steps, config) steps.zip(EXTENSION_DIR, EXTENSION_ZIP) steps.stash(EXTENSION_ZIP_STASH, EXTENSION_ZIP) + } } diff --git a/src/ru/pulsar/jenkins/library/steps/EdtValidate.groovy b/src/ru/pulsar/jenkins/library/steps/EdtValidate.groovy index 70efc79f..bb4f7886 100644 --- a/src/ru/pulsar/jenkins/library/steps/EdtValidate.groovy +++ b/src/ru/pulsar/jenkins/library/steps/EdtValidate.groovy @@ -1,10 +1,10 @@ package ru.pulsar.jenkins.library.steps +import ru.pulsar.jenkins.library.edt.EdtCliEngineFactory import ru.pulsar.jenkins.library.IStepExecutor import ru.pulsar.jenkins.library.configuration.JobConfiguration import ru.pulsar.jenkins.library.configuration.SourceFormat import ru.pulsar.jenkins.library.ioc.ContextRegistry -import ru.pulsar.jenkins.library.utils.EDT import ru.pulsar.jenkins.library.utils.FileUtils import ru.pulsar.jenkins.library.utils.Logger @@ -31,7 +31,6 @@ class EdtValidate implements Serializable { def env = steps.env() - String workspaceLocation = "$env.WORKSPACE/$DesignerToEdtFormatTransformation.WORKSPACE" String projectList if (config.sourceFormat == SourceFormat.DESIGNER) { @@ -50,15 +49,11 @@ class EdtValidate implements Serializable { projectList = "--project-list \"$projectDir\"" } - def resultFile = "$env.WORKSPACE/$RESULT_FILE" - def edtVersionForRing = EDT.ringModule(config) - Logger.println("Выполнение валидации EDT") - def ringCommand = "ring $edtVersionForRing workspace validate --workspace-location \"$workspaceLocation\" --file \"$resultFile\" $projectList" - steps.catchError { - steps.ringCommand(ringCommand) - } + def engine = EdtCliEngineFactory.getEngine(config.edtVersion) + + engine.edtValidate(steps, config, projectList) steps.archiveArtifacts("$DesignerToEdtFormatTransformation.WORKSPACE/.metadata/.log") steps.archiveArtifacts(RESULT_FILE)