微信小程序的持续集成实践CICD&Jenkins

经过调研,目前有2种方式,一种是命令行工具HTTP的方式,另一种是2020年微信发布的miniprogram-ci工具。miniprogram-ci 从 1.0.28 开始支持第三方平台开发的上传和预览,也就是说1.0.28版本之后,就可以通过脚本来上传和预览小程序了。

以上2种具体使用方式如下:

1、使用微信开发者命令行工具

主要是用wechatwebdevtools.app的命令行工具来进行上传,Jenkinsfile实践如下:

// 添加CLI路径到环境变量
environment {
  WENXIN_CLI="/Applications/wechatwebdevtools.app/Contents/MacOS/cli"
}

然后上传的时候使用命令行工具上传,通过参数配置版本号和description。

steps {
  // https://www.w3cschool.cn/weixinapp/weixinapp-x46e2jbf.html (官方文档不 work 需要 V1 文档)
  sh "${WENXIN_CLI} -u ${params.VERSION}@${WORKSPACE}/dist --upload-desc \"${params.UPDATE_DESCRIPTION}\""
}

这种上传方式的缺点,开发者工具登录会过期,所以需要手动扫码登录,以下的Jenkinsfile是把登录的二维码打印在Build Description上。

pipeline {
   agent any
   environment {
    WENXIN_CLI="/Applications/wechatwebdevtools.app/Contents/MacOS/cli"
    INSTALL_MD="'Library/Application Support/微信开发者工具/${MD5哈希值}/Default/.ide'"
   }
   stages {
        stage('Clean ws and checkout') {
            steps {
                deleteDir()
                checkout scm
            }
        }
        stage('relogin devtools') {
            steps {
              script {
                sh "${WENXIN_CLI} -o"
                PORT = sh (
                            script: "cat ~/${INSTALL_MD}",
                            returnStdout: true
                          ).trim()
                        sh "curl http://127.0.0.1:${PORT}/login --output login_qrcode.png"
                        currentBuild.description = "<h2>登录二维码</h2><img src='${BUILD_URL}/execution/node/3/ws/login_qrcode.png' width='150' height='150'>"
                }
          }
        }
    }
}

INSTALL_MD是微信开发者工具启动端口号存的文件地址,网上很多资料都是直接获取~/Library/Application Support/微信开发者工具/Default/.ide里面的端口号,但是使用时发现这个端口号不是真正在运行的,所以加上了MD5的路径。

拿到端口之后就是通过curl http://127.0.0.1:${PORT}/login --output login_qrcode.png把登录图片保存到本地,然后再设置到build的description中。

注意:这里尝试过命令行工具获取base64的登录二维码,但是Jenkins的build的description无法显示base64的图片,所以就用了HTTP的方式获取登录二维码图片了。

以上这种方式还强依赖于微信开发者工具,目前又只能安装在Mac和windows上。

2、使用微信CI工具

微信miniprogram-ci目前提供以下能力:

  • 上传代码,对应小程序开发者工具的上传
  • 预览代码,对应小程序开发者工具的预览
  • 构建 npm,对应小程序开发者工具的: 菜单-工具-构建npm
  • 上传云开发云函数代码,对应小程序开发者工具的上传云函数能力
  • 代理,配置 miniprogram-ci 的网络请求代理方式
  • 支持获取最近上传版本的 sourceMap
  • 支持 node 脚本调用方式和 命令行 调用方式

这种方式更加轻量级,按照官方文档设置就能实现。但是在使用docker版的Jenkins集成微信CI的时候要注意以下内容:

  • 启动Jenkins docker之前要在微信公众平台上下载好上传代码所需的密钥,映射到容器里。上传的时候使用密钥和白名单设置来保证安全。


    image.png
  • Jenkins docker是Linux环境,需要安装nodeJs插件,并且在系统管理->全局工具配置 中加上nodeJS。


    image.png
  • 默认没有yarn,如果使用yarn 需要安装,例如上图中在global安装yarn。

开发版预览

开发版预览的Jenkinsfile如下

