use of org.jenkinsci.plugins.workflow.graph.FlowNode in project blueocean-plugin by jenkinsci.
the class LinkResolverImpl method resolve.
@Override
public Link resolve(Object modelObject) {
if (modelObject instanceof FlowNode) {
FlowNode flowNode = (FlowNode) modelObject;
BlueRun r = resolveFlowNodeRun(flowNode);
if (PipelineNodeUtil.isParallelBranch(flowNode) || PipelineNodeUtil.isStage(flowNode)) {
// its Node
if (r != null) {
return r.getLink().rel("nodes/" + flowNode.getId());
}
} else if (flowNode instanceof StepAtomNode && !PipelineNodeUtil.isStage(flowNode)) {
if (r != null) {
return r.getLink().rel("steps/" + flowNode.getId());
}
}
} else if (modelObject instanceof BluePipelineNode || modelObject instanceof BluePipelineStep) {
return ((Resource) modelObject).getLink();
}
return null;
}
use of org.jenkinsci.plugins.workflow.graph.FlowNode in project blueocean-plugin by jenkinsci.
the class PipelineNodeGraphVisitor method chunkEnd.
@Override
public void chunkEnd(@Nonnull FlowNode endNode, @CheckForNull FlowNode afterBlock, @Nonnull ForkScanner scanner) {
super.chunkEnd(endNode, afterBlock, scanner);
if (isNodeVisitorDumpEnabled)
dump(String.format("chunkEnd=> id: %s, name: %s, function: %s, type:%s", endNode.getId(), endNode.getDisplayName(), endNode.getDisplayFunctionName(), endNode.getClass()));
if (isNodeVisitorDumpEnabled && endNode instanceof StepEndNode) {
dump("\tStartNode: " + ((StepEndNode) endNode).getStartNode());
}
if (endNode instanceof StepStartNode) {
if (endNode.getDisplayFunctionName().equals("node")) {
agentNode = (StepStartNode) endNode;
}
}
// capture orphan branches
captureOrphanParallelBranches();
//if block stage node push it to stack as it may have nested stages
if (parallelEnd == null && endNode instanceof StepEndNode && //skip synthetic stages
!PipelineNodeUtil.isSyntheticStage(((StepEndNode) endNode).getStartNode()) && PipelineNodeUtil.isStage(((StepEndNode) endNode).getStartNode())) {
//XXX: There seems to be bug in eventing, chunkEnd is sent twice for the same FlowNode
// Lets peek and if the last one is same as this endNode then skip adding it
FlowNode node = null;
if (!nestedStages.empty()) {
node = nestedStages.peek();
}
if (node == null || !node.equals(endNode)) {
nestedStages.push(endNode);
}
}
firstExecuted = null;
// if we're using marker-based (and not block-scoped) stages, add the last node as part of its contents
if (!(endNode instanceof BlockEndNode)) {
atomNode(null, endNode, afterBlock, scanner);
}
}
use of org.jenkinsci.plugins.workflow.graph.FlowNode in project blueocean-plugin by jenkinsci.
the class PipelineNodeGraphVisitor method createParallelSyntheticNode.
/**
* Create synthetic stage that wraps a parallel block at top level, that is not enclosed inside a stage.
*/
@Nullable
private FlowNodeWrapper createParallelSyntheticNode() {
if (parallelBranches.isEmpty()) {
return null;
}
FlowNodeWrapper firstBranch = parallelBranches.getLast();
FlowNodeWrapper parallel = firstBranch.getFirstParent();
String firstNodeId = firstBranch.getId();
List<FlowNode> parents;
if (parallel != null) {
parents = parallel.getNode().getParents();
} else {
parents = new ArrayList<>();
}
FlowNode syntheticNode = new FlowNode(firstBranch.getNode().getExecution(), createSyntheticStageId(firstNodeId, PARALLEL_SYNTHETIC_STAGE_NAME), parents) {
@Override
protected String getTypeDisplayName() {
return PARALLEL_SYNTHETIC_STAGE_NAME;
}
};
syntheticNode.addAction(new LabelAction(PARALLEL_SYNTHETIC_STAGE_NAME));
long duration = 0;
long pauseDuration = 0;
long startTime = 0;
//= parallelStartNode.getAction(TimingAction.class);
TimingAction timingAction = null;
if (timingAction != null) {
startTime = timingAction.getStartTime();
}
boolean isCompleted = true;
boolean isPaused = false;
boolean isFailure = false;
boolean isUnknown = false;
for (FlowNodeWrapper pb : parallelBranches) {
if (!isPaused && pb.getStatus().getState() == BlueRun.BlueRunState.PAUSED) {
isPaused = true;
}
if (isCompleted && pb.getStatus().getState() != BlueRun.BlueRunState.FINISHED) {
isCompleted = false;
}
if (!isFailure && pb.getStatus().getResult() == BlueRun.BlueRunResult.FAILURE) {
isFailure = true;
}
if (!isUnknown && pb.getStatus().getResult() == BlueRun.BlueRunResult.UNKNOWN) {
isUnknown = true;
}
duration += pb.getTiming().getTotalDurationMillis();
pauseDuration += pb.getTiming().getPauseDurationMillis();
}
BlueRun.BlueRunState state = isCompleted ? BlueRun.BlueRunState.FINISHED : (isPaused ? BlueRun.BlueRunState.PAUSED : BlueRun.BlueRunState.RUNNING);
BlueRun.BlueRunResult result = isFailure ? BlueRun.BlueRunResult.FAILURE : (isUnknown ? BlueRun.BlueRunResult.UNKNOWN : BlueRun.BlueRunResult.SUCCESS);
TimingInfo timingInfo = new TimingInfo(duration, pauseDuration, startTime);
FlowNodeWrapper synStage = new FlowNodeWrapper(syntheticNode, new NodeRunStatus(result, state), timingInfo, run);
Iterator<FlowNodeWrapper> sortedBranches = parallelBranches.descendingIterator();
while (sortedBranches.hasNext()) {
FlowNodeWrapper p = sortedBranches.next();
p.addParent(synStage);
synStage.addEdge(p.getId());
}
return synStage;
}
use of org.jenkinsci.plugins.workflow.graph.FlowNode in project blueocean-plugin by jenkinsci.
the class PipelineNodeUtil method getCauseOfBlockage.
/**
* Gives cause of block for declarative style plugin where agent (node block) is declared inside a stage.
* <pre>
* pipeline {
* agent none
* stages {
* stage ('first') {
* agent {
* label 'first'
* }
* steps{
* sh 'echo "from first"'
* }
* }
* }
* }
* </pre>
*
* @param stage stage's {@link FlowNode}
* @param nodeBlock agent or node block's {@link FlowNode}
* @param run {@link WorkflowRun} instance
* @return cause of block if present, nul otherwise
* @throws IOException in case of IOException
* @throws InterruptedException in case of Interrupted exception
*/
@CheckForNull
public static String getCauseOfBlockage(@Nonnull FlowNode stage, @Nullable FlowNode nodeBlock, @Nonnull WorkflowRun run) throws IOException, InterruptedException {
if (nodeBlock != null) {
//Check and see if this node block is inside this stage
for (FlowNode p : nodeBlock.getParents()) {
if (p.equals(stage)) {
//see if there is blocked item in queue
for (Queue.Item i : Jenkins.getInstance().getQueue().getItems()) {
if (i.task instanceof ExecutorStepExecution.PlaceholderTask) {
ExecutorStepExecution.PlaceholderTask task = (ExecutorStepExecution.PlaceholderTask) i.task;
String cause = i.getCauseOfBlockage().getShortDescription();
if (task.getCauseOfBlockage() != null) {
cause = task.getCauseOfBlockage().getShortDescription();
}
Run r = task.runForDisplay();
//Set cause if its there and run and node block in the queue is same as the one we
if (cause != null && r != null && r.equals(run) && task.getNode() != null && task.getNode().equals(nodeBlock)) {
return cause;
}
}
}
}
}
}
return null;
}
use of org.jenkinsci.plugins.workflow.graph.FlowNode in project blueocean-plugin by jenkinsci.
the class PipelineNodeTest method testNestedBlockStage.
@Test
public void testNestedBlockStage() throws Exception {
String pipeline = "" + "node {" + //start
" stage ('dev');" + " echo ('development'); " + " stage ('Build') { " + " echo ('Building'); " + " stage('Packaging') {" + " echo 'packaging...'" + " }" + " } \n" + " stage ('test') { " + " echo ('Testing'); " + " parallel firstBranch: {\n" + " echo 'Hello first Branch'\n" + " echo 'first Branch 1'\n" + " echo 'first Branch end'\n" + " \n" + " },\n" + " thirdBranch: {\n" + " echo 'Hello third Branch'\n" + " sh 'sleep 1' \n" + " echo 'third Branch 1'\n" + " echo 'third Branch 2'\n" + " echo 'third Branch end'\n" + " \n" + " },\n" + " secondBranch: {" + " echo 'first Branch'\n" + " stage('firstBranchTest') {" + " echo 'running firstBranchTest'\n" + " sh 'sleep 1'\n" + " }\n" + " echo 'first Branch end'\n" + " },\n" + " failFast: false\n" + " } \n" + " stage ('deploy') { " + " writeFile file: 'file.txt', text:'content'; " + " archive(includes: 'file.txt'); " + " echo ('Deploying'); " + " } \n" + "}";
WorkflowJob job1 = j.jenkins.createProject(WorkflowJob.class, "pipeline1");
job1.setDefinition(new CpsFlowDefinition(pipeline));
WorkflowRun b1 = job1.scheduleBuild2(0).get();
j.assertBuildStatusSuccess(b1);
NodeGraphBuilder builder = NodeGraphBuilder.NodeGraphBuilderFactory.getInstance(b1);
List<FlowNode> stages = getStages(builder);
List<FlowNode> parallels = getParallelNodes(builder);
Assert.assertEquals(4, stages.size());
Assert.assertEquals(3, parallels.size());
//TODO: complete test
List<Map> resp = get("/organizations/jenkins/pipelines/pipeline1/runs/1/nodes/", List.class);
Assert.assertEquals(7, resp.size());
String testStageId = null;
String devNodeId = null;
for (int i = 0; i < resp.size(); i++) {
Map rn = resp.get(i);
List<Map> edges = (List<Map>) rn.get("edges");
if (rn.get("displayName").equals("dev")) {
Assert.assertEquals(0, i);
devNodeId = (String) rn.get("id");
Assert.assertEquals(1, edges.size());
Assert.assertEquals(rn.get("result"), "SUCCESS");
Assert.assertEquals(rn.get("state"), "FINISHED");
} else if (rn.get("displayName").equals("build")) {
Assert.assertEquals(1, i);
Assert.assertEquals(1, edges.size());
Assert.assertEquals(rn.get("result"), "SUCCESS");
Assert.assertEquals(rn.get("state"), "FINISHED");
} else if (rn.get("displayName").equals("test")) {
Assert.assertEquals(2, i);
testStageId = (String) rn.get("id");
Assert.assertEquals(3, edges.size());
Assert.assertEquals(rn.get("result"), "SUCCESS");
Assert.assertEquals(rn.get("state"), "FINISHED");
} else if (rn.get("displayName").equals("firstBranch")) {
Assert.assertEquals(3, i);
Assert.assertEquals(1, edges.size());
Assert.assertEquals(rn.get("result"), "SUCCESS");
Assert.assertEquals(rn.get("state"), "FINISHED");
} else if (rn.get("displayName").equals("secondBranch")) {
Assert.assertEquals(4, i);
Assert.assertEquals(1, edges.size());
Assert.assertEquals(rn.get("result"), "SUCCESS");
Assert.assertEquals(rn.get("state"), "FINISHED");
} else if (rn.get("displayName").equals("thirdBranch")) {
Assert.assertEquals(5, i);
Assert.assertEquals(1, edges.size());
Assert.assertEquals(rn.get("result"), "SUCCESS");
Assert.assertEquals(rn.get("state"), "FINISHED");
} else if (rn.get("displayName").equals("deploy")) {
Assert.assertEquals(6, i);
Assert.assertEquals(0, edges.size());
Assert.assertEquals(rn.get("result"), "SUCCESS");
Assert.assertEquals(rn.get("state"), "FINISHED");
}
}
resp = get("/organizations/jenkins/pipelines/pipeline1/runs/1/steps/", List.class);
Assert.assertEquals(19, resp.size());
Assert.assertNotNull(testStageId);
resp = get("/organizations/jenkins/pipelines/pipeline1/runs/1/nodes/" + testStageId + "/steps/", List.class);
Assert.assertEquals(13, resp.size());
//firstBranch is parallel with nested stage. firstBranch /steps should also include steps inside nested stage
FlowNode firstBranch = null;
FlowNode secondBranch = null;
FlowNode thirdBranch = null;
for (FlowNode n : parallels) {
if (n.getDisplayName().equals("Branch: firstBranch")) {
firstBranch = n;
}
if (n.getDisplayName().equals("Branch: secondBranch")) {
secondBranch = n;
}
if (n.getDisplayName().equals("Branch: thirdBranch")) {
thirdBranch = n;
}
}
Assert.assertNotNull(firstBranch);
resp = get("/organizations/jenkins/pipelines/pipeline1/runs/1/nodes/" + firstBranch.getId() + "/steps/", List.class);
Assert.assertEquals(3, resp.size());
Assert.assertNotNull(secondBranch);
resp = get("/organizations/jenkins/pipelines/pipeline1/runs/1/nodes/" + secondBranch.getId() + "/steps/", List.class);
Assert.assertEquals(4, resp.size());
Assert.assertNotNull(thirdBranch);
resp = get("/organizations/jenkins/pipelines/pipeline1/runs/1/nodes/" + thirdBranch.getId() + "/steps/", List.class);
Assert.assertEquals(5, resp.size());
Assert.assertNotNull(devNodeId);
resp = get("/organizations/jenkins/pipelines/pipeline1/runs/1/nodes/" + devNodeId + "/steps/", List.class);
Assert.assertEquals(1, resp.size());
}
Aggregations