feat(质量分析) 质量分析接口&分析结果列表接口

sonar7.7
youys 1 year ago
parent 0783540035
commit 43d5ed2be5

@ -1,13 +1,14 @@
package net.educoder.ecsonar.controller; package net.educoder.ecsonar.controller;
import net.educoder.ecsonar.model.RollPage;
import net.educoder.ecsonar.model.api.QualityInspect; import net.educoder.ecsonar.model.api.QualityInspect;
import net.educoder.ecsonar.model.api.QualityInspectIsCompleted;
import net.educoder.ecsonar.model.api.QualityInspectResultData;
import net.educoder.ecsonar.model.vo.GraduationProjectQualityInspectVO; import net.educoder.ecsonar.model.vo.GraduationProjectQualityInspectVO;
import net.educoder.ecsonar.model.vo.GraduationQualityInspectResultQueryVO;
import net.educoder.ecsonar.services.GraduationProjectQualityInspectService; import net.educoder.ecsonar.services.GraduationProjectQualityInspectService;
import net.educoder.ecsonar.utils.ResponseResult; import net.educoder.ecsonar.utils.ResponseResult;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.List; import java.util.List;
@ -15,7 +16,7 @@ import java.util.List;
/** /**
* @Author: youys * @Author: youys
* @Date: 2023/8/30 * @Date: 2023/8/30
* @Description: * @Description:
*/ */
@RestController @RestController
@ -24,15 +25,38 @@ public class GraduationProjectController {
@Resource @Resource
private GraduationProjectQualityInspectService qualityInspectService; private GraduationProjectQualityInspectService graduationProjectQualityInspect;
@GetMapping("/qualityInspect") /**
public ResponseResult qualityInspect(@RequestBody List<GraduationProjectQualityInspectVO> qualityInspectVOList){ *
QualityInspect qualityInspect = qualityInspectService.graduationProjectQualityInspect(qualityInspectVOList); * @param qualityInspectVOList
* @return
*/
@PostMapping("/qualityInspect")
public ResponseResult graduationQualityInspect(@RequestBody List<GraduationProjectQualityInspectVO> qualityInspectVOList){
QualityInspect qualityInspect = graduationProjectQualityInspect.graduationProjectQualityInspect(qualityInspectVOList);
return ResponseResult.success(qualityInspect); return ResponseResult.success(qualityInspect);
} }
/**
*
*
* @param graduationQualityInspectResultQueryVO
* @return
*/
@RequestMapping(value = "qualityInspectResultQuery", method = RequestMethod.GET)
@ResponseBody
public ResponseResult graduationQualityInspectResultQuery(@RequestBody GraduationQualityInspectResultQueryVO graduationQualityInspectResultQueryVO) {
QualityInspectIsCompleted isCompleted = graduationProjectQualityInspect.qualityInspectIsCompleted(graduationQualityInspectResultQueryVO.getTaskId());
if (isCompleted.getCompleted() != 1) {
return ResponseResult.error("质量检测正在处理中");
}
RollPage<QualityInspectResultData> result = graduationProjectQualityInspect.qualityInspectResultQuery(graduationQualityInspectResultQueryVO);
return ResponseResult.success(result);
}
} }

