Bạn đặt cancel-in-progress: false để một công việc đang chạy không bị hủy. Sau vài lần bấm chạy tiếp, một lượt vẫn bị canceled dù chưa bắt đầu. Trước khi coi đó là lỗi runner, hãy kiểm tra cả chính sách pending trong concurrency group.
Bài đối chiếu tài liệu GitHub Actions ngày 25/10/2026. YAML bên dưới đã được parse và rà cấu trúc tại máy, nhưng chưa được gửi lên GitHub hoặc chạy trên hosted runner. Đây là workflow quan sát hàng đợi, không thực hiện deploy và không cần secret.
1. Tách running khỏi pending
Theo hướng dẫn concurrency của GitHub, mặc định một group có tối đa một lượt running và một lượt pending. Lượt pending mới có thể thay lượt pending cũ. cancel-in-progress: true còn cho phép hủy lượt đang chạy.
Vì vậy, đặt false không tự biến group thành hàng đợi giữ mọi yêu cầu. Bạn cần phân biệt hai mong muốn: “không ngắt việc đang làm” và “mọi yêu cầu đều phải được xử lý”. Chúng là hai yêu cầu vận hành khác nhau.
2. Một workflow thử không chạm hệ thống thật
Trong repository thử có Actions được bật, tạo .github/workflows/concurrency-demo.yml trên default branch để có thể chạy thủ công:
name: Concurrency queue demo
on:
workflow_dispatch:
permissions: {}
concurrency:
group: demo-one-resource
cancel-in-progress: false
jobs:
observe:
runs-on: ubuntu-latest
steps:
- name: Hold this demo slot
env:
DEMO_RUN_ID: ${{ github.run_id }}
run: |
echo "Started demo run $DEMO_RUN_ID"
sleep 45
echo "Finished demo run $DEMO_RUN_ID"
Workflow không checkout source và chỉ in ID rồi giữ slot một thời gian ngắn. ubuntu-latest là nhãn runner do GitHub quản lý, không phải cam kết một bản hệ điều hành cố định. Việc thử vẫn có thể sử dụng hạn mức Actions của repository; chọn môi trường thử phù hợp của nhóm.
Mục đích của sleep là tạo thời gian để bạn quan sát trạng thái. Nó không mô phỏng transaction deploy, không xác nhận khả năng rollback và không chứng minh tác vụ ngoài GitHub đã dừng nếu workflow bị hủy.
3. Quan sát ba lượt có điều kiện rõ ràng
Gọi lượt đầu là A. Đợi A thực sự ở trạng thái running rồi tạo lượt B. Khi B đã pending trong cùng group, tạo lượt C trước khi A kết thúc. Với chính sách mặc định, hãy kiểm tra liệu B bị thay bởi C và A có tiếp tục không.
Ghi run ID và thời điểm chuyển trạng thái thay vì chỉ nhìn vị trí các dòng trên màn hình. Nếu A kết thúc quá nhanh hoặc B chưa vào pending khi C được tạo, bạn chưa dựng đúng tình huống cần quan sát. Hãy làm lại trong repository thử; không kết luận chỉ từ thứ tự ba lần bấm.
Sau đó đổi cancel-in-progress thành true trên một nhánh thử theo quy trình repository và lặp lại. Lần này điều cần quan sát là chính sách đối với running cũng thay đổi. Bài không ghi một output hosted giả định; bạn cần giữ log và trạng thái của lần chạy thực tế.
4. Đặt group theo tài nguyên cần bảo vệ
Một group cố định như ví dụ khiến các lượt của demo tranh cùng slot. Với CI độc lập theo nhánh, bạn có thể cần khóa có chứa workflow và ref để các nhánh không hủy lẫn nhau. Với nhiều workflow cùng tác động một môi trường, group chung có thể là chủ đích.
Tham chiếu workflow syntax mô tả concurrency ở cấp workflow và job. Đặt khóa ở cấp phù hợp: khóa toàn workflow sẽ giữ slot cả cho những công việc không trực tiếp dùng tài nguyên cần bảo vệ, còn khóa ở một job có phạm vi hẹp hơn.
Trước khi sửa khóa, liệt kê các workflow khác có thể tạo cùng tên group. Tên trông khác với người đọc chưa chắc tạo group độc lập; tài liệu lưu ý group không phân biệt hoa thường. Đặt tên có cấu trúc và ghi ý nghĩa trong README của dự án để người tiếp theo không dùng trùng ngoài ý muốn.
Khi nào cần giữ nhiều lượt chờ?
Tài liệu tại ngày đối chiếu còn có tùy chọn queue: max, cho phép nhiều pending hơn, tối đa 100, và không kết hợp với cancel-in-progress: true. Nếu nhóm cần giữ từng yêu cầu, hãy đọc lại khả năng hiện hành và giới hạn trước khi chọn. Không coi đó là một hàng đợi vô hạn hoặc suy ra thứ tự dispatch luôn là thứ tự bắt đầu chờ.
Với tác vụ có side effect, concurrency chỉ là một phần của thiết kế. Nhóm vẫn cần quyết định cách nhận biết phiên bản được xử lý, cách tiếp tục sau lỗi và khi nào một lượt mới được phép bỏ qua lượt cũ. Các chính sách đó không tự xuất hiện từ một cờ YAML.
Lỗi thường gặp và cách kiểm tra
Nếu hai workflow bất ngờ hủy nhau, tìm group trùng ở cấp repository. Nếu mỗi lượt đều chạy đồng thời, kiểm tra khóa có chứa một giá trị duy nhất cho mỗi run khiến chúng không còn cùng group không. Nếu pending biến mất dù false, kiểm tra chính sách queue trước khi sửa runner.
Parse YAML chỉ kiểm tra được một phần cấu trúc. Kết quả hosted mới giúp xác nhận event, quyền repository và hành vi hàng đợi thực tế. Hãy phân biệt hai loại bằng chứng này trong pull request.
Kết luận
Chọn concurrency bằng cách mô tả tài nguyên dùng chung và chính sách với cả running lẫn pending. Khi đã biết lượt nào được phép bỏ qua, bạn mới chọn group, cancel và queue phù hợp. Một phép thử không deploy giúp nhóm hiểu các lựa chọn đó trước khi đưa vào công việc thật.


