GitHub Actions CI/CD:让代码自动跑起来
·
本文是《Python工程化实践》专栏第十七章,讲解如何使用 GitHub Actions 实现 Python 项目的自动化测试、构建和部署。
1. 为什么需要 CI/CD
1.1 手动部署的痛苦
没有 CI/CD 之前:
# 每次发布都要手动执行一堆命令
git pull
pytest
docker build
docker push
docker pull 生产服务器
docker run
# 运气好,没问题
# 运气不好,凌晨两点修 bug
手动部署的问题:
- 容易忘记步骤
- 不同机器环境不一致
- 回滚困难
- 团队协作时谁都不敢部署
1.2 CI/CD 解决什么问题
CI = Continuous Integration(持续集成)
每次代码提交后自动运行测试,确保代码质量
CD = Continuous Deployment(持续部署)
测试通过后自动部署到服务器
代码提交 → 自动测试 → 自动构建 → 自动部署
↑ ↓
└────────── 出问题自动回滚 ←───────────┘
2. GitHub Actions 基础
2.1 核心概念
| 概念 | 说明 |
|---|---|
| Workflow(工作流) | 整个自动化流程,定义在 .github/workflows/ 目录 |
| Job(任务) | 一个 Workflow 包含多个 Job |
| Step(步骤) | 每个 Job 包含多个 Step |
| Action(动作) | Step 中的具体操作,可复用 |
| Runner | 执行 Job 的服务器 |
2.2 目录结构
myproject/
├── .github/
│ └── workflows/
│ ├── ci.yml # 持续集成
│ └── release.yml # 发布流程
├── app/
├── tests/
├── Dockerfile
└── requirements.txt
2.3 最小 workflow 示例
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- run: pip install -r requirements.txt
- run: pytest
3. 自动化测试
3.1 完整测试 workflow
name: CI
on:
push:
branches: [ main ]
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: 设置 Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: 'pip' # 自动缓存依赖
- name: 安装依赖
run: |
pip install -r requirements.txt
pip install pytest pytest-cov
- name: 运行测试
run: pytest --cov=app --cov-report=xml
- name: 上传覆盖率报告
uses: codecov/codecov-action@v4
with:
file: ./coverage.xml
3.2 多任务并行
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- run: pip install ruff
- run: ruff check .
type-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- run: pip install mypy
- run: mypy app
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- run: pip install -r requirements.txt
- run: pytest
3.3 任务依赖关系
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: pip install ruff
- run: ruff check .
test:
needs: lint # 等 lint 完成后才运行
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: pip install -r requirements.txt
- run: pytest
build:
needs: test # 等 test 完成后才运行
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: docker build -t myapp:${{ github.sha }} .
4. 自动发布
4.1 PyPI 自动发布
name: 发布到 PyPI
on:
release:
types: [published]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: 设置 Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: 安装构建工具
run: pip install build
- name: 构建包
run: python -m build
- name: 发布到 PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
获取 PyPI API Token:
- 登录 PyPI.org
- Account Settings → API tokens
- 创建 Token,复制到 GitHub 的 Secrets
4.2 Docker Hub 自动发布
name: 发布 Docker 镜像
on:
push:
tags:
- 'v*'
jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: 提取版本号
id: version
run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
- name: 登录 Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: 构建镜像
run: |
docker build \
--tag myapp:${{ env.VERSION }} \
--tag myapp:latest \
.
- name: 推送镜像
run: |
docker push myapp:${{ env.VERSION }}
docker push myapp:latest
5. 版本管理策略
5.1 语义化版本
主版本.次版本.修订号
1 . 2 . 3
| 变化 | 示例 | 说明 |
|---|---|---|
| 主版本 | 1.x.x → 2.0.0 | 不兼容的 API 变更 |
| 次版本 | 1.2.x → 1.3.0 | 新增功能(向后兼容) |
| 修订号 | 1.2.3 → 1.2.4 | Bug 修复 |
5.2 自动生成 Release
name: 创建 Release
on:
push:
tags:
- 'v*'
jobs:
create-release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: 提取版本号
id: version
run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
- name: 创建 Release
uses: softprops/action-gh-release@v1
with:
files: dist/* # 上传构建产物
generate_release_notes: true # 自动生成更新日志
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
5.3 CHANGELOG 自动生成
推荐使用 git-cliff 自动生成更新日志:
# 安装
- name: 安装 git-cliff
run: |
FILE=git-cliff-2.1.0-x86_64-unknown-linux-musl.tar.gz
wget https://github.com/orhun/git-cliff/releases/download/v2.1.0/$FILE
tar -xzf $FILE && sudo mv cliff /usr/local/bin/
# 生成 CHANGELOG
- name: 生成更新日志
run: git-cliff --output CHANGELOG.md
6. 秘密管理
6.1 GitHub Secrets
不要把敏感信息写进代码!
# 错误示例
env:
DATABASE_URL: postgres://user:password@host/db # ❌ 泄露!
# 正确示例
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }} # ✅ 从 Secrets 读取
6.2 添加 Secrets
- 进入 GitHub 仓库 → Settings → Secrets and variables → Actions
- 点击 “New repository secret”
- 填写 Name 和 Value
6.3 环境级别的 Secrets
jobs:
test:
runs-on: ubuntu-latest
environment: test # 使用 test 环境的 Secrets
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
deploy:
runs-on: ubuntu-latest
environment: production # 使用 production 环境的 Secrets
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
7. 缓存优化
7.1 pip 依赖缓存
- uses: actions/setup-python@v5
with:
python-version: '3.11'
cache: 'pip'
cache-dependency-path: requirements.txt
7.2 Docker 层缓存
- name: 构建镜像
uses: docker/build-push-action@v5
with:
cache-from: type=gha
cache-to: type=gha,mode=max
7.3 完整优化示例
name: CI
on:
push:
branches: [main]
jobs:
optimized-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: 设置 Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
cache: 'pip'
cache-dependency-path: requirements.txt
- name: 缓存 ruff
uses: actions/cache@v4
with:
path: ~/.cache/ruff
key: ruff-${{ hashFiles('requirements.txt') }}
- name: 安装依赖
run: pip install -r requirements.txt pytest
- name: lint
run: ruff check .
- name: 测试
run: pytest -v
8. 条件执行
8.1 根据分支条件触发
on:
push:
branches:
- main
- develop
pull_request:
branches: [main]
8.2 根据文件变化触发
on:
push:
paths:
- '**.py' # Python 文件变化才触发
- 'requirements.txt'
- '.github/workflows/**'
8.3 手动触发
on:
workflow_dispatch:
inputs:
environment:
description: '部署环境'
required: true
default: 'staging'
# 手动触发时使用输入参数
- name: 部署到 ${{ github.event.inputs.environment }}
run: deploy.sh ${{ github.event.inputs.environment }}
9. 常见问题
9.1 超时问题
jobs:
test:
timeout-minutes: 30 # 设置超时时间
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# ...
9.2 并发控制
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true # 取消正在运行的同名 workflow
9.3 自定义 Runner
如果 GitHub 提供的 Ubuntu/Windows/macOS 不够用,可以搭建自托管 Runner:
jobs:
test:
runs-on: self-hosted # 使用自托管 runner
labels:
- linux
- large
10. 完整示例
一个完整的 Python 项目的 CI/CD workflow:
name: Python CI/CD
on:
push:
branches: [main]
tags: ['v*']
pull_request:
branches: [main]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
cache: 'pip'
- run: pip install ruff
- run: ruff check .
test:
needs: lint
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.10', '3.11', '3.12']
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'
- run: pip install -r requirements.txt
- run: pytest --cov=app
build:
needs: test
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/v')
steps:
- uses: actions/checkout@v4
- name: 登录 Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: 构建并推送
run: |
docker build -t myapp:${{ github.sha }} .
docker tag myapp:${{ github.sha }} myapp:latest
docker push myapp:latest
11. 总结
这一章我们介绍了 GitHub Actions CI/CD 的核心要素:
- Workflow:定义自动化流程的 YAML 文件
- 自动化测试:push/PR 时自动运行测试,多版本并行
- 自动发布:发布时自动构建并推送到 PyPI/Docker Hub
- 版本管理:语义化版本 + 自动 Release
- 秘密管理:敏感信息存 Secrets,不写进代码
- 缓存优化:减少构建时间
- 条件执行:按需触发 workflow
GitHub Actions 让你的代码在每次提交后都经历完整的质量检查和部署流程,再也不用担心"在我的机器上能跑"的问题了。
预告:附录篇我们将整理 Python 工程化的工具速查清单,帮助大家快速检索常用命令和配置。
更多推荐


所有评论(0)