Jenkins 脚本化管道:如何在此特定情况下应用@NonCPS 注释

Jenkins scripted Pipeline: How to apply @NonCPS annotation in this specific case

我正在开发一个脚本化的 Jenkins 管道,它需要将具有特定编码的字符串写入文件,如下例所示:

class Logger implements Closeable {

    private final PrintWriter writer

    [...]

    Logger() {
        FileWriter fw = new FileWriter(file, true)
        BufferedWriter bw = new BufferedWriter(fw)
        this.writer = new PrintWriter(bw)
    }

    def log(String msg) {
        try {
            writer.println(msg)
            [...]
        } catch (e) {
            [...]
        }
    }
}

上面的代码不起作用,因为 PrintWriter 是不可序列化的,所以我知道我必须防止某些代码被 CPS 转换。不过,我不知道该怎么做,因为据我所知 @NonCPS 注释只能应用于方法。 我知道一种解决方案是将所有与输出相关的代码移动到 log(msg) 并注释该方法,但这样每次调用该方法时我都必须创建一个新的编写器。

有人知道我该如何改正我的代码吗?

提前致谢!

这里有一种使用 log 函数来完成这项工作的方法,该函数在 vars\log.groovy 的共享库中定义:

import java.io.FileWriter
import java.io.BufferedWriter
import java.io.PrintWriter

// The annotated variable will become a private field of the script class. 
@groovy.transform.Field 
PrintWriter writer = null

void call( String msg ) {
    if( ! writer ) {
        def fw = new FileWriter(file, true)
        def bw = new BufferedWriter(fw)
        writer = new PrintWriter(bw)
    }

    try {
        writer.println(msg)
        [...]
    } catch (e) {
        [...]
    }     
}

毕竟,vars 文件夹中的脚本被实例化为单例 类,这非常适合记录器。即使没有 @NonCPS 注释也能正常工作。

管道中的用法很简单:

log 'some message'