繁体   English   中英

Jenkins - 在单个作业中多次加载 groovy 脚本,但具有不同的阶段

[英]Jenkins - load groovy script multiple times in a single job but with different stages

我有一个 Jenkins 管道,它可以在脚本管道中构建和部署任务。 管道维护在中央存储库中。 对于每个部署阶段,它都会等待用户输入,等待时间可能长达数天。 在等待期间,如果管道脚本发生更改,我希望在部署批准(用户输入)后加载最新的脚本。

脚本的第一个load步骤工作正常,当我再次尝试加载时,出现以下错误。 GroovyClassLoader 似乎抛出了这个错误。

我试图通过currentBuild.rawBuild.getExecution().loadedScripts loadedScripts的脚本,但这没有帮助。 有没有办法实现我在每个阶段重新加载脚本的用例? 任何指针都会有所帮助。

java.lang.LinkageError: loader org.jenkinsci.plugins.workflow.cps.CpsGroovyShell$CleanGroovyClassLoader @8d141543 attempted duplicate class definition for Script1. (Script1 is in unnamed module of loader org.jenkinsci.plugins.workflow.cps.CpsGroovyShell$CleanGroovyClassLoader

// pipeline.groovy
def config 
node('agent') {
    stage('build') {
        config = loadScripts()
        echo 'perform some tasks'
    }
    stage('deploy-dev') {
        input message: 'approve'
        config = loadScripts()
        echo 'perform some tasks'
    }
    stage('deploy-sit') {
        input message: 'approve'
        config = loadScripts()
        echo 'perform some tasks'
    }
}

def loadScripts() {
    checkout scm
    config = load 'somepath/external.groovy'
    return config
}

// somepath/external.groovy

class JobConfig {
    def someDataVar1
    def someDataVar2
}

def sayHello() {
    println 'hello'
}

return this

在此处输入图像描述

也许我不完全理解你的问题(在这种情况下,我道歉),但我不明白为什么你的 'somepath/external.groovy' 不是一个简单的 groovy 库,(像这样: http://rtyler .github.io/jenkins.io/doc/book/pipeline/shared-libraries/ ),在管道开始时声明为已使用,然后您的 JobConfig 和 sayHello 可以根据需要多次调用并具有不同的行为基于一些参数 - 比如舞台名称。

简短的回答是共享库旨在解决此类问题。 如果这不是一个选项,那么您的脚本文件的一些重组可能会解决这个问题作为一种解决方法。

您收到的错误表明您正在重新定义一个不允许的同名类。 由于您第二次加载相同的脚本,这与两次加载同名的类基本相同。

选项 1 是将您的管道拆分为多个管道,这些管道都摄取相同的配置。 对于等待用户输入继续的长时间运行的管道,我个人从来没有好运过。 相反,您可以将您的管道拆分为一个“构建”管道,该管道基本上加载您的配置并运行构建步骤,然后当您准备好部署时,您运行一个加载配置的“deploy-dev”管道,然后运行部署开发步骤。 然后是另一个对“deploy-sit”执行相同操作的管道。

// pipeline-build.groovy
def config 
node('agent') {
    stage('build') {
        config = loadScripts()
        echo 'perform some tasks'
    }
}

def loadScripts() {
    checkout scm
    config = load 'somepath/external.groovy'
    return config
}

// pipeline-deploy-dev.groovy
def config 
node('agent') {
    stage('deploy-dev') {
        input message: 'approve'
        config = loadScripts()
        echo 'perform some tasks'
    }
}

def loadScripts() {
    checkout scm
    config = load 'somepath/external.groovy'
    return config
}

// pipeline-deploy-sit.groovy
def config 
node('agent') {
    stage('deploy-sit') {
        input message: 'approve'
        config = loadScripts()
        echo 'perform some tasks'
    }
}

def loadScripts() {
    checkout scm
    config = load 'somepath/external.groovy'
    return config
}

选项 2 是将脚本拆分为多个脚本。 一个脚本将包含类定义,并且只会在管道顶部加载一次。 然后其他脚本将包含每个管道步骤将使用的其他每个方法。 这看起来像这样:

// pipeline.groovy
def config 
node('agent') {
    loadScript("somepath/JobConfig.groovy")
    stage('build') {
        config = loadScript("somepath/Build.groovy")
        echo 'perform some tasks'
    }
    stage('deploy-dev') {
        input message: 'approve'
        config = loadScript("somepath/DeployDev.groovy")
        echo 'perform some tasks'
    }
    stage('deploy-sit') {
        input message: 'approve'
        config = loadScript("somepath/DeploySit.groovy")
        echo 'perform some tasks'
    }
}

def loadScript(def script) {
    checkout scm
    config = load script
    return config
}

然后,当您加载后面的脚本时,它们可以更新并加载,而无需重新定义初始类定义或重新定义单个方法(我想这也是一个问题)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM