CI CD là gì mà dev nào cũng nói “phải có CI/CD”, nhưng nhiều team nhỏ vẫn deploy bằng FTP hoặc SSH copy file? Thực tế, CI/CD không phải thứ phức tạp chỉ dành cho Big Tech. Với GitHub Actions — hoàn toàn miễn phí cho repo private — bạn có thể setup CI/CD pipeline hoàn chỉnh trong 1 giờ. Bài viết này hướng dẫn từ A-Z cho đội dev 2-10 người.
CI/CD là gì? Giải thích 60 giây
CI — Continuous Integration
Mỗi khi developer push code mới → hệ thống TỰ ĐỘNG:
- Pull code mới nhất
- Build ứng dụng
- Chạy tests (unit test, integration test)
- Kiểm tra code quality
- Thông báo kết quả: PASS hoặc FAIL
Không có CI: Dev push code → không ai biết code có lỗi không → merge vào main → deploy → SẬP.
Có CI: Dev push code → 5 phút sau biết ngay code lỗi hay không → fix trước khi merge.
CD — Continuous Delivery / Deployment
Sau khi CI pass → hệ thống TỰ ĐỘNG:
- Build production version
- Deploy lên staging server (test)
- (Optional) Deploy lên production sau khi approve
Không có CD: Code pass CI → dev/admin SSH vào server → pull code → restart app → cầu nguyện.
Có CD: Code pass CI → tự động deploy → 10 phút sau user đã dùng feature mới.
Toàn bộ flow CI/CD
Dev push code → Build → Test → Code Quality → Deploy Staging → Review → Deploy Production
(1 phút) (2 phút) (3 phút) (1 phút) (2 phút) (human) (2 phút)
Tổng: ~11 phút từ code → production (thay vì 2-3 ngày thủ công)
Tại sao GitHub Actions?
So sánh CI/CD tools
| Tool | Miễn phí | Self-hosted | Dễ dùng | Phổ biến |
|---|---|---|---|---|
| GitHub Actions | 2,000 phút/tháng | Không cần | Dễ nhất | Rất cao |
| GitLab CI | 400 phút/tháng | Có | Trung bình | Cao |
| Jenkins | Open-source | Cần server | Khó | Cao (cũ) |
| CircleCI | 6,000 phút/tháng | Không | Dễ | Trung bình |
| Vercel / Netlify | Unlimited (static) | Không | Rất dễ | Cao (frontend) |
Tại sao chọn GitHub Actions?
- Miễn phí: 2,000 phút/tháng cho private repo — đủ cho team 5-10 devs
- Tích hợp sẵn: Code trên GitHub → CI/CD trên GitHub, không cần tool bên ngoài
- Marketplace: 20,000+ actions có sẵn, không cần viết từ đầu
- Dễ setup: File YAML đơn giản, copy-paste template là chạy
- Phổ biến: Rất nhiều tutorial, community lớn
Free tier đủ dùng không?
| Team size | Deploys/ngày | Phút ước tính/tháng | Free tier (2,000 phút) |
|---|---|---|---|
| 2 devs | 3-5 | 300-500 | Dư |
| 5 devs | 8-15 | 600-1,200 | Đủ |
| 10 devs | 15-30 | 1,200-2,000 | Vừa đủ |
Setup GitHub Actions từ A-Z
Bước 1: Tạo workflow file (5 phút)
Trong repo GitHub, tạo file .github/workflows/ci.yml:
name: CI/CD Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- run: npm test
- run: npm run build
Giải thích:
on: push→ Chạy mỗi khi push coderuns-on: ubuntu-latest→ Chạy trên server Ubuntu (miễn phí)npm ci→ Cài dependenciesnpm test→ Chạy testsnpm run build→ Build ứng dụng
Bước 2: Thêm deployment (10 phút)
Thêm job deploy sau job test:
deploy-staging:
needs: test
if: github.ref == 'refs/heads/develop'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci && npm run build
- name: Deploy to staging
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.STAGING_HOST }}
username: ${{ secrets.STAGING_USER }}
key: ${{ secrets.STAGING_SSH_KEY }}
script: |
cd /var/www/staging
git pull origin develop
npm ci --production
pm2 restart app
deploy-production:
needs: test
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci && npm run build
- name: Deploy to production
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.PROD_HOST }}
username: ${{ secrets.PROD_USER }}
key: ${{ secrets.PROD_SSH_KEY }}
script: |
cd /var/www/production
git pull origin main
npm ci --production
pm2 restart app
Bước 3: Cấu hình Secrets (5 phút)
- Vào GitHub repo → Settings → Secrets and variables → Actions
- Thêm secrets:
STAGING_HOST: IP server stagingSTAGING_USER: SSH usernameSTAGING_SSH_KEY: SSH private key- (Tương tự cho production)
Bước 4: Thêm notification (5 phút)
Thông báo kết quả qua Slack hoặc email:
notify:
needs: [test, deploy-production]
if: always()
runs-on: ubuntu-latest
steps:
- uses: 8398a7/action-slack@v3
with:
status: ${{ job.status }}
text: 'Deploy ${{ github.sha }} - ${{ job.status }}'
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}
Workflow Templates cho các dự án phổ biến
Lead Magnet: Tải miễn phí GitHub Actions workflow templates cho web/app — 8 templates sẵn dùng cho React, Node.js, Python, Docker, WordPress.
Template 1: React/Next.js Website
name: React CI/CD
on:
push:
branches: [main]
jobs:
build-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: '20' }
- run: npm ci
- run: npm run lint
- run: npm test -- --coverage
- run: npm run build
- name: Deploy to Vercel
uses: amondnet/vercel-action@v25
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }}
vercel-org-id: ${{ secrets.ORG_ID }}
vercel-project-id: ${{ secrets.PROJECT_ID }}
vercel-args: '--prod'
Template 2: Node.js API + Docker
name: API CI/CD
on:
push:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:15
env:
POSTGRES_PASSWORD: test
ports: ['5432:5432']
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: '20' }
- run: npm ci
- run: npm test
env:
DATABASE_URL: postgresql://postgres:test@localhost:5432/test
deploy:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build & Push Docker image
run: |
docker build -t myapp:${{ github.sha }} .
docker tag myapp:${{ github.sha }} registry/myapp:latest
docker push registry/myapp:latest
Template 3: Python/Django
name: Django CI/CD
on:
push:
branches: [main, develop]
jobs:
test:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:15
env:
POSTGRES_PASSWORD: test
ports: ['5432:5432']
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with: { python-version: '3.12' }
- run: pip install -r requirements.txt
- run: python manage.py test
- run: flake8 .
Best Practices cho team nhỏ
1. Branch Strategy đơn giản
main (production) ← develop (staging) ← feature/xxx (dev)
- Dev tạo branch feature/xxx từ develop
- Viết code → push → CI tự chạy test
- Tạo Pull Request → teammate review → merge vào develop
- Develop auto deploy lên staging
- Test OK → merge develop vào main → auto deploy production
2. Không skip tests
Quy tắc tuyệt đối: Không merge nếu CI fail. Bật “branch protection rules” trên GitHub:
- Require CI pass trước khi merge
- Require 1 code review approval
- Không cho push trực tiếp vào main
3. Keep pipeline fast (< 10 phút)
Pipeline chậm = dev không kiên nhẫn chờ = skip CI. Target: toàn bộ pipeline < 10 phút.
| Bước | Target time |
|---|---|
| Install dependencies | < 1 phút (cache) |
| Lint + Type check | < 1 phút |
| Unit tests | < 3 phút |
| Build | < 2 phút |
| Deploy | < 2 phút |
| Tổng | < 10 phút |
4. Cache dependencies
- uses: actions/cache@v4
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
Giảm thời gian install từ 2 phút → 10 giây.
5. Environment variables cho mỗi môi trường
| Variable | Staging | Production |
|---|---|---|
| DATABASE_URL | staging-db | prod-db |
| API_KEY | test-key | prod-key |
| LOG_LEVEL | debug | error |
| SENTRY_DSN | staging-dsn | prod-dsn |
Lưu trong GitHub Secrets, không hard-code trong code.
Những lỗi phổ biến khi setup CI/CD
Lỗi 1: Secret bị leak
Không push file .env, API keys vào git. Dùng GitHub Secrets cho mọi sensitive data.
Lỗi 2: Pipeline quá phức tạp
Team 3 devs không cần Kubernetes, multi-stage deployment, canary release. Giữ đơn giản: test → build → deploy.
Lỗi 3: Không có rollback plan
Deploy lỗi → phải rollback nhanh. Cách đơn giản: deploy lại commit trước đó. Cách tốt hơn: blue-green deployment.
Lỗi 4: Bỏ qua staging
Deploy thẳng production = liều mạng. Luôn deploy staging trước, test OK rồi mới production.
Lỗi 5: Không monitor sau deploy
Deploy xong phải check: app có chạy không? Error rate có tăng không? Response time có bình thường không?
So sánh: Trước và sau CI/CD
| Chỉ số | Trước (thủ công) | Sau (CI/CD) |
|---|---|---|
| Deploy frequency | 1-2 lần/tháng | 5+ lần/ngày |
| Thời gian deploy | 2-4 giờ | 10 phút |
| Deploy lỗi | 30% | < 5% |
| Thời gian fix | 2-8 giờ | 10-30 phút (rollback) |
| Dev thức đêm | Thường xuyên | Không bao giờ |
| Code review | Tùy hứng | Bắt buộc |
| Test coverage | 0% | 60-80% |
Trinh Digital CI/CD Setup
Tại Trinh Digital, chúng tôi giúp team dev:
- CI/CD Setup — Thiết lập pipeline hoàn chỉnh trong 1-2 ngày
- DevOps Consulting — Tư vấn workflow phù hợp team size
- Training — Đào tạo dev team sử dụng GitHub Actions
- Managed DevOps — Quản trị CI/CD, monitoring hàng tháng
FAQ — Câu hỏi thường gặp
1. Team 2 người có cần CI/CD không?
Có. Thậm chí 1 developer cũng nên có CI/CD cơ bản: auto test + auto deploy. Mất 1 giờ setup, tiết kiệm hàng chục giờ mỗi tháng. Quan trọng hơn: tránh deploy lỗi lên production.
2. GitHub Actions free tier có đủ không?
2,000 phút/tháng đủ cho team 5-8 devs với 10-15 deploys/ngày. Nếu vượt: GitHub Teams $4/dev/tháng với 3,000 phút. Rất rẻ so với giá trị mang lại.
3. Dự án PHP/WordPress có dùng được không?
Được. GitHub Actions hỗ trợ mọi ngôn ngữ. WordPress: auto deploy qua SSH/rsync. PHP: auto test với PHPUnit, deploy với Deployer.
4. CI/CD có thay thế QA/tester không?
Không hoàn toàn. CI/CD chạy automated tests — phát hiện lỗi kỹ thuật. QA/tester kiểm tra UX, business logic, edge cases mà automated test khó cover.
5. Setup CI/CD mất bao lâu?
Basic (test + deploy): 1-2 giờ. Intermediate (test + staging + production + notification): 1 ngày. Advanced (Docker + security scan + performance test): 2-3 ngày.
Muốn setup CI/CD cho team dev? Liên hệ Trinh Digital để nhận GitHub Actions workflow templates miễn phí và hỗ trợ setup.