1. 授权认证
  2. 获取用户个人信息
  3. 项目协同
  4. 代码托管
  5. 持续集成
  6. 制品仓库
  7. 测试管理
  1. 项目协同
  2. 代码仓库
  3. DevOps 实践之旅
  4. 一分钟开始持续集成之旅
  5. 持续部署
  6. 制品库

基于 CI 实现微信小程序的持续构建

做为一个前端开发,在开发微信小程序的时候,我们应该都遇到过这样的场景:

我们双手正在在键盘上飞舞,像写诗一样认真的编写每一行代码,脑海里想着解耦合、设计模式、抽象和分层的时候。突然之间,

产品经理轻轻拍了拍了你肩膀,假装满怀歉意的跟你说:“我需要一个最新测试环境的体验二维码“

于是你端起了印着“和气生财”的马克杯,喝了口水,开始了一波操作

1. git stash
2. git checkout branch
3. npm install
4. npm build
5. 点击“预览”,生成二维码,发送给对方

搞定后,你活动了一下有些许酸疼的手指,切回分支恢复进度,脑海里努力得回忆着刚刚得思路。

这时,测试工程师突然又找你,他也想要一个测试环境的二维码,这时候你又看了看一眼你的马克杯,黯然神伤…

概括

本文将借助于 CODING 的持续集成,手把手带你实现一个微信小程序的持续集成环境,从构建、发布、通知实现自动化,帮你告别繁琐重复性的劳动。帮你解决上诉的烦恼。

整个工作流程如下

整个实现流程大致如下:

1,创建 CODING DevOps 项目

2,创建构建计划,配置微信小程序代码上传白名单

3,配置微信小程序代码上传私钥到环境变量中

4,配置企业微信的 webhook 地址到环境变量中

5,配置构建计划,分为 4 个步骤(检出、编译、上传新版本、发送通知)

下面我们来一步步实现它。

准备工具

  • CODING DevOps 项目
  • 微信小程序具有管理员权限的账号
  • 企业微信

创建 CODING DevOps 项目

登陆到 CODING 的工作台,在右上角选择 新增项目。随后选择 DevOps 项目创建即可。

设置小程序白名单

小程序代码上传需要配置 IP 的白名单,只有在指定的 IP 下才可以上传代码。
设置白名单分为两步:

1,我们来到 CODING DevOps 的项目中,新建一个构建计划,选择自定义构建过程
然后在构建详情选,选择 “基础信息”,在节点池中,复制选节点的公网出口

2,到微信小程序管理后台的 左侧菜单中选择 开发 -> 开发者设置 -> 小程序代码上传 -> 编辑 IP 白名单,将刚刚复制到的出口地址添加进去。

环境变量配置

持续集成过程中,我们总会将一些配置(如:账号密码/版本号等)信息以环境变量的形式注入到构建过程中。

CODING 持续集成支持多种环境变量使用形式,具体可查阅此文档

在本例中,我们需要设置两个环境变量

  • 微信小程序代码上传私钥

  • 企业微信机器人 webhook 地址

小程序代码上传私钥

微信小程序代码上传的私钥,可在微信管理后台:开发 -> 开发设置 -> 小程序代码上传 中获取。先保存到本地

然后我们来到 CODING DevOps 项目中的 项目设置 -> 开发者选项 -> 凭据管理 -> 新增凭据 -> 选择 SSH 私钥

打开我们之前在微信管理后台获取到的 ssh 私钥文件,复制里面的内容粘贴到凭据里面去保存。CODING 会对您的私钥进行加密保存,不会泄漏出去。

最后,回到我们刚刚创建的构建计划,在编辑模式中,选中顶部菜单的 “变量与缓存“。选择新建环境变量 -> coding 凭证,选择我们刚刚创建的 SSH 私钥。

企业微信群聊机器人 webhook

企业微信群聊机器人的 webhook 可以在群聊右键菜单中选择“新建群机器人”,在新建成功后,可以看到 webhook 地址,将它复制一下。
最后,回到我们刚刚创建的构建计划,在编辑模式中,选中顶部菜单的 “变量与缓存“。选择新建环境变量 -> 字符串类型,将刚刚复制的 webhook 地址粘贴进去即可。



配置构建流程

接下来我们来配置一下整个构建流程,在刚刚创建的构建计划,在编辑模式中,选中顶部菜单的 “流程编辑“ -> 选择 “文本编辑器”。

整个 Jenkinsfile 代码如下,

可以看到,主要分为检出、构建、上传版本、发送通知等 4 个阶段

主要都是调用一些脚本,下文中会对每个 stage 进行说明。

pipeline {
  agent any
  stages {
    stage('检出') {
        steps {
            checkout([
            $class: 'GitSCM',
            branches: [[name: env.GIT_BUILD_REF]],
            userRemoteConfigs: [[
                url: env.GIT_REPO_URL,
                credentialsId: env.CREDENTIALS_ID
            ]]])
        }
    }
    stage('构建') {
        steps {
          echo '开始安装依赖'
          sh 'npm install'
          echo '开始构建...'
          sh 'npm run build'
          echo '构建完成'
        }
    }
    stage('上传新版本') {
        steps {
          withCredentials([sshUserPrivateKey(credentialsId: "${env.privatekey}",keyFileVariable: 'identity')]) {
            sh 'node upload.js -p ${identity}'
          }
        }
    }
    stage('发送新版本通知') {
        steps {
            sh 'node notification.js -u ${WECHAT_WEBHOOK}'
        }
    }
  }
}

