import { Logger } from "winston" import service from "../../service" import netTool from "../../service/netTool" import { Gitlab } from "../../types/gitlab" import reviewFiles from "./reviewFiles" import summaryFiles from "./summaryFiles" import summaryMr from "./summaryMr" import Commenter from "./utils/commenter" import { Inputs } from "./utils/inputs" import { PathFilter } from "./utils/pathFilter" /** * 过滤事件 * @param {Gitlab.MergeRequestEvent} event - 合并请求事件 * @returns {boolean} - 是否通过过滤 */ const filterEvent = (event: Gitlab.MergeRequestEvent): boolean => { return ( event.event_type === "merge_request" && event.object_attributes?.state === "opened" && !event.object_attributes?.changes ) } /** * 处理原始事件 * @param {Gitlab.MergeRequestEvent} mergeRequest - 合并请求事件 * @param {Logger} logger - 日志记录器 * @returns {Promise} - 处理结果 */ const manageRawEvent = async ( mergeRequest: Gitlab.MergeRequestEvent, logger: Logger ): Promise => { // 如果MR不是打开或重新打开状态,则不处理 const isOnCreateMr = filterEvent(mergeRequest) logger.info(`isOnCreateMr: ${isOnCreateMr}`) if (!isOnCreateMr) return netTool.ok() // 获取最新的MR Version const versions = await service.gitlab.mr.getDiffVersions( mergeRequest.project.id, mergeRequest.object_attributes.iid ) if (versions.length === 0) { logger.error("Failed to get MR versions") return netTool.serverError("Failed to get MR versions") } const latestVersion = versions[0] logger.debug(`latestVersion: ${JSON.stringify(latestVersion)}`) // 获取MR的全部修改 const changes = await service.gitlab.mr.getChanges( mergeRequest.project.id, mergeRequest.object_attributes.iid ) logger.debug(`changes: ${JSON.stringify(changes)}`) // 如果MR的全部修改不存在,则不处理 if (!changes) { logger.error("Failed to get MR changes") return netTool.serverError("Failed to get MR changes") } // 如果MR的描述中包含'skip review',则不处理 if (changes.description.includes("skip review")) { logger.info("Skip review") return netTool.ok() } // 创建路径过滤器 const pathFilter = new PathFilter([ "**/*.css", "**/*.less", "**/*.scss", "**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx", ]) // 获取MR的文件修改,并过滤出需要处理的文件 const files = changes.changes.filter( (change) => pathFilter.check(change.new_path) && !change.deleted_file && !change.renamed_file && change.diff ) // 如果没有需要处理的文件,则不处理 if (files.length === 0) { logger.info("No files need to be processed") return netTool.ok() } // 创建Commenter实例 const commenter = new Commenter( latestVersion.base_commit_sha, latestVersion.head_commit_sha, latestVersion.start_commit_sha, mergeRequest.project.id, mergeRequest.object_attributes.iid, logger ) // 发起loading评论,无所谓是否成功 await commenter.createLoadingComment() // 创建输入实例 const inputs: Inputs = new Inputs() // 获取MR的标题和描述 inputs.title = changes.title inputs.description = changes.description || "暂无描述" // 对文件进行总结 const { summarizedFileMap, needReviewFileMap } = await summaryFiles( files, true, inputs, logger ) // 如果总结完的文件Map为空,则不处理 if (summarizedFileMap.size === 0) { logger.info("No summarized files") await commenter.modifyLoadingOrCreateComment("没有需要审查的文件") return netTool.ok() } // 总结MR const summarizedMr = await summaryMr(summarizedFileMap, inputs, logger) // 如果总结MR为空,则不处理 if (!summarizedMr) { logger.info("No summarized Mr") await commenter.modifyLoadingOrCreateComment("没有生成整体的总结") return netTool.ok() } // 更新输入实例短总结 inputs.shortSummary = summarizedMr // 发送总结评论 + 文件变更 await commenter.createSummarizedComment(summarizedMr, summarizedFileMap) // 过滤出需要审查的文件 const needReviewFiles = files.filter( (file) => needReviewFileMap.get(file.new_path) || false ) // 如果需要审查的文件为空,则不处理 if (needReviewFiles.length === 0) { logger.info("No need review files") await commenter.createComment("没有需要审查的文件") return netTool.ok() } // 对需要审查的文件进行审查 await reviewFiles(needReviewFiles, inputs, commenter, logger) return netTool.ok() } const manageMrEvent = { manageRawEvent, } export default manageMrEvent