Issue
In this integration pipeline in Jenkins, I am triggering different builds in parallel using the build step, as follows:
stage('trigger all builds')
{
parallel
{
stage('componentA')
{
steps
{
script
{
def myjob=build job: 'componentA', propagate: true, wait: true
}
}
}
stage('componentB')
{
steps
{
script
{
def myjob=build job: 'componentB', propagate: true, wait: true
}
}
}
}
}
I would like to access the return value of the build
step, so that I can know in my Groovy scripts what job name, number was triggered.
I have found in the examples that the object returned has getters like getProjectName()
or getNumber()
that I can use for this.
But how do I know the exact class of the returned object and the list of methods I can call on it? This seems to be missing from the Pipeline documentation. I am asking for this case in particular, but generally speaking, how can I know the class of the returned object and its documentation?
Solution
The step documentation is generated based on some files that are bundled with the plugin, which sometimes isn't enough. One easy way would be to just print out the class
of the result object by calling getClass
:
def myjob=build job: 'componentB', propagate: true, wait: true
echo "${myjob.getClass()}"
This output would tell you that the result (in this case) is a org.jenkinsci.plugins.workflow.support.steps.build.RunWrapper
which has published Javadoc.
For other cases, I usually have to dive into the Jenkins source code. Here is my general strategy:
- Figure out which plugin the step comes from either by the step documentation, jenkins.io steps reference, or just searching the internet
- From the plugin site, go to the source code repository
Search for the String literal of the step name, and find the step type that returns it. In this case, it looks to be coming from the
BuildTriggerStep
class, whichextends AbstractStepImpl
@Override public String getFunctionName() { return "build"; }
Look at the nested
DescriptorImpl
to see what execution class is returnedpublic DescriptorImpl() { super(BuildTriggerStepExecution.class); }
Go to
BuildTriggerStepExecution
and look at the execution body in thestart()
methodReading over the workflow step README shows that something should call
context.onSuccess(value)
to return a result. There is one place in that file, but that is only on the "no-wait" case, which always returns immediately and isnull
(source).if (step.getWait()) { return false; } else { getContext().onSuccess(null); return true; }
Ok, so it isn't completing in the step execution, so it must be somwhere else. We can also search the repository for
onSuccess
and see what else might trigger it from this plugin. We find that aRunListener
implementation handles setting the result asynchronously for the step execution if it has been configured that way:for (BuildTriggerAction.Trigger trigger : BuildTriggerAction.triggersFor(run)) { LOGGER.log(Level.FINE, "completing {0} for {1}", new Object[] {run, trigger.context}); if (!trigger.propagate || run.getResult() == Result.SUCCESS) { if (trigger.interruption == null) { trigger.context.onSuccess(new RunWrapper(run, false)); } else { trigger.context.onFailure(trigger.interruption); } } else { trigger.context.onFailure(new AbortException(run.getFullDisplayName() + " completed with status " + run.getResult() + " (propagate: false to ignore)")); } } run.getActions().removeAll(run.getActions(BuildTriggerAction.class));
The
trigger.context.onSuccess(new RunWrapper(run, false));
is where theRunWrapper
result comes from
Answered By - mkobit
Answer Checked By - Dawn Plyler (JavaFixing Volunteer)