@ -5,7 +5,7 @@ import java.math.BigDecimal;
/** /**
* @Author: youys * @Author: youys
* @Date: 2022/1/17 * @Date: 2022/1/17
* @Description: * @Description:
*/ */
public class QualityInspectResultData { public class QualityInspectResultData {

@ -0,0 +1,38 @@
package net.educoder.ecsonar.model.vo;
import lombok.Data;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
/**
* @Author: youys
* @Date: 2023/9/1
* @Description:
*/
@Data
public class GraduationQualityInspectResultQueryVO {
private Integer pageSize;
@Min(value = 1, message = "起始页最少是1")
private Integer pageNumber;
@NotBlank(message = "任务id不能为空")
private String taskId;
@Min(value = 1, message = "最小值为1")
@Max(value = 100, message = "最大值为100")
private Integer bugRate;
@Min(value = 1, message = "最小值为1")
@Max(value = 100, message = "最大值为100")
private Integer vulnerabilityRate;
@Min(value = 1, message = "最小值为1")
@Max(value = 100, message = "最大值为100")
private Integer codeSmallRate;
}

@ -4,10 +4,13 @@ import net.educoder.ecsonar.config.DynamicDataSourceConfig;
import net.educoder.ecsonar.config.DynamicDataSourceContextHolder; import net.educoder.ecsonar.config.DynamicDataSourceContextHolder;
import net.educoder.ecsonar.dao.*; import net.educoder.ecsonar.dao.*;
import net.educoder.ecsonar.model.GameCodes; import net.educoder.ecsonar.model.GameCodes;
import net.educoder.ecsonar.model.GraduationProjectTaskInfoDetail;
import net.educoder.ecsonar.model.Project; import net.educoder.ecsonar.model.Project;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.annotation.Resource;
/** /**
* @Author: youys * @Author: youys
* @Date: 2021/12/31 * @Date: 2021/12/31
@ -32,7 +35,8 @@ public class DbOperateService {
@Autowired @Autowired
private CloudTaskInfoDetailDao cloudTaskInfoDetailDao; private CloudTaskInfoDetailDao cloudTaskInfoDetailDao;
private GraduationProjectTaskInfoDao graduationProjectTaskInfoDao; @Resource
private GraduationProjectTaskInfoDetailDao graduationProjectTaskInfoDetailDao;
/** /**
* idcode * idcode
@ -67,7 +71,7 @@ public class DbOperateService {
} }
public void updateGraduationProjectTaskInfoDetail(String id, Integer status) { public void updateGraduationProjectTaskInfoDetail(String id, Integer status) {
graduationProjectTaskInfoDao.updateTaskInfoStatus(id, status); graduationProjectTaskInfoDetailDao.updateGraduationProjectTaskInfoDetailStatus(id, status);
} }
public void updateCloudTaskInfoDetail(String id, Integer status) { public void updateCloudTaskInfoDetail(String id, Integer status) {

@ -4,6 +4,7 @@ import cn.hutool.core.util.RandomUtil;
import net.educoder.ecsonar.dao.*; import net.educoder.ecsonar.dao.*;
import net.educoder.ecsonar.exception.BusinessException; import net.educoder.ecsonar.exception.BusinessException;
import net.educoder.ecsonar.model.*; import net.educoder.ecsonar.model.*;
import net.educoder.ecsonar.model.api.Quality;
import net.educoder.ecsonar.model.api.QualityInspect; import net.educoder.ecsonar.model.api.QualityInspect;
import net.educoder.ecsonar.model.api.QualityInspectIsCompleted; import net.educoder.ecsonar.model.api.QualityInspectIsCompleted;
import net.educoder.ecsonar.model.api.QualityInspectResultData; import net.educoder.ecsonar.model.api.QualityInspectResultData;
@ -11,6 +12,7 @@ import net.educoder.ecsonar.model.dto.*;
import net.educoder.ecsonar.model.vo.*; import net.educoder.ecsonar.model.vo.*;
import net.educoder.ecsonar.task.GraduationProjectQualityInspectRunnable; import net.educoder.ecsonar.task.GraduationProjectQualityInspectRunnable;
import net.educoder.ecsonar.utils.IdUtils; import net.educoder.ecsonar.utils.IdUtils;
import net.educoder.ecsonar.utils.SystemUtil;
import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -19,6 +21,8 @@ import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
@ -33,10 +37,10 @@ public class GraduationProjectQualityInspectService {
private static final Logger LOGGER = LoggerFactory.getLogger(GraduationProjectQualityInspectService.class); private static final Logger LOGGER = LoggerFactory.getLogger(GraduationProjectQualityInspectService.class);
@Autowired @Autowired
private GraduationProjectTaskInfoDao taskInfoDao; private GraduationProjectTaskInfoDao graduationProjectTaskInfoDao;
@Autowired @Autowired
private GraduationProjectTaskInfoDetailDao taskInfoDetailDao; private GraduationProjectTaskInfoDetailDao graduationProjectTaskInfoDetailDao;
@Autowired @Autowired
private DbOperateService dbOperateService; private DbOperateService dbOperateService;
@ -77,7 +81,7 @@ public class GraduationProjectQualityInspectService {
taskInfo.setId(IdUtils.nextStrId()); taskInfo.setId(IdUtils.nextStrId());
taskInfo.setPeopleNumber(qualityInspectVOList.size()); taskInfo.setPeopleNumber(qualityInspectVOList.size());
taskInfoDao.insertTaskInfo(taskInfo); graduationProjectTaskInfoDao.insertTaskInfo(taskInfo);
LOGGER.info("taskId:{}, {}个人提交了代码", taskInfo.getId(), qualityInspectVOList.size()); LOGGER.info("taskId:{}, {}个人提交了代码", taskInfo.getId(), qualityInspectVOList.size());
for (GraduationProjectQualityInspectVO qualityInspectVO : qualityInspectVOList) { for (GraduationProjectQualityInspectVO qualityInspectVO : qualityInspectVOList) {
@ -92,7 +96,7 @@ public class GraduationProjectQualityInspectService {
graduationProjectTaskInfoDetail.setGitUrl(qualityInspectVO.getGitUrl()); graduationProjectTaskInfoDetail.setGitUrl(qualityInspectVO.getGitUrl());
graduationProjectTaskInfoDetail.setLanguage(qualityInspectVO.getLanguage()); graduationProjectTaskInfoDetail.setLanguage(qualityInspectVO.getLanguage());
taskInfoDetailDao.insertTaskInfoDetail(graduationProjectTaskInfoDetail); graduationProjectTaskInfoDetailDao.insertTaskInfoDetail(graduationProjectTaskInfoDetail);
// 提交一个sonar扫描任务 // 提交一个sonar扫描任务
GraduationProjectQualityInspectRunnable runnable = new GraduationProjectQualityInspectRunnable(taskInfo.getId(), GraduationProjectQualityInspectRunnable runnable = new GraduationProjectQualityInspectRunnable(taskInfo.getId(),
@ -108,31 +112,147 @@ public class GraduationProjectQualityInspectService {
} }
public RollPage<QualityInspectResultData> qualityInspectResultQuery(Integer pageNum, Integer pageSize, String taskId) { public RollPage<QualityInspectResultData> qualityInspectResultQuery(GraduationQualityInspectResultQueryVO queryVO) {
RollPage<QualityInspectResultData> rollPage = new RollPage(); int pageSize = queryVO.getPageSize();
int pageNum = queryVO.getPageNumber();
RollPage<QualityInspectResultData> rollPage = new RollPage<>();
rollPage.setCurrentPage(pageNum); rollPage.setCurrentPage(pageNum);
rollPage.setPageSize(pageSize); rollPage.setPageSize(pageSize);
int offset = (queryVO.getPageNumber() - 1) * queryVO.getPageSize();
Integer totalCount = graduationProjectTaskInfoDetailDao.
selectGraduationProjectTaskInfoDetailPageCount(queryVO.getTaskId(), pageSize, offset);
rollPage.setRecordSum(totalCount);
if (totalCount == null || totalCount == 0) {
rollPage.setRecordList(new ArrayList<>());
} else {
List<GraduationProjectTaskInfoDetail> taskInfoDetails = graduationProjectTaskInfoDetailDao.
selectGraduationProjectTaskInfoDetailPageList(queryVO.getTaskId(), pageSize, offset);
List<QualityInspectResultData> resultDataList = new ArrayList<>(taskInfoDetails.size());
rollPage.setRecordList(resultDataList);
// 组装数据
for (GraduationProjectTaskInfoDetail taskInfoDetail : taskInfoDetails) {
QualityInspectResultData resultData = new QualityInspectResultData();
resultData.setName(taskInfoDetail.getName());
resultData.setStudentId(taskInfoDetail.getStudentId());
resultData.setUserId(taskInfoDetail.getUserId());
Metrics metrics = reportService.getMetrics(taskInfoDetail.getProjectName());
resultData.setDiscern(!metrics.getBugs().equals("-"));
resultData.setBug(new Quality(metrics.getBlock_bugs(), metrics.getMajor_bugs(), metrics.getMinor_bugs(), metrics.getCritical_bugs(), metrics.getBugs()));
resultData.setVulnerability(new Quality(metrics.getBlock_violations(), metrics.getMajor_violations(), metrics.getMinor_violations(), metrics.getCritical_violations(), metrics.getViolations()));
resultData.setCodeSmall(new Quality(metrics.getBlock_code_smells(), metrics.getMajor_code_smells(), metrics.getMinor_code_smells(), metrics.getCritical_code_smells(), metrics.getCode_smells()));
resultData.setComplexity(metrics.getComplexity());
resultData.setTotalRowNumber(metrics.getLines());
resultDataList.add(resultData);
}
int maxBugNumber = resultDataList.stream().mapToInt((QualityInspectResultData resultData) -> {
Quality bug = resultData.getBug();
return bug.getMinor() + bug.getBlocker() + bug.getMajor() + bug.getCritical();
}).max().getAsInt();
int maxVulnerabilityNumber = resultDataList.stream().mapToInt((QualityInspectResultData resultData) -> {
Quality vulnerability = resultData.getVulnerability();
return vulnerability.getMinor() + vulnerability.getBlocker() + vulnerability.getMajor() + vulnerability.getCritical();
}).max().getAsInt();
int maxCodeSmallNumber = resultDataList.stream().mapToInt((QualityInspectResultData resultData) -> {
Quality codeSmall = resultData.getCodeSmall();
return codeSmall.getMinor() + codeSmall.getBlocker() + codeSmall.getMajor() + codeSmall.getCritical();
}).max().getAsInt();
// 计算得分
for (QualityInspectResultData resultData : resultDataList) {
BigDecimal finalScore = calcQualityScore(resultData, queryVO.getBugRate(), maxBugNumber,
queryVO.getVulnerabilityRate(), maxVulnerabilityNumber,
queryVO.getCodeSmallRate(), maxCodeSmallNumber);
resultData.setQualityScore(finalScore);
}
}
return rollPage; return rollPage;
} }
public QualityInspectIsCompleted qualityInspectIsCompleted(String taskId) { public QualityInspectIsCompleted qualityInspectIsCompleted(String taskId) {
return null; GraduationProjectTaskInfo graduationProjectTaskInfo = graduationProjectTaskInfoDao.selectById(taskId);
if (graduationProjectTaskInfo == null) {
throw new BusinessException(2, "任务id不存在");
}
if (graduationProjectTaskInfo.getStatus() == 1) {
return new QualityInspectIsCompleted(taskId, graduationProjectTaskInfo.getStatus());
}
Integer taskNumber = graduationProjectTaskInfoDetailDao.selectCountByTaskId(graduationProjectTaskInfo.getId());
int completed = graduationProjectTaskInfo.getPeopleNumber().equals(taskNumber) ? 1 : 0;
// 数据库未更新状态但sonar任务已经全部执行完更新task_info状态
if (graduationProjectTaskInfo.getStatus() == 0 && completed == 1) {
graduationProjectTaskInfoDao.updateTaskInfoStatus(graduationProjectTaskInfo.getId(), 1);
// 并且删除文件 /tmp/$taskId
String command = String.format("rm -rf /tmp/%s", taskId);
SystemUtil.executeAndGetExitStatus(command);
}
return new QualityInspectIsCompleted(taskId, completed);
} }
/** /**
* * =50*(x-a)/x + 30*(y-b)/y + 20*(z-c)/c
* 10 5 3 1 * 1xa
* 2yb
* 3zc
*
* *
* @param resultData * @param resultData
* @return * @param bugRate bug
* @param maxBugNumber bug
* @param vulnerabilityRate
* @param maxVulnerabilityNumber
* @param codeSmallRate
* @param maxCodeSmallNumber
* @return score
*/ */
private BigDecimal calcQualityScore(QualityInspectResultData resultData) { private BigDecimal calcQualityScore(QualityInspectResultData resultData,
int bugRate,
int maxBugNumber,
int vulnerabilityRate,
int maxVulnerabilityNumber,
int codeSmallRate,
int maxCodeSmallNumber) {
if (resultData.getTotalRowNumber() <= 0) {
return BigDecimal.ZERO;
}
return null; Quality bug = resultData.getBug();
BigDecimal bugScore = BigDecimal.valueOf(bugRate)
.multiply(BigDecimal.valueOf(maxBugNumber - (bug.getBlocker() + bug.getCritical() + bug.getMajor() + bug.getMinor())))
.divide(BigDecimal.valueOf(maxBugNumber), 2, RoundingMode.HALF_UP);
Quality vulnerability = resultData.getVulnerability();
BigDecimal vulnerabilityScore = BigDecimal.valueOf(vulnerabilityRate)
.multiply(BigDecimal.valueOf(maxVulnerabilityNumber - (vulnerability.getBlocker() + vulnerability.getCritical() + vulnerability.getMajor() + vulnerability.getMinor())))
.divide(BigDecimal.valueOf(maxVulnerabilityNumber), 2, RoundingMode.HALF_UP);
Quality codeSmall = resultData.getCodeSmall();
BigDecimal codeSmallScore = BigDecimal.valueOf(codeSmallRate)
.multiply(BigDecimal.valueOf(maxCodeSmallNumber - (codeSmall.getBlocker() + codeSmall.getCritical() + codeSmall.getMajor() + codeSmall.getMinor())))
.divide(BigDecimal.valueOf(maxCodeSmallNumber), 2, RoundingMode.HALF_UP);
BigDecimal score = bugScore.add(vulnerabilityScore).add(codeSmallScore);
return score;
} }

@ -1,10 +1,13 @@
package net.educoder.ecsonar.task; package net.educoder.ecsonar.task;
import com.alibaba.fastjson.JSONObject;
import net.educoder.ecsonar.constant.Constant; import net.educoder.ecsonar.constant.Constant;
import net.educoder.ecsonar.model.GraduationProjectTaskInfoDetail; import net.educoder.ecsonar.model.GraduationProjectTaskInfoDetail;
import net.educoder.ecsonar.model.SonarScannerParam; import net.educoder.ecsonar.model.SonarScannerParam;
import net.educoder.ecsonar.services.DbOperateService; import net.educoder.ecsonar.services.DbOperateService;
import net.educoder.ecsonar.services.SonarService; import net.educoder.ecsonar.services.SonarService;
import net.educoder.ecsonar.utils.SystemUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -50,6 +53,13 @@ public class GraduationProjectQualityInspectRunnable implements Runnable {
String projectName = taskInfoDetail.getProjectName(); String projectName = taskInfoDetail.getProjectName();
String path = String.format("/tmp/%s/%s/", taskId, projectName); String path = String.format("/tmp/%s/%s/", taskId, projectName);
// 需要先git clone 到某个目录下面
SystemUtil.ExecuteResp executeResp = gitClone(path, taskInfoDetail.getGitUrl());
if (executeResp.getStatus() != 0) {
LOGGER.warn("projectName:{} git clone失败", taskInfoDetail.getProjectName());
return;
}
// 写完所有文件开始用sonar进行质量分析 // 写完所有文件开始用sonar进行质量分析
SonarScannerParam param = new SonarScannerParam(projectName, path); SonarScannerParam param = new SonarScannerParam(projectName, path);
if (Constant.C.equalsIgnoreCase(language) || Constant.CXX.equalsIgnoreCase(language)) { if (Constant.C.equalsIgnoreCase(language) || Constant.CXX.equalsIgnoreCase(language)) {
@ -89,4 +99,22 @@ public class GraduationProjectQualityInspectRunnable implements Runnable {
public void setSonarService(SonarService sonarService) { public void setSonarService(SonarService sonarService) {
this.sonarService = sonarService; this.sonarService = sonarService;
} }
/**
*
*
* @param path
* @param gitUrl
* @return
*/
private SystemUtil.ExecuteResp gitClone(String path, String gitUrl) {
String command = StringUtils.join("rm -rf ", path, " && mkdir -p ", path, " && cd ", path, " && git clone ", gitUrl);
LOGGER.info("git clonecommand:{}", command);
SystemUtil.ExecuteResp executeResp = SystemUtil.executeAndGetExitStatus(command);
LOGGER.info("git clone结果:{}", JSONObject.toJSONString(executeResp));
return executeResp;
}
} }

@ -6,9 +6,9 @@
spring.datasource.initSize=20 spring.datasource.initSize=20
#spring.datasource.master.url=jdbc:postgresql://127.0.0.1:5432/sonar7.7 #spring.datasource.master.url=jdbc:postgresql://127.0.0.1:5432/sonar7.7
spring.datasource.master.url=jdbc:postgresql://117.50.14.123:5432/sonar spring.datasource.master.url=jdbc:postgresql://121.40.224.66:45432/sonar
spring.datasource.master.username=sonar spring.datasource.master.username=postgres
spring.datasource.master.password=sonar spring.datasource.master.password=Edu_postgresql
spring.datasource.master.driverClassName=org.postgresql.Driver spring.datasource.master.driverClassName=org.postgresql.Driver
@ -43,9 +43,9 @@ zip.save.path=/tmp/
#excel.template.path=/Users/guange/work/java/ecsonar/src/main/resources/template.xlsx #excel.template.path=/Users/guange/work/java/ecsonar/src/main/resources/template.xlsx
excel.template.path=template.xlsx excel.template.path=template.xlsx
sonar.url=http://127.0.0.1:9000 #sonar.url=http://127.0.0.1:9000
#sonar.url=http://117.50.14.123:9000 sonar.url=http://121.40.224.66:49000
# token令牌 # token
sonar.token=0253a518e824a976ea2f11aec17938cb0f8c0495 sonar.token=0253a518e824a976ea2f11aec17938cb0f8c0495
extract.path=/usr/local/bin/unar extract.path=/usr/local/bin/unar

Loading…
Cancel
Save