cz-customizable 配置还不够灵活?小改源码试试!

1,124 阅读4分钟

一句话概括: 改造 cz-customizable ,使 commit message 的配置更加个性化。

前言

多人协作开发时,也许会有 commit message 格式规范的要求。
git + commitize + cz-customizable 可以帮助我们实现规范化的 commit message。

本文主要记录笔者在适配 cz-customizable 时遇到的问题、解决思路 及 操作步骤。

抛砖引玉,希望能给遇到相似问题的朋友一点参考或启发。

cz-customizable 的局限性

下文是 commitize 和 cz-customizable 的简单介绍,熟悉的朋友可以跳过。

commitize 是一个辅助提交 commit message 的工具。
通过开发人员与CLI的交互,生成并提交一条格式化的 commit message。  

而 cz-customizable 是 commitize 的适配器。
通过读取文件 cz-config.js 实现一定程度上的配置调整,比如跳过scope的填写、自定义题目等等。

但使用 cz-customizable 也有局限性,如 不支持添加新题目、无法添加变量输入。这种局限性,源于官网文档 cz-config.js 不提供相关参数的配置。笔者正在做的(麻花要求 commit message )项目,也是如此。

以下问题清单,由局限性而生。

问题清单

下列为笔者遇到的问题清单,其中问题1和2建议按顺序阅读:

1. 如何新增一个自定义变量并给出输入提示?
2. 如何自定义message.header的格式?
3. 如何集成到项目中?并实现源码最小改动?(待更新)

本文默认您已使用过cz-customizable,或者看过readme操作文档。

1. 如何新增一个自定义变量并给出输入提示?

本文以存储变量issueId为例,预期的输入提示question为"Write the connnected issueId of this change (required):"

思路:观察 message 如何生成 -> 查看对应源码

1.观察 message 如何生成:
message 是字符串,由用户输入项按约定格式拼接而成。
CLI 执行命令 cz-customizable 后,会弹出提示文字question,并将用户输入项(一般为字符串)存储到 question 指定的变量中,再按一定规则将这些变量组织成我们最终想要的 commit message 格式。

2.查看源码
cz-customizable 源码 index.js,给了我们questions的定义路径。

// index.js
const questions = require('./lib/questions').getQuestions(config, cz);

进入源码 questions.js 看 getQuestions 函数,能提炼出以下信息:

getQuestions 给开发者提供了CLI输出 questions 的调整机会,如:
题目说明自定义、选项自定义、跳过指定题目 等。

questions 调整需要同步更改配置文档 cz-config.js 。

也就是说,要存储issueId,需要同时改动 questions.js 和 cz-config.js。

回到 getQuestions 函数,变量 questions 是 getQuestions 的内部变量,笔者想到两个方案改动 questions :

一、直接在函数内部往数组变量 questions 插入新对象。
二、question 支持从 config 配置获取。

操作步骤

为了快速验证答案,本次选了方案一,下方为伪代码:

// 数组变量 questions 插入此对象
{
    type: 'input',

    name: 'issueId',

    message: messages.issueId,

    default: null,

    validate(value) {

        const limit = config.issueIdLimitRange || [0, 10];

        if (value.length > limit[1] || value.length < limit[0]) {

            return `Exceed limit range: [${limit[0]}, ${limit[0]}]`;

        }

        const reg = new RegExp(/^\d+$/);

        if(!reg.test(value)) {

            return '只允许输入数字'

        }

    return true;

    }

}

// cz-config.js - message对象添加属性:

messages: {

    issueId:"\nWrite the connnected issueId of this change (required):",

    // ...

}

至此,添加完毕。
CLI运行 cz-customizable,第一个即是我们为issueId自定义的题目。效果如图:

20221231-224933.jpeg

补充:

数组变量 questions 的数据结构遵循 inquirer 插件的 questions 结构。

插件 inquirer,与命令行交互的工具(A collection of common interactive command line user interfaces)。

