增加构建通知
This commit is contained in:
parent
f6569fe020
commit
3fc6ddc8fc
@ -67,12 +67,12 @@ public interface IJenkinsBuildRepository extends IBaseRepository<JenkinsBuild, L
|
||||
List<Object[]> countByJobIds(@Param("jobIds") Collection<Long> jobIds);
|
||||
|
||||
/**
|
||||
* 查询指定时间之后创建的构建记录(用于构建通知)
|
||||
* 查询指定时间之后开始的构建记录(用于构建通知)
|
||||
*
|
||||
* @param externalSystemId 外部系统ID
|
||||
* @param createTime 创建时间
|
||||
* @param starttime 构建开始时间
|
||||
* @return 构建记录列表
|
||||
*/
|
||||
List<JenkinsBuild> findByExternalSystemIdAndCreateTimeAfter(
|
||||
Long externalSystemId, LocalDateTime createTime);
|
||||
List<JenkinsBuild> findByExternalSystemIdAndStarttimeAfter(
|
||||
Long externalSystemId, LocalDateTime starttime);
|
||||
}
|
||||
@ -74,6 +74,12 @@ public class JenkinsBuildServiceImpl extends BaseServiceImpl<JenkinsBuild, Jenki
|
||||
@Resource
|
||||
private ITeamApplicationRepository teamApplicationRepository;
|
||||
|
||||
@Resource
|
||||
private IApplicationRepository applicationRepository;
|
||||
|
||||
@Resource
|
||||
private IEnvironmentRepository environmentRepository;
|
||||
|
||||
@Resource
|
||||
private ITeamEnvironmentNotificationConfigRepository teamEnvironmentNotificationConfigRepository;
|
||||
|
||||
@ -330,7 +336,12 @@ public class JenkinsBuildServiceImpl extends BaseServiceImpl<JenkinsBuild, Jenki
|
||||
}
|
||||
|
||||
try {
|
||||
String actionsJson = objectMapper.writeValueAsString(response.getActions());
|
||||
// 保存 actions 和 changeSets 到 JSON
|
||||
Map<String, Object> buildData = new HashMap<>();
|
||||
buildData.put("actions", response.getActions());
|
||||
buildData.put("changeSets", response.getChangeSets());
|
||||
buildData.put("gitCommitId", response.getGitCommitId());
|
||||
String actionsJson = objectMapper.writeValueAsString(buildData);
|
||||
jenkinsBuild.setActions(actionsJson);
|
||||
} catch (JsonProcessingException e) {
|
||||
log.error("Failed to serialize build actions", e);
|
||||
@ -427,10 +438,10 @@ public class JenkinsBuildServiceImpl extends BaseServiceImpl<JenkinsBuild, Jenki
|
||||
return;
|
||||
}
|
||||
|
||||
// 1. 查询最近同步的构建(6分钟内,比同步间隔5分钟多1分钟)
|
||||
// 1. 查询最近开始的构建(6分钟内,比同步间隔5分钟多1分钟)
|
||||
LocalDateTime since = LocalDateTime.now().minusMinutes(6);
|
||||
List<JenkinsBuild> recentBuilds = jenkinsBuildRepository
|
||||
.findByExternalSystemIdAndCreateTimeAfter(externalSystemId, since);
|
||||
.findByExternalSystemIdAndStarttimeAfter(externalSystemId, since);
|
||||
|
||||
if (recentBuilds.isEmpty()) {
|
||||
log.info("没有新的构建记录");
|
||||
@ -500,7 +511,18 @@ public class JenkinsBuildServiceImpl extends BaseServiceImpl<JenkinsBuild, Jenki
|
||||
build -> jobMap.get(build.getJobId()).getJobName()
|
||||
));
|
||||
|
||||
// 9. 处理每个 Job 的构建通知
|
||||
// 9. 批量查询应用信息
|
||||
Set<Long> applicationIds = teamApps.stream()
|
||||
.map(TeamApplication::getApplicationId)
|
||||
.collect(Collectors.toSet());
|
||||
Map<Long, Application> applicationMap = applicationRepository.findAllById(applicationIds).stream()
|
||||
.collect(Collectors.toMap(Application::getId, a -> a));
|
||||
|
||||
// 10. 批量查询环境信息
|
||||
Map<Long, Environment> environmentMap = environmentRepository.findAllById(envIds).stream()
|
||||
.collect(Collectors.toMap(Environment::getId, e -> e));
|
||||
|
||||
// 11. 处理每个 Job 的构建通知
|
||||
buildsByJobName.forEach((jobName, builds) -> {
|
||||
List<TeamApplication> relatedTeamApps = teamAppsByJob.get(jobName);
|
||||
if (relatedTeamApps == null || relatedTeamApps.isEmpty()) {
|
||||
@ -517,10 +539,12 @@ public class JenkinsBuildServiceImpl extends BaseServiceImpl<JenkinsBuild, Jenki
|
||||
if (channel == null) continue;
|
||||
|
||||
JenkinsJob job = jobMap.get(builds.get(0).getJobId());
|
||||
Application application = applicationMap.get(teamApp.getApplicationId());
|
||||
Environment environment = environmentMap.get(teamApp.getEnvironmentId());
|
||||
|
||||
// 处理该团队环境的所有构建通知
|
||||
for (JenkinsBuild build : builds) {
|
||||
processBuildNotification(config, channel, job, build, externalSystem);
|
||||
processBuildNotification(config, channel, job, build, externalSystem, application, environment);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -531,14 +555,16 @@ public class JenkinsBuildServiceImpl extends BaseServiceImpl<JenkinsBuild, Jenki
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理单个构建的通知(照搬longi逻辑)
|
||||
* 处理单个构建的通知
|
||||
*/
|
||||
private void processBuildNotification(
|
||||
TeamEnvironmentNotificationConfig config,
|
||||
NotificationChannel channel,
|
||||
JenkinsJob job,
|
||||
JenkinsBuild build,
|
||||
ExternalSystem externalSystem) {
|
||||
ExternalSystem externalSystem,
|
||||
Application application,
|
||||
Environment environment) {
|
||||
|
||||
try {
|
||||
// 1. 查询通知记录
|
||||
@ -583,7 +609,7 @@ public class JenkinsBuildServiceImpl extends BaseServiceImpl<JenkinsBuild, Jenki
|
||||
|
||||
// 只通知成功和失败
|
||||
if ("SUCCESS".equals(status) || "FAILURE".equals(status)) {
|
||||
sendNotification(config, channel, job, build, status, externalSystem);
|
||||
sendNotification(config, channel, job, build, status, externalSystem, application, environment);
|
||||
}
|
||||
|
||||
record.setBuildEndNotice(true);
|
||||
@ -615,7 +641,9 @@ public class JenkinsBuildServiceImpl extends BaseServiceImpl<JenkinsBuild, Jenki
|
||||
JenkinsJob job,
|
||||
JenkinsBuild build,
|
||||
String status,
|
||||
ExternalSystem externalSystem) {
|
||||
ExternalSystem externalSystem,
|
||||
Application application,
|
||||
Environment environment) {
|
||||
|
||||
try {
|
||||
// 1. 检查是否配置了构建通知模板
|
||||
@ -636,37 +664,70 @@ public class JenkinsBuildServiceImpl extends BaseServiceImpl<JenkinsBuild, Jenki
|
||||
|
||||
// 3. 构建模板参数
|
||||
Map<String, Object> templateParams = new HashMap<>();
|
||||
|
||||
// 应用信息
|
||||
if (application != null) {
|
||||
templateParams.put("applicationId", application.getId());
|
||||
templateParams.put("applicationCode", application.getAppCode());
|
||||
templateParams.put("applicationName", application.getAppName());
|
||||
}
|
||||
|
||||
// 环境信息
|
||||
if (environment != null) {
|
||||
templateParams.put("environmentId", environment.getId());
|
||||
templateParams.put("environmentCode", environment.getEnvCode());
|
||||
templateParams.put("environmentName", environment.getEnvName());
|
||||
}
|
||||
|
||||
// Jenkins 构建信息
|
||||
templateParams.put("jobName", job.getJobName());
|
||||
templateParams.put("buildNumber", build.getBuildNumber());
|
||||
templateParams.put("buildUrl", build.getBuildUrl());
|
||||
templateParams.put("status", status);
|
||||
templateParams.put("startTime", build.getStarttime());
|
||||
templateParams.put("buildStatus", status);
|
||||
|
||||
// 状态显示
|
||||
String statusDisplay = switch (status) {
|
||||
case "SUCCESS" -> "✅ 成功";
|
||||
case "FAILURE" -> "❌ 失败";
|
||||
case "BUILDING" -> "🔄 构建中";
|
||||
default -> status;
|
||||
};
|
||||
templateParams.put("statusDisplay", statusDisplay);
|
||||
|
||||
// 耗时
|
||||
if (build.getDuration() != null) {
|
||||
long seconds = build.getDuration() / 1000;
|
||||
long minutes = seconds / 60;
|
||||
long secs = seconds % 60;
|
||||
templateParams.put("duration", String.format("%d分%d秒", minutes, secs));
|
||||
templateParams.put("durationMs", build.getDuration());
|
||||
// 时间格式化
|
||||
java.time.format.DateTimeFormatter formatter = java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||
if (build.getStarttime() != null) {
|
||||
templateParams.put("buildStartTime", build.getStarttime().format(formatter));
|
||||
}
|
||||
|
||||
// 4. 构建 SendNotificationRequest
|
||||
// 构建结束时间(如果有)
|
||||
if (build.getStarttime() != null && build.getDuration() != null) {
|
||||
LocalDateTime endTime = build.getStarttime().plusNanos(build.getDuration() * 1_000_000);
|
||||
templateParams.put("buildEndTime", endTime.format(formatter));
|
||||
}
|
||||
|
||||
// 耗时格式化
|
||||
if (build.getDuration() != null) {
|
||||
long totalSeconds = build.getDuration() / 1000;
|
||||
long minutes = totalSeconds / 60;
|
||||
long seconds = totalSeconds % 60;
|
||||
templateParams.put("buildDurationFormatted", String.format("%d分%d秒", minutes, seconds));
|
||||
templateParams.put("buildDurationMs", build.getDuration());
|
||||
}
|
||||
|
||||
// 从 actions JSON 中解析 commit 信息
|
||||
parseCommitInfoFromActions(build.getActions(), templateParams);
|
||||
|
||||
// 4. 校验模板和渠道类型是否匹配
|
||||
if (!template.getChannelType().equals(channel.getChannelType())) {
|
||||
log.warn("模板渠道类型({})与通知渠道类型({})不匹配,跳过通知: templateId={}, channelId={}",
|
||||
template.getChannelType(), channel.getChannelType(),
|
||||
config.getBuildNotificationTemplateId(), channel.getId());
|
||||
return;
|
||||
}
|
||||
|
||||
// 5. 构建 SendNotificationRequest
|
||||
SendNotificationRequest request = new SendNotificationRequest();
|
||||
request.setNotificationTemplateId(config.getBuildNotificationTemplateId());
|
||||
request.setTemplateParams(templateParams);
|
||||
request.setSendRequest(createSendRequestByChannel(channel, template));
|
||||
|
||||
// 5. 发送通知
|
||||
log.debug("准备发送构建通知: job={}, build={}, templateId={}, channelId={}, channelType={}",
|
||||
job.getJobName(), build.getBuildNumber(), config.getBuildNotificationTemplateId(),
|
||||
channel.getId(), channel.getChannelType());
|
||||
|
||||
// 6. 发送通知
|
||||
notificationService.send(request);
|
||||
|
||||
log.info("已发送构建通知: job={}, build={}, status={}, templateId={}",
|
||||
@ -720,6 +781,53 @@ public class JenkinsBuildServiceImpl extends BaseServiceImpl<JenkinsBuild, Jenki
|
||||
}
|
||||
return WeworkMessageTypeEnum.TEXT;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 actions JSON 中解析 commit 信息
|
||||
*/
|
||||
private void parseCommitInfoFromActions(String actionsJson, Map<String, Object> templateParams) {
|
||||
if (actionsJson == null || actionsJson.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
JsonNode root = objectMapper.readTree(actionsJson);
|
||||
|
||||
// 解析 gitCommitId
|
||||
if (root.has("gitCommitId") && !root.get("gitCommitId").isNull()) {
|
||||
templateParams.put("gitCommitId", root.get("gitCommitId").asText());
|
||||
}
|
||||
|
||||
// 解析 changeSets 中的 commit 信息
|
||||
JsonNode changeSets = root.get("changeSets");
|
||||
if (changeSets != null && changeSets.isArray() && changeSets.size() > 0) {
|
||||
StringBuilder commitMessages = new StringBuilder();
|
||||
for (JsonNode changeSet : changeSets) {
|
||||
JsonNode items = changeSet.get("items");
|
||||
if (items != null && items.isArray()) {
|
||||
for (JsonNode item : items) {
|
||||
String message = item.has("message") ? item.get("message").asText() : "";
|
||||
String author = item.has("author") ? item.get("author").asText() : "";
|
||||
String commitId = item.has("commitId") ? item.get("commitId").asText() : "";
|
||||
|
||||
if (!message.isEmpty()) {
|
||||
if (commitMessages.length() > 0) {
|
||||
commitMessages.append("\n");
|
||||
}
|
||||
// 截取 commitId 前8位
|
||||
String shortCommitId = commitId.length() > 8 ? commitId.substring(0, 8) : commitId;
|
||||
commitMessages.append(String.format("[%s] %s - %s", shortCommitId, message.trim(), author));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (commitMessages.length() > 0) {
|
||||
templateParams.put("commitMessage", commitMessages.toString());
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("解析 commit 信息失败: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送构建失败日志文件到企业微信
|
||||
|
||||
Loading…
Reference in New Issue
Block a user