Search in sources :

Example 1 with ParallelStep

use of org.jenkinsci.plugins.workflow.cps.steps.ParallelStep in project workflow-cps-plugin by jenkinsci.

the class DSL method invokeStep.

/**
 * When {@link #invokeMethod(String, Object)} is calling a {@link StepDescriptor}
 */
protected Object invokeStep(StepDescriptor d, Object args) {
    final NamedArgsAndClosure ps = parseArgs(args, d);
    CpsThread thread = CpsThread.current();
    FlowNode an;
    // TODO: generalize the notion of Step taking over the FlowNode creation.
    boolean hack = d instanceof ParallelStep.DescriptorImpl || d instanceof LoadStep.DescriptorImpl;
    if (ps.body == null && !hack) {
        an = new StepAtomNode(exec, d, thread.head.get());
        // TODO: use CPS call stack to obtain the current call site source location. See JENKINS-23013
        thread.head.setNewHead(an);
    } else {
        an = new StepStartNode(exec, d, thread.head.get());
        thread.head.setNewHead(an);
    }
    final CpsStepContext context = new CpsStepContext(d, thread, handle, an, ps.body);
    Step s;
    boolean sync;
    ClassLoader originalLoader = Thread.currentThread().getContextClassLoader();
    try {
        d.checkContextAvailability(context);
        Thread.currentThread().setContextClassLoader(CpsVmExecutorService.ORIGINAL_CONTEXT_CLASS_LOADER.get());
        s = d.newInstance(ps.namedArgs);
        try {
            // No point storing empty arguments, and ParallelStep is a special case where we can't store its closure arguments
            if (ps.namedArgs != null && !(ps.namedArgs.isEmpty()) && isKeepStepArguments() && !(s instanceof ParallelStep)) {
                // Get the environment variables to find ones that might be credentials bindings
                Computer comp = context.get(Computer.class);
                EnvVars allEnv = new EnvVars(context.get(EnvVars.class));
                if (comp != null && allEnv != null) {
                    allEnv.entrySet().removeAll(comp.getEnvironment().entrySet());
                }
                an.addAction(new ArgumentsActionImpl(ps.namedArgs, allEnv));
            }
        } catch (Exception e) {
            // Avoid breaking execution because we can't store some sort of crazy Step argument
            LOGGER.log(Level.WARNING, "Error storing the arguments for step: " + d.getFunctionName(), e);
        }
        // Persist the node - block start and end nodes do their own persistence.
        CpsFlowExecution.maybeAutoPersistNode(an);
        StepExecution e = s.start(context);
        thread.setStep(e);
        sync = e.start();
    } catch (Exception e) {
        if (e instanceof MissingContextVariableException)
            reportMissingContextVariableException(context, (MissingContextVariableException) e);
        context.onFailure(e);
        s = null;
        sync = true;
    } finally {
        Thread.currentThread().setContextClassLoader(originalLoader);
    }
    if (sync) {
        assert context.bodyInvokers.isEmpty() : "If a step claims synchronous completion, it shouldn't invoke body";
        if (context.getOutcome() == null) {
            context.onFailure(new AssertionError("Step " + s + " claimed to have ended synchronously, but didn't set the result via StepContext.onSuccess/onFailure"));
        }
        thread.setStep(null);
        // we just move on accordingly
        if (an instanceof StepStartNode) {
            // no body invoked, so EndNode follows StartNode immediately.
            thread.head.setNewHead(new StepEndNode(exec, (StepStartNode) an, an));
        }
        thread.head.markIfFail(context.getOutcome());
        return context.replay();
    } else {
        // if it's in progress, suspend it until we get invoked later.
        // when it resumes, the CPS caller behaves as if this method returned with the resume value
        Continuable.suspend(new ThreadTaskImpl(context));
        // so the execution will never reach here.
        throw new AssertionError();
    }
}
Also used : StepStartNode(org.jenkinsci.plugins.workflow.cps.nodes.StepStartNode) LoadStep(org.jenkinsci.plugins.workflow.cps.steps.LoadStep) Step(org.jenkinsci.plugins.workflow.steps.Step) LoadStep(org.jenkinsci.plugins.workflow.cps.steps.LoadStep) ParallelStep(org.jenkinsci.plugins.workflow.cps.steps.ParallelStep) StepEndNode(org.jenkinsci.plugins.workflow.cps.nodes.StepEndNode) StepAtomNode(org.jenkinsci.plugins.workflow.cps.nodes.StepAtomNode) StepExecution(org.jenkinsci.plugins.workflow.steps.StepExecution) NoStaplerConstructorException(org.kohsuke.stapler.NoStaplerConstructorException) GroovyRuntimeException(groovy.lang.GroovyRuntimeException) IOException(java.io.IOException) MissingContextVariableException(org.jenkinsci.plugins.workflow.steps.MissingContextVariableException) ParallelStep(org.jenkinsci.plugins.workflow.cps.steps.ParallelStep) EnvVars(hudson.EnvVars) ArgumentsActionImpl(org.jenkinsci.plugins.workflow.cps.actions.ArgumentsActionImpl) Computer(hudson.model.Computer) MissingContextVariableException(org.jenkinsci.plugins.workflow.steps.MissingContextVariableException) FlowNode(org.jenkinsci.plugins.workflow.graph.FlowNode)

Aggregations

GroovyRuntimeException (groovy.lang.GroovyRuntimeException)1 EnvVars (hudson.EnvVars)1 Computer (hudson.model.Computer)1 IOException (java.io.IOException)1 ArgumentsActionImpl (org.jenkinsci.plugins.workflow.cps.actions.ArgumentsActionImpl)1 StepAtomNode (org.jenkinsci.plugins.workflow.cps.nodes.StepAtomNode)1 StepEndNode (org.jenkinsci.plugins.workflow.cps.nodes.StepEndNode)1 StepStartNode (org.jenkinsci.plugins.workflow.cps.nodes.StepStartNode)1 LoadStep (org.jenkinsci.plugins.workflow.cps.steps.LoadStep)1 ParallelStep (org.jenkinsci.plugins.workflow.cps.steps.ParallelStep)1 FlowNode (org.jenkinsci.plugins.workflow.graph.FlowNode)1 MissingContextVariableException (org.jenkinsci.plugins.workflow.steps.MissingContextVariableException)1 Step (org.jenkinsci.plugins.workflow.steps.Step)1 StepExecution (org.jenkinsci.plugins.workflow.steps.StepExecution)1 NoStaplerConstructorException (org.kohsuke.stapler.NoStaplerConstructorException)1