持续集成与持续部署(CI/CD)是现代软件工程的基础设施。GitHub Actions作为与代码仓库深度集成的自动化平台,凭借其易用性和丰富的生态,已成为众多团队的首选。本文将从工作流设计原则出发,结合具体配置示例,分享GitHub Actions的最佳实践。
GitHub Actions工作流定义在.github/workflows/目录下的YAML文件中。以下是一个最基础的Python项目CI配置:
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.10', '3.11', '3.12']
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: $
- name: Cache dependencies
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: $-pip-$
restore-keys: |
$-pip-
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Run linter
run: flake8 src/ tests/
- name: Run tests
run: pytest tests/ --cov=src --cov-report=xml
- name: Upload coverage
uses: codecov/codecov-action@v4
with:
files: ./coverage.xml
关键设计要点:
main和develop分支的push以及针对main的PR时触发,避免所有分支的无关提交都消耗CI资源。actions/cache缓存pip依赖,显著缩短构建时间。安全是CI/CD设计的底线。GitHub Actions提供了精细的权限控制机制:
name: Secure Deploy
on:
push:
branches: [main]
permissions:
contents: read # 默认只读权限
id-token: write # 用于OIDC认证
jobs:
deploy:
runs-on: ubuntu-latest
environment: production # 关联受保护环境
steps:
- uses: actions/checkout@v4
- name: Configure AWS credentials via OIDC
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789:role/GitHubActionsRole
aws-region: ap-northeast-1
- name: Deploy to ECS
run: |
aws ecs update-service \
--cluster production \
--service api-service \
--force-new-deployment
安全最佳实践:
permissions,而非使用默认的write-all。environment: production可设置审批人和保护规则,防止未经审核的代码直接部署到生产环境。- name: Build Docker image
run: |
docker build \
--build-arg DATABASE_URL=$ \
-t myapp:$ .
当多个项目需要相同的构建逻辑时,可复用工作流(Reusable Workflows)能避免重复配置:
# .github/workflows/reusable-python-ci.yml
name: Reusable Python CI
on:
workflow_call:
inputs:
python-version:
required: true
type: string
run-integration-tests:
required: false
type: boolean
default: false
jobs:
quality-checks:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: $
- name: Install dependencies
run: pip install -r requirements.txt
- name: Lint
run: flake8 src/
- name: Unit tests
run: pytest tests/unit/
- name: Integration tests
if: $
run: pytest tests/integration/
env:
TEST_DATABASE_URL: $
调用方配置:
# .github/workflows/app-ci.yml
name: App CI
on: [push, pull_request]
jobs:
call-reusable-workflow:
uses: ./.github/workflows/reusable-python-ci.yml
with:
python-version: '3.11'
run-integration-tests: true
secrets: inherit
对于更细粒度的复用,可以创建Composite Action:
# .github/actions/setup-project/action.yml
name: 'Setup Project'
description: 'Install dependencies and configure environment'
inputs:
node-version:
description: 'Node.js version'
required: true
default: '20'
runs:
using: 'composite'
steps:
- uses: actions/setup-node@v4
with:
node-version: $
cache: 'npm'
- name: Install dependencies
shell: bash
run: npm ci
- name: Generate types from OpenAPI
shell: bash
run: npm run generate-types
CI时间直接影响开发效率,以下是几个优化策略:
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npm run lint
unit-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npm run test:unit
integration-test:
runs-on: ubuntu-latest
needs: unit-test # 单元测试通过后才运行集成测试
services:
postgres:
image: postgres:15
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@v4
- run: npm ci
- run: npm run test:integration
env:
DATABASE_URL: postgres://postgres:postgres@localhost:5432/test
lint和unit-test并行执行,integration-test依赖unit-test的结果,同时启动PostgreSQL服务容器。
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: myapp:$
cache-from: type=gha
cache-to: type=gha,mode=max
使用GitHub Actions缓存后端(type=gha)缓存Docker构建层,避免每次从零构建。
以下是一个从代码提交到生产部署的完整流水线:
# .github/workflows/pipeline.yml
name: Full Pipeline
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
REGISTRY: ghcr.io
IMAGE_NAME: $
jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build test image
uses: docker/build-push-action@v5
with:
context: .
target: test
load: true
tags: test-image
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Run tests in container
run: docker run --rm test-image pytest
- name: Build production image
uses: docker/build-push-action@v5
with:
context: .
push: $
tags: $/$:$
cache-from: type=gha
deploy-staging:
needs: build-and-test
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
environment: staging
steps:
- name: Deploy to staging
run: |
echo "Deploying $ to staging"
# 调用部署脚本或API
deploy-production:
needs: deploy-staging
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
environment: production
steps:
- name: Deploy to production
run: |
echo "Deploying $ to production"
# 执行蓝绿部署或滚动更新
对应的多阶段Dockerfile:
# Dockerfile
FROM python:3.11-slim as base
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
FROM base as test
COPY . .
CMD ["pytest"]
FROM base as production
COPY src/ ./src/
USER nobody
CMD ["python", "-m", "src.main"]
CI/CD流水线本身也需要监控。当构建失败时,及时通知团队:
- name: Notify Slack on failure
if: failure()
uses: slackapi/slack-github-action@v1
with:
payload: |
{
"text": "构建失败",
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*项目*: $\n*分支*: $\n*提交*: $\n*作者*: $"
}
},
{
"type": "actions",
"elements": [
{
"type": "button",
"text": {"type": "plain_text", "text": "查看详情"},
"url": "$/$/actions/runs/$"
}
]
}
]
}
env:
SLACK_WEBHOOK_URL: $
设计良好的CI/CD流水线应当具备以下特征:快速反馈、安全可靠、易于维护、清晰可观测。GitHub Actions提供了丰富的原语来实现这些目标,关键在于根据团队规模和项目特点,选择合适的抽象层级,避免过度工程化。建议从简单配置开始,随着需求增长逐步引入矩阵构建、复用工作流、环境审批等高级特性。