CI/CD 流水线实战 - GitHub Actions 从入门到精通
CI/CD 怎么做?本文详解 GitHub Actions 和自动化部署实战。
折
折腾侠
2026/03/15 发布
9约 6 分钟489 字 / 1105 词00
CI/CD 流水线实战 - GitHub Actions 从入门到精通
CI/CD 怎么做?本文详解 GitHub Actions 和自动化部署实战。
📋 前言
CI/CD 是现代软件开发的标配。
CI/CD 是什么?
- CI(持续集成):代码频繁合并,自动构建测试
- CD(持续交付):自动部署到测试/生产环境
为什么需要 CI/CD?
- 快速反馈
- 减少人为错误
- 提高交付速度
- 保证代码质量
主流工具:
- GitHub Actions(推荐)
- Jenkins
- GitLab CI
- CircleCI
本文详解 GitHub Actions 实战。
🎯 GitHub Actions 基础
核心概念
| 概念 | 说明 |
|---|---|
| Workflow | 工作流,自动化流程 |
| Event | 触发事件(push、PR 等) |
| Job | 工作流中的任务 |
| Step | 任务中的步骤 |
| Action | 可重用的操作单元 |
基本结构
YAML
name: CI/CD Pipeline
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install dependencies
run: npm install
- name: Run tests
run: npm test
- name: Build
run: npm run build
🚀 快速开始
1. 创建 Workflow 文件
Bash
# 项目根目录创建
mkdir -p .github/workflows
touch .github/workflows/ci.yml
2. 编写 CI 配置
YAML
# .github/workflows/ci.yml
name: Node.js CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16, 18, 20]
steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
- name: Build
run: npm run build
3. 查看执行结果
GitHub 仓库 → Actions 标签页 → 查看运行记录
💡 实战场景
场景 1:Node.js 项目 CI/CD
YAML
name: Node.js Deploy
on:
push:
branches: [main]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
- name: Build
run: npm run build
- name: Deploy to Vercel
uses: amondnet/vercel-action@v20
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }}
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
vercel-args: '--prod'
场景 2:Docker 镜像构建
YAML
name: Docker Build
on:
push:
tags: ['v*']
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push
uses: docker/build-push-action@v4
with:
context: .
push: true
tags: |
${{ secrets.DOCKER_USERNAME }}/myapp:latest
${{ secrets.DOCKER_USERNAME }}/myapp:${{ github.ref_name }}
场景 3:多环境部署
YAML
name: Multi-Env Deploy
on:
push:
branches: [main, develop]
jobs:
deploy-staging:
if: github.ref == 'refs/heads/develop'
runs-on: ubuntu-latest
environment: staging
steps:
- uses: actions/checkout@v3
- name: Deploy to Staging
run: ./deploy.sh staging
env:
API_KEY: ${{ secrets.STAGING_API_KEY }}
deploy-production:
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/checkout@v3
- name: Deploy to Production
run: ./deploy.sh production
env:
API_KEY: ${{ secrets.PRODUCTION_API_KEY }}
场景 4:定时任务
YAML
name: Daily Backup
on:
schedule:
# 每天凌晨 2 点执行(UTC 时间)
- cron: '0 2 * * *'
workflow_dispatch: # 允许手动触发
jobs:
backup:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Run backup script
run: ./scripts/backup.sh
env:
DB_HOST: ${{ secrets.DB_HOST }}
DB_PASSWORD: ${{ secrets.DB_PASSWORD }}
- name: Upload backup to S3
uses: aws-actions/configure-aws-credentials@v2
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-east-1
- name: Upload to S3
run: aws s3 cp backup.sql s3://my-bucket/backups/
🔧 常用 Action
代码相关
YAML
# 检出代码
- uses: actions/checkout@v3
# 设置 Node.js
- uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
# 设置 Python
- uses: actions/setup-python@v4
with:
python-version: '3.11'
# 设置 Java
- uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '17'
测试相关
YAML
# 运行测试
- name: Run tests
run: npm test
# 代码覆盖率
- name: Upload coverage
uses: codecov/codecov-action@v3
with:
file: ./coverage/lcov.info
# 运行 E2E 测试
- name: Run E2E tests
uses: cypress-io/github-action@v5
部署相关
YAML
# 部署到 Vercel
- uses: amondnet/vercel-action@v20
# 部署到 Netlify
- uses: nwtgck/actions-netlify@v2
# 部署到 AWS
- uses: aws-actions/configure-aws-credentials@v2
# 部署到 Kubernetes
- uses: azure/k8s-deploy@v4
⚡ 高级特性
1. 缓存依赖
YAML
- name: Cache node modules
uses: actions/cache@v3
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
2. 矩阵构建
YAML
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [16, 18, 20]
steps:
- name: Test on ${{ matrix.os }} with Node.js ${{ matrix.node-version }}
run: npm test
3. 条件执行
YAML
# 只在 main 分支执行
if: github.ref == 'refs/heads/main'
# 只在 tag 推送时执行
if: startsWith(github.ref, 'refs/tags/')
# 跳过某些情况
if: ${{ !contains(github.event.head_commit.message, '[skip ci]') }}
4. 复用 Workflow
YAML
# .github/workflows/reusable.yml
name: Reusable Workflow
on:
workflow_call:
inputs:
environment:
required: true
type: string
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Deploy
run: ./deploy.sh ${{ inputs.environment }}
YAML
# 调用复用 Workflow
name: Main Workflow
on: push
jobs:
call-reusable:
uses: ./.github/workflows/reusable.yml
with:
environment: production
5. 自定义 Action
YAML
# action.yml
name: 'My Custom Action'
description: 'Does something useful'
inputs:
name:
description: 'Name to greet'
required: true
runs:
using: 'node16'
main: 'dist/index.js'
JavaScript
// index.js
const core = require('@actions/core');
const name = core.getInput('name');
core.setOutput('greeting', `Hello ${name}!`);
⚠️ 最佳实践
1. 安全管理
YAML
# ✅ 使用 Secrets
env:
API_KEY: ${{ secrets.API_KEY }}
# ❌ 不要硬编码密码
env:
API_KEY: my-secret-key # 错误!
2. 固定 Action 版本
YAML
# ✅ 固定版本
- uses: actions/checkout@v3.0.0
# ❌ 使用 latest 标签
- uses: actions/checkout@latest
3. 超时设置
YAML
jobs:
build:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Long running task
run: ./long-task.sh
4. 错误处理
YAML
steps:
- name: Try something
run: ./script.sh
continue-on-error: true
- name: Always run
run: echo "This always runs"
if: always()
- name: Run on failure
run: echo "Something failed"
if: failure()
5. 日志输出
YAML
- name: Debug info
run: |
echo "Node version: $(node -v)"
echo "NPM version: $(npm -v)"
echo "Working directory: $(pwd)"
🎯 完整示例
全栈应用 CI/CD
YAML
name: Full Stack CI/CD
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
NODE_VERSION: '18'
PYTHON_VERSION: '3.11'
jobs:
frontend-test:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./frontend
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
cache-dependency-path: frontend/package-lock.json
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
- name: Build
run: npm run build
- name: Upload build artifacts
uses: actions/upload-artifact@v3
with:
name: frontend-build
path: frontend/dist
backend-test:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./backend
services:
postgres:
image: postgres:14
env:
POSTGRES_PASSWORD: postgres
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
steps:
- uses: actions/checkout@v3
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Install dependencies
run: pip install -r requirements.txt
- name: Run tests
run: pytest
env:
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/test
deploy:
needs: [frontend-test, backend-test]
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v3
- name: Download frontend build
uses: actions/download-artifact@v3
with:
name: frontend-build
path: ./frontend/dist
- name: Deploy to production
run: ./deploy.sh
env:
DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
🎁 总结
核心概念:
✅ Workflow - 工作流配置
✅ Event - 触发条件
✅ Job - 工作任务
✅ Step - 执行步骤
✅ Action - 可复用操作
✅ Secret - 敏感信息
学习路径:
1. 理解基本概念
2. 编写简单 CI
3. 添加 CD 部署
4. 学习高级特性
5. 优化和定制
最后建议:
CI/CD 不是一蹴而就的。
从简单开始,逐步完善,持续优化。
你有什么 GitHub Actions 实战经验? 欢迎在评论区分享!👇