pipeline{
    agent any

    tools {nodejs "nodejs12"}

    triggers {
      pollSCM('H/2 * * * *')
    }

    options {
      timeout(time: 10, unit: 'MINUTES')
    }

    stages{
        stage("install"){
          steps{
            sh "npm install --no-optional"
          }
        }

        stage("build Dev") {
          steps {
            sh "npm run build:weapp"
          }
        }

        stage("Deploy QA") {
          steps {
            script{
              sh "APP_ID=XXXXXX PREVIEW_PATH=${pwd()} node scripts/upload-dev-package.js"
              currentBuild.description = "<h2>预览二维码</h2><img src='${BUILD_URL}/execution/node/3/ws/preview-dev.png' width='150' height='150'>"
            }
          }
        }
    }
}

upload-dev-package.js就是微信官网的配置内容,这里 主要是把APP_ID和preview二维码图片保存路径传进来。

const ci = require('miniprogram-ci')
;(async () => {
  const project = new ci.Project({
    appid: process.env.APP_ID,
    type: 'miniProgram',
    projectPath: process.env.PWD + "/dist",
    privateKeyPath: `../private.${process.env.APP_ID}.key`,
    ignores: ['node_modules/**/*']
  })
  const previewResult = await ci.preview({
    project,
    desc: '', // 此备注将显示在“小程序助手”开发版列表中
    setting: {
      es6: true,
    },
    robot: 1,
    qrcodeFormat: 'image',
    qrcodeOutputDest: process.env.PREVIEW_PATH + "/preview-dev.png",
    onProgressUpdate: console.log,
  })
  console.log(previewResult)
})()


最终效果如下:

image.png

上传体验版

到目前为止微信并没有一个接口可以指定某个上传版本为体验版,这个还需要在微信公众平台去配置是哪个robot上传的为体验版。
上传的脚本如下,也是把小程序的APP_ID、版本号、描述信息通过环境变量设置进来。

const ci = require('miniprogram-ci')
;(async () => {
  const project = new ci.Project({
    appid: process.env.APP_ID,
    type: 'miniProgram',
    projectPath: process.env.PWD + "/dist",
    privateKeyPath: `../private.${process.env.APP_ID}.key`,
    ignores: ['node_modules/**/*']
  })
  const uploadResult = await ci.upload({
    project,
    version: process.env.VERSION,
    desc: `描述:${process.env.DESCRIPTION}`,
    setting: {
      es6: true,
    },
    robot: 2,
    onProgressUpdate: console.log,
  })
  console.log(uploadResult)
})()

Jenkinsfile中通过参数配置构建的tag、版本号、描述

parameters {
  text(name: "TAG_NAME", defaultValue: '*/master', description: 'tag Required')
  text(name: "VERSION", defaultValue: '1.0', description: '版本号')
  text(name: "DESCRIPTION", defaultValue: '', description: '描述')
}

checkout到tag对应的版本

stage("checkout"){
   when {
     not {
      equals expected: "", actual: params.TAG_NAME
     }
  }
  steps{
    checkout([
      $class: 'GitSCM',
      branches: [[name: "${TAG_NAME}"]],
      doGenerateSubmoduleConfigurations: false,
      extensions: [],
      submoduleCfg: [],
      userRemoteConfigs:
      [[credentialsId: 'miniprogram', url: 'git地址']]
     ])
  }
}
.
.
.
stage("Deploy QA") {
  steps {
    sh " APP_ID=XXXX VERSION=$params.VERSION DESCRIPTION=$params.DESCRIPTION node scripts/upload-package.js"
   }
}

上传后能够看到体验版已更新。
最终效果图如下:


image.png

以上,开发者可以自己设置版本的描述信息,但是提交者只能看到ci机器人XX提交,微信暂不提供修改提交的机器人名称。目前能够使用的机器有30个,也就是可以指定1~30的机器人。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,080评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,422评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,630评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,554评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,662评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,856评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,014评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,752评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,212评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,541评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,687评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,347评论 4 331
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,973评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,777评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,006评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,406评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,576评论 2 349