Merge pull request 'fix(review publish): 降級處理 Gitea review 批次發布失敗' (#8) from develop into master
CD / Release Tag Version (push) Failing after 0s

Reviewed-on: docker-actions/ai-code-review#8
Reviewed-by: 系統管理員 <1+admin@noreply.localhost>
This commit was merged in pull request #8.
This commit is contained in:
2026-06-25 15:29:22 +00:00
2 changed files with 46 additions and 1 deletions
+19
View File
@@ -116,6 +116,8 @@ function toReviewComment(f) {
export async function postFindingsReview(findings, deps = {}) { export async function postFindingsReview(findings, deps = {}) {
const { const {
postReview = postPullReview, postReview = postPullReview,
postInline = postPullReviewComment,
postIssue = postComment,
summaryFindings = findings, summaryFindings = findings,
commentFindings = findings, commentFindings = findings,
usageSection = '', usageSection = '',
@@ -123,7 +125,24 @@ export async function postFindingsReview(findings, deps = {}) {
const sortedComments = [...commentFindings].sort(bySeverity); const sortedComments = [...commentFindings].sort(bySeverity);
const comments = sortedComments.filter(f => f.is_new !== false).map(toReviewComment).filter(Boolean); const comments = sortedComments.filter(f => f.is_new !== false).map(toReviewComment).filter(Boolean);
const body = buildReviewSummary(summaryFindings, usageSection); const body = buildReviewSummary(summaryFindings, usageSection);
try {
await postReview({ body, comments }); await postReview({ body, comments });
} catch (e) {
warn(`整批 review 發布失敗,改用 summary + 逐筆行內 comment: ${e.message}`);
try {
await postReview({ body, comments: [] });
} catch (summaryErr) {
warn(`review summary 發布失敗,改用一般 comment: ${summaryErr.message}`);
await postIssue(body);
}
for (const comment of comments) {
try {
await postInline({ path: comment.path, line: comment.new_position, body: comment.body });
} catch (commentErr) {
warn(`行內 review comment 發布失敗(略過): ${comment.path}:${comment.new_position} error=${commentErr.message}`);
}
}
}
ok(`review 發布: summary=${summaryFindings.length} total=${sortedComments.length} commentable=${comments.length}`); ok(`review 發布: summary=${summaryFindings.length} total=${sortedComments.length} commentable=${comments.length}`);
line(`review summary 統計: ${formatFindingsStatsLine(summaryFindings)}`); line(`review summary 統計: ${formatFindingsStatsLine(summaryFindings)}`);
line(`review comments 統計: ${formatFindingsStatsLine(sortedComments)}`); line(`review comments 統計: ${formatFindingsStatsLine(sortedComments)}`);
+26
View File
@@ -393,4 +393,30 @@ describe('postFindingsReview', () => {
assert.match(reviewCalls[0].comments[0].body, /.*/s); assert.match(reviewCalls[0].comments[0].body, /.*/s);
assert.doesNotMatch(reviewCalls[0].comments[0].body, /.*app\/a\.js:5/s); assert.doesNotMatch(reviewCalls[0].comments[0].body, /.*app\/a\.js:5/s);
}); });
it('falls back to summary review and per-comment posting when batch review fails', async () => {
const reviewCalls = [];
const inlineCalls = [];
await postFindingsReview([
{ level: 'warning', role: 'Leo', location: 'app/a.js:5', suggestion: '修正 A', is_new: true },
{ level: 'info', role: 'Maya', location: 'app/b.js:9', suggestion: '修正 B', is_new: true },
], {
postReview: async (args) => {
reviewCalls.push(args);
if (args.comments.length > 0) throw new Error('Request failed with status code 500');
},
postInline: async (args) => {
inlineCalls.push(args);
if (args.path === 'app/b.js') throw new Error('line not in diff');
},
postIssue: async () => {
throw new Error('一般 comment 不應被呼叫');
},
});
assert.equal(reviewCalls.length, 2);
assert.equal(reviewCalls[0].comments.length, 2);
assert.equal(reviewCalls[1].comments.length, 0);
assert.deepEqual(inlineCalls.map(c => `${c.path}:${c.line}`), ['app/a.js:5', 'app/b.js:9']);
});
}); });