腾讯云自动构建微信小程序,生成预览码,上传微信管理平台


前言

提示:本文的环境是腾讯云(CODING) + uniapp + 钉钉

自动化构建微信小程序,其实每个平台的方法是不一样的哈,我这里也只是记录下个人完成的情形,如果有人跟我的基础条件一样,那很幸运啦,我把坑都踩完了。
当然不一样,也没关系,可以借鉴或者保存下,毕竟万一以后工作上用到了呢?是吧

最终实现目标,腾讯云中点击构建,自动打包,编译,上传预览,生成二维码后,由机器人发到钉钉群里面。
在这里插入图片描述


一、官方文档

腾讯云自动化构建微信小程序
微信官方文档

最好看下这两篇文档内容啊,虽然大家都知道,官方文档永远都是避重就轻,但一般比较详细,简单看看还是有必要的。
腾讯云自动化构建微信小程序这篇博客对接的是企业微信,还是比较详细的,但是我这里是钉钉
以下内容默认已阅读这两篇文档

二、脚本开发

1.安装miniprogram-ci

npm install miniprogram-ci --save

这是微信官方提供的,核心包,上传,预览都需要通过它执行。

2.编写上传,预览功能

const ci = require('miniprogram-ci') // 引入包
// 注意: new ci.Project 调用时,请确保项目代码已经是完整的,避免编译过程出现找不到文件的报错。
const project = new ci.Project({
  appid: 'wxsomeappid', // appid
  type: 'miniProgram', // 小程序类型,具体有几种看上面微信官方文档
  projectPath: 'the/project/path', // 项目路径
  privateKeyPath: 'the/privatekey/path', // 私钥,在获取项目属性和上传时用于鉴权使用,在微信公众平台上登录后下载
  ignores: ['node_modules/**/*'], // 指定需要排除的规则
})

私钥获取方式,登录微信公众号平台找到管理>开发管理>开发设置-小程序代码上传-小程序代码上传密钥,点击生成即可获取

预览

const previewResult = await ci.preview({
    project,
    version:1.0.0, // 版本信息,这里非必填哈
    desc: 'hello', // 此备注将显示在“小程序助手”开发版列表中
    robot: 1, //  指定使用哪一个 ci 机器人,可选值:1 ~ 30
    setting: {
      es6: true,
      minifyJS: true,
        minifyWXML: true,
        minifyWXSS: true,
        minify: true
    }, // #编译设置
    qrcodeFormat: 'image', // 返回二维码文件的格式 "image" 或 "base64", 默认值 "terminal" 供调试用
    qrcodeOutputDest: '/path/to/qrcode/file/destination.jpg', // 二维码文件保存路径
    onProgressUpdate: console.log,
  })

上传

const uploadResult = await ci.upload({
    project,
    version: '1.1.1',
    desc: 'hello',
    robot: 1,
    setting: {
      es6: true,
      minifyJS: true,
      minifyWXML: true,
      minifyWXSS: true,
      minify: true
    },
    onProgressUpdate: console.log,
})

走到这里其实核心的都完成了,是不是很简单,但是我这里还有很多没完成,因为我最终的目的是,点击构建,然后完成后自动有一个预览二维码推到钉钉群里。

3.钉钉群里面添加机器人

我们钉钉先建一个群,里面设置机器人
在这里插入图片描述
添加机器人选择自定义,设置关键字,当发送的消息有关键字时,机器人就会把消息发出来,最后添加完成会生成一个Webhook
例如
https://oapi.dingtalk.com/robot/send?access_token=xxxxxxxx
最后对这个地址发送axios请求,就可以在群里把消息发送出来。

可能出现的问题

1,微信上传预览就失败了

这里注意看看要加ip白名单的,不然是上传不了的。
在这里插入图片描述

2,钉钉发送消息失败

这里注意下,钉钉发送图片不支持base64,必须要http地址哈,所以我这里其实还要加个把生成的预览图片上传到cos,换取到对应的http地址

全部脚本代码

const ci = require('miniprogram-ci')
const axios = require('axios')
const COS = require('cos-nodejs-sdk-v5')
const dayjs = require('dayjs')
const path = require('path')
const fs = require('fs')
const argv = require('minimist')(process.argv.slice(2))
const robot = argv.r || 1
const mpVersion = argv.v || '1.0.0'
const versionDesc = argv.d || ''
const uploaderWeChat = argv.w || 'false'
const appDirectory = fs.realpathSync(process.cwd()) // __dirname
const previewPath = path.resolve(appDirectory, `./xxx/xxx.jpg`) // 保存预览图片地址

const app_id = 'xxxxxxxxxxxx'
let client: any = null
let ossData: any = null

const uploadMp = async () => {
  try {
    const project = new ci.Project({
      appid: app_id,
      type: 'miniProgram',
      projectPath: path.resolve(appDirectory, './xxx/xxx'), //项目路径
      privateKeyPath: argv.p,
      ignores: ['node_modules/**/*']
    })

    console.log('--------------开发版 preview 开始-------------')
    const desc = `机器人 ${robot} 打包,版本:${mpVersion},备注:${versionDesc}`

    await ci.preview({
      project,
      version: mpVersion,
      desc,
      qrcodeFormat: 'image',
      qrcodeOutputDest: previewPath,
      robot,
      setting: {
        es6: true,
        minifyJS: true,
        minifyWXML: true,
        minifyWXSS: true,
        minify: true
      },
      onProgressUpdate: console.log
    })
    console.log('--------------开发版 preview 结束-------------')

    if (uploaderWeChat == 'true') {
      console.log('--------------开始上传微信-------------')
      await ci.upload({
        project,
        version: mpVersion,
        desc,
        robot,
        setting: {
          es6: true,
          minifyJS: true,
          minifyWXML: true,
          minifyWXSS: true,
          minify: true
        },
        onProgressUpdate: console.log
      })
      console.log('--------------上传微信完成-------------')
    }
  } catch (e) {
    console.error('error =======> ', e)
    process.exit(1) // 执行失败退出
  }
}

// 垃圾钉钉 不支持base64发送消息
const sendQrCode = (codeUrl: any) => {
  console.log('--------------发送钉钉消息-------------')
  let context = `关键字关键字关键字xxxxx<font class="text-color-2" color="#FF7A00">机器人${robot}</font> 打包成功,版本:${mpVersion}`
  context += `<font class="text-color-2" color="#FF7A00">备注:${versionDesc}</font> `
  context += `请扫码查看!或者前往小程序助手查看! \n  👇👇👇👇👇👇 \n ![二维码](${codeUrl}) \n `
  context += `<font class="text-color-2" color="#f44336">开发版二维码将于 ${dayjs(Date.now() + 60 * 24 * 1000).format('MM/DD HH:mm')} 时失效</font>`
  return axios({
    headers: { 'Content-Type': 'application/json' },
    method: 'post',
    url: 'https://oapi.dingtalk.com/robot/send?access_token=xxxxxxxxxxxxx',
    data: {
      msgtype: 'markdown',
      markdown: {
        title: `哈喽~小程序构建成功`,
        text: context
      }
    }
  })
}

const initCOS = () => {
  client = new COS({
    SimpleUploadMethod: 'putObject',
    getAuthorization: (options: any, callback: any) => {
      const obj = {
        TmpSecretId: ossData.data.oss_tmp_secret_id,
        TmpSecretKey: ossData.data.oss_tmp_secret_key,
        XCosSecurityToken: ossData.data.oss_session_token,
        StartTime: ossData.data.oss_start_time,
        // 时间戳,单位秒,如:1580000000,建议返回服务器时间作为签名的开始时间,避免用户浏览器本地时间偏差过大导致签名错误
        ExpiredTime: ossData.data.oss_expired_time,
        // 时间戳,单位秒,如:1580000900
        ScopeLimit: true // 细粒度控制权限需要设为 true,会限制密钥只在相同请求时重复使用--如果是要单次使用,即每次上传都需要获取一次签名时,那么就需要改为false
      }
      callback(obj)
    }
  })
}

const getCosToken = () => {
  return new Promise((resolve, reject) => {
    const data = { src: 'xxx' }
    axios
      .post('https://xxx.xxx.com/xxx/xx', data)
      .then((response: any) => {
        // 请求成功的回调函数
        ossData = response.data
        initCOS()
        resolve(response.data)
      })
      .catch((error: any) => {
        // 请求失败的回调函数
        console.log('Error', error)
        reject(error)
      })
  })
}

// 上传二维码
const uploadImage = () => {
  console.log('--------------上传二维码开始-------------')
  // eslint-disable-next-line no-async-promise-executor
  return new Promise(async (resolve, reject) => {
    try {
      const imageData = fs.readFileSync(previewPath)
      const base64Code = imageData.toString('base64')
      const dataBuffer = Buffer.from(base64Code, 'base64') // base64 -> 二进制Buffer
      const fileName = `xxx/xx.jpg`
      const data = await client.putObject({
        Bucket: ossData.data.oss_bucket, // 存储桶名称
        Region: ossData.data.oss_region, // 存储桶所在地域
        Key: ossData.data.oss_path + fileName, // 可以理解为图片存储的路径+名称(唯一) 例如:indexImages/1670050961361.png
        Body: dataBuffer, // 上传文件的内容,可以为 FileStream、字符串、Buffer, 我们这里接收二进制Buffer
        onProgress: (progressData: any) => {
          console.log('progress: ', progressData)
        }
      })
      resolve(`https://${data.Location}`)
      console.log('--------------上传二维码结束-------------')
    } catch (error) {
      reject(error)
      // console.log(error)
      console.log('--------------上传二维码失败-------------')
    }
  })
}

;(async () => {
  try {
    // 初始化COS
    await getCosToken()

    // 上传至微信
    await uploadMp()

    // 二维码上传cos
    const imageUrl = await uploadImage()
    console.log('开发版二维码路径:', imageUrl)

    // 发送消息
    await sendQrCode(imageUrl)

    console.log('执行成功 ------------------------------------')
    process.exit(0) // 执行成功退出
  } catch (e) {
    console.error(e)
    process.exit(1) // 执行失败退出
  }
})()

运行脚本

sh 'ts-node autoUpload.ts -p ${identity} -r ${robot} -w ${uploaderWeChat} -v ${version} -d ${versionDesc}'

注意,不要那么想当然复制就能用,看看情况,有些参数可以写死,让本地先跑起来,我这里还有着腾讯构建计划里面设置的东西,配置的流程,这种公司私密东西就不放出来了,可以借鉴参考一下

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值