upload-miniprogram 0.0.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/README.md +111 -0
- package/bin/upload-miniprogram.js +30 -0
- package/chatlabs-upload-miniprogram-1.0.0.tgz +0 -0
- package/lib/index.js +194 -0
- package/package.json +42 -0
- package/scripts/prepare-publish.js +51 -0
- package/upload-miniprogram-1.0.0.tgz +0 -0
- package/upload-miniprogram.js +191 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [1.0.0] - 2025-10-22
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- 初始版本发布
|
|
12
|
+
- 支持微信小程序代码上传
|
|
13
|
+
- 支持预览二维码生成
|
|
14
|
+
- 支持多环境配置
|
|
15
|
+
- 命令行接口和编程接口
|
|
16
|
+
- Jenkins CI/CD集成支持
|
|
17
|
+
- 交互式参数输入
|
package/README.md
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# upload-miniprogram
|
|
2
|
+
|
|
3
|
+
微信小程序CI/CD上传工具,支持自动上传代码和生成预览二维码。
|
|
4
|
+
|
|
5
|
+
## 功能特性
|
|
6
|
+
|
|
7
|
+
- ✅ 自动上传小程序代码到微信开发者平台
|
|
8
|
+
- ✅ 生成预览二维码
|
|
9
|
+
- ✅ 支持多环境配置 (开发/测试/预发布/生产)
|
|
10
|
+
- ✅ 支持命令行参数和交互式输入
|
|
11
|
+
- ✅ 集成Jenkins CI/CD环境
|
|
12
|
+
- ✅ 自动获取Git用户信息
|
|
13
|
+
|
|
14
|
+
## 安装
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install -g upload-miniprogram
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
或者作为开发依赖安装:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install --save-dev upload-miniprogram
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## 使用方法
|
|
27
|
+
|
|
28
|
+
### 命令行方式
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
# 基本用法
|
|
32
|
+
upload-miniprogram --appid your-appid --project-path ./dist --version 1.0.0
|
|
33
|
+
|
|
34
|
+
# 完整参数
|
|
35
|
+
upload-miniprogram \
|
|
36
|
+
--appid your-appid \
|
|
37
|
+
--project-path ./dist \
|
|
38
|
+
--version 1.0.0 \
|
|
39
|
+
--desc "功能更新" \
|
|
40
|
+
--user developer@example.com \
|
|
41
|
+
--env production
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### 参数说明
|
|
45
|
+
|
|
46
|
+
| 参数 | 缩写 | 必填 | 说明 |
|
|
47
|
+
|------|------|------|------|
|
|
48
|
+
| --appid | -a | 是 | 小程序ID |
|
|
49
|
+
| --project-path | -p | 是 | 小程序项目打包后的代码路径 |
|
|
50
|
+
| --version | -v | 是 | 版本号 |
|
|
51
|
+
| --desc | -d | 否 | 版本描述 |
|
|
52
|
+
| --user | -u | 否 | 上传用户 |
|
|
53
|
+
| --env | -e | 否 | 环境变量 (development\|staging\|uat\|production) |
|
|
54
|
+
|
|
55
|
+
### 编程方式
|
|
56
|
+
|
|
57
|
+
```javascript
|
|
58
|
+
const uploadMiniprogram = require('upload-miniprogram');
|
|
59
|
+
|
|
60
|
+
// 使用默认配置
|
|
61
|
+
uploadMiniprogram({
|
|
62
|
+
appid: 'your-appid',
|
|
63
|
+
projectPath: './dist',
|
|
64
|
+
version: '1.0.0',
|
|
65
|
+
desc: '功能更新',
|
|
66
|
+
user: 'developer@example.com',
|
|
67
|
+
env: 'production'
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// 或者使用类方式
|
|
71
|
+
const { UploadMiniprogram } = require('upload-miniprogram');
|
|
72
|
+
const uploader = new UploadMiniprogram(options);
|
|
73
|
+
await uploader.run();
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## 环境配置
|
|
77
|
+
|
|
78
|
+
### 私钥配置
|
|
79
|
+
|
|
80
|
+
工具需要微信小程序的私钥文件才能上传代码。私钥文件应该放在以下位置:
|
|
81
|
+
|
|
82
|
+
**本地开发环境:**
|
|
83
|
+
```
|
|
84
|
+
./scripts/private.{appid}.key
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
**Jenkins环境:**
|
|
88
|
+
```
|
|
89
|
+
${WORKSPACE}/../mp-ci-upload-key/private.{appid}.key
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### 环境变量
|
|
93
|
+
|
|
94
|
+
支持以下环境:
|
|
95
|
+
|
|
96
|
+
| 环境 | 版本后缀 | 机器人 | 描述 |
|
|
97
|
+
|------|----------|--------|------|
|
|
98
|
+
| development | .dev | 1 | 开发环境 |
|
|
99
|
+
| staging | .staging | 2 | 测试环境 |
|
|
100
|
+
| uat | .uat | 3 | 预发布环境 |
|
|
101
|
+
| production | (无) | 5 | 生产环境 |
|
|
102
|
+
|
|
103
|
+
## Jenkins集成
|
|
104
|
+
|
|
105
|
+
在Jenkins中配置环境变量:
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
## 许可证
|
|
110
|
+
|
|
111
|
+
MIT
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { program } = require('commander');
|
|
4
|
+
const uploadMiniprogram = require('../lib/index');
|
|
5
|
+
|
|
6
|
+
program
|
|
7
|
+
.version('1.0.0')
|
|
8
|
+
.description('微信小程序CI/CD上传工具')
|
|
9
|
+
.option('-a, --appid <appid>', '小程序ID')
|
|
10
|
+
.option('-p, --project-path <path>', '小程序项目打包后的代码路径')
|
|
11
|
+
.option('-v, --version <version>', '版本号')
|
|
12
|
+
.option('-d, --desc <desc>', '版本描述')
|
|
13
|
+
.option('-u, --user <user>', '上传用户')
|
|
14
|
+
.option('-e, --env <env>', '环境变量 (development|staging|uat|production)', 'development')
|
|
15
|
+
.parse(process.argv);
|
|
16
|
+
|
|
17
|
+
const options = program.opts();
|
|
18
|
+
|
|
19
|
+
// 设置环境变量
|
|
20
|
+
if (options.env) {
|
|
21
|
+
process.env.NODE_ENV = options.env;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
uploadMiniprogram({
|
|
25
|
+
appid: options.appid,
|
|
26
|
+
projectPath: options.projectPath,
|
|
27
|
+
version: options.version,
|
|
28
|
+
desc: options.desc,
|
|
29
|
+
user: options.user
|
|
30
|
+
});
|
|
Binary file
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
const ci = require("miniprogram-ci");
|
|
2
|
+
const { execSync } = require("child_process");
|
|
3
|
+
const inquirer = require("inquirer");
|
|
4
|
+
|
|
5
|
+
class UploadMiniprogram {
|
|
6
|
+
constructor(options = {}) {
|
|
7
|
+
this.options = options;
|
|
8
|
+
this.WORKSPACE = process.env.WORKSPACE;
|
|
9
|
+
this.ENV = process.env.NODE_ENV || 'development';
|
|
10
|
+
|
|
11
|
+
this.ENV_MAP = {
|
|
12
|
+
development: { v: ".dev", desc: "【Dev环境】", robot: 1 },
|
|
13
|
+
staging: { v: ".staging", desc: "【Staging环境】", robot: 2 },
|
|
14
|
+
uat: { v: ".uat", desc: "【Uat环境】", robot: 3 },
|
|
15
|
+
production: { v: "", desc: "【正式环境】", robot: 5 },
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// 获取 Git 邮箱
|
|
20
|
+
getGitEmail() {
|
|
21
|
+
try {
|
|
22
|
+
return execSync("git config --global user.email", {
|
|
23
|
+
encoding: "utf8",
|
|
24
|
+
}).trim();
|
|
25
|
+
} catch (error) {
|
|
26
|
+
console.error("无法获取 Git 邮箱:", error.message);
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// 构建私钥路径
|
|
32
|
+
getPrivateKeyPath(appid) {
|
|
33
|
+
const isJenkins = Boolean(process.env.BUILD_URL);
|
|
34
|
+
const template = isJenkins
|
|
35
|
+
? "${WORKSPACE}/../mp-ci-upload-key/private.${APP_ID}.key"
|
|
36
|
+
: "./scripts/private.${APP_ID}.key";
|
|
37
|
+
|
|
38
|
+
return template
|
|
39
|
+
.replace("${WORKSPACE}", this.WORKSPACE || "")
|
|
40
|
+
.replace("${APP_ID}", appid);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// 构建预览码路径
|
|
44
|
+
getPreviewCodePath() {
|
|
45
|
+
const isJenkins = Boolean(process.env.BUILD_URL);
|
|
46
|
+
const template = isJenkins
|
|
47
|
+
? "${WORKSPACE}/../mp-ci-qrcode-back"
|
|
48
|
+
: "./scripts/previewCode";
|
|
49
|
+
|
|
50
|
+
return template.replace("${WORKSPACE}", this.WORKSPACE || "");
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async executeUpload(options) {
|
|
54
|
+
const {
|
|
55
|
+
appid,
|
|
56
|
+
projectPath,
|
|
57
|
+
version,
|
|
58
|
+
desc = "",
|
|
59
|
+
user = ""
|
|
60
|
+
} = options;
|
|
61
|
+
|
|
62
|
+
const gitEmail = this.getGitEmail();
|
|
63
|
+
const jenkinsURL = process.env.BUILD_URL ?? "";
|
|
64
|
+
const isJenkins = Boolean(jenkinsURL);
|
|
65
|
+
|
|
66
|
+
const envConfig = this.ENV_MAP[this.ENV];
|
|
67
|
+
if (!envConfig) {
|
|
68
|
+
throw new Error(`不支持的env环境: ${this.ENV}`);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const fullVersion = `${version}${envConfig.v}`;
|
|
72
|
+
const fullDesc = `${envConfig.desc} ${desc} upload by ${
|
|
73
|
+
gitEmail || user || "Jenkins "
|
|
74
|
+
} ${jenkinsURL ? `from JenkinsURL: ${jenkinsURL}` : ""}`;
|
|
75
|
+
|
|
76
|
+
const project = new ci.Project({
|
|
77
|
+
appid: appid,
|
|
78
|
+
type: "miniProgram",
|
|
79
|
+
projectPath: projectPath,
|
|
80
|
+
privateKeyPath: this.getPrivateKeyPath(appid),
|
|
81
|
+
ignores: ["node_modules/**/*"],
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// 上传小程序
|
|
85
|
+
console.log("========= 运行上传小程序函数 ==========");
|
|
86
|
+
const uploadResult = await ci.upload({
|
|
87
|
+
project,
|
|
88
|
+
robot: envConfig.robot,
|
|
89
|
+
version: fullVersion,
|
|
90
|
+
desc: fullDesc,
|
|
91
|
+
setting: {
|
|
92
|
+
useProjectConfig: true,
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
console.log("上传小程序结果 uploadResult: ", uploadResult);
|
|
96
|
+
|
|
97
|
+
// 生成预览二维码
|
|
98
|
+
console.log("========= 运行预览并生成二维码函数 ==========");
|
|
99
|
+
const qrCodePath = `${this.getPreviewCodePath()}/code.jpg`;
|
|
100
|
+
const previewResult = await ci.preview({
|
|
101
|
+
project,
|
|
102
|
+
robot: envConfig.robot,
|
|
103
|
+
desc: `${fullVersion} ${fullDesc}`,
|
|
104
|
+
setting: {
|
|
105
|
+
useProjectConfig: true,
|
|
106
|
+
},
|
|
107
|
+
qrcodeFormat: "image",
|
|
108
|
+
qrcodeOutputDest: qrCodePath,
|
|
109
|
+
});
|
|
110
|
+
console.log(`二维码路径:${qrCodePath}`);
|
|
111
|
+
console.log("预览并生成二维码结果 previewResult: ", previewResult);
|
|
112
|
+
|
|
113
|
+
console.log("========= 小程序上传结果 ==========");
|
|
114
|
+
console.log(`由机器人${envConfig.robot}上传`);
|
|
115
|
+
console.log(`版本:${fullVersion}`);
|
|
116
|
+
console.log(`描述:${fullDesc}`);
|
|
117
|
+
console.log("============ end ==============");
|
|
118
|
+
|
|
119
|
+
return {
|
|
120
|
+
uploadResult,
|
|
121
|
+
previewResult,
|
|
122
|
+
qrCodePath
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
async promptForMissingOptions() {
|
|
127
|
+
const questions = [];
|
|
128
|
+
|
|
129
|
+
if (!this.options.appid) {
|
|
130
|
+
questions.push({
|
|
131
|
+
type: "input",
|
|
132
|
+
name: "appid",
|
|
133
|
+
message: "请输入小程序ID",
|
|
134
|
+
validate: input => input ? true : "小程序ID不能为空"
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (!this.options.projectPath) {
|
|
139
|
+
questions.push({
|
|
140
|
+
type: "input",
|
|
141
|
+
name: "projectPath",
|
|
142
|
+
message: "请输入小程序项目打包后的代码路径",
|
|
143
|
+
validate: input => input ? true : "项目路径不能为空"
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if (!this.options.version) {
|
|
148
|
+
questions.push({
|
|
149
|
+
type: "input",
|
|
150
|
+
name: "version",
|
|
151
|
+
message: "请输入版本号",
|
|
152
|
+
validate: input => input ? true : "版本号不能为空"
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (!this.options.desc) {
|
|
157
|
+
questions.push({
|
|
158
|
+
type: "input",
|
|
159
|
+
name: "desc",
|
|
160
|
+
message: "请输入版本描述",
|
|
161
|
+
default: ""
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (questions.length > 0) {
|
|
166
|
+
const answers = await inquirer.prompt(questions);
|
|
167
|
+
this.options = { ...this.options, ...answers };
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return this.options;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
async run() {
|
|
174
|
+
try {
|
|
175
|
+
await this.promptForMissingOptions();
|
|
176
|
+
|
|
177
|
+
if (!this.options.appid || !this.options.projectPath || !this.options.version) {
|
|
178
|
+
throw new Error("缺少必要参数: appid, projectPath, version");
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return await this.executeUpload(this.options);
|
|
182
|
+
} catch (error) {
|
|
183
|
+
console.error("执行失败:", error.message);
|
|
184
|
+
process.exit(1);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
module.exports = function uploadMiniprogram(options = {}) {
|
|
190
|
+
const uploader = new UploadMiniprogram(options);
|
|
191
|
+
return uploader.run();
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
module.exports.UploadMiniprogram = UploadMiniprogram;
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "upload-miniprogram",
|
|
3
|
+
"version": "0.0.20",
|
|
4
|
+
"description": "chatlabs 集成 微信小程序CI/CD上传工具,支持自动上传代码和生成预览二维码",
|
|
5
|
+
"main": "lib/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"upload-miniprogram": "bin/upload-miniprogram.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"start": "node bin/upload-miniprogram.js",
|
|
11
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"miniprogram",
|
|
15
|
+
"wechat",
|
|
16
|
+
"ci",
|
|
17
|
+
"cd",
|
|
18
|
+
"upload",
|
|
19
|
+
"qrcode"
|
|
20
|
+
],
|
|
21
|
+
"author": "cynthia",
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"miniprogram-ci": "^1.9.0",
|
|
25
|
+
"inquirer": "^8.2.4",
|
|
26
|
+
"commander": "^9.4.1"
|
|
27
|
+
},
|
|
28
|
+
"engines": {
|
|
29
|
+
"node": ">=14.0.0"
|
|
30
|
+
},
|
|
31
|
+
"repository": {
|
|
32
|
+
"type": "git",
|
|
33
|
+
"url": "git+https://github.com/chatlabs/upload-miniprogram.git"
|
|
34
|
+
},
|
|
35
|
+
"bugs": {
|
|
36
|
+
"url": "https://github.com/chatlabs/upload-miniprogram/issues"
|
|
37
|
+
},
|
|
38
|
+
"homepage": "https://github.com/chatlabs/upload-miniprogram#readme",
|
|
39
|
+
"publishConfig": {
|
|
40
|
+
"access": "public"
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
|
|
6
|
+
console.log('🚀 准备发布 upload-miniprogram npm 包...');
|
|
7
|
+
|
|
8
|
+
// 检查 package.json
|
|
9
|
+
const packageJsonPath = path.join(__dirname, '..', 'package.json');
|
|
10
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
11
|
+
|
|
12
|
+
console.log('📦 包信息:');
|
|
13
|
+
console.log(` 名称: ${packageJson.name}`);
|
|
14
|
+
console.log(` 版本: ${packageJson.version}`);
|
|
15
|
+
console.log(` 描述: ${packageJson.description}`);
|
|
16
|
+
|
|
17
|
+
// 检查必要的文件是否存在
|
|
18
|
+
const requiredFiles = [
|
|
19
|
+
'package.json',
|
|
20
|
+
'README.md',
|
|
21
|
+
'CHANGELOG.md',
|
|
22
|
+
'bin/upload-miniprogram.js',
|
|
23
|
+
'lib/index.js'
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
console.log('📁 检查必要文件:');
|
|
27
|
+
requiredFiles.forEach(file => {
|
|
28
|
+
const filePath = path.join(__dirname, '..', file);
|
|
29
|
+
if (fs.existsSync(filePath)) {
|
|
30
|
+
console.log(` ✅ ${file}`);
|
|
31
|
+
} else {
|
|
32
|
+
console.log(` ❌ ${file} - 文件缺失`);
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// 检查 .npmignore 配置
|
|
38
|
+
const npmignorePath = path.join(__dirname, '..', '.npmignore');
|
|
39
|
+
if (fs.existsSync(npmignorePath)) {
|
|
40
|
+
console.log('📋 .npmignore 配置检查: ✅');
|
|
41
|
+
} else {
|
|
42
|
+
console.log('📋 .npmignore 配置检查: ⚠️ 文件缺失,建议创建');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
console.log('\n🎯 发布命令:');
|
|
46
|
+
console.log(' npm publish --access public');
|
|
47
|
+
console.log('\n📚 测试安装命令:');
|
|
48
|
+
console.log(' npm pack');
|
|
49
|
+
console.log(' npm install -g upload-miniprogram-1.0.0.tgz');
|
|
50
|
+
|
|
51
|
+
console.log('\n✅ 发布准备完成!');
|
|
Binary file
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/* eslint-disable import/no-commonjs */
|
|
2
|
+
// https://www.npmjs.com/package/miniprogram-ci
|
|
3
|
+
|
|
4
|
+
const ci = require("miniprogram-ci");
|
|
5
|
+
const { execSync } = require("child_process");
|
|
6
|
+
const inquirer = require("inquirer");
|
|
7
|
+
|
|
8
|
+
const WORKSPACE = process.env.WORKSPACE;
|
|
9
|
+
|
|
10
|
+
let APP_ID = ""; // 小程序ID
|
|
11
|
+
let PROJECT_PATH = ""; // 小程序项目打包后的代码路径
|
|
12
|
+
|
|
13
|
+
const PRIVATE_KEY_PATH_JENKINS =
|
|
14
|
+
"${WORKSPACE}/../mp-ci-upload-key/private.${APP_ID}.key".replace(
|
|
15
|
+
"${WORKSPACE}",
|
|
16
|
+
WORKSPACE
|
|
17
|
+
); // 小程序私钥路径(需要存在Jerkin服务器,不要存在项目文件里)
|
|
18
|
+
const PREVIEW_CODE_PATH_JENKINS = "${WORKSPACE}/../mp-ci-qrcode-back".replace(
|
|
19
|
+
"${WORKSPACE}",
|
|
20
|
+
WORKSPACE
|
|
21
|
+
); // 小程序预览Code的路径
|
|
22
|
+
const PRIVATE_KEY_PATH_LOCAL = "./scripts/private.${APP_ID}.key"; // 小程序私钥路径(需要存在Jerkin服务器,不要存在项目文件里,如不需要本地执行,可以忽略该配置)
|
|
23
|
+
const PREVIEW_CODE_PATH_LOCAL = "./scripts/previewCode"; // 本地预览二维码路径(本地运行命令时才会用到,也要配置本地的IP,如不需要本地执行,可以忽略该配置)
|
|
24
|
+
const PREVIEW_CODE_FILE_NAME = "code.jpg"; // 预览二维码文件名 "code-${version}.jpg"
|
|
25
|
+
|
|
26
|
+
const ENV = process.env.NODE_ENV;
|
|
27
|
+
const ENV_MAP = {
|
|
28
|
+
development: { v: ".dev", desc: "【Dev环境】", robot: 1 },
|
|
29
|
+
staging: { v: ".staging", desc: "【Staging环境】", robot: 2 },
|
|
30
|
+
uat: { v: ".uat", desc: "【Uat环境】", robot: 3 },
|
|
31
|
+
production: { v: "", desc: "【正式环境】", robot: 5 },
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const env_argv = process.argv;
|
|
35
|
+
console.log("argvs", env_argv);
|
|
36
|
+
|
|
37
|
+
let v_in_argv, d_in_argv, u_in_argv;
|
|
38
|
+
|
|
39
|
+
env_argv.forEach((item) => {
|
|
40
|
+
if (item.includes("version")) {
|
|
41
|
+
v_in_argv = item.split("=")[1];
|
|
42
|
+
}
|
|
43
|
+
if (item.includes("desc")) {
|
|
44
|
+
d_in_argv = item.split("=")[1];
|
|
45
|
+
}
|
|
46
|
+
if (item.includes("user")) {
|
|
47
|
+
u_in_argv = item.split("=")[1];
|
|
48
|
+
}
|
|
49
|
+
if (item.includes("appid")) {
|
|
50
|
+
APP_ID = item.split("=")[1];
|
|
51
|
+
}
|
|
52
|
+
if (item.includes("project-path")) {
|
|
53
|
+
PROJECT_PATH = item.split("=")[1];
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// 获取 Git 邮箱
|
|
58
|
+
function getGitEmail() {
|
|
59
|
+
try {
|
|
60
|
+
return execSync("git config --global user.email", {
|
|
61
|
+
encoding: "utf8",
|
|
62
|
+
}).trim();
|
|
63
|
+
} catch (error) {
|
|
64
|
+
console.error("无法获取 Git 邮箱:", error.message);
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const executeUploadMPCode = async () => {
|
|
70
|
+
const gitEmail = getGitEmail();
|
|
71
|
+
const JerkinsURL = process.env.BUILD_URL ?? "";
|
|
72
|
+
const isJerkin = Boolean(JerkinsURL);
|
|
73
|
+
|
|
74
|
+
const version = `${v_in_argv}${ENV_MAP[ENV].v}`;
|
|
75
|
+
const desc = `${d_in_argv || ""}`;
|
|
76
|
+
const fullDesc = `${ENV_MAP[ENV].desc} ${desc} upload by ${
|
|
77
|
+
gitEmail || u_in_argv || "Jenkins "
|
|
78
|
+
} ${JerkinsURL ? `from JerkinsURL: ${JerkinsURL}` : ""} `;
|
|
79
|
+
|
|
80
|
+
const project = new ci.Project({
|
|
81
|
+
appid: APP_ID,
|
|
82
|
+
type: "miniProgram",
|
|
83
|
+
projectPath: PROJECT_PATH,
|
|
84
|
+
privateKeyPath: isJerkin
|
|
85
|
+
? PRIVATE_KEY_PATH_JENKINS.replace("${APP_ID}", APP_ID)
|
|
86
|
+
: PRIVATE_KEY_PATH_LOCAL.replace("${APP_ID}", APP_ID),
|
|
87
|
+
ignores: ["node_modules/**/*"],
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// 上传小程序
|
|
91
|
+
|
|
92
|
+
console.log("========= 运行上传小程序函数 ==========");
|
|
93
|
+
const uploadResult = await ci.upload({
|
|
94
|
+
project,
|
|
95
|
+
robot: ENV_MAP[ENV].robot,
|
|
96
|
+
version: version,
|
|
97
|
+
desc: fullDesc,
|
|
98
|
+
setting: {
|
|
99
|
+
useProjectConfig: true,
|
|
100
|
+
},
|
|
101
|
+
// onProgressUpdate: console.log,
|
|
102
|
+
});
|
|
103
|
+
console.log("上传小程序结果 uploadResult: ", uploadResult);
|
|
104
|
+
|
|
105
|
+
console.log("========= 运行预览并生成二维码函数 ==========");
|
|
106
|
+
const qrCodePath = `${
|
|
107
|
+
isJerkin ? PREVIEW_CODE_PATH_JENKINS : PREVIEW_CODE_PATH_LOCAL
|
|
108
|
+
}/${PREVIEW_CODE_FILE_NAME.replace("${version}", version)}`;
|
|
109
|
+
const previewResult = await ci.preview({
|
|
110
|
+
project,
|
|
111
|
+
robot: ENV_MAP[ENV].robot,
|
|
112
|
+
desc: `${version} ${fullDesc}`,
|
|
113
|
+
setting: {
|
|
114
|
+
useProjectConfig: true,
|
|
115
|
+
},
|
|
116
|
+
qrcodeFormat: "image",
|
|
117
|
+
qrcodeOutputDest: qrCodePath, // 服务器链接,可以定期清除,这个是必填字段
|
|
118
|
+
// onProgressUpdate: console.log,
|
|
119
|
+
});
|
|
120
|
+
console.log(
|
|
121
|
+
`二维码路径:${qrCodePath} (可能不生效或无权限,建议直接从小程序助手进入查看)`
|
|
122
|
+
);
|
|
123
|
+
console.log("预览并生成二维码结果 previewResult: ", previewResult);
|
|
124
|
+
|
|
125
|
+
console.log("========= 小程序上传结果 ==========");
|
|
126
|
+
console.log(`由机器人${ENV_MAP[ENV].robot}上传`);
|
|
127
|
+
console.log(`版本:${version}`);
|
|
128
|
+
console.log(`描述: ${fullDesc}`);
|
|
129
|
+
console.log("============ end ==============");
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
(async () => {
|
|
133
|
+
if (!ENV_MAP[ENV]) {
|
|
134
|
+
console.error("env is not supported: ", ENV);
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (!v_in_argv || !APP_ID || !PROJECT_PATH) {
|
|
139
|
+
console.error("version is required");
|
|
140
|
+
|
|
141
|
+
const questions = [];
|
|
142
|
+
|
|
143
|
+
if (!APP_ID) {
|
|
144
|
+
questions.push({
|
|
145
|
+
type: "input",
|
|
146
|
+
name: "appid",
|
|
147
|
+
message: "请输入小程序ID",
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (!PROJECT_PATH) {
|
|
152
|
+
questions.push({
|
|
153
|
+
type: "input",
|
|
154
|
+
name: "projectPath",
|
|
155
|
+
message: "请输入小程序项目打包后的代码路径",
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (!v_in_argv) {
|
|
160
|
+
questions.push({
|
|
161
|
+
type: "input",
|
|
162
|
+
name: "version",
|
|
163
|
+
message: "请输入版本号",
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
if (!d_in_argv) {
|
|
167
|
+
questions.push({
|
|
168
|
+
type: "input",
|
|
169
|
+
name: "desc",
|
|
170
|
+
message: "请输入版本描述",
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
inquirer.prompt(questions).then(function (answers) {
|
|
175
|
+
let { version = "", desc = "", appid = "", projectPath = "" } = answers;
|
|
176
|
+
|
|
177
|
+
v_in_argv = version;
|
|
178
|
+
if (desc) d_in_argv = desc;
|
|
179
|
+
if (appid) APP_ID = appid;
|
|
180
|
+
if (projectPath) PROJECT_PATH = projectPath;
|
|
181
|
+
if (version) {
|
|
182
|
+
executeUploadMPCode();
|
|
183
|
+
} else {
|
|
184
|
+
console.log("版本号不能为空");
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
return;
|
|
188
|
+
} else {
|
|
189
|
+
executeUploadMPCode();
|
|
190
|
+
}
|
|
191
|
+
})();
|