美文网首页
使用Jenkins打包生成微信小程序二维码进行测试

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

作者: 小安然 | 来源:发表于2018-11-16 16:29 被阅读0次

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

    先安装,只有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、扫码体验的微信号也需要开权限,否则不能预览。。。

    相关文章

      网友评论

          本文标题:使用Jenkins打包生成微信小程序二维码进行测试

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