@spaceflow/review-summary 0.20.0 → 0.22.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/CHANGELOG.md +36 -0
- package/package.json +5 -2
- package/src/review-summary.service.ts +199 -38
- package/src/types.ts +70 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,41 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.21.0](https://github.com/Lydanne/spaceflow/compare/@spaceflow/review-summary@0.20.0...@spaceflow/review-summary@0.21.0) (2026-03-02)
|
|
4
|
+
|
|
5
|
+
### 修复BUG
|
|
6
|
+
|
|
7
|
+
* **core:** 重构配置 Schema 生成逻辑,使用 SpaceflowConfigSchema 作为基础 ([c73eb1c](https://github.com/Lydanne/spaceflow/commit/c73eb1ce5b6f212b8a932a15224db7e63822f8d0))
|
|
8
|
+
|
|
9
|
+
### 测试用例
|
|
10
|
+
|
|
11
|
+
* **review:** 增强 AI 评论识别和过滤功能的测试覆盖 ([bda706b](https://github.com/Lydanne/spaceflow/commit/bda706b99aab113521afe6bcd386a590811e20a6))
|
|
12
|
+
|
|
13
|
+
### 其他修改
|
|
14
|
+
|
|
15
|
+
* **core:** released version 0.19.0 [no ci] ([c8bfe6b](https://github.com/Lydanne/spaceflow/commit/c8bfe6ba20893e2c3cd383ed7e7d3217b0492eb6))
|
|
16
|
+
* **publish:** released version 0.43.0 [no ci] ([1074b9c](https://github.com/Lydanne/spaceflow/commit/1074b9c5fb21a447093ef23300c451d790710b33))
|
|
17
|
+
* **review:** released version 0.51.0 [no ci] ([c93be78](https://github.com/Lydanne/spaceflow/commit/c93be78f6f1df9cb5e3515cee58cda65cad1b00f))
|
|
18
|
+
* **review:** released version 0.52.0 [no ci] ([c86406f](https://github.com/Lydanne/spaceflow/commit/c86406f6934d5de4f198eadff66ee6c3f7cfbe0d))
|
|
19
|
+
* **review:** released version 0.53.0 [no ci] ([5a6af03](https://github.com/Lydanne/spaceflow/commit/5a6af03c260060ac1b1901bb7273f501ca0037c7))
|
|
20
|
+
* **review:** 移除 .spaceflow 目录及其配置文件 ([64b310d](https://github.com/Lydanne/spaceflow/commit/64b310d8a77614a259a8d7588a09169626efb3ae))
|
|
21
|
+
* **scripts:** released version 0.20.0 [no ci] ([e1fac49](https://github.com/Lydanne/spaceflow/commit/e1fac49257bf4a5902c5884ec0e054384a7859d6))
|
|
22
|
+
* **shell:** released version 0.20.0 [no ci] ([8b69b53](https://github.com/Lydanne/spaceflow/commit/8b69b5340fe99973add2bea3e7d53f2082d0da54))
|
|
23
|
+
|
|
24
|
+
## [0.20.0](https://github.com/Lydanne/spaceflow/compare/@spaceflow/review-summary@0.19.0...@spaceflow/review-summary@0.20.0) (2026-02-27)
|
|
25
|
+
|
|
26
|
+
### 新特性
|
|
27
|
+
|
|
28
|
+
* **core:** 为 Gitea 和 GitHub 适配器完善已解决评论列表功能 ([7134c83](https://github.com/Lydanne/spaceflow/commit/7134c83b0b440bdfb688d93e86c9552302bf45b2))
|
|
29
|
+
* **review:** 增强已解决问题同步功能,支持记录解决者 ([2c74996](https://github.com/Lydanne/spaceflow/commit/2c74996471e003f8666f8ccec715590f0f64c017))
|
|
30
|
+
|
|
31
|
+
### 其他修改
|
|
32
|
+
|
|
33
|
+
* **core:** released version 0.18.0 [no ci] ([7d931eb](https://github.com/Lydanne/spaceflow/commit/7d931eba98a172cf6ad365f09b780251ad35b212))
|
|
34
|
+
* **publish:** released version 0.42.0 [no ci] ([61ac6b2](https://github.com/Lydanne/spaceflow/commit/61ac6b233564550d35e84759eff60a9e04181c46))
|
|
35
|
+
* **review:** released version 0.50.0 [no ci] ([cff42fa](https://github.com/Lydanne/spaceflow/commit/cff42fafcc588d0c497d9e0e4750620262adcfec))
|
|
36
|
+
* **scripts:** released version 0.19.0 [no ci] ([e198652](https://github.com/Lydanne/spaceflow/commit/e198652a1dcbd137dcd0fe4d7a2f404e12a991bc))
|
|
37
|
+
* **shell:** released version 0.19.0 [no ci] ([2dc2597](https://github.com/Lydanne/spaceflow/commit/2dc25974cfeac9c80d03a601e722133bccb25086))
|
|
38
|
+
|
|
3
39
|
## [0.19.0](https://github.com/Lydanne/spaceflow/compare/@spaceflow/review-summary@0.18.0...@spaceflow/review-summary@0.19.0) (2026-02-27)
|
|
4
40
|
|
|
5
41
|
### 修复BUG
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spaceflow/review-summary",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.22.0",
|
|
4
4
|
"description": "Spaceflow 审查统计命令,根据时间范围统计 PR 贡献情况,按人员汇总并排序",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Lydanne",
|
|
@@ -14,12 +14,15 @@
|
|
|
14
14
|
},
|
|
15
15
|
"type": "module",
|
|
16
16
|
"main": "./dist/index.js",
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"@spaceflow/review": "0.57.0"
|
|
19
|
+
},
|
|
17
20
|
"devDependencies": {
|
|
18
21
|
"@types/node": "^22.15.0",
|
|
19
22
|
"@spaceflow/cli": "0.38.0"
|
|
20
23
|
},
|
|
21
24
|
"peerDependencies": {
|
|
22
|
-
"@spaceflow/core": "0.
|
|
25
|
+
"@spaceflow/core": "0.20.0"
|
|
23
26
|
},
|
|
24
27
|
"spaceflow": {
|
|
25
28
|
"type": "flow",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { GitProviderService, shouldLog, normalizeVerbose } from "@spaceflow/core";
|
|
2
2
|
import type { IConfigReader } from "@spaceflow/core";
|
|
3
3
|
import type { PullRequest, Issue, CiConfig } from "@spaceflow/core";
|
|
4
|
+
import { MarkdownFormatter, type ReviewIssue } from "@spaceflow/review";
|
|
4
5
|
import { writeFileSync } from "fs";
|
|
5
6
|
import { join } from "path";
|
|
6
7
|
import type {
|
|
@@ -11,24 +12,32 @@ import type {
|
|
|
11
12
|
UserStats,
|
|
12
13
|
OutputTarget,
|
|
13
14
|
TimePreset,
|
|
15
|
+
WeightedScoreWeights,
|
|
16
|
+
CommitBasedWeights,
|
|
17
|
+
ReviewSummaryConfig,
|
|
18
|
+
ScoreStrategy,
|
|
14
19
|
} from "./types";
|
|
15
20
|
|
|
16
|
-
/**
|
|
17
|
-
const
|
|
18
|
-
/** 每个 PR 的基础分 */
|
|
21
|
+
/** 加权模式默认权重 */
|
|
22
|
+
const DEFAULT_WEIGHTED_WEIGHTS: Required<WeightedScoreWeights> = {
|
|
19
23
|
prBase: 10,
|
|
20
|
-
/** 每 100 行新增代码的分数 */
|
|
21
24
|
additionsPer100: 2,
|
|
22
|
-
/** 每 100 行删除代码的分数 */
|
|
23
25
|
deletionsPer100: 1,
|
|
24
|
-
/** 每个变更文件的分数 */
|
|
25
26
|
changedFile: 0.5,
|
|
26
|
-
/** 每个未修复问题的扣分 */
|
|
27
27
|
issueDeduction: 3,
|
|
28
|
-
/** 每个已修复问题的加分 */
|
|
29
28
|
fixedBonus: 1,
|
|
30
29
|
};
|
|
31
30
|
|
|
31
|
+
/** 分数累计模式默认权重 */
|
|
32
|
+
const DEFAULT_COMMIT_BASED_WEIGHTS: Required<CommitBasedWeights> = {
|
|
33
|
+
validCommit: 5,
|
|
34
|
+
errorDeduction: 2,
|
|
35
|
+
warnDeduction: 1,
|
|
36
|
+
errorFixedBonus: 1,
|
|
37
|
+
warnFixedBonus: 0.5,
|
|
38
|
+
minCommitLines: 5,
|
|
39
|
+
};
|
|
40
|
+
|
|
32
41
|
/**
|
|
33
42
|
* 周期统计服务
|
|
34
43
|
*/
|
|
@@ -140,7 +149,8 @@ export class PeriodSummaryService {
|
|
|
140
149
|
} catch {
|
|
141
150
|
// 如果获取文件失败,使用默认值
|
|
142
151
|
}
|
|
143
|
-
const
|
|
152
|
+
const issueStats = await this.extractIssueStats(owner, repo, pr.number!);
|
|
153
|
+
const validCommitCount = await this.countValidCommits(owner, repo, pr.number!);
|
|
144
154
|
return {
|
|
145
155
|
number: pr.number!,
|
|
146
156
|
title: pr.title ?? "",
|
|
@@ -149,8 +159,8 @@ export class PeriodSummaryService {
|
|
|
149
159
|
additions,
|
|
150
160
|
deletions,
|
|
151
161
|
changedFiles,
|
|
152
|
-
|
|
153
|
-
|
|
162
|
+
...issueStats,
|
|
163
|
+
validCommitCount,
|
|
154
164
|
description: this.extractDescription(pr),
|
|
155
165
|
};
|
|
156
166
|
}
|
|
@@ -162,31 +172,125 @@ export class PeriodSummaryService {
|
|
|
162
172
|
owner: string,
|
|
163
173
|
repo: string,
|
|
164
174
|
prNumber: number,
|
|
165
|
-
): Promise<{
|
|
175
|
+
): Promise<{
|
|
176
|
+
issueCount: number;
|
|
177
|
+
fixedCount: number;
|
|
178
|
+
errorCount: number;
|
|
179
|
+
warnCount: number;
|
|
180
|
+
fixedErrors: number;
|
|
181
|
+
fixedWarns: number;
|
|
182
|
+
}> {
|
|
183
|
+
const empty = { issueCount: 0, fixedCount: 0, errorCount: 0, warnCount: 0, fixedErrors: 0, fixedWarns: 0 };
|
|
166
184
|
try {
|
|
167
185
|
const comments = await this.gitProvider.listIssueComments(owner, repo, prNumber);
|
|
168
|
-
|
|
169
|
-
|
|
186
|
+
// 优先从 review 模块嵌入的结构化数据中精确提取
|
|
187
|
+
const formatter = new MarkdownFormatter();
|
|
170
188
|
for (const comment of comments) {
|
|
171
189
|
const body = comment.body ?? "";
|
|
172
|
-
const
|
|
173
|
-
if (
|
|
174
|
-
|
|
175
|
-
}
|
|
176
|
-
const fixedMatch = body.match(/已修复[::]\s*(\d+)/);
|
|
177
|
-
if (fixedMatch) {
|
|
178
|
-
fixedCount = Math.max(fixedCount, parseInt(fixedMatch[1], 10));
|
|
190
|
+
const parsed = formatter.parse(body);
|
|
191
|
+
if (parsed?.result?.issues) {
|
|
192
|
+
return this.computeIssueStatsFromReviewIssues(parsed.result.issues);
|
|
179
193
|
}
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
194
|
+
}
|
|
195
|
+
// 回退:没有结构化数据时,从评论文本正则提取(兼容旧数据)
|
|
196
|
+
return this.extractIssueStatsFromText(comments);
|
|
197
|
+
} catch {
|
|
198
|
+
return empty;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* 从 ReviewIssue 列表中精确计算各类问题统计
|
|
204
|
+
*/
|
|
205
|
+
protected computeIssueStatsFromReviewIssues(issues: ReviewIssue[]): {
|
|
206
|
+
issueCount: number;
|
|
207
|
+
fixedCount: number;
|
|
208
|
+
errorCount: number;
|
|
209
|
+
warnCount: number;
|
|
210
|
+
fixedErrors: number;
|
|
211
|
+
fixedWarns: number;
|
|
212
|
+
} {
|
|
213
|
+
const errorCount = issues.filter((i) => i.severity === "error").length;
|
|
214
|
+
const warnCount = issues.filter((i) => i.severity === "warn").length;
|
|
215
|
+
const fixedErrors = issues.filter((i) => i.severity === "error" && i.fixed).length;
|
|
216
|
+
const fixedWarns = issues.filter((i) => i.severity === "warn" && i.fixed).length;
|
|
217
|
+
return {
|
|
218
|
+
issueCount: issues.length,
|
|
219
|
+
fixedCount: fixedErrors + fixedWarns,
|
|
220
|
+
errorCount,
|
|
221
|
+
warnCount,
|
|
222
|
+
fixedErrors,
|
|
223
|
+
fixedWarns,
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* 回退:从评论文本正则提取问题统计(兼容无结构化数据的旧评论)
|
|
229
|
+
*/
|
|
230
|
+
protected extractIssueStatsFromText(
|
|
231
|
+
comments: { body?: string }[],
|
|
232
|
+
): {
|
|
233
|
+
issueCount: number;
|
|
234
|
+
fixedCount: number;
|
|
235
|
+
errorCount: number;
|
|
236
|
+
warnCount: number;
|
|
237
|
+
fixedErrors: number;
|
|
238
|
+
fixedWarns: number;
|
|
239
|
+
} {
|
|
240
|
+
let issueCount = 0;
|
|
241
|
+
let fixedCount = 0;
|
|
242
|
+
let errorCount = 0;
|
|
243
|
+
let warnCount = 0;
|
|
244
|
+
for (const comment of comments) {
|
|
245
|
+
const body = comment.body ?? "";
|
|
246
|
+
const issueMatch = body.match(/发现\s*(\d+)\s*个问题/);
|
|
247
|
+
if (issueMatch) {
|
|
248
|
+
issueCount = Math.max(issueCount, parseInt(issueMatch[1], 10));
|
|
249
|
+
}
|
|
250
|
+
const fixedMatch = body.match(/已修复[::]\s*(\d+)/);
|
|
251
|
+
if (fixedMatch) {
|
|
252
|
+
fixedCount = Math.max(fixedCount, parseInt(fixedMatch[1], 10));
|
|
253
|
+
}
|
|
254
|
+
const statsMatch = body.match(/🔴\s*(\d+).*🟡\s*(\d+)/);
|
|
255
|
+
if (statsMatch) {
|
|
256
|
+
errorCount = Math.max(errorCount, parseInt(statsMatch[1], 10));
|
|
257
|
+
warnCount = Math.max(warnCount, parseInt(statsMatch[2], 10));
|
|
258
|
+
issueCount = Math.max(issueCount, errorCount + warnCount);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
// 文本模式无法区分修复类型,统一设为 0
|
|
262
|
+
return { issueCount, fixedCount, errorCount, warnCount, fixedErrors: 0, fixedWarns: 0 };
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* 统计 PR 中有效 commit 数量(逐 commit 获取行数判断)
|
|
267
|
+
*/
|
|
268
|
+
protected async countValidCommits(owner: string, repo: string, prNumber: number): Promise<number> {
|
|
269
|
+
const config = this.getStrategyConfig();
|
|
270
|
+
const minLines = config.commitBasedWeights?.minCommitLines ?? DEFAULT_COMMIT_BASED_WEIGHTS.minCommitLines;
|
|
271
|
+
try {
|
|
272
|
+
const commits = await this.gitProvider.getPullRequestCommits(owner, repo, prNumber);
|
|
273
|
+
let validCount = 0;
|
|
274
|
+
for (const commit of commits) {
|
|
275
|
+
if (!commit.sha) continue;
|
|
276
|
+
// 跳过 merge commit(commit message 以 "Merge" 开头)
|
|
277
|
+
if (commit.commit?.message?.startsWith("Merge")) continue;
|
|
278
|
+
try {
|
|
279
|
+
const commitInfo = await this.gitProvider.getCommit(owner, repo, commit.sha);
|
|
280
|
+
const totalLines = (commitInfo.files ?? []).reduce(
|
|
281
|
+
(sum, file) => sum + (file.additions ?? 0) + (file.deletions ?? 0),
|
|
282
|
+
0,
|
|
283
|
+
);
|
|
284
|
+
if (totalLines >= minLines) {
|
|
285
|
+
validCount++;
|
|
286
|
+
}
|
|
287
|
+
} catch {
|
|
288
|
+
// 获取单个 commit 失败,跳过
|
|
185
289
|
}
|
|
186
290
|
}
|
|
187
|
-
return
|
|
291
|
+
return validCount;
|
|
188
292
|
} catch {
|
|
189
|
-
return
|
|
293
|
+
return 0;
|
|
190
294
|
}
|
|
191
295
|
}
|
|
192
296
|
|
|
@@ -216,6 +320,11 @@ export class PeriodSummaryService {
|
|
|
216
320
|
totalChangedFiles: 0,
|
|
217
321
|
totalIssues: 0,
|
|
218
322
|
totalFixed: 0,
|
|
323
|
+
totalErrors: 0,
|
|
324
|
+
totalWarns: 0,
|
|
325
|
+
totalFixedErrors: 0,
|
|
326
|
+
totalFixedWarns: 0,
|
|
327
|
+
totalValidCommits: 0,
|
|
219
328
|
score: 0,
|
|
220
329
|
features: [],
|
|
221
330
|
prs: [],
|
|
@@ -228,33 +337,82 @@ export class PeriodSummaryService {
|
|
|
228
337
|
userStats.totalChangedFiles += pr.changedFiles;
|
|
229
338
|
userStats.totalIssues += pr.issueCount;
|
|
230
339
|
userStats.totalFixed += pr.fixedCount;
|
|
340
|
+
userStats.totalErrors += pr.errorCount;
|
|
341
|
+
userStats.totalWarns += pr.warnCount;
|
|
342
|
+
userStats.totalFixedErrors += pr.fixedErrors;
|
|
343
|
+
userStats.totalFixedWarns += pr.fixedWarns;
|
|
344
|
+
userStats.totalValidCommits += pr.validCommitCount;
|
|
231
345
|
if (pr.description) {
|
|
232
346
|
userStats.features.push(pr.description);
|
|
233
347
|
}
|
|
234
348
|
userStats.prs.push(pr);
|
|
235
349
|
}
|
|
350
|
+
this.applyScoreStrategy(userMap);
|
|
351
|
+
return userMap;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* 获取当前评分策略配置
|
|
356
|
+
*/
|
|
357
|
+
protected getStrategyConfig(): ReviewSummaryConfig {
|
|
358
|
+
try {
|
|
359
|
+
return this.config.get<ReviewSummaryConfig>("review-summary") ?? {};
|
|
360
|
+
} catch {
|
|
361
|
+
return {};
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* 根据配置的策略计算所有用户的分数
|
|
367
|
+
*/
|
|
368
|
+
protected applyScoreStrategy(userMap: Map<string, UserStats>): void {
|
|
369
|
+
const config = this.getStrategyConfig();
|
|
370
|
+
const strategy: ScoreStrategy = config.strategy ?? "weighted";
|
|
236
371
|
for (const userStats of userMap.values()) {
|
|
237
|
-
|
|
372
|
+
switch (strategy) {
|
|
373
|
+
case "commit-based":
|
|
374
|
+
userStats.score = this.calculateCommitBasedScore(userStats, config);
|
|
375
|
+
break;
|
|
376
|
+
case "weighted":
|
|
377
|
+
default:
|
|
378
|
+
userStats.score = this.calculateWeightedScore(userStats, config);
|
|
379
|
+
break;
|
|
380
|
+
}
|
|
238
381
|
}
|
|
239
|
-
return userMap;
|
|
240
382
|
}
|
|
241
383
|
|
|
242
384
|
/**
|
|
243
|
-
*
|
|
385
|
+
* 加权模式:计算用户综合分数
|
|
244
386
|
*/
|
|
245
|
-
protected
|
|
246
|
-
const
|
|
247
|
-
const
|
|
248
|
-
const
|
|
249
|
-
const
|
|
387
|
+
protected calculateWeightedScore(stats: UserStats, config: ReviewSummaryConfig): number {
|
|
388
|
+
const weights = { ...DEFAULT_WEIGHTED_WEIGHTS, ...config.scoreWeights };
|
|
389
|
+
const prScore = stats.prCount * weights.prBase;
|
|
390
|
+
const additionsScore = (stats.totalAdditions / 100) * weights.additionsPer100;
|
|
391
|
+
const deletionsScore = (stats.totalDeletions / 100) * weights.deletionsPer100;
|
|
392
|
+
const filesScore = stats.totalChangedFiles * weights.changedFile;
|
|
250
393
|
const unfixedIssues = stats.totalIssues - stats.totalFixed;
|
|
251
|
-
const issueDeduction = unfixedIssues *
|
|
252
|
-
const fixedBonus = stats.totalFixed *
|
|
394
|
+
const issueDeduction = unfixedIssues * weights.issueDeduction;
|
|
395
|
+
const fixedBonus = stats.totalFixed * weights.fixedBonus;
|
|
253
396
|
const totalScore =
|
|
254
397
|
prScore + additionsScore + deletionsScore + filesScore - issueDeduction + fixedBonus;
|
|
255
398
|
return Math.max(0, Math.round(totalScore * 10) / 10);
|
|
256
399
|
}
|
|
257
400
|
|
|
401
|
+
/**
|
|
402
|
+
* 分数累计模式:按有效 commit 加分,按 error/warn 扣分
|
|
403
|
+
*/
|
|
404
|
+
protected calculateCommitBasedScore(stats: UserStats, config: ReviewSummaryConfig): number {
|
|
405
|
+
const weights = { ...DEFAULT_COMMIT_BASED_WEIGHTS, ...config.commitBasedWeights };
|
|
406
|
+
const commitScore = stats.totalValidCommits * weights.validCommit;
|
|
407
|
+
const errorDeduction = stats.totalErrors * weights.errorDeduction;
|
|
408
|
+
const warnDeduction = stats.totalWarns * weights.warnDeduction;
|
|
409
|
+
const fixedBonus =
|
|
410
|
+
stats.totalFixedErrors * weights.errorFixedBonus +
|
|
411
|
+
stats.totalFixedWarns * weights.warnFixedBonus;
|
|
412
|
+
const totalScore = commitScore - errorDeduction - warnDeduction + fixedBonus;
|
|
413
|
+
return Math.max(0, Math.round(totalScore * 10) / 10);
|
|
414
|
+
}
|
|
415
|
+
|
|
258
416
|
/**
|
|
259
417
|
* 按分数排序用户统计
|
|
260
418
|
*/
|
|
@@ -497,9 +655,12 @@ export class PeriodSummaryService {
|
|
|
497
655
|
content: string,
|
|
498
656
|
): Promise<{ type: OutputTarget; location: string }> {
|
|
499
657
|
const title = `📊 周期统计报告: ${result.period.since} ~ ${result.period.until}`;
|
|
658
|
+
const config = this.getStrategyConfig();
|
|
659
|
+
const labelName = config.issueLabel ?? "report";
|
|
500
660
|
const issue: Issue = await this.gitProvider.createIssue(context.owner, context.repo, {
|
|
501
661
|
title,
|
|
502
662
|
body: content,
|
|
663
|
+
labels: [labelName],
|
|
503
664
|
});
|
|
504
665
|
const location = issue.html_url ?? `#${issue.number}`;
|
|
505
666
|
if (shouldLog(context.verbose, 1)) {
|
package/src/types.ts
CHANGED
|
@@ -71,6 +71,16 @@ export interface PrStats {
|
|
|
71
71
|
issueCount: number;
|
|
72
72
|
/** 已修复的问题数 */
|
|
73
73
|
fixedCount: number;
|
|
74
|
+
/** error 级别问题数 */
|
|
75
|
+
errorCount: number;
|
|
76
|
+
/** warn 级别问题数 */
|
|
77
|
+
warnCount: number;
|
|
78
|
+
/** 已修复的 error 问题数 */
|
|
79
|
+
fixedErrors: number;
|
|
80
|
+
/** 已修复的 warn 问题数 */
|
|
81
|
+
fixedWarns: number;
|
|
82
|
+
/** 有效 commit 数(单个 commit 新增+删除 >= minCommitLines 行) */
|
|
83
|
+
validCommitCount: number;
|
|
74
84
|
/** PR 描述/功能摘要 */
|
|
75
85
|
description: string;
|
|
76
86
|
}
|
|
@@ -91,6 +101,16 @@ export interface UserStats {
|
|
|
91
101
|
totalIssues: number;
|
|
92
102
|
/** 总已修复问题数 */
|
|
93
103
|
totalFixed: number;
|
|
104
|
+
/** 总 error 级别问题数 */
|
|
105
|
+
totalErrors: number;
|
|
106
|
+
/** 总 warn 级别问题数 */
|
|
107
|
+
totalWarns: number;
|
|
108
|
+
/** 总已修复 error 数 */
|
|
109
|
+
totalFixedErrors: number;
|
|
110
|
+
/** 总已修复 warn 数 */
|
|
111
|
+
totalFixedWarns: number;
|
|
112
|
+
/** 总有效 commit 数 */
|
|
113
|
+
totalValidCommits: number;
|
|
94
114
|
/** 综合分数 */
|
|
95
115
|
score: number;
|
|
96
116
|
/** 功能摘要列表 */
|
|
@@ -99,6 +119,56 @@ export interface UserStats {
|
|
|
99
119
|
prs: PrStats[];
|
|
100
120
|
}
|
|
101
121
|
|
|
122
|
+
/** 评分策略类型 */
|
|
123
|
+
export type ScoreStrategy = "weighted" | "commit-based";
|
|
124
|
+
|
|
125
|
+
/** 加权模式权重配置 */
|
|
126
|
+
export interface WeightedScoreWeights {
|
|
127
|
+
/** 每个 PR 的基础分,默认 10 */
|
|
128
|
+
prBase?: number;
|
|
129
|
+
/** 每 100 行新增代码的分数,默认 2 */
|
|
130
|
+
additionsPer100?: number;
|
|
131
|
+
/** 每 100 行删除代码的分数,默认 1 */
|
|
132
|
+
deletionsPer100?: number;
|
|
133
|
+
/** 每个变更文件的分数,默认 0.5 */
|
|
134
|
+
changedFile?: number;
|
|
135
|
+
/** 每个未修复问题的扣分,默认 3 */
|
|
136
|
+
issueDeduction?: number;
|
|
137
|
+
/** 每个已修复问题的加分,默认 1 */
|
|
138
|
+
fixedBonus?: number;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/** 分数累计模式权重配置 */
|
|
142
|
+
export interface CommitBasedWeights {
|
|
143
|
+
/** 每个有效 commit 的加分,默认 5 */
|
|
144
|
+
validCommit?: number;
|
|
145
|
+
/** 每个 error 问题的扣分,默认 2 */
|
|
146
|
+
errorDeduction?: number;
|
|
147
|
+
/** 每个 warn 问题的扣分,默认 1 */
|
|
148
|
+
warnDeduction?: number;
|
|
149
|
+
/** 修复一个 error 问题的加分,默认为 errorDeduction 的一半(1) */
|
|
150
|
+
errorFixedBonus?: number;
|
|
151
|
+
/** 修复一个 warn 问题的加分,默认为 warnDeduction 的一半(0.5) */
|
|
152
|
+
warnFixedBonus?: number;
|
|
153
|
+
/** 有效 commit 的最低代码行数(新增+删除),默认 5 */
|
|
154
|
+
minCommitLines?: number;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/** @deprecated 使用 WeightedScoreWeights 代替 */
|
|
158
|
+
export type ScoreWeights = WeightedScoreWeights;
|
|
159
|
+
|
|
160
|
+
/** review-summary 扩展配置 */
|
|
161
|
+
export interface ReviewSummaryConfig {
|
|
162
|
+
/** 评分策略,默认 "weighted" */
|
|
163
|
+
strategy?: ScoreStrategy;
|
|
164
|
+
/** 加权模式权重配置(strategy 为 "weighted" 时生效) */
|
|
165
|
+
scoreWeights?: WeightedScoreWeights;
|
|
166
|
+
/** 分数累计模式权重配置(strategy 为 "commit-based" 时生效) */
|
|
167
|
+
commitBasedWeights?: CommitBasedWeights;
|
|
168
|
+
/** 创建 Issue 时添加的标签名称,默认 "report" */
|
|
169
|
+
issueLabel?: string;
|
|
170
|
+
}
|
|
171
|
+
|
|
102
172
|
/** 周期统计结果 */
|
|
103
173
|
export interface PeriodSummaryResult {
|
|
104
174
|
/** 统计周期 */
|