fe-build-cli 1.2.4 → 1.5.0
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/README.md +248 -11
- package/package.json +1 -1
- package/src/cli.js +197 -26
- package/src/config-template.js +14 -1
- package/src/deploy-core.js +310 -64
- package/src/dingtalk.js +31 -17
- package/src/git-branch.js +191 -34
- package/src/index.js +13 -1
- package/src/logger.js +381 -0
- package/src/ssh-client.js +69 -0
package/src/git-branch.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { execSync } from 'node:child_process';
|
|
2
|
+
import { DeployLogger } from './logger.js';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Git 分支管理模块
|
|
5
6
|
* 支持当前分支发布和主分支发布两种模式
|
|
7
|
+
* 集成日志记录,记录每一步操作及状态
|
|
6
8
|
*/
|
|
7
9
|
|
|
8
10
|
/**
|
|
@@ -30,6 +32,32 @@ export function getGitSha() {
|
|
|
30
32
|
}
|
|
31
33
|
}
|
|
32
34
|
|
|
35
|
+
/**
|
|
36
|
+
* 获取最近一次 Git 提交信息
|
|
37
|
+
* @returns {string} 提交信息
|
|
38
|
+
*/
|
|
39
|
+
export function getGitCommitMessage() {
|
|
40
|
+
try {
|
|
41
|
+
return execSync('git log -1 --pretty=format:"%s"', { encoding: 'utf-8' }).trim();
|
|
42
|
+
} catch (error) {
|
|
43
|
+
return '';
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* 获取最近 N 次 Git 提交信息
|
|
49
|
+
* @param {number} count - 提交数量
|
|
50
|
+
* @returns {string} 提交信息列表
|
|
51
|
+
*/
|
|
52
|
+
export function getGitCommitMessages(count = 3) {
|
|
53
|
+
try {
|
|
54
|
+
const messages = execSync(`git log -${count} --pretty=format:"%s"`, { encoding: 'utf-8' }).trim();
|
|
55
|
+
return messages.split('\n').map(m => `- ${m}`).join('\n');
|
|
56
|
+
} catch (error) {
|
|
57
|
+
return '';
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
33
61
|
/**
|
|
34
62
|
* 检查工作区是否干净
|
|
35
63
|
* @returns {boolean} 是否干净
|
|
@@ -63,13 +91,25 @@ export function checkUncommittedChanges() {
|
|
|
63
91
|
/**
|
|
64
92
|
* 切换到指定分支
|
|
65
93
|
* @param {string} branchName - 分支名
|
|
94
|
+
* @param {DeployLogger} logger - 日志记录器(可选)
|
|
66
95
|
*/
|
|
67
|
-
export function checkoutBranch(branchName) {
|
|
96
|
+
export function checkoutBranch(branchName, logger = null) {
|
|
97
|
+
const fromBranch = getCurrentBranch();
|
|
68
98
|
try {
|
|
69
99
|
console.log(`\n📌 切换到分支: ${branchName}`);
|
|
70
100
|
execSync(`git checkout ${branchName}`, { stdio: 'inherit' });
|
|
71
101
|
console.log(`✅ 已切换到 ${branchName}`);
|
|
102
|
+
|
|
103
|
+
// 记录日志
|
|
104
|
+
if (logger) {
|
|
105
|
+
logger.logBranch('切换分支', fromBranch, branchName, true);
|
|
106
|
+
}
|
|
107
|
+
return true;
|
|
72
108
|
} catch (error) {
|
|
109
|
+
// 记录失败日志
|
|
110
|
+
if (logger) {
|
|
111
|
+
logger.logBranch('切换分支', fromBranch, branchName, false, error.message);
|
|
112
|
+
}
|
|
73
113
|
throw new Error(`切换到分支 ${branchName} 失败: ${error.message}`);
|
|
74
114
|
}
|
|
75
115
|
}
|
|
@@ -92,16 +132,28 @@ export function pullBranch(branchName) {
|
|
|
92
132
|
* 合并分支
|
|
93
133
|
* @param {string} sourceBranch - 源分支
|
|
94
134
|
* @param {string} targetBranch - 目标分支(当前所在分支)
|
|
135
|
+
* @param {DeployLogger} logger - 日志记录器(可选)
|
|
95
136
|
* @returns {boolean} 是否成功
|
|
96
137
|
*/
|
|
97
|
-
export function mergeBranch(sourceBranch, targetBranch) {
|
|
138
|
+
export function mergeBranch(sourceBranch, targetBranch, logger = null) {
|
|
98
139
|
try {
|
|
99
140
|
console.log(`\n🔀 合并 ${sourceBranch} 到 ${targetBranch}...`);
|
|
100
141
|
execSync(`git merge ${sourceBranch} --no-edit`, { stdio: 'inherit' });
|
|
101
142
|
console.log(`✅ 合并成功`);
|
|
143
|
+
|
|
144
|
+
// 记录日志
|
|
145
|
+
if (logger) {
|
|
146
|
+
logger.logMerge(sourceBranch, targetBranch, true);
|
|
147
|
+
}
|
|
102
148
|
return true;
|
|
103
149
|
} catch (error) {
|
|
104
150
|
console.error(`❌ 合并失败: ${error.message}`);
|
|
151
|
+
|
|
152
|
+
// 记录失败日志
|
|
153
|
+
if (logger) {
|
|
154
|
+
logger.logMerge(sourceBranch, targetBranch, false, true);
|
|
155
|
+
}
|
|
156
|
+
|
|
105
157
|
// 尝试中止合并
|
|
106
158
|
try {
|
|
107
159
|
execSync('git merge --abort', { stdio: 'inherit' });
|
|
@@ -130,9 +182,10 @@ export function pushBranch(branchName) {
|
|
|
130
182
|
/**
|
|
131
183
|
* 储藏本地改动(stash)
|
|
132
184
|
* @param {string} branchName - 当前分支名(用于备注)
|
|
185
|
+
* @param {DeployLogger} logger - 日志记录器(可选)
|
|
133
186
|
* @returns {boolean} 是否成功
|
|
134
187
|
*/
|
|
135
|
-
export function stashChanges(branchName = '') {
|
|
188
|
+
export function stashChanges(branchName = '', logger = null) {
|
|
136
189
|
try {
|
|
137
190
|
console.log('\n📦 储藏本地改动...');
|
|
138
191
|
const stashMessage = branchName
|
|
@@ -140,26 +193,47 @@ export function stashChanges(branchName = '') {
|
|
|
140
193
|
: 'fe-build-cli-auto-stash';
|
|
141
194
|
execSync(`git stash push -m "${stashMessage}"`, { stdio: 'inherit' });
|
|
142
195
|
console.log('✅ 本地改动已储藏');
|
|
196
|
+
|
|
197
|
+
// 记录日志
|
|
198
|
+
if (logger) {
|
|
199
|
+
logger.logStash('储藏改动', true, `分支: ${branchName || getCurrentBranch()}`);
|
|
200
|
+
}
|
|
143
201
|
return true;
|
|
144
202
|
} catch (error) {
|
|
145
203
|
console.error('❌ 储藏失败:', error.message);
|
|
204
|
+
|
|
205
|
+
// 记录失败日志
|
|
206
|
+
if (logger) {
|
|
207
|
+
logger.logStash('储藏改动', false, error.message);
|
|
208
|
+
}
|
|
146
209
|
return false;
|
|
147
210
|
}
|
|
148
211
|
}
|
|
149
212
|
|
|
150
213
|
/**
|
|
151
214
|
* 恢复储藏的改动(stash pop)
|
|
215
|
+
* @param {DeployLogger} logger - 日志记录器(可选)
|
|
152
216
|
* @returns {boolean} 是否成功
|
|
153
217
|
*/
|
|
154
|
-
export function stashPop() {
|
|
218
|
+
export function stashPop(logger = null) {
|
|
155
219
|
try {
|
|
156
220
|
console.log('\n📦 恢复储藏的改动...');
|
|
157
221
|
execSync('git stash pop', { stdio: 'inherit' });
|
|
158
222
|
console.log('✅ 本地改动已恢复');
|
|
223
|
+
|
|
224
|
+
// 记录日志
|
|
225
|
+
if (logger) {
|
|
226
|
+
logger.logStash('恢复改动', true);
|
|
227
|
+
}
|
|
159
228
|
return true;
|
|
160
229
|
} catch (error) {
|
|
161
230
|
console.error('❌ 恢复失败:', error.message);
|
|
162
231
|
console.log('💡 提示: 可能存在冲突,请手动执行 git stash pop 解决');
|
|
232
|
+
|
|
233
|
+
// 记录失败日志
|
|
234
|
+
if (logger) {
|
|
235
|
+
logger.logStash('恢复改动', false, error.message);
|
|
236
|
+
}
|
|
163
237
|
return false;
|
|
164
238
|
}
|
|
165
239
|
}
|
|
@@ -167,9 +241,11 @@ export function stashPop() {
|
|
|
167
241
|
/**
|
|
168
242
|
* 自动提交当前分支的所有改动
|
|
169
243
|
* @param {string} message - 提交信息
|
|
244
|
+
* @param {DeployLogger} logger - 日志记录器(可选)
|
|
170
245
|
* @returns {boolean} 是否成功
|
|
171
246
|
*/
|
|
172
|
-
export function autoCommit(message) {
|
|
247
|
+
export function autoCommit(message, logger = null) {
|
|
248
|
+
const currentBranch = getCurrentBranch();
|
|
173
249
|
try {
|
|
174
250
|
console.log('\n📝 自动提交改动...');
|
|
175
251
|
// 添加所有改动
|
|
@@ -177,9 +253,19 @@ export function autoCommit(message) {
|
|
|
177
253
|
// 提交
|
|
178
254
|
execSync(`git commit -m "${message}"`, { stdio: 'inherit' });
|
|
179
255
|
console.log('✅ 改动已提交');
|
|
256
|
+
|
|
257
|
+
// 记录日志
|
|
258
|
+
if (logger) {
|
|
259
|
+
logger.log('SUCCESS', '自动提交', `分支: ${currentBranch}, 提交信息: ${message}`);
|
|
260
|
+
}
|
|
180
261
|
return true;
|
|
181
262
|
} catch (error) {
|
|
182
263
|
console.error('❌ 提交失败:', error.message);
|
|
264
|
+
|
|
265
|
+
// 记录失败日志
|
|
266
|
+
if (logger) {
|
|
267
|
+
logger.log('ERROR', '自动提交', `分支: ${currentBranch}, 错误: ${error.message}`);
|
|
268
|
+
}
|
|
183
269
|
return false;
|
|
184
270
|
}
|
|
185
271
|
}
|
|
@@ -191,10 +277,11 @@ export function autoCommit(message) {
|
|
|
191
277
|
* @param {string} config.testBranch - 测试分支名
|
|
192
278
|
* @param {string} config.mainBranch - 主分支名
|
|
193
279
|
* @param {boolean} config.pushToRemote - 是否推送到远程
|
|
280
|
+
* @param {DeployLogger} config.logger - 日志记录器(可选)
|
|
194
281
|
* @returns {object} 执行结果
|
|
195
282
|
*/
|
|
196
283
|
export function executeMainBranchFlow(config) {
|
|
197
|
-
const { testBranch, mainBranch, pushToRemote = true } = config;
|
|
284
|
+
const { testBranch, mainBranch, pushToRemote = true, logger = null } = config;
|
|
198
285
|
const originalBranch = getCurrentBranch();
|
|
199
286
|
|
|
200
287
|
console.log('\n========================================');
|
|
@@ -205,21 +292,29 @@ export function executeMainBranchFlow(config) {
|
|
|
205
292
|
console.log(`主分支: ${mainBranch}`);
|
|
206
293
|
console.log('========================================');
|
|
207
294
|
|
|
295
|
+
// 记录开始日志
|
|
296
|
+
if (logger) {
|
|
297
|
+
logger.log('INFO', '主分支发布流程', `当前分支: ${originalBranch}, 测试分支: ${testBranch}, 主分支: ${mainBranch}`);
|
|
298
|
+
}
|
|
299
|
+
|
|
208
300
|
// 检查工作区状态
|
|
209
301
|
const { clean, changes } = checkUncommittedChanges();
|
|
210
302
|
if (!clean) {
|
|
211
303
|
console.error('❌ 工作区有未提交的更改:');
|
|
212
304
|
changes.forEach(change => console.log(` ${change}`));
|
|
305
|
+
if (logger) {
|
|
306
|
+
logger.log('ERROR', '工作区检查', '存在未提交的更改');
|
|
307
|
+
}
|
|
213
308
|
throw new Error('请先提交或暂存更改后再执行发布');
|
|
214
309
|
}
|
|
215
310
|
|
|
216
311
|
try {
|
|
217
312
|
// 步骤1: 切换到测试分支并拉取最新代码
|
|
218
|
-
checkoutBranch(testBranch);
|
|
313
|
+
checkoutBranch(testBranch, logger);
|
|
219
314
|
pullBranch(testBranch);
|
|
220
315
|
|
|
221
316
|
// 步骤2: 合并当前分支到测试分支
|
|
222
|
-
if (!mergeBranch(originalBranch, testBranch)) {
|
|
317
|
+
if (!mergeBranch(originalBranch, testBranch, logger)) {
|
|
223
318
|
throw new Error(`合并 ${originalBranch} 到 ${testBranch} 失败`);
|
|
224
319
|
}
|
|
225
320
|
|
|
@@ -229,11 +324,11 @@ export function executeMainBranchFlow(config) {
|
|
|
229
324
|
}
|
|
230
325
|
|
|
231
326
|
// 步骤4: 切换到主分支并拉取最新代码
|
|
232
|
-
checkoutBranch(mainBranch);
|
|
327
|
+
checkoutBranch(mainBranch, logger);
|
|
233
328
|
pullBranch(mainBranch);
|
|
234
329
|
|
|
235
330
|
// 步骤5: 合并测试分支到主分支
|
|
236
|
-
if (!mergeBranch(testBranch, mainBranch)) {
|
|
331
|
+
if (!mergeBranch(testBranch, mainBranch, logger)) {
|
|
237
332
|
throw new Error(`合并 ${testBranch} 到 ${mainBranch} 失败`);
|
|
238
333
|
}
|
|
239
334
|
|
|
@@ -247,6 +342,10 @@ export function executeMainBranchFlow(config) {
|
|
|
247
342
|
console.log(`当前分支: ${mainBranch}`);
|
|
248
343
|
console.log('========================================');
|
|
249
344
|
|
|
345
|
+
if (logger) {
|
|
346
|
+
logger.log('SUCCESS', '主分支发布流程', `完成,当前分支: ${mainBranch}`);
|
|
347
|
+
}
|
|
348
|
+
|
|
250
349
|
return {
|
|
251
350
|
success: true,
|
|
252
351
|
originalBranch,
|
|
@@ -257,7 +356,7 @@ export function executeMainBranchFlow(config) {
|
|
|
257
356
|
} catch (error) {
|
|
258
357
|
// 出错时尝试切回原分支
|
|
259
358
|
try {
|
|
260
|
-
checkoutBranch(originalBranch);
|
|
359
|
+
checkoutBranch(originalBranch, logger);
|
|
261
360
|
} catch (e) {
|
|
262
361
|
// 忽略
|
|
263
362
|
}
|
|
@@ -268,9 +367,10 @@ export function executeMainBranchFlow(config) {
|
|
|
268
367
|
/**
|
|
269
368
|
* 执行当前分支发布流程
|
|
270
369
|
* 不切换分支,直接在当前分支发布
|
|
370
|
+
* @param {DeployLogger} logger - 日志记录器(可选)
|
|
271
371
|
* @returns {object} 执行结果
|
|
272
372
|
*/
|
|
273
|
-
export function executeCurrentBranchFlow() {
|
|
373
|
+
export function executeCurrentBranchFlow(logger = null) {
|
|
274
374
|
const currentBranch = getCurrentBranch();
|
|
275
375
|
const gitSha = getGitSha();
|
|
276
376
|
|
|
@@ -281,6 +381,11 @@ export function executeCurrentBranchFlow() {
|
|
|
281
381
|
console.log(`提交 SHA: ${gitSha}`);
|
|
282
382
|
console.log('========================================');
|
|
283
383
|
|
|
384
|
+
// 记录日志
|
|
385
|
+
if (logger) {
|
|
386
|
+
logger.log('INFO', '当前分支发布', `分支: ${currentBranch}, SHA: ${gitSha}`);
|
|
387
|
+
}
|
|
388
|
+
|
|
284
389
|
return {
|
|
285
390
|
success: true,
|
|
286
391
|
originalBranch: currentBranch,
|
|
@@ -296,10 +401,11 @@ export function executeCurrentBranchFlow() {
|
|
|
296
401
|
* @param {boolean} config.mergeChanges - 是否合并本地改动
|
|
297
402
|
* @param {boolean} config.pushToRemote - 是否推送到远程
|
|
298
403
|
* @param {function} config.prompt - 交互提示函数
|
|
404
|
+
* @param {DeployLogger} config.logger - 日志记录器(可选)
|
|
299
405
|
* @returns {object} 执行结果
|
|
300
406
|
*/
|
|
301
407
|
export async function executeTestBranchFlow(config) {
|
|
302
|
-
const { testBranch, mergeChanges, pushToRemote = true, prompt } = config;
|
|
408
|
+
const { testBranch, mergeChanges, pushToRemote = true, prompt, logger = null } = config;
|
|
303
409
|
const originalBranch = getCurrentBranch();
|
|
304
410
|
const { clean, changes } = checkUncommittedChanges();
|
|
305
411
|
|
|
@@ -311,10 +417,18 @@ export async function executeTestBranchFlow(config) {
|
|
|
311
417
|
console.log(`工作区状态: ${clean ? '干净' : '有未提交改动'}`);
|
|
312
418
|
console.log('========================================');
|
|
313
419
|
|
|
420
|
+
// 记录开始日志
|
|
421
|
+
if (logger) {
|
|
422
|
+
logger.log('INFO', 'Test 环境发布', `当前分支: ${originalBranch}, Test 分支: ${testBranch}, 工作区状态: ${clean ? '干净' : '有改动'}`);
|
|
423
|
+
}
|
|
424
|
+
|
|
314
425
|
// 情况1:当前分支本身就是 test
|
|
315
426
|
if (originalBranch === testBranch) {
|
|
316
427
|
console.log('\n✓ 当前已在 test 分支');
|
|
317
428
|
pullBranch(testBranch);
|
|
429
|
+
if (logger) {
|
|
430
|
+
logger.log('INFO', 'Test 发布', '当前已在 test 分支,拉取最新代码');
|
|
431
|
+
}
|
|
318
432
|
return {
|
|
319
433
|
success: true,
|
|
320
434
|
originalBranch,
|
|
@@ -327,7 +441,7 @@ export async function executeTestBranchFlow(config) {
|
|
|
327
441
|
// 情况2:当前分支 ≠ test,无本地改动
|
|
328
442
|
if (clean) {
|
|
329
443
|
console.log('\n✓ 无本地改动,直接切换发布');
|
|
330
|
-
checkoutBranch(testBranch);
|
|
444
|
+
checkoutBranch(testBranch, logger);
|
|
331
445
|
pullBranch(testBranch);
|
|
332
446
|
return {
|
|
333
447
|
success: true,
|
|
@@ -343,11 +457,15 @@ export async function executeTestBranchFlow(config) {
|
|
|
343
457
|
console.log('\n⚠️ 存在未提交的改动:');
|
|
344
458
|
changes.forEach(change => console.log(` ${change}`));
|
|
345
459
|
|
|
460
|
+
if (logger) {
|
|
461
|
+
logger.log('WARN', '工作区检查', `存在未提交改动: ${changes.length} 个文件`);
|
|
462
|
+
}
|
|
463
|
+
|
|
346
464
|
// 如果已确定合并选项,直接执行
|
|
347
465
|
if (mergeChanges === true) {
|
|
348
|
-
return await executeTestMergeFlow(originalBranch, testBranch, pushToRemote);
|
|
466
|
+
return await executeTestMergeFlow(originalBranch, testBranch, pushToRemote, logger);
|
|
349
467
|
} else if (mergeChanges === false) {
|
|
350
|
-
return await executeTestStashFlow(originalBranch, testBranch);
|
|
468
|
+
return await executeTestStashFlow(originalBranch, testBranch, logger);
|
|
351
469
|
}
|
|
352
470
|
|
|
353
471
|
// 否则交互询问
|
|
@@ -359,9 +477,9 @@ export async function executeTestBranchFlow(config) {
|
|
|
359
477
|
const answer = await prompt('请输入选项 (1/2): ');
|
|
360
478
|
|
|
361
479
|
if (answer === '1') {
|
|
362
|
-
return await executeTestMergeFlow(originalBranch, testBranch, pushToRemote);
|
|
480
|
+
return await executeTestMergeFlow(originalBranch, testBranch, pushToRemote, logger);
|
|
363
481
|
} else if (answer === '2') {
|
|
364
|
-
return await executeTestStashFlow(originalBranch, testBranch);
|
|
482
|
+
return await executeTestStashFlow(originalBranch, testBranch, logger);
|
|
365
483
|
} else {
|
|
366
484
|
throw new Error('无效选项,已取消发布');
|
|
367
485
|
}
|
|
@@ -372,38 +490,52 @@ export async function executeTestBranchFlow(config) {
|
|
|
372
490
|
|
|
373
491
|
/**
|
|
374
492
|
* 执行合并流程(提交当前分支,合并到 test)
|
|
493
|
+
* @param {string} originalBranch - 原分支名
|
|
494
|
+
* @param {string} testBranch - test 分支名
|
|
495
|
+
* @param {boolean} pushToRemote - 是否推送到远程
|
|
496
|
+
* @param {DeployLogger} logger - 日志记录器(可选)
|
|
375
497
|
*/
|
|
376
|
-
async function executeTestMergeFlow(originalBranch, testBranch, pushToRemote) {
|
|
498
|
+
async function executeTestMergeFlow(originalBranch, testBranch, pushToRemote, logger = null) {
|
|
377
499
|
console.log('\n========================================');
|
|
378
500
|
console.log(' 🔀 合并改动发布模式');
|
|
379
501
|
console.log('========================================');
|
|
380
502
|
|
|
503
|
+
if (logger) {
|
|
504
|
+
logger.log('INFO', '合并发布模式', `原分支: ${originalBranch}, Test 分支: ${testBranch}`);
|
|
505
|
+
}
|
|
506
|
+
|
|
381
507
|
try {
|
|
382
508
|
// 1. 自动提交当前分支改动(备注包含原分支名)
|
|
383
509
|
const commitMessage = `auto commit: deploy test from ${originalBranch}`;
|
|
384
|
-
if (!autoCommit(commitMessage)) {
|
|
510
|
+
if (!autoCommit(commitMessage, logger)) {
|
|
385
511
|
throw new Error('自动提交失败');
|
|
386
512
|
}
|
|
387
513
|
|
|
388
514
|
// 2. 推送当前分支到远程
|
|
389
515
|
if (pushToRemote) {
|
|
390
516
|
pushBranch(originalBranch);
|
|
517
|
+
if (logger) {
|
|
518
|
+
logger.log('SUCCESS', '推送分支', `推送 ${originalBranch} 到远程成功`);
|
|
519
|
+
}
|
|
391
520
|
}
|
|
392
521
|
|
|
393
522
|
// 3. 切换到 test 分支
|
|
394
|
-
checkoutBranch(testBranch);
|
|
523
|
+
checkoutBranch(testBranch, logger);
|
|
395
524
|
pullBranch(testBranch);
|
|
396
525
|
|
|
397
526
|
// 4. 合并当前分支到 test
|
|
398
|
-
if (!mergeBranch(originalBranch, testBranch)) {
|
|
527
|
+
if (!mergeBranch(originalBranch, testBranch, logger)) {
|
|
399
528
|
// 合并冲突,切回原分支
|
|
400
|
-
checkoutBranch(originalBranch);
|
|
529
|
+
checkoutBranch(originalBranch, logger);
|
|
401
530
|
throw new Error(`合并冲突: ${originalBranch} 到 ${testBranch},请手动解决冲突后重新发布`);
|
|
402
531
|
}
|
|
403
532
|
|
|
404
533
|
// 5. 推送 test 分支
|
|
405
534
|
if (pushToRemote) {
|
|
406
535
|
pushBranch(testBranch);
|
|
536
|
+
if (logger) {
|
|
537
|
+
logger.log('SUCCESS', '推送分支', `推送 ${testBranch} 到远程成功`);
|
|
538
|
+
}
|
|
407
539
|
}
|
|
408
540
|
|
|
409
541
|
console.log('\n========================================');
|
|
@@ -411,6 +543,10 @@ async function executeTestMergeFlow(originalBranch, testBranch, pushToRemote) {
|
|
|
411
543
|
console.log(`当前分支: ${testBranch}`);
|
|
412
544
|
console.log('========================================');
|
|
413
545
|
|
|
546
|
+
if (logger) {
|
|
547
|
+
logger.log('SUCCESS', '合并发布流程', `完成,当前分支: ${testBranch}`);
|
|
548
|
+
}
|
|
549
|
+
|
|
414
550
|
return {
|
|
415
551
|
success: true,
|
|
416
552
|
originalBranch,
|
|
@@ -421,9 +557,14 @@ async function executeTestMergeFlow(originalBranch, testBranch, pushToRemote) {
|
|
|
421
557
|
autoRestore: true // 合并模式自动切回
|
|
422
558
|
};
|
|
423
559
|
} catch (error) {
|
|
560
|
+
// 记录错误日志
|
|
561
|
+
if (logger) {
|
|
562
|
+
logger.log('ERROR', '合并发布流程', error.message);
|
|
563
|
+
}
|
|
564
|
+
|
|
424
565
|
// 出错时切回原分支
|
|
425
566
|
try {
|
|
426
|
-
checkoutBranch(originalBranch);
|
|
567
|
+
checkoutBranch(originalBranch, logger);
|
|
427
568
|
} catch (e) {
|
|
428
569
|
// 忽略
|
|
429
570
|
}
|
|
@@ -433,20 +574,27 @@ async function executeTestMergeFlow(originalBranch, testBranch, pushToRemote) {
|
|
|
433
574
|
|
|
434
575
|
/**
|
|
435
576
|
* 执行暂存流程(stash 储藏,用纯净 test 发布)
|
|
577
|
+
* @param {string} originalBranch - 原分支名
|
|
578
|
+
* @param {string} testBranch - test 分支名
|
|
579
|
+
* @param {DeployLogger} logger - 日志记录器(可选)
|
|
436
580
|
*/
|
|
437
|
-
async function executeTestStashFlow(originalBranch, testBranch) {
|
|
581
|
+
async function executeTestStashFlow(originalBranch, testBranch, logger = null) {
|
|
438
582
|
console.log('\n========================================');
|
|
439
583
|
console.log(' 📦 暂存改动发布模式');
|
|
440
584
|
console.log('========================================');
|
|
441
585
|
|
|
586
|
+
if (logger) {
|
|
587
|
+
logger.log('INFO', '暂存发布模式', `原分支: ${originalBranch}, Test 分支: ${testBranch}`);
|
|
588
|
+
}
|
|
589
|
+
|
|
442
590
|
try {
|
|
443
591
|
// 1. 储藏本地改动(备注包含原分支名)
|
|
444
|
-
if (!stashChanges(originalBranch)) {
|
|
592
|
+
if (!stashChanges(originalBranch, logger)) {
|
|
445
593
|
throw new Error('储藏改动失败');
|
|
446
594
|
}
|
|
447
595
|
|
|
448
596
|
// 2. 切换到 test 分支
|
|
449
|
-
checkoutBranch(testBranch);
|
|
597
|
+
checkoutBranch(testBranch, logger);
|
|
450
598
|
pullBranch(testBranch);
|
|
451
599
|
|
|
452
600
|
console.log('\n========================================');
|
|
@@ -454,6 +602,10 @@ async function executeTestStashFlow(originalBranch, testBranch) {
|
|
|
454
602
|
console.log(`当前分支: ${testBranch}`);
|
|
455
603
|
console.log('========================================');
|
|
456
604
|
|
|
605
|
+
if (logger) {
|
|
606
|
+
logger.log('SUCCESS', '暂存发布流程', `完成,当前分支: ${testBranch}`);
|
|
607
|
+
}
|
|
608
|
+
|
|
457
609
|
return {
|
|
458
610
|
success: true,
|
|
459
611
|
originalBranch,
|
|
@@ -463,10 +615,15 @@ async function executeTestStashFlow(originalBranch, testBranch) {
|
|
|
463
615
|
autoRestore: false // stash 模式询问是否切回
|
|
464
616
|
};
|
|
465
617
|
} catch (error) {
|
|
618
|
+
// 记录错误日志
|
|
619
|
+
if (logger) {
|
|
620
|
+
logger.log('ERROR', '暂存发布流程', error.message);
|
|
621
|
+
}
|
|
622
|
+
|
|
466
623
|
// 出错时切回原分支并恢复 stash
|
|
467
624
|
try {
|
|
468
|
-
checkoutBranch(originalBranch);
|
|
469
|
-
stashPop();
|
|
625
|
+
checkoutBranch(originalBranch, logger);
|
|
626
|
+
stashPop(logger);
|
|
470
627
|
} catch (e) {
|
|
471
628
|
// 忽略
|
|
472
629
|
}
|
|
@@ -478,18 +635,18 @@ async function executeTestStashFlow(originalBranch, testBranch) {
|
|
|
478
635
|
* 发布后切回原分支
|
|
479
636
|
* @param {string} originalBranch - 原分支名
|
|
480
637
|
* @param {boolean} hasStash - 是否有储藏的改动
|
|
638
|
+
* @param {DeployLogger} logger - 日志记录器(可选)
|
|
481
639
|
*/
|
|
482
|
-
export function restoreBranch(originalBranch, hasStash = false) {
|
|
640
|
+
export function restoreBranch(originalBranch, hasStash = false, logger = null) {
|
|
483
641
|
const currentBranch = getCurrentBranch();
|
|
484
642
|
if (currentBranch !== originalBranch) {
|
|
485
643
|
console.log(`\n📌 切回原分支: ${originalBranch}`);
|
|
486
|
-
checkoutBranch(originalBranch);
|
|
644
|
+
checkoutBranch(originalBranch, logger);
|
|
487
645
|
}
|
|
488
646
|
|
|
489
|
-
//
|
|
647
|
+
// 如果有储藏的改动,恢复
|
|
490
648
|
if (hasStash) {
|
|
491
|
-
|
|
492
|
-
console.log(' git stash pop');
|
|
649
|
+
stashPop(logger);
|
|
493
650
|
}
|
|
494
651
|
}
|
|
495
652
|
|
package/src/index.js
CHANGED
|
@@ -11,6 +11,8 @@ export { SSHClient } from './ssh-client.js';
|
|
|
11
11
|
export {
|
|
12
12
|
getCurrentBranch,
|
|
13
13
|
getGitSha,
|
|
14
|
+
getGitCommitMessage,
|
|
15
|
+
getGitCommitMessages,
|
|
14
16
|
isWorkingTreeClean,
|
|
15
17
|
checkUncommittedChanges,
|
|
16
18
|
checkoutBranch,
|
|
@@ -35,8 +37,12 @@ export {
|
|
|
35
37
|
uploadBuild,
|
|
36
38
|
deployAndExtract,
|
|
37
39
|
cleanupFiles,
|
|
40
|
+
downloadBackup,
|
|
38
41
|
deployToServer,
|
|
39
|
-
rollbackDeployment
|
|
42
|
+
rollbackDeployment,
|
|
43
|
+
getServerBackupList,
|
|
44
|
+
getLocalBackupList,
|
|
45
|
+
rollbackFromLocal
|
|
40
46
|
} from './deploy-core.js';
|
|
41
47
|
|
|
42
48
|
// 钉钉通知
|
|
@@ -47,5 +53,11 @@ export {
|
|
|
47
53
|
sendRollbackNotification
|
|
48
54
|
} from './dingtalk.js';
|
|
49
55
|
|
|
56
|
+
// 日志记录
|
|
57
|
+
export {
|
|
58
|
+
DeployLogger,
|
|
59
|
+
cleanLocalBackups
|
|
60
|
+
} from './logger.js';
|
|
61
|
+
|
|
50
62
|
// 配置模板
|
|
51
63
|
export { default as configTemplate } from './config-template.js';
|