你如何加载一个groovy文件并执行它

Posted

技术标签:

【中文标题】你如何加载一个groovy文件并执行它【英文标题】:How do you load a groovy file and execute it 【发布时间】:2016-10-14 11:43:22 【问题描述】:

我有一个 jenkinsfile 放到我的项目的根目录中,并且想为我的管道拉入一个 groovy 文件并执行它。我能够让它工作的唯一方法是创建一个单独的项目并使用fileLoader.fromGit 命令。我想做

def pipeline = load 'groovy-file-name.groovy'
pipeline.pipeline()

【问题讨论】:

【参考方案1】:

如果您的 Jenkinsfile 和 groovy 文件在一个存储库中,并且 Jenkinsfile 是从 SCM 加载的,您必须这样做:

Example.Groovy

def exampleMethod() 
    //do something


def otherExampleMethod() 
    //do something else

return this

JenkinsFile

node 
    def rootDir = pwd()
    def exampleModule = load "$rootDir@script/Example.Groovy "
    exampleModule.exampleMethod()
    exampleModule.otherExampleMethod()

【讨论】:

读者,请注意,在 Groovy 中,“return this”至关重要。 @anton 同时我找到了.& 运算符(例如:def exampleMethod = example.&exampleMethod。效果很好...... @MichaelEaster 'this' 究竟返回了什么?如果那是 gradle 脚本,它将返回一个 Project 类的实例作为绑定。但在一个普通的 groovy 文件中,我想不通。 @AntonShishkin ,$rootDir 变量是什么,它在哪里/如何设置?它是詹金斯固有的还是习惯的?我收到groovy.lang.MissingPropertyException: No such property: rootDir for class: groovy.lang.Binding 所以,我发现了一个警告——当运行同一作业的 2 个并发实例时,Jenkins 会将 @2 附加到工作区名称......但是,@987654330 并非如此@ 目录,这意味着 $workspace@script/Example.Groovy 在运行并发构建时将不起作用。【参考方案2】:

如果您的管道可以加载多个 groovy 文件,并且这些 groovy 文件也会在它们之间共享内容:

JenkinsFile.groovy

def modules = [:]
pipeline 
    agent any
    stages 
        stage('test') 
            steps 
                script
                    modules.first = load "first.groovy"
                    modules.second = load "second.groovy"
                    modules.second.init(modules.first)
                    modules.first.test1()
                    modules.second.test2()
                
            
        
    

first.groovy

def test1()
    //add code for this method

def test2()
    //add code for this method

return this

second.groovy

import groovy.transform.Field
@Field private First = null

def init(first) 
    First = first

def test1()
    //add code for this method

def test2()
    First.test2()

return this

【讨论】:

可能会返回一些不一样的返回 this - 例如返回“This”?【参考方案3】:

在执行load 之前,您必须执行checkout scm(或从SCM 签出代码的其他方式)。

【讨论】:

这假定要加载的文件在 SCM 中。 你是对的,如果文件在 SCM 中,那么你需要在尝试加载之前从那里获取它。但是,如果库文件与主 jenkinsfile 位于同一个 repo 中,那么如果管道配置为自动提取 repo,则不必调用 checkout;在作业配置中。【参考方案4】:

感谢@anton 和@Krzysztof Krasori,如果我将checkout scm 和确切的源文件结合起来效果很好

Example.Groovy

def exampleMethod() 
    println("exampleMethod")


def otherExampleMethod() 
    println("otherExampleMethod")

return this

JenkinsFile

node 
    // Git checkout before load source the file
    checkout scm

    // To know files are checked out or not
    sh '''
        ls -lhrt
    '''

    def rootDir = pwd()
    println("Current Directory: " + rootDir)

    // point to exact source file
    def example = load "$rootDir/Example.Groovy"

    example.exampleMethod()
    example.otherExampleMethod()

【讨论】:

这是我需要让来自 SCM 的 Jenkins 管道工作的东西,现在我将所有常量和函数集中到一个公共的 Jenkinsfile.common.Groovy 中,在我的发布管道和我的集成之间共享测试管道。 jenkins.io/doc/pipeline/steps/workflow-cps/…【参考方案5】:

非常有用的帖子,遇到了同样的问题,跟着你解决了。

我的问题是:Jenkinsfile -> 打电话给first.groovy -> 打电话给second.groovy

这是我的解决方案:

Jenkinsfile

node 
  checkout scm
  //other commands if you have

  def runner = load pwd() + '/first.groovy'
  runner.whateverMethod(arg1,arg2)

first.groovy

def first.groovy(arg1,arg2)
  //whatever others commands

  def caller = load pwd() + '/second.groovy'
  caller.otherMethod(arg1,arg2)

注意:参数是可选的,如果有,请添加或留空。

希望这可以进一步帮助。

【讨论】:

快速提醒一下,load() 仅在 node() 中有效。第二个 load() 有效,因为在 node() 中调用了whateverMethod()。

以上是关于你如何加载一个groovy文件并执行它的主要内容,如果未能解决你的问题,请参考以下文章

_groovy

Groovy内存机制详解

从 groovy 脚本运行 gsutil:找不到 Python 可执行文件

springboot 中使用groovy脚本的各种方式

提取groovy jar

如何在同一个 Jenkins 节点中加载另一个 groovy 脚本?