Skip to content

Commit

Permalink
[JENKINS-70808] Fix isRestartable by only checking against the curren… (
Browse files Browse the repository at this point in the history
#2416)

* [JENKINS-70808] Fix isRestartable by only checking against the current node
* [JENKINS-70808] Handle restartable computation in constructor
  • Loading branch information
Dohbedoh committed Mar 17, 2023
1 parent 864ac53 commit 1ec0fd7
Showing 1 changed file with 53 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,16 @@
import io.jenkins.blueocean.service.embedded.rest.QueueUtil;
import net.sf.json.JSONObject;
import org.apache.commons.io.IOUtils;
import org.jenkinsci.plugins.pipeline.StageStatus;
import org.jenkinsci.plugins.pipeline.modeldefinition.Utils;
import org.jenkinsci.plugins.pipeline.modeldefinition.actions.ExecutionModelAction;
import org.jenkinsci.plugins.pipeline.modeldefinition.actions.RestartDeclarativePipelineAction;
import org.jenkinsci.plugins.pipeline.modeldefinition.ast.ModelASTStage;
import org.jenkinsci.plugins.pipeline.modeldefinition.ast.ModelASTStages;
import org.jenkinsci.plugins.workflow.actions.LogAction;
import org.jenkinsci.plugins.workflow.cps.CpsFlowExecution;
import org.jenkinsci.plugins.workflow.flow.FlowExecution;
import org.jenkinsci.plugins.workflow.flow.FlowExecutionOwner;
import org.jenkinsci.plugins.workflow.graph.FlowNode;
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
import org.jenkinsci.plugins.workflow.job.WorkflowRun;
Expand Down Expand Up @@ -57,6 +65,7 @@ public class PipelineNodeImpl extends BluePipelineNode {
private final Link self;
private final String runExternalizableId;
private final Reachable parent;
private final boolean restartable;
public static final int waitJobInqueueTimeout = Integer.getInteger("blueocean.wait.job.inqueue", 1000);

public PipelineNodeImpl(FlowNodeWrapper node, Reachable parent, WorkflowRun run) {
Expand All @@ -67,6 +76,16 @@ public PipelineNodeImpl(FlowNodeWrapper node, Reachable parent, WorkflowRun run)
this.durationInMillis = node.getTiming().getTotalDurationMillis();
this.self = parent.getLink().rel(node.getId());
this.parent = parent;
/*
* PipelineNodeImpl are created as long as the build is not finished. And 'isRestartable' will be systematically
* called after this is created. So we can store whether the stage is restartable or no here.
*/
if(this.getStateObj() == BlueRun.BlueRunState.FINISHED) {
RestartDeclarativePipelineAction restartDeclarativePipelineAction = run.getAction(RestartDeclarativePipelineAction.class);
restartable = restartDeclarativePipelineAction != null && isRestartable(this.getDisplayName());
} else {
restartable = false;
}
}

@Override
Expand Down Expand Up @@ -183,13 +202,40 @@ private WorkflowRun getRun() {

@Override
public boolean isRestartable() {
RestartDeclarativePipelineAction restartDeclarativePipelineAction =
getRun().getAction( RestartDeclarativePipelineAction.class );
if (restartDeclarativePipelineAction != null) {
List<String> restartableStages = restartDeclarativePipelineAction.getRestartableStages();
if (restartableStages != null) {
return restartableStages.contains(this.getDisplayName())
&& this.getStateObj() == BlueRun.BlueRunState.FINISHED;
return restartable;
}

/**
* @return the Pipeline execution
* @todo: This can be removed once https://github.com/jenkinsci/pipeline-model-definition-plugin/pull/596 is available.
*/
@CheckForNull
private CpsFlowExecution getExecution() {
FlowExecutionOwner owner = ((FlowExecutionOwner.Executable) getRun()).asFlowExecutionOwner();
FlowExecution exec = owner.getOrNull();
return exec instanceof CpsFlowExecution ? (CpsFlowExecution) exec : null;
}

/**
* Returns whether a stage is restartable.
* @param stageName the stage name
* @return true is restartable, false otherwise
* @todo: This can be removed once https://github.com/jenkinsci/pipeline-model-definition-plugin/pull/596 is available.
*/
private boolean isRestartable(String stageName) {
FlowExecution execution = getExecution();
if (execution != null) {
ExecutionModelAction execAction = getRun().getAction(ExecutionModelAction.class);
if (execAction != null) {
ModelASTStages stages = execAction.getStages();
if (stages != null) {
for (ModelASTStage s : stages.getStages()) {
if(s.getName().equals(stageName)) {
return !Utils.stageHasStatusOf(s.getName(), execution,
StageStatus.getSkippedForFailure(), StageStatus.getSkippedForUnstable());
}
}
}
}
}
return false;
Expand Down

0 comments on commit 1ec0fd7

Please sign in to comment.