Return a map/value from a step in a pipeline build

60 views
Skip to first unread message

Lakshmi Narasimhan

unread,
Nov 12, 2020, 12:08:37 AM11/12/20
to Jenkins Developers
Hello Jenkins devs,

Is it possible to get back a return value from a pipeline step? I am looking for a map similar to  checkout step https://issues.jenkins.io/browse/JENKINS-26100.

Currently, I am exporting the values I need to get back from the step to the environment using an EnvironmentContributingAction.

Thanks in advance for your help.

Victor Martinez

unread,
Nov 12, 2020, 5:41:32 AM11/12/20
to Jenkins Developers
Hey,

You can use the groovy.transform.Field with a global variable in the pipeline, for instance, the below snippet set the value of myStep in the variable myStepData which it's consumed later on in another stage


import groovy.transform.Field
@Field def myStepData = [:]

pipeline {
    ...
    stage('producer') {
        ...
        steps {
            script {
               // myStep returns a map with values
               myStepData = myStep(....)
               ...
            }
         }
     }
     ....
    stage('consumer') {
        ...
        steps {
            script {
               // where <field> is one of the entries
               if (myStepData?.<field>?.equals('acme'))) {
          
               }
            }
         }
     }
}

Cheers

Lakshmi Narasimhan

unread,
Nov 12, 2020, 6:08:12 AM11/12/20
to Jenkins Developers
Hi Victor, 

Thanks for the tip. 

My issue is that the step does not return a map or any value. I am referring to the  "step" metastep. Unlike the "checkout" metastep that returns a map (see  https://issues.jenkins.io/browse/JENKINS-26100), step does not return a value. For instance, this is not possible  or even it is possible, I don't know how I can send back the data from MyStepClass

def vars = step ([$class: "MyStepClass"...] 

But the following is possible because the checkout metastep can get back a map if MySCMClass overrides #buildEnvironment

def vars = checkout ([$class: "MySCMClass"...]   

I am trying to figure out if I can make "MyStepClass" return a map somehow. The workaround is to contribute an action that in turn exports the name-value pairs to the build environment. I can then access it in the script using the env object.

Jesse Glick

unread,
Nov 12, 2020, 1:19:07 PM11/12/20
to Jenkins Dev
On Thu, Nov 12, 2020 at 6:08 AM Lakshmi Narasimhan
<vaikuntam....@gmail.com> wrote:
> My issue is that the step does not return a map or any value. I am referring to the "step" metastep.

No, you cannot return values if you use `SimpleBuildStep`. You can
extend `Step` directly (Pipeline-specific). But it may be better to
extend `SimpleBuildWrapper` and define environment variables within
its block; this will work in freestyle, Scripted Pipeline, _and_
Declarative Pipeline (without `script` blocks).

Lakshmi Narasimhan

unread,
Dec 10, 2020, 4:25:52 AM12/10/20
to Jenkins Developers
Hi Jesse, 

Thanks for the suggestion. I went through the docs and implementing Step would certainly work well for my use case.

I am trying to understand  how I can leverage SimpleBuildWrapper to be able to work in different job types. I assume that I need another class to implement the BuildWrapper extension point. In that case, I would end up having something like this
step ([$class: "MyStepClass"...]  // This performs some action and has the return values (name-value pairs)

withMyWrapperClass() { // I need this wrapper to inject those return values from the previous step into the block.
    
    // I can call my step here and have another wrapper block too.
}

I need to send some data from MyStepClass instance to following MyWrapperClass  instance so that it can inject that data into the block's environment. I am tending towards  doing this through an intermediate action created by MyStepClass instance. But if I keep adding actions from my step class to the build, then it is possible that an outer wrapper picks up an action from an inner step.  Same issue will persist if I update just a single action or replace it.

Please let me know if I understood your suggestion properly regarding SimpleBuildWrapper and whether the approach is correct.

Jesse Glick

unread,
Dec 10, 2020, 11:51:41 AM12/10/20
to Jenkins Dev
On Thu, Dec 10, 2020 at 4:26 AM Lakshmi Narasimhan
<vaikuntam....@gmail.com> wrote:
> I am trying to understand how I can leverage SimpleBuildWrapper to be able to work in different job types.

`SimpleBuildWrapper` is specifically designed (in fact restricted) to
be compatible with traditional job types as well as Pipeline. Please
read

https://www.jenkins.io/doc/developer/plugin-development/pipeline-integration/

> step ([$class: "MyStepClass"...] // This performs some action and has the return values (name-value pairs)

No, you just define a `@Symbol` and that becomes a Pipeline step name.

> I am tending towards doing this through an intermediate action

`Run.addAction` affects the build globally, which will lead to
incorrect or confused results if a Pipeline build uses the wrapper
multiple times, or does work after the block ends, or (especially) if
the wrapper is run in parallel. So avoid that.

From a `SimpleBuildWrapper` you can communicate information to nested
steps using simple (textual) environment variables. If you need to
communicate richer substructure contextually, you will need to use
`Step` and check the documentation on `BodyInvoker`.

Matt Sicker

unread,
Dec 10, 2020, 12:15:25 PM12/10/20
to jenkin...@googlegroups.com
Indeed, if you're modifying run actions inside a pipeline thing like
in credentials-binding, you need to ensure to merge existing actions
into the new one however it makes sense for that usage. If it doesn't
make sense to do so, then attaching actions is likely too coarse for
your use case.
> --
> You received this message because you are subscribed to the Google Groups "Jenkins Developers" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to jenkinsci-de...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/jenkinsci-dev/CANfRfr0o1KLdpNpWVarYoycm5v_hKBofXeVyyoYcTiN8JeRQDQ%40mail.gmail.com.



--
Matt Sicker
Senior Software Engineer, CloudBees
Reply all
Reply to author
Forward
0 new messages