10 điểm bởi GN⁺ 2026-01-15 | 3 bình luận | Chia sẻ qua WhatsApp
  • Chia sẻ trải nghiệm đầy bực bội của một lập trình viên về vòng lặp phản hồi chậm và quá trình gỡ lỗi phức tạp của GitHub Actions
  • Trong dự án tmplr, tác giả dùng build.rs để tạo tài liệu bằng CUE, nhưng vấn đề bắt đầu khi bản dựng CI thất bại
  • Trong 4 nền tảng, chỉ Linux ARM bị lỗi build; nguyên nhân là cách GitHub Actions ẩn binary x86_64 trên runner arm64 trong quá trình cross build
  • Vòng lặp phản hồi kém hiệu quả lặp đi lặp lại, mất 2~3 phút cho mỗi lần kiểm tra một thay đổi đơn lẻ
  • Giải pháp là xóa build.rs và chuyển sang GNU Makefile, từ đó giải quyết vấn đề bằng cách tự kiểm soát logic CI

Bối cảnh phát sinh vấn đề

  • tmplr là công cụ scaffolding file/dự án sử dụng các file mẫu mà con người có thể đọc và viết
  • Trong build.rs, tác giả dùng CUE để tạo README.md, CHANGELOG.md, các file phiên bản/trợ giúp nhằm bảo đảm tính nhất quán
  • Bản thân công việc chỉ mất khoảng 1,5 giờ để hoàn thành, và bài viết liên quan cũng đã được viết xong
  • Mọi thứ hoạt động bình thường ở môi trường local, nhưng trong môi trường CI của GitHub Actions thì bản dựng thất bại do chưa cài binary CUE

Nguyên nhân bản dựng thất bại

  • Trong 4 nền tảng (Linux ARM, macOS ARM, Linux x86_64, macOS x86_64), chỉ Linux ARM gặp lỗi “command not found”
  • Nguyên nhân: matrix cross build bị cô lập rất chặt, nên CUE chỉ được cài trên host Linux x86_64host macOS ARM
    • macOS không gặp vấn đề khi chạy binary x86_64
    • Linux x86_64 cũng không gặp vấn đề khi chạy binary x86_64
    • Nhưng GitHub Actions ẩn binary x86_64 trên runner arm64, khiến nó không thể thực thi

Vòng lặp phản hồi kém hiệu quả

  • Quy trình được lặp đi lặp lại để xử lý vấn đề:
    1. Tìm các cách sửa có thể áp dụng
    2. Sửa ci.yml
    3. Commit và push (jj squash --ignore-immutable && jj git push)
    4. Mở tab “Actions”
    5. Mở lần chạy mới nhất
    6. Mở lần chạy Linux ARM
    7. Đợi vài giây
    8. Thất vọng
    9. Lặp lại
  • Mất 2~3 phút cho mỗi thay đổi đơn lẻ
  • Lý tưởng nhất là GitHub nên cung cấp local runner đầy đủ tính năng, hoặc ít nhất là tính năng giúp xem nhanh tiến trình sau khi push
    • Một tính năng như "scratch commit": cách để thử nhiều lần chạy khác nhau mà không làm bẩn lịch sử Git và lịch sử thực thi Action
  • Nhưng hiện tại chưa có tính năng như vậy

Cách giải quyết

  • Sau khi lặp lại vòng đó trong 30 phút, tác giả dừng lại
  • Áp dụng lời khuyên phổ biến trên Internet: “Đừng để GitHub Actions quản lý logic; hãy tự kiểm soát bằng script, còn Actions chỉ việc gọi script đó
  • Xóa build.rs (dù có chút tiếc nuối, nhưng cần phải hy sinh)
  • Chuyển toàn bộ tác vụ tạo file sang GNU Makefile
  • Commit các file đã được tạo vào repository và hoàn tác các thay đổi trong CI
  • Vấn đề được giải quyết hoàn toàn

Kết luận

  • GitHub Actions là nguyên nhân khiến người ta không thể tận dụng một số điều tốt đẹp
  • Việc gỡ lỗi runner hoặc tối ưu hóa quy trình build làm tốn rất nhiều thời gian
  • Tuy vậy, nó vẫn có những lợi ích khó có được bằng cách khác, chẳng hạn như build macOS
  • Dĩ nhiên, cũng không rõ có hệ thống nào khác dễ cấu hình hơn GitHub Actions hay không

We are all doomed to GitHub Actions. …but at least I dodged the bullet early.

3 bình luận

 
iolothebard 2026-01-15

GitHub Actions chỉ nên làm việc thiết lập môi trường (OS, build toolchain, …) và chạy script (shell, Python, bat, ps1…). Dù GitHub có bị sập thì chỉ cần có đủ môi trường là phải có thể build ở bất cứ đâu. Dạo này nhìn workflow GitHub Actions thấy đến mức này mà vẫn phải lục tìm để dùng những thứ như vậy sao. Ngày xửa ngày xưa(?) Ansible cũng từng như thế rồi thất bại.

 
GN⁺ 2026-01-15
Ý kiến trên Hacker News
  • Vấn đề cốt lõi của GitHub Actions là vòng phản hồi quá chậm
    Việc phải push rồi chờ chỉ để xác nhận một lỗi đơn giản thực sự rất bực bội
    Tôi nghĩ tốt hơn là tách các tác vụ CI thành những script có thể chạy cục bộ, còn tính năng của Actions chỉ nên dùng như một lớp cải tiến bổ sung
    Tổ hợp workflow_dispatchgh workflow run cũng ổn, nhưng việc cái sau không trả ngay URL của workflow đã chạy thì khá bất tiện

    • Dùng nektos/act thì có thể chạy Actions ở máy local
      Nó khá hiệu quả trong việc mang lại phản hồi nhanh
    • Tôi đã chuẩn hóa để Actions build và test image Docker
      Khi có sự cố, có thể debug trong trạng thái gần như giống hệt môi trường GitHub Actions
    • Tôi thấy việc không thể chạy các bước CI ở local là vô lý
      Đó nên là yêu cầu cơ bản của mọi hệ thống CI
    • Tôi từng cân nhắc tự làm một công cụ CI có thể chạy local
      Rốt cuộc điều quan trọng là các tính năng như xếp hàng, phân tích đầu ra, và telemetry lịch sử build
    • Khi dùng gh workflow run, để lấy URL tôi phải gọi lại GitHub API để lấy danh sách các lần chạy workflow
      Nếu có nhiều lần chạy đồng thời thì có thể bị rối, nhưng hiện tại vẫn hoạt động tạm ổn
  • Tôi đã tổng hợp vài mẹo thiết kế CI

    1. Dùng ngôn ngữ script thân thiện với CI như pwsh thay vì bash
    2. Đừng nhét logic vào workflow, hãy giữ nó đơn giản
    3. Tạo thành các script độc lập để có thể test ở local
    4. Ghi lại trạng thái và thông tin phiên bản để dễ debug
    5. Cân nhắc runner bên thứ ba có tính năng debug tốt
    • Tôi không đồng ý với (1). Nếu quá trình build hay test trở nên phức tạp thì đó là một mùi code
      Shell đơn giản là đủ
    • Tôi không đồng ý với (1), nhưng nghĩ (2) là đúng
      Nên định nghĩa target CI trong Makefile, rồi gọi đơn giản như make ci-test
    • Trước đây tôi từng trải qua địa ngục plugin Jenkins
      Từ đó về sau, tôi quản lý toàn bộ CI bằng những wrapper đơn giản như make build
    • Nếu bọc mọi bản build trong một script duy nhất thì hệ thống CI sẽ mất insight về từng bước chi tiết
      Sẽ tốt hơn nếu có thể phân tách bằng các marker như BeginStep("Step Name")
    • Cuối cùng, với cấu trúc như vậy, có lẽ cần một công cụ CI mới chuyên chạy trực tiếp các script
  • Vấn đề không nằm ở bản thân GitHub Actions, mà là ở lớp tự động hóa chắp vá đặt lên trên nó
    Logic nên được script hóa bằng ngôn ngữ như Python để cũng có thể chạy ở local

    • Điều khiến nhiều người khó chịu là không thể truy cập trực tiếp qua SSH vào VM bị lỗi để debug
      Lúc nào cũng phải sửa workflow, push rồi chờ
    • Cũng có người đùa rằng “mấy việc script hóa như vậy là kiểu công việc vài tuần có lương”
    • Những tính năng chỉ dành cho CI như deploy, release, cache thì khó tái hiện hoàn toàn ở local
    • Cách tiếp cận này gợi cảm giác như thời systemd gọi các script init.d, nhưng cũng không tệ
    • Có người còn khẳng định “đây là lỗi 100% của GitHub Actions”
  • Tôi xử lý toàn bộ CI bên trong container
    Nền tảng CI chỉ việc chạy container đó, nên ở local cũng có thể chạy y hệt
    Các nền tảng không thích cách này vì nó phá vỡ vendor lock-in

    • Tôi thích SourceHut CI
      Khi lỗi có thể SSH vào ngay để debug, và có thể sửa manifest rồi chạy lại mà không cần push branch
      Tuy nhiên nó cần tự self-host
    • Trong GitLab CI tôi cũng từng dùng cách tương tự với image Docker chuyên dụng
      Việc chuẩn hóa trở nên dễ hơn, nhưng đánh đổi bằng chi phí bảo trì image
    • Nhược điểm là build macOS rất khó container hóa
    • Webhook của GitHub rất chi tiết
      Thực ra gần như không có lock-in, chỉ là mọi người đang sa vào cargo cult CI/CD
    • Thậm chí còn có phản hồi kiểu “hãy gửi nội dung này thành newsletter cho tôi”
  • Tôi thích GitHub Actions
    Nó tốt hơn Travis mà tôi từng dùng trước đây, và là một nguồn tài nguyên miễn phí rất hữu ích cho các dự án OSS
    Sau khi áp dụng Nix, tính tái lập môi trường tăng lên nên Actions hợp với nó hơn hẳn

    • Tôi cũng đồng ý với cách tiếp cận Nix
      Container tạo bằng flake có thể chạy nguyên xi trong Actions
      Dự án ví dụ
  • Tôi nghĩ GitHub Actions đơn giản chỉ nên có cấu trúc gọi các script bash hoặc python
    Bash có nhiều giới hạn, còn Python linh hoạt hơn và cũng dễ chạy local hơn
    Cách tự động cài uv và quản lý dependency như trong bài viết này là lý tưởng
    Nó phức tạp hơn bash, nhưng trong môi trường Actions thì vấn đề hiệu năng không lớn

    • Thực tế YAML là để định nghĩa môi trường runtime, còn logic thực thi nên đặt ở script bên ngoài
  • Vấn đề lớn nhất của Actions là cách quảng bá việc “hãy ghép các workflow lại với nhau”
    Việc debug gần như bất khả thi, cấu hình cache thì khó nên build chậm
    Vì vậy cách chạy trực tiếp trên VM tồn tại liên tục trở nên khá hấp dẫn

  • Tôi là nhà sáng lập của Depot
    Tôi đang vận hành một dịch vụ cung cấp runner GitHub Actions nhanh hơn và rẻ hơn
    Những bất mãn mà nhiều người cảm nhận thực sự là ý kiến của đa số
    Bản thân hệ thống Actions có sự kém hiệu quả mang tính cấu trúc, và tuần nào chúng tôi cũng phát hiện ra một điểm nghẽn mới
    Tôi tin chắc có cách tốt hơn và đang thử nghiệm điều đó
    Có thể xem thêm tại depot.dev

  • Cuối tuần trước tôi đã làm một công cụ tên là gg watch action
    Đây là công cụ tìm action mới nhất hoặc đang chạy của branch hiện tại
    Liên kết GitHub

    • Mọi người phản hồi khá tốt, kiểu như “đây đáng ra phải là tính năng của gh CLI”
      Tuy vậy có lỗi là lệnh gg tui không hiển thị repository
  • Tôi từng thắc mắc liệu công cụ như act có hữu ích không
    nektos/act
    Do khác biệt kiến trúc nên việc chạy local và online có thể khác nhau, nhưng trông vẫn khá hữu ích

    • Hồi trước khi tôi xem thì nó chưa phải giải pháp thay thế hoàn chỉnh
      Mức tương thích khoảng 80%
    • Nó không hoàn toàn giống hệt, nhưng rất hữu ích để tạo ra vòng phản hồi nhanh
    • Thực ra điều cần nhất là khả năng SSH vào để debug sau khi thất bại
      SourceHut hỗ trợ điều này nên thực sự rất tiện
 
anyflow 2026-01-18

Có vẻ đây là một vấn đề khó tránh khỏi vì cấu trúc buộc phải nhét logic vào bên trong YAML.

Bài viết trên dường như cũng đưa ra câu trả lời đại khái như bên dưới, và tôi cũng nghĩ rằng nếu thay phần script bằng Dagger thì đó có lẽ mới là đáp án đúng.

"Đừng để GitHub Actions quản lý logic; hãy trực tiếp kiểm soát script, còn Actions chỉ nên gọi các script đó thôi"