通过自定cli给多个项目添加yml脚本的经验分享

472 阅读2分钟

背景

上周自己项目组成功使用 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实现收集用户配置

最终结果已经发布在npm,源码在github,如果帮助到你,求个star(图穷匕见)