Tôi thực sự ghét GitHub Actions
(xlii.space)- 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.rsvà 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ạoREADME.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_64 và host 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ửaci.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
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.
Ý 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_dispatchvàgh workflow runcũng ổn, nhưng việc cái sau không trả ngay URL của workflow đã chạy thì khá bất tiệnNó khá hiệu quả trong việc mang lại phản hồi nhanh
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
Đó nên là yêu cầu cơ bản của mọi hệ thống CI
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
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 workflowNế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
Shell đơn giản là đủ
Nên định nghĩa target CI trong
Makefile, rồi gọi đơn giản nhưmake ci-testTừ đó về sau, tôi quản lý toàn bộ CI bằng những wrapper đơn giản như
make buildSẽ tốt hơn nếu có thể phân tách bằng các marker như
BeginStep("Step Name")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
Lúc nào cũng phải sửa workflow, push rồi chờ
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
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
Việc chuẩn hóa trở nên dễ hơn, nhưng đánh đổi bằng chi phí bảo trì image
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
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
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
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
ghCLI”Tuy vậy có lỗi là lệnh
gg tuikhông hiển thị repositoryTôi từng thắc mắc liệu công cụ như
actcó hữu ích khôngnektos/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
Mức tương thích khoảng 80%
SourceHut hỗ trợ điều này nên thực sự rất tiện
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"