增加构建通知

This commit is contained in:
dengqichen 2025-11-14 15:01:09 +08:00
parent 46f23104f9
commit d8e65d8855
3 changed files with 36 additions and 27 deletions

View File

@ -1,6 +1,7 @@
package com.qqchen.deploy.backend.framework.exception; package com.qqchen.deploy.backend.framework.exception;
import com.qqchen.deploy.backend.framework.enums.ResponseCode; import com.qqchen.deploy.backend.framework.enums.ResponseCode;
import com.qqchen.deploy.backend.framework.utils.MessageUtils;
import lombok.Getter; import lombok.Getter;
@Getter @Getter
@ -19,8 +20,18 @@ public abstract class BaseException extends RuntimeException {
} }
protected BaseException(ResponseCode errorCode, Object[] args, Throwable cause) { protected BaseException(ResponseCode errorCode, Object[] args, Throwable cause) {
super(cause); super(buildMessage(errorCode, args), cause);
this.errorCode = errorCode; this.errorCode = errorCode;
this.args = args; this.args = args;
} }
}
private static String buildMessage(ResponseCode errorCode, Object[] args) {
if (errorCode == null) {
return null;
}
if (args == null || args.length == 0) {
return MessageUtils.getMessage(errorCode.getMessageKey());
}
return MessageUtils.getMessage(errorCode.getMessageKey(), args);
}
}

View File

