Merge remote-tracking branch 'origin/master'

This commit is contained in:
HopeLi 2025-07-08 17:37:41 +08:00
commit c765a7417a
12 changed files with 203 additions and 13 deletions

View File

@ -5,6 +5,7 @@ import cd.casic.ci.process.dto.req.shuimu.ShuiMuProjectCreateReq;
import cd.casic.ci.process.dto.req.shuimu.ShuiMuTestProblemReq; import cd.casic.ci.process.dto.req.shuimu.ShuiMuTestProblemReq;
import cd.casic.ci.process.dto.req.shuimu.ShuiMuUpdateWFuzzJsonReq; import cd.casic.ci.process.dto.req.shuimu.ShuiMuUpdateWFuzzJsonReq;
import cd.casic.ci.process.dto.resp.shuimu.ShuiMuProjectInfoResp; import cd.casic.ci.process.dto.resp.shuimu.ShuiMuProjectInfoResp;
import cd.casic.ci.process.dto.resp.shuimu.ShuiMuProjectReportResp;
import cd.casic.ci.process.dto.resp.shuimu.ShuiMuProjectVersionResp; import cd.casic.ci.process.dto.resp.shuimu.ShuiMuProjectVersionResp;
import cd.casic.ci.process.dto.resp.shuimu.ShuiMuTestProblemResp; import cd.casic.ci.process.dto.resp.shuimu.ShuiMuTestProblemResp;
import cd.casic.ci.process.process.service.shuimu.ShuiMuService; import cd.casic.ci.process.process.service.shuimu.ShuiMuService;
@ -69,4 +70,8 @@ public class ShuiMuController {
public CommonResult<List<ShuiMuTestProblemResp>> problemsOfTest(@RequestBody ShuiMuTestProblemReq req){ public CommonResult<List<ShuiMuTestProblemResp>> problemsOfTest(@RequestBody ShuiMuTestProblemReq req){
return CommonResult.success(shuiMuService.problemsOfTest(req)); return CommonResult.success(shuiMuService.problemsOfTest(req));
} }
@GetMapping("/getProjectReport")
public CommonResult<ShuiMuProjectReportResp> getProjectReport(@RequestParam String projectId){
return CommonResult.success(shuiMuService.getProjectReport(projectId));
}
} }

View File

@ -18,4 +18,5 @@ public class ShuiMuUrlConstant {
public static final String executeAllEntrypointsTest ="/api/driverGeneration/executeAllEntrypointsTest"; public static final String executeAllEntrypointsTest ="/api/driverGeneration/executeAllEntrypointsTest";
public static final String problemsOfTest = "/api/test/problemsOfTest"; public static final String problemsOfTest = "/api/test/problemsOfTest";
public static final String getProjectReport = "/api/project";
} }

View File

@ -0,0 +1,22 @@
package cd.casic.ci.process.dto.resp.shuimu;
import lombok.Data;
@Data
public class ShuiMuProjectReportResp {
private String id;
private String name;
private String language;
private String description;
private String product;
private String ownerId;
private String createBy;
private String createAt;
private String updateAt;
private String deleteAt;
private String projectRunning;
private String problemsCount;
private String fixedProblemsCount;
private String noFixedProblemsCount;
private String projectFlag;
}

View File

@ -5,4 +5,6 @@ public class AFLConstant {
public static final String COMMAND_END="commandEnd"; public static final String COMMAND_END="commandEnd";
public static final String EXECUTABLE_NAME ="executableName"; public static final String EXECUTABLE_NAME ="executableName";
public static final String RUNNING_TIME ="runningTime"; public static final String RUNNING_TIME ="runningTime";
public static final String GROUP_ID= "groupId";
} }

View File

@ -0,0 +1,9 @@
package cd.casic.ci.process.engine.manager;
import cd.casic.ci.process.engine.postHandler.ExecuteTaskPostHandler;
import cd.casic.ci.process.process.dataObject.history.PipPipelineHisInstance;
public interface PostHandlerManager {
public void registerPostHandler(ExecuteTaskPostHandler handler);
public void executePostHandler(PipPipelineHisInstance hisInstance);
}

View File

