最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 微信,支付宝小程序CI/CD

    正文概述 掘金(j果er)   2020-12-19   653

    本文内容均只用于支付宝和微信小程序

    背景

    先说一下为什么要做这个东西把。

    • 基于提审
      • 原生小程序中漫长的提审流程,合PR,切到主分支,pull代码,点击上传,后台提审
      • 原生小程序基于config文件决定抛出环境,提审时项目环境完全靠人工校验
    • 基于测试
      • 测试bugfix校验或者后端同学需要测试环境时,通常都是直接跟我们要二维码,这时我们可能在开发别的项目,本地代码不纯净,所以普遍我们都是commit本地代码,切到干净的分支,然后切好测试环境,在生成二维码给到他们,然后再切回开发分支。这也太麻烦了吧。所以我们开发了一个生成小程序二维码的平台,可以让他们完成脱离我们
      • 测试同学可能对git不熟悉,而且对怎么切换环境也不熟悉

    就是基于上面这几点原因让我们基于支付宝和微信提供的SDK开发了属于我们小程序的CI/CD,尽最大可能解放一些繁琐且打断我们思路的工作

    功能介绍

    • 自动上传小程序后台,PR合并后触发
      • 校验环境,version自增1(根据自己的项目自行补充需要的校验和功能)
      • 上传完成后叮叮通知,通知信息包括version,体验版二维码,包信息
    • 小程序预览平台
      • 用户体系:普通(可构建),管理员(可上传),超管(可添加用户)
      • 获取所有分支,可切分支
      • 获取当前环境,可切换环境
      • 定义入口页
      • 定义入口页参数
      • 构建预览二维码
      • 管理员以上可手动上传

    微信,支付宝小程序CI/CD
    微信,支付宝小程序CI/CD
    本篇文章先说一下自动上传是如何实现的

    gitee webHook配置

    添加webhook

    微信,支付宝小程序CI/CD

    勾选PR

    微信,支付宝小程序CI/CD

    添加完成

    微信,支付宝小程序CI/CD

    完成如上步骤后发起PR和更新PR后,码云会发起一个post请求到我们的承接接口。

    接口实现

    注册之前码云上填写的路由来接收WebHook

    router.post('/upload/:appKey', async ctx => {
      // ...log
    }
    

    启动node服务,这时我们去刚刚添加完成的页面点一下测试按钮,接口就能接收到码云发来的请求啦~

    既然第一步已经完成,那么我们梳理一下这个接口需要实现的内容:

    • 校验PR的目标分支和PR的状态
    • clone或者pull目标分支的代码至本地
    • 校验是否需要上传,version是否需要+1,是否为正式环境(与自己项目耦合的功能)
    • 叮叮通知开始上传
    • 上传
    • 叮叮通知上传成功
    • 结束

    梳理完之后是不是非常的清晰,接下来让我们一步步来实现它

    校验目标分支和PR状态

    因为我们所有的PR目标分支均是master,并且需要提审的版本也是master,所以在接收到请求之后,需要判断一下目标分支是不是master并且PR的状态是不是合并完成。
    WebHook推送数据的数据类型文档
    PS:PR分为新建,更新,合并,关闭,每次状态更新都会发起一次请求,所以需要过滤不是合并的请求

    router.post('/upload/:appKey', async ctx => {
        const { body } = ctx.request
        if (body.state === 'merged' && body.target_branch === "master") {
        	// ...
        }
    }
    

    拉取代码

    校验完之后就需要拉取代码,如果项目目录存在就去pull,不存在就去clone(偷个懒,确保你的目录是存在的,不然会报错)

    if (fs.existsSync(xcxpath)) {
      child_process.execSync('git pull', {
        cwd: xcxPath
      })
    } else {
      child_process.execSync(`git clone ${git地址}`, {
        cwd: path.join(xcxPath, '..'))
      })
    }
    

    自定义校验

    接下来就需要去做一些与自己项目相关的上传前的校验,比如我们有些时候可能存在多个PR,不想每次合并后都上传一次,这时我们利用PR中的标签来判断是否需要上传,当我们选中aNotUpload标签时,这个PR将不会上传
    微信,支付宝小程序CI/CD

    let arr = body.pull_request.labels.filter(item => item.name === 'aNotUpload')
    if( arr.length ) {
    	// ...存在,所以不上传
      ctx.body = {
        code: 200,
        msg: '自主选择不上传',
        success: true
      }
      return 
    }
    
    

    然后我们也维护了一套自己的version用来区分每次的版本,但是每次都需要手动去+1,非常不合理。为了完成这个自动化,在合并PR之后(合并了所有commit)偷偷在master增加version并且push(暂时没有想到更合理的方法)

    const parser = require("@babel/parser");
    const generator = require("@babel/generator").default;
    const traverse = require("@babel/traverse").default;
    // 获取ast
    function readConfig(root) {
        const configFile = path.join(root, '/config/config.js')
        const context = fs.readFileSync(configFile, "utf-8")
        const ast = parser.parse(context)
        return {
            ast,
            file: configFile
        }
    } 
    // version是否+1
    function prodHooks({
        root,
        appKey
    }) {
        let {
            ast,
            file
        } = readConfig(root)
        let isVersionUp = false
        // 是否上升了一个版本号
        const diffStr = child_process.execSync(`git diff HEAD^ config/config.js`, {
            cwd: '项目路径',
            encoding: 'utf-8'
        })
        // 获取不同的version,大概得到['-  version: "10.0.0"', '+  version: "10.0.1"']
        let diffArr = diffStr.match(/(\+|-)(.*)version:[^\r\n]*[\r\n]/g)
        if (diffStr && diffArr.length) {
            // 提取数字
            diffArr = diffArr.map(i => i.replace(/\D*/g, ''))
            // +的version是否比-的version大,是的话就完成了version的提升
            isVersionUp = diffArr[1] - diffArr[0] > 0
        }
      	// 没有增加version,自动+1
        if(!isVersionUp) {
          	traverse(ast, {
                enter(p) {
                    if (p.isObjectProperty()) {
                        let name = p.node.key.name
                        if (name === 'version' || name === 'versionCode') {
                            let val = p.node.value.value
                            if (typeof val === 'string') {
                                val = versionUpdate(val)
                            } else {
                                val += 1
                            }
                            p.node.value.value = val
                        }
                    }
                }
            })
            const {
                code
            } = generator(ast)
            fs.writeFileSync(file, code, "utf-8")
            child_process.execSync(`git add . && git commit -m 'version up' && git pull && git push`, {
                cwd: '项目目录'
            })
        }
        return true
    }
    /**
     * 升级版本号
     * @param {string} val '2.09.09' | '99.99.99'
     * @return {string} '2.09.10' | '100.00.00'
     *  
    */ 
    function versionUpdate(val) {
        let num = [...(1 + Number(val.replace(/\D/g, '')) + '')]
        for(let i=val.length-1; i>=0; i--){
            if(val[i] === '.') {
                num.splice(i - val.length + 1 , 0, '.')
            }
        }
        return num.join('')
    }
    

    到这里我们完成了所有上传前的校验和自定义处理,接下来就到了最重要的通知和上传阶段啦~

    钉钉群通知

    平常上班主要使用钉钉,所以接入钉钉群机器人通知上传进度
    PS:钉钉群机器人SDK
    先创建一个钉钉群并设置自定义机器人获取accessToken和secret
    微信,支付宝小程序CI/CD
    微信,支付宝小程序CI/CD
    微信,支付宝小程序CI/CD
    点击完成后打开机器人
    微信,支付宝小程序CI/CD
    就可以得到accessToken和secret
    然后利用sdk向钉钉群发送一个推送吧

    const Robot = require('dingtalk-robot-sdk');
    const robot = new Robot({
      accessToken: 'xxxx',
      secret: 'xxxx'
    });
    const text = new Robot.Text('走起~')
    robot.send(text)
    

    上传

    支付宝和微信小程序利用sdk上传前的准备工作这边就不说啦,大家跟着官方文档去配置吧
    PS:微信上传文档,支付宝上传文档
    支付宝

    alipaydev.setConfig({
      toolId,
      privateKey,
    })
    const uploadResult = await alipaydev.miniUpload({
      appId: '支付宝appid',
      clientType: 'alipay',
      project: '项目地址',
      experience: true // 设置为体验版
    })
    

    微信

    const project = new ci.Project({
      appid,
      type: 'miniProgram',
      projectPath,
      privateKeyPath
    })
    const year = new Date().getFullYear() - 2000
    let month = new Date().getMonth() + 1
    const day = new Date().getDate()
    // 根据年月日当版本号
    const version = '2.5.' + year + (month < 10 ? '0' + month : month) + (day < 10 ? '0' + day : day);
    // 上传
    const previewResult = await ci.upload({
      project,
      version,
      desc: body.title,
      setting: {
        es6: true,
        minify: true,
        autoPrefixWXSS: true,
        minifyWXML: true,
        minifyWXSS: true,
        minifyJS: true
      }
    })
    

    起源地下载网 » 微信,支付宝小程序CI/CD

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元