Claude Code trong CI/CD: review pull request tự động với -p
Chạy Claude Code headless trong CI bằng claude -p, lấy finding dạng JSON để comment lên PR, giảm false positive và chọn API đồng bộ hay Message Batches.
Một bot review làm treo pipeline, đăng lại cùng một comment năm lần, hoặc bắt bẻ từng lỗi style nhỏ thì chỉ sau một tuần là bị tắt. Scenario 5 của đề CCAR-F xoay quanh đúng những lỗi đó. Bài này chỉ cách chạy Claude Code ở chế độ headless trong CI, lấy kết quả dạng JSON để đăng thành inline comment trên PR, và chọn đúng API cho từng loại job.
Chạy Claude Code trong CI/CD bằng `claude -p`
Lệnh claude "Review this PR" mở một phiên tương tác. Trên CI runner không có ai trả lời, nên job đứng chờ mãi. Cách sửa là cờ -p (hoặc --print): Claude Code xử lý prompt, in kết quả ra stdout rồi thoát với exit code mà script kiểm tra được.
gh pr diff "$PR_NUMBER" | claude -p "Review this diff for bugs and security issues" \
--allowedTools "Read,Grep,Glob"
Đáp án nhiễu trong đề hay bịa ra thứ không tồn tại: biến môi trường CLAUDE_HEADLESS, cờ --batch, hoặc redirect stdin từ /dev/null. Cách được tài liệu hóa là -p.
Thêm hai cờ hay dùng: --allowedTools cấp sẵn quyền cho các tool cần thiết vì không có ai bấm "allow", và --max-turns giới hạn độ dài một lần chạy.
Kết quả máy đọc được với `--output-format json` và `--json-schema`
Text tự do đủ cho người đọc log. Nhưng muốn đăng inline comment, script cần file, số dòng và nội dung của từng finding. Task statement 3.6 nêu hai cờ:
--output-format jsonbọc response trong JSON, text nằm ở trườngresult, kèm session ID, usage và chi phí.--json-schematruyền vào một JSON Schema. Output phải khớp schema và nằm ở trườngstructured_output.
claude -p "Review the changes on this branch against CLAUDE.md review criteria" \
--allowedTools "Read,Grep,Glob,Bash(git diff *)" \
--output-format json \
--json-schema "$(cat .github/review-schema.json)" \
| jq '.structured_output.findings' > findings.json
Schema chỉ cần mỗi finding có file, line, severity (ví dụ bug, security, performance) và message. Bước sau duyệt findings.json và gọi GitHub API để đăng từng comment.
Phiên bản GitHub Actions
Anthropic có action chính thức anthropics/claude-code-action@v1. Ở automation mode bạn truyền prompt, còn claude_args nhận mọi cờ CLI:
name: Claude PR review
on:
pull_request:
types: [opened, synchronize]
jobs:
review:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
id-token: write
steps:
- uses: actions/checkout@v6
- uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
prompt: "Review PR #${{ github.event.pull_request.number }} using the criteria in CLAUDE.md"
claude_args: "--max-turns 10"
Đề thi hỏi về cờ CLI chứ không hỏi input của action, nên học -p, --output-format json, --json-schema trước. Hiện Anthropic còn có tính năng Code Review được quản lý sẵn, chạy trên mọi PR mà không cần file workflow. Tính năng này ra sau exam guide và không phải thứ Scenario 5 hỏi tới.
Cung cấp context cho reviewer trong CI và giữ nó độc lập
CLAUDE.md là context của CI. Lần chạy claude -p load CLAUDE.md của repo giống như phiên tương tác. Đặt tiêu chí review, chuẩn viết test và các fixture có sẵn ở đó, pipeline nào cũng dùng được. Lưu ý theo tài liệu hiện tại: cờ --bare (khuyến nghị cho script cần kết quả ổn định) bỏ qua CLAUDE.md. Nếu dùng nó, hãy truyền tiêu chí bằng --append-system-prompt-file. Xem thêm thứ bậc CLAUDE.md.
Review lại chỉ báo cái mới. Khi developer push bản sửa, lần review mới không nhớ gì về lần trước và sẽ lặp lại toàn bộ. Hãy đưa các finding cũ vào prompt và yêu cầu Claude chỉ báo vấn đề mới hoặc chưa được xử lý. Với sinh test cũng vậy: đưa các file test hiện có vào context để Claude không đề xuất lại kịch bản đã có.
Dùng reviewer độc lập. Phiên đã viết code vẫn giữ lập luận của chính nó nên dễ đồng tình với quyết định cũ. Task statement 4.6 nói rõ: một instance thứ hai không có context của bên sinh code bắt lỗi tốt hơn câu lệnh "hãy tự review lại" hay extended thinking trong cùng phiên.
Chia PR lớn thành nhiều lượt. Một lượt cho 14 file sẽ cho độ sâu không đều và nhận xét mâu thuẫn nhau. Chạy một lượt riêng cho từng file để bắt lỗi cục bộ, rồi một lượt integration xem luồng dữ liệu giữa các file. Context window lớn hơn không chữa được việc chú ý bị dàn mỏng.
Giảm false positive bằng tiêu chí rõ ràng
Bot sai một nửa số lần thì developer sẽ bỏ qua, và một nhóm lỗi nhiều nhiễu kéo theo mất niềm tin vào cả nhóm chính xác. Câu "hãy thận trọng" hay "chỉ báo khi chắc chắn" không giúp mấy. Quy tắc theo loại cụ thể thì có:
- Báo: lỗi logic, lỗi bảo mật, comment mô tả sai hành vi thật của code.
- Bỏ qua: style nhỏ, sở thích đặt tên, pattern giống code xung quanh.
Mỗi mức severity nên có ví dụ code cụ thể để phân loại nhất quán. Nếu một nhóm cứ sinh nhiễu, tạm tắt nó trong lúc sửa prompt.
API đồng bộ hay Message Batches API
Có job chặn merge, có job đợi đến sáng được. Chọn API theo yêu cầu độ trễ:
| Workload | API | Lý do |
|---|---|---|
| Check trước merge, developer đang chờ | Messages API đồng bộ (hoặc claude -p) | Cần kết quả ngay |
| Sinh test hằng đêm, audit hằng tuần, báo cáo tech debt | Message Batches API | Rẻ hơn 50%, chịu được độ trễ |
Batches API xử lý trong tối đa 24 giờ, không cam kết độ trễ. Mỗi request có custom_id để ghép kết quả với input và chỉ gửi lại những request lỗi. Nó cũng không hỗ trợ gọi tool nhiều lượt trong một request, nên việc agentic cần kết quả tool giữa chừng phải dùng API đồng bộ.
Thử sức
Bot review trong CI chạy mỗi lần push lên PR. Sau khi developer push bản sửa, bot đăng lại cả tám comment cũ, kể cả ba lỗi đã sửa. Bạn nên đổi gì?
A. Thêm --max-turns 1 để review dừng trước khi lặp lại.
B. Đưa finding của lần chạy trước vào prompt và yêu cầu Claude chỉ báo vấn đề mới hoặc chưa được xử lý.
C. Chạy review trong cùng phiên đã sinh code để nó nhớ các comment cũ.
D. Chuyển lần review lại sang Message Batches API để kết quả được khử trùng lặp theo custom_id.
Đáp án: B. Lần chạy mới không biết gì về comment cũ, nên bạn phải đưa finding trước đó vào và nói rõ cần báo gì.
- A giới hạn số lượt, không giải quyết trùng lặp. Review một lượt vẫn có thể lặp đủ tám comment.
- C tái dùng context của bên sinh code, làm review kém đi, và CI vốn không mang bộ nhớ giữa các lần push.
- D nhầm giữa ghép cặp và khử trùng lặp.
custom_idchỉ ghép response với request, không biết gì về review cũ.
Điểm chính cần nhớ
-p(--print) là cách chính thức để chạy Claude Code không tương tác. Thiếu nó, CI bị treo.--output-format jsoncùng--json-schemacho finding parse được trongstructured_output, sẵn sàng làm inline comment.- CLAUDE.md mang tiêu chí review vào CI. Finding cũ mang trạng thái giữa các lần review lại.
- Review bằng instance độc lập, chia PR lớn thành lượt theo file cộng một lượt integration.
- Đồng bộ cho check chặn merge, Message Batches (50% chi phí, tối đa 24h,
custom_id) cho job ban đêm.
Câu hỏi thường gặp
Nó chạy Claude Code ở chế độ không tương tác (print): nhận prompt, chạy đến hết, ghi kết quả ra stdout rồi thoát. Đó là thứ pipeline CI và script cần.
Theo cách đề thi đặt vấn đề thì không. Batch có thể mất tới 24 giờ và không cam kết độ trễ, nên check chặn merge phải dùng API đồng bộ.
Đọc thêm: structured output với JSON schema và hooks hay ép bằng prompt. Luyện câu hỏi Scenario 5 để nắm chắc thiết kế CI và review.