@ -58,12 +58,13 @@ public abstract class BaseNodeDelegate<I, O> implements JavaDelegate {
// 当前执行上下文用于日志记录 // 当前执行上下文用于日志记录
private String currentProcessInstanceId; private String currentProcessInstanceId;
private String currentNodeId; private String currentNodeId;
// 预初始化的输出对象子类可以直接访问和修改 // 预初始化的输出对象子类可以直接访问和修改
protected O output; protected O output;
// 当前输入映射对象用于读取 continueOnFailure 等配置 // 当前输入映射对象用于读取 continueOnFailure 等配置
protected I currentInputMapping; protected I currentInputMapping;
@Override @Override
@ -103,21 +104,20 @@ public abstract class BaseNodeDelegate<I, O> implements JavaDelegate {
} catch (Exception e) { } catch (Exception e) {
// 业务异常根据 continueOnFailure 配置决定行为 // 业务异常根据 continueOnFailure 配置决定行为
log.error("Business exception in node: {}", currentNodeId, e); log.error("Business exception in node: {}", currentNodeId, e);
boolean continueOnFailure = WorkflowUtils.getContinueOnFailure(currentInputMapping); boolean continueOnFailure = WorkflowUtils.getContinueOnFailure(currentInputMapping);
if (continueOnFailure) { if (continueOnFailure) {
// 非阻断模式标记失败但流程继续 // 非阻断模式标记失败但流程继续
log.warn("⚠️ Node failed (continue mode enabled by config): {}", e.getMessage()); log.error("Node failed (continue mode enabled by config): {}", e.getMessage());
markFailure(e); markFailure(e);
// 保存失败状态的 NodeContext // 保存失败状态的 NodeContext
nodeContext.setConfigs(configsMap); nodeContext.setConfigs(configsMap);
nodeContext.setInputMapping(inputMappingObj); nodeContext.setInputMapping(inputMappingObj);
nodeContext.setOutputs(this.output); nodeContext.setOutputs(this.output);
execution.setVariable(currentNodeId, nodeContext.toMap(objectMapper)); execution.setVariable(currentNodeId, nodeContext.toMap(objectMapper));
} else { } else {
// 阻断模式终止流程默认行为 //阻断模式终止流程默认行为
log.error("Node failed (terminate mode, default): {}", e.getMessage()); log.error("Node failed (terminate mode, default): {}", e.getMessage());
terminateWorkflow(e); // 抛出 BpmnError触发流程终止 terminateWorkflow(e); // 抛出 BpmnError触发流程终止
} }
} }
@ -268,10 +268,10 @@ public abstract class BaseNodeDelegate<I, O> implements JavaDelegate {
*/ */
protected void terminateWorkflow(String errorCode, String errorMessage) { protected void terminateWorkflow(String errorCode, String errorMessage) {
log.error("🛑 Terminating workflow: errorCode={}, message={}", errorCode, errorMessage); log.error("🛑 Terminating workflow: errorCode={}, message={}", errorCode, errorMessage);
// 自动记录错误日志到 Redis Stream // 自动记录错误日志到 Redis Stream
logError(errorMessage); logError(errorMessage);
throw new org.flowable.engine.delegate.BpmnError(errorCode, errorMessage); throw new org.flowable.engine.delegate.BpmnError(errorCode, errorMessage);
} }
@ -294,8 +294,8 @@ public abstract class BaseNodeDelegate<I, O> implements JavaDelegate {
* @param exception 异常对象 * @param exception 异常对象
*/ */
protected void terminateWorkflow(Exception exception) { protected void terminateWorkflow(Exception exception) {
String errorMessage = exception.getMessage() != null String errorMessage = exception.getMessage() != null
? exception.getMessage() ? exception.getMessage()
: exception.getClass().getSimpleName(); : exception.getClass().getSimpleName();
terminateWorkflow(errorMessage); terminateWorkflow(errorMessage);
} }
@ -337,7 +337,6 @@ public abstract class BaseNodeDelegate<I, O> implements JavaDelegate {
} }
/** /**
* 创建失败状态的输出对象非致命错误流程继续 * 创建失败状态的输出对象非致命错误流程继续
* <p> * <p>
@ -413,7 +412,7 @@ public abstract class BaseNodeDelegate<I, O> implements JavaDelegate {
if (outputs instanceof BaseNodeOutputs) { if (outputs instanceof BaseNodeOutputs) {
((BaseNodeOutputs) outputs).setStatus(NodeExecutionStatusEnum.SUCCESS); ((BaseNodeOutputs) outputs).setStatus(NodeExecutionStatusEnum.SUCCESS);
// 自动生成默认成功消息 // 自动生成默认成功消息
String nodeName = WorkflowUtils.extractNodeName(configsMap); String nodeName = WorkflowUtils.extractNodeName(configsMap);
((BaseNodeOutputs) outputs).setMessage(nodeName + "执行成功"); ((BaseNodeOutputs) outputs).setMessage(nodeName + "执行成功");
@ -435,7 +434,7 @@ public abstract class BaseNodeDelegate<I, O> implements JavaDelegate {
/** /**
* 记录错误日志到 Redis Stream * 记录错误日志到 Redis Stream
* *
* @param message 错误信息 * @param message 错误信息
*/ */
protected void logError(String message) { protected void logError(String message) {
@ -457,7 +456,7 @@ public abstract class BaseNodeDelegate<I, O> implements JavaDelegate {
/** /**
* 记录警告日志到 Redis Stream * 记录警告日志到 Redis Stream
* *
* @param message 警告信息 * @param message 警告信息
*/ */
protected void logWarn(String message) { protected void logWarn(String message) {
@ -478,7 +477,7 @@ public abstract class BaseNodeDelegate<I, O> implements JavaDelegate {
/** /**
* 记录信息日志到 Redis Stream * 记录信息日志到 Redis Stream
* *
* @param message 信息内容 * @param message 信息内容
*/ */
protected void logInfo(String message) { protected void logInfo(String message) {

View File

@ -94,7 +94,7 @@ public class JenkinsBuildDelegate extends BaseNodeDelegate<JenkinsBuildInputMapp
log.info("Build details - changeSets: {}, artifacts: {}", buildDetails.getChangeSets(), buildDetails.getArtifacts()); log.info("Build details - changeSets: {}, artifacts: {}", buildDetails.getChangeSets(), buildDetails.getArtifacts());
// 6. 设置输出结果执行到这里说明构建成功 // 6. 设置输出结果执行到这里说明构建成功
// 直接修改预初始化的 output 对象 // 直接修改预初始化的 output 对象
// 设置 Jenkins 特有字段 // 设置 Jenkins 特有字段
output.setBuildStatus(buildStatus.name()); output.setBuildStatus(buildStatus.name());
@ -169,7 +169,7 @@ public class JenkinsBuildDelegate extends BaseNodeDelegate<JenkinsBuildInputMapp
// 等待一定时间后再检查 // 等待一定时间后再检查
Thread.sleep(BUILD_POLL_INTERVAL * 1000L); Thread.sleep(BUILD_POLL_INTERVAL * 1000L);
// 1. 增量拉取并保存 Jenkins 构建日志 // 1. 增量拉取并保存 Jenkins 构建日志
try { try {
JenkinsConsoleOutputResponse consoleOutput = jenkinsServiceIntegration.getConsoleOutput(externalSystem, jobName, buildNumber, logOffset); JenkinsConsoleOutputResponse consoleOutput = jenkinsServiceIntegration.getConsoleOutput(externalSystem, jobName, buildNumber, logOffset);
@ -192,17 +192,17 @@ public class JenkinsBuildDelegate extends BaseNodeDelegate<JenkinsBuildInputMapp
switch (status) { switch (status) {
case SUCCESS: case SUCCESS:
// 构建成功拉取剩余日志后返回状态 // 构建成功拉取剩余日志后返回状态
log.info("Jenkins build succeeded: job={}, buildNumber={}", jobName, buildNumber); log.info("Jenkins build succeeded: job={}, buildNumber={}", jobName, buildNumber);
fetchRemainingLogs(execution, externalSystem, jobName, buildNumber, logOffset); fetchRemainingLogs(execution, externalSystem, jobName, buildNumber, logOffset);
logInfo(String.format("✅ Jenkins 构建成功: buildNumber=%d", buildNumber)); logInfo(String.format("✅ Jenkins 构建成功: buildNumber=%d", buildNumber));
return status; return status;
case FAILURE: case FAILURE:
// 构建失败拉取剩余日志后抛出异常 // 构建失败拉取剩余日志后抛出异常
fetchRemainingLogs(execution, externalSystem, jobName, buildNumber, logOffset); fetchRemainingLogs(execution, externalSystem, jobName, buildNumber, logOffset);
throw new RuntimeException(String.format("Jenkins build failed: job=%s, buildNumber=%d", jobName, buildNumber)); throw new RuntimeException(String.format("Jenkins build failed: job=%s, buildNumber=%d", jobName, buildNumber));
case ABORTED: case ABORTED:
// 构建被取消拉取剩余日志后抛出异常 // 构建被取消拉取剩余日志后抛出异常
fetchRemainingLogs(execution, externalSystem, jobName, buildNumber, logOffset); fetchRemainingLogs(execution, externalSystem, jobName, buildNumber, logOffset);
throw new RuntimeException(String.format("Jenkins build was aborted: job=%s, buildNumber=%d", jobName, buildNumber)); throw new RuntimeException(String.format("Jenkins build was aborted: job=%s, buildNumber=%d", jobName, buildNumber));
case IN_PROGRESS: case IN_PROGRESS:
@ -210,7 +210,7 @@ public class JenkinsBuildDelegate extends BaseNodeDelegate<JenkinsBuildInputMapp
attempts++; attempts++;
break; break;
case NOT_FOUND: case NOT_FOUND:
// 构建记录丢失抛出异常 // 构建记录丢失抛出异常
throw new RuntimeException(String.format("Jenkins build not found: job=%s, buildNumber=%d", jobName, buildNumber)); throw new RuntimeException(String.format("Jenkins build not found: job=%s, buildNumber=%d", jobName, buildNumber));
} }
} catch (InterruptedException e) { } catch (InterruptedException e) {
@ -218,8 +218,7 @@ public class JenkinsBuildDelegate extends BaseNodeDelegate<JenkinsBuildInputMapp
throw new RuntimeException("Build status polling was interrupted", e); throw new RuntimeException("Build status polling was interrupted", e);
} }
} }
throw new RuntimeException(String.format("Jenkins build timed out after %d minutes: job=%s, buildNumber=%d", throw new RuntimeException(String.format("Jenkins build timed out after %d minutes: job=%s, buildNumber=%d", MAX_BUILD_POLLS * BUILD_POLL_INTERVAL / 60, jobName, buildNumber));
MAX_BUILD_POLLS * BUILD_POLL_INTERVAL / 60, jobName, buildNumber));
} }
/** /**