GitHub-Actions深度实践
1. 核心概念
workflow (文件级)
└── job (并行/串行)
└── step (顺序执行)
└── action / run
触发器 → Jobs → Steps → 输出。每个 Job 是独立 runner 环境。
2. 完整前端 CI/CD 示例
name: CI/CD
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
NODE_VERSION: 20
REGISTRY: ghcr.io
IMAGE_NAME: $}} github.repository }}
jobs:
# === CI ===
lint-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: $}} env.NODE_VERSION }}
cache: npm
- run: npm ci
- run: npm run lint
- run: npm run test -- --coverage
- uses: actions/upload-artifact@v4
if: always()
with:
name: coverage
path: coverage/
build:
runs-on: ubuntu-latest
needs: lint-test
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: $}} env.NODE_VERSION }}
cache: npm
- run: npm ci
- run: npm run build
env:
NEXT_PUBLIC_API_URL: $}} vars.API_URL }}
- uses: actions/upload-artifact@v4
with:
name: dist
path: dist/
# === CD(只 main 分支)===
deploy:
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
runs-on: ubuntu-latest
needs: build
permissions:
contents: read
packages: write
environment:
name: production
url: https://app.example.com
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
with:
registry: $}} env.REGISTRY }}
username: $}} github.actor }}
password: $}} secrets.GITHUB_TOKEN }}
- uses: docker/metadata-action@v5
id: meta
with:
images: $}} env.REGISTRY }}/$}} env.IMAGE_NAME }}
tags: |
type=sha
type=raw,value=latest
- uses: docker/build-push-action@v6
with:
context: .
push: true
tags: $}} steps.meta.outputs.tags }}
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Deploy to K8s
run: |
echo "$}} secrets.KUBECONFIG }}" > kubeconfig
export KUBECONFIG=kubeconfig
kubectl set image deployment/frontend \
web=$}} env.REGISTRY }}/$}} env.IMAGE_NAME }}:sha-${GITHUB_SHA::7} \
-n frontend
kubectl rollout status deployment/frontend -n frontend --timeout=300s
3. 缓存策略
3.1 npm 缓存
- uses: actions/setup-node@v4
with:
cache: npm # 自动缓存 ~/.npm
或手动:
- uses: actions/cache@v4
with:
path: ~/.npm
key: $}} runner.os }}-npm-$}} hashFiles('**/package-lock.json') }}
restore-keys: $}} runner.os }}-npm-
3.2 Docker 层缓存
cache-from: type=gha
cache-to: type=gha,mode=max
type=gha 用 GitHub Actions 内置 cache(10GB 上限)。mode=max 缓存所有层。
3.3 构建产物缓存(Turborepo/Nx)
- uses: actions/cache@v4
with:
path: .turbo
key: turbo-$}} github.sha }}
restore-keys: turbo-
4. 矩阵构建
strategy:
matrix:
node-version: [18, 20, 22]
os: [ubuntu-latest, macos-latest]
fail-fast: false # 一个失败不中止其他
前端常用场景:多 Node 版本兼容测试。
5. 复用 workflow
# .github/workflows/reusable-build.yml
on:
workflow_call:
inputs:
node-version:
type: string
default: "20"
secrets:
NPM_TOKEN:
required: false
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: $}} inputs.node-version }}, cache: npm }
- run: npm ci
- run: npm run build
# 调用
jobs:
build:
uses: ./.github/workflows/reusable-build.yml
with:
node-version: "20"
6. Environments & 审批
jobs:
deploy-prod:
environment:
name: production # 在 GitHub Settings → Environments 配审批人
url: https://app.example.com
配置 required reviewers + 等待时间 + branch protection,实现手动审批发布。
7. 安全
7.1 最小权限
permissions:
contents: read # 只读代码
packages: write # 写镜像
# 不需要的不给
7.2 Secrets
$}} secrets.XXX }}:加密存储,日志自动掩码- 不要在
echo输出密钥 - 不要在 build-args 传密钥(会进镜像 history)
7.3 第三方 Action 锁定
# ✗ 不锁定,可能被投毒
uses: some-action@main
# ✓ 锁 hash
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
8. 常见反模式
- 不用缓存:每次 CI 装 node_modules 3 分钟
npm install而非npm ci:非锁文件安装,不可重现- 密钥用
echo调试:泄露 - push main 不加
needs:lint 没过就部署了 - 单 workflow 500 行:拆成 reusable
- Actions 不锁版本:上游 tag 被篡改投毒
- artifact 不设过期:占满存储配额
- self-hosted runner 不隔离:PR 可执行任意代码