Answer a question

I am working on a scripted Jenkins-Pipeline that needs to write a String with a certain encoding to a file as in the following example:

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) {
            [...]
        }
    }
}

The above code doesn't work since PrintWriter ist not serializable so I know I got to prevent some of the code from being CPS-transformed. I don't have an idea on how to do so, though, since as far as I know the @NonCPS annotation can only be applied to methods. I know that one solution would be to move all output-related code to log(msg) and annotate the method but this way I would have to create a new writer every time the method gets called.

Does someone have an idea on how I could fix my code instead?

Thanks in advance!

Answers

Here is a way to make this work using a log function that is defined in a shared library in 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) {
        [...]
    }     
}

After all, scripts in the vars folder are instanciated as singleton classes, which is perfectly suited for a logger. This works even without @NonCPS annotation.

Usage in pipeline is as simple as:

log 'some message'
Logo

CI/CD社区为您提供最前沿的新闻资讯和知识内容

更多推荐