@ -5,6 +5,7 @@ import cd.casic.ci.process.dto.resp.context.TreeRunContextResp;
import cd.casic.ci.process.engine.constant.EngineRuntimeConstant; import cd.casic.ci.process.engine.constant.EngineRuntimeConstant;
import cd.casic.ci.process.engine.enums.ContextStateEnum; import cd.casic.ci.process.engine.enums.ContextStateEnum;
import cd.casic.ci.process.engine.manager.LoggerManager; import cd.casic.ci.process.engine.manager.LoggerManager;
import cd.casic.ci.process.engine.manager.PostHandlerManager;
import cd.casic.ci.process.engine.manager.RunContextManager; import cd.casic.ci.process.engine.manager.RunContextManager;
import cd.casic.ci.process.engine.runContext.BaseRunContext; import cd.casic.ci.process.engine.runContext.BaseRunContext;
import cd.casic.ci.process.engine.runContext.PipelineRunContext; import cd.casic.ci.process.engine.runContext.PipelineRunContext;
@ -46,11 +47,12 @@ public class DefaultRunContextManager implements RunContextManager {
@Resource @Resource
private LoggerManager loggerManager; private LoggerManager loggerManager;
@Resource @Resource
private PipTaskDao taskDao;
@Resource
private PipPipelineHisInstanceDao hisInstanceDao; private PipPipelineHisInstanceDao hisInstanceDao;
@Resource @Resource
private PipelineService pipelineService; private PipelineService pipelineService;
@Resource
private PostHandlerManager postHandlerManager;
@Override @Override
public Boolean stopPipeline(String pipelineId) { public Boolean stopPipeline(String pipelineId) {
return null; return null;
@ -148,7 +150,7 @@ public class DefaultRunContextManager implements RunContextManager {
} }
pipelineRunContext.changeContextStateAndChild(stateEnum); pipelineRunContext.changeContextStateAndChild(stateEnum);
} }
// 记录日志需要新事成功或失败不影响流水线执行 // 记录日志需要新事成功或失败不影响流水线执行
@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRES_NEW) @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRES_NEW)
public void toHistory(String pipelineId){ public void toHistory(String pipelineId){
log.info("========================开始入库"); log.info("========================开始入库");
@ -193,6 +195,8 @@ public class DefaultRunContextManager implements RunContextManager {
pipPipelineHisInstance.setTargetVersionName(""); pipPipelineHisInstance.setTargetVersionName("");
pipPipelineHisInstance.setTargetVersionId(pipeline.getTargetVersionId()); pipPipelineHisInstance.setTargetVersionId(pipeline.getTargetVersionId());
hisInstanceDao.insert(pipPipelineHisInstance); hisInstanceDao.insert(pipPipelineHisInstance);
// 执行后置处理逻辑
postHandlerManager.executePostHandler(pipPipelineHisInstance);
} }
} }
} }

View File

@ -0,0 +1,40 @@
package cd.casic.ci.process.engine.manager.impl;
import cd.casic.ci.process.engine.manager.PostHandlerManager;
import cd.casic.ci.process.engine.postHandler.ExecuteTaskPostHandler;
import cd.casic.ci.process.process.dataObject.history.PipPipelineHisInstance;
import cd.casic.framework.commons.exception.ServiceException;
import cd.casic.framework.commons.exception.enums.GlobalErrorCodeConstants;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
@Component
public class MemoryPostHandlerManager implements PostHandlerManager {
private final ConcurrentHashMap<String, List<ExecuteTaskPostHandler>> handlerMap = new ConcurrentHashMap<>();
@Override
public void registerPostHandler(ExecuteTaskPostHandler handler) {
if (handler==null|| StringUtils.isNotEmpty(handler.getPipelineId())) {
throw new ServiceException(GlobalErrorCodeConstants.PIPELINE_ERROR.getCode(),"注册后置处理器失败");
}
List<ExecuteTaskPostHandler> orDefault = handlerMap.getOrDefault(handler.getPipelineId(), new CopyOnWriteArrayList<>());
orDefault.add(handler);
handlerMap.put(handler.getPipelineId(),orDefault);
}
@Override
public void executePostHandler(PipPipelineHisInstance hisInstance) {
String pipelineId = hisInstance.getPipelineId();
List<ExecuteTaskPostHandler> pipExecutePostHandlers = handlerMap.get(pipelineId);
if (CollectionUtils.isEmpty(pipExecutePostHandlers)) {
return;
}
for (ExecuteTaskPostHandler postHandler : pipExecutePostHandlers) {
postHandler.executeAfterDone(hisInstance);
}
}
}

View File

@ -0,0 +1,17 @@
package cd.casic.ci.process.engine.postHandler;
import cd.casic.ci.process.process.dataObject.history.PipPipelineHisInstance;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public abstract class ExecuteTaskPostHandler {
private String taskId;
private String pipelineId;
/**
* 流水线执行结束需要执行的操作
* */
public abstract void executeAfterDone(PipPipelineHisInstance pipPipelineHisInstance);
}

