Dependency đổi lúc 3 giờ sáng — ai canh cho bạn?

Dependency đổi lúc 3 giờ sáng — ai canh cho bạn?

Dùng GitHub Actions để tự động phát hiện file upstream thay đổi và mở issue nhắc team — setup xong trong 30 phút.

Bạn đang nhìn đường hay đang nhắm mắt lái?

Bạn có bao giờ mở laptop sáng thứ Hai, pha cà phê xong, và nhận ngay tin nhắn: "Anh ơi, API bên đối tác đổi response schema rồi, app mình lỗi từ tối thứ Sáu"?

Mình thì có. Nhiều hơn một lần.

Vấn đề không phải team bạn kém. Vấn đề là bạn đang phụ thuộc vào một thứ nằm ngoài tầm kiểm soát — một file upstream, một API spec, một class bạn "mượn" từ thư viện khác — và không có ai canh. Hiểu nôm na: bạn đang chạy xe trên cao tốc mà không có cảnh báo giao thông. Đường tốt thì không sao, nhưng khi có tai nạn phía trước, bạn là người biết sau cùng.

Simon Willison — tác giả của Datasette — gặp đúng bài toán này. Ông muốn dùng class GZipMiddleware của Starlette nhưng không muốn kéo cả thư viện vào làm dependency. Giải pháp: extract class đó ra package riêng. Nhưng Starlette vẫn được maintain tích cực — nếu họ fix bug hay cải tiến, làm sao biết để cập nhật bản copy?

Câu trả lời: GitHub Actions + git scraping + tự động mở issue.

Trước khi có "lính gác": canh bằng cơm

Nếu team bạn đang dùng cách nào trong số này, mình hiểu cảm giác:

Giả sử team bạn 5 người, maintain một service dùng code extract từ 3 thư viện khác nhau. Mỗi thư viện release trung bình vài lần mỗi tháng. Bạn cần canh ít nhất 3 file ở 3 repo khác nhau. Nhân lên theo thời gian, đây là công việc không ai muốn làm — và vì không ai muốn, nên không ai làm.

Như mình đã chia sẻ trong bài về dependency "bẩn" (bài 49), một dependency mà bạn không kiểm soát có thể trở thành quả bom hẹn giờ. Hôm nay mình nói thêm phần "rà bom" — cách phát hiện sớm trước khi nổ.

Sau khi có "lính gác": bot canh, bot báo, bạn chỉ việc review

Ý tưởng cốt lõi đơn giản đến bất ngờ:

  1. Cron job trên GitHub Actions chạy định kỳ (ví dụ mỗi ngày)
  2. Mỗi lần chạy, nó fetch file bạn muốn theo dõi từ URL gốc
  3. So sánh với bản cũ đã lưu trong repo
  4. Nếu khác → commit bản mới + tự động mở issue kèm diff

Bạn không cần server, không cần database, không cần trả thêm đồng nào. GitHub Actions free tier cho public repo là quá đủ. Nói thẳng ra thì toàn bộ cơ chế giám sát này chạy trên hạ tầng miễn phí, bằng đúng một file YAML.

30 phút setup: từ zero đến lính gác

Bước 1 — Tạo workflow file

Trong repo của bạn, tạo file .github/workflows/track-upstream.yml:

name: Track upstream file
on:
  schedule:
    - cron: '0 8 * * *'  # Chạy mỗi ngày lúc 8h UTC
  workflow_dispatch:       # Cho phép chạy tay khi cần

jobs:
  track:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Fetch upstream file
        run: |
          curl -sL "URL_FILE_BAN_MUON_CANH" -o tracked/upstream-file.py

      - name: Check for changes
        id: diff
        run: |
          if git diff --quiet tracked/; then
            echo "changed=false" >> $GITHUB_OUTPUT
          else
            echo "changed=true" >> $GITHUB_OUTPUT
          fi

      - name: Commit changes
        if: steps.diff.outputs.changed == 'true'
        run: |
          git config user.name "github-actions[bot]"
          git config user.email "github-actions[bot]@users.noreply.github.com"
          git add tracked/
          git commit -m "Update: upstream file changed"
          git push

      - name: Open issue
        if: steps.diff.outputs.changed == 'true'
        uses: peter-evans/create-issue-from-file@v4
        with:
          title: "⚠️ Upstream file changed — cần review"
          content: |
            File upstream vừa thay đổi.
            Kiểm tra diff trong commit mới nhất.
          labels: upstream-change

Bước 2 — Tạo thư mục tracked/ và fetch bản đầu tiên

mkdir tracked
curl -sL "URL_FILE_BAN_MUON_CANH" -o tracked/upstream-file.py
git add tracked/ && git commit -m "Initial tracked file" && git push

Bước 3 — Test bằng workflow_dispatch

Vào tab Actions trên GitHub, chọn workflow, bấm "Run workflow". Nếu file chưa đổi → không có issue mới. Muốn test nhanh? Sửa file trong tracked/ để giả lập thay đổi, push lên, rồi chạy lại — issue sẽ được tạo tự động.

Hai kịch bản thực tế cho team Việt Nam

Kịch bản 1 — Canh API spec của đối tác:
Team bạn integrate với cổng thanh toán. Đối tác publish file OpenAPI spec trên một URL công khai. Mỗi khi họ đổi schema (thêm field, đổi format), workflow tự phát hiện và mở issue. Team review diff, cập nhật client code trước khi user nào kịp gặp lỗi.

Kịch bản 2 — Theo dõi thư viện đã fork:
Bạn fork một module xử lý ảnh từ thư viện lớn, chỉ giữ phần mình cần (giống cách Simon Willison extract GZipMiddleware). Workflow canh file gốc trên GitHub của thư viện mẹ. Khi upstream commit fix lỗi bảo mật, bạn biết trong vòng 24 giờ thay vì 24 ngày.

Bẫy mà mình từng dẫm

Bẫy 1 — Quên xử lý rate limit. Nếu bạn fetch từ GitHub API thay vì raw URL, cron chạy quá thường xuyên sẽ bị rate limit. Giải pháp: dùng raw URL (raw.githubusercontent.com) hoặc thêm token vào workflow secrets.

Bẫy 2 — False positive từ reformat. File upstream thay đổi format nhưng không đổi logic — upstream reformat code, thêm trailing newline. Bạn nhận alert, review xong thấy... không có gì đáng kể. Giải pháp: thêm bước normalize (strip whitespace, sort imports) trước khi so sánh, hoặc chấp nhận false positive — vẫn tốt hơn miss một bug fix thật.

Bẫy 3 — Issue mở rồi, không ai đọc. Automation hay mấy mà không ai assign, không ai review thì cũng như lắp chuông báo cháy trong nhà hoang. Thêm label, assign người cụ thể trong workflow, hoặc gắn thêm bước gửi Slack notification qua webhook.

Mở rộng khi đã quen tay

Đừng tin mình, thử đi rồi biết — 30 phút là đủ để có một con bot canh chừng giùm bạn, chạy 24/7, không đòi lương, không nghỉ phép, và quan trọng nhất: không bao giờ quên.

---

Bụi Wire — nghiện đọc release notes lúc 2 giờ sáng

Nguồn tham khảo