You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 12:15:16