詹金斯共享库中的“ vars”如何工作?

问题描述

我在Jenkins共享库中遇到了一些行为,如果有人可以向我解释一下,那就太好了:

第一期

假设我在vars目录中有一个文件

// MultiMethod.groovy

def Foo() { ... }

def Bar() { ... }

现在,如果我想从管道中使用这些功能,我要做的是:

// Jenkinsfile
@Library('LibName') _

pipeline {
  ...
  steps {
    script { 
        // Method (1): this will work
        def var = new MultiMethod()
        var.Foo()
        var.Bar()

        // Method (2) this will not work
          MultiMethod.Foo()
       }
  }

}

(((1)和(2)方法是在groovy脚本中调用方法方法。请不要对“方法”一词的这两种用法感到困惑。)

因此,仅当我使用MultiMethod运算符实例化此new时,此方法才起作用。

但是,如果我将文件名为multiMethod(camelCased)而不是MultiMethod,则可以使用方法(2)来调用脚本中的方法。有人可以解释这种行为吗?

这似乎很好。

第二期

基于以上示例。如果我有一个名为MultiMethod的groovy文件(我们前面曾看到,如果用new实例化,我可以使用其方法),我似乎无法实例化MultiMethod的对象动态加载库时,如下所示:

// Jenkinsfile

pipeline {
  ...
  steps {
    script { 
        // Method (1): this will not work
        library 'LibName'
        def var = new MultiMethod()
        var.Foo()
        var.Bar()

       }
  }

}

如果我尝试这样做,我会得到:

Running in Durability level: MAX_SURVIVABILITY
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup Failed:
WorkflowScript: 11: unable to resolve class multiMethod 
 @ line 11,column 32.
                       def mult = new multiMethod()
                                  ^

1 error

    at org.codehaus.groovy.control.ErrorCollector.failIfErrors(ErrorCollector.java:310)
    at org.codehaus.groovy.control.compilationunit.applyToSourceUnits(compilationunit.java:958)
    at org.codehaus.groovy.control.compilationunit.doPhaSEOperation(CompilationUni  
...

最后一个问题

如果可以的话,另一个问题。我注意到人们习惯于写作

return this

vars目录中的脚本末尾。有人可以解释这有什么好处吗?如果有人可以在这种机制的工作原理的背景下对此进行解释,我会很高兴,例如为什么这些脚本会变成全局变量

谢谢

解决方法

第一个问题答案

这是因为 Jenkins 为共享库定义了该标准。为了消除您的疑问,Jenkins 官方 documentation 中确实有很好的解释,如果您按照标准进行操作,它将起作用。像下面的例子:

确保您遵循此文件夹结构

shared-library
├── src
│   └── org
│       └── any
│           └── MultiMethod.groovy
└── vars
    └── multiMethod.groovy

multiMethod.groovy

def foo() {
  echo "Hello foo from vars/multiMethod.groovy"
}
def bar() {
  echo "Hello bar from vars/multiMethod.groovy"
}

一旦你有了这个并且你像 this 这样配置你的共享库,那么你可以在你的 Jenkins 文件中使用 multiMethod.groovy,如下所示:

Jenkinsfile

@Library('jenkins-shared-library') _
pipeline {
    agent any;
    stages {
        stage('log') {
            steps {
                script {
                    multiMethod.foo()
                    multiMethod.foo()
                }
            }
        }
    }
}

为什么会这样? - 它解释了 here

但是要使用 src/org/any/MultiMethod.groovy 文件夹中的 src,您必须实例化该类并调用该方法。下面是我的例子

MultiMethod.groovy

package org.any

class MultiMethod {
    def steps;
    MultiMethod(steps) {
        this.steps = steps
    }
    def foo() {
        steps.echo "Hello foo from src/org/any/MultiMethod.groovy"
    }
    def bar() {
        steps.echo "Hello bar from src/org/any/MultiMethod.groovy"
    }
}

Jenkinsfile

@Library('jenkins-shared-library') _
import org.any.MultiMethod

pipeline {
    agent any;
    stages {
        stage('log') {
            steps {
                script { 
                    def x= new MultiMethod(this);
                    x.foo()
                    x.bar()
                }
                
            }
        }
    }
}

第二题答案

您的第二个问题与 this post 重复。我试图解释并举了一个例子。请看一下。

最后一个问题的答案

如果您这样做,则无需从 return this 中定义的 Jenkins 全局变量中vars

vars/returnThisTest.groovy

def helloWorld() {
    echo "Hello EveryOne"
}

def helloWorld() {
    echo "Hello EveryOne"
}

return this;

两者都是相同的,从 Jenkinsfile 中您可以像 returnThisTest.helloWorld() 一样调用,但是当场景类似于 this 时,return this 可能更有用 - Jenkins 文档中的一个很好的例子