增加构建通知
This commit is contained in:
parent
360b794bff
commit
6f218dca6a
@ -4,6 +4,7 @@ import com.qqchen.deploy.backend.deploy.entity.JenkinsBuildNotification;
|
||||
import com.qqchen.deploy.backend.framework.repository.IBaseRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
@ -26,4 +27,11 @@ public interface IJenkinsBuildNotificationRepository
|
||||
*/
|
||||
Optional<JenkinsBuildNotification> findByBuildIdAndTeamIdAndEnvironmentId(
|
||||
Long buildId, Long teamId, Long environmentId);
|
||||
|
||||
/**
|
||||
* 查询未完成结束通知的记录
|
||||
*
|
||||
* @return 未完成结束通知的记录列表
|
||||
*/
|
||||
List<JenkinsBuildNotification> findByBuildEndNoticeFalseAndDeletedFalse();
|
||||
}
|
||||
|
||||
@ -325,7 +325,8 @@ public class JenkinsBuildServiceImpl extends BaseServiceImpl<JenkinsBuild, Jenki
|
||||
|
||||
private void updateBuildFromResponse(JenkinsBuild jenkinsBuild, JenkinsBuildResponse response) {
|
||||
jenkinsBuild.setBuildUrl(response.getUrl());
|
||||
jenkinsBuild.setBuildStatus(response.getResult());
|
||||
// Jenkins API 返回的 result 在构建进行中时为 null,设置默认值 "BUILDING"
|
||||
jenkinsBuild.setBuildStatus(response.getResult() != null ? response.getResult() : "BUILDING");
|
||||
jenkinsBuild.setDuration(response.getDuration());
|
||||
|
||||
if (response.getTimestamp() != null) {
|
||||
@ -439,19 +440,38 @@ public class JenkinsBuildServiceImpl extends BaseServiceImpl<JenkinsBuild, Jenki
|
||||
return;
|
||||
}
|
||||
|
||||
// 1. 查询最近开始的构建(6分钟内,比同步间隔5分钟多1分钟)
|
||||
LocalDateTime since = LocalDateTime.now().minusMinutes(6);
|
||||
// 1. 查询最近6分钟内开始的新构建(用于发送开始通知)
|
||||
LocalDateTime recentSince = LocalDateTime.now().minusMinutes(6);
|
||||
List<JenkinsBuild> recentBuilds = jenkinsBuildRepository
|
||||
.findByExternalSystemIdAndStarttimeAfter(externalSystemId, since);
|
||||
.findByExternalSystemIdAndStarttimeAfter(externalSystemId, recentSince);
|
||||
|
||||
if (recentBuilds.isEmpty()) {
|
||||
log.info("没有新的构建记录");
|
||||
// 2. 查询未完成通知的构建ID(用于发送结束通知和兜底处理)
|
||||
List<JenkinsBuildNotification> pendingNotifications = jenkinsBuildNotificationRepository
|
||||
.findByBuildEndNoticeFalseAndDeletedFalse();
|
||||
Set<Long> pendingBuildIds = pendingNotifications.stream()
|
||||
.map(JenkinsBuildNotification::getBuildId)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
// 3. 查询未完成通知对应的构建记录
|
||||
List<JenkinsBuild> pendingBuilds = pendingBuildIds.isEmpty()
|
||||
? Collections.emptyList()
|
||||
: jenkinsBuildRepository.findAllById(pendingBuildIds).stream()
|
||||
.filter(b -> b.getExternalSystemId().equals(externalSystemId))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 4. 合并需要处理的构建(去重)
|
||||
Map<Long, JenkinsBuild> buildMap = new HashMap<>();
|
||||
recentBuilds.forEach(b -> buildMap.put(b.getId(), b));
|
||||
pendingBuilds.forEach(b -> buildMap.put(b.getId(), b));
|
||||
List<JenkinsBuild> buildsToProcess = new ArrayList<>(buildMap.values());
|
||||
|
||||
if (buildsToProcess.isEmpty()) {
|
||||
log.info("没有需要处理的构建记录");
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 反查团队绑定关系(只查询构建类型为JENKINS的应用)
|
||||
List<TeamApplication> teamApps = teamApplicationRepository
|
||||
.findByDeploySystemIdAndBuildType(externalSystemId, BuildTypeEnum.JENKINS);
|
||||
List<TeamApplication> teamApps = teamApplicationRepository.findByDeploySystemIdAndBuildType(externalSystemId, BuildTypeEnum.JENKINS);
|
||||
|
||||
if (teamApps.isEmpty()) {
|
||||
log.info("没有团队绑定该Jenkins系统: externalSystemId={}", externalSystemId);
|
||||
@ -498,7 +518,7 @@ public class JenkinsBuildServiceImpl extends BaseServiceImpl<JenkinsBuild, Jenki
|
||||
.collect(Collectors.toMap(NotificationChannel::getId, c -> c));
|
||||
|
||||
// 7. 批量查询 Job
|
||||
Set<Long> jobIds = recentBuilds.stream()
|
||||
Set<Long> jobIds = buildsToProcess.stream()
|
||||
.map(JenkinsBuild::getJobId)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
@ -507,7 +527,7 @@ public class JenkinsBuildServiceImpl extends BaseServiceImpl<JenkinsBuild, Jenki
|
||||
.collect(Collectors.toMap(JenkinsJob::getId, j -> j));
|
||||
|
||||
// 8. 按 job_name 分组构建记录
|
||||
Map<String, List<JenkinsBuild>> buildsByJobName = recentBuilds.stream()
|
||||
Map<String, List<JenkinsBuild>> buildsByJobName = buildsToProcess.stream()
|
||||
.collect(Collectors.groupingBy(
|
||||
build -> jobMap.get(build.getJobId()).getJobName()
|
||||
));
|
||||
@ -577,44 +597,55 @@ public class JenkinsBuildServiceImpl extends BaseServiceImpl<JenkinsBuild, Jenki
|
||||
)
|
||||
.orElse(null);
|
||||
|
||||
// 2. 新构建
|
||||
// 2. 新构建(只处理6分钟内的新构建)
|
||||
if (record == null) {
|
||||
long minutesAgo = java.time.temporal.ChronoUnit.MINUTES.between(
|
||||
build.getStarttime(),
|
||||
LocalDateTime.now()
|
||||
);
|
||||
|
||||
// 超过6分钟的旧构建,不创建通知记录,直接跳过
|
||||
if (minutesAgo > 6) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 6分钟内的新构建,发送"构建中"通知
|
||||
record = new JenkinsBuildNotification();
|
||||
record.setBuildId(build.getId());
|
||||
record.setTeamId(config.getTeamId());
|
||||
record.setEnvironmentId(config.getEnvironmentId());
|
||||
|
||||
if (minutesAgo > 20) {
|
||||
// 超时,直接标记完成(不发通知)
|
||||
record.setBuildStartNotice(true);
|
||||
record.setBuildEndNotice(true);
|
||||
jenkinsBuildNotificationRepository.save(record);
|
||||
return;
|
||||
} else {
|
||||
// 未超时,发送"构建中"通知
|
||||
sendNotification(config, channel, job, build, "BUILDING", externalSystem, application, environment);
|
||||
record.setBuildStartNotice(true);
|
||||
jenkinsBuildNotificationRepository.save(record);
|
||||
return;
|
||||
}
|
||||
sendNotification(config, channel, job, build, "BUILDING", externalSystem, application, environment);
|
||||
record.setBuildStartNotice(true);
|
||||
jenkinsBuildNotificationRepository.save(record);
|
||||
return;
|
||||
}
|
||||
|
||||
// 3. 已有记录,检查结束通知
|
||||
if (!record.getBuildEndNotice() && isBuildFinished(build)) {
|
||||
String status = build.getBuildStatus();
|
||||
|
||||
// 通知成功、失败、取消
|
||||
if ("SUCCESS".equals(status) || "FAILURE".equals(status) || "ABORTED".equals(status)) {
|
||||
sendNotification(config, channel, job, build, status, externalSystem, application, environment);
|
||||
if (!record.getBuildEndNotice()) {
|
||||
if (isBuildFinished(build)) {
|
||||
// 构建已完成,发送结束通知
|
||||
String status = build.getBuildStatus();
|
||||
|
||||
// 通知成功、失败、取消
|
||||
if ("SUCCESS".equals(status) || "FAILURE".equals(status) || "ABORTED".equals(status)) {
|
||||
sendNotification(config, channel, job, build, status, externalSystem, application, environment);
|
||||
}
|
||||
|
||||
record.setBuildEndNotice(true);
|
||||
jenkinsBuildNotificationRepository.save(record);
|
||||
} else {
|
||||
// 兜底逻辑:构建开始超过2小时仍未完成,强制标记为已完成(不发通知)
|
||||
long hoursAgo = java.time.temporal.ChronoUnit.HOURS.between(
|
||||
build.getStarttime(),
|
||||
LocalDateTime.now()
|
||||
);
|
||||
if (hoursAgo >= 2) {
|
||||
log.warn("构建超时未完成,强制标记结束通知: buildId={}, teamId={}, envId={}, startTime={}",
|
||||
build.getId(), config.getTeamId(), config.getEnvironmentId(), build.getStarttime());
|
||||
record.setBuildEndNotice(true);
|
||||
jenkinsBuildNotificationRepository.save(record);
|
||||
}
|
||||
}
|
||||
|
||||
record.setBuildEndNotice(true);
|
||||
jenkinsBuildNotificationRepository.save(record);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user