使用Jenkins打包生成微信小程序二维码进行测试

一、本地使用微信小程序开发者工具生成预览二维码

先安装,只有mac和Windows版,下面地址下载对应版本后安装应用,我这里下载贼慢,耐心点。。。
https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html
安装好之后,微信扫码登录客户端,测试一下使用工具生成本地代码的预览二维码,微信扫码能够访问,安装开发者工具的准备工作就完成了。
完成后注意不要关闭应用,保持登录,以便脚本调用工具。

二、接入Jenkins实现一键生成二维码

1、安装下列Jenkins插件后重启:
GIT plugin
Git Parameter:获取所有分支名,作为参数列表
SSH Credentials Plugin
Git Changelog:获取Git提交log
build-name-setter
description setter plugin:在build历史记录描述信息中增加二维码显示
PostBuildScript Plugin:编译完成后执行脚本
NodeJS Plugin:小程序构建需要,在更改提交状态时使用node技术
AnsiColor

2、在Jenkins系统管理——全局安全配置页面,将标记格式器在下拉列表中修改为Safe HTML然后保存,这个修改是为了在build历史记录中能够直接显示二维码图片;

3、在Jenkins系统管理——全局工具配置页面,新增nodejs配置,选择node版本,这一步是为了后面“NodeJS Installation”下拉选择中有版本可选。

4、创建自由风格Jenkins任务,参数化构建过程中添加Git Parameter,用来获取分支打包时选择;

配置成功后build效果:

5、参数化构建过程中添加选项参数build_type,用来读取指定环境的配置,后续脚本中有用到这个值;

6、参数化构建过程中添加字符参数work_path,就是你的Jenkins拉下来的代码路径;

7、源码管理中,添加代码地址、账号密码,分支填上面Git Parameter传过来的值$Branch;

8、构建环境按照如下配置:

9、构建操作,cd到Jenkins拉下来的代码目录下,执行deploy脚本。

10、构建后操作,把生成二维码的HTML代码写到build历史记录中显示二维码图片,具体内容为:
旧的写法:
(<img src="http://JenkinsIP端口或域名/jenkins/job/edu-wechat-mini/ws/${BUILD_ID}.png" alt="二维码${BUILD_ID}" width="200" height="200" /><a href="http://JenkinsIP端口或域名/jenkins/job/edu-wechat-mini/ws/${BUILD_ID}.png">二维码${BUILD_ID}</a>)
优化了下:
<img src="${JOB_URL}ws/${BUILD_ID}.png" alt="二维码${BUILD_ID}" width="200" height="200" /><a href="${JOB_URL}ws/${BUILD_ID}.png">二维码${BUILD_ID}</a>

最后打包出来的结果:

11、附上使用到的脚本,需要加到项目代码根目录下:
(脚本需要用到wget,没有安装的自行安装,我是用homebrew安装的:brew install wget)
(1)deploy.sh:

#!/bin/bash
msg() {
    printf '%b\n' "$1" >&2
}

info()
{
    msg "[INFO] $1"
}

success() {
    msg "\e[1;32m[✔] ${1}${2} \33[0m "
}

notice() {
    msg "\e[1;33m ${1} \e[0m"
}

error_exit() {
    msg "\e[1;31m[✘] ${1}${2} \33[0m"
    exit 1
}

exec_cmd()
{
  echo "[执行命令] $1"
  $1
  if [ "$?" != "0" ]; then
    error_exit "命令执行失败: 错误码为 $?"
  fi
}

# sed匹配hosts.js内容,替换服务端环境
change_hosts() 
{
    if [ -f "hosts.js" ]; then
        case $build_type in 
            "test")
                target_env="test"
                echo "${work_path}"/hosts.js
                sed -i "" "s/^const curr_env = .*/const curr_env = '$target_env'/" ${work_path}"/hosts.js"
                info "切换到 ${target_env} 环境"
            ;;
            "dev")
                target_env="dev"
                echo "${work_path}"/hosts.js
                sed -i "" "s/^const curr_env = .*/const curr_env = '$target_env'/" ${work_path}"/hosts.js"
                info "切换到 ${target_env} 环境"
            ;;
            "prod")
                target_env="prod"
                echo "${work_path}"/hosts.js
                sed -i "" "s/^const curr_env = .*/const curr_env = '$target_env'/" ${work_path}"/hosts.js"
                info "切换到 ${target_env} 环境"
            ;;
        esac
        if [ "$?" != "0" ]; then
            error_exit "切换环境失败!"
        fi
    else
        error_exit "没有找到hosts.js文件!"
    fi
}

# 根据feature参数增加版本号,上传到微信小程序后台准备提审
# 用node程序直接读取version.js修改版本号
upload_for_release() 
{
    if [ -f ${work_path}"/version.js" ]; then
        exec_cmd "node /Users/min/.jenkins/workspace/ops-server/tmp/mp/upload.js ${work_path} $feature $desc"
    else
        error_exit "没有找到version.js文件!"
    fi
}

