t-comm
Version:
专业、稳定、纯粹的工具库
590 lines (589 loc) • 20.2 kB
TypeScript
/** MR 变更文件信息 */
export interface MRChange {
/** 旧文件路径 */
old_path: string;
/** 新文件路径 */
new_path: string;
/** 是否新增文件 */
new_file: boolean;
/** 是否重命名 */
renamed_file: boolean;
/** 是否删除 */
deleted_file: boolean;
/** diff 内容 */
diff: string;
}
/** MR 详情 */
export interface MRDetail {
id: number;
iid: number;
title: string;
description: string;
state: string;
source_branch: string;
target_branch: string;
author: {
username: string;
name: string;
};
web_url: string;
source_project_id: number;
target_project_id: number;
[k: string]: unknown;
}
/** MR 变更详情(含 diff),统一使用 changes 字段名 */
export interface MRChangesDetail extends MRDetail {
changes: MRChange[];
}
/**
* 从 TGit MR 的 URL 中解析出项目名称和 MR ID
*
* iid 与 id 的区别:
* - iid:项目内的序号,从 1 开始递增,即 URL 和 Web 界面上看到的数字(如 /merge_requests/112 中的 112)
* - id:MR 在整个 TGit 系统中的全局唯一 ID,不同项目间不重复
*
* 本函数从 URL 中解析出的数字是 iid(项目内序号),不是全局 id。
* 如需获取全局 id,可使用 queryMRByIId 通过 iid 查询 MR 详情后获取。
*
* @param {string} url TGit MR 的 URL,如 https://git.woa.com/group/project/-/merge_requests/112
* @returns {{ projectName: string, mrIid: string } | null} 解析结果(mrIid 为 URL 中的 iid),解析失败返回 null
* @example
*
* // URL 中的 112 是 iid(项目内序号)
* parseMRUrl('https://git.woa.com/pmd-mobile/ai-tool/rd-ai-common/-/merge_requests/112/notes')
* // => { projectName: 'pmd-mobile/ai-tool/rd-ai-common', mrIid: '112' }
*
* parseMRUrl('https://git.woa.com/coecology/xd/-/merge_requests/169')
* // => { projectName: 'coecology/xd', mrIid: '169' }
*/
export declare function parseMRUrl(url: string): {
projectName: string;
mrIid: string;
} | null;
/**
* 创建MR
* @param {object} options 输入配置
* @param {string} options.projectName 项目名称
* @param {string} options.privateToken 密钥
* @param {string} options.sourceBranch 源分支
* @param {string} options.targetBranch 目标分支
* @param {number} [options.approverRule=1] 审批规则
* @param {number} [options.necessaryApproverRule=0] 必要审批规则
* @returns {Promise<object>} 请求Promise
* @example
*
* createMR({
* projectName: 't-comm',
* privateToken: 'xxxxx',
* sourceBranch: 'master',
* targetBranch: 'release',
* }).then((resp) => {
*
* })
*/
export declare function createMR({ projectName, privateToken, sourceBranch, targetBranch, approverRule, necessaryApproverRule, baseUrl, titlePrefix, title: customTitle, description, assigneeList, reviewerList, }: {
projectName: string | number;
privateToken: string;
sourceBranch: string;
targetBranch: string;
approverRule?: number;
necessaryApproverRule?: number;
baseUrl?: string;
/** MR 标题前缀,如 '[WIP]' 可防止被自动合入(仅在未显式传 title 时生效) */
titlePrefix?: string;
/** 自定义 MR 标题;未传则自动生成 `${sourceBranch} => ${targetBranch}` */
title?: string;
/** MR 描述 */
description?: string;
/**
* 评审人(Assignee)用户名列表(工蜂英文名/RTX)。
* 函数内部会调用 resolveUserIds 转换为数字 ID。
* 工蜂 v3 仅支持单个 assignee_id,传多人时取第一个能解析到的。
*/
assigneeList?: string[];
/**
* Reviewers 用户名列表(工蜂英文名/RTX)。
* 函数内部会调用 resolveUserIds 转换为数字 ID。
* 未传时会默认使用 assigneeList 作为 reviewers(与 GitApiService 行为保持一致)。
*/
reviewerList?: string[];
}): Promise<any>;
/**
* 获取MR列表
* @param {object} options 输入配置
* @param {string} options.projectName 项目名称
* @param {string} options.privateToken 密钥
* @returns {Promise<object>} 请求Promise
* @example
*
* getMrList({
* projectName: 't-comm',
* privateToken: 'xxxxx',
* }).then((resp) => {
*
* })
*/
export declare function getMrList({ projectName, privateToken, baseUrl }: {
projectName: string;
privateToken: string;
baseUrl?: string;
}): Promise<object>;
/**
* 获取MR的一条评论
* @param {object} options 输入配置
* @param {string} options.projectName 项目名称
* @param {string} options.privateToken 密钥
* @param {string} options.mrId 某次MR的Id
* @returns {Promise<object>} 请求Promise
* @example
*
* getOneMrComments({
* projectName: 't-comm',
* privateToken: 'xxxxx',
* mrId: '1'
* }).then((resp) => {
*
* })
*/
export declare function getOneMrComments({ mrId, projectName, privateToken, baseUrl }: {
projectName: string;
mrId: string;
privateToken: string;
baseUrl?: string;
}): Promise<object>;
/**
* 发表评审意见(同意/拒绝/评论/要求修改)
* @param {object} options 输入配置
* @param {string} [options.projectName] 项目名称(与 url 二选一)
* @param {string} options.privateToken 密钥
* @param {string} [options.reviewableId] 合并请求的 reviewable_id(与 url 二选一)。注意 reviewer/summary API 需要的既不是全局 id 也不是 iid,而是 reviewable_id,可通过 queryMRByIId 获取
* @param {string} [options.url] TGit MR 的 URL,传入后自动解析 projectName 和 mrIid,并自动调用 queryMRByIId 获取 reviewable_id
* @param {string} options.reviewerEvent 评审人事件,可选:comment | approve | require_change | deny
* @param {string} [options.summary] 评审信息摘要
* @returns {Promise<object>} 请求Promise
* @example
*
* // 方式一:直接传入 projectName 和 reviewableId
* reviewMR({
* projectName: 't-comm',
* privateToken: 'xxxxx',
* reviewableId: '1',
* reviewerEvent: 'approve',
* summary: 'LGTM',
* }).then((resp) => {
*
* })
*
* // 方式二:传入 URL 自动解析
* reviewMR({
* url: 'https://git.woa.com/coecology/xd/-/merge_requests/169',
* privateToken: 'xxxxx',
* reviewerEvent: 'approve',
* }).then((resp) => {
*
* })
*/
export declare function reviewMR({ baseUrl, reviewableId, projectName, privateToken, reviewerEvent, summary, url, }: {
projectName?: string;
reviewableId?: string;
privateToken: string;
reviewerEvent: 'comment' | 'approve' | 'require_change' | 'deny';
summary?: string;
url?: string;
baseUrl?: string;
}): Promise<object>;
/**
* 根据 iid(项目内序号)查询 MR 评审信息
*
* iid 与 id 的区别:
* - iid:项目内的序号,从 1 开始递增,即 URL 和 Web 界面上看到的数字(如 /merge_requests/112 中的 112)
* - id:MR 在整个 TGit 系统中的全局唯一 ID,不同项目间不重复
*
* 对应 API:GET /api/v3/projects/:id/merge_request/iid/:merge_request_iid/review
*
* @param {object} options 输入配置
* @param {string} options.projectName 项目名称或项目全路径
* @param {string} options.privateToken 密钥
* @param {string} options.mrIid 合并请求在项目中的编号 iid(即 URL 中看到的数字)
* @param {string} [options.baseUrl] 自定义 API 基础路径
* @returns {Promise<object>} MR 评审信息,包含 id(评审记录全局 ID)、reviewable_id(reviewer/summary 接口需要的 ID)、iid、title、description、author 等字段
* @example
*
* queryMRByIId({
* projectName: 'coecology/xd',
* privateToken: 'xxxxx',
* mrIid: '169',
* }).then((resp) => {
* console.log(resp.id); // 全局 id
* console.log(resp.title); // MR 标题
* })
*/
export declare function queryMRByIId({ projectName, privateToken, mrIid, baseUrl }: {
projectName: string;
mrIid: string;
privateToken: string;
baseUrl?: string;
}): Promise<object>;
/**
* 通过 iid(项目内 MR 序号)获取 MR 的全局 id
*
* iid 与 id 的区别:
* - iid:项目内的序号,从 1 开始递增,即 URL 和 Web 界面上看到的数字
* - id:MR 在整个 TGit 系统中的全局唯一 ID
*
* 工蜂 v3 API 的 merge_request 详情接口使用全局 id,而非 iid。
* 新建的 MR 在工蜂 API 侧可能有短暂同步延迟,本函数默认进行 3 次重试(3s 间隔)。
*
* 对应工蜂 API:GET /api/v3/projects/:id/merge_requests?iid=:iid
*
* @param {object} options 输入配置
* @param {string | number} options.projectName 项目名称或项目 ID
* @param {number | string} options.mrIid MR 的项目内序号
* @param {string} options.privateToken 密钥
* @param {string} [options.baseUrl] baseUrl
* @param {number} [options.maxRetries=3] 最大重试次数
* @param {number} [options.retryDelay=3000] 重试间隔(毫秒)
* @returns {Promise<number>} MR 的全局 id
* @example
*
* getMRIdByIid({
* projectName: 'group/sub/repo',
* mrIid: 112,
* privateToken: 'xxxxx',
* }).then((id) => {
* console.log(id); // 全局 id
* })
*/
export declare function getMRIdByIid({ projectName, mrIid, privateToken, baseUrl, maxRetries, retryDelay, }: {
projectName: string | number;
mrIid: number | string;
privateToken: string;
baseUrl?: string;
maxRetries?: number;
retryDelay?: number;
}): Promise<number>;
/**
* 获取 MR 详情(参数为 iid,内部自动转全局 id)
*
* 对应工蜂 API:GET /api/v3/projects/:id/merge_request/:id
*
* @param {object} options 输入配置
* @param {string | number} options.projectName 项目名称或项目 ID
* @param {number | string} options.mrIid MR 的项目内序号
* @param {string} options.privateToken 密钥
* @param {string} [options.baseUrl] baseUrl
* @returns {Promise<MRDetail>} MR 详情
* @example
*
* getMRDetail({
* projectName: 'coecology/xd',
* mrIid: 169,
* privateToken: 'xxxxx',
* }).then((mr) => {
* console.log(mr.title, mr.state);
* })
*/
export declare function getMRDetail({ projectName, mrIid, privateToken, baseUrl, }: {
projectName: string | number;
mrIid: number | string;
privateToken: string;
baseUrl?: string;
}): Promise<MRDetail>;
/**
* 获取 MR 变更内容(含 diff)
*
* 对应工蜂 API:GET /api/v3/projects/:id/merge_request/:id/changes
*
* 工蜂 v3 API 返回的变更文件字段名为 `files`,本函数会额外映射一个 `changes` 字段
* 方便调用方以统一的字段名访问(同时保留 files)。
*
* @param {object} options 输入配置
* @param {string | number} options.projectName 项目名称或项目 ID
* @param {number | string} options.mrIid MR 的项目内序号
* @param {string} options.privateToken 密钥
* @param {string} [options.baseUrl] baseUrl
* @returns {Promise<MRChangesDetail>} MR 变更详情
* @example
*
* getMRChanges({
* projectName: 'coecology/xd',
* mrIid: 169,
* privateToken: 'xxxxx',
* }).then((res) => {
* res.changes.forEach(c => console.log(c.new_path));
* })
*/
export declare function getMRChanges({ projectName, mrIid, privateToken, baseUrl, }: {
projectName: string | number;
mrIid: number | string;
privateToken: string;
baseUrl?: string;
}): Promise<MRChangesDetail>;
/**
* 在 MR 上提交评论(Note)
*
* - 不传 filePath/line:普通评论(贴在 MR 讨论区)
* - 传 filePath 和 line:行内评论(贴在 diff 指定文件的指定行)
*
* 对应工蜂 API:POST /api/v3/projects/:id/merge_requests/:id/notes
*
* @param {object} options 输入配置
* @param {string | number} options.projectName 项目名称或项目 ID
* @param {number | string} options.mrIid MR 的项目内序号
* @param {string} options.body 评论内容
* @param {string} options.privateToken 密钥
* @param {string} [options.filePath] 行内评论:diff 中的新文件路径
* @param {number} [options.line] 行内评论:新文件中的行号
* @param {'new' | 'old'} [options.lineType='new'] 行内评论:行类型,默认 new
* @param {string} [options.baseUrl] baseUrl
* @returns {Promise<{ id: number }>} 新建评论的 ID
* @example
*
* // 1. 普通评论
* createMRNote({
* projectName: 'coecology/xd',
* mrIid: 169,
* body: 'LGTM',
* privateToken: 'xxxxx',
* }).then((res) => console.log(res.id));
*
* // 2. 行内评论
* createMRNote({
* projectName: 'coecology/xd',
* mrIid: 169,
* body: '这里可以优化',
* filePath: 'src/index.ts',
* line: 12,
* lineType: 'new',
* privateToken: 'xxxxx',
* });
*/
export declare function createMRNote({ projectName, mrIid, body, privateToken, filePath, line, lineType, baseUrl, }: {
projectName: string | number;
mrIid: number | string;
body: string;
privateToken: string;
filePath?: string;
line?: number;
lineType?: 'new' | 'old';
baseUrl?: string;
}): Promise<{
id: number;
}>;
/**
* 获取 MR 的所有评论(Notes)列表
*
* 对应工蜂 API:GET /api/v3/projects/:id/merge_requests/:id/notes
*
* @param {object} options 输入配置
* @param {string | number} options.projectName 项目名称或项目 ID
* @param {number | string} options.mrIid MR 的项目内序号
* @param {string} options.privateToken 密钥
* @param {number} [options.perPage=100] 每页数量
* @param {string} [options.baseUrl] baseUrl
* @returns {Promise<Array<Record<string, unknown>>>} 评论列表
* @example
*
* getMRNotes({
* projectName: 'coecology/xd',
* mrIid: 169,
* privateToken: 'xxxxx',
* }).then((notes) => {
* notes.forEach(n => console.log(n.id, n.body));
* })
*/
export declare function getMRNotes({ projectName, mrIid, privateToken, perPage, baseUrl, }: {
projectName: string | number;
mrIid: number | string;
privateToken: string;
perPage?: number;
baseUrl?: string;
}): Promise<Array<Record<string, unknown>>>;
/**
* 获取 MR 的单条评论(Note)详情
*
* 对应工蜂 API:GET /api/v3/projects/:id/merge_requests/:id/notes/:noteId
*
* @param {object} options 输入配置
* @param {string | number} options.projectName 项目名称或项目 ID
* @param {number | string} options.mrIid MR 的项目内序号
* @param {number | string} options.noteId 评论 ID
* @param {string} options.privateToken 密钥
* @param {string} [options.baseUrl] baseUrl
* @returns {Promise<Record<string, unknown>>} 评论详情
* @example
*
* getMRNoteById({
* projectName: 'coecology/xd',
* mrIid: 169,
* noteId: 123456,
* privateToken: 'xxxxx',
* }).then((note) => {
* console.log(note.body);
* })
*/
export declare function getMRNoteById({ projectName, mrIid, noteId, privateToken, baseUrl, }: {
projectName: string | number;
mrIid: number | string;
noteId: number | string;
privateToken: string;
baseUrl?: string;
}): Promise<Record<string, unknown>>;
/**
* 更新 MR 上的已有评论
*
* 对应工蜂 API:PUT /api/v3/projects/:id/merge_requests/:id/notes/:noteId
*
* @param {object} options 输入配置
* @param {string | number} options.projectName 项目名称或项目 ID
* @param {number | string} options.mrIid MR 的项目内序号
* @param {number | string} options.noteId 要更新的评论 ID
* @param {string} options.body 新的评论内容
* @param {string} options.privateToken 密钥
* @param {string} [options.baseUrl] baseUrl
* @returns {Promise<{ id: number }>} 更新后的评论
* @example
*
* updateMRNote({
* projectName: 'coecology/xd',
* mrIid: 169,
* noteId: 123456,
* body: '更新后的评论内容',
* privateToken: 'xxxxx',
* }).then((res) => console.log(res.id));
*/
export declare function updateMRNote({ projectName, mrIid, noteId, body, privateToken, baseUrl, }: {
projectName: string | number;
mrIid: number | string;
noteId: number | string;
body: string;
privateToken: string;
baseUrl?: string;
}): Promise<{
id: number;
}>;
/**
* 回复 MR 上的已有评论(在讨论串中回复)
*
* 对应工蜂 API:POST /api/v3/projects/:id/merge_requests/:id/notes/:noteId/replies
*
* @param {object} options 输入配置
* @param {string | number} options.projectName 项目名称或项目 ID
* @param {number | string} options.mrIid MR 的项目内序号
* @param {number | string} options.parentNoteId 要回复的父评论 ID
* @param {string} options.body 回复内容
* @param {string} options.privateToken 密钥
* @param {string} [options.baseUrl] baseUrl
* @returns {Promise<{ id: number }>} 新建回复的 ID
* @example
*
* createNoteReply({
* projectName: 'coecology/xd',
* mrIid: 169,
* parentNoteId: 123456,
* body: '同意上面的意见',
* privateToken: 'xxxxx',
* }).then((res) => console.log(res.id));
*/
export declare function createNoteReply({ projectName, mrIid, parentNoteId, body, privateToken, baseUrl, }: {
projectName: string | number;
mrIid: number | string;
parentNoteId: number | string;
body: string;
privateToken: string;
baseUrl?: string;
}): Promise<{
id: number;
}>;
/**
* 回复代码评审中的评论(行内评论 reply)
*
* 对应工蜂 API:POST /api/v3/projects/:id/reviews/:reviewId/notes/:noteId/replies
*
* 只能回复代码行上的第一条评论,不支持回复「已是回复」的评论。
*
* @param {object} options 输入配置
* @param {string | number} options.projectName 项目名称或项目 ID
* @param {number | string} options.reviewId 评审记录 ID
* @param {number | string} options.noteId 要回复的评论 ID
* @param {string} options.body 回复内容
* @param {string} options.privateToken 密钥
* @param {string} [options.baseUrl] baseUrl
* @returns {Promise<{ id: number }>} 新建回复的 ID
* @example
*
* createReviewNoteReply({
* projectName: 'coecology/xd',
* reviewId: 9999,
* noteId: 123456,
* body: '这里应该补一下边界检查',
* privateToken: 'xxxxx',
* }).then((res) => console.log(res.id));
*/
export declare function createReviewNoteReply({ projectName, reviewId, noteId, body, privateToken, baseUrl, }: {
projectName: string | number;
reviewId: number | string;
noteId: number | string;
body: string;
privateToken: string;
baseUrl?: string;
}): Promise<{
id: number;
}>;
/**
* 关闭 MR(参数为 iid,内部自动转全局 id)
*
* 对应工蜂 API:PUT /api/v3/projects/:id/merge_request/:id body: { state_event: 'close' }
*
* @param {object} options 输入配置
* @param {string | number} options.projectName 项目名称或项目 ID
* @param {number | string} options.mrIid MR 的项目内序号
* @param {string} options.privateToken 密钥
* @param {string} [options.baseUrl] baseUrl
* @returns {Promise<MRDetail>} 关闭后的 MR 详情
* @example
*
* closeMR({
* projectName: 'coecology/xd',
* mrIid: 169,
* privateToken: 'xxxxx',
* }).then((mr) => {
* console.log(mr.state);
* })
*/
export declare function closeMR({ projectName, mrIid, privateToken, baseUrl, }: {
projectName: string | number;
mrIid: number | string;
privateToken: string;
baseUrl?: string;
}): Promise<MRDetail>;
/**
* 通过 MR URL 关闭一个 MR
*
* 内部流程:
* 1. 调用 {@link parseMRUrl} 从 URL 中解析出 projectName + mrIid
* 2. 调用 {@link closeMR} 完成关闭操作
*
* @param {object} options 输入配置
* @param {string} options.mrUrl MR 的 URL
* @param {string} options.privateToken 密钥
* @param {string} [options.baseUrl] baseUrl
* @returns {Promise<{ projectName: string; mrIid: string; raw: MRDetail }>} 解析与关闭结果
* @example
*
* closeMRByUrl({
* mrUrl: 'https://git.woa.com/coecology/xd/-/merge_requests/169',
* privateToken: 'xxxxx',
* }).then((res) => {
* console.log(res.projectName, res.mrIid, res.raw.state);
* })
*/
export declare function closeMRByUrl({ mrUrl, privateToken, baseUrl, }: {
mrUrl: string;
privateToken: string;
baseUrl?: string;
}): Promise<{
projectName: string;
mrIid: string;
raw: MRDetail;
}>;