Search code examples
jenkinsjenkins-pluginsjenkins-pipelinejenkins-blueocean

How do I create a Body block for a custom Jenkins Pipeline Step in the Java code of my Jenkins plugin?


Context

I am creating a Jenkins plugin that adds a custom pipeline step.

I have successfully got Java code to execute when my step (dostuff) is used in a pipeline script, such as

script1

node {
  stage( 'doingstuff' ) {
    dostuff()
  }
}

However, I want my custom step to render some stages and parallel streams in the Jenkins WebUI visualization, so I want to be doing the equivalent of parallel([...]) and stage( ... ) { ... } and maybe even node { ... } blocks in my plugin. For example, if the following were my intended pipeline:

script2

node {
  stage( 'one' ) {
    parallel([
      "stream one": {
        sh "echo hi from stream one"
      },
      "stream two": {
        sh "echo hi from stream two"
      }
    ])
  }
}

I would like to reduce it to

script3

node {
  dostuff()
}

where dostuff() will do the equivalent of

script4

stage( 'one' ) {
  parallel([
    "stream one": {
      sh "echo hi from stream one"
    },
    "stream two": {
      sh "echo hi from stream two"
    }
  ])
}

and, importantly, will render properly in the "Pipeline Steps" view of the Jenkins WebUI, and so that the parallel streams will render properly in the Blue Ocean web UI.

While I have seen how to execute the body block that is passed to a custom step defined in a plugin, from a pipeline script (for example), I cannot figure out the idiom for creating a body block in Java code.

I do not want to/cannot do this in pure Groovy because

  1. The "real" logic I want to write will depend on classes in several non-Jenkins JARs that aren't on the classpath by default, from several Maven repositories (and so cannot be imported (though they could maybe be @Grab'd))
  2. The "real" logic I want to write will use concurrency libraries, including Java's synchronized, and as far as I can tell pipeline scripts do not support this.
  3. The "real" logic I want to write would like to share state across all instances of the logic in the JVM, and as far as I can tell pipeline scripts cannot communicate with other running pipeline scripts.

Question(s)

  1. Is it/should it be possible to create a pipeline body block in Java, and have a custom pipeline step execute that block?
  2. Are there any plugins that do this that I could look at?

Solution

  • I spoke to Andrew Bayer - engineer working on pipeline for CloudBees - at Jenkins World 2017 and he confirmed that it's architecturally impossible to compose a pipeline step of other pipeline steps from pure Java in a Jenkins plug-in.