Python 项目的 CI 不仅是「跑测试」,而是「把代码质量关」。从依赖锁定到类型检查,从格式化到安全扫描——一个完善的 Python CI 流水线应该在代码合并前拦截 90% 以上的低级问题。本文用 GitHub Actions 搭建覆盖多版本 Python 的完整 CI,包括 Poetry 依赖管理、pytest 测试、coverage 门禁、Black/Flake8/mypy 质量检查和 PyPI 自动发布。
一、基础 CI 流水线:测试与检查
1.1 完整工作流
# .github/workflows/ci.yml
name: Python CI
on:
push:
branches: [main, master]
pull_request:
branches: [main, master]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.9", "3.10", "3.11", "3.12"]
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install Poetry
uses: snok/install-poetry@v1
with:
version: latest
virtualenvs-create: true
virtualenvs-in-project: true
- name: Cache dependencies
uses: actions/cache@v3
with:
path: .venv
key: venv-${{ runner.os }}-${{ matrix.python-version }}-${{ hashFiles('poetry.lock') }}
- name: Install dependencies
run: poetry install --no-interaction --no-root
- name: Run tests
run: poetry run pytest tests/ -v --cov=src --cov-report=xml --cov-report=term
- name: Upload coverage
uses: codecov/codecov-action@v3
with:
files: ./coverage.xml
fail_ci_if_error: true
1.2 关键要点
矩阵测试:确保代码在 Python 3.9-3.12 均通过
Poetry 缓存:.venv 目录缓存,复用依赖安装
覆盖率:--cov 生成 xml + terminal 报告
Codecov:上传覆盖率并设门禁(如 < 80% 失败)
二、代码质量检查:Black + Flake8 + mypy
2.1 工作流扩展
- name: Check formatting with Black
run: poetry run black --check src/ tests/
- name: Lint with Flake8
run: poetry run flake8 src/ tests/ --max-line-length=88 --extend-ignore=E203
- name: Type check with mypy
run: poetry run mypy src/
2.2 配置同步
# pyproject.toml
[tool.black]
line-length = 88
target-version = ['py39', 'py310', 'py311', 'py312']
[tool.flake8]
max-line-length = 88
extend-ignore = ["E203", "W503"]
[tool.mypy]
python_version = "3.11"
strict = true
warn_return_any = true
warn_unused_configs = true
2.3 提交前检查
# .pre-commit-config.yaml
repos:
- repo: https://github.com/psf/black
rev: 23.12.1
hooks:
- id: black
- repo: https://github.com/pycqa/flake8
rev: 6.1.0
hooks:
- id: flake8
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.7.1
hooks:
- id: mypy
三、安全扫描:Bandit + Safety
3.1 安全扫描工作流
- name: Security scan with Bandit
run: poetry run bandit -r src/ -f json -o bandit-report.json || true
- name: Check dependencies for known vulnerabilities
run: poetry run safety check
3.2 安全策略
Bandit:扫描代码中的安全问题(硬编码密码、SQL 注入模式等)
Safety:扫描依赖中的已知 CVE
# 生产建议:加入 CI 门禁,安全漏洞阻塞合并
四、发布到 PyPI
4.1 自动发布工作流
# .github/workflows/release.yml
name: Release to PyPI
on:
release:
types: [published]
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install Poetry
uses: snok/install-poetry@v1
- name: Configure PyPI token
run: poetry config pypi-token.pypi ${{ secrets.PYPI_TOKEN }}
- name: Build and publish
run: |
poetry build
poetry publish
4.2 版本管理
Poetry version bump:
poetry version patch # 1.0.0 → 1.0.1
poetry version minor # 1.0.0 → 1.1.0
poetry version major # 1.0.0 → 2.0.0
# GitHub Release 触发发布:
# 1) 本地 poetry version patch && git commit && git tag v1.0.1
# 2) git push && git push --tags
# 3) GitHub 上创建 Release → 触发 Actions 发布到 PyPI
五、性能与可靠性优化
5.1 缓存策略
依赖缓存:
- .venv 目录( Poetry 虚拟环境)
- pip 缓存(actions/setup-python 自带)
- pre-commit 缓存
缓存键设计:
key: venv-${{ runner.os }}-${{ matrix.python-version }}-${{ hashFiles('poetry.lock') }}
restore-keys: |
venv-${{ runner.os }}-${{ matrix.python-version }}-
5.2 失败处理
- name: Run tests
run: poetry run pytest tests/ -v
continue-on-error: ${{ matrix.python-version == '3.13-dev' }}
- name: Notify on failure
if: failure()
uses: slackapi/slack-github-action@v1
with:
payload: |
{"text": "CI failed on ${{ github.ref }}"}
六、多包 Monorepo 策略
6.1 项目结构
project/
packages/
core/
pyproject.toml
src/
api/
pyproject.toml
src/
cli/
pyproject.toml
src/
.github/workflows/ci.yml
6.2 矩阵构建
strategy:
matrix:
package: [core, api, cli]
python-version: ["3.10", "3.11"]
steps:
- uses: actions/checkout@v4
- name: Test ${{ matrix.package }}
working-directory: packages/${{ matrix.package }}
run: |
poetry install
poetry run pytest
七、CI 模板速查
# 最小可用 Python CI
name: CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install dependencies
run: |
pip install -r requirements.txt
- name: Run tests
run: pytest
总结
Python 项目的 GitHub Actions CI 核心 pipeline 是:检出代码 → 安装 Poetry → 缓存依赖 → 运行 pytest + coverage → Black 格式化检查 → Flake8 lint → mypy 类型检查 → Bandit/Safety 安全扫描 → 上传报告。矩阵测试覆盖 Python 3.9-3.12,确保兼容性。发布到 PyPI 通过 GitHub Release 触发自动化。Poetry 的锁文件 poetry.lock 比 requirements.txt 更可靠,缓存 .venv 让 CI 运行时间从 3 分钟降到 30 秒。代码质量工具在 CI 中设门禁,比 code review 更前置拦截问题。
延伸阅读:
- GitHub Actions Node.js CI — Node.js 项目 CI 对比
- GitHub Actions PR 自动化 — PR 标签与审查自动化
- Python 性能优化专题 — Python 性能进阶
- DevOps 专题 — CI/CD 通用原则
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。