mirror of
https://github.com/Tencent/teamai-cli.git
synced 2026-10-02 03:14:40 +08:00
fix(ci): fail closed when comment lookup fails (#697)
Co-authored-by: ydflow <314143294+ydflow@users.noreply.github.com>
This commit is contained in:
@@ -1659,6 +1659,8 @@ Workflow:
|
||||
|
||||
If the review-status API returns a non-2xx response, write mode fails closed: the job exits without writing files, committing, or pushing to the team knowledge repo.
|
||||
|
||||
Comment mode also fails closed when it cannot list the existing marker comment, so a transient provider error cannot create a duplicate comment.
|
||||
|
||||
Ready-to-use templates:
|
||||
|
||||
- `examples/ci/github-actions-mr-extract.yml` (GitHub Actions)
|
||||
|
||||
@@ -1607,6 +1607,8 @@ teamai ci extract-mr --url "$MR_URL" --mode write --team-repo ./team-repo --indi
|
||||
|
||||
如果审核状态 API 返回非 2xx 响应,write 模式会按 fail-closed 处理:任务失败退出,且不会向团队知识仓库写入文件、提交或 push。
|
||||
|
||||
评论模式在无法列出已有 marker 评论时也会按 fail-closed 处理,避免临时的 Provider 错误创建重复评论。
|
||||
|
||||
开箱即用模板:
|
||||
|
||||
- `examples/ci/github-actions-mr-extract.yml`(GitHub Actions)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { parseMrUrl, formatComment } from '../ci/mr-comment.js';
|
||||
import { afterEach, describe, it, expect, vi } from 'vitest';
|
||||
import { parseMrUrl, formatComment, postOrUpdateMrComment } from '../ci/mr-comment.js';
|
||||
import type { LearningDraft, CodebaseSuggestion } from '../types.js';
|
||||
|
||||
describe('parseMrUrl', () => {
|
||||
@@ -62,3 +62,38 @@ describe('formatComment', () => {
|
||||
expect(result).not.toContain('### Codebase.md 更新建议');
|
||||
});
|
||||
});
|
||||
|
||||
describe('postOrUpdateMrComment API failures', () => {
|
||||
afterEach(() => {
|
||||
vi.unstubAllEnvs();
|
||||
vi.unstubAllGlobals();
|
||||
});
|
||||
|
||||
it('fails without creating a duplicate GitHub comment when listing comments fails', async () => {
|
||||
vi.stubEnv('GITHUB_TOKEN', 'test-token');
|
||||
const fetchMock = vi.fn().mockResolvedValue(new Response(null, { status: 503 }));
|
||||
vi.stubGlobal('fetch', fetchMock);
|
||||
|
||||
await expect(postOrUpdateMrComment(
|
||||
'https://github.com/acme/app/pull/7', undefined, undefined,
|
||||
)).rejects.toThrow('GitHub comment list request failed (503)');
|
||||
|
||||
expect(fetchMock).toHaveBeenCalledTimes(1);
|
||||
expect(fetchMock.mock.calls[0][1]?.method).toBe('GET');
|
||||
});
|
||||
|
||||
it('fails without creating a duplicate TGit note when listing notes fails', async () => {
|
||||
vi.stubEnv('TGIT_TOKEN', 'test-token');
|
||||
const fetchMock = vi.fn()
|
||||
.mockResolvedValueOnce(new Response(JSON.stringify([{ id: 42, iid: 7 }]), { status: 200 }))
|
||||
.mockResolvedValueOnce(new Response(null, { status: 503 }));
|
||||
vi.stubGlobal('fetch', fetchMock);
|
||||
|
||||
await expect(postOrUpdateMrComment(
|
||||
'https://git.woa.com/acme/app/merge_requests/7', undefined, undefined,
|
||||
)).rejects.toThrow('TGit note list request failed (503)');
|
||||
|
||||
expect(fetchMock).toHaveBeenCalledTimes(2);
|
||||
expect(fetchMock.mock.calls.some(([, init]) => init?.method === 'POST')).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -133,7 +133,9 @@ async function findGitHubComment(
|
||||
`/repos/${owner}/${repo}/issues/${prNumber}/comments?per_page=100`,
|
||||
'GET',
|
||||
);
|
||||
if (!resp.ok) return null;
|
||||
if (!resp.ok) {
|
||||
throw new Error(`GitHub comment list request failed (${resp.status})`);
|
||||
}
|
||||
const comments = (await resp.json()) as GitHubComment[];
|
||||
return comments.find((c) => c.body.includes(marker)) ?? null;
|
||||
}
|
||||
@@ -224,7 +226,9 @@ async function findTGitComment(
|
||||
`/projects/${projectId}/merge_requests/${mrGlobalId}/notes?per_page=100`,
|
||||
'GET',
|
||||
);
|
||||
if (!resp.ok) return null;
|
||||
if (!resp.ok) {
|
||||
throw new Error(`TGit note list request failed (${resp.status})`);
|
||||
}
|
||||
const notes = (await resp.json()) as TGitNote[];
|
||||
return notes.find((n) => n.body.includes(marker)) ?? null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user