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

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

作者: 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