# 生成开发版二维码
# 这里直接执行小程序cli的命令
upload_for_preview()
{
    exec_cmd "/Applications/wechatwebdevtools.app/Contents/Resources/app.nw/bin/cli -o"
    port=$(cat "/Users/min/Library/Application Support/微信web开发者工具/Default/.ide")
    echo "微信开发者工具运行在${port}端口"
    echo "调用http://127.0.0.1:${port}/open"
    return_code=$(curl -sL -w %{http_code} http://127.0.0.1:${port} -o /open)
    if [ $return_code == 200 ]; then
        echo "返回状态码200,devtool启动成功!"
    else
    echo "返回状态码${return_code},devtool启动失败"
        exit 1
    fi
  exec_cmd "pwd"
    exec_cmd "wget  -O  ${work_path}/$BUILD_ID.png http://127.0.0.1:${port}/preview?projectpath=${work_path}"
}

if [ "$build_type" == "test" ]; then
  info "发布测试版!"
  change_hosts
  #生成二维码
  upload_for_preview
  success "预览成功!请扫描二维码进入测试版!"
elif [ "$build_type" == "dev" ]; then
  info "发布开发版!"
  change_hosts
  #生成二维码
  upload_for_preview
  success "预览成功!请扫描二维码进入开发版!"
elif [ "$build_type" == 'prod' ]; then
  info "准备上传!"
  change_hosts
  #提交代码微信公众平台
  upload_for_release
  success "上传成功!请到微信小程序后台设置体验版并提交审核!"
else
    error_exit "需要设置合法的build_type!"
fi

(2)upload.js

var fs = require('fs');
var cp = require('child_process');
var args = process.argv;  // 获取命令行带入的参数 args[0]是程序执行的目录 args[1]是文件名

const succ_code = 0;
const err_code = 1;

function err_msg(str) {
    console.log('[NODE ERR] ', str);
}

function info_msg(str) {
    console.log('[NODE INFO] ', str);
}

function exec_cmd(cmd, cb) {
    info_msg('执行命令: ' + cmd)
    // 使用child_process在终端执行命令
    cp.exec(cmd, function(err, stdout, stderr) {
        var succ = true;
        if (err) {
            // 命令执行异常,退出程序
            err_msg(err);
            if (stderr) {
                err_msg(stderr);
            }
            succ = false;
        }   else {
            // 打印所执行命令的标准输出
            info_msg(stdout);
            if (stderr) {
                err_msg(stderr);
            }
        }
        typeof cb === 'function' && cb(succ);
    })
}

try {
    var path = args[2];
    var feature = args[3];
    var desc = '【RELEASE】' + args[4];

    var ver_path = path + '/version.js';
    var version_conf = require(ver_path);

    // 根据feature参数确定版本号增加的逻辑
    switch(feature) {
        case 'debug': {
            version_conf.debug++;
            break;
        }
        case 'update': {
            version_conf.update++;
            version_conf.debug = 0;
            break;
        }
        case 'refactor': {
            version_conf.refactor++;
            version_conf.update = 0;
            version_conf.debug = 0;
            break;
        }
        default:
            err_msg('未设置正确的版本特性!');
            process.exit(err_code);
    }
    // 生成version.js所需的文件内容,方便小程序代码直接读取
    var str = 'module.exports = {' + '\n\trefactor: ' + version_conf.refactor + ',\n\tupdate: ' + version_conf.update + ',\n\tdebug: ' + version_conf.debug + '\n}';
    // 写入文件(fs.writeFile() 以w模式打开文件,写入的内容会覆盖原有内容)
    fs.writeFile(ver_path, str, function(err) {
        if (err) {
            err_msg(err);
            process.exit(err_code);
        } else {
            info_msg('UPDATE VERSION SUCCESS!');
            info_msg('Build feature is: ' + feature);
            info_msg('Current version is: ' + version_conf.refactor + '.' + version_conf.update + '.' + version_conf.debug);
            var ver = version_conf.refactor + '.' + version_conf.update + '.' + version_conf.debug;
            // 写入正常,执行小程序cli命令上传
            var upload_cmd = '/Applications/wechatwebdevtools.app/Contents/Resources/app.nw/bin/cli -u ' + ver + '@' + path + ' --upload-desc ' + desc;
            exec_cmd(upload_cmd, function(ok) {
                process.exit(ok ? succ_code : err_code);
            });
        }
    });
} catch(error) {
    // 捕获异常,退出程序
    err_msg(error);
    process.exit(err_code);
}

(3)hosts.js

const curr_env = 'test'
const hosts = {
test: {
hostSmart: 'http://测试环境IP或域名', 
hostDc: 'https://.cn' // 
},
dev: {
hostSmart: 'http://.具体环境(如:beta)..com', 
hostDc: 'https://.cn' // 
},
prod: {
hostSmart: 'http://.生成环境..com', 
hostDc: 'https://.cn' // 
}
}
module.exports = {
getHosts: function () {
return hosts[curr_env]
}
}

——————————————————————————-
打包命令优化为官方命令,语句更简单更稳定:

exec_cmd "rm -if $WORKSPACE/*.png"
exec_cmd "/Applications/wechatwebdevtools.app/Contents/MacOS/cli preview --project $WORKSPACE --qr-output $WORKSPACE/$BUILD_ID.png --qr-format image"

被小程序账号权限问题坑了两次:

1、一直遇到生成预览二维码图片这一步报400错误,不懂为啥,最后拿开发者账号扫码登录发现可以,才知道必须是开发者账号登录才行,我的账号不是开发者账号。。。所以需要在Jenkins机器上使用小程序开发者账号登录小程序开发者工具客户端。。。

2、扫码体验的微信号也需要开权限,否则不能预览。。。

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

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,392评论 25 707
  • 用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金 Cover 有什么料? 从这篇文章中你...
    hw1212阅读 12,680评论 2 59
  • 转载链接 注:本文转载知乎上的回答 作者:初雪 链接:https://www.zhihu.com/question...
    pengshuangta阅读 28,473评论 9 295
  • 之前App在提交测试和最终部署的过程中App打包一直是由开发人员来完成的,由于项目比较大, 再加上Android打...
    南若水阅读 6,108评论 1 16
  • 寒风吹光了枝头 酷霜染尽了枫红 瑶池觞漪着霖公 别了无心的封候
    吉羊玉奕v阅读 184评论 1 3