增加构建通知
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 com.qqchen.deploy.backend.framework.repository.IBaseRepository;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -26,4 +27,11 @@ public interface IJenkinsBuildNotificationRepository
|
|||||||
*/
|
*/
|
||||||
Optional<JenkinsBuildNotification> findByBuildIdAndTeamIdAndEnvironmentId(
|
Optional<JenkinsBuildNotification> findByBuildIdAndTeamIdAndEnvironmentId(
|
||||||
Long buildId, Long teamId, Long environmentId);
|
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) {
|
private void updateBuildFromResponse(JenkinsBuild jenkinsBuild, JenkinsBuildResponse response) {
|
||||||
jenkinsBuild.setBuildUrl(response.getUrl());
|
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());
|
jenkinsBuild.setDuration(response.getDuration());
|
||||||
|
|
||||||
if (response.getTimestamp() != null) {
|
if (response.getTimestamp() != null) {
|
||||||
@ -439,19 +440,38 @@ public class JenkinsBuildServiceImpl extends BaseServiceImpl<JenkinsBuild, Jenki
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1. 查询最近开始的构建(6分钟内,比同步间隔5分钟多1分钟)
|
// 1. 查询最近6分钟内开始的新构建(用于发送开始通知)
|
||||||
LocalDateTime since = LocalDateTime.now().minusMinutes(6);
|
LocalDateTime recentSince = LocalDateTime.now().minusMinutes(6);
|
||||||
List<JenkinsBuild> recentBuilds = jenkinsBuildRepository
|
List<JenkinsBuild> recentBuilds = jenkinsBuildRepository
|
||||||
.findByExternalSystemIdAndStarttimeAfter(externalSystemId, since);
|
.findByExternalSystemIdAndStarttimeAfter(externalSystemId, recentSince);
|
||||||
|
|
||||||
if (recentBuilds.isEmpty()) {
|
// 2. 查询未完成通知的构建ID(用于发送结束通知和兜底处理)
|
||||||
log.info("没有新的构建记录");
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 反查团队绑定关系(只查询构建类型为JENKINS的应用)
|
// 2. 反查团队绑定关系(只查询构建类型为JENKINS的应用)
|
||||||
List<TeamApplication> teamApps = teamApplicationRepository
|
List<TeamApplication> teamApps = teamApplicationRepository.findByDeploySystemIdAndBuildType(externalSystemId, BuildTypeEnum.JENKINS);
|
||||||
.findByDeploySystemIdAndBuildType(externalSystemId, BuildTypeEnum.JENKINS);
|
|
||||||
|
|
||||||
if (teamApps.isEmpty()) {
|
if (teamApps.isEmpty()) {
|
||||||
log.info("没有团队绑定该Jenkins系统: externalSystemId={}", externalSystemId);
|
log.info("没有团队绑定该Jenkins系统: externalSystemId={}", externalSystemId);
|
||||||
@ -498,7 +518,7 @@ public class JenkinsBuildServiceImpl extends BaseServiceImpl<JenkinsBuild, Jenki
|
|||||||
.collect(Collectors.toMap(NotificationChannel::getId, c -> c));
|
.collect(Collectors.toMap(NotificationChannel::getId, c -> c));
|
||||||
|
|
||||||
// 7. 批量查询 Job
|
// 7. 批量查询 Job
|
||||||
Set<Long> jobIds = recentBuilds.stream()
|
Set<Long> jobIds = buildsToProcess.stream()
|
||||||
.map(JenkinsBuild::getJobId)
|
.map(JenkinsBuild::getJobId)
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
@ -507,7 +527,7 @@ public class JenkinsBuildServiceImpl extends BaseServiceImpl<JenkinsBuild, Jenki
|
|||||||
.collect(Collectors.toMap(JenkinsJob::getId, j -> j));
|
.collect(Collectors.toMap(JenkinsJob::getId, j -> j));
|
||||||
|
|
||||||
// 8. 按 job_name 分组构建记录
|
// 8. 按 job_name 分组构建记录
|
||||||
Map<String, List<JenkinsBuild>> buildsByJobName = recentBuilds.stream()
|
Map<String, List<JenkinsBuild>> buildsByJobName = buildsToProcess.stream()
|
||||||
.collect(Collectors.groupingBy(
|
.collect(Collectors.groupingBy(
|
||||||
build -> jobMap.get(build.getJobId()).getJobName()
|
build -> jobMap.get(build.getJobId()).getJobName()
|
||||||
));
|
));
|
||||||
@ -577,44 +597,55 @@ public class JenkinsBuildServiceImpl extends BaseServiceImpl<JenkinsBuild, Jenki
|
|||||||
)
|
)
|
||||||
.orElse(null);
|
.orElse(null);
|
||||||
|
|
||||||
// 2. 新构建
|
// 2. 新构建(只处理6分钟内的新构建)
|
||||||
if (record == null) {
|
if (record == null) {
|
||||||
long minutesAgo = java.time.temporal.ChronoUnit.MINUTES.between(
|
long minutesAgo = java.time.temporal.ChronoUnit.MINUTES.between(
|
||||||
build.getStarttime(),
|
build.getStarttime(),
|
||||||
LocalDateTime.now()
|
LocalDateTime.now()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// 超过6分钟的旧构建,不创建通知记录,直接跳过
|
||||||
|
if (minutesAgo > 6) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6分钟内的新构建,发送"构建中"通知
|
||||||
record = new JenkinsBuildNotification();
|
record = new JenkinsBuildNotification();
|
||||||
record.setBuildId(build.getId());
|
record.setBuildId(build.getId());
|
||||||
record.setTeamId(config.getTeamId());
|
record.setTeamId(config.getTeamId());
|
||||||
record.setEnvironmentId(config.getEnvironmentId());
|
record.setEnvironmentId(config.getEnvironmentId());
|
||||||
|
sendNotification(config, channel, job, build, "BUILDING", externalSystem, application, environment);
|
||||||
if (minutesAgo > 20) {
|
record.setBuildStartNotice(true);
|
||||||
// 超时,直接标记完成(不发通知)
|
jenkinsBuildNotificationRepository.save(record);
|
||||||
record.setBuildStartNotice(true);
|
return;
|
||||||
record.setBuildEndNotice(true);
|
|
||||||
jenkinsBuildNotificationRepository.save(record);
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
// 未超时,发送"构建中"通知
|
|
||||||
sendNotification(config, channel, job, build, "BUILDING", externalSystem, application, environment);
|
|
||||||
record.setBuildStartNotice(true);
|
|
||||||
jenkinsBuildNotificationRepository.save(record);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. 已有记录,检查结束通知
|
// 3. 已有记录,检查结束通知
|
||||||
if (!record.getBuildEndNotice() && isBuildFinished(build)) {
|
if (!record.getBuildEndNotice()) {
|
||||||
String status = build.getBuildStatus();
|
if (isBuildFinished(build)) {
|
||||||
|
// 构建已完成,发送结束通知
|
||||||
|
String status = build.getBuildStatus();
|
||||||
|
|
||||||
// 通知成功、失败、取消
|
// 通知成功、失败、取消
|
||||||
if ("SUCCESS".equals(status) || "FAILURE".equals(status) || "ABORTED".equals(status)) {
|
if ("SUCCESS".equals(status) || "FAILURE".equals(status) || "ABORTED".equals(status)) {
|
||||||
sendNotification(config, channel, job, build, status, externalSystem, application, environment);
|
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) {
|
} catch (Exception e) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user