View File

@ -1,26 +1,35 @@
package cd.casic.ci.process.engine.worker.afl; package cd.casic.ci.process.engine.worker.afl;
import cd.casic.ci.process.common.WorkAtom; import cd.casic.ci.process.common.WorkAtom;
import cd.casic.ci.process.dto.req.aflManager.AflManagerReq;
import cd.casic.ci.process.dto.req.resource.ResourceQueryReq; import cd.casic.ci.process.dto.req.resource.ResourceQueryReq;
import cd.casic.ci.process.dto.resp.resource.ResourceFindResp; import cd.casic.ci.process.dto.resp.resource.ResourceFindResp;
import cd.casic.ci.process.dto.resp.taskResource.TaskResourceFindResp; import cd.casic.ci.process.dto.resp.taskResource.TaskResourceFindResp;
import cd.casic.ci.process.engine.constant.AFLConstant; import cd.casic.ci.process.engine.constant.AFLConstant;
import cd.casic.ci.process.engine.constant.AFLSlotCompileConstant;
import cd.casic.ci.process.engine.constant.DIYImageExecuteCommandConstant; import cd.casic.ci.process.engine.constant.DIYImageExecuteCommandConstant;
import cd.casic.ci.process.engine.constant.PipelineVariableConstant; import cd.casic.ci.process.engine.manager.PostHandlerManager;
import cd.casic.ci.process.engine.postHandler.ExecuteTaskPostHandler;
import cd.casic.ci.process.engine.runContext.TaskRunContext; import cd.casic.ci.process.engine.runContext.TaskRunContext;
import cd.casic.ci.process.engine.worker.base.DockerWorker; import cd.casic.ci.process.engine.worker.base.DockerWorker;
import cd.casic.ci.process.process.dataObject.history.PipPipelineHisInstance;
import cd.casic.ci.process.process.dataObject.pipeline.PipPipeline; import cd.casic.ci.process.process.dataObject.pipeline.PipPipeline;
import cd.casic.ci.process.process.dataObject.target.TargetVersion; import cd.casic.ci.process.process.dataObject.target.TargetVersion;
import cd.casic.ci.process.process.dataObject.task.PipTask; import cd.casic.ci.process.process.dataObject.task.PipTask;
import cd.casic.ci.process.process.service.aflManager.AflInfoService;
import cd.casic.ci.process.process.service.aflManager.AflPlotInfoService;
import cd.casic.ci.process.process.service.aflManager.AflSeedInfoService;
import cd.casic.ci.process.process.service.target.TargetVersionService; import cd.casic.ci.process.process.service.target.TargetVersionService;
import cd.casic.ci.process.util.SftpUploadUtil;
import com.alibaba.fastjson.JSON;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import java.io.File; import java.io.File;
import java.util.Map; import java.util.Map;
import java.util.UUID;
import static cd.casic.ci.process.engine.constant.AFLConstant.*; import static cd.casic.ci.process.engine.constant.AFLConstant.*;
import static cd.casic.ci.process.engine.constant.PipelineVariableConstant.*; import static cd.casic.ci.process.engine.constant.PipelineVariableConstant.*;
@ -30,6 +39,14 @@ import static cd.casic.ci.process.engine.constant.PipelineVariableConstant.*;
public class AFLWorker extends DockerWorker { public class AFLWorker extends DockerWorker {
@Resource @Resource
private TargetVersionService targetVersionService; private TargetVersionService targetVersionService;
@Resource
private AflInfoService aflInfoService;
@Resource
private AflSeedInfoService aflSeedInfoService;
@Resource
private AflPlotInfoService aflPlotInfoService;
@Resource
private PostHandlerManager postHandlerManager;
@Override @Override
public void execute(TaskRunContext context) { public void execute(TaskRunContext context) {
int statusCode = -1; int statusCode = -1;
@ -49,6 +66,7 @@ public class AFLWorker extends DockerWorker {
String commandEnd = taskProperties.get(COMMAND_END) instanceof String ? ((String) taskProperties.get(COMMAND_END)) : null; String commandEnd = taskProperties.get(COMMAND_END) instanceof String ? ((String) taskProperties.get(COMMAND_END)) : null;
String imageName = getVariableNearby(context,IMAGE_NAME) instanceof String ? ((String) getVariableNearby(context,IMAGE_NAME)) : null; String imageName = getVariableNearby(context,IMAGE_NAME) instanceof String ? ((String) getVariableNearby(context,IMAGE_NAME)) : null;
String executableName = taskProperties.get(EXECUTABLE_NAME) instanceof String ? ((String) taskProperties.get(EXECUTABLE_NAME)) : null; String executableName = taskProperties.get(EXECUTABLE_NAME) instanceof String ? ((String) taskProperties.get(EXECUTABLE_NAME)) : null;
putGlobalVariable(context, EXECUTABLE_NAME_KEY,imageName);
// 代码编译目录 // 代码编译目录
String workDir = (String)getGlobalVariable(context,AFL_DOCKER_WORK_DIR_KEY); String workDir = (String)getGlobalVariable(context,AFL_DOCKER_WORK_DIR_KEY);
// 入参目录 // 入参目录
@ -102,20 +120,67 @@ public class AFLWorker extends DockerWorker {
toBadEnding(); toBadEnding();
} }
localVariables.put(DIYImageExecuteCommandConstant.STATUS_CODE, statusCode); localVariables.put(DIYImageExecuteCommandConstant.STATUS_CODE, statusCode);
putGlobalVariable(context, EXECUTABLE_NAME_KEY,imageName); afterTaskExecute(context);
afterPipelineExecute(context);
} }
} }
public String cdSourceName(String fileName){ private String cdSourceName(String fileName){
int dotIndex = fileName.lastIndexOf("."); int dotIndex = fileName.lastIndexOf(".");
if (dotIndex!=-1) { if (dotIndex!=-1) {
return "cd "+fileName.substring(0, dotIndex)+"\n"; return "cd "+fileName.substring(0, dotIndex)+"\n";
} }
return ""; return "";
} }
public Long getRunningTime(Double runningTimeHours){ private Long getRunningTime(Double runningTimeHours){
if (runningTimeHours!=null && runningTimeHours >0) { if (runningTimeHours!=null && runningTimeHours >0) {
return (long)(runningTimeHours*60*60*1000); return (long)(runningTimeHours*60*60*1000);
} }
return null; return null;
} }
@Async
public void afterTaskExecute(TaskRunContext context){
append(context,"开始拉取afl输出信息");
PipTask contextDef = (PipTask)context.getContextDef();
Map<String, Object> localVariables = context.getLocalVariables();
String pipelineId =contextDef.getPipelineId();
String taskId = contextDef.getId();
String groupId = UUID.randomUUID().toString().replace("-","");
localVariables.put(GROUP_ID,groupId);
AflManagerReq req = new AflManagerReq();
req.setGroupIdentifier(groupId);
req.setTaskId(taskId);
req.setPipelineId(pipelineId);
try {
aflInfoService.saveAflInfo(req);
} catch (SftpUploadUtil.SftpUploadException e) {
log.error("保存afl信息失败,入参{}", JSON.toJSONString(req),e);
}
aflSeedInfoService.saveAflSeedInfo(req);
try {
aflPlotInfoService.saveAflPlotInfo(req);
} catch (SftpUploadUtil.SftpUploadException e) {
log.error("保存afl信息失败,入参{}", JSON.toJSONString(req),e);
}
}
private void afterPipelineExecute(TaskRunContext context){
append(context,"开始拉取afl输出信息");
PipTask contextDef = (PipTask)context.getContextDef();
String pipelineId =contextDef.getPipelineId();
String taskId = contextDef.getId();
AflManagerReq req = new AflManagerReq();
req.setTaskId(taskId);
req.setPipelineId(pipelineId);
postHandlerManager.registerPostHandler(new ExecuteTaskPostHandler(taskId,pipelineId) {
@Override
public void executeAfterDone(PipPipelineHisInstance pipPipelineHisInstance) {
Map<String, Object> localVariables = context.getLocalVariables();
String groupId = localVariables.get(GROUP_ID) instanceof String ? ((String) localVariables.get(GROUP_ID)) : null;
req.setGroupIdentifier(groupId);
req.setPipelineHistoryId(pipPipelineHisInstance.getId());
aflInfoService.updateHistoryPipelineIdByAflInfo(req);
aflSeedInfoService.updateHistoryPipelineIdByAflSeedInfo(req);
aflPlotInfoService.updateHistoryPipelineIdByAflPlotInfo(req);
}
});
}
} }

