自定义 Release Note 格式

Modern.js 提供了 modern gen-release-note 命令,支持通过当前存在的 changeset 和 git commit 信息自动生成 Release Note 信息,在发布命令执行之前,可以通过执行该命令生成本次发布的 Release Note。

默认生成的 Release Note 格式为:

- fix: add missing type definitions by @zllkjc in https://github.com/web-infra-dev/modern.js/pull/3835

根据 commit 信息获取 changeset 的 Pull Request ID,并生成 Github 的链接,内容为 changeset 的 changelog 信息和作者信息。

INFO

获取作者信息,需要提供 Github Token 环境变量,通过 GITHUB_AUTH_TOKEN 传入。

当默认生成 Release Note 逻辑不能满足需求时,支持自定义 Release Note 格式。

信息

getReleaseInfo

生成 Release Note 信息需要先收集一些信息,比如 commit ID、Pull Request ID、commit message 等等。

该逻辑可通过 getReleaseInfo 函数实现。

Params

  • commit

类型: string;

当前 changeset 对应的 commit message 信息。

执行 git log --pretty=format:%h--%s--%ae .changeset/${changeset.id}.md 的结果。

  • commitObj

初步解析 commit 获取基本信息。

export enum CommitType {
  Performance = 'performance',
  Features = 'features',
  BugFix = 'bugFix',
  Doc = 'doc',
  Other = 'other',
}

interface Commit {
  id: string; // commit id
  type: CommitType;
  repository?: string; // 参数传入的 repo 信息或者 package.json 中定义的 repository 信息
  pullRequestId?: string;
  author?: string;
  message: string; // commit message
  summary: string; // changeset summary
  summary_zh: string; // changeset zh summary
  [key: string]: string | undefined;
}

返回值

commitObj, 补充后完整的 commit 对象。

默认实现

Modern.js 的默认实现为:根据 commit 信息拆分出 Pull Request ID,并根据 commit id 获取到用户信息,加入到 commitObj 中。

function getReleaseInfo(commit: string, commitObj: Commit) {
  const commitRegex = /(.*)\(#(\d*)\)/;

  const [commitId, message, email] = commit.split('--');

  const author = AuthorMap.get(email);
  const token = authToken || process.env.GITHUB_AUTH_TOKEN;
  if (author) {
    commitObj.author = author;
  } else if (repo && token) {
    try {
      const res = await axios.get(
        `https://api.github.com/repos/${repo}/commits/${commitId}`,
        {
          method: 'GET',
          headers: {
            'Content-Type': 'application/json',
            Authorization: token,
          },
        },
      );
      const author = res.data.author.login;
      commitObj.author = author;
      AuthorMap.set(email, author);
    } catch (e) {
      console.warn(e);
    }
  }

  if ((message || commitObj.summary).match(commitRegex)) {
    const [, messageShort, pullRequestId] = (
      message || commitObj.summary
    ).match(commitRegex)!;
    commitObj.pullRequestId = pullRequestId;
    commitObj.message = messageShort.trim();
  }

  return commitObj;
}

getReleaseNoteLine

根据 getReleaseInfo 中获取的 commit 对象信息,生成对应的 Release Note。

该逻辑可通过 getReleaseNoteLine 函数实现。

Params

  • commit

类型和上述 commitObj 类型一致。

  • lang

类型: string;

获取对应语言的 Release Note 信息,支持 enzh,默认为 en

返回值

生成的 Release Note。

默认实现

Modern.js 的默认实现为:

export function getReleaseNoteLine(
  commit: Commit,
  lang: 'en' | 'zh' = 'en',
) {
  const { repository, pullRequestId, summary, summary_zh, author } = commit;
  const pullRequest =
    pullRequestId && repository
      ? `https://github.com/${repository}/pull/${pullRequestId}`
      : '';
  if (lang === 'en') {
    return `- ${summary}${author ? ` by @${author}` : ''}${
      pullRequest ? ` in ${pullRequest}` : ''
    }\n`;
  }
  return `- ${summary_zh}${author ? ` 由 @${author} 实现` : ''}${
    pullRequest ? `, 详情可查看 ${pullRequest}` : ''
  }\n`;
}

使用自定义模块

gen-release-note 命令支持 --custom 参数,该参数可传入自定义 Release Note 模块的模块名称或者路径。

配置相对路径

custom 参数值如果为相对路径为项目跟目录

例如创建 scripts/my-release-note-config.js 文件,定义如下内容:

scripts/my-release-note-config.js
function getReleaseInfo(commit, commitObj) {
  return commitObj;
}

function getReleaseNoteLine(commit) {}

module.exports = {
  getReleaseInfo,
  getReleaseNoteLine,
};

执行下面命令:

pnpm run gen-release-note --custom ./scripts/my-release-note-config.js

也可以把命令参数直接定义到 package.json 中:

package.json
{
    "scripts": {
        ...
        "gen-release-note": "modern gen-release-note --custom ./scripts/my-release-note-config.js"
    },
    ...
}

直接执行命令 pnpm run gen-release-note 即可。

使用 Modern.js Module

custom 参数值还可以使用 Modern.js Module 进行管理,提供通用方案。

使用 npx @modern-js/create@latest 创建 Modern.js Module

? 请选择你想创建的工程类型:Npm 模块
? 请填写项目名称:custom-release-note
? 请选择开发语言:TS
? 请选择包管理工具:pnpm

实现自定义内容

src/index.ts
export function getReleaseInfo() {}

export function getReleaseNoteLine() {}

将模块发布到 NPM

在目标仓库根目录安装对应模块,例如 custom-release-note

执行 gen-release-note 命令添加 custom 参数

pnpm run gen-release-note --custom custom-release-note

使用 Monorepo 工程方案

如果你当前仓库为 Monorepo 工程方案,可以直接使用模块子项目进行管理。

执行 pnpm run new 创建模块子项目

? 请选择你想创建的工程类型:Npm 模块
? 请填写子项目名称:custom-release-note
? 请填写子项目目录名称:custom-release-note
? 请选择开发语言:TS

实现自定义内容

src/index.ts
export function getReleaseInfo() {}

export function getReleaseNoteLine() {}

在 Monorepo 根目录添加子项目模块依赖,例如 custom-release-note

package.json
{
  "devDependencies": {
    "custom-release-note": "workspace:*",
    ...
  }
}

执行 gen-release-note 命令添加 --custom 参数

pnpm run gen-release-note --custom custom-release-note

该模块发布到 NPM 后,依然可以和模块类型一样供其他仓库使用。