迁移性也不错,支持多平台

20221231-225130.jpeg

2.如何自定义message.header的格式?

下表列出了 messsage.header 的两种格式,表体第一行为官网支持格式,第二行为自定义格式(在第一行的基础上改动,添加了 issueId,删除了 scope )。

格式对比举例
<type>(<scope>):<subject>refactor(视图调整):代码更改,既不修复错误也不添加功能
[issueId]<type>:<subject>[14653]refactor:代码更改,既不修复错误也不添加功能

有了问题1(question.js新增issueId输入)的铺垫,问题2要实现起来并不困难。

直接上落地方案:
build-commit.js 添加 addissueId 函数


// build-commit.js

const addissueId = (id, config) => {

const prefix = _.get(config, 'idPrefix', '[');

const suffix = _.get(config, 'idSuffix', ']');

return _.trim(`${prefix}${id}${suffix}`);

};

const head =

addissueId(answers.issueId, config) + // add

addType(answers.type, config) +

addScope(answers.scope, config) +

addTicketNumber(answers.ticketNumber, config) +

addSubject(answers.subject.slice(0, config.subjectLimit));

CLI执行,最终生成了预期的 message 格式,输出结果一览:

[655544]feat: ff2
飞书20230101-204006.jpg

这里 type 删除了前后缀,是因为改造了 addType 。
header其他部分的格式改造大抵如此(如 addScope|addTicketNumber|addSubject )。


const addType = (type, config) => {

const prefix = _.get(config, 'typePrefix', '');

const suffix = _.get(config, 'typeSuffix', '');

/* 删除前后缀 */

// return _.trim(`${prefix}${type}${suffix}`);

return _.trim(`${type}`);

};

3. 如何集成到项目中?

笔者通过打源码补丁包的方式,将改动集成到项目中。

先说明为什么要改源码:

如果涉及问题12,即官网 cz-config.js 不支持的参数配置。
那么我们必须改动 question.js 和 build-commit.js 。

至此问题转换成如下两个:

一、如何获取稳定版本的源码。   
二、如何生成源码补丁。

当然也可以直接把源码拷贝出来,放到项目下,当做项目代码的一部分,此方法的操作步骤没什么好说的。

回到问题一二。

一、如何获取稳定版本的源码?

很简单,package.json的版本号固定即可,参考官网版本号约定规范。如有必要也可以提交package-lock.json。

二、如何生成源码补丁?

本次使用插件 patch-package,github地址

CLI运行命令 npx patch-package cz-customizable,项目根目录下的patches目录中创建一个名为package-name+version.patch的文件

执行成功的结果如下图:

img_v2_dda79397-78ad-4968-b800-fdc1258d802g.jpg

验证补丁包能否生效:

验证思路:
项目移除依赖 cz-customizable -> 重装依赖包和补丁包 -> CLI执行 cz-customizable 验证是否成功

1.项目移除依赖 cz-customizable:

npm uninstall cz-customizable

2.重装依赖包和补丁包:

CLI 执行命令 npm i 之前,先配置package.json


"devDependencies": {

+ "cz-customizable": "7.0.0"

},

"scripts": {

+ "postinstall": "patch-package"

}

提交代码本来就是开发干的事儿,因此只加到 devDependencies

postinstall - 是运行命令 npm install 期间要附加执行的命令,命令组合规则为 +script (本例 post + install ),postinstall 在安装软件包后运行。更多 npm 支持 package.json 文件的“scripts”属性规则参考文档

CLI 执行命令 npm i ,下图可看到 cz-customizable 安装成功。

img_v2_79e1b6ad-054d-4f72-9b51-f84178b6b83g.jpg 3.CLI执行 cz-customizable

顺利的话,弹出了我们关于 issueId 的提示(回顾问题二)

img_v2_8bad4041-7d02-43a2-a5d4-8735a83c9e4g.jpg