前言
GitHub Actions 是 GitHub 提供的持续集成和持续部署(CI/CD)平台,允许开发者在代码仓库中直接定义自动化工作流。自 2018 年推出以来,GitHub Actions 已经成为最受欢迎的 CI/CD 工具之一。本文将详细介绍 GitHub Actions 的核心概念、workflow 结构、触发事件、矩阵构建、缓存策略以及自动化部署实践。
1. GitHub Actions 基础概念
1.1 核心概念
| 概念 | 说明 |
|---|---|
| Workflow | 自动化的完整流程,由一个或多个 job 组成 |
| Job | 一组 step 的集合,在同一个 runner 上执行 |
| Step | 一个 job 中的最小执行单元,可以是 shell 命令或 action |
| Action | 可复用的命令集合,类似函数 |
| Runner | 执行 workflow 的服务器(GitHub 托管或自托管) |
| Event | 触发 workflow 的事件(如 push、pull_request) |
1.2 为什么选择 GitHub Actions
| 特性 | GitHub Actions | Jenkins | GitLab CI |
|---|---|---|---|
| 集成度 | 原生 GitHub 集成 | 需要插件 | GitLab 原生 |
| 配置方式 | YAML in 仓库 | Web UI + 插件 | YAML in 仓库 |
| 学习曲线 | 低 | 高 | 中 |
| 价格(公开仓库) | 免费 | 免费 | 免费 |
| 价格(私有仓库) | 免费额度 + 按量 | 自托管免费 | 按订阅 |
2. Workflow 文件结构
2.1 基本结构
GitHub Actions workflow 文件存放在仓库的 .github/workflows/ 目录下,使用 YAML 格式。
# .github/workflows/ci.yml
name: CI Pipeline # workflow 名称
on: # 触发事件
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
jobs: # 定义任务
build:
runs-on: ubuntu-latest # 运行环境
steps: # 步骤
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
- name: Install dependencies
run: npm install
- name: Run tests
run: npm test2.2 文件命名规则
- 文件名:
*.yml或*.yaml - 建议:使用描述性名称,如
ci.yml、deploy.yml、release.yml - 一个仓库可以有多个 workflow 文件
3. 触发事件(on)
3.1 常见触发事件
on:
# 代码推送
push:
branches:
- main
- 'releases/**' # 支持 glob 模式
# 拉取请求
pull_request:
branches:
- main
# 定时触发(cron)
schedule:
- cron: '0 0 * * *' # 每天 UTC 0 点
# 手动触发
workflow_dispatch:
inputs:
environment:
description: '部署环境'
required: true
default: 'staging'
type: choice
options:
- staging
- production
# 外部事件(repository_dispatch)
repository_dispatch:
types: [deploy-trigger]3.2 事件过滤
on:
push:
branches:
- main
paths:
- 'src/**'
- 'package.json'
- '.github/workflows/**'
paths-ignore:
- 'docs/**'
- '*.md'3.3 推送到特定标签
on:
push:
tags:
- 'v*' # 匹配 v1.0、v2.1.3 等4. Jobs 详解
4.1 单 Job 配置
jobs:
build:
name: Build and Test
runs-on: ubuntu-latest
timeout-minutes: 30 # 超时时间
continue-on-error: false # 出错是否继续
steps:
- name: Step 1
run: echo "Hello"4.2 多 Job 并行
jobs:
test:
runs-on: ubuntu-latest
steps:
- run: npm test
build:
runs-on: ubuntu-latest
steps:
- run: npm run build
lint:
runs-on: ubuntu-latest
steps:
- run: npm run lint默认情况下,所有 job 并行执行。
4.3 Job 依赖(needs)
jobs:
test:
runs-on: ubuntu-latest
steps:
- run: npm test
build:
runs-on: ubuntu-latest
needs: test # 等待 test job 完成
steps:
- run: npm run build
deploy:
runs-on: ubuntu-latest
needs: [test, build] # 等待多个 job
steps:
- run: npm run deploy5. Runner 环境
5.1 GitHub 托管 Runner
| Runner | 说明 | 适用场景 |
|---|---|---|
ubuntu-latest |
最新 Ubuntu | 通用 Linux 构建 |
ubuntu-22.04 |
Ubuntu 22.04 | 固定版本 |
windows-latest |
最新 Windows | .NET Framework 等 |
windows-2022 |
Windows Server 2022 | 固定版本 |
macos-latest |
最新 macOS | iOS/macOS 构建 |
macos-14 |
macOS 14 | 固定版本 |
5.2 自托管 Runner
runs-on: self-hosted # 使用自托管 runner
# 或指定标签
runs-on: [self-hosted, linux, x64]设置自托管 Runner:
- 进入仓库 → Settings → Actions → Runners
- 点击 "New self-hosted runner"
- 按照指引下载并配置
6. Steps 详解
6.1 使用 Action
steps:
# 使用 GitHub 官方 action
- name: Checkout
uses: actions/checkout@v4
# 使用社区 action(指定版本)
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
cache: 'npm'
# 使用 Docker 容器 action
- name: Run in Docker
uses: docker://alpine:latest6.2 执行 Shell 命令
steps:
- name: Run shell command
run: echo "Hello, World!"
# 多行命令
- name: Multi-line command
run: |
echo "Line 1"
echo "Line 2"
npm install
npm test
# 指定 shell
- name: PowerShell script
shell: pwsh
run: Write-Host "Hello from PowerShell"
# 工作目录
- name: Build in subdir
working-directory: ./src
run: npm run build6.3 环境变量
jobs:
build:
runs-on: ubuntu-latest
env:
NODE_ENV: production
API_KEY: ${{ secrets.API_KEY }} # 从 secrets 读取
steps:
- name: Print env
run: echo $NODE_ENV
env:
LOCAL_VAR: local_value # step 级别的环境变量7. 矩阵构建(Matrix Builds)
矩阵构建允许在多个配置组合上并行运行 job。
7.1 基础矩阵
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [14, 16, 18]
os: [ubuntu-latest, windows-latest]
include:
- os: macos-latest
node-version: 18
exclude:
- os: windows-latest
node-version: 14
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- name: Run tests
run: npm test上述配置会生成 5 个 job 组合:
- ubuntu-latest + Node 14
- ubuntu-latest + Node 16
- ubuntu-latest + Node 18
- windows-latest + Node 16
- windows-latest + Node 18
- macos-latest + Node 18
7.2 矩阵配置说明
| 关键字 | 说明 |
|---|---|
matrix |
定义矩阵变量 |
include |
添加额外的组合 |
exclude |
排除特定组合 |
fail-fast |
一个失败是否取消其他(默认 true) |
max-parallel |
最大并行数 |
8. 缓存策略
8.1 缓存依赖
steps:
- uses: actions/checkout@v4
- name: Cache node modules
uses: actions/cache@v3
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- name: Install dependencies
run: npm ci8.2 缓存策略说明
| 缓存目标 | 路径 | 键策略 |
|---|---|---|
| npm | ~/.npm |
hashFiles('**/package-lock.json') |
| yarn | ~/.cache/yarn |
hashFiles('**/yarn.lock') |
| pip | ~/.cache/pip |
hashFiles('**/requirements.txt') |
| Docker | /tmp/.buildx-cache |
hashFiles('**/Dockerfile') |
9. Artifacts(构建产物)
9.1 上传 Artifacts
steps:
- name: Build
run: npm run build
- name: Upload artifacts
uses: actions/upload-artifact@v3
with:
name: build-output
path: dist/
retention-days: 7 # 保留天数(默认 90)9.2 下载 Artifacts
steps:
- name: Download artifacts
uses: actions/download-artifact@v3
with:
name: build-output
path: dist/10. Secrets 管理
10.1 设置 Secrets
- 进入仓库 → Settings → Secrets and variables → Actions
- 点击 "New repository secret"
- 输入名称和值
10.2 使用 Secrets
steps:
- name: Deploy to server
run: |
echo "Deploying with API key: ${{ secrets.API_KEY }}"
curl -H "Authorization: Bearer ${{ secrets.API_KEY }}" ...10.3 环境变量与 Secrets 的区别
| 特性 | env | secrets |
|---|---|---|
| 可见性 | 日志中可见 | 自动脱敏 |
| 适用场景 | 普通配置 | 密码、Token |
| 加密存储 | 否 | 是 |
11. 自动化部署实践
11.1 部署到服务器(SSH)
name: Deploy to Server
on:
push:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Deploy via SSH
uses: appleboy/ssh-action@v1.0.0
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
cd /var/www/app
git pull origin main
docker-compose restart11.2 部署到 Docker Hub
name: Build and Push Docker Image
on:
push:
tags: [ 'v*' ]
jobs:
docker:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- 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: myapp:latest,myapp:${{ github.ref_name }}11.3 部署到 Kubernetes
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup kubectl
uses: azure/setup-kubectl@v3
with:
version: 'latest'
- name: Configure kubeconfig
run: |
echo "${{ secrets.KUBE_CONFIG }}" > ~/.kube/config
chmod 600 ~/.kube/config
- name: Deploy to K8s
run: |
kubectl set image deployment/myapp myapp=myapp:${{ github.sha }}
kubectl rollout status deployment/myapp12. 实战完整示例
12.1 Node.js 项目 CI/CD
# .github/workflows/ci-cd.yml
name: CI/CD Pipeline
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
env:
NODE_VERSION: '18'
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16, 18, 20]
steps:
- uses: actions/checkout@v4
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run linter
run: npm run lint
- name: Run tests
run: npm test
- name: Upload coverage
uses: actions/upload-artifact@v3
if: matrix.node-version == 18
with:
name: coverage
path: coverage/
build:
needs: test
runs-on: ubuntu-latest
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: Upload build artifacts
uses: actions/upload-artifact@v3
with:
name: build
path: dist/
deploy:
needs: build
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
environment: production
steps:
- name: Download build artifacts
uses: actions/download-artifact@v3
with:
name: build
path: dist/
- name: Deploy to production
uses: appleboy/ssh-action@v1.0.0
with:
host: ${{ secrets.PROD_HOST }}
username: ${{ secrets.PROD_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
cd /var/www/app
# 部署逻辑
systemctl restart myapp13. 常见问题排查
13.1 Workflow 不触发
# 检查项:
1. workflow 文件是否在 .github/workflows/ 目录下
2. 文件名是否以 .yml 或 .yaml 结尾
3. YAML 语法是否正确(可用 yamllint 检查)
4. on 触发条件是否匹配当前事件13.2 依赖下载慢
# 使用镜像加速
steps:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
registry-url: 'https://registry.npmmirror.com'13.3 权限错误
# 某些操作需要设置权限
permissions:
contents: read
packages: write14. 最佳实践
- 使用具体版本:
actions/checkout@v4而非actions/checkout@main - 合理使用缓存:加速依赖安装
- 分离 job:测试、构建、部署分离,提高并行度
- 保护 secrets:不在日志中输出敏感信息
- 使用矩阵构建:一次测试多个版本
- 设置超时:避免 job 无限运行
- 使用 environment:生产部署增加审批流程
environment:
name: production
url: https://prod.example.com15. 总结
GitHub Actions 是一个功能强大且易用的 CI/CD 平台。本文详细介绍了:
- 核心概念:workflow、job、step、action
- 触发事件:push、pull_request、schedule、workflow_dispatch
- 矩阵构建:多版本、多环境并行测试
- 缓存策略:加速依赖安装
- 自动化部署:SSH、Docker、Kubernetes 部署示例
- 最佳实践:安全性、性能优化、可维护性
下一步:
- 为你的项目创建第一个 workflow
- 探索 GitHub Marketplace 的 action
- 结合项目需求定制 CI/CD 流程