All checks were successful
CI Monitor MIflow / build-image (push) Successful in 1m2s
172 lines
4.9 KiB
TypeScript
172 lines
4.9 KiB
TypeScript
import db from "../../db"
|
||
import service from "../../service"
|
||
import netTool from "../../service/netTool"
|
||
import { EggMessage } from "../../types/eggMessage"
|
||
import { Gitlab } from "../../types/gitlab"
|
||
import { sec2minStr } from "../../utils/timeTools"
|
||
|
||
/**
|
||
* 判断是否是合并请求
|
||
* @param pipeline
|
||
* @returns
|
||
*/
|
||
const checkIsMergeCommit = (pipeline: Gitlab.PipelineEvent) => {
|
||
const regex = /^Merge branch '.*' into '.*'$/
|
||
return regex.test(pipeline.commit.title)
|
||
}
|
||
|
||
/**
|
||
* 判断是否是成功的CI
|
||
* @param pipeline
|
||
* @returns
|
||
*/
|
||
const checkIsSuccess = async (
|
||
pipeline: Gitlab.PipelineEvent,
|
||
stage?: string | null
|
||
) => {
|
||
/**
|
||
* 创建结果对象
|
||
* @param buildId 构建ID
|
||
* @param continueFlag 是否继续
|
||
* @returns 结果对象
|
||
*/
|
||
const makeResult = (buildId: string, continueFlag: boolean) => ({
|
||
buildId: continueFlag ? buildId : "",
|
||
continueFlag,
|
||
})
|
||
|
||
// 没有指定Stage则整个流水线成功即为成功
|
||
if (!stage)
|
||
return makeResult(
|
||
pipeline.builds
|
||
.sort((a, b) => a.finished_at.localeCompare(b.finished_at))[0]
|
||
.id.toString(),
|
||
pipeline.object_attributes.status === "success"
|
||
)
|
||
// 指定了Stage,该Stage是否全部成功
|
||
const builds = pipeline.builds.filter((build) => build.stage === stage)
|
||
// 没有该Stage的构建
|
||
if (builds.length === 0) return makeResult("", false)
|
||
// 有该Stage的构建,但不全成功
|
||
if (!builds.every((build) => build.status === "success"))
|
||
return makeResult("", false)
|
||
// 按finished_at排序,获取最后一个运行的id
|
||
const lastId = builds.sort((a, b) =>
|
||
a.finished_at.localeCompare(b.finished_at)
|
||
)[0].id
|
||
// 该ID的通知是否已经发送过
|
||
const notify = await db.notify.getOne(lastId.toString())
|
||
if (notify) return makeResult("", false)
|
||
return makeResult(lastId.toString(), true)
|
||
}
|
||
|
||
/**
|
||
* 获取合并请求
|
||
* @param pipeline
|
||
* @returns
|
||
*/
|
||
const getMergeRequest = async (pipeline: Gitlab.PipelineEvent) => {
|
||
if (!checkIsMergeCommit(pipeline)) return null
|
||
const res = await service.gitlab.commit.getMr(
|
||
pipeline.project.id,
|
||
pipeline.object_attributes.sha
|
||
)
|
||
if (res.length === 0) return null
|
||
return res.find((mr) => mr.merge_commit_sha === pipeline.commit.id) || null
|
||
}
|
||
|
||
/**
|
||
* 获取用户信息
|
||
* @param pipeline
|
||
* @param mergeRequest
|
||
* @returns
|
||
*/
|
||
const getUserInfo = (
|
||
pipeline: Gitlab.PipelineEvent,
|
||
mergeRequest: Gitlab.MergeRequest | null
|
||
) => {
|
||
let participant = pipeline.user.name
|
||
const receiver = [pipeline.user.username]
|
||
// 有MR且用户不同
|
||
if (mergeRequest && mergeRequest.author.username !== pipeline.user.username) {
|
||
participant += `、${mergeRequest.author.name}`
|
||
receiver.push(mergeRequest.author.username)
|
||
}
|
||
return { participant, receiver }
|
||
}
|
||
|
||
/**
|
||
* 获取机器人消息
|
||
* @param variable 模板变量
|
||
* @returns
|
||
*/
|
||
const getRobotMsg = async (variable: EggMessage.CardVariable) =>
|
||
JSON.stringify({
|
||
type: "template",
|
||
data: {
|
||
config: {
|
||
update_multi: true,
|
||
},
|
||
template_id: "ctp_AA36QafWyob2",
|
||
template_variable: variable,
|
||
},
|
||
})
|
||
|
||
/**
|
||
* 发送通知消息
|
||
* @param pipeline
|
||
* @param apiKey
|
||
* @returns
|
||
*/
|
||
const sendNotifyMsg = async (
|
||
pipeline: Gitlab.PipelineEvent,
|
||
apiKey: string,
|
||
params: URLSearchParams
|
||
) => {
|
||
const { continueFlag, buildId } = await checkIsSuccess(
|
||
pipeline,
|
||
params.get("stage")
|
||
)
|
||
// 只处理成功的CICD
|
||
if (!continueFlag) return netTool.ok()
|
||
// 获取对应的合并请求
|
||
const mergeRequest = await getMergeRequest(pipeline)
|
||
// 获取用户信息
|
||
const { participant, receiver } = getUserInfo(pipeline, mergeRequest)
|
||
// sonar的ID
|
||
const sonarParams = new URLSearchParams({
|
||
id: pipeline.project.path_with_namespace.replaceAll("/", ":"),
|
||
branch: pipeline.object_attributes.ref,
|
||
})
|
||
// 获取模板变量
|
||
const variable: EggMessage.CardVariable = {
|
||
project: pipeline.project.path_with_namespace,
|
||
project_link: pipeline.project.web_url,
|
||
pipeline: pipeline.object_attributes.id.toString(),
|
||
pipeline_link: `${pipeline.project.web_url}/-/pipelines`,
|
||
ref: pipeline.object_attributes.ref,
|
||
ref_link: `${pipeline.project.web_url}/-/commits/${pipeline.object_attributes.ref}`,
|
||
commit_user: pipeline.user.name,
|
||
duration: sec2minStr(pipeline.object_attributes.duration),
|
||
participant,
|
||
commit_message: pipeline.commit.title,
|
||
mr: mergeRequest ? mergeRequest.references.full : "无关联的MR",
|
||
mr_link: mergeRequest ? mergeRequest.web_url : "",
|
||
sonar_link: `https://sonarqube.mioffice.cn/dashboard?${sonarParams}`,
|
||
}
|
||
// 获取机器人消息
|
||
const robotMsg = await getRobotMsg(variable)
|
||
// 发送消息
|
||
service.message.byUserIdList(receiver, robotMsg, apiKey)
|
||
// 记录日志
|
||
await db.notify.create({ ...variable, build_id: buildId })
|
||
// 返回成功
|
||
return netTool.ok()
|
||
}
|
||
|
||
const managePipelineEvent = {
|
||
sendNotifyMsg,
|
||
}
|
||
|
||
export default managePipelineEvent
|