GitHub Actions CI/CD: Xây dựng, Kiểm thử và Triển khai Workflow từ Đầu
Tìm hiểu cách thiết lập GitHub Actions cho tích hợp liên tục và triển khai liên tục. Bao gồm triggers, jobs, matrices, secrets, caching, Docker và các ví dụ workflow thực tế.
GitHub Actions biến mỗi lần push, pull request và merge thành một pipeline tự động — chạy kiểm thử, build artifacts, quét lỗ hổng bảo mật và triển khai lên môi trường production. Đây là nền tảng CI/CD tích hợp ngay trong repository của bạn, không cần quản lý bất kỳ cơ sở hạ tầng nào.
GitHub Actions hoạt động như thế nào
Mỗi workflow là một file YAML nằm trong .github/workflows/. Khi một sự kiện trigger được kích hoạt, GitHub khởi động một máy ảo mới, chạy các jobs của bạn và báo cáo kết quả — tất cả chỉ trong vài giây.
Push to main
↓
Workflow triggered
↓
Job: Build & Test (ubuntu-latest)
├── Step 1: Checkout code
├── Step 2: Install Node.js
├── Step 3: npm ci
├── Step 4: npm test
└── Step 5: npm run build
↓
✅ All checks passed
Workflow đầu tiên của bạn
Tạo file .github/workflows/ci.yml:
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- run: npm ci
- run: npm test
- run: npm run build
Vậy là xong. Mỗi lần push lên main và mỗi PR sẽ tự động chạy bộ kiểm thử của bạn.
Triggers: khi nào workflow chạy
Sự kiện liên quan đến code
on:
push:
branches: [main, develop]
paths: ['src/**', 'package.json'] # Chỉ chạy khi những file này thay đổi
pull_request:
types: [opened, synchronize]
Lịch định kỳ (cron)
on:
schedule:
- cron: '0 6 * * 1' # Mỗi thứ Hai lúc 6:00 UTC
Kích hoạt thủ công
on:
workflow_dispatch:
inputs:
environment:
description: 'Deploy target'
required: true
type: choice
options: [staging, production]
Tính năng này thêm nút "Run workflow" vào giao diện GitHub, nơi bạn có thể chọn các tham số.
Reusable workflows
on:
workflow_call:
inputs:
node-version:
type: string
default: '20'
Gọi nó từ workflow khác bằng uses: ./.github/workflows/reusable.yml.
Jobs và steps
Các jobs chạy song song
Mặc định các jobs chạy song song với nhau:
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm run lint
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm test
build:
runs-on: ubuntu-latest
needs: [lint, test] # Chờ cả hai hoàn thành
steps:
- uses: actions/checkout@v4
- run: npm run build
Matrix strategy — kiểm thử trên nhiều phiên bản
Chạy cùng một job trên nhiều cấu hình khác nhau:
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18, 20, 22]
os: [ubuntu-latest, windows-latest]
fail-fast: false
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
- run: npm test
Cấu hình này tạo ra 6 jobs chạy song song (3 phiên bản × 2 hệ điều hành).
Secrets và biến môi trường
Sử dụng secrets
Lưu trữ các giá trị nhạy cảm trong Settings → Secrets and variables → Actions:
steps:
- name: Deploy
env:
API_KEY: ${{ secrets.API_KEY }}
DATABASE_URL: ${{ secrets.DATABASE_URL }}
run: ./deploy.sh
Secrets được ẩn trong logs và không bao giờ bị lộ ra với các fork.
Biến môi trường
# Cấp độ workflow
env:
NODE_ENV: production
jobs:
build:
# Cấp độ job
env:
CI: true
steps:
- name: Build
# Cấp độ step
env:
VITE_API_URL: https://api.example.com
run: npm run build
Caching để tăng tốc độ build
Nếu không có caching, mỗi lần chạy sẽ tải lại toàn bộ dependencies từ đầu. Caching giúp giảm thời gian build từ 50-80%:
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm # Caching npm tích hợp sẵn
# Hoặc caching thủ công cho các công cụ khác
- uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-
Artifacts: chia sẻ dữ liệu giữa các jobs
Upload kết quả build từ một job và download ở job khác:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm run build
- uses: actions/upload-artifact@v4
with:
name: dist
path: dist/
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/download-artifact@v4
with:
name: dist
- run: ./deploy.sh
Ví dụ workflow thực tế
Build và push Docker
name: Docker
on:
push:
tags: ['v*']
permissions:
packages: write
jobs:
docker:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/build-push-action@v5
with:
push: true
tags: ghcr.io/${{ github.repository }}:${{ github.ref_name }}
cache-from: type=gha
cache-to: type=gha,mode=max
Triển khai lên Cloudflare Pages
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- run: npm ci && npm run build
- uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
command: pages deploy dist --project-name=my-site
Release kèm changelog
name: Release
on:
push:
tags: ['v*.*.*']
permissions:
contents: write
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Generate changelog
run: |
git log $(git describe --tags --abbrev=0 HEAD^)..HEAD \
--pretty=format:"- %s" > CHANGELOG.md
- uses: softprops/action-gh-release@v2
with:
body_path: CHANGELOG.md
generate_release_notes: true
Thực thi có điều kiện
Kiểm soát thời điểm các steps và jobs được chạy:
steps:
- name: Deploy to production
if: github.ref == 'refs/heads/main'
run: ./deploy-prod.sh
- name: Deploy to staging
if: github.event_name == 'pull_request'
run: ./deploy-staging.sh
- name: Notify on failure
if: failure()
run: curl -X POST ${{ secrets.SLACK_WEBHOOK }} -d '{"text":"Build failed!"}'
Các biện pháp bảo mật tốt nhất
1. Ghim phiên bản action theo SHA
# ❌ Tag có thể thay đổi — có thể bị xâm phạm
- uses: actions/checkout@v4
# ✅ Ghim vào SHA commit chính xác
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
2. Sử dụng quyền tối thiểu cần thiết
permissions:
contents: read # Chỉ những gì cần thiết
packages: write
3. Không bao giờ in secrets ra màn hình
# ❌ KHÔNG BAO GIỜ làm điều này
- run: echo ${{ secrets.API_KEY }}
# ✅ Sử dụng biến môi trường
- env:
API_KEY: ${{ secrets.API_KEY }}
run: ./script-that-uses-api-key.sh
4. Giới hạn quyền cho PR từ fork
on:
pull_request_target: # Chạy trong ngữ cảnh của branch gốc
types: [opened, synchronize]
Gỡ lỗi workflow thất bại
- Xem logs — Nhấp vào bất kỳ step nào bị lỗi để xem toàn bộ output
- Bật debug logging — Đặt secret
ACTIONS_STEP_DEBUGthànhtrue - Dùng
actở máy local — Chạy workflows trên máy của bạn với nektos/act - SSH vào runner — Dùng
mxschmitt/action-tmateđể debug tương tác
Xây dựng workflow bằng giao diện trực quan
Không muốn tự viết YAML? Hãy dùng GitHub Actions Generator của chúng tôi để xây dựng workflow bằng giao diện trực quan với các template cho Node.js, Python, Docker, triển khai và nhiều hơn nữa — sau đó tải về file YAML sẵn sàng cho môi trường production.
Tổng kết
GitHub Actions mang đến cho bạn CI/CD tích hợp ngay trong repository:
- Bắt đầu đơn giản — Một file workflow với build + test
- Thêm caching — Giảm thời gian build với
actions/cachehoặc caching ngôn ngữ tích hợp sẵn - Dùng matrix — Kiểm thử trên nhiều phiên bản và hệ điều hành
- Bảo vệ secrets — Không bao giờ hardcode, luôn dùng encrypted secrets
- Tự động hóa mọi thứ — Releases, triển khai, quét bảo mật, tác vụ định kỳ
Pipeline CI/CD tốt nhất là pipeline chạy trên mỗi commit mà bạn không cần phải nghĩ đến. Thiết lập một lần, và để GitHub lo phần còn lại.