• 基于miniprogram-ci的微信小程序的CI以及接入钉钉通知


    一、背景

    在开发微信小程序的时候每次上传小程序都要去打开编辑器,点击上传,输入版本号和版本描述,但是有时候产品还是会问这个版本升级的功能是什么,然后把二维码再发过去。虽然说这不是一个工作量很大的活,但是如果这个时候你在思考其他的东西,这种打断思路的问题还是很让人抓狂。

    二、痛点

    1. 每次上传都要打开编辑器进行操作
    2. 缺少版本更新日志
    3. 通知到相关人员

    三、解决方案

    • 基于release-it 自动提升版本号,自动打tag标签以及CHANGELOG版本日志
    • 基于微信的miniprogram-ci进行自动上传
    • 基于钉钉的群聊机器人将版本日志以及二维码通知给相关人员

    四、方案操作

    记得准备一个小程序项目先, 我的项目是基于uniapp的,不过编译之后都是一样的

    a、自动升级版本号和版本日志

    安装release-itnpm i @release-it/conventional-changelog -D
    npm init release-it
    会让你选择生成单独的.release-it.json配置文件还是在package.json中进行配置,选择单独的配置文件即可。

    如果没有生成单独的文件,自己新建一个就行

    // package.json
    "scripts": {
        ......
        "release": "release-it"
      },
    
    • 1
    • 2
    • 3
    • 4
    • 5

    npm i @release-it/conventional-changelog -D

    @release-it/conventional-changelog配置项

    新建一个CHANGELOG.md文件作为版本更新日志

    // .release-it.json
    {
      "github": {
        "release": false
      },
      "git": {
        "commitMessage": "release: v${version}"
      },
      "npm": {
        "publish": false
      },
      "hooks": {
        "after:bump": "echo 更新版本成功"
      },
      "plugins": {
        "@release-it/conventional-changelog": {
          // 这里用的是angular的提交规范
          "preset": "angular",
          // 这里的文件就是刚才新建的版本日志文件
          "infile": "CHANGELOG.md"
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    b、配置miniprogram-ci环境

    miniprogram-ci
    在微信公众平台的开发设置中将代码上传密钥下载下来,白名单看情况设置
    在这里插入图片描述
    目录结构
    在这里插入图片描述
    这里的upload.js是等会写的重点

    //upload.js
    const ci = require('miniprogram-ci')
    
    const { green, bold, red } = require('kolorist'); //在控制台输出高亮提示的插件
    
    // 终端显示信息
    const step = (msg) => console.log(bold(green(`[step] ${msg}`)));
    const stepErr = (msg) => console.log(bold(red(`[error] ${msg}`)));
    
    //获取版本号
    let { version } = require('./package.json')
    
    version = 'V' + version
    
    // 这个等下会优化
    desc='上传版本描述'
    
    if (!version) version = 'v1.0.0'
    
    // 项目对象   更多配置可以去官网看
    const project = new ci.Project({
      appid: '你自己的appid',
      type: 'miniProgram',
      // 项目路径
      projectPath: process.cwd() + '/dist/dev/mp-weixin',
      privateKeyPath: process.cwd() + '/key/private.你自己的appid.key',
      ignores: ['node_modules/**/*','key/**/*'],
    })
    
    
    // 上传模式
    async function upload(desc){
      try {
        const result = await ci.upload({
          robot: 3,
          project,
          version,
          desc,
          setting: {
              minify: true,
          },
        })
        step('上传成功')
        step(JSON.stringify(result) )
      } catch (error) {
        stepErr(JSON.stringify(error)) 
      }
    
    }
    // 预览模式
    async function preview(desc){
      try {
        const result = await ci.preview({
          project,
          desc, // 此备注将显示在“小程序助手”开发版列表中
          setting: {
            es6: true,
          },
          qrcodeFormat: 'image',
          qrcodeOutputDest: process.cwd() + '/key/preview.jpg',
          onProgressUpdate: console.log,
          pagePath: 'pages/index/index', // 预览页面
          // searchQuery: 'a=1&b=2',  // 预览参数 [注意!]这里的`&`字符在命令行中应写成转义字符`\&`
        })
        step('预览成功')
        step(JSON.stringify(result) )
      } catch (error) {
        stepErr(JSON.stringify(error)) 
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70

    写到现在还是有两个小问题需要封装一下
    1、版本描述不能写死,每次上传的时候需要输入
    2、预览模式还是上传模式需要用户选择
    方案:使用enquirer让用户在控制台进行选择和输入
    npm i enquirer

    // upload.js
    const { prompt, AutoComplete  } = require('enquirer')
    
    // 发布模式   上传 or 预览
    const relaseMode = new AutoComplete({
      name: 'flavor',
      message: '请选择发布方式',
      choices: [
        '预览',
        '上传'
      ]
    });
    
    // 获取版本描述
    async function getVersionDesc(){
      const { desc } = await prompt({
                        type: 'input',
                        name: 'desc',
                        message: `请输入${version}版本描述`,
                        // default:new Date() + '上传'
                      })
      if(!desc) desc = new Date() + '上传'    
      step(desc)           
      return desc
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    这样我们就可以拿到用户的输入了,之后再进行对应的逻辑编码
    OK,到现在我们自动打版本号以及更新CHANGE.LOG文件了
    package.json中添加一条命令,执行upload.js文件

    // package.json
    "scripts": {
       "upload-wx": "node upload.js",
       ...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    主要的痛点问题到这里就告一段落了
    具体操作流程:

    1. 修改文件,并且commit,(注意这里的提交格式,我的配置是angular格式),这个时候注意不要push代码
    2. 执行npm run release,这时你可以填版本号(默认是递增的)、tag和push代码
    3. 指定npm run upload-wx 执行编写的upload.js文件

    在这里插入图片描述
    上传之后小程序后台显示
    在这里插入图片描述

    c、接入钉钉群聊机器人

    新建机器人
    在这里插入图片描述
    在这里插入图片描述
    选择自定义机器人
    在这里插入图片描述
    这里安全设置自己选择就行
    在这里插入图片描述
    添加成功之后会有一个webhook链接
    在这里插入图片描述
    下面在upload.js编写通知逻辑

    // upload.js
    // 钉钉群聊机器人文档   https://open.dingtalk.com/document/group/message-types-supported-by-enterprise-internal-robots
    // 发送变动日志到钉钉   发送的内容要包含你设置的关键词才行
    function sendChangLogToDingDing(){
      // 机器人webhook
      const url = '群聊机器人的webhook链接'
      // 读取版本更新日志
      const data = fs.readFileSync('./CHANGELOG.md', 'utf8')
      // 请求参数配置
      const options = 
      {
        headers: {
        "Content-Type": "application/json;charset=utf-8"
        },
        // markdown 消息类型
        json: {
          "msgtype": "markdown", 
          "markdown": {
            "title":"更新日志",
            "text": '小趴菜'+data
          }, 
          "at": {
            "atMobiles":  [] ,
            "isAtAll": false
          }
        },
    
        // 文本消息类型
        // json: {
        //   "msgtype": "text", 
        //   "text": {
        //     "content": '小趴菜'+data
        //   }, 
        //   "at": {
        //     "atMobiles":  [] ,
        //     "isAtAll": false
        //   }
        // }
      };
      req.post(url, options, function(error, response, body){
        console.log(`response: ${JSON.stringify(body)}`);
        if(error){
          stepErr('通知异常')
        }
        if(response.statusCode === 200){
          step('钉钉通知已发送,请注意查收')
        }
      });
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    在这里插入图片描述

    最后再组织一下流程就OK了

    //upload.js
    submit()
    // 提交上传
    async function submit(){
      try {
        const release = await relaseMode.run()
        const desc = await getVersionDesc()
        return
        if(release === '上传'){
          await upload(desc)
        }else{
          await preview(desc)
        }
        sendChangLogToDingDing()
        
      } catch (error) {
        stepErr(error)
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    这里还有一个优化点,就是不论是上传还是预览都会通知成版本变更日志的形式,实际上预览模式的话我们只需要将预览的二维码通知到群里就行了,所以这个实际上就是根据用户选择的上传还是预览的结果改变通知的内容,
    实现起来比较简单,自己去试试吧

  • 相关阅读:
    Shiro之基本使用
    MySQL——锁
    SpringMvc进阶
    基于Web的酒店客房管理系统的设计与实现(Java+SSM+MySQL)
    读书笔记-Java并发编程的艺术-3.1
    物联网浏览器(IoTBrowser)-整合机器学习yolo框架实现车牌识别
    S7-1200PLC红灯闪烁报警,提示“硬件组件已移除或缺失”的原因分析
    关于.NET 6.0 Crossgen2的一些研究
    在 UltraEdit 和 UEStudio 中开始使用 Perl 正则表达式
    bash关闭按tab两次才显示关闭按tab显示隐藏文件
  • 原文地址:https://blog.csdn.net/A_bad_boy_hahaha/article/details/126033326