0

我正在为 CNB(buildpacks)开发一个 Jenkins 管道插件。我需要用Java获取管道脚本中的变量但我仍然无法成功。

这是我的管道脚本。

buildpacks {
    builder = "some/builder"
}

我可以在 buildpacks.groovy 中使用 Groovy 语言访问这些变量(如构建器变量)

package dsl

// The call(body) method in any file in workflowLibs.git/vars is exposed as a
// method with the same name as the file.
def call(body) {
    def config = [:]
    body.resolveStrategy = Closure.DELEGATE_FIRST
    body.delegate = config
    body()
    try {
    
        echo "${config.builder}"

    } catch (Exception rethrow) {
        throw rethrow
    }

}

但正如我所说,我需要在 Java 中获取这些变量。下面是我从 GlobalVariable 类继承的类。

public abstract class PipelineDSLGlobal extends GlobalVariable {

public abstract String getFunctionName();

@Override
public String getName() {
    return getFunctionName();
}

@Override
public Object getValue(CpsScript script) throws Exception {
    Binding binding = script.getBinding();

    CpsThread c = CpsThread.current();
    if (c == null)
        throw new IllegalStateException("Expected to be called from CpsThread");

    ClassLoader cl = getClass().getClassLoader();

    String scriptPath = "dsl/" + getFunctionName() + ".groovy";
    Reader r = new InputStreamReader(cl.getResourceAsStream(scriptPath), "UTF-8");

    GroovyCodeSource gsc = new GroovyCodeSource(r, getFunctionName() + ".groovy", cl.getResource(scriptPath).getFile());
    gsc.setCachable(true);
    System.out.println(gsc.toString());

    Object pipelineDSL = c.getExecution()
            .getShell()
            .getClassLoader()
            .parseClass(gsc)
            .getDeclaredConstructor()
            .newInstance();
    binding.setVariable(getName(), pipelineDSL);
    r.close();

    System.out.println("test");
    
    return pipelineDSL;
}

}

下面是我为我的 buildpacksdsl 创建的课程。

package io.jenkins.plugins.buildpacks;

import hudson.Extension;
import io.jenkins.plugins.pipelinedsl.PipelineDSLGlobal;
import org.jenkinsci.plugins.scriptsecurity.sandbox.whitelists.ProxyWhitelist;
import org.jenkinsci.plugins.scriptsecurity.sandbox.whitelists.StaticWhitelist;

import java.io.IOException;

@Extension
public class BuildpacksDSL extends PipelineDSLGlobal {

@Override
public String getFunctionName() {
    return "buildpacks";
}

@Extension
public static class MiscWhitelist extends ProxyWhitelist {
    public MiscWhitelist() throws IOException {
        super(new StaticWhitelist(
                "method java.util.Map$Entry getKey",
                "method java.util.Map$Entry getValue"
        ));
    }
}

}

如果您想更详细地查看结构,可以查看存储库

有人能帮我吗 ?谢谢。

4

1 回答 1

0

我们找到了一个小解决方案。

我们使用 Groovy 和 Java 之间的兼容性创建了一个类的实例。并且由于我们已经可以用 Groovy 获取值,所以我们可以直接在构造函数方法中传递参数。

可能有一种更有效的方法。但现在它正在工作。

// Buildpacks.groovy
...


import io.jenkins.plugins.buildpacks.pipeline.BuildpacksDSL.BuildpacksPipelineDSL

class Buildpacks implements Serializable {

    // first executed method is similar to main method in java
    public void call(final Closure body) {

        // the config array is the array that holds the variables.
        def config = [:]
        body.resolveStrategy = Closure.DELEGATE_FIRST
        body.delegate = config
        body()

        // creating a new instance, when we give the 'config' array in the constructor, the variables is transferred.
        BuildpacksPipelineDSL pipeline = new BuildpacksPipelineDSL(config)
        pipeline.build()

    }

}

...
// BuildpacksDSL.java

...


 public static class BuildpacksPipelineDSL {

        public BuildpacksPipelineDSL() {
        }

        /**
         * This constructor takes dsl parameters, logger and envs from Jenkins and
         * extracts them to local variables.
         * 
         * @param c
         * @throws Exception
         */
        public BuildpacksPipelineDSL(LinkedHashMap<String, Object> c)
                throws Exception {
            
        // codes...

        }
}

...
于 2021-09-23T11:33:19.777 回答