第39章:CI/CD流程
39.1 CI/CD概述
持续集成(CI)和持续部署(CD)是现代软件开发的重要实践,它们通过自动化构建、测试和部署流程,提高了软件开发的效率和质量。剪映小助手采用GitHub Actions作为CI/CD平台,实现了完整的自动化流程。
39.2 GitHub Actions工作流架构
39.2.1 工作流文件结构
剪映小助手的CI/CD流程通过两个主要的工作流文件实现:
- dev.yml:开发环境工作流,处理main分支的push和pull_request事件
- release.yml:发布环境工作流,处理版本tag的推送事件
39.2.2 开发环境工作流(dev.yml)
开发环境工作流主要负责代码的持续集成和开发环境的部署:
yaml
name: Docker Image CI Dev
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v3
with:
version: "0.4.0"
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install dependencies
run: |
uv sync
uv add --dev pytest pytest-html pytest-json-report
- name: List directory structure
run: ls -R
- name: Prepare production files
run: |
mkdir -p dist
cp -r src dist/
cp pyproject.toml dist/
cp main.py dist/
cp -r tests dist/
cp requirements*.txt dist/ 2>/dev/null || true
cp .env.example dist/ 2>/dev/null || true
ls -la dist/
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Docker Hub
if: github.event_name != 'pull_request'
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: gogoshine/capcut-mate
tags: |
type=ref,event=branch
type=ref,event=pr
type=sha,prefix={{branch}}-
type=raw,value=latest,enable={{is_default_branch}}
- name: Validate tag format
run: |
echo "Tags to be applied: ${{ steps.meta.outputs.tags }}"
echo "Labels to be applied: ${{ steps.meta.outputs.labels }}"
# 验证标签格式
for tag in ${{ steps.meta.outputs.tags }}; do
echo "Validating tag: $tag"
if [[ ! "$tag" =~ ^[a-zA-Z0-9._-]+:[a-zA-Z0-9._-]+$ ]]; then
echo "Invalid tag format: $tag"
exit 1
fi
done
echo "All tags are valid"
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-from: type=gha,scope=dev
cache-to: type=gha,mode=max
39.2.3 发布环境工作流(release.yml)
发布环境工作流主要负责生产环境的构建和部署:
yaml
name: Docker Image CI
on:
push:
tags:
- 'v*'
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v3
with:
version: "0.4.0"
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install dependencies
run: |
uv sync
uv add --dev pytest pytest-html pytest-json-report
- name: Prepare production files
run: |
mkdir -p dist
cp -r src dist/
cp pyproject.toml dist/
cp main.py dist/
cp -r tests dist/
cp requirements*.txt dist/ 2>/dev/null || true
cp .env.example dist/ 2>/dev/null || true
ls -la dist/
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: gogoshine/capcut-mate
tags: |
type=ref,event=tag
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=raw,value=latest,enable={{is_default_branch}}
- name: Validate tag format
run: |
echo "Tags to be applied: ${{ steps.meta.outputs.tags }}"
echo "Labels to be applied: ${{ steps.meta.outputs.labels }}"
# 验证标签格式
for tag in ${{ steps.meta.outputs.tags }}; do
echo "Validating tag: $tag"
if [[ ! "$tag" =~ ^[a-zA-Z0-9._-]+:[a-zA-Z0-9._-]+$ ]]; then
echo "Invalid tag format: $tag"
exit 1
fi
done
echo "All tags are valid"
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
39.3 工作流详细解析
39.3.1 触发条件配置
开发环境触发条件
yaml
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
- push事件:当代码推送到main分支时触发
- pull_request事件:当向main分支发起拉取请求时触发
- 分支过滤:只监听main分支的变化
发布环境触发条件
yaml
on:
push:
tags:
- 'v*'
- tag事件:当推送以'v'开头的tag时触发
- 版本tag:通常用于版本发布,如v1.0.0、v2.1.0等
- 精确匹配:只监听符合特定模式的tag
39.3.2 环境准备阶段
代码检出
yaml
- name: Checkout code
uses: actions/checkout@v4
- 操作:检出当前触发工作流的代码
- 版本:使用v4版本的checkout动作
- 功能:获取完整的代码仓库,包括子模块
Python环境配置
yaml
- name: Install uv
uses: astral-sh/setup-uv@v3
with:
version: "0.4.0"
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- uv安装:安装指定版本的uv包管理器
- Python版本:使用Python 3.11版本
- 环境隔离:确保构建环境的独立性和一致性
依赖安装
yaml
- name: Install dependencies
run: |
uv sync
uv add --dev pytest pytest-html pytest-json-report
- 依赖同步:使用uv sync安装项目依赖
- 测试工具:安装pytest及其相关插件,为自动化测试做准备
- 开发依赖:--dev参数确保开发工具也被安装
39.3.3 生产文件准备
yaml
- name: Prepare production files
run: |
mkdir -p dist
cp -r src dist/
cp pyproject.toml dist/
cp main.py dist/
cp -r tests dist/
cp requirements*.txt dist/ 2>/dev/null || true
cp .env.example dist/ 2>/dev/null || true
ls -la dist/
文件准备过程:
- 创建dist目录:建立生产文件输出目录
- 复制源码:将src目录复制到dist
- 配置文件:复制pyproject.toml项目配置文件
- 主程序:复制main.py主程序文件
- 测试文件:复制tests目录,包含测试用例
- 依赖文件:尝试复制requirements文件(如果存在)
- 环境示例:复制.env.example环境变量示例文件
- 文件列表:显示dist目录的文件结构
39.3.4 Docker构建配置
Docker Buildx设置
yaml
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- Buildx功能:提供多平台构建能力
- 缓存支持:支持构建缓存,提高构建效率
- 版本:使用v3版本的setup-buildx-action
Docker Hub登录
yaml
- name: Log in to Docker Hub
if: github.event_name != 'pull_request'
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- 条件执行:只在非pull_request事件时执行登录
- 密钥管理:使用GitHub Secrets管理Docker Hub凭据
- 安全考虑:避免在PR构建中暴露登录信息
39.3.5 镜像标签管理
元数据提取
yaml
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: gogoshine/capcut-mate
tags: |
type=ref,event=branch
type=ref,event=pr
type=sha,prefix={{branch}}-
type=raw,value=latest,enable={{is_default_branch}}
开发环境标签策略:
- 分支标签:使用分支名作为标签
- PR标签:使用PR编号作为标签
- SHA标签:使用提交SHA的前缀
- 最新标签:为默认分支添加latest标签
发布环境标签策略:
yaml
tags: |
type=ref,event=tag
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=raw,value=latest,enable={{is_default_branch}}
- tag标签:使用完整的tag名称
- 版本标签:使用语义化版本号
- 主版本标签:使用主版本号
- 次版本标签:使用主版本.次版本格式
标签格式验证
yaml
- name: Validate tag format
run: |
echo "Tags to be applied: ${{ steps.meta.outputs.tags }}"
echo "Labels to be applied: ${{ steps.meta.outputs.labels }}"
# 验证标签格式
for tag in ${{ steps.meta.outputs.tags }}; do
echo "Validating tag: $tag"
if [[ ! "$tag" =~ ^[a-zA-Z0-9._-]+:[a-zA-Z0-9._-]+$ ]]; then
echo "Invalid tag format: $tag"
exit 1
fi
done
echo "All tags are valid"
- 格式验证:使用正则表达式验证标签格式
- 错误处理:发现无效标签时终止构建
- 输出信息:显示待应用的标签和标签信息
39.3.6 镜像构建与推送
yaml
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
构建参数说明:
- 构建上下文:使用当前目录作为构建上下文
- 推送条件:只在非PR事件时推送镜像
- 标签应用:应用提取的元数据标签
- 标签信息:应用提取的标签信息
- 构建缓存:使用GitHub Actions缓存
- 缓存模式:最大缓存模式,提高后续构建速度
39.4 自动化测试集成
39.4.1 测试框架配置
虽然工作流中安装了pytest,但可以在工作流中添加测试执行步骤:
yaml
- name: Run tests
run: |
uv run pytest tests/ -v --html=reports/test_report.html --json-report --json-report-file=reports/test_report.json
- name: Upload test results
uses: actions/upload-artifact@v4
if: always()
with:
name: test-results
path: reports/
39.4.2 测试报告生成
测试报告的配置:
- HTML报告:生成可视化的HTML测试报告
- JSON报告:生成结构化的JSON测试报告
- 详细输出:使用-v参数显示详细测试输出
- 结果上传:将测试报告作为构建产物上传
39.4.3 测试质量门禁
可以添加测试质量检查:
yaml
- name: Check test coverage
run: |
uv run pytest tests/ --cov=src --cov-report=html --cov-report=json
coverage_percentage=$(uv run coverage report --format=total | grep -o '[0-9]\+\.[0-9]\+' | head -1)
echo "Test coverage: ${coverage_percentage}%"
if (( $(echo "$coverage_percentage < 80" | bc -l) )); then
echo "Test coverage is below 80%"
exit 1
fi
39.5 环境配置管理
39.5.1 密钥管理
GitHub Secrets的配置:
- DOCKERHUB_USERNAME:Docker Hub用户名
- DOCKERHUB_TOKEN:Docker Hub访问令牌
- 配置位置:Settings -> Secrets and variables -> Actions
- 安全考虑:密钥值不会显示在日志中
39.5.2 环境变量配置
环境变量的使用:
yaml
env:
PYTHON_VERSION: '3.11'
UV_VERSION: '0.4.0'
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
39.5.3 条件执行
条件执行的使用:
yaml
- name: Deploy to production
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
run: |
echo "Deploying to production"
39.6 部署策略
39.6.1 蓝绿部署
蓝绿部署的实现思路:
- 准备两个相同的生产环境
- 新版本部署到绿色环境
- 验证绿色环境功能
- 切换流量到绿色环境
- 保留蓝色环境用于回滚
39.6.2 滚动部署
滚动部署的实现:
yaml
- name: Rolling deployment
run: |
# 逐步替换实例
docker service update --image gogoshine/capcut-mate:${{ github.sha }} capcut-service
39.6.3 金丝雀部署
金丝雀部署的步骤:
- 部署新版本到少量实例
- 监控新版本性能指标
- 逐步增加新版本实例
- 完全切换到新版本
39.7 监控与回滚
39.7.1 部署监控
部署监控的配置:
yaml
- name: Monitor deployment
run: |
# 检查服务健康状态
for i in {1..30}; do
if curl -f http://localhost:60000/health; then
echo "Service is healthy"
exit 0
fi
sleep 10
done
echo "Service health check failed"
exit 1
39.7.2 自动回滚
自动回滚机制:
yaml
- name: Rollback on failure
if: failure()
run: |
echo "Deployment failed, rolling back"
# 执行回滚操作
docker service rollback capcut-service
39.8 性能优化
39.8.1 构建缓存优化
缓存配置的最佳实践:
yaml
cache-from: |
type=gha
type=registry,ref=gogoshine/capcut-mate:buildcache
cache-to: type=gha,mode=max
39.8.2 并行执行
并行执行的配置:
yaml
strategy:
matrix:
python-version: ['3.10', '3.11', '3.12']
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.10', '3.11', '3.12']
steps:
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
39.8.3 构建时间优化
构建时间优化策略:
- 减少构建步骤:合并相关的构建步骤
- 使用缓存:充分利用各种缓存机制
- 优化镜像大小:使用更小的基础镜像
- 并行处理:尽可能并行执行独立的任务
39.9 安全考虑
39.9.1 密钥安全
密钥管理的最佳实践:
- 使用GitHub Secrets:不要在代码中硬编码密钥
- 定期轮换:定期更新访问密钥
- 最小权限:为密钥分配最小必要的权限
- 审计日志:监控密钥的使用情况
39.9.2 镜像安全
镜像安全检查:
yaml
- name: Security scan
uses: aquasecurity/trivy-action@master
with:
image-ref: 'gogoshine/capcut-mate:${{ github.sha }}'
format: 'sarif'
output: 'trivy-results.sarif'
39.9.3 代码安全
代码安全扫描:
yaml
- name: Code security scan
uses: github/super-linter@v4
env:
DEFAULT_BRANCH: main
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
39.10 CI/CD最佳实践
39.10.1 分支策略
推荐的分支策略:
- 主分支保护:main分支需要PR才能修改
- 功能分支:每个功能开发使用独立分支
- 发布分支:发布版本使用专门的发布分支
- 热修复分支:紧急修复使用hotfix分支
39.10.2 提交信息规范
提交信息格式:
type(scope): subject
body
footer
39.10.3 版本管理
版本管理策略:
- 语义化版本:使用语义化版本号(MAJOR.MINOR.PATCH)
- 自动版本:使用工具自动生成版本号
- 变更日志:维护详细的变更日志
- 发布说明:为每个版本编写发布说明
39.10.4 监控与告警
监控指标:
- 构建成功率:监控构建成功的比例
- 构建时间:监控构建耗时
- 部署频率:监控部署的频率
- 回滚次数:监控回滚的频率
通过合理的CI/CD流程设计和实施,剪映小助手实现了高效的自动化构建、测试和部署,大大提高了开发效率和软件质量。
附录
代码仓库地址:
- GitHub:
https://github.com/Hommy-master/capcut-mate - Gitee:
https://gitee.com/taohongmin-gitee/capcut-mate
接口文档地址:
- API文档地址:
https://docs.jcaigc.cn