View File

@ -7,6 +7,7 @@ import cd.casic.ci.process.engine.constant.PipelineBehaviorConstant;
import cd.casic.ci.process.engine.context.ConstantContext; import cd.casic.ci.process.engine.context.ConstantContext;
import cd.casic.ci.process.engine.enums.ContextStateEnum; import cd.casic.ci.process.engine.enums.ContextStateEnum;
import cd.casic.ci.process.engine.manager.LoggerManager; import cd.casic.ci.process.engine.manager.LoggerManager;
import cd.casic.ci.process.engine.manager.PostHandlerManager;
import cd.casic.ci.process.engine.manager.RunContextManager; import cd.casic.ci.process.engine.manager.RunContextManager;
import cd.casic.ci.process.engine.runContext.BaseRunContext; import cd.casic.ci.process.engine.runContext.BaseRunContext;
@ -50,7 +51,8 @@ public abstract class BaseWorker implements Runnable{
protected LoggerManager loggerManager; protected LoggerManager loggerManager;
@Resource @Resource
protected ResourceManagerService resourceManagerService; protected ResourceManagerService resourceManagerService;
@Resource
protected PostHandlerManager postHandlerManager;
@Override @Override
public void run() { public void run() {

View File

@ -4,10 +4,7 @@ import cd.casic.ci.process.dto.req.shuimu.ShuiMuBuildAndSaveReq;
import cd.casic.ci.process.dto.req.shuimu.ShuiMuProjectCreateReq; import cd.casic.ci.process.dto.req.shuimu.ShuiMuProjectCreateReq;
import cd.casic.ci.process.dto.req.shuimu.ShuiMuTestProblemReq; import cd.casic.ci.process.dto.req.shuimu.ShuiMuTestProblemReq;
import cd.casic.ci.process.dto.req.shuimu.ShuiMuUpdateWFuzzJsonReq; import cd.casic.ci.process.dto.req.shuimu.ShuiMuUpdateWFuzzJsonReq;
import cd.casic.ci.process.dto.resp.shuimu.ShuiMuProjectInfoResp; import cd.casic.ci.process.dto.resp.shuimu.*;
import cd.casic.ci.process.dto.resp.shuimu.ShuiMuProjectResourceResp;
import cd.casic.ci.process.dto.resp.shuimu.ShuiMuProjectVersionResp;
import cd.casic.ci.process.dto.resp.shuimu.ShuiMuTestProblemResp;
import cd.casic.framework.commons.pojo.CommonResult; import cd.casic.framework.commons.pojo.CommonResult;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
@ -38,4 +35,7 @@ public interface ShuiMuService {
ShuiMuProjectResourceResp getProjectResource(String projectId); ShuiMuProjectResourceResp getProjectResource(String projectId);
List<ShuiMuTestProblemResp> problemsOfTest(ShuiMuTestProblemReq req); List<ShuiMuTestProblemResp> problemsOfTest(ShuiMuTestProblemReq req);
ShuiMuProjectReportResp getProjectReport(String projectId);
} }

View File

@ -24,6 +24,7 @@ import org.apache.commons.lang3.StringUtils;
import org.springframework.core.io.FileSystemResource; import org.springframework.core.io.FileSystemResource;
import org.springframework.http.*; import org.springframework.http.*;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap; import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
@ -296,6 +297,28 @@ public class ShuiMuServiceImpl implements ShuiMuService {
String data = jsonObject.getString("data"); String data = jsonObject.getString("data");
return JSONArray.parseArray(data, ShuiMuTestProblemResp.class); return JSONArray.parseArray(data, ShuiMuTestProblemResp.class);
} }
@Override
public ShuiMuProjectReportResp getProjectReport(String projectId) {
HttpEntity<String> entity = new HttpEntity<>(null,getHeaders());
String uriString = UriComponentsBuilder.fromUriString(shuiMuProperties.getBaseUrl() + getProjectReport )
.queryParam("skip",0)
.queryParam("limit",1)
.queryParam("product","code")
.queryParam("projectId",projectId)
.queryParam("showMine",0)
.toUriString();
ResponseEntity<String> exchange = restTemplate.exchange(uriString, HttpMethod.GET, entity, String.class, new HashMap<>());
if (exchange.getStatusCode().isError()) {
throw new ServiceException(GlobalErrorCodeConstants.PIPELINE_ERROR.getCode(),"保存并且构建失败");
}
String data = JSON.parseObject(exchange.getBody()).getString("data");
List<ShuiMuProjectReportResp> list = JSON.parseArray(data, ShuiMuProjectReportResp.class);
if (CollectionUtils.isEmpty(list)) {
return null;
}
return list.get(0);
}
private HttpHeaders getHeaders(){ private HttpHeaders getHeaders(){
HttpHeaders httpHeaders = new HttpHeaders(); HttpHeaders httpHeaders = new HttpHeaders();