Bỏ qua để đến nội dung

3.6 CI/CD Integration

Thả Claude Code vào một pipeline CI/CD thì nó thôi làm công cụ tương tác cho developer và trở thành một cỗ máy review và sinh code tự động. Đề thi kiểm tra năm khái niệm trong task statement này, và cờ -p là thứ được hỏi trực tiếp nhiều nhất (nó là Question 10 trong bộ sample question).

Claude Code mặc định chạy ở interactive mode: nó chờ input từ bàn phím và hiển thị giao diện hội thoại. Một CI pipeline thì không có bàn phím. Không có cờ -p, job treo vĩnh viễn, chờ một input không bao giờ tới.

Terminal window
# WRONG — hangs in CI
claude "Analyse this pull request for security issues"
# CORRECT — runs non-interactively
claude -p "Analyse this pull request for security issues"

Cờ -p (cũng viết là --print) chuyển Claude Code sang print mode: nó xử lý prompt, in kết quả ra stdout, rồi thoát. Không cần input tương tác.

Cái này thuần học thuộc. Đề thi đưa ra một CI job bị treo, log cho thấy Claude đang chờ input, rồi hỏi bạn chọn cách sửa. Đáp án là cờ -p. Không phải CLAUDE_HEADLESS=true (không tồn tại). Không phải --batch (không tồn tại). Không phải chuyển hướng stdin từ /dev/null (không thực sự giải quyết interactive mode của Claude Code).

Trong CI, output của Claude Code phải máy đọc được. Không có người nào ngồi đọc nó. Hệ thống tự động sẽ xử lý nó để đăng inline comment lên PR, cập nhật dashboard, hay kích hoạt workflow phía sau.

Hai cờ làm việc cùng nhau:

  • --output-format json — bọc lần chạy trong một JSON envelope (text kết quả, session ID, metadata về chi phí và usage) thay vì text cho người đọc
  • --json-schema — validate output cuối của agent theo một JSON Schema (chỉ dùng được ở print mode)
Terminal window
claude -p \
--output-format json \
--json-schema '{"type":"object","properties":{"findings":{"type":"array","items":{"type":"object","properties":{"file":{"type":"string"},"line":{"type":"integer"},"severity":{"type":"string"},"message":{"type":"string"}}}}}}' \
"Review this PR for security issues"

Dữ liệu khớp schema nằm ở field structured_output của envelope — lấy bằng jq '.structured_output', không phải từ cấp trên cùng. Nhờ vậy hệ thống tự động có được các finding đã validate để:

  • Parse bằng code
  • Đăng thành inline comment trên PR ở đúng file và đúng dòng
  • Lọc theo severity cho các kênh thông báo khác nhau
  • Theo dõi qua các lần review

Chính session Claude đã sinh ra code thì review lại thay đổi của mình kém hiệu quả hơn. Đây không phải lo lắng lý thuyết; đó là hiệu ứng đo được.

Vì sao tự review lại yếu hơn:

Khi Claude sinh code trong một session, nó tích lại context suy luận: vì sao chọn hướng này, đã cân nhắc đánh đổi gì, đã loại bỏ phương án nào. Bảo nó review chính đoạn code đó trong cùng session thì nó giữ nguyên toàn bộ phần đó. Nó ít có khả năng chất vấn những quyết định mà nó đã tự biện minh.

Cách sửa: dùng instance review độc lập

Dùng một lần gọi Claude Code riêng để review — một lần gọi không có quyền truy cập context suy luận của session sinh code. Bên review độc lập đánh giá code theo đúng bản thân nó, không bị thiên lệch bởi phần biện minh trước đó.

Terminal window
# Step 1: Generate code (session A)
claude -p "Implement the authentication middleware"
# Step 2: Review code (session B — independent, no shared context)
claude -p "Review the authentication middleware for security issues, error handling gaps, and edge cases"

Khái niệm này nối sang Domain 4 (kiến trúc review nhiều instance) và Domain 5 (quản lý context). Đề thi hỏi nó cụ thể trong bối cảnh CI/CD.

Review tự động chạy ở mọi lần push. Không có context về các lần review trước, mỗi lần chạy lại phân tích cả PR từ đầu, nên nó suy ra y nguyên bộ finding cũ mỗi lần. Một vấn đề đã thật sự sửa thì tự rụng khỏi danh sách, vì code đã đổi không còn kích hoạt nó nữa. Những cái quay lại đều đặn là các vấn đề developer đã thấy và cố ý không đổi; một lần quét lại không có context thì không phân biệt nổi chúng với vấn đề mới, nên nó lại gắn cờ ở mọi lần push.

Cách sửa: đưa các finding từ lần review trước vào context và yêu cầu Claude chỉ báo cáo vấn đề mới hoặc vấn đề vẫn chưa được xử lý.

Terminal window
claude -p \
--output-format json \
"Review this PR. Here are the findings from the previous review:
${PREVIOUS_FINDINGS}
Report ONLY:
1. New issues not in the previous findings
2. Issues from the previous findings that are still present
Do NOT re-report previous findings the developer has already reviewed and chosen not to act on."

Comment trùng lặp bào mòn lòng tin của developer. Nếu mỗi lần push đều sinh ra đúng năm comment y hệt bất kể developer đã sửa hay chưa, developer sẽ ngừng đọc comment. Context review tăng dần giữ được tỉ lệ tín hiệu trên nhiễu.

Khi Claude Code chạy trong CI, nó đọc file CLAUDE.md của project y như khi chạy tương tác. Nên CLAUDE.md chính là cách bạn đưa context riêng của project vào một lần chạy do CI gọi:

  • Chuẩn testing: thế nào là một test có giá trị, theo pattern nào, tránh gì
  • Fixture có sẵn: đang có những test fixture nào, dùng ra sao, chứa dữ liệu gì
  • Tiêu chí review: thế nào là finding nghiêm trọng, thế nào chỉ là vấn đề style nhỏ
  • Coverage hiện có: cái gì đã được phủ, để tránh đề xuất test trùng

Không có phần context này trong CLAUDE.md, việc sinh test do CI gọi sẽ cho ra boilerplate vô giá trị. Có nó, test được sinh ra theo pattern của team và bổ sung coverage thật.

# .claude/CLAUDE.md — CI-relevant section
## Testing Standards
- Tests must use the factory pattern from test/factories/ for data creation
- Integration tests connect to the test database via test/setup/db.ts
- Do not test private implementation details — test public API contracts
- Coverage target: 80% branch coverage for new code
- Available fixtures: test/fixtures/users.json, test/fixtures/orders.json

-p là cờ được hỏi trực tiếp nhiều nhất, nhưng đề thi cũng mong bạn quen với những cờ định hình một lần chạy headless: output được format thế nào, dùng system prompt nào, và permission cùng tool được giới hạn ra sao. Những cờ này dùng được với claude -p trong CI và với lệnh claude tương tác.

Cờ liên quan tới system prompt. Claude Code có bốn cờ ở đây, và đề thi kiểm tra phân biệt append với replace:

Cờ Tác dụng
--system-prompt "<text>" Thay thế toàn bộ system prompt mặc định
--system-prompt-file <path> Thay thế prompt mặc định bằng nội dung một file
--append-system-prompt "<text>" Nối thêm text vào prompt mặc định
--append-system-prompt-file <path> Nối nội dung một file vào prompt mặc định

Dùng append khi Claude vẫn nên là trợ lý code, chỉ thêm việc tuân theo quy tắc riêng của bạn. Append giữ nguyên phần hướng dẫn tool, chỉ dẫn an toàn và coding convention mặc định, nên bạn chỉ phải cung cấp phần khác biệt. Dùng replace khi định danh hoặc mô hình permission khác hẳn Claude Code, ví dụ một agent phi lập trình trong pipeline không ai giám sát. Replace bỏ toàn bộ prompt mặc định, nên bạn chịu trách nhiệm với mọi thứ tác vụ còn cần.

Output và giới hạn ở chế độ headless (print mode).

Cờ Tác dụng
--output-format text|json|stream-json Dạng output cho -p; jsonstream-json máy đọc được
--input-format text|stream-json Dạng input cho -p
--json-schema '<schema>' Output được validate theo schema cho -p; đi kèm --output-format json thì nằm ở field structured_output của envelope
--max-turns <n> Chặn số lượt agentic rồi thoát

Permission, tool và context.

Cờ Tác dụng
--permission-mode <mode> Khởi động ở default, acceptEdits, plan, auto, dontAsk, bypassPermissions, hoặc manual (alias của default, từ v2.1.200)
--allowedTools "<rules>" Tool chạy được mà không hỏi permission, ví dụ "Bash(git diff *)" "Read"
--disallowedTools "<rules>" Deny rule; chỉ ghi trần tên tool sẽ gỡ hẳn tool đó khỏi context
--tools "Bash,Edit,Read" Giới hạn những built-in tool nào khả dụng
--add-dir <path> Thêm một thư mục Claude được đọc và sửa (cấp quyền truy cập file, không phải phát hiện cấu hình)
--model <alias|name> Đặt model cho session (sonnet, opus, hoặc tên model đầy đủ)

Session và khởi động. -c / --continue tiếp tục hội thoại gần nhất trong thư mục hiện tại, còn -r / --resume <id|name> tiếp tục một session cụ thể. --bare là chế độ tối giản: nó bỏ qua việc tự phát hiện hook, skill, plugin, MCP server, auto memory và CLAUDE.md để lệnh gọi trong script khởi động nhanh hơn, chỉ để lại cho Claude tool Bash và tool đọc/sửa file. Dùng --bare khi bạn muốn một lần chạy script nhanh, dễ đoán và không cần load cấu hình của project.

Đưa test hiện có vào để tránh trùng lặp

Phần tiêu đề “Đưa test hiện có vào để tránh trùng lặp”

Khi chạy sinh test trong CI, hãy đưa những file test hiện có vào context. Thiếu chúng, Claude Code có thể đề xuất những test đã tồn tại, làm phí thời gian review của developer. Có chúng, Claude nhận ra khoảng trống coverage thay vì nhân bản những kịch bản đã có.

Message Batches API giảm 50% chi phí nhưng thời gian xử lý có thể lên tới 24 giờ, không có cam kết SLA về độ trễ. Điều đó tạo ra một ranh giới quyết định rõ ràng:

Loại workflow Chọn API Lý do
Kiểm tra trước merge (chặn) Real-time (đồng bộ) Developer ngồi chờ kết quả
Báo cáo technical debt chạy đêm Batch API Không gấp về thời gian, tiết kiệm 50%
Audit code hàng tuần Batch API Có lịch, chịu được độ trễ
Sinh test ban đêm Batch API Chạy qua đêm, sáng hôm sau xem

Kiểm tra trước merge là workflow chặn. Developer không merge được tới khi kiểm tra xong. Batch API không phù hợp ở đây vì nó không cam kết gì về độ trễ. Đề thi hỏi trực tiếp phân biệt này (Sample Question 11).

Một script CI pipeline chạy claude với một prompt nhưng job treo vô thời hạn. Log cho thấy Claude Code đang chờ input tương tác. Cách sửa đúng là gì?

  • A. Thêm cờ -p để Claude Code chạy ở print mode non-interactive
  • B. Set biến môi trường CLAUDE_HEADLESS=true trước khi chạy lệnh
  • C. Chuyển hướng stdin từ /dev/null để chặn các prompt tương tác
  • D. Thêm cờ –batch để bật chế độ xử lý theo lô
Đáp án & giải thích

Đúng: A

  • A — Cờ -p (–print) chạy Claude Code ở chế độ non-interactive. Nó xử lý prompt, in kết quả ra stdout, rồi thoát mà không chờ input từ user. Đây là cách tích hợp CI/CD được ghi trong tài liệu.
  • B — CLAUDE_HEADLESS không phải biến môi trường có thật của Claude Code. Phương án này nhắc tới một tính năng không tồn tại.
  • C — Chuyển hướng stdin kiểu Unix là cách chữa cháy chung chung, không thực sự giải quyết interactive mode của Claude Code. Cờ -p mới là cách đúng, có trong tài liệu.
  • D — –batch không phải cờ CLI có thật của Claude Code. Phương án này nhắc tới một tính năng không tồn tại.

Sáu câu trắc nghiệm theo format đề thi về CI/CD Integration. Chọn đáp án trước, rồi mở phần giải thích.

Một script CI pipeline chạy ‘claude “Analyse this PR”’ nhưng job treo vô thời hạn. Log cho thấy Claude Code đang chờ input tương tác. Cách sửa đúng là gì?

  • A. Thêm cờ –batch: claude –batch “Analyse this PR”
  • B. Set biến môi trường CLAUDE_HEADLESS=true trước khi chạy lệnh
  • C. Chuyển hướng stdin từ /dev/null: claude “Analyse this PR” < /dev/null
  • D. Thêm cờ -p: claude -p “Analyse this PR” trong CI
Đáp án & giải thích

Đúng: D

  • A sai vì: –batch không phải cờ CLI có thật của Claude Code. Phương án này nhắc tới một tính năng không tồn tại.
  • B sai vì: CLAUDE_HEADLESS không phải biến môi trường có thật của Claude Code. Phương án này nhắc tới một tính năng không tồn tại.
  • C sai vì: Chuyển hướng stdin kiểu Unix là cách chữa cháy chung chung, không thực sự giải quyết interactive mode của Claude Code. Cờ -p mới là cách đúng, có trong tài liệu.
  • D đúng vì: Cờ -p (–print) chạy Claude Code ở chế độ non-interactive. Nó xử lý prompt, in kết quả ra stdout, rồi thoát mà không chờ input từ user. Đây là cách tích hợp CI/CD được ghi trong tài liệu.

Một CI pipeline cần đăng các finding review thành inline comment trên PR ở đúng file và đúng số dòng. Nên dùng cờ nào với Claude Code?

  • A. –output-format json cùng với –json-schema
  • B. –verbose và –line-numbers
  • C. –format markdown và –annotate
  • D. Chỉ –output-format json, không cần schema
Đáp án & giải thích

Đúng: A

  • A đúng vì: –output-format json cho ra output JSON, còn –json-schema cưỡng chế một cấu trúc cụ thể với các field file, line, severity và message. Nhờ vậy hệ thống tự động parse được finding và đăng chúng thành inline comment ở đúng vị trí.
  • B sai vì: –verbose và –line-numbers không phải cờ hợp lệ của Claude Code cho output có cấu trúc.
  • C sai vì: –format markdown và –annotate không phải cờ hợp lệ của Claude Code.
  • D sai vì: –output-format json có cho ra JSON, nhưng thiếu –json-schema thì cấu trúc không đảm bảo có đúng những field cần cho việc comment inline trên PR.

Một team chạy Claude Code để sinh authentication middleware, rồi trong cùng session nhờ Claude review đoạn code vừa sinh. Bản review không tìm thấy vấn đề nào. Một thành viên khác review độc lập chính đoạn code đó thì tìm ra ba lỗ hổng bảo mật. Vì sao bản tự review bỏ sót?

  • A. Session sinh code dùng model kém hơn session review
  • B. Claude Code không review được code do chính nó sinh ra vì một giới hạn kỹ thuật
  • C. Session giữ lại context lúc sinh code và sẽ không tự chất vấn mình
  • D. Bản tự review cần prompt chi tiết hơn để tìm ra vấn đề bảo mật
Đáp án & giải thích

Đúng: C

  • A sai vì: Cả hai session dùng cùng model. Vấn đề là thiên lệch do context, không phải năng lực model.
  • B sai vì: Không có giới hạn kỹ thuật nào ngăn việc tự review. Vấn đề là hiệu quả, không phải khả năng. Tự review vẫn chạy nhưng bị thiên lệch.
  • C đúng vì: Session sinh code đã tích lại context suy luận — vì sao chọn hướng này, cân nhắc đánh đổi gì, loại bỏ phương án nào. Khi được nhờ review, nó vẫn giữ phần biện minh đó và ít có khả năng chất vấn những quyết định nó đã tự hợp lý hoá.
  • D sai vì: Prompt chi tiết hơn không gỡ được thiên lệch từ context suy luận. Vấn đề gốc là session khó tự thách thức lập luận trước đó của chính nó.

Một CI review pipeline chạy ở mọi lần push. Developer phàn nàn rằng cùng năm vấn đề bị gắn cờ ở mọi lần push, kể cả sau khi họ đã xử lý một số. Cách sửa đúng là gì?

  • A. Giảm tần suất review xuống một lần mỗi ngày thay vì mỗi lần push
  • B. Đưa finding cũ vào và chỉ yêu cầu vấn đề mới hoặc chưa sửa
  • C. Lọc output để bỏ các finding cũ hơn 24 giờ
  • D. Dùng prompt review khác, bớt kỹ hơn
Đáp án & giải thích

Đúng: B

  • A sai vì: Giảm tần suất không sửa được vấn đề comment trùng lặp. Cùng những vấn đề đó vẫn xuất hiện mỗi lần review chạy.
  • B đúng vì: Đưa finding trước đó vào context và yêu cầu Claude chỉ báo cáo vấn đề mới hoặc vẫn còn tồn tại sẽ chặn được comment trùng lặp. Cách này giữ tỉ lệ tín hiệu trên nhiễu và giữ lòng tin của developer vào hệ thống review.
  • C sai vì: Lọc theo tuổi là không đáng tin. Một vấn đề bị gắn cờ hôm qua và đã sửa hôm nay vẫn bị chặn. Vấn đề mới cũng có thể lọt vào bộ lọc.
  • D sai vì: Làm bản review bớt kỹ thì bỏ sót vấn đề thật. Vấn đề là báo cáo trùng lặp, không phải phát hiện quá mức.

Một team muốn dùng Message Batches API cho các kiểm tra CI trước merge để tiết kiệm chi phí. Cách này có phù hợp không?

  • A. Không, Batch API có thể mất tới 24 giờ và không cam kết SLA về độ trễ
  • B. Có, khoản tiết kiệm 50% đủ để dùng Batch API cho mọi workflow CI
  • C. Có, miễn là team đặt timeout 5 phút cho batch request
  • D. Không, vì Batch API không hỗ trợ tác vụ code review
Đáp án & giải thích

Đúng: A

  • A đúng vì: Message Batches API có thời gian xử lý tới 24 giờ và không cam kết SLA về độ trễ. Kiểm tra trước merge là workflow chặn — developer không merge được tới khi kiểm tra xong. Batch API phù hợp với tải không chặn, chịu được độ trễ, như báo cáo technical debt chạy đêm hay audit hàng tuần.
  • B sai vì: Tiết kiệm chi phí không bù được việc chặn developer đang chờ merge. Kiểm tra trước merge phải xong nhanh.
  • C sai vì: Batch API không hỗ trợ đặt timeout tuỳ ý. Không có cơ chế nào đảm bảo hoàn thành nhanh.
  • D sai vì: Batch API xử lý được tác vụ code review. Vấn đề là độ trễ, không phải khả năng.

Claude Code do CI gọi sinh ra file test, nhưng test dùng dữ liệu inline chung chung thay vì các factory function và file fixture đã có của team. Nguyên nhân nhiều khả năng nhất là gì?

  • A. Claude Code không truy cập được thư mục test/factories/ trong CI
  • B. Claude Code chạy trong CI dùng model rút gọn, không sinh được test tinh vi
  • C. Chuẩn testing, factory function và fixture có sẵn của team không được ghi trong CLAUDE.md
  • D. Cờ -p vô hiệu hoá việc truy cập file cấu hình của project
Đáp án & giải thích

Đúng: C

  • A sai vì: Claude Code trong CI có cùng quyền truy cập file như ở chế độ tương tác, trong phạm vi repository.
  • B sai vì: Cùng một model chạy ở cả chế độ tương tác lẫn CI. Không có biến thể rút gọn nào.
  • C đúng vì: Claude Code đọc CLAUDE.md trong CI y như khi chạy tương tác. Không có chuẩn testing, tài liệu về factory function và đường dẫn fixture trong CLAUDE.md, Claude Code chẳng có context nào về pattern của team và rơi về boilerplate chung chung.
  • D sai vì: Cờ -p chỉ chuyển từ interactive sang print mode. Nó không chặn việc truy cập file cấu hình. File CLAUDE.md vẫn được đọc.