# Tham Khảo Nhanh GitHub Actions

*Workflows, triggers, jobs, secrets, caching, artifacts*

> Source: GitHub Actions Documentation (docs.github.com/actions) · MIT

## Cơ Bản Về Workflow

### Workflow Tối Giản

```
# .github/workflows/ci.yml
name: CI
on: push
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: echo "Hello from CI"
```

### Khái Niệm Chính

| Command | Description |
|---------|-------------|
| `Workflow` | File YAML trong `.github/workflows/` định nghĩa tự động hóa |
| `Event` | Trigger khởi động workflow (push, PR, schedule, v.v.) |
| `Job` | Tập hợp các bước chạy trên cùng một runner |
| `Step` | Tác vụ riêng lẻ — chạy lệnh hoặc dùng action |
| `Runner` | VM thực thi jobs (`ubuntu-latest`, `macos-latest`, `windows-latest`) |
| `Action` | Đơn vị code tái sử dụng được tham chiếu bằng `uses:` |

## Triggers

### Sự Kiện Phổ Biến

```
on:
  push:
    branches: [main]
  pull_request:
    branches: [main]
  schedule:
    - cron: "0 6 * * 1"    # every Monday 6 AM UTC
  workflow_dispatch:          # manual trigger
```

### Bộ Lọc Sự Kiện

| Command | Description |
|---------|-------------|
| `branches:` | Trigger chỉ cho branch cụ thể |
| `paths:` | Trigger chỉ khi file khớp thay đổi |
| `tags:` | Trigger khi push tag (`v*`) |
| `types: [opened, synchronize]` | Lọc loại hoạt động PR |
| `branches-ignore:` | Loại trừ branch cụ thể |
| `paths-ignore:` | Loại trừ đường dẫn file cụ thể |

## Jobs & Steps

### Cấu Hình Job

```
jobs:
  test:
    runs-on: ubuntu-latest
    needs: build            # depends on build job
    if: github.ref == 'refs/heads/main'
    timeout-minutes: 10
    steps:
      - uses: actions/checkout@v4
      - run: npm test
```

### Loại Step

| Command | Description |
|---------|-------------|
| `run:` | Thực thi lệnh shell |
| `uses:` | Dùng action đã publish |
| `with:` | Truyền input cho action |
| `name:` | Tên hiển thị trong UI |
| `id:` | Tham chiếu output step qua `steps.<id>.outputs` |
| `if:` | Thực thi có điều kiện |
| `continue-on-error: true` | Không fail job nếu step thất bại |

## Actions

### Sử Dụng Actions

```
steps:
  - uses: actions/checkout@v4
  - uses: actions/setup-node@v4
    with:
      node-version: 20
  - uses: ./.github/actions/my-action  # local action
```

### Actions Phổ Biến

| Command | Description |
|---------|-------------|
| `actions/checkout@v4` | Checkout code repository |
| `actions/setup-node@v4` | Cài đặt Node.js |
| `actions/setup-python@v5` | Cài đặt Python |
| `actions/upload-artifact@v4` | Tải lên build artifacts |
| `actions/download-artifact@v4` | Tải xuống artifacts từ job khác |
| `actions/cache@v4` | Cache dependencies giữa các lần chạy |
| `actions/github-script@v7` | Chạy JS với client GitHub API |

## Biến Môi Trường

### Thiết Lập Biến

```
env:                          # workflow-level
  NODE_ENV: production
jobs:
  build:
    env:                      # job-level
      CI: true
    steps:
      - run: echo "$MY_VAR"
        env:                  # step-level
          MY_VAR: hello
```

### Biến Mặc Định

| Command | Description |
|---------|-------------|
| `github.sha` | SHA commit kích hoạt workflow |
| `github.ref` | Ref branch hoặc tag (`refs/heads/main`) |
| `github.repository` | Tên owner/repo |
| `github.actor` | Người dùng kích hoạt workflow |
| `github.event_name` | Sự kiện kích hoạt workflow |
| `runner.os` | OS của runner (`Linux`, `macOS`, `Windows`) |

## Secrets

### Sử Dụng Secrets

```
steps:
  - run: deploy --token "$TOKEN"
    env:
      TOKEN: ${{ secrets.DEPLOY_TOKEN }}
  - uses: some/action@v1
    with:
      api-key: ${{ secrets.API_KEY }}
```

### Quy Tắc Secret

| Command | Description |
|---------|-------------|
| `secrets.GITHUB_TOKEN` | Token tự động tạo có phạm vi repo |
| `Settings → Secrets` | Thêm secrets trong cài đặt repo hoặc org |
| `Masking` | Giá trị secret tự động che trong log |
| `Environment secrets` | Giới hạn trong môi trường deployment |
| `Org secrets` | Chia sẻ giữa các repo trong tổ chức |

## Chiến Lược Matrix

### Matrix Builds

```
jobs:
  test:
    strategy:
      matrix:
        os: [ubuntu-latest, macos-latest]
        node: [18, 20]
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node }}
```

### Tùy Chọn Matrix

| Command | Description |
|---------|-------------|
| `matrix:` | Định nghĩa các tổ hợp biến để mở rộng |
| `include:` | Thêm tổ hợp ngoài vào matrix |
| `exclude:` | Loại bỏ tổ hợp cụ thể |
| `fail-fast: false` | Tiếp tục job khác nếu một job thất bại |
| `max-parallel: 2` | Giới hạn số matrix job chạy đồng thời |

## Caching

### Cache Dependencies

```
- uses: actions/cache@v4
  with:
    path: ~/.npm
    key: npm-${{ hashFiles('package-lock.json') }}
    restore-keys: npm-
```

### Cache Tích Hợp Sẵn

```
- uses: actions/setup-node@v4
  with:
    node-version: 20
    cache: npm            # auto-cache for npm/yarn/pnpm
- uses: actions/setup-python@v5
  with:
    python-version: "3.12"
    cache: pip            # auto-cache for pip
```

## Artifacts

### Tải Lên & Tải Xuống

```
- uses: actions/upload-artifact@v4
  with:
    name: build-output
    path: dist/
    retention-days: 7
- uses: actions/download-artifact@v4
  with:
    name: build-output
```

### Lưu Ý Về Artifacts

| Command | Description |
|---------|-------------|
| `retention-days` | Tự động xóa sau N ngày (mặc định 90) |
| `path` | File hoặc thư mục cần tải lên (hỗ trợ glob) |
| `Cross-job` | Tải lên ở một job, tải xuống ở job khác với `needs:` |
| `compression-level` | 0 (không nén) đến 9 (nén tối đa), mặc định 6 |

## Mẫu Phổ Biến

### Triển Khai Có Điều Kiện

```
- name: Deploy to production
  if: github.ref == 'refs/heads/main'
  run: ./deploy.sh
- name: Post PR comment
  if: github.event_name == 'pull_request'
  run: gh pr comment $PR --body "Build passed"
```

### Biểu Thức Hữu Ích

| Command | Description |
|---------|-------------|
| `success()` | True nếu tất cả bước trước thành công |
| `failure()` | True nếu bất kỳ bước nào thất bại |
| `always()` | Chạy bất kể trạng thái (dọn dẹp) |
| `cancelled()` | True nếu workflow bị hủy |
| `contains(github.ref, 'release')` | Kiểm tra chuỗi có chứa |
| `startsWith(github.ref, 'refs/tags')` | Kiểm tra tiền tố chuỗi |
| `hashFiles('**/lock*')` | SHA-256 của file (cho cache key) |
