2

我在 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脚本中方法的方法。请不要被“方法”这个词的这两种用法混淆。)

所以它只有在我MultiMethodnew操作员实例化它时才有效。

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

这似乎工作正常。

第二期

基于上面的例子。如果我有一个名为 的 groovy 文件MultiMethod,(我们之前看到,如果我用 with 实例化,我可以使用它的方法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  
...

编辑

我注意到,如果我这样做:

// Jenkinsfile

pipeline {
  ...
  steps {
    script { 
        library 'LibName'
        MultiMethod.Foo()
        MultiMethod.Bar()
       }
  }

}

它确实有效!

最后一个问题

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

return this

在他们的脚本末尾的vars目录中。有人可以解释它有什么用吗?如果有人能在这个机制如何工作的背景下解释这一点,我会很高兴,比如为什么这些脚本会变成全局变量?

谢谢

4

1 回答 1

2

第一个问题答案

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

确保您遵循此文件夹结构

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

多方法.groovy

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

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

詹金斯文件

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

为什么它会这样工作?- 它在这里解释

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

多方法.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"
    }
}

詹金斯文件

@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()
                }
                
            }
        }
    }
}

第二个问题答案

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

最后一个问题答案

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

vars/returnThisTest.groovy

def helloWorld() {
    echo "Hello EveryOne"
}

或者

def helloWorld() {
    echo "Hello EveryOne"
}

return this;

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

于 2021-02-07T20:51:01.757 回答