[T.10] 团队项目:CI/CD实践
| 这个作业属于哪个课程 | 北航2026年春季软件工程 |
|---|---|
| 这个作业的要求在哪里 | [T.10] 实验课/团队项目:团队代码管理准备 |
| 我在这个课程的目标是 | 体验完整软件开发流程,交付一款真正解决科研阅读痛点的软件产品 |
| 这个作业在哪个具体方面帮助我实现目标 | CI/CD实践 |
选项选择及理由
方案 A(GitHub Actions)
打包
理由如下:
- 项目为前后端分离架构(Python 后端 + Vue/TypeScript 前端),GitHub Actions 支持多 Job 并行/串行、矩阵策略、环境隔离,可以很自然地为前后端分别编写独立的工作流,互不干扰
- 使用 GitHub 原生 CI/CD 服务,无需搭建额外的基础设施
- 团队已有在
dev分支上协作的习惯,将自动化放在dev分支的 push 和 PR 事件上,可以在代码集成阶段就获得快速反馈,而不会阻塞特性分支的随意提交 - 相比纯粹的代码检查或简单测试,打包能产出可部署的制品(后端 Docker 镜像、前端静态资源包)能为后续的自动化部署打下基础
配置文件脚本
位于 .github/workflows/ 下
后端 CI/CD (backend-cicd.yml)
name: Backend CI/CD
on:
push:
branches: [dev]
paths:
- 'src/backend/**'
pull_request:
branches: [dev]
paths:
- 'src/backend/**'
defaults:
run:
working-directory: src/backend
jobs:
lint-and-test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
cache: 'pip'
cache-dependency-path: src/backend/requirements.txt
- name: Install dependencies
run: |
pip install --upgrade pip
pip install -r requirements.txt
pip install flake8 pytest
- name: Lint with flake8
run: flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
- name: Run tests
run: pytest --maxfail=3 --disable-warnings -q
build-and-deploy:
needs: lint-and-test
if: github.event_name == 'push' && github.ref == 'refs/heads/dev'
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: src/backend
push: true
tags: |
ghcr.io/${{ github.repository }}/backend:dev
ghcr.io/${{ github.repository }}/backend:${{ github.sha }}
- name: Deploy to dev server via SSH
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.SERVER_IP }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
cd /opt/backend
docker compose pull backend
docker compose up -d backend
docker image prune -f
前端 CI/CD (frontend-cicd.yml)
name: Frontend CI/CD
on:
push:
branches: [dev] # 仅 dev 分支 push 触发
paths:
- 'src/frontend/**'
pull_request:
branches: [dev] # 向 dev 发 PR 时触发
paths:
- 'src/frontend/**'
defaults:
run:
working-directory: src/frontend
jobs:
lint-and-build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
cache-dependency-path: src/frontend/package-lock.json
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: Upload dist artifact
uses: actions/upload-artifact@v4
with:
name: frontend-dist
path: src/frontend/dist
deploy:
needs: lint-and-build
if: github.event_name == 'push' && github.ref == 'refs/heads/dev'
runs-on: ubuntu-latest
steps:
- name: Download dist artifact
uses: actions/download-artifact@v4
with:
name: frontend-dist
path: dist
- name: Deploy to dev server via rsync
uses: easingthemes/ssh-deploy@v4.1.10
with:
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
ARGS: "-avz --delete"
SOURCE: "dist/"
REMOTE_HOST: ${{ secrets.SERVER_IP }}
REMOTE_USER: ${{ secrets.SERVER_USER }}
TARGET: "/var/www/frontend" # dev 环境的前端部署目录
实现方式及理由
分支范围:仅监听 dev 分支。团队采用 Git Flow 简化版,所有功能分支先合并到 dev 进行集成,稳定后才会合入 main。这种设置避免了开发阶段的频繁触发对 main 分支的干扰。
触发条件:
push:当有代码推送到dev分支(且变更文件在对应模块目录下)时触发,用于持续集成和自动部署。pull_request:当有 PR 指向dev分支时也会触发,可在合并前进行质量门禁。- 通过
paths过滤器实现精准触发:后端工作流仅关注src/backend/**变更,前端仅关注src/frontend/**变更。
执行的动作:
-
后端打包与部署:使用
docker/build-push-action@v5构建 Docker 镜像并推送到 GitHub 容器仓库(ghcr.io)。镜像打上了两个标签:dev(指向最新的开发镜像)和github.sha(与本次提交一一对应,确保可追溯),让后端代码的每一次集成都可以直接获得一个可运行的容器。构建完成后,通过appleboy/ssh-action@v1.0.3SSH 连接到开发服务器,执行docker compose pull、docker compose up -d更新后端服务,并清理无用的旧镜像。 -
前端打包与部署:通过
npm run build生成静态资源,之后使用actions/upload-artifact@v4将dist目录上传为工作流产物。该产物可在 GitHub Actions 的页面上直接下载,方便团队成员在不搭建本地环境的情况下快速查看某个版本的构建结果,也为后续的部署 Job 提供了可传递的制品(通过download-artifact实现)。部署阶段使用easingthemes/ssh-deploy@v4.1.10通过 rsync 将构建产物同步到开发服务器的/var/www/frontend目录,--delete参数确保远端目录与构建结果完全一致。 -
质量左移:在工作流中,打包之前都串行了 lint 检查(后端 flake8)和测试(后端 pytest),任意前置环节失败,打包和部署都将被阻止。前端构建步骤中,
npm ci会严格按package-lock.json安装依赖,确保构建环境的一致性。
CI/CD 触发结果展示


浙公网安备 33010602011771号