semantic-release GitLab发布扩展publish函数未执行,迁移笔记无法附加求助
问题分析与修复
核心问题
你在@semantic-release/gitlab的配置里定义的publish函数不会被执行——官方插件的配置项中没有这个参数,你的自定义代码根本没机会运行,官方只会调用内置的publish逻辑。
修复步骤
1. 拆分自定义逻辑为独立内联插件
把修改release notes的逻辑抽成单独的内联插件,放在@semantic-release/gitlab之前。利用semantic-release的publish阶段钩子,先修改好nextRelease.notes,再让gitlab插件基于修改后的内容发布。
2. 修正代码中的小bug
extractMigrationNotes的判断条件错误:原代码里if (migrationNotes)应该改为if (migrationSection),否则会把null值推入数组,导致迁移笔记内容异常。- 增加对merge request描述的空值判断,避免因接口返回异常导致报错。
修改后的完整配置
/** * @type {import('semantic-release').GlobalConfig} */ module.exports = { branches: ["main", "master", "+([0-9])?(.{+([0-9]),x}).x"], ci: false, plugins: [ [ "@semantic-release/commit-analyzer", { preset: "conventionalcommits", }, ], [ "@semantic-release/release-notes-generator", { preset: "conventionalcommits", }, ], [ "@semantic-release/changelog", { changelogFile: "CHANGELOG.md", changelogTitle: "# Changelog\n\nAll notable changes to this project will be documented in this file.", }, ], [ "@semantic-release/git", { assets: ["CHANGELOG.md"], message: "chore(release): version ${nextRelease.version}\n\n${nextRelease.notes}", }, ], // 收集迁移笔记的内联插件(analyzeCommits阶段) { analyzeCommits: async (pluginConfig, context) => { const { commits, logger } = context; const migrationNotes = []; logger.log( `Analyzing ${commits.length} commits for migration notes...` ); for (const commit of commits) { const subjectPattern = /Merge branch .* into 'main'/; const bodyPattern = /See merge request ([\w/-]+![0-9]+)/; if (subjectPattern.test(commit.subject)) { const bodyMatch = commit.body.match(bodyPattern); if (bodyMatch) { const mergeRequest = bodyMatch[1]; const response = await fetchMergeRequest(mergeRequest, logger); const migrationSection = extractMigrationNotes(response); // 修正判断条件:只添加非null的有效内容 if (migrationSection) { migrationNotes.push(migrationSection); } } } } if (migrationNotes.length > 0) { const joinedNotes = migrationNotes.join("\n\n"); logger.log("Collected migration notes: ", joinedNotes); context.migrationNotes = joinedNotes; } return null; }, ], // 新增:修改release notes的内联插件(publish阶段) { publish: async (pluginConfig, context) => { const { nextRelease, logger } = context; const { migrationNotes } = context; if (migrationNotes) { logger.log("Appending migration notes to release notes..."); nextRelease.notes += `\n\n---\n\n### Migration Notes\n\n${migrationNotes}`; } // 返回null不阻断后续插件执行 return null; }, ], // 官方gitlab插件,将使用修改后的nextRelease.notes创建发布 [ "@semantic-release/gitlab", { successComment: "This ${issue.pull_request ? 'PR is included' : 'issue has been resolved'} in version ${nextRelease.version} :tada:", labels: false, releasedLabels: false, assets: [{ path: "dist/*", label: "Distribution" }], }, ], ], }; // helper function to fetch merge request description from GitLab API async function fetchMergeRequest(input, logger) { const [project, mergeRequestId] = input.split("!"); const urlEncodedProject = encodeURIComponent(project); try { const response = await fetch( `${process.env.CI_API_V4_URL}/projects/${urlEncodedProject}/merge_requests/${mergeRequestId}`, { headers: { "PRIVATE-TOKEN": process.env.GITLAB_TOKEN, }, } ); const data = await response.json(); return data; } catch (error) { logger.log("Error fetching merge request description: ", error); return null; } } // helper function to extract migration notes from the MR description function extractMigrationNotes(mergeRequest) { if (!mergeRequest?.description) return null; const migrationNotesRegex = /## Migration Notes([\s\S]*?)(?=###|$)/; const match = mergeRequest.description.match(migrationNotesRegex); if (match) { return `#### ${mergeRequest.source_branch}\n${match[1].trim()}`; } return null; }
关键说明
- 新增的内联插件在
publish阶段优先执行,修改nextRelease.notes后,@semantic-release/gitlab插件会直接使用更新后的内容生成发布。 - 修正了迁移笔记收集环节的空值判断,避免无效内容混入最终发布。
- 插件顺序严格遵循semantic-release的阶段执行逻辑,确保上下文数据能正确传递。
内容的提问来源于stack exchange,提问作者Lizzal
相关产品推荐
相关产品推荐

