UNPKG

t-comm

Version:

专业、稳定、纯粹的工具库

141 lines (124 loc) 4.75 kB
/** * @file t-comm merge-branches CLI 子命令 * @description 调用 mergeBranches 将源分支(或 commit)合并到目标分支。 * * 支持两种使用方式: * 1. 直接传入 MR URL(--mr <url>):自动解析 projectName,并通过 queryMRByIId 拿到 * source_branch / target_branch(以及可能的 source_project_id),然后发起合并。 * 2. 显式传参(--id, --source, --target):与原有 trial 脚本行为一致。 */ const { mergeBranches, parseMRUrl, queryMRByIId, } = require('../lib'); /** * 解析 MR URL,并通过 queryMRByIId 获取分支信息 * @param {string} url MR URL * @param {object} ctx 上下文:privateToken、baseUrl * @returns {Promise<{ projectName: string, sourceBranch: string, targetBranch: string, sourceProjectId?: number }>} */ async function resolveFromMrUrl(url, { privateToken, baseUrl }) { const parsed = parseMRUrl(url); if (!parsed) { throw new Error(`无法从 URL 解析出 projectName 和 mrIid: ${url}`); } const { projectName, mrIid } = parsed; const review = await queryMRByIId({ projectName, mrIid, privateToken, baseUrl, }); const sourceBranch = review && review.source_branch; const targetBranch = review && review.target_branch; if (!sourceBranch || !targetBranch) { throw new Error(`通过 queryMRByIId 未获取到 source_branch/target_branch,请检查 MR 状态: ${url}`); } return { projectName, sourceBranch, targetBranch, // 跨项目 MR 时 source_project_id 与目标项目可能不同,透传给 mergeBranches sourceProjectId: review.source_project_id, }; } /** * t-comm merge-branches CLI 命令处理函数 * @param {object} options Commander 解析得到的选项 */ async function mergeBranchesCommand(options) { const { mr, id, source, target, sourceProjectId, mergeType = 'merge', commitMessage, privateToken, baseUrl, } = options; const token = privateToken || process.env.GIT_WOA_PRIVATE_TOKEN; const finalBaseUrl = baseUrl || process.env.GIT_WOA_BASE_URL; if (!token) { console.error('❌ 缺少 PRIVATE TOKEN,请通过 --private-token 或环境变量 GIT_WOA_PRIVATE_TOKEN 提供'); process.exit(1); } const validMergeTypes = ['merge', 'rebase', 'squash']; if (!validMergeTypes.includes(mergeType)) { console.error(`❌ 无效的 --merge-type "${mergeType}",可选值:${validMergeTypes.join(' | ')}`); process.exit(1); } if (mergeType === 'rebase' && !commitMessage) { console.error('❌ --merge-type=rebase 时必须通过 --commit-message 提供合并点提交信息'); process.exit(1); } let resolvedId = id; let resolvedSource = source; let resolvedTarget = target; let resolvedSourceProjectId = sourceProjectId ? Number(sourceProjectId) : undefined; if (mr) { const info = await resolveFromMrUrl(mr, { privateToken: token, baseUrl: finalBaseUrl }); // MR URL 推导出的字段,仅在用户未显式覆盖时使用 resolvedId = resolvedId || info.projectName; resolvedSource = resolvedSource || info.sourceBranch; resolvedTarget = resolvedTarget || info.targetBranch; if (resolvedSourceProjectId === undefined && info.sourceProjectId !== undefined) { resolvedSourceProjectId = Number(info.sourceProjectId); } console.log(`🔗 已解析 MR: ${mr}`); console.log(` 项目: ${resolvedId},源分支: ${resolvedSource} -> 目标分支: ${resolvedTarget}`); } if (!resolvedId || !resolvedSource || !resolvedTarget) { console.error('❌ 缺少必要参数:--id <id>、--source <branch>、--target <branch>(或使用 --mr <url> 自动解析)'); process.exit(1); } // id 支持数字 ID 或项目全路径 const finalId = typeof resolvedId === 'string' && /^\d+$/.test(resolvedId) ? Number(resolvedId) : resolvedId; console.log(`🚀 正在合并: ${resolvedSource} -> ${resolvedTarget}`); console.log(` 项目: ${finalId},合并方式: ${mergeType}${commitMessage ? `,提交信息: ${commitMessage}` : ''}${resolvedSourceProjectId ? `,源项目 ID: ${resolvedSourceProjectId}` : ''}`); try { const res = await mergeBranches({ id: finalId, sourceObjectId: resolvedSource, targetBranch: resolvedTarget, mergeType, commitMessage, sourceProjectId: resolvedSourceProjectId, privateToken: token, baseUrl: finalBaseUrl, }); console.log('✅ 合并成功:', res); } catch (err) { const detail = err && err.response ? err.response.data : err; console.error('❌ 合并失败:', detail); process.exit(1); } } module.exports = { mergeBranchesCommand, resolveFromMrUrl, };