美文网首页
小程序-自动生成二维码-自动打码

小程序-自动生成二维码-自动打码

作者: kyle背背要转运 | 来源:发表于2018-07-05 20:54 被阅读0次

    目前公司小程序 是随M/pc/app一样正常版本迭代。开发小程序的流程也更加规范,人员也越多
    每次 QA 或者PM 在 钉钉群里 @前端 “给我生成个 开发版的小程序二维码”,让前端很麻烦,要停止开发 切分支编译,还要耗时。
    因此有了这个自动打码的需求

    先上图

    编译完给个链接
    jenkins上的配置

    为什么要自动打码?

    1 . 避免打包编译结果不一致(win/mac/node版本/本地代码不是最新等等)

    1. 避免可互相覆盖的问题,没有统一版本
    2. QA/PM 不能自主控制 ,老是要等FE给我弄,你总不能让每个QA也安装开发者工具然后配环境吧。。
    3. 写代码写bug写开森呢,让我给你打码!?
    4. 编码一次半分钟,一会就要切换编译一次,累死了。。。
    5. ....等等问题

    前期准备

    1. 翻了微信官方API,使用cli命令
      https://developers.weixin.qq.com/miniprogram/dev/devtools/cli.html
    2. 找一台mac 安装上微信开发者工具,配置好项目,把【project.config.json】配置好
    3. jenkins 配置好git项目,gitlab 上配置好基于事件的webhook,
    4. 这样 只要合并过 指定分支,就能触发jenkins编译啦

    编译流程如下:

    1. QA 点击 jenkins 立即构建 或者 webhook触发编译
    2. 执行编译脚本,我们使用了 wepy ,需要先 npm run build
    3. 使用cli -p 判断是否需要登录
    4. 未登录 的情况 ,需要使用 cli -l 执行登录,扫码
    5. 登录情况下,直接生成二维码
    6. 然后使用钉钉 机器人这个东东,在群里反馈下
    7. curl 发一个请求给钉钉机器人就完事儿啦

    说明

    1. 如果是本地跑的话,不用这么麻烦,照着https://developers.weixin.qq.com/miniprogram/dev/devtools/cli.html一步步走下去就行了
    2. 主要是因为jenkins不会展示 微信这个cli回调里面的图片,要不不会这么复杂
    3. 钉钉机器人里面的图片地址都要外网能解析的,所以我们选择了Link模式
    4. 下面的源码是没有放到 sy-cli 里面的,接下来会放到 sy-cli里面做统一维护
    5. 下面的源码没有经过测试,只是mac可以用嗷。。
    6. wepy部分可以看 <<迷死氧身后的男人,踩坑小程序开发>> 这篇文章
    7. 其实做过jenkins做编译的都了解,就是个持续集成的思想。
      把编译工作收敛,放在一个地方编译,减少上面那些问题,我司所有前端项目都在jenkins上编译啦

    遇到问题

    1.jenkins的编译机,必须要先配置好 微信开发者工具 和 开发者工具里面的项目,还有一堆配置。简单说就是不通过微信的cli 是个正常开发环境。

    1. 微信的cli 生成二维码没有回调,只有扫码成功和扫码失败的回调,所以写了先删除目录,再setTimeout去发钉钉消息
    2. 微信的cli 不会生成目录,要自己mkdir
    3. jenkins拿 微信的cli 二维码回调,不会显示图片,所以才另存图片发送
    4. jenkins上的图片,没有对外网解析,钉钉是拿不到的
    5. 必须要先编译,再预览/登录,才行,要不不能保证每次生成的代码都是最新
    6. jenkins的打包机器为 物理mac机器,所以不能在内部gitlab 使用webhook触发,需要主动触发
    7. dist目录里面要有 project.config.json,wepy 1.7.0之前要手工生成下,1.7.0以后不需要,详见 wepy传送门

    简化版本

    使用 https://github.com/soyoung616/sy-cli

    
    // 在你的项目中
    npm install sy-cli -D
    // 新建 sy-cli-qr.json
    // 修改package.json的scripts
    
    // package.json
    
    ...
    "scripts": {
        "dev": "wepy build --watch",
        "build": "cross-env NODE_ENV=production wepy build --no-cache",
        "test": "echo \"Error: no test specified\" && exit 1",
        "qr": "sy-cli qr \"./sy-cli-qr.json\""
      },
    ...
    
    // sy-cli-qr.json
    
    {
     "path":{
    // mac上的cli路径都一样
       "cli":"/Applications/wechatwebdevtools.app/Contents/Resources/app.nw/bin/cli",
    // wepy生成后的路径
       "wx":"./dist"
     },
     "source":{
    // wepy的编译
       "scripts":"npm run build"
     },
    // jenkins的工作空间里面
     "jenkinsURL":"http://XXXX/job/XXXX/ws/XXXX/",
    // 钉钉机器人的token
     "dingtalkToken":"XXXX"
    }
    
    
    

    源码:

    1. 新建 sy-cli-qr.json 和qr.js,跟package.json平级
    2. 把sy-cli-qr.json里面的值替换掉
    3. node qr.js 或者 npm run qr
    //qr.js
    
    const shell = require('shelljs')
    const path = require('path')
    const config = require('./sy-cli-qr.json')
    const cli = config.path.cli
    const distProject = path.resolve(__dirname, config.path.wx)
    const sourceProject = path.resolve(__dirname)
    const sourceScripts = config.source.scripts
    const dingtalkToken = config.dingtalkToken
    const jenkinsURL = config.jenkinsURL
    
    const QR = {
      picLogin: 'QR/login.png',
      picPreview: 'QR/preview.png',
      login() {
        let _this = this
        let _time = Date.parse(new Date())
        shell.rm('-rf','QR')
        shell.mkdir('QR')
        shell.exec(`${cli} -l --login-qr-output image@${path.resolve(__dirname, _this.picLogin)}`, (code, stdout, stderr) => {
          if (stdout.indexOf('login success') > -1) {
            _this.createQR()
          }
        })
        setTimeout(() => {
          let _txt = `小程序编译,请扫码登录,${_this.toDate(new Date())}`
          shell.exec(`curl 'https://oapi.dingtalk.com/robot/send?access_token=${dingtalkToken}' \
          -H 'Content-Type: application/json' \
          -d '
         {"msgtype": "actionCard",
           "actionCard": {
              "text": "${_txt}",
              "title": "${_txt}",
              "hideAvatar": "0",
              "btnOrientation": "1",
              "btns": [
                  {
                      "title": "扫码登录",
                      "actionURL": "${jenkinsURL}${_this.picLogin}?t=${_time}"
                  }
              ]
            }
         }'`)
        }, 2000)
      },
      createQR() {
        let _this = this
        let _time = Date.parse(new Date())
        shell.rm('-rf','QR')
        shell.mkdir('QR')
        shell.exec(`${cli} -p ${distProject} --preview-qr-output image@${path.resolve(__dirname, _this.picPreview)}`, (code, stdout, stderr) => {
          if (stderr.indexOf('需要重新登录') > -1) {
            _this.login()
          } else {
            let _txt = `小程序编译成功,请扫码查看,${_this.toDate(new Date())}`
            shell.exec(`curl 'https://oapi.dingtalk.com/robot/send?access_token=${dingtalkToken}' \
        -H 'Content-Type: application/json' \
        -d '
       {"msgtype": "actionCard",
         "actionCard": {
          "text": "${_txt}",
          "title": "${_txt}",
          "hideAvatar": "0",
          "btnOrientation": "1",
          "btns": [
              {
                  "title": "扫码查看",
                  "actionURL": "${jenkinsURL}${_this.picPreview}?t=${_time}"
              }
          ]
          }
       }'`)
          }
        })
      },
      build() {
        return new Promise((resolve, reject) => {
          shell.cd(`${sourceProject}`)
          shell.exec(`${sourceScripts}`, (code, stdout, stderr) => {
            if (code) {
              reject(stderr)
            } else {
              resolve(1)
            }
          })
        })
      },
      async init() {
        let _this = this
        let _build = await _this.build().catch((err) => {
          console.log(err)
          console.log('编译失败')
          process.exit(1)
        })
        if (_build) {
          _this.createQR()
        }
      },
      toDate (timeStamp, getMilliseconds) {
        let date = new Date(timeStamp)
        let time = [
          date.getFullYear(),
          date.getMonth() + 1,
          date.getDate(),
          date.getHours(),
          date.getMinutes(),
          date.getSeconds()
        ]
    
        getMilliseconds && time.push(date.getMilliseconds())
    
        for (var i = 0; i < time.length; i++) {
          var val = time[i]
          if (val <= 9) {
            time[i] = '0' + val
          }
        }
        if (getMilliseconds) {
          time = time.slice(0, 3).join('-') + ' ' + time.slice(3, time.length).join(':')
        } else {
          time = time.slice(0, 3).join('-') + ' ' + time.slice(3, 6).join(':')
        }
        return time
      }
    }
    
    QR.init()
    
    
    
    // package.json
    
    ...
    "scripts": {
        "dev": "wepy build --watch",
        "build": "cross-env NODE_ENV=production wepy build --no-cache",
        "test": "echo \"Error: no test specified\" && exit 1",
        "qr": "node qr.js"
      },
    ...
    

    相关文章

      网友评论

          本文标题:小程序-自动生成二维码-自动打码

          本文链接:https://www.haomeiwen.com/subject/qaypuftx.html