构建阶段

可以看到就调用了两个命令:

npm install
npm run build

作为前端开发,我们都知道 npm 在执行 install 的时候因为网络原因是相当耗时的,而 CODING 持续集成提供的香港构建节点和构建缓存设置可以极大的提高 install 的速度。

具体你可以看到构建计划中的设置 -> 变量与缓存 菜单中找到。

在本例中,build 的规则比较简单:调用 gulp 运行了一个构建任务,将对应的 sass 文件处理成 wxss 文件,其他类型都是直接复制过去。

这个具体可根据自己的项目进行配置

本例的构建规则可查看源码仓库中的 gulpfile。

上传新版本

这里使用 miniprogram-ci 来实现代码的上传。

miniprogram-ci 是从微信开发者工具中抽离的关于小程序/小游戏项目代码的编译模块。开发者可不打开小程序开发者工具,独立使用 miniprogram-ci 进行小程序代码的上传、预览等操作。

此前我们将小程序上传代码的凭证加到环境变量中,这里我们使用 withCredentials 快速提取凭证,凭据具体的使用可以查看凭据使用

withCredentials([sshUserPrivateKey(credentialsId: "${env.privatekey}",keyFileVariable: 'identity')]) {
   sh 'node upload.js -p ${identity}'
}

提取到凭证后,调用了一个 upload.js 脚本。这里主要是利用 miniprogram-ci 进行代码的上传和预览二维码的生成,请看下方的代码。

const ci = require('miniprogram-ci')
const path = require('path');
const fs = require("fs");
const argv = require('minimist')(process.argv.slice(2));
const package = require('./package.json')
const appDirectory = fs.realpathSync(process.cwd());
const ProjectConfig = require('./dist/project.config.json');
const previewPath = path.resolve(appDirectory, './preview.jpg');


(async () => {
    try {
        const project = new ci.Project({
            appid: ProjectConfig.appid,
            type: "miniProgram",
            projectPath: path.resolve(appDirectory, './dist'),
            privateKeyPath: argv.p,
            ignores: ["node_modules/**/*"],
        })
        await ci.upload({
            project,
            version: package.version,
            desc: package.versionDesc,
            setting: {
                ...ProjectConfig.setting
            },
            onProgressUpdate: console.log,
        })
        await ci.preview({
            project,
            version: package.version,
            desc: package.versionDesc,
            qrcodeFormat: "image",
            qrcodeOutputDest: previewPath,
            setting: {
                ...ProjectConfig.setting
            },
            onProgressUpdate: console.log,
        })
    } catch (e) {
        console.error(e);
        process.exit(1);
    }

})()

通知阶段

这里也很简单,直接发送一个请求,触发 webhook ,将预览二维码发送出去。

关于企业微信 API 的可查看这里企业微信文档

const md5File = require('md5-file')
const axios = require('axios');
const path = require('path');
const argv = require('minimist')(process.argv.slice(2));
const fs = require("fs");
const appDirectory = fs.realpathSync(process.cwd());

const previewPath = path.resolve(appDirectory, './preview.jpg');


function sendQrCode (imageBase64, hash) {
    return axios({
        headers: { "Content-Type": 'application/json' },
        method: 'post',
        url: argv.u,
        data: {
            "msgtype": "image",
            "image": {
                "base64": imageBase64,
                "md5": hash
            }
        }
    });
}

(async () => {
    try {
        const imageData = fs.readFileSync(previewPath);
        const hash = md5File.sync(previewPath)
        const imageBase64 = imageData.toString("base64");
        await sendQrCode(imageBase64, hash);

    } catch(e) {
        console.error(e);
        process.exit(1);
    }
})()

当我们把代码上传,发布新版本之后,就会往企业微信群上发送一个预览二维码,通知群上的同事进行预览体验

到这里,就完成整个微信小程序自动化构建上传的全部流程啦,源码可在这里找到:源码地址

总结

更多扩展

  • 版本号和版本说明没有集中管理,目前是读取 package.json 文件里的 version 和 versionDesc,像团队里其他角色,像产品或者测试,想知道某个版本更新了什么内容就比较麻烦。这里可以试着使用 CODING 代码仓库的版本管理,通过 tag 来管理版本,同时配置通过 tag 来触发构建。

  • 通知只发送了二维码,没有发送版本号和版本说明,这里通过企业微信的 api,发送图文信息来解决,由于图文信息的 api 需要图片的网络地址,需要增加 cdn 的上传环节,为了不增加示例的复杂度,这里就没有实现。

上一篇构建基于 Tensorflow.js 的机器学习应用
最近更新
感谢反馈有用
感谢反馈没用