@spaceflow/review 0.71.0 → 0.73.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 +30 -0
- package/dist/index.js +38 -18
- package/package.json +2 -2
- package/src/review.service.ts +49 -24
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.72.0](https://github.com/Lydanne/spaceflow/compare/@spaceflow/review@0.71.0...@spaceflow/review@0.72.0) (2026-04-03)
|
|
4
|
+
|
|
5
|
+
### 修复BUG
|
|
6
|
+
|
|
7
|
+
* **review:** 为 skipDuplicateWorkflow 添加错误处理以应对权限不足问题 ([6d0292d](https://github.com/Lydanne/spaceflow/commit/6d0292d20b6eba790f594c555ceb18b75ebfe253))
|
|
8
|
+
|
|
9
|
+
### 其他修改
|
|
10
|
+
|
|
11
|
+
* **core:** released version 0.28.0 [no ci] ([6baebaa](https://github.com/Lydanne/spaceflow/commit/6baebaa4cd777b6f8babcb5d8a2f25c426f8da05))
|
|
12
|
+
* **publish:** released version 0.52.0 [no ci] ([bcbc2a9](https://github.com/Lydanne/spaceflow/commit/bcbc2a97e5bdedfd728330a33f19ec9172d80f40))
|
|
13
|
+
* **review-summary:** released version 0.40.0 [no ci] ([9c5c262](https://github.com/Lydanne/spaceflow/commit/9c5c26256984c9349def2801af6e77b7013e703f))
|
|
14
|
+
|
|
15
|
+
## [0.71.0](https://github.com/Lydanne/spaceflow/compare/@spaceflow/review@0.70.0...@spaceflow/review@0.71.0) (2026-04-02)
|
|
16
|
+
|
|
17
|
+
### 新特性
|
|
18
|
+
|
|
19
|
+
* **review:** 添加 skipDuplicateWorkflow 和 autoApprove 配置选项支持 ([3ede6e3](https://github.com/Lydanne/spaceflow/commit/3ede6e30d89ced5ef57e154e42f723da5e3c5d92))
|
|
20
|
+
|
|
21
|
+
### 修复BUG
|
|
22
|
+
|
|
23
|
+
* **review-summary:** 在用户名前添加 @ 符号以支持用户提及 ([a4aa03f](https://github.com/Lydanne/spaceflow/commit/a4aa03f377bb26e1fa7adc90568d89f2bb9936ce))
|
|
24
|
+
* **review-summary:** 在用户名前添加 @ 符号以支持用户提及 ([fd83df4](https://github.com/Lydanne/spaceflow/commit/fd83df4a647e6c4d42617b44fdaf0ebbec7892e4))
|
|
25
|
+
|
|
26
|
+
### 其他修改
|
|
27
|
+
|
|
28
|
+
* **review-summary:** released version 0.38.0 [no ci] ([119c2a8](https://github.com/Lydanne/spaceflow/commit/119c2a8861a02e68a4e31135aa88799fe63d29ff))
|
|
29
|
+
* **review-summary:** released version 0.39.0 [no ci] ([40fbd43](https://github.com/Lydanne/spaceflow/commit/40fbd435b3895b22b04dce7cce4c487f0edbdd2a))
|
|
30
|
+
* **scripts:** released version 0.29.0 [no ci] ([496843a](https://github.com/Lydanne/spaceflow/commit/496843add224941b646837d8fc8ec03f790530fc))
|
|
31
|
+
* **shell:** released version 0.29.0 [no ci] ([368f8c8](https://github.com/Lydanne/spaceflow/commit/368f8c83ae3e485df5bfd4128e46aef4a6689eb0))
|
|
32
|
+
|
|
3
33
|
## [0.70.0](https://github.com/Lydanne/spaceflow/compare/@spaceflow/review@0.69.0...@spaceflow/review@0.70.0) (2026-04-02)
|
|
4
34
|
|
|
5
35
|
### 新特性
|
package/dist/index.js
CHANGED
|
@@ -2209,6 +2209,7 @@ class ReviewService {
|
|
|
2209
2209
|
}
|
|
2210
2210
|
// 检查是否有其他同名 review workflow 正在运行中(防止同一 PR 重复审查)
|
|
2211
2211
|
// 需要显式启用 skipDuplicateWorkflow 配置
|
|
2212
|
+
// 注意:Gitea Actions API 要求用户是 repo owner,否则会返回 403
|
|
2212
2213
|
if (skipDuplicateWorkflow && ci && pr?.head?.sha) {
|
|
2213
2214
|
const headSha = pr.head.sha;
|
|
2214
2215
|
// 获取当前 PR 编号(从 CI 环境变量)
|
|
@@ -2217,25 +2218,33 @@ class ReviewService {
|
|
|
2217
2218
|
const ref = process.env.GITHUB_REF || process.env.GITEA_REF || "";
|
|
2218
2219
|
const prMatch = ref.match(/refs\/pull\/(\d+)/);
|
|
2219
2220
|
const currentPrNumber = prMatch ? parseInt(prMatch[1], 10) : prNumber;
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2221
|
+
try {
|
|
2222
|
+
const runningWorkflows = await this.gitProvider.listWorkflowRuns(owner, repo, {
|
|
2223
|
+
status: "in_progress"
|
|
2224
|
+
});
|
|
2225
|
+
// 获取当前 workflow 名称和 run ID
|
|
2226
|
+
const currentWorkflowName = process.env.GITHUB_WORKFLOW || process.env.GITEA_WORKFLOW;
|
|
2227
|
+
const currentRunId = process.env.GITHUB_RUN_ID || process.env.GITEA_RUN_ID;
|
|
2228
|
+
// 只检查同 PR 同名的其他 workflow run(排除当前 run)
|
|
2229
|
+
const duplicateReviewRuns = runningWorkflows.filter((w)=>w.sha === headSha && w.name === currentWorkflowName && (!currentRunId || String(w.id) !== currentRunId));
|
|
2230
|
+
if (duplicateReviewRuns.length > 0) {
|
|
2231
|
+
if (shouldLog(verbose, 1)) {
|
|
2232
|
+
console.log(`⏭️ 跳过审查: 当前 PR #${currentPrNumber} 有 ${duplicateReviewRuns.length} 个同名 workflow 正在运行中`);
|
|
2233
|
+
}
|
|
2234
|
+
return {
|
|
2235
|
+
success: true,
|
|
2236
|
+
description: `跳过审查: PR #${currentPrNumber} 有 ${duplicateReviewRuns.length} 个同名 workflow 正在运行中,等待完成后重新审查`,
|
|
2237
|
+
issues: [],
|
|
2238
|
+
summary: [],
|
|
2239
|
+
round: 1
|
|
2240
|
+
};
|
|
2241
|
+
}
|
|
2242
|
+
} catch (error) {
|
|
2243
|
+
// Gitea Actions API 可能返回 403(需要 repo owner 权限)
|
|
2244
|
+
// 捕获错误后跳过重复检查,继续执行审查
|
|
2229
2245
|
if (shouldLog(verbose, 1)) {
|
|
2230
|
-
console.
|
|
2246
|
+
console.warn(`⚠️ 无法检查重复 workflow(可能缺少 repo owner 权限),跳过此检查:`, error instanceof Error ? error.message : error);
|
|
2231
2247
|
}
|
|
2232
|
-
return {
|
|
2233
|
-
success: true,
|
|
2234
|
-
description: `跳过审查: PR #${currentPrNumber} 有 ${duplicateReviewRuns.length} 个同名 workflow 正在运行中,等待完成后重新审查`,
|
|
2235
|
-
issues: [],
|
|
2236
|
-
summary: [],
|
|
2237
|
-
round: 1
|
|
2238
|
-
};
|
|
2239
2248
|
}
|
|
2240
2249
|
}
|
|
2241
2250
|
} else if (effectiveBaseRef && effectiveHeadRef) {
|
|
@@ -2348,7 +2357,7 @@ class ReviewService {
|
|
|
2348
2357
|
summary: applicableSpecs.length === 0 ? "无适用的审查规则" : "已跳过"
|
|
2349
2358
|
}));
|
|
2350
2359
|
const prInfo = context.generateDescription && llmMode ? await this.generatePrDescription(commits, changedFiles, llmMode, undefined, verbose) : await this.buildFallbackDescription(commits, changedFiles);
|
|
2351
|
-
|
|
2360
|
+
const result = {
|
|
2352
2361
|
success: true,
|
|
2353
2362
|
title: prInfo.title,
|
|
2354
2363
|
description: prInfo.description,
|
|
@@ -2356,6 +2365,17 @@ class ReviewService {
|
|
|
2356
2365
|
summary,
|
|
2357
2366
|
round: 1
|
|
2358
2367
|
};
|
|
2368
|
+
// CI 模式下也需要发送 review 评论
|
|
2369
|
+
if (ci && prNumber && !dryRun) {
|
|
2370
|
+
if (shouldLog(verbose, 1)) {
|
|
2371
|
+
console.log(`💬 提交 PR 评论...`);
|
|
2372
|
+
}
|
|
2373
|
+
await this.postOrUpdateReviewComment(owner, repo, prNumber, result, verbose, autoApprove);
|
|
2374
|
+
if (shouldLog(verbose, 1)) {
|
|
2375
|
+
console.log(`✅ 评论已提交`);
|
|
2376
|
+
}
|
|
2377
|
+
}
|
|
2378
|
+
return result;
|
|
2359
2379
|
}
|
|
2360
2380
|
const headSha = pr?.head?.sha || headRef || "HEAD";
|
|
2361
2381
|
const fileContents = await this.getFileContents(owner, repo, changedFiles, commits, headSha, prNumber, verbose, isLocalMode);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spaceflow/review",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.73.0",
|
|
4
4
|
"description": "Spaceflow 代码审查插件,使用 LLM 对 PR 代码进行自动审查",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Lydanne",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"@spaceflow/cli": "0.40.0"
|
|
29
29
|
},
|
|
30
30
|
"peerDependencies": {
|
|
31
|
-
"@spaceflow/core": "0.
|
|
31
|
+
"@spaceflow/core": "0.28.0"
|
|
32
32
|
},
|
|
33
33
|
"spaceflow": {
|
|
34
34
|
"type": "flow",
|
package/src/review.service.ts
CHANGED
|
@@ -540,6 +540,7 @@ export class ReviewService {
|
|
|
540
540
|
|
|
541
541
|
// 检查是否有其他同名 review workflow 正在运行中(防止同一 PR 重复审查)
|
|
542
542
|
// 需要显式启用 skipDuplicateWorkflow 配置
|
|
543
|
+
// 注意:Gitea Actions API 要求用户是 repo owner,否则会返回 403
|
|
543
544
|
if (skipDuplicateWorkflow && ci && pr?.head?.sha) {
|
|
544
545
|
const headSha = pr.head.sha;
|
|
545
546
|
// 获取当前 PR 编号(从 CI 环境变量)
|
|
@@ -549,32 +550,43 @@ export class ReviewService {
|
|
|
549
550
|
const prMatch = ref.match(/refs\/pull\/(\d+)/);
|
|
550
551
|
const currentPrNumber = prMatch ? parseInt(prMatch[1], 10) : prNumber;
|
|
551
552
|
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
(
|
|
561
|
-
w
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
553
|
+
try {
|
|
554
|
+
const runningWorkflows = await this.gitProvider.listWorkflowRuns(owner, repo, {
|
|
555
|
+
status: "in_progress",
|
|
556
|
+
});
|
|
557
|
+
// 获取当前 workflow 名称和 run ID
|
|
558
|
+
const currentWorkflowName = process.env.GITHUB_WORKFLOW || process.env.GITEA_WORKFLOW;
|
|
559
|
+
const currentRunId = process.env.GITHUB_RUN_ID || process.env.GITEA_RUN_ID;
|
|
560
|
+
// 只检查同 PR 同名的其他 workflow run(排除当前 run)
|
|
561
|
+
const duplicateReviewRuns = runningWorkflows.filter(
|
|
562
|
+
(w) =>
|
|
563
|
+
w.sha === headSha &&
|
|
564
|
+
w.name === currentWorkflowName &&
|
|
565
|
+
(!currentRunId || String(w.id) !== currentRunId),
|
|
566
|
+
);
|
|
567
|
+
if (duplicateReviewRuns.length > 0) {
|
|
568
|
+
if (shouldLog(verbose, 1)) {
|
|
569
|
+
console.log(
|
|
570
|
+
`⏭️ 跳过审查: 当前 PR #${currentPrNumber} 有 ${duplicateReviewRuns.length} 个同名 workflow 正在运行中`,
|
|
571
|
+
);
|
|
572
|
+
}
|
|
573
|
+
return {
|
|
574
|
+
success: true,
|
|
575
|
+
description: `跳过审查: PR #${currentPrNumber} 有 ${duplicateReviewRuns.length} 个同名 workflow 正在运行中,等待完成后重新审查`,
|
|
576
|
+
issues: [],
|
|
577
|
+
summary: [],
|
|
578
|
+
round: 1,
|
|
579
|
+
};
|
|
580
|
+
}
|
|
581
|
+
} catch (error) {
|
|
582
|
+
// Gitea Actions API 可能返回 403(需要 repo owner 权限)
|
|
583
|
+
// 捕获错误后跳过重复检查,继续执行审查
|
|
566
584
|
if (shouldLog(verbose, 1)) {
|
|
567
|
-
console.
|
|
568
|
-
|
|
585
|
+
console.warn(
|
|
586
|
+
`⚠️ 无法检查重复 workflow(可能缺少 repo owner 权限),跳过此检查:`,
|
|
587
|
+
error instanceof Error ? error.message : error,
|
|
569
588
|
);
|
|
570
589
|
}
|
|
571
|
-
return {
|
|
572
|
-
success: true,
|
|
573
|
-
description: `跳过审查: PR #${currentPrNumber} 有 ${duplicateReviewRuns.length} 个同名 workflow 正在运行中,等待完成后重新审查`,
|
|
574
|
-
issues: [],
|
|
575
|
-
summary: [],
|
|
576
|
-
round: 1,
|
|
577
|
-
};
|
|
578
590
|
}
|
|
579
591
|
}
|
|
580
592
|
} else if (effectiveBaseRef && effectiveHeadRef) {
|
|
@@ -700,7 +712,7 @@ export class ReviewService {
|
|
|
700
712
|
context.generateDescription && llmMode
|
|
701
713
|
? await this.generatePrDescription(commits, changedFiles, llmMode, undefined, verbose)
|
|
702
714
|
: await this.buildFallbackDescription(commits, changedFiles);
|
|
703
|
-
|
|
715
|
+
const result: ReviewResult = {
|
|
704
716
|
success: true,
|
|
705
717
|
title: prInfo.title,
|
|
706
718
|
description: prInfo.description,
|
|
@@ -708,6 +720,19 @@ export class ReviewService {
|
|
|
708
720
|
summary,
|
|
709
721
|
round: 1,
|
|
710
722
|
};
|
|
723
|
+
|
|
724
|
+
// CI 模式下也需要发送 review 评论
|
|
725
|
+
if (ci && prNumber && !dryRun) {
|
|
726
|
+
if (shouldLog(verbose, 1)) {
|
|
727
|
+
console.log(`💬 提交 PR 评论...`);
|
|
728
|
+
}
|
|
729
|
+
await this.postOrUpdateReviewComment(owner, repo, prNumber, result, verbose, autoApprove);
|
|
730
|
+
if (shouldLog(verbose, 1)) {
|
|
731
|
+
console.log(`✅ 评论已提交`);
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
return result;
|
|
711
736
|
}
|
|
712
737
|
|
|
713
738
|
const headSha = pr?.head?.sha || headRef || "HEAD";
|