use of org.jenkinsci.plugins.workflow.graphanalysis.DepthFirstScanner in project blueocean-plugin by jenkinsci.
the class PipelineNodeGraphVisitor method getPipelineNodeSteps.
@Override
public List<BluePipelineStep> getPipelineNodeSteps(final String nodeId, Link parent) {
FlowExecution execution = run.getExecution();
if (execution == null) {
logger.debug(String.format("Pipeline %s, runid %s has null execution", run.getParent().getName(), run.getId()));
return Collections.emptyList();
}
DepthFirstScanner depthFirstScanner = new DepthFirstScanner();
// If blocked scope, get the end node
FlowNode n = depthFirstScanner.findFirstMatch(execution.getCurrentHeads(), input -> (input != null && input.getId().equals(nodeId) && (PipelineNodeUtil.isStage(input) || PipelineNodeUtil.isParallelBranch(input))));
if (n == null) {
// if no node found or the node is not stage or parallel we return empty steps
return Collections.emptyList();
}
PipelineStepVisitor visitor = new PipelineStepVisitor(run, n);
ForkScanner.visitSimpleChunks(execution.getCurrentHeads(), visitor, new StageChunkFinder());
return visitor.getSteps().stream().map(node -> new PipelineStepImpl(node, parent)).collect(Collectors.toList());
}
use of org.jenkinsci.plugins.workflow.graphanalysis.DepthFirstScanner in project workflow-cps-plugin by jenkinsci.
the class FlowDurabilityTest method verifySucceededCleanly.
static void verifySucceededCleanly(Jenkins j, WorkflowRun run) throws Exception {
Assert.assertEquals(Result.SUCCESS, run.getResult());
int outputHash = run.getLog().hashCode();
FlowExecution exec = run.getExecution();
verifyCompletedCleanly(j, run);
// Confirm the flow graph is fully navigable and contains the heads with appropriate ending
DepthFirstScanner scan = new DepthFirstScanner();
List<FlowNode> allNodes = scan.allNodes(exec);
FlowNode endNode = exec.getCurrentHeads().get(0);
Assert.assertEquals(FlowEndNode.class, endNode.getClass());
assert allNodes.contains(endNode);
Assert.assertEquals(8, allNodes.size());
// Graph structure assertions
Assert.assertEquals(2, scan.filteredNodes(endNode, (Predicate) (Predicates.instanceOf(StepStartNode.class))).size());
Assert.assertEquals(2, scan.filteredNodes(endNode, (Predicate) (Predicates.instanceOf(StepEndNode.class))).size());
Assert.assertEquals(1, scan.filteredNodes(endNode, (Predicate) (Predicates.instanceOf(FlowStartNode.class))).size());
Predicate<FlowNode> sleepOrSemaphoreMatch = Predicates.or(new NodeStepNamePredicate(StepDescriptor.byFunctionName("semaphore").getId()), new NodeStepNamePredicate(StepDescriptor.byFunctionName("sleep").getId()));
Assert.assertEquals(1, scan.filteredNodes(endNode, sleepOrSemaphoreMatch).size());
Assert.assertEquals(1, scan.filteredNodes(endNode, new NodeStepNamePredicate(StepDescriptor.byFunctionName("echo").getId())).size());
for (FlowNode node : (List<FlowNode>) (scan.filteredNodes(endNode, (Predicate) (Predicates.instanceOf(StepNode.class))))) {
Assert.assertNotNull("Node: " + node.toString() + " does not have a TimingAction", node.getAction(TimingAction.class));
}
assertHasTimingAction(run.getExecution());
}
use of org.jenkinsci.plugins.workflow.graphanalysis.DepthFirstScanner in project workflow-cps-plugin by jenkinsci.
the class FlowDurabilityTest method testResumeBlocked.
@Test
public void testResumeBlocked() throws Exception {
final String jobName = "survivesEverything";
final String[] logStart = new String[1];
final List<FlowNode> nodesOut = new ArrayList<FlowNode>();
story.addStepWithDirtyShutdown(new Statement() {
@Override
public void evaluate() throws Throwable {
Jenkins jenkins = story.j.jenkins;
WorkflowRun run = createAndRunSleeperJob(story.j.jenkins, jobName, FlowDurabilityHint.MAX_SURVIVABILITY);
run.getParent().setResumeBlocked(true);
FlowExecution exec = run.getExecution();
if (exec instanceof CpsFlowExecution) {
assert ((CpsFlowExecution) exec).getStorage().isPersistedFully();
}
logStart[0] = JenkinsRule.getLog(run);
nodesOut.addAll(new DepthFirstScanner().allNodes(run.getExecution()));
nodesOut.sort(FlowScanningUtils.ID_ORDER_COMPARATOR);
}
});
story.addStep(new Statement() {
@Override
public void evaluate() throws Throwable {
WorkflowRun run = story.j.jenkins.getItemByFullName(jobName, WorkflowJob.class).getLastBuild();
verifyFailedCleanly(story.j.jenkins, run);
assertIncludesNodes(nodesOut, run);
}
});
}
use of org.jenkinsci.plugins.workflow.graphanalysis.DepthFirstScanner in project workflow-cps-plugin by jenkinsci.
the class FlowDurabilityTest method fuzzTimingDurable.
/**
* Test interrupting build by randomly dying at unpredictable times.
*/
@Test
// Too long to run as part of main suite
@Ignore
@TimedRepeatRule.RepeatForTime(repeatMillis = 170_000)
public void fuzzTimingDurable() throws Exception {
final String jobName = "NestedParallelDurableJob";
final String[] logStart = new String[1];
final List<FlowNode> nodesOut = new ArrayList<FlowNode>();
// Create thread that eventually interrupts Jenkins with a hard shutdown at a random time interval
story.addStepWithDirtyShutdown(new Statement() {
@Override
public void evaluate() throws Throwable {
Jenkins jenkins = story.j.jenkins;
WorkflowJob job = jenkins.getItemByFullName(jobName, WorkflowJob.class);
if (job == null) {
// Job may already have been created
job = jenkins.createProject(WorkflowJob.class, jobName);
FlowDurabilityHint hint = FlowDurabilityHint.MAX_SURVIVABILITY;
TestDurabilityHintProvider provider = Jenkins.getInstance().getExtensionList(TestDurabilityHintProvider.class).get(0);
provider.registerHint(job.getFullName(), hint);
job.setDefinition(new CpsFlowDefinition("echo 'first'\n" + "def steps = [:]\n" + "steps['1'] = {\n" + " echo 'do 1 stuff'\n" + "}\n" + "steps['2'] = {\n" + " echo '2a'\n" + " echo '2b'\n" + " def nested = [:]\n" + " nested['2-1'] = {\n" + " echo 'do 2-1'\n" + " } \n" + " nested['2-2'] = {\n" + " sleep 1\n" + " echo '2 section 2'\n" + " }\n" + " parallel nested\n" + "}\n" + "parallel steps\n" + "echo 'final'"));
}
story.j.buildAndAssertSuccess(job);
long millisDuration = job.getLastBuild().getDuration();
int time = new Random().nextInt((int) millisDuration);
WorkflowRun run = job.scheduleBuild2(0).getStartCondition().get();
Thread.sleep(time);
logStart[0] = JenkinsRule.getLog(run);
nodesOut.clear();
nodesOut.addAll(new DepthFirstScanner().allNodes(run.getExecution()));
nodesOut.sort(FlowScanningUtils.ID_ORDER_COMPARATOR);
}
});
story.addStep(new Statement() {
@Override
public void evaluate() throws Throwable {
WorkflowRun run = story.j.jenkins.getItemByFullName(jobName, WorkflowJob.class).getLastBuild();
if (run.isBuilding()) {
story.j.waitForCompletion(run);
Assert.assertEquals(Result.SUCCESS, run.getResult());
} else {
verifyCompletedCleanly(story.j.jenkins, run);
}
assertIncludesNodes(nodesOut, run);
story.j.assertLogContains(logStart[0], run);
}
});
}
use of org.jenkinsci.plugins.workflow.graphanalysis.DepthFirstScanner in project workflow-cps-plugin by jenkinsci.
the class FlowDurabilityTest method assertIncludesNodes.
/**
* Verify that we retain and flowgraph start with the included nodes, which must be in sorted order
*/
void assertIncludesNodes(List<FlowNode> prefixNodes, WorkflowRun run) throws Exception {
List<FlowNode> nodes = new DepthFirstScanner().allNodes(run.getExecution());
nodes.sort(FlowScanningUtils.ID_ORDER_COMPARATOR);
// Make sure we have the starting nodes at least
assert prefixNodes.size() <= nodes.size();
for (int i = 0; i < prefixNodes.size(); i++) {
try {
FlowNode match = prefixNodes.get(i);
FlowNode after = nodes.get(i);
Assert.assertEquals(match.getDisplayFunctionName(), after.getDisplayFunctionName());
} catch (Exception ex) {
throw new Exception("Error with flownode at index=" + i, ex);
}
}
}
Aggregations