GitHub Actions是GitHub内置的CI/CD工具,配置简单、与GitHub生态深度集成。对于托管在GitHub上的项目,基本上是CI/CD的首选方案。这篇文章介绍Actions的核心概念和常见配置模式。
基本概念
GitHub Actions的几个核心概念:
- Workflow(工作流):一个自动化流程,定义在
.github/workflows/目录下的YAML文件中 - Event(事件):触发workflow的条件,比如push、pull_request、定时等
- Job(作业):workflow中的一组步骤,运行在同一个runner上
- Step(步骤):job中的单个任务,可以执行命令或调用action
- Action(动作):可复用的步骤单元,社区有大量现成的action可用
第一个Workflow
在项目根目录创建.github/workflows/ci.yml:
name: CI
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '16'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
- name: Build
run: npm run build
推送到GitHub后,每次push到main/develop分支或者提PR到main时,这个workflow就会自动运行。
触发事件
常用的触发事件:
on:
# 代码推送
push:
branches: [ main ]
tags: [ 'v*' ] # tag推送时触发
paths:
- 'src/**' # 只有src目录变更才触发
- '!src/**/*.md' # 排除md文件
# Pull Request
pull_request:
types: [ opened, synchronize, reopened ]
# 定时任务(cron语法)
schedule:
- cron: '0 2 * * 1' # 每周一凌晨2点
# 手动触发
workflow_dispatch:
inputs:
environment:
description: 'Deploy environment'
required: true
default: 'staging'
type: choice
options:
- staging
- production
Job配置
多Job并行
默认情况下,多个job是并行执行的:
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- run: npm ci
- run: npm run lint
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- run: npm ci
- run: npm test
build:
needs: [lint, test] # 等lint和test都通过后再build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- run: npm ci
- run: npm run build
矩阵策略
同时在多个环境/版本上测试:
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [14, 16, 18]
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
- run: npm test
这个配置会生成 3x3=9 个job并行跑。
环境变量和Secrets
jobs:
deploy:
runs-on: ubuntu-latest
env:
NODE_ENV: production
steps:
- name: Deploy
env:
DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
SERVER_HOST: ${{ secrets.SERVER_HOST }}
run: |
echo "Deploying to $SERVER_HOST"
# 使用ssh部署等操作
Secrets在GitHub仓库的Settings > Secrets中配置,日志中会自动打码。
常用Actions
社区有大量现成的action,不用重复造轮子:
# 缓存依赖,加速构建
- uses: actions/cache@v3
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
# Docker构建并推送
- uses: docker/build-push-action@v4
with:
push: true
tags: myapp:latest
# 发送通知
- uses: slackapi/slack-github-action@v1
with:
payload: |
{"text": "Deployment succeeded!"}
实际案例:前端项目CI/CD
一个比较完整的前端项目配置:
name: Frontend CI/CD
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
ci:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- run: npm ci
- run: npm run lint
- run: npm test -- --coverage
- run: npm run build
- name: Upload coverage
if: github.event_name == 'push'
uses: codecov/codecov-action@v3
- name: Upload build artifacts
if: github.ref == 'refs/heads/main'
uses: actions/upload-artifact@v3
with:
name: dist
path: dist/
deploy:
needs: ci
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
runs-on: ubuntu-latest
steps:
- uses: actions/download-artifact@v3
with:
name: dist
path: dist/
- name: Deploy to server
uses: appleboy/scp-action@v0.1.4
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
source: "dist/*"
target: "/var/www/app"
小结
GitHub Actions的优势在于跟GitHub无缝集成,社区action生态丰富。配置上就是YAML文件,理解了event、job、step这几个概念,基本上就能覆盖大部分CI/CD需求。比起自建Jenkins,省心不少。