DEV Community

Gregory Paciga
Gregory Paciga

Posted on • Originally published at gerg.dev on

Jenkins: Check whether a DSL method exists

Occasionally when working with Jenkinsfiles, you’ll run into a NoSuchMethodError because of calling a function that Jenkins’s doesn’t know about:

java.lang.NoSuchMethodError: **No such DSL method 'someFunc'** found among [...]
Enter fullscreen mode Exit fullscreen mode

There are number of reasons that this can happen, such as a required plugin not being installed, or the shared library that defines the function isn’t loaded.

Lately I have been working a lot with shared libraries and building up functionality that is designed for multiple people to use, without necessarily knowing the technical details of each product. I occasionally want to check if a function is available before running some code to avoid the NoSuchMethodError, but I don’t want to block everything if it isn’t available. This allows making libraries more robust by not failing when an optional dependency is missing.

So, how do we check if a DSL method exists before calling it?

Based on the stacktrace that came with the error, I ended up poking around the source code for the CpsScript class to see how it detected this problem. It turns out that in a pipeline script we can use the this object to get the bindings available on the script itself, and check whether a given method exists. This is all you need:

this.getBinding().hasVariable('foobar')
Enter fullscreen mode Exit fullscreen mode

That expression will evaluate to true if foobar exists, and false if it doesn’t.

For convenience, if we’re doing this multiple times, we can write a simple function in the pipeline itself:

boolean dslMethodExists(String name) {
    return this.getBinding().hasVariable(name)   
}

if (dslMethodExists('foobar')) {
    foobar()
}
Enter fullscreen mode Exit fullscreen mode

If you wanted to take advantage of this across multiple Jenkinsfiles, the function can go into a shared library function. However, in that context this will no longer point to the pipeline script being executed. We can still do the check by passing a reference to the current script directly:

// vars/dslMethodExists.groovy in a shared library

import org.jenkinsci.plugins.workflow.cps.CpsScript

boolean call(CpsScript script, String name) {
    return script.getBinding().hasVariable(name)
}
Enter fullscreen mode Exit fullscreen mode

I’m importing the CpsScript class just so I can declare its type in the function signature; it’s good practice to avoid def, and it helps future developers know what class they’re working with explicitly.

Then, as long as that shared library is loaded, you can call that function in your pipelines, or even in other shared library functions:

if (dslMethodExists('foobar')) {
    foobar()
}
Enter fullscreen mode Exit fullscreen mode

And that’s all there is to it. I don’t guarantee that this is the best way to check for a DSL method—as I said I went poking around in the source code to find this—but it works. I googled this enough times, without finding an answer, that when I finally figured it out I thought I should put it up here in the hopes it’ll help someone else.

Top comments (0)