Skip to content

Commit

Permalink
topology for jenkins pipeline job (#79)
Browse files Browse the repository at this point in the history
* user story #560010: Pipeline as a Code - Octane pipeline topology should reflect the pipeline stages
  • Loading branch information
lazara3 authored and m-seldin committed Apr 17, 2018
1 parent 991e27a commit 7e31a18
Show file tree
Hide file tree
Showing 3 changed files with 148 additions and 82 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@
import com.hp.octane.integrations.dto.snapshots.CIBuildResult;
import com.hpe.application.automation.tools.octane.configuration.ConfigurationService;
import com.hpe.application.automation.tools.octane.model.CIEventCausesFactory;
import com.hpe.application.automation.tools.octane.model.processors.builders.WorkFlowRunProcessor;
import com.hpe.application.automation.tools.octane.model.processors.parameters.ParameterProcessors;
import com.hpe.application.automation.tools.octane.model.processors.projects.JobProcessorFactory;
import com.hpe.application.automation.tools.octane.model.processors.scm.SCMProcessor;
Expand Down Expand Up @@ -112,8 +111,9 @@ public void onStarted(final Run r, TaskListener listener) {
}

OctaneSDK.getInstance().getEventsService().publishEvent(event);
WorkFlowRunProcessor workFlowRunProcessor = new WorkFlowRunProcessor(r);
workFlowRunProcessor.registerEvents(executor);
//events on the internal stages of the workflowRun are handled in this place:
// com.hpe.application.automation.tools.octane.workflow.WorkflowGraphListener

} else {
if (r.getParent() instanceof MatrixConfiguration) {
event = dtoFactory.newDTO(CIEvent.class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,45 +31,27 @@
*
*/

package com.hpe.application.automation.tools.octane.model.processors.builders;
package com.hpe.application.automation.tools.octane.workflow;

import com.google.common.util.concurrent.ListenableFuture;
import com.hpe.application.automation.tools.octane.workflow.WorkflowGraphListener;
import hudson.model.Run;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jenkinsci.plugins.workflow.flow.FlowExecution;
import org.jenkinsci.plugins.workflow.job.WorkflowRun;
import com.cloudbees.workflow.rest.external.StatusExt;
import com.hp.octane.integrations.dto.snapshots.CIBuildResult;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
public class WorkFlowUtils {

/**
* Created by gadiel on 21/07/2016.
*/

public class WorkFlowRunProcessor {
private static final Logger logger = LogManager.getLogger(WorkFlowRunProcessor.class);
WorkflowRun workFlowRun;
public static CIBuildResult convertStatus(StatusExt status) {

public WorkFlowRunProcessor(Run r) {
this.workFlowRun = (WorkflowRun) r;
}
switch (status) {
case FAILED:
return CIBuildResult.FAILURE;
case SUCCESS:
return CIBuildResult.SUCCESS;
case UNSTABLE:
return CIBuildResult.UNSTABLE;
case ABORTED:
return CIBuildResult.ABORTED;
default:
return CIBuildResult.UNAVAILABLE;
}

public void registerEvents(ExecutorService executor) {
ListenableFuture<FlowExecution> promise = workFlowRun.getExecutionPromise();
promise.addListener(new Runnable() {
@Override
public void run() {
try {
FlowExecution ex = workFlowRun.getExecutionPromise().get();
ex.addListener(new WorkflowGraphListener());
} catch (InterruptedException ie) {
logger.error("failed to obtain execution promise of " + workFlowRun, ie);
} catch (ExecutionException ee) {
logger.error("failed to obtain execution promise of " + workFlowRun, ee);
}
}
}, executor);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,17 @@
package com.hpe.application.automation.tools.octane.workflow;


import com.cloudbees.workflow.rest.external.StageNodeExt;
import com.hp.octane.integrations.OctaneSDK;
import com.hp.octane.integrations.dto.DTOFactory;
import com.hp.octane.integrations.dto.causes.CIEventCause;
import com.hp.octane.integrations.dto.causes.CIEventCauseType;

import com.hp.octane.integrations.dto.events.CIEvent;
import com.hp.octane.integrations.dto.events.CIEventType;
import com.hp.octane.integrations.dto.events.PhaseType;
import com.hpe.application.automation.tools.octane.model.CIEventCausesFactory;
import com.hpe.application.automation.tools.octane.tests.build.BuildHandlerUtils;
import hudson.Extension;
import hudson.model.*;
import org.jenkinsci.plugins.workflow.actions.WorkspaceAction;
Expand All @@ -50,39 +57,56 @@
import java.util.*;

/**
* Created by gadiel on 07/06/2016.
* Jenkins create a new instance of this for each run of workflowRun (by using @Extension annotation)
* 1. This listener send an event on stage start and stage finish.
* 2. this listener save the details of the node (after the node finished to run) for the next flow of the test results report.
*
* User: gadiel
* Date: 07/06/2016
* Time: 17:21
*/
@Extension
public class WorkflowGraphListener implements GraphListener {
private static final DTOFactory dtoFactory = DTOFactory.getInstance();
private static final DTOFactory dtoFactory = DTOFactory.getInstance();
// private Stack<CIEvent> finishedEventsStack = new Stack<CIEvent>();
// String lastDisplayName = "";
// String lastId = "";
// CIEventCause lastCIEventCause;
public static FlowNodeContainer container;
public void onNewHead(FlowNode flowNode) {
if (flowNode instanceof StepEndNode) {
//finishAllStartedEvents();
WorkspaceAction workspaceAction =((StepEndNode) flowNode).getStartNode().getAction(WorkspaceAction.class);
if(workspaceAction!=null){

try {
WorkflowRun run = (WorkflowRun) flowNode.getExecution().getOwner().getExecutable();
//TaskListener listener = flowNode.getExecution().getOwner().getListener();
WorkflowBuildAdapter adapter = new WorkflowBuildAdapter(run.getParent(), run, workspaceAction.getWorkspace());
FlowNodeContainer.addFlowNode(adapter);
} catch (IOException e) {
e.printStackTrace();
}
}
// } else if (StageNodeExt.isStageNode(flowNode)) {

public static FlowNodeContainer container;

private StageNodeExt previousStage = null;

@Override
public void onNewHead(FlowNode flowNode) {
if (flowNode instanceof StepEndNode) {
sendFinishEventOnPreviousStage(previousStage, flowNode);

WorkspaceAction workspaceAction = ((StepEndNode) flowNode).getStartNode().getAction(WorkspaceAction.class);
if (workspaceAction != null) {

try {
WorkflowRun run = (WorkflowRun) flowNode.getExecution().getOwner().getExecutable();
WorkflowBuildAdapter adapter = new WorkflowBuildAdapter(run.getParent(), run, workspaceAction.getWorkspace());
FlowNodeContainer.addFlowNode(adapter);
} catch (IOException e) {
e.printStackTrace();
}
}
} else if (StageNodeExt.isStageNode(flowNode)) {
//ints a stage - it is also a finish of the previous stage - will send finish event
sendFinishEventOnPreviousStage(previousStage, flowNode);
sendStartEventOnCurrentStage(flowNode);

// .setEstimatedDuration(r.getEstimatedDuration())
// .setCauses(CIEventCausesFactory.processCauses(extractCauses(r)));
// // its a stage node - it is also a finish of previous stage
// finishAllStartedEvents();
// // starting an event:
// dispatchStartEvent(flowNode);
// // after the dispatching of the event, we create the finish event and add it to the queue:
// createFinishEvent(flowNode);
}
}
// else if (flowNode instanceof StepAtomNode) // its outer Job
// {
// if(isItStageStep(flowNode)){
Expand All @@ -96,16 +120,76 @@ public void onNewHead(FlowNode flowNode) {
// popNewJobEvent(flowNode); // popping a new event (we want to draw it on NGA)
// }

}
}

private void sendFinishEventOnPreviousStage(StageNodeExt previousStageNode, FlowNode flowNode) {
if (previousStageNode == null) {
return;
}

try {
WorkflowRun parentRun = (WorkflowRun) flowNode.getExecution().getOwner().getExecutable();

CIEvent event = dtoFactory.newDTO(CIEvent.class)
.setEventType(CIEventType.FINISHED)
.setPhaseType(PhaseType.POST)
.setProject(previousStageNode.getName())
.setStartTime(previousStageNode.getStartTimeMillis())
.setNumber(String.valueOf(parentRun.getNumber()))
.setBuildCiId(BuildHandlerUtils.getBuildCiId(parentRun))
.setCauses(getCauses(parentRun))
.setDuration(previousStageNode.getDurationMillis())
.setEstimatedDuration(previousStageNode.getDurationMillis())
.setResult(WorkFlowUtils.convertStatus(previousStageNode.getStatus()));

OctaneSDK.getInstance().getEventsService().publishEvent(event);
this.previousStage = null;

} catch (IOException e) {
e.printStackTrace();
}
}

private List<CIEventCause> getCauses(WorkflowRun parentRun) {
CIEventCause causes = dtoFactory.newDTO(CIEventCause.class)
.setType(CIEventCauseType.UPSTREAM)
.setProject(BuildHandlerUtils.getJobCiId(parentRun))
.setBuildCiId(BuildHandlerUtils.getBuildCiId(parentRun))
.setCauses(CIEventCausesFactory.processCauses((parentRun.getCauses())));

List<CIEventCause> causeList = new ArrayList<>();
causeList.add(causes);

return causeList;
}

private void sendStartEventOnCurrentStage(FlowNode flowNode) {
CIEvent event;
try {
StageNodeExt stageNode = StageNodeExt.create(flowNode);
WorkflowRun parentRun = (WorkflowRun) flowNode.getExecution().getOwner().getExecutable();

event = dtoFactory.newDTO(CIEvent.class)
.setEventType(CIEventType.STARTED)
.setPhaseType(PhaseType.POST)
.setProject(stageNode.getName())
.setStartTime(stageNode.getStartTimeMillis())
.setNumber(String.valueOf(parentRun.getNumber()))
.setBuildCiId(BuildHandlerUtils.getBuildCiId(parentRun))
.setCauses(getCauses(parentRun));

OctaneSDK.getInstance().getEventsService().publishEvent(event);
previousStage = stageNode;
} catch (IOException e) {
e.printStackTrace();
previousStage = null;
}
}

// private boolean isItBuildStep(FlowNode flowNode) {
// return ((StepAtomNode) flowNode).getDescriptor().getFunctionName().equalsIgnoreCase("build");
// }
//
// private boolean isItStageStep(FlowNode flowNode) {
// return ((StepAtomNode) flowNode).getDescriptor().getFunctionName().equalsIgnoreCase("stage");
// }

// private void popNewJobEvent(FlowNode flowNode) {
// // this option is off at the moment.
// // in general, we want to pop regular jobs that created inside a stage HERE,
Expand Down Expand Up @@ -266,26 +350,26 @@ public void onNewHead(FlowNode flowNode) {
//
// }

public static class FlowNodeContainer{
private static Map<String, List<Run>> map = new HashMap<>();
public static class FlowNodeContainer {
private static Map<String, List<Run>> map = new HashMap<>();

protected static void addFlowNode(Run run){
String key = getKey(run);
List<Run> list = map.get(key);
protected static void addFlowNode(Run run) {
String key = getKey(run);
List<Run> list = map.get(key);

if(list == null){
list = new ArrayList<>();
map.put(key,list);
}
list.add(run);
}
if (list == null) {
list = new ArrayList<>();
map.put(key, list);
}
list.add(run);
}

public static List<Run> getFlowNode(Run run){
return map.remove(getKey(run));
}
public static List<Run> getFlowNode(Run run) {
return map.remove(getKey(run));
}

private static String getKey(Run run) {
return run.getId() + run.getParent().getName();
}
}
private static String getKey(Run run) {
return run.getId() + run.getParent().getName();
}
}
}

0 comments on commit 7e31a18

Please sign in to comment.