作者:汪奇超
一、背景与痛点
手动发布流程的重复性
多平台重复配置
微信、支付宝、抖音等小程序平台各有独立的后台系统,每次发布需分别登录、填写版本号、上传代码包、设置权限等,操作流程高度相似但无法复用
版本信息同步
需手动在多个平台更新版本号、更新日志,易出现不一致(如微信v1.2.0 vs 支付宝v1.1.9)
效率瓶颈与人力消耗
时间成本
据统计,手动发布三端小程序平均耗时30分钟以上
团队协作低效
依赖特定成员操作(如“只有某人会抖音发布”),形成单点故障风险
潜在风险与业务影响
人为错误率高
上传错误代码包
二、技术选型
核心工具依赖
- 微信:miniprogram-ci(www.npmjs.com/package/min…)
- 支付宝:minidev(www.npmjs.com/package/min…)
- 抖音:tt-ide-cli(www.npmjs.com/package/tt-…)
- 开发框架:
Node.js - 执行工具:
jenkins
三、自动化脚本设计
整体架构
├── scripts/
│ ├── build/ # 多端发布脚本
│ ├── config/ # 平台差异化配置
│ ├── notify.js # 消息通知脚本
│ └── publish.js # 主流程控制
关键模块实现
配置中心
- 统一版本号同步
通过package.json中的version同步各端的版本号
- 各端配置文件
{
"ciConfig": {
"ddNotifyToken": "", // 用于钉钉通知
"channelList": ["weapp", "alipay", "tt"],
"tt": {
"email": "",
"password": "",
"appid": "",
"projectPath": "./dist/tt",
},
"alipay": {
"appid": "",
"toolId": "",
"privateKey": "",
"projectPath": "./dist/alipay",
},
"weapp": {
"appid": "",
"projectPath": "./dist/weapp",
"privateKeyPath": "./config/weapp.key",
}
}
}
上传逻辑
- 微信
const ci = require("miniprogram-ci");
const project = new ci.Project({
appid: ciConfig.appid,
type: "miniProgram",
projectPath: ciConfig.projectPath,
privateKeyPath: ciConfig.privateKeyPath,
ignores: ["node_modules/**/*"],
});
// 如果需要预览码 则需要进行preview
await ci.preview({
project,
desc,
robot: 1,
setting: {
es6: true,
minify: true,
swc: true,
},
qrcodeFormat: "image",
qrcodeOutputDest: "./weappPreview.jpg", // 将预览码进行通知
});
await ci.upload({
project,
version,// 本次更新版本
desc,// 本次更新日志
setting: {
es6: true,
minify: true,
swc: true,
},
});
- 支付宝
import {minidev} from "minidev";
// 授权信息
await minidev.config.useRuntime({
"alipay.authentication.privateKey": ciConfig.privateKey,
"alipay.authentication.toolId": ciConfig.toolId,
});
// 获取预览码
const {qrcodeUrl} = await minidev.preview({
appId: ciConfig.appid,
project: ciConfig.projectPath,
});
// 例: 获取小程序所有上传版本
const allVersionList = await minidev.app.getUploadedVersionList({
appId: ciConfig.appid,
});
// 删除版本
const deleteVersion = async (version) => {
await minidev.app.deleteVersion({
appId: ciConfig.appid,
version,
});
console.log(`删除版本${version}`);
};
// 支付宝有开发版本数量上限 所以这里可以定义一个规则删除历史开发版本 可以减少人为操作
await minidev.upload({
appId: ciConfig.appid,
project: ciConfig.projectPath,
version,// 本次更新版本
experience: false,
});
- 抖音
抖音可以直接把版本到审核完自动上线阶段。
为什么没有这么做?
- 保持三端统一性
- 为了保持可控性和稳定性,不希望自动发布上线
- 如果版本发布频繁,上一个版本未审核通过,下一个版本提交审核会导致发布失败
const tma = require("tt-ide-cli");
await tma.loginByEmail({
email: ciConfig.email,
password: ciConfig.password,
});
await tma.upload({
project: {
path: ciConfig.projectPath, // 项目地址
},
changeLog: desc, // 本次更新日志
version, // 本次更新版本
needUploadSourcemap: true, // 是否上传后生成 sourcemap,推荐使用 true,否则开发者后台解析错误时将不能展示原始代码
qrcode: {
format: "imageFile", // imageSVG | imageFile | null | terminal
output: "./ttPreview.jpg", // 只在 imageFile 生效,填写图片输出绝对路径
options: {
small: false, // 使用小二维码,主要用于 terminal
},
},
});
通知
通过OSS将本地图片转换成网络图片以便于钉钉通知小程序预览码
const OSS = require("ali-oss");
const client = new OSS({
region: "",
accessKeyId: "",
accessKeySecret: "",
bucket: "",
});
const put = (ossFilePath, localFilePath) => {
// 'object'填写上传至OSS的object名称,即不包括Bucket名称在内的Object的完整路径。
// 'localfile'填写上传至OSS的本地文件完整路径。
const fullPath = `https://*****.aliyuncs.com/${ossFilePath}`;
return new Promise((res) => {
client.put(ossFilePath, localFilePath).then(() => {
res(fullPath);
});
});
};
调用钉钉API将发布信息以及预览二维码通知到钉钉中
export const notify = async (props) => {
const {
token,
version,
desc,
type,
typeStr,
icon,
publishUrl,
name,
previewUrl,
packageTip
} = props;
const dev = `https://oapi.dingtalk.com/robot/send?access_token=${token}`;
async function sendDDMsg(preview, resolve) {
const da = {
msgtype: "actionCard",
actionCard: {
title: "",
text: `### **${name}** \n  \n ### **${typeStr}小程序上传成功** \n ### **版本号 -> ${version}** \n ### **版本描述 -> ${
desc || "-"
}** \n ${packageTip} \n ### **验证二维码** \n`,
singleTitle: "点我去发布~",
singleURL: `dingtalk://dingtalkclient/page/link?pc_slide=false&url=${encodeURIComponent(
publishUrl
)}`, // 各端小程序开放平台后台地址
},
};
await http.post(dev, da);
resolve();
}
function saveImg() {
const date = new Date().getTime();
return new Promise((resolve) => {
if (previewUrl) {
sendDDMsg(previewUrl, resolve);
return previewUrl;
} else {
return put(
`******/${type}Preview${date}.jpg`,
`./${type}Preview.jpg`
).then((data) => {
sendDDMsg(data, resolve);
return data;
});
}
});
}
await saveImg();
};
四、脚本执行
执行步骤
- 拉取工程代码
- 安装依赖包
- 编译
- 发布
- 通知
注意事项
- 不要清空发布文件夹
一般jenkins发布脚本一般会执行完成后清空发布文件夹以减少对磁盘的压力,但是前端项目依赖包比较庞大,所以每次安装会比较耗时。所以建议不删除依赖包,加快整体发布速度。
- 发布机器性能足够的情况下,进行三端同步编译发布,提升效率(出现过机器降配导致发布中断)
stage('编译程序'){
parallel {
stage('支付宝') {
steps {
sh '''
echo "微信"
yarn build weapp
npm run kone-upload -- -c weapp
'''
}
}
stage('抖音') {
steps {
sh '''
echo "抖音"
yarn build tt
npm run kone-upload -- -c tt
'''
}
}
stage('支付宝') {
steps {
sh '''
echo "支付宝"
yarn build alipay
npm run kone-upload -- -c alipay
'''
}
}
}
}
通过jenkins并发脚本进行三端并发打包发布,加快整体发布速度。
五、实现成果
- 一键发布,无技术壁垒
- 之前需要一名人员持续操作,现完全自动完成
- 发布时间从30分钟以上降低到10分钟以内(支付宝的发布会相对久一点)
- 多端版本号完全统一