GitHub Actions — Pipeline CI/CD tự động cho dự án thật sự
GitHub Actions — Pipeline CI/CD tự động cho dự án thật sự
Xưa mình cứ nghĩ deploy là việc "gõ lệnh ssh rồi copy code". Lên dự án thật sự, nhiều lần tay mồm hơn tay code: quên test, deploy nhầm nhánh, cache X chỗ không đâu. Cho tới khi chuyển hết sang GitHub Actions, mọi thứ thành một luồng tự động, ai push nhánh main là tự nó test + build + deploy, mình chỉ ngồi xem kết quả. Bài này mình ghi lại những thứ làm dự án CI/CD chạy ngon và đúng.
1. Workflow cơ bản — YAML là vua
Một workflow là file .github/workflows/deploy.yml. Phần quan trọng nhất là triggers (on) và jobs:
name: CI/CD
on:
push:
branches: [main]
pull_request:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.22'
- run: go test ./...
Chú ý là checkout@v4, setup-go@v5 — chỉ định version sha hoặc major, đừng dùng @main trên action bên ngoài, kẻo một hôm nó đổi behaviour là build chết bất ngờ.
2. Matrix build — chạy song song nhiều version
Muốn chắc app chạy trên nhiều version Go, Node... thì dùng strategy.matrix. GitHub tự đẻ ra N job song song từ một định nghĩa:
strategy:
matrix:
go: ['1.21', '1.22', '1.23']
steps:
- uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go }}
Chạy song song nghĩa là nhanh hơn, nhưng để ý free tier chỉ có 20 job đồng thời/account — project nhiều matrix quá mức là bị xếp hàng chặt.
3. Cache dependency — đừng để mỗi lần tải lại từ đầu
Dependency chậm nhất chỗ nào? Tải go mod hay npm install mỗi lần từ zero. Dùng action cache:
- uses: actions/cache@v4
with:
path: ~/.cache/go-build
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
hashFiles là chìa khoá: cache chỉ hợp lệ khi go.sum không đổi. Nhờ vậy giảm thời gian pipeline từ 5 phút xuống còn 40 giây — kinh nghiệm thật, không phải lý thuyết.
4. Secrets — đừng bao giờ hardcode
Cấu hình quan trọng nhất: không ghi credential thẳng vào YAML. Qua tab Settings → Secrets → Actions mà khai báo, rồi dùng ${{ secrets.X }}:
- name: Deploy
env:
SUPABASE_URL: ${{ secrets.SUPABASE_URL }}
SERVICE_KEY: ${{ secrets.SERVICE_ROLE_KEY }}
run: |
curl -X POST "$SUPABASE_URL/rest/v1/posts" \
-H "Authorization: Bearer $SERVICE_KEY" ...
GitHub tự mask value của secret trong log — không sợ lộ ra terminal. Nhớ để quyền tối thiểu: cho service role vào build là giết con gà lấy trứng.
5. Deploy tự động — production an toàn
Cuối cùng là nhánh deploy. Quy tắc mình áp dụng:
- Test xong mới build — job
testlà dependency của job deploy - Build image xong push lên registry rồi mới update container
- Không deploy khi test fail — GitHub tự chặn vì job deploy
needs: test
deploy:
needs: test
runs-on: ubuntu-latest
steps:
- run: ./deploy.sh # đọc env từ secrets
Kinh nghiệm dính đòn
- Checkout thiếu — action đầu tiên luôn phải
actions/checkout, không có thì chạy như mù. - Version action lỏng — dùng
@v4not@main. - Secrets vào log — logs là nơi dễ lộ nhất, test cẩn thận trước khi chạy thật.
- Cache key sai — cache vô dụng khi hash không khớp file dependencies.
CI/CD không phải phép màu, nó chỉ là kỷ luật đóng khung. Có pipeline tự động, mỗi lần push là mình biết liền code có vỡ không — không còn "nó chạy trên máy tui mà". Nếu project bạn còn đang dùng cách deploy tay, bắt đầu từ workflow 5 dòng test này là đủ thay đổi cuộc chơi. 🚀