增加构建通知
This commit is contained in:
parent
44ea1353b2
commit
33f648d79f
@ -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.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@ -34,4 +35,12 @@ public interface IJenkinsBuildNotificationRepository
|
|||||||
* @return 未完成结束通知的记录列表
|
* @return 未完成结束通知的记录列表
|
||||||
*/
|
*/
|
||||||
List<JenkinsBuildNotification> findByBuildEndNoticeFalseAndDeletedFalse();
|
List<JenkinsBuildNotification> findByBuildEndNoticeFalseAndDeletedFalse();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据构建ID批量查询通知记录
|
||||||
|
*
|
||||||
|
* @param buildIds 构建ID集合
|
||||||
|
* @return 通知记录列表
|
||||||
|
*/
|
||||||
|
List<JenkinsBuildNotification> findByBuildIdInAndDeletedFalse(Collection<Long> buildIds);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -436,81 +436,56 @@ public class JenkinsBuildServiceImpl extends BaseServiceImpl<JenkinsBuild, Jenki
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查并发送构建通知(照搬longi-deployment逻辑)
|
* 检查并发送构建通知(参考longi-deployment逻辑重构)
|
||||||
|
*
|
||||||
|
* <p>核心流程:
|
||||||
|
* <ol>
|
||||||
|
* <li>获取所有绑定了该Jenkins系统的TeamApplication</li>
|
||||||
|
* <li>按 deployJob 分组,遍历每个 Job</li>
|
||||||
|
* <li>获取该 Job 的最新构建记录</li>
|
||||||
|
* <li>查通知记录表,判断是否需要发送通知</li>
|
||||||
|
* </ol>
|
||||||
*/
|
*/
|
||||||
private void checkBuildNotifications(Long externalSystemId) {
|
private void checkBuildNotifications(Long externalSystemId) {
|
||||||
log.info("开始检查构建通知: externalSystemId={}", externalSystemId);
|
log.info("开始检查构建通知: externalSystemId={}", externalSystemId);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 0. 获取外部系统信息(用于后续获取日志)
|
// 1. 获取外部系统信息
|
||||||
ExternalSystem externalSystem = externalSystemRepository.findById(externalSystemId)
|
ExternalSystem externalSystem = externalSystemRepository.findById(externalSystemId).orElse(null);
|
||||||
.orElse(null);
|
|
||||||
if (externalSystem == null) {
|
if (externalSystem == null) {
|
||||||
log.warn("外部系统不存在: externalSystemId={}", externalSystemId);
|
log.warn("外部系统不存在: externalSystemId={}", externalSystemId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1. 查询最近6分钟内开始的新构建(用于发送开始通知)
|
// 2. 查询绑定该Jenkins系统的TeamApplication(构建类型为JENKINS)
|
||||||
LocalDateTime recentSince = LocalDateTime.now().minusMinutes(6);
|
List<TeamApplication> teamApps = teamApplicationRepository
|
||||||
List<JenkinsBuild> recentBuilds = jenkinsBuildRepository
|
.findByDeploySystemIdAndBuildType(externalSystemId, BuildTypeEnum.JENKINS);
|
||||||
.findByExternalSystemIdAndStarttimeAfter(externalSystemId, recentSince);
|
|
||||||
|
|
||||||
// 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))
|
|
||||||
.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);
|
|
||||||
|
|
||||||
if (teamApps.isEmpty()) {
|
if (teamApps.isEmpty()) {
|
||||||
log.info("没有团队绑定该Jenkins系统: externalSystemId={}", externalSystemId);
|
log.info("没有团队绑定该Jenkins系统: externalSystemId={}", externalSystemId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. 按 deploy_job 分组 TeamApplication
|
// 3. 按 deployJob 分组(过滤掉空的deployJob)
|
||||||
Map<String, List<TeamApplication>> teamAppsByJob = teamApps.stream()
|
Map<String, List<TeamApplication>> teamAppsByJob = teamApps.stream()
|
||||||
|
.filter(ta -> ta.getDeployJob() != null && !ta.getDeployJob().isEmpty())
|
||||||
.collect(Collectors.groupingBy(TeamApplication::getDeployJob));
|
.collect(Collectors.groupingBy(TeamApplication::getDeployJob));
|
||||||
|
if (teamAppsByJob.isEmpty()) {
|
||||||
|
log.info("没有配置deployJob的团队应用");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 4. 查询启用了构建通知的团队环境配置
|
// 4. 查询启用了构建通知的团队环境配置
|
||||||
Set<Long> teamIds = teamApps.stream()
|
Set<Long> teamIds = teamApps.stream().map(TeamApplication::getTeamId).collect(Collectors.toSet());
|
||||||
.map(TeamApplication::getTeamId)
|
Set<Long> envIds = teamApps.stream().map(TeamApplication::getEnvironmentId).collect(Collectors.toSet());
|
||||||
.collect(Collectors.toSet());
|
|
||||||
|
|
||||||
Set<Long> envIds = teamApps.stream()
|
|
||||||
.map(TeamApplication::getEnvironmentId)
|
|
||||||
.collect(Collectors.toSet());
|
|
||||||
|
|
||||||
List<TeamEnvironmentNotificationConfig> configs =
|
|
||||||
teamEnvironmentNotificationConfigRepository
|
|
||||||
.findByTeamIdInAndEnvironmentIdInAndBuildNotificationEnabledTrue(teamIds, envIds);
|
|
||||||
|
|
||||||
|
List<TeamEnvironmentNotificationConfig> configs = teamEnvironmentNotificationConfigRepository
|
||||||
|
.findByTeamIdInAndEnvironmentIdInAndBuildNotificationEnabledTrue(teamIds, envIds);
|
||||||
if (configs.isEmpty()) {
|
if (configs.isEmpty()) {
|
||||||
log.info("没有团队启用构建通知");
|
log.info("没有团队启用构建通知");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. 按 team_id + environment_id 分组配置
|
// 5. 构建配置Map(key: teamId_envId)
|
||||||
Map<String, TeamEnvironmentNotificationConfig> configMap = configs.stream()
|
Map<String, TeamEnvironmentNotificationConfig> configMap = configs.stream()
|
||||||
.collect(Collectors.toMap(
|
.collect(Collectors.toMap(
|
||||||
cfg -> cfg.getTeamId() + "_" + cfg.getEnvironmentId(),
|
cfg -> cfg.getTeamId() + "_" + cfg.getEnvironmentId(),
|
||||||
@ -522,63 +497,101 @@ public class JenkinsBuildServiceImpl extends BaseServiceImpl<JenkinsBuild, Jenki
|
|||||||
.map(TeamEnvironmentNotificationConfig::getNotificationChannelId)
|
.map(TeamEnvironmentNotificationConfig::getNotificationChannelId)
|
||||||
.filter(Objects::nonNull)
|
.filter(Objects::nonNull)
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
|
Map<Long, NotificationChannel> channelMap = notificationChannelRepository.findAllById(channelIds)
|
||||||
|
.stream().collect(Collectors.toMap(NotificationChannel::getId, c -> c));
|
||||||
|
|
||||||
Map<Long, NotificationChannel> channelMap =
|
// 7. 批量查询应用和环境信息
|
||||||
notificationChannelRepository.findAllById(channelIds).stream()
|
Set<Long> applicationIds = teamApps.stream().map(TeamApplication::getApplicationId).collect(Collectors.toSet());
|
||||||
.collect(Collectors.toMap(NotificationChannel::getId, c -> c));
|
Map<Long, Application> applicationMap = applicationRepository.findAllById(applicationIds)
|
||||||
|
.stream().collect(Collectors.toMap(Application::getId, a -> a));
|
||||||
|
Map<Long, Environment> environmentMap = environmentRepository.findAllById(envIds)
|
||||||
|
.stream().collect(Collectors.toMap(Environment::getId, e -> e));
|
||||||
|
|
||||||
// 7. 批量查询 Job
|
// 8. 批量查询所有视图下的Job,构建 jobName -> JenkinsJob 的Map
|
||||||
Set<Long> jobIds = buildsToProcess.stream()
|
List<JenkinsView> views = jenkinsViewRepository.findByExternalSystemId(externalSystemId);
|
||||||
.map(JenkinsBuild::getJobId)
|
Map<String, JenkinsJob> jobByNameMap = new HashMap<>();
|
||||||
|
for (JenkinsView view : views) {
|
||||||
|
List<JenkinsJob> jobs = jenkinsJobRepository.findByExternalSystemIdAndViewId(externalSystemId, view.getId());
|
||||||
|
for (JenkinsJob job : jobs) {
|
||||||
|
jobByNameMap.put(job.getJobName(), job);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 9. 收集需要处理的Job及其最新构建
|
||||||
|
Map<Long, JenkinsBuild> latestBuildByJobId = new HashMap<>();
|
||||||
|
Set<String> jobNamesToProcess = teamAppsByJob.keySet();
|
||||||
|
for (String jobName : jobNamesToProcess) {
|
||||||
|
JenkinsJob job = jobByNameMap.get(jobName);
|
||||||
|
if (job == null) {
|
||||||
|
log.debug("Job不存在: jobName={}", jobName);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
jenkinsBuildRepository.findTopByExternalSystemIdAndJobIdOrderByBuildNumberDesc(externalSystemId, job.getId())
|
||||||
|
.ifPresent(build -> latestBuildByJobId.put(job.getId(), build));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (latestBuildByJobId.isEmpty()) {
|
||||||
|
log.info("没有需要处理的构建记录");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 10. 批量查询通知记录(避免N+1)
|
||||||
|
Set<Long> buildIds = latestBuildByJobId.values().stream()
|
||||||
|
.map(JenkinsBuild::getId)
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
|
List<JenkinsBuildNotification> existingNotifications = jenkinsBuildNotificationRepository
|
||||||
Map<Long, JenkinsJob> jobMap = jenkinsJobRepository
|
.findByBuildIdInAndDeletedFalse(buildIds);
|
||||||
.findAllById(jobIds).stream()
|
// 构建 buildId_teamId_envId -> notification 的Map
|
||||||
.collect(Collectors.toMap(JenkinsJob::getId, j -> j));
|
Map<String, JenkinsBuildNotification> notificationMap = existingNotifications.stream()
|
||||||
|
.collect(Collectors.toMap(
|
||||||
// 8. 按 job_name 分组构建记录
|
n -> n.getBuildId() + "_" + n.getTeamId() + "_" + n.getEnvironmentId(),
|
||||||
Map<String, List<JenkinsBuild>> buildsByJobName = buildsToProcess.stream()
|
n -> n
|
||||||
.collect(Collectors.groupingBy(
|
|
||||||
build -> jobMap.get(build.getJobId()).getJobName()
|
|
||||||
));
|
));
|
||||||
|
|
||||||
// 9. 批量查询应用信息
|
// 11. 遍历每个 Job,处理通知
|
||||||
Set<Long> applicationIds = teamApps.stream()
|
for (Map.Entry<String, List<TeamApplication>> entry : teamAppsByJob.entrySet()) {
|
||||||
.map(TeamApplication::getApplicationId)
|
String jobName = entry.getKey();
|
||||||
.collect(Collectors.toSet());
|
List<TeamApplication> relatedTeamApps = entry.getValue();
|
||||||
Map<Long, Application> applicationMap = applicationRepository.findAllById(applicationIds).stream()
|
|
||||||
.collect(Collectors.toMap(Application::getId, a -> a));
|
|
||||||
|
|
||||||
// 10. 批量查询环境信息
|
JenkinsJob job = jobByNameMap.get(jobName);
|
||||||
Map<Long, Environment> environmentMap = environmentRepository.findAllById(envIds).stream()
|
if (job == null) continue;
|
||||||
.collect(Collectors.toMap(Environment::getId, e -> e));
|
|
||||||
|
|
||||||
// 11. 处理每个 Job 的构建通知
|
JenkinsBuild latestBuild = latestBuildByJobId.get(job.getId());
|
||||||
buildsByJobName.forEach((jobName, builds) -> {
|
if (latestBuild == null) continue;
|
||||||
List<TeamApplication> relatedTeamApps = teamAppsByJob.get(jobName);
|
|
||||||
if (relatedTeamApps == null || relatedTeamApps.isEmpty()) {
|
// 从 Jenkins API 实时获取最新状态(每个Job只调用一次)
|
||||||
return;
|
JenkinsBuildResponse latestBuildInfo = fetchLatestBuildInfo(externalSystem, job, latestBuild.getBuildNumber());
|
||||||
|
String latestStatus = (latestBuildInfo != null && latestBuildInfo.getResult() != null)
|
||||||
|
? latestBuildInfo.getResult()
|
||||||
|
: "BUILDING";
|
||||||
|
|
||||||
|
// 更新数据库中的构建状态(如果有变化)
|
||||||
|
if (latestBuildInfo != null && !latestStatus.equals(latestBuild.getBuildStatus())) {
|
||||||
|
updateBuildFromResponse(latestBuild, latestBuildInfo);
|
||||||
|
jenkinsBuildRepository.save(latestBuild);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 处理每个关联的 TeamApplication
|
||||||
for (TeamApplication teamApp : relatedTeamApps) {
|
for (TeamApplication teamApp : relatedTeamApps) {
|
||||||
String key = teamApp.getTeamId() + "_" + teamApp.getEnvironmentId();
|
String configKey = teamApp.getTeamId() + "_" + teamApp.getEnvironmentId();
|
||||||
TeamEnvironmentNotificationConfig config = configMap.get(key);
|
TeamEnvironmentNotificationConfig config = configMap.get(configKey);
|
||||||
|
|
||||||
if (config == null) continue;
|
if (config == null) continue;
|
||||||
|
|
||||||
NotificationChannel channel = channelMap.get(config.getNotificationChannelId());
|
NotificationChannel channel = channelMap.get(config.getNotificationChannelId());
|
||||||
if (channel == null) continue;
|
if (channel == null) continue;
|
||||||
|
|
||||||
JenkinsJob job = jobMap.get(builds.get(0).getJobId());
|
|
||||||
Application application = applicationMap.get(teamApp.getApplicationId());
|
Application application = applicationMap.get(teamApp.getApplicationId());
|
||||||
Environment environment = environmentMap.get(teamApp.getEnvironmentId());
|
Environment environment = environmentMap.get(teamApp.getEnvironmentId());
|
||||||
|
|
||||||
// 处理该团队环境的所有构建通知
|
// 从Map中获取通知记录(避免循环内查询)
|
||||||
for (JenkinsBuild build : builds) {
|
String notificationKey = latestBuild.getId() + "_" + config.getTeamId() + "_" + config.getEnvironmentId();
|
||||||
processBuildNotification(config, channel, job, build, externalSystem, application, environment);
|
JenkinsBuildNotification existingRecord = notificationMap.get(notificationKey);
|
||||||
}
|
|
||||||
|
// 处理该构建的通知
|
||||||
|
processBuildNotification(config, channel, job, latestBuild, latestStatus,
|
||||||
|
externalSystem, application, environment, existingRecord);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("检查构建通知失败: externalSystemId={}", externalSystemId, e);
|
log.error("检查构建通知失败: externalSystemId={}", externalSystemId, e);
|
||||||
@ -586,82 +599,85 @@ public class JenkinsBuildServiceImpl extends BaseServiceImpl<JenkinsBuild, Jenki
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理单个构建的通知
|
* 处理单个构建的通知(参考longi-deployment逻辑)
|
||||||
* <p>参考 longi-deployment 的实现:每次都从 Jenkins API 实时获取最新状态
|
*
|
||||||
|
* <p>核心逻辑:
|
||||||
|
* <ul>
|
||||||
|
* <li>无记录 = 新构建:超时(>20分钟)直接标记完成,未超时发送"构建中"通知</li>
|
||||||
|
* <li>有记录但buildEndNotice=false:检查是否完成,发送结束通知</li>
|
||||||
|
* </ul>
|
||||||
*/
|
*/
|
||||||
private void processBuildNotification(TeamEnvironmentNotificationConfig config, NotificationChannel channel, JenkinsJob job, JenkinsBuild build, ExternalSystem externalSystem, Application application, Environment environment) {
|
private void processBuildNotification(
|
||||||
|
TeamEnvironmentNotificationConfig config,
|
||||||
|
NotificationChannel channel,
|
||||||
|
JenkinsJob job,
|
||||||
|
JenkinsBuild build,
|
||||||
|
String latestStatus,
|
||||||
|
ExternalSystem externalSystem,
|
||||||
|
Application application,
|
||||||
|
Environment environment,
|
||||||
|
JenkinsBuildNotification existingRecord) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 1. 查询通知记录
|
// 计算构建开始到现在的分钟数
|
||||||
JenkinsBuildNotification record = jenkinsBuildNotificationRepository.findByBuildIdAndTeamIdAndEnvironmentId(build.getId(), config.getTeamId(), config.getEnvironmentId())
|
long minutesAgo = java.time.temporal.ChronoUnit.MINUTES.between(build.getStarttime(), LocalDateTime.now());
|
||||||
.orElse(null);
|
|
||||||
|
|
||||||
// 2. 从 Jenkins API 实时获取该构建的最新状态
|
// 1. 新构建(通知记录不存在)
|
||||||
JenkinsBuildResponse latestBuildInfo = fetchLatestBuildInfo(externalSystem, job, build.getBuildNumber());
|
if (existingRecord == null) {
|
||||||
String latestStatus = (latestBuildInfo != null && latestBuildInfo.getResult() != null)
|
// 超过20分钟的旧构建,直接标记完成,不发通知
|
||||||
? latestBuildInfo.getResult()
|
if (minutesAgo > 20) {
|
||||||
: "BUILDING";
|
JenkinsBuildNotification record = new JenkinsBuildNotification();
|
||||||
|
record.setBuildId(build.getId());
|
||||||
// 3. 新构建(只处理6分钟内的新构建)
|
record.setTeamId(config.getTeamId());
|
||||||
if (record == null) {
|
record.setEnvironmentId(config.getEnvironmentId());
|
||||||
long minutesAgo = java.time.temporal.ChronoUnit.MINUTES.between(
|
record.setBuildStartNotice(true);
|
||||||
build.getStarttime(),
|
record.setBuildEndNotice(true); // 直接标记结束
|
||||||
LocalDateTime.now()
|
jenkinsBuildNotificationRepository.save(record);
|
||||||
);
|
log.info("构建超时,直接标记完成: job={}, build={}, minutesAgo={}",
|
||||||
|
job.getJobName(), build.getBuildNumber(), minutesAgo);
|
||||||
// 超过6分钟的旧构建,不创建通知记录,直接跳过
|
|
||||||
if (minutesAgo > 6) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 6分钟内的新构建,发送"构建中"通知
|
// 未超时,发送"构建中"通知
|
||||||
record = new JenkinsBuildNotification();
|
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);
|
sendNotification(config, channel, job, build, "BUILDING", externalSystem, application, environment);
|
||||||
record.setBuildStartNotice(true);
|
record.setBuildStartNotice(true);
|
||||||
|
record.setBuildEndNotice(false);
|
||||||
jenkinsBuildNotificationRepository.save(record);
|
jenkinsBuildNotificationRepository.save(record);
|
||||||
|
log.info("发送构建开始通知: job={}, build={}", job.getJobName(), build.getBuildNumber());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. 已有记录,检查结束通知
|
// 2. 已有记录,检查是否需要发送结束通知
|
||||||
if (!record.getBuildEndNotice()) {
|
if (!existingRecord.getBuildEndNotice()) {
|
||||||
// 使用实时获取的状态判断是否已完成
|
|
||||||
if (isStatusFinished(latestStatus)) {
|
if (isStatusFinished(latestStatus)) {
|
||||||
// 更新数据库中的构建状态
|
// 构建已完成,发送结束通知
|
||||||
if (latestBuildInfo != null) {
|
sendNotification(config, channel, job, build, latestStatus, externalSystem, application, environment);
|
||||||
updateBuildFromResponse(build, latestBuildInfo);
|
existingRecord.setBuildEndNotice(true);
|
||||||
jenkinsBuildRepository.save(build);
|
jenkinsBuildNotificationRepository.save(existingRecord);
|
||||||
}
|
log.info("发送构建结束通知: job={}, build={}, status={}",
|
||||||
|
job.getJobName(), build.getBuildNumber(), latestStatus);
|
||||||
// 发送结束通知
|
|
||||||
if ("SUCCESS".equals(latestStatus) || "FAILURE".equals(latestStatus) || "ABORTED".equals(latestStatus)) {
|
|
||||||
sendNotification(config, channel, job, build, latestStatus, externalSystem, application, environment);
|
|
||||||
}
|
|
||||||
|
|
||||||
record.setBuildEndNotice(true);
|
|
||||||
jenkinsBuildNotificationRepository.save(record);
|
|
||||||
} else {
|
} else {
|
||||||
// 兜底逻辑:构建开始超过2小时仍未完成,强制标记为已完成(不发通知)
|
// 兜底:超过2小时仍未完成,强制标记结束(不发通知)
|
||||||
long hoursAgo = java.time.temporal.ChronoUnit.HOURS.between(
|
long hoursAgo = java.time.temporal.ChronoUnit.HOURS.between(build.getStarttime(), LocalDateTime.now());
|
||||||
build.getStarttime(),
|
|
||||||
LocalDateTime.now()
|
|
||||||
);
|
|
||||||
if (hoursAgo >= 2) {
|
if (hoursAgo >= 2) {
|
||||||
log.warn("构建超时未完成,强制标记结束通知: buildId={}, teamId={}, envId={}, startTime={}",
|
log.warn("构建超时未完成,强制标记结束: job={}, build={}, startTime={}",
|
||||||
build.getId(), config.getTeamId(), config.getEnvironmentId(), build.getStarttime());
|
job.getJobName(), build.getBuildNumber(), build.getStarttime());
|
||||||
record.setBuildEndNotice(true);
|
existingRecord.setBuildEndNotice(true);
|
||||||
jenkinsBuildNotificationRepository.save(record);
|
jenkinsBuildNotificationRepository.save(existingRecord);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (org.springframework.orm.ObjectOptimisticLockingFailureException e) {
|
} catch (org.springframework.orm.ObjectOptimisticLockingFailureException e) {
|
||||||
// 乐观锁冲突,说明记录已被其他线程更新,跳过即可
|
log.warn("构建通知记录乐观锁冲突,跳过: teamId={}, envId={}, buildId={}",
|
||||||
log.warn("构建通知记录乐观锁冲突,跳过处理: teamId={}, envId={}, buildId={}", config.getTeamId(), config.getEnvironmentId(), build.getId());
|
config.getTeamId(), config.getEnvironmentId(), build.getId());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("处理构建通知失败: teamId={}, envId={}, buildId={}", config.getTeamId(), config.getEnvironmentId(), build.getId(), e);
|
log.error("处理构建通知失败: teamId={}, envId={}, buildId={}",
|
||||||
|
config.getTeamId(), config.getEnvironmentId(), build.getId(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user