Một step ghi COLOR=green vào file GITHUB_ENV, nhưng dòng echo ngay sau vẫn đọc giá trị cũ. Đây không nhất thiết là lỗi runner. Bạn vừa ghi dữ liệu để runner cấp cho các step sau, chưa thay biến trong tiến trình shell đang chạy.
Tài liệu GitHub Actions được đọc ngày 03/11/2026. Workflow đã được parse YAML, các script Bash được kiểm tra cục bộ với environment file tạm. Chưa chạy workflow trên GitHub, chưa dùng hosted runner hoặc secret. Kết quả local được tách khỏi hành vi liên step mô tả theo tài liệu.
Hai cơ chế diễn ra ở thời điểm khác nhau
export NAME=value cập nhật biến trong shell hiện tại và môi trường của tiến trình con nó tạo ra. Ghi một dòng vào $GITHUB_ENV là cung cấp dữ liệu theo giao thức environment file của runner. Nó không tự thực thi một lệnh gán trong shell hiện tại.
Tài liệu GitHub quy định giá trị ghi theo cách này khả dụng ở các step tiếp theo trong cùng job. Nó không phải kho biến toàn cục giữa nhiều job độc lập. Với nhu cầu truyền dữ liệu giữa job, cần thiết kế outputs hoặc cơ chế phù hợp, thay vì dựa vào một environment file của step trước.
Workflow thủ công để quan sát
Có thể lưu đoạn sau thành .github/workflows/env-demo.yml trong repository thử:
name: Environment file demonstration
on:
workflow_dispatch:
permissions: {}
jobs:
environment-demo:
runs-on: ubuntu-latest
timeout-minutes: 3
env:
AEDEV_COLOR: blue
steps:
- name: Write next-step environment
shell: bash
run: |
printf 'Before: %s\n' "$AEDEV_COLOR"
printf 'AEDEV_COLOR=green\n' >> "$GITHUB_ENV"
printf 'After write: %s\n' "$AEDEV_COLOR"
- name: Read environment in next step
shell: bash
run: |
printf 'Next step: %s\n' "$AEDEV_COLOR"
Theo hợp đồng runner, hai dòng của step đầu dự kiến vẫn đọc blue; step sau đọc green. Đây là tiêu chí cần kiểm chứng khi bạn chạy workflow thử, không phải log GitHub đã thu trong bài. Workflow chỉ có trigger thủ công, không checkout, không gọi action bên ngoài và không cần credential.
Không tự tạo GITHUB_ENV trong workflow thật. Runner cung cấp đường dẫn cho từng step. Chỉ trong fixture local của bài, chúng ta dùng file tạm để kiểm tra việc ghi file không tự thay biến shell.
Khi cần dùng ngay trong cùng step
Trong một step Bash đã có $GITHUB_ENV, mẫu sau vừa gán giá trị hiện tại vừa ghi cho step sau:
AEDEV_COLOR=green
export AEDEV_COLOR
printf 'AEDEV_COLOR=%s\n' "$AEDEV_COLOR" >> "$GITHUB_ENV"
printf 'Current shell: %s\n' "$AEDEV_COLOR"
Snippet này đã chạy cục bộ với file tạm và biến ban đầu blue: shell đọc green, file nhận đúng một dòng gán green. Phép thử không mô phỏng toàn bộ parser, quyền hay lifecycle của runner. Nó chỉ xác nhận hai hành động cần tách rõ trong script.
Giữ định dạng và phạm vi rõ ràng
Demo dùng tên biến riêng của bài, không ghi đè PATH, HOME hoặc biến mặc định GITHUB_*. Dùng >> để append thay vì ghi đè các dòng mà cùng step có thể đã tạo. Giá trị trong ví dụ chỉ một dòng và không chứa dữ liệu không tin cậy.
Với nội dung có newline, cú pháp một dòng NAME=value không đủ để giữ nguyên nội dung. Hãy đọc quy tắc multiline environment file và chọn delimiter không xuất hiện trong dữ liệu. Không dùng source "$GITHUB_ENV" làm cách áp dụng chung: file theo giao thức runner không phải hợp đồng cho phép thực thi shell tùy ý.
Tránh in token hoặc mật khẩu để “kiểm tra biến đã truyền chưa”. Các giá trị màu trong demo không nhạy cảm nên có thể quan sát trực tiếp; ứng dụng thật nên kiểm tra sự hiện diện hoặc hành vi cần thiết mà không lộ secret.
Kiểm tra kết quả đúng cấp
Ở local, kiểm tra stdout và nội dung file tạm. Trên GitHub, kiểm tra log từng step và phạm vi cùng job. Nếu step sau vẫn đọc giá trị cũ, rà tên biến, vị trí ghi, định dạng và việc nó có thực sự thuộc cùng job hay không.
Chốt thời điểm cần dùng biến trước khi chọn export hay environment file. Phân biệt shell hiện tại với step tiếp theo giúp bạn sửa đúng chỗ thay vì thêm nhiều dòng echo nhưng vẫn không hiểu giá trị đến từ đâu.


