Product Management
Đăng nhập
ESC

Nhập từ khóa để tìm kiếm

↑↓ Di chuyển
Enter Mở
ESC Đóng

Bài 7 — Tích hợp agent vào CI/CD và pull request

Đã đọc 0/10 mục · còn khoảng 3 phút
Cách chúng tôi ghi nhận

Một mục được tính là đã đọc khi nó nằm giữa màn hình đủ lâu so với độ dài của nó (bảng và sơ đồ tính một nửa), bạn vẫn đang cuộn hoặc bấm phím, và bạn đã thấy tới cuối mục. Lướt nhanh hoặc để tab mở không được tính. Chúng tôi chỉ lưu thời gian đọc từng mục — không lưu gì khác.

Một agent chạy trên máy cá nhân thì ít giá trị. Sức mạnh thật đến khi nó tự chạy trên mỗi pull request, comment thẳng vào dòng code có lỗi, và chặn merge khi có P0. Bài này biến agent thành người gác cổng tự động.

1. Nguyên tắc vàng: chỉ quét DIFF

Quét toàn repo mỗi PR vừa chậm vừa tốn token, lại tạo nhiễu về code cũ chưa ai đụng. Chỉ quét phần thay đổi (kèm vài dòng ngữ cảnh):

git diff --unified=8 origin/main...HEAD -- '*.php' '*.py' '*.js' > changes.diff

--unified=8 cho 8 dòng ngữ cảnh quanh mỗi thay đổi để agent hiểu bối cảnh mà vẫn gọn.

2. Pipeline CI (ví dụ GitHub Actions)

name: sast-agent
on: [pull_request]
jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with: { fetch-depth: 0 }
      - name: Get diff
        run: git diff --unified=8 origin/${{github.base_ref}}...HEAD
              -- '*.php' '*.py' > changes.diff
      - name: Run agent
        env:
          LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
        run: python -m agent.scan --diff changes.diff --out report.sarif
      - name: Upload SARIF
        uses: github/codeql-action/upload-sarif@v3
        with: { sarif_file: report.sarif }
      - name: Gate
        run: python -m agent.gate report.sarif --fail-on P0

3. Xuất chuẩn SARIF để comment inline

SARIF là định dạng chuẩn để GitHub/GitLab hiển thị cảnh báo ngay trên dòng code trong tab Files changed. Map finding của agent sang SARIF:

def to_sarif(findings):
    return {"version": "2.1.0", "runs": [{
      "tool": {"driver": {"name": "SAST-LLM-Agent"}},
      "results": [{
        "ruleId": f["type"],
        "level": "error" if f["priority"] >= 250 else "warning",
        "message": {"text": f'{f["why"]}\nFix: {f["fix"]}'},
        "locations": [{"physicalLocation": {
          "artifactLocation": {"uri": f["file"]},
          "region": {"startLine": f["line"]}}}]
      } for f in findings]}]}

4. Cổng chặn (gate) hợp lý

Đừng chặn merge vì mọi cảnh báo — sẽ gây phẫn nộ. Chính sách nên là:

  • P0 (CONFIRMED, confidence cao) → chặn merge (fail CI).
  • P1/P2 → comment cảnh báo, KHÔNG chặn.
  • UNCERTAIN → comment nhẹ "cần review thủ công", không chặn.
def gate(findings):
    blockers = [f for f in findings
                if f["priority"] >= 250 and f["verdict"] == "CONFIRMED"]
    if blockers:
        print(f"BLOCKED: {len(blockers)} lỗ hổng P0")
        sys.exit(1)

5. Chống nhiễu lặp lại (dedup + baseline)

Đừng báo lại lỗi cũ ở mỗi lần push. Lưu fingerprint (hash của file+dòng+loại) và bỏ qua cái đã được đánh dấu "đã xử lý" hoặc "chấp nhận rủi ro":

fp = hashlib.sha1(f"{f['file']}:{f['type']}:{f['snippet']}".encode())
if fp.hexdigest() in accepted_baseline:
    continue   # bỏ qua, đã được duyệt trước đó

6. Kiểm soát chi phí và thời gian

  • Chỉ quét file mã nguồn (bỏ test, vendor, node_modules).
  • Gộp finding theo file trước khi phản biện để giảm số lời gọi.
  • Đặt timeout và ngân sách token tối đa mỗi PR.
  • Cache kết quả theo hash nội dung file — file không đổi thì không quét lại.

Các bước triển khai

  • Thêm job CI chạy trên pull_request.
  • Lấy diff với ngữ cảnh, lọc theo đuôi file.
  • Chạy finder → verifier → rank.
  • Xuất SARIF, upload để hiện inline.
  • Gate chỉ chặn P0 CONFIRMED.
  • Áp baseline để bỏ lỗi đã duyệt.
  • Đặt trần token + timeout.

Checklist tích hợp

  • [ ] Chỉ quét diff, không toàn repo?
  • [ ] Xuất SARIF để comment inline?
  • [ ] Gate chỉ chặn P0 CONFIRMED?
  • [ ] Có baseline/dedup chống lặp?
  • [ ] Secret key qua CI secrets, không hardcode?
  • [ ] Có trần token và timeout?

Sai lầm thường gặp

  • Chặn merge vì mọi cảnh báo: dev nổi loạn, tắt tool.
  • Quét toàn repo mỗi PR: chậm, tốn tiền, đầy nhiễu code cũ.
  • Không dedup: cùng một lỗi báo lại 10 lần qua các commit.
  • Không giới hạn token: một PR khổng lồ đốt sạch ngân sách.
  • Log secret vào output CI: rò key API.
Bài cuối: vận hành thực tế, đo lường và cải thiện liên tục.

Học xong bài này rồi? Tạo tài khoản miễn phí để lưu lại — lần sau vào là biết ngay đang dở ở đâu, và học hết khóa thì có chứng chỉ. Lưu tiến độ của tôi