Bắt Đầu Nhanh: Workflow GitHub Actions Đầu Tiên Trong 5 Phút
Nếu bạn đã từng push code rồi vội vàng SSH thủ công vào server để deploy — bạn biết cái cảm giác đó rồi. GitHub Actions giải quyết vấn đề đó cho tôi khoảng hai năm trước. Từ đó đến nay không còn cảnh rollback lúc nửa đêm vì deploy tay bị lỗi nữa.
Ý tưởng cốt lõi: viết một file YAML, commit vào repo, và GitHub sẽ tự động chạy script của bạn mỗi khi có sự kiện xảy ra — push code, tạo pull request, hay gắn tag. Không cần CI server riêng, không cần cài Jenkins, không mất thêm tiền trừ khi bạn thực sự cần.
Hai lệnh để bắt đầu:
# Tạo thư mục workflow
mkdir -p .github/workflows
touch .github/workflows/ci.yml
Dán pipeline tối giản này:
name: CI Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Lấy code về
uses: actions/checkout@v4
- name: Cài đặt Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Cài đặt thư viện
run: pip install -r requirements.txt
- name: Chạy tests
run: pytest tests/
Commit file này, push lên GitHub, rồi vào tab Actions của repo. Bạn sẽ thấy workflow đang chạy. Đó là CI pipeline đầu tiên của bạn rồi đó.
Tìm Hiểu Sâu: Hiểu Cấu Trúc Workflow
Cấu trúc YAML trực quan hơn bạn nghĩ. Bốn khái niệm sau giải thích được 90% những gì bạn sẽ gặp hàng ngày.
Triggers (on:)
Block on: định nghĩa điều kiện kích hoạt workflow. Đây là những trigger tôi dùng thường xuyên nhất:
on:
push:
branches: [main]
tags:
- 'v*' # Kích hoạt khi có tag phiên bản như v1.0.0
pull_request:
branches: [main]
schedule:
- cron: '0 2 * * *' # Chạy hàng ngày lúc 2 giờ sáng UTC
workflow_dispatch: # Cho phép kích hoạt thủ công từ GitHub UI
Trigger workflow_dispatch thường bị đánh giá thấp. Chỉ cần click một nút trong GitHub UI là có thể kích hoạt deployment thủ công — rất tiện cho môi trường staging khi bạn không muốn tự động hóa hoàn toàn.
Jobs và Steps
Mặc định, các job chạy song song. Các step bên trong một job chạy tuần tự. Muốn các job chạy theo thứ tự? Dùng needs::
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: pytest tests/
build:
runs-on: ubuntu-latest
needs: test # Chỉ chạy nếu 'test' thành công
steps:
- uses: actions/checkout@v4
- run: docker build -t myapp:latest .
deploy:
runs-on: ubuntu-latest
needs: build # Chờ 'build' thành công
steps:
- run: echo "Đang triển khai..."
Quản Lý Secrets
Không bao giờ hardcode thông tin xác thực vào file workflow. Vào repo → Settings → Secrets and variables → Actions để thêm secrets. Tham chiếu chúng như sau:
- name: Triển khai lên server
env:
SSH_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
SERVER_HOST: ${{ secrets.SERVER_HOST }}
run: |
echo "$SSH_KEY" > /tmp/deploy_key
chmod 600 /tmp/deploy_key
ssh -i /tmp/deploy_key -o StrictHostKeyChecking=no \
ubuntu@$SERVER_HOST "cd /app && git pull && systemctl restart myapp"
Sử Dụng Nâng Cao: Các Pattern Hoạt Động Tốt Trong Thực Tế
Matrix Build cho Nhiều Môi Trường
Khi cần kiểm tra code chạy được trên Python 3.9, 3.10 và 3.11, tôi không viết ba job riêng lẻ. Matrix strategy xử lý điều đó:
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.9', '3.10', '3.11']
os: [ubuntu-latest, windows-latest]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- run: pytest tests/
Đó là 6 job chạy song song — mọi phiên bản Python trên mọi hệ điều hành. Khi có lỗi, GitHub hiển thị chính xác tổ hợp nào bị lỗi. Python 3.11 trên Windows crash trong khi 3.9 vẫn pass? Bạn sẽ biết ngay sau một lần chạy.
Cache Dependencies
Cài đặt lại từ đầu mỗi lần chạy làm pipeline chậm đi. Hãy cache các gói pip giữa các lần chạy:
- name: Cache các gói pip
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-
- name: Cài đặt thư viện
run: pip install -r requirements.txt
Cache key băm nội dung requirements.txt, nên tự động invalidate khi dependencies thay đổi. Với một project Python cỡ trung bình, điều này giúp cắt giảm thời gian cài đặt từ ~60 giây xuống còn ~5 giây.
Build Docker và Push Lên Registry
Đây là workflow build-and-push đầy đủ cho Docker Hub:
jobs:
docker:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Đăng nhập vào Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_TOKEN }}
- name: Build và push
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: |
myuser/myapp:latest
myuser/myapp:${{ github.sha }}
Mỗi lần build đều được gắn tag bằng git commit SHA. Rollback trở nên đơn giản — bạn luôn biết chính xác commit nào đang chạy trên production.
Triển Khai Theo Môi Trường
GitHub Environments cho phép bạn thêm quy tắc bảo vệ và tách biệt secrets theo từng môi trường (staging và production):
jobs:
deploy-staging:
runs-on: ubuntu-latest
environment: staging
steps:
- name: Triển khai lên staging
run: ./deploy.sh staging
deploy-production:
runs-on: ubuntu-latest
environment: production # Có thể yêu cầu phê duyệt thủ công
needs: deploy-staging
if: github.ref == 'refs/heads/main'
steps:
- name: Triển khai lên production
run: ./deploy.sh production
Cấu hình môi trường production yêu cầu người review, và không gì được triển khai cho đến khi ai đó click Approve trong GitHub UI. Một cửa kiểm soát thủ công. Mọi thứ còn lại vẫn tự động.
Mẹo Thực Tế Từ Các Pipeline Thực Chiến
Giữ Workflow Tập Trung
Một lỗi phổ biến là nhét tất cả mọi thứ vào một file workflow duy nhất. Hãy tách biệt: file ci.yml để test mỗi khi push, file deploy.yml chỉ kích hoạt khi có tag hoặc merge vào main. File nhỏ hơn dễ debug hơn khi có sự cố lúc 11 giờ đêm.
Dùng Điều Kiện if: để Bỏ Qua Bước Thông Minh
- name: Chỉ triển khai trên nhánh main
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
run: ./deploy.sh
Test chạy trên mọi nhánh. Deploy chỉ kích hoạt trên main. Các nhánh feature không thể vô tình tác động đến production.
Dừng Sớm, Nhưng Đừng Quá Vội
strategy:
fail-fast: false # Cho phép tất cả matrix job hoàn thành dù có job bị lỗi
matrix:
python-version: ['3.9', '3.10', '3.11']
Hành vi mặc định là hủy tất cả matrix job ngay khi một job bị lỗi. Đặt fail-fast: false và bạn sẽ có bức tranh toàn cảnh — có thể 3.9 pass nhưng 3.11 bị lỗi. Nhiều dữ liệu hơn, sửa nhanh hơn.
Thêm Badge Trạng Thái Vào README
GitHub tự động tạo badge trạng thái cho mọi workflow. Tìm nó trong tab Actions → workflow của bạn → menu ba chấm → Create status badge. Dán vào README của bạn:

Theo Dõi Số Phút Runner
Gói miễn phí cho 2.000 phút mỗi tháng cho repo riêng tư. Repo công khai có số phút không giới hạn. Nếu bạn đang tiêu tốn quota nhanh vì matrix build nặng, hai điều này sẽ giúp ích: cache tốt hơn, và bộ lọc paths: để các thay đổi docs không kích hoạt toàn bộ test:
on:
push:
paths:
- 'src/**'
- 'tests/**'
- 'requirements.txt'
# Thay đổi ở docs/ hoặc README.md sẽ không kích hoạt pipeline
GitHub Actions biến checklist deploy thủ công 15 bước thành chỉ một cái push. Đường cong học tập nhẹ nhàng hơn bạn nghĩ — một khi hiểu được cấu trúc YAML, phần còn lại sẽ tự nhiên theo sau. Pipeline nằm ngay trong repo cũng có nghĩa là chúng được quản lý phiên bản cùng với code. Bắt đầu với phần quick-start ở trên, rồi dần dần áp dụng các pattern nâng cao khi cần.

