Files
devops-platform-api/src/notifications/wecom/deploy-notification.service.ts
T
2026-06-11 20:49:59 +08:00

104 lines
2.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { Injectable } from '@nestjs/common';
import { redactSensitive } from '../../common/security/redact-sensitive';
import { DeployRunSummary } from '../../deploy-runs/deploy-run.types';
import { WeComClient } from './wecom.client';
export type DeployNotificationEvent =
| 'created'
| 'queued'
| 'succeeded'
| 'failed'
| 'canceled'
| 'retried';
export type DeployNotificationResult = {
status: 'sent' | 'skipped' | 'failed';
channel: 'wecom';
reason?: string;
};
/**
* 统一封装发布单企微通知,保证 webhook 只存在于后端配置边界内。
*/
@Injectable()
export class DeployNotificationService {
constructor(private readonly weComClient: WeComClient) {}
async sendDeployRunEvent(
run: DeployRunSummary,
event: DeployNotificationEvent,
): Promise<DeployNotificationResult> {
const health = this.weComClient.healthSummary();
if (health.status === 'not_configured') {
return {
status: 'skipped',
channel: 'wecom',
reason: health.message ?? 'WeCom webhook is not configured',
};
}
try {
await this.weComClient.sendMarkdown({
title: this.titleFor(event),
markdown: this.markdownFor(run, event),
});
return { status: 'sent', channel: 'wecom' };
} catch (error) {
return {
status: 'failed',
channel: 'wecom',
reason:
error instanceof Error
? redactSensitive({ message: error.message }).message
: 'Unknown WeCom notification error',
};
}
}
private titleFor(event: DeployNotificationEvent): string {
if (event === 'canceled') {
return 'DevOps 发布已取消';
}
if (event === 'queued') {
return 'DevOps 发布已进入 Jenkins 队列';
}
if (event === 'succeeded') {
return 'DevOps 发布成功';
}
if (event === 'failed') {
return 'DevOps 发布失败';
}
if (event === 'retried') {
return 'DevOps 发布已重试';
}
return 'DevOps 发布已创建';
}
private markdownFor(
run: DeployRunSummary,
event: DeployNotificationEvent,
): string {
return [
`> 事件:${this.titleFor(event)}`,
`> 项目:${run.projectKey}`,
`> 环境:${run.environment}`,
`> Ref${run.ref}`,
`> 状态:${run.status}`,
`> 操作者:${run.operator}`,
`> Run ID${run.id}`,
run.jenkinsQueueId ? `> Jenkins Queue${run.jenkinsQueueId}` : undefined,
run.jenkinsBuildNumber ? `> Jenkins Build#${run.jenkinsBuildNumber}` : undefined,
run.failureSummary ? `> 失败摘要:${run.failureSummary}` : undefined,
]
.filter(Boolean)
.join('\n');
}
}