背景
上周自己项目组成功使用 gitlab CICD 自动化发版流程,领导叫我复制到其他四个项目组的十几个项目中,相对复制粘贴,是个尝试写工具的好机会。
需求分析
流程分为 runner 和 yml 脚本两部分,runner 已经使用 shared-runner 解决,我的实际需求是能够根据不同配置生成yml脚本的cli工具。
两个概念 + 两个核心依赖 = 自定义cli
概念 bin
package.json 文件中的 bin,指的是如果package中包含希望添加到PATH中的可执行命令,可以提供 bin 来实现映射,本地安装时会安装到项目的 ./node_modules/.bin/,全局会安装在prefix/bin。
这也是为什么像下面这种常见的命令,只可以在命令行里敲 npm run dev,而不能敲 vue-cli-service serve --mode development。因为前者实际对应的是 ./node_modules/.bin/vue-cli-service serve --mode development
"scripts": {
"dev": "vue-cli-service serve --mode development",
}
顺带一提可以不用在意的另一个概念
#!/usr/bin/env node 是 shebang 的一个实例:类 Unix 平台上可执行纯文本文件中的第一行,它通过命令告诉系统将该文件传递给哪个解释器执行。简单来说,他帮助文件找到正确的执行器。
核心依赖
首先是 commander。
号称完整命令行解决方案,通过更简单的方式,定义-V,-help等命令
var program = require('commander');
program
.version(`${require('../package').version}`, '-v, --version')
.command('create') // 声明create命令
.alias('c') // 声明create命令的别名
.description('根据模版创建.gitlab-ci.yml') // --help时显示的描述内容
.action(() => {}) // 实际执行操作
action(() => {})回调的部分,则需要 inquirer。
var inquirer = require('inquirer');
inquirer
.prompt([
// 问题列表
])
.then((answers) => {
// 使用收集的选项来做操作
})
.catch((error) => {
});
比如我的问题列表包括:
// input类型的输入,其中name表示 .then((answers) => {})里answers的字段
{
type:'input',
message:'oss地址',
name:'ossURL'
},
// 选择 y/n confirm
{
type:'confirm',
message:'是否需要把结果通知到企业微信(需要企微机器人的webhook key)?',
name:'notifyNeed',
},
// 等等
总的来说,这三步走,实现一个自定义cli。
graph TD
bin字段实现可执行命令 --> commander实现自定命令 --> inquirer实现收集用户配置