ai-git-tools 2.0.18 → 2.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/README.md
CHANGED
|
@@ -158,7 +158,6 @@ npx ai-git-tools pr [選項]
|
|
|
158
158
|
|
|
159
159
|
選項:
|
|
160
160
|
-b, --base <branch> 目標分支 (預設: 配置檔的 defaultBase 或自動偵測)
|
|
161
|
-
-h, --head <branch> 來源分支 (預設: 當前分支,通常不需指定)
|
|
162
161
|
-m, --model <model> 指定 AI 模型
|
|
163
162
|
--preview 僅預覽,不創建 PR
|
|
164
163
|
--no-confirm 跳過確認直接創建
|
|
@@ -212,16 +211,16 @@ export default {
|
|
|
212
211
|
|
|
213
212
|
// GitHub 設定
|
|
214
213
|
github: {
|
|
215
|
-
defaultBase: 'release', //
|
|
214
|
+
defaultBase: 'release', // 預設目標分支:'release'=自動查找最新,或指定具體分支名
|
|
216
215
|
autoLabels: true, // 自動添加 Labels
|
|
217
216
|
},
|
|
218
217
|
|
|
219
218
|
// Reviewer 設定
|
|
220
219
|
reviewers: {
|
|
221
|
-
interactiveReviewers:
|
|
220
|
+
interactiveReviewers: true, // true=啟用互動式選擇,false=不添加任何 reviewers
|
|
222
221
|
maxSuggested: 5, // 最多建議人數
|
|
223
222
|
gitHistoryDepth: 20, // Git 歷史分析深度
|
|
224
|
-
excludeAuthors: [], //
|
|
223
|
+
excludeAuthors: [], // 排除特定作者(最高優先順序,即使手動選擇也會被過濾)
|
|
225
224
|
},
|
|
226
225
|
|
|
227
226
|
// 輸出設定
|
|
@@ -232,6 +231,44 @@ export default {
|
|
|
232
231
|
};
|
|
233
232
|
\`\`\`
|
|
234
233
|
|
|
234
|
+
### defaultBase 配置說明
|
|
235
|
+
|
|
236
|
+
\`defaultBase\` 支援兩種模式:
|
|
237
|
+
|
|
238
|
+
#### 1. 自動模式(推薦)
|
|
239
|
+
```javascript
|
|
240
|
+
github: {
|
|
241
|
+
defaultBase: 'release', // 自動查找最新的 release 分支
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
- 工具會自動偵測所有 \`release-*\` 或 \`release/*\` 格式的分支
|
|
245
|
+
- 自動選擇最新版本(優先選擇月度分支,如 release-2025-m12.1)
|
|
246
|
+
- 適合經常更新 release 版本的專案
|
|
247
|
+
|
|
248
|
+
#### 2. 具體分支模式
|
|
249
|
+
```javascript
|
|
250
|
+
github: {
|
|
251
|
+
defaultBase: 'release-2025-m12.1', // 固定使用此分支
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
- 直接使用指定的分支名稱
|
|
255
|
+
- 適合需要固定某個版本的情況
|
|
256
|
+
- 或使用 \`main\`、\`develop\` 等標準分支
|
|
257
|
+
|
|
258
|
+
**範例輸出**:
|
|
259
|
+
```bash
|
|
260
|
+
# 使用 defaultBase: 'release'
|
|
261
|
+
配置檔指定使用 release 分支,正在偵測最新版本...
|
|
262
|
+
📋 偵測到的 release 分支:
|
|
263
|
+
月度分支 (優先):
|
|
264
|
+
1. release-2025-m12.1 ← 最新
|
|
265
|
+
2. release-2025-m11.1
|
|
266
|
+
✅ 自動選擇最新 release 分支: release-2025-m12.1
|
|
267
|
+
|
|
268
|
+
# 使用 defaultBase: 'release-2025-m12.1'
|
|
269
|
+
✅ 使用配置檔指定的分支: release-2025-m12.1
|
|
270
|
+
```
|
|
271
|
+
|
|
235
272
|
## 🔧 環境需求
|
|
236
273
|
|
|
237
274
|
- **Node.js** >= 18.0.0
|
|
@@ -267,7 +304,7 @@ npx ai-git-tools commit-all
|
|
|
267
304
|
### 場景 3:快速發 PR
|
|
268
305
|
|
|
269
306
|
\`\`\`bash
|
|
270
|
-
npx ai-git-tools pr --auto-
|
|
307
|
+
npx ai-git-tools pr --auto-labels
|
|
271
308
|
# ✅ 自動生成完整的 PR 標題和描述
|
|
272
309
|
# ✅ 建議合適的 reviewers
|
|
273
310
|
# ✅ 添加相關的 labels
|
package/bin/cli.js
CHANGED
|
@@ -51,13 +51,10 @@ program
|
|
|
51
51
|
.command('pr')
|
|
52
52
|
.description('AI 自動生成 PR 並創建 Pull Request')
|
|
53
53
|
.option('--base <branch>', '指定目標分支')
|
|
54
|
-
.option('--head <branch>', '指定來源分支')
|
|
55
54
|
.option('--model <model>', '指定 AI 模型')
|
|
56
55
|
.option('--org <org-name>', '指定 GitHub 組織名稱')
|
|
57
|
-
.option('--draft', '創建草稿 PR')
|
|
58
56
|
.option('--preview', '僅預覽 PR 內容,不實際創建')
|
|
59
57
|
.option('--no-confirm', '跳過確認直接創建')
|
|
60
|
-
.option('--auto-reviewers', '自動選擇 reviewers')
|
|
61
58
|
.option('--auto-labels', '自動添加 Labels')
|
|
62
59
|
.option('--no-labels', '不添加 Labels')
|
|
63
60
|
.action(prCommand);
|
package/package.json
CHANGED
|
@@ -119,27 +119,18 @@ export function parsePRCliArgs() {
|
|
|
119
119
|
case '--base':
|
|
120
120
|
config.baseBranch = args[++i];
|
|
121
121
|
break;
|
|
122
|
-
case '--head':
|
|
123
|
-
config.headBranch = args[++i];
|
|
124
|
-
break;
|
|
125
122
|
case '--model':
|
|
126
123
|
config.model = args[++i];
|
|
127
124
|
break;
|
|
128
125
|
case '--org':
|
|
129
126
|
config.orgName = args[++i];
|
|
130
127
|
break;
|
|
131
|
-
case '--draft':
|
|
132
|
-
config.draft = true;
|
|
133
|
-
break;
|
|
134
128
|
case '--preview':
|
|
135
129
|
config.preview = true;
|
|
136
130
|
break;
|
|
137
131
|
case '--no-confirm':
|
|
138
132
|
config.noConfirm = true;
|
|
139
133
|
break;
|
|
140
|
-
case '--auto-reviewers':
|
|
141
|
-
config.autoReviewers = true;
|
|
142
|
-
break;
|
|
143
134
|
case '--auto-labels':
|
|
144
135
|
config.autoLabels = true;
|
|
145
136
|
break;
|
|
@@ -101,8 +101,31 @@ export class PRWorkflow {
|
|
|
101
101
|
if (!baseBranch) {
|
|
102
102
|
// 優先使用配置檔中的 defaultBase
|
|
103
103
|
if (this.config.github?.defaultBase) {
|
|
104
|
-
|
|
105
|
-
|
|
104
|
+
const defaultBase = this.config.github.defaultBase;
|
|
105
|
+
|
|
106
|
+
// 如果 defaultBase 是 'release',則自動查找最新的 release 分支
|
|
107
|
+
if (defaultBase === 'release' || defaultBase.match(/^release$/i)) {
|
|
108
|
+
log.step('配置檔指定使用 release 分支,正在偵測最新版本...\n');
|
|
109
|
+
const allBranches = this.git.detectReleaseBranches();
|
|
110
|
+
const latestRelease = this.git.findLatestReleaseBranch();
|
|
111
|
+
|
|
112
|
+
if (latestRelease) {
|
|
113
|
+
baseBranch = latestRelease;
|
|
114
|
+
this.displayDetectedBranches(allBranches, latestRelease);
|
|
115
|
+
log.success(`自動選擇最新 release 分支: ${baseBranch}`);
|
|
116
|
+
log.info(`提示: 使用 --base <分支名> 指定其他分支\n`);
|
|
117
|
+
} else {
|
|
118
|
+
throw new PRError('未偵測到任何 release 分支', 'NO_RELEASE_BRANCH', [
|
|
119
|
+
'使用 --base 參數指定目標分支',
|
|
120
|
+
'或在 .ai-git-config.js 中設置具體的分支名(如 release-2025-m12.1)',
|
|
121
|
+
'確認遠端分支存在: git branch -r | grep release',
|
|
122
|
+
]);
|
|
123
|
+
}
|
|
124
|
+
} else {
|
|
125
|
+
// 使用配置檔中指定的具體分支名
|
|
126
|
+
baseBranch = defaultBase;
|
|
127
|
+
log.success(`使用配置檔指定的分支: ${baseBranch}\n`);
|
|
128
|
+
}
|
|
106
129
|
} else {
|
|
107
130
|
// 如果沒有配置,則自動偵測最新的 release 分支
|
|
108
131
|
log.step('正在偵測 release 分支...\n');
|
|
@@ -324,6 +347,13 @@ export class PRWorkflow {
|
|
|
324
347
|
return null;
|
|
325
348
|
}
|
|
326
349
|
|
|
350
|
+
// 如果禁用互動式選擇,不添加任何 reviewers
|
|
351
|
+
if (!this.config.reviewers.interactiveReviewers) {
|
|
352
|
+
console.log('ℹ️ 已禁用 reviewer 選擇(interactiveReviewers: false)\n');
|
|
353
|
+
log.info('提示: 你可以在創建 PR 後手動添加 reviewers\n');
|
|
354
|
+
return null;
|
|
355
|
+
}
|
|
356
|
+
|
|
327
357
|
// 獲取當前用戶
|
|
328
358
|
const currentUser = this.git.getCurrentUser();
|
|
329
359
|
|
|
@@ -332,12 +362,6 @@ export class PRWorkflow {
|
|
|
332
362
|
changeData.changedFiles
|
|
333
363
|
);
|
|
334
364
|
|
|
335
|
-
// 如果禁用互動式選擇,直接自動選擇
|
|
336
|
-
if (!this.config.reviewers.interactiveReviewers) {
|
|
337
|
-
console.log('🤖 自動選擇 reviewers(基於 Git 歷史)\n');
|
|
338
|
-
return this.reviewerSelector.autoSelectReviewers(suggestedReviewers, currentUser);
|
|
339
|
-
}
|
|
340
|
-
|
|
341
365
|
// 抓取 GitHub 團隊資訊(只在互動模式需要)
|
|
342
366
|
const teams = await this.github.fetchTeams();
|
|
343
367
|
|
|
@@ -178,16 +178,30 @@ export class ReviewerSelector {
|
|
|
178
178
|
}
|
|
179
179
|
});
|
|
180
180
|
|
|
181
|
+
// 應用 excludeAuthors 過濾(優先順序最高)
|
|
182
|
+
const filteredIndividuals = selectedIndividuals.filter((login) => {
|
|
183
|
+
const shouldExclude = this.excludeAuthors.some((excluded) => {
|
|
184
|
+
const normalizedExcluded = excluded.toLowerCase();
|
|
185
|
+
return login.toLowerCase().includes(normalizedExcluded);
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
if (shouldExclude) {
|
|
189
|
+
log.warning(`已排除 @${login}(在 excludeAuthors 列表中)`);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return !shouldExclude;
|
|
193
|
+
});
|
|
194
|
+
|
|
181
195
|
console.log('');
|
|
182
196
|
if (selectedTeams.length > 0) {
|
|
183
197
|
log.success(`已選擇團隊: ${selectedTeams.join(', ')}`);
|
|
184
198
|
}
|
|
185
|
-
if (
|
|
186
|
-
log.success(`已選擇個人: ${
|
|
199
|
+
if (filteredIndividuals.length > 0) {
|
|
200
|
+
log.success(`已選擇個人: ${filteredIndividuals.map((u) => `@${u}`).join(', ')}`);
|
|
187
201
|
}
|
|
188
202
|
console.log('');
|
|
189
203
|
|
|
190
|
-
return { teams: selectedTeams, individuals:
|
|
204
|
+
return { teams: selectedTeams, individuals: filteredIndividuals };
|
|
191
205
|
}
|
|
192
206
|
|
|
193
207
|
/**
|
|
@@ -217,16 +231,10 @@ export class ReviewerSelector {
|
|
|
217
231
|
}
|
|
218
232
|
|
|
219
233
|
/**
|
|
220
|
-
* 選擇 Reviewers
|
|
234
|
+
* 選擇 Reviewers(互動模式)
|
|
221
235
|
*/
|
|
222
236
|
async select(teamsData, suggestedReviewers, currentUser) {
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
return this.selectInteractive(teamsData, suggestedReviewers, currentUser);
|
|
226
|
-
} else {
|
|
227
|
-
// interactiveReviewers: false 表示自動選擇(基於 Git 歷史)
|
|
228
|
-
console.log('🤖 自動選擇 reviewers(基於 Git 歷史)\n');
|
|
229
|
-
return this.autoSelectReviewers(suggestedReviewers, currentUser);
|
|
230
|
-
}
|
|
237
|
+
// 此方法現在只在 interactiveReviewers: true 時被調用
|
|
238
|
+
return this.selectInteractive(teamsData, suggestedReviewers, currentUser);
|
|
231
239
|
}
|
|
232
240
|
}
|