使用GitHub Actions实现DeOldify模型的CI/CD:自动测试与镜像构建
使用GitHub Actions实现DeOldify模型的CI/CD:自动测试与镜像构建
最近在折腾一个老照片上色的项目,用的是DeOldify这个模型。项目本身挺有意思,但每次更新代码、测试模型效果、再打包成Docker镜像,这一套流程下来,手动操作不仅繁琐,还容易出错。团队里有人改了代码忘了跑测试,或者打包的镜像版本对不上,都是常有的事。
后来我们决定,得把这一套流程自动化起来。正好GitHub Actions用起来挺方便,就在上面搭了一套CI/CD流水线。现在只要代码一提交,自动就跑测试;打个标签,自动就构建镜像推送到仓库。整个过程清晰透明,省心不少。今天就来聊聊我们是怎么做的,如果你也在做类似的项目,或许能给你一些参考。
1. 为什么DeOldify项目需要CI/CD?
你可能用过DeOldify,它是一个基于深度学习的老照片、老视频上色工具,效果挺惊艳的。但把它用起来,尤其是在团队协作或者想要提供稳定服务的时候,就会遇到一些工程上的麻烦。
首先,这个项目依赖不算少,环境配置起来需要点耐心。不同人电脑上的环境稍有差异,可能我这儿跑得好好的,你那儿就报错了。其次,模型本身有一些测试用例,比如检查颜色渲染是否自然、边界处理是否得当。这些测试如果全靠人工来跑,效率低不说,还容易遗漏。
更关键的是部署。我们最终是要把模型封装成Docker镜像,提供API服务。手动构建镜像、打标签、上传,步骤多,容易手滑。比如忘了更新镜像版本号,导致线上服务还是旧的代码,这就出问题了。
所以,引入CI/CD(持续集成/持续部署)就是为了解决这些痛点:让机器代替人工,去完成那些重复、易错的工作,保证每次代码变更都是可验证、可追溯、可自动部署的。
2. 设计我们的自动化流水线
在动手写代码之前,我们先想清楚这个流水线应该帮我们做什么。核心目标有三个:
- 保证代码质量:每次提交代码,自动运行测试,确保新改动不会破坏原有功能。
- 自动化构建与发布:当我们需要发布新版本时,通过一个简单的动作(比如打一个Git标签),就能自动打包出Docker镜像,并推送到镜像仓库。
- 生成部署文档:自动生成或更新相关的部署说明,比如镜像的拉取命令、版本信息等。
基于GitHub Actions,我们设计了两个主要的工作流(Workflow):
- CI流水线(持续集成):监听每一次代码推送(比如推送到main分支),触发单元测试和模型精度测试。
- CD流水线(持续部署):监听特定的Git标签推送事件(比如
v1.0.0),触发Docker镜像的构建和推送。
下面这张图概括了整个流程:
graph TD A[开发者提交代码到GitHub] --> B{触发事件类型?}; B -- 推送到主分支 --> C[CI流水线: 运行测试]; C --> D[测试结果反馈]; B -- 推送版本标签 --> E[CD流水线: 构建镜像]; E --> F[推送镜像到仓库]; F --> G[生成部署文档]; D --> H[流程结束]; G --> H;接下来,我们看看具体怎么实现。
3. 搭建CI流水线:自动运行测试
我们的测试主要分两类:一类是传统的单元测试,检查工具函数、数据处理逻辑对不对;另一类是针对模型的“精度”测试,虽然不完全是严格的数值精度,更多的是检查模型加载、预处理、推理的基本流程是否通畅,输出是否合理。
我们在项目根目录下的.github/workflows文件夹里,创建了一个叫run-tests.yml的文件。
name: Run Tests on Push on: push: branches: [ main, develop ] pull_request: branches: [ main ] jobs: test: runs-on: ubuntu-latest steps: - name: Checkout Code uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: python-version: '3.9' - name: Install Dependencies run: | pip install --upgrade pip pip install -r requirements.txt # 安装测试相关的额外包 pip install pytest pytest-cov - name: Run Unit Tests run: | pytest tests/unit/ -v --cov=deoldify --cov-report=xml - name: Run Model Sanity Tests run: | python tests/model_sanity_test.py env: # 假设测试需要一个小型测试模型文件 TEST_MODEL_PATH: ./test_models/artistic_model.pth这个配置文件做了几件事:
- 触发条件:当代码推送到
main或develop分支,或者向main分支发起拉取请求时,这个工作流就会启动。 - 准备环境:它会在GitHub提供的最新版Ubuntu系统上,拉取我们的代码,安装指定版本的Python和项目依赖。
- 执行测试:
Run Unit Tests:使用pytest运行tests/unit/目录下的所有单元测试,并生成测试覆盖率报告。Run Model Sanity Tests:运行一个我们写的模型完整性测试脚本。这个脚本会尝试加载模型,用一张小的测试图片跑一遍上色流程,确保核心推理链路没有崩溃,输出图片的格式、尺寸是符合预期的。
这样,每次团队成员提交代码,都能立刻看到测试是否通过。如果测试失败了,GitHub会发出通知,我们就能第一时间定位问题,而不是等到要打包发布的时候才发现。
4. 搭建CD流水线:自动构建与推送镜像
当测试都通过,我们觉得代码可以发布一个新版本了,CD流水线就该上场了。我们约定,给代码库打上一个类似v1.2.3的标签,就代表要发布。
我们在.github/workflows目录下创建另一个文件build-and-push.yml。
name: Build and Push Docker Image on: push: tags: - 'v*' # 匹配所有以v开头的标签,如 v1.0, v1.0.1 jobs: build-and-push: runs-on: ubuntu-latest permissions: contents: read packages: write steps: - name: Checkout Code uses: actions/checkout@v4 - name: Extract Metadata for Docker id: meta uses: docker/metadata-action@v5 with: images: | your-docker-registry/username/deoldify tags: | type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} type=ref,event=tag - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Log in to Container Registry uses: docker/login-action@v3 with: registry: your-docker-registry.com # 例如 ghcr.io, docker.io username: ${{ secrets.REGISTRY_USERNAME }} password: ${{ secrets.REGISTRY_TOKEN }} - name: Build and Push Docker Image uses: docker/build-push-action@v5 with: context: . file: ./Dockerfile push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} cache-from: type=gha cache-to: type=gha,mode=max - name: Generate Deployment Doc run: | IMAGE_TAGS="${{ steps.meta.outputs.tags }}" echo "## 最新镜像版本" >> DEPLOYMENT.md echo "以下镜像已自动构建并推送至仓库:" >> DEPLOYMENT.md echo "\`\`\`bash" >> DEPLOYMENT.md for TAG in $(echo $IMAGE_TAGS | tr ',' '\n'); do echo "docker pull $TAG" >> DEPLOYMENT.md done echo "\`\`\`" >> DEPLOYMENT.md echo "" >> DEPLOYMENT.md echo "**构建时间:** $(date)" >> DEPLOYMENT.md echo "**Git 标签:** ${{ github.ref_name }}" >> DEPLOYMENT.md echo "**提交哈希:** ${{ github.sha }}" >> DEPLOYMENT.md - name: Commit and Push Deployment Doc uses: stefanzweifel/git-auto-commit-action@v5 with: file_pattern: DEPLOYMENT.md commit_message: "docs: update deployment info for ${{ github.ref_name }}"这个流程稍微复杂点,我解释一下关键步骤:
- 触发条件:只有推送了符合
v*模式的标签时才会运行。 - 镜像元数据:使用
docker/metadata-action自动根据Git标签生成Docker镜像的标签。比如打了标签v1.2.3,它会生成your-registry/deoldify:1.2.3、:1.2和:latest(如果是最新)等多个标签,方便不同场景下拉取。 - 登录与构建:使用存储在GitHub Secrets中的凭证登录到你的Docker镜像仓库(如Docker Hub、GitHub Container Registry等),然后使用Buildx构建镜像并推送。这里还配置了缓存,能加速后续的构建过程。
- 生成部署文档:这一步非常实用。流水线会自动生成或更新一个
DEPLOYMENT.md文件,里面包含了刚刚构建的镜像的完整拉取命令、构建时间、对应的Git版本信息。任何人需要部署时,看这个文件就一目了然。 - 提交文档:最后,自动将更新后的部署文档提交回代码仓库,确保文档与版本同步。
注意:你需要提前在GitHub仓库的Settings -> Secrets and variables -> Actions里配置REGISTRY_USERNAME和REGISTRY_TOKEN,这是安全登录镜像仓库所必需的。
5. 实际效果与经验分享
这套流水线跑起来以后,最直接的感受就是“省心”和“靠谱”。
以前发布一个版本,需要我手动做一系列操作:跑测试脚本、构建Docker镜像、打标签、推送、再写更新日志。现在,我只需要专注写代码,然后打一个Git标签,剩下的全部交给GitHub Actions。大概几分钟后,镜像就已经在仓库里了,DEPLOYMENT.md文件也更新好了。团队其他成员看到新标签,就知道可以去拉取新镜像了。
在实践过程中,我们也积累了一些小经验:
- 测试要快且稳定:CI流水线里的测试不能太耗时,否则会影响开发反馈速度。我们的模型完整性测试用的是特别小的测试图片和简化的流程,只做最基本的冒烟测试,保证核心流程不挂。
- 善用缓存:Docker构建和Python依赖安装都比较耗时。我们按照上面配置了Buildx的缓存,以及可以使用
actions/cache来缓存Python的pip包,能显著缩短流水线运行时间。 - 部署文档是宝藏:自动生成的
DEPLOYMENT.md成了我们团队内部的部署标准参考。运维同事再也不用跑来问“这次更新用哪个镜像标签”了。 - 分支策略:我们通常会在
develop分支进行功能开发和CI测试,main分支用于稳定版本的发布和CD构建。通过PR(Pull Request)来合并代码,确保每次合并前CI都是通过的。
6. 总结
给DeOldify这类AI模型项目配上CI/CD,听起来好像是大工程的专属,但其实用GitHub Actions来实现,门槛并不高。核心思路就是把那些重复性的、容易出错的步骤,用配置文件描述出来,让自动化工具去执行。
这么做的好处是实实在在的。代码质量有了自动化的守护,发布流程变得规范且可追溯,团队协作起来摩擦也少了。更重要的是,它把开发者从繁琐的运维操作中解放出来,能更专注于模型效果的优化和业务逻辑的开发。
如果你正在管理一个类似的开源项目或者团队内的AI服务,强烈建议花点时间把自动化流水线搭起来。一开始可能会觉得有点麻烦,但一旦跑通,你会发现它带来的效率和可靠性提升,绝对是值得的。从最简单的“提交代码自动跑测试”开始,逐步完善,你的项目也会显得更专业、更可靠。
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。
