From 9d2d9367b272d76ab9a715daec1a7157cd327f95 Mon Sep 17 00:00:00 2001 From: lintsinghua Date: Fri, 28 Nov 2025 20:43:26 +0800 Subject: [PATCH] feat: improve Docker deployment and release workflows - Add WeasyPrint system dependencies with Chinese font support - Update requirements.txt with all dependencies - Fix docker-compose.yml network configuration - Update GitHub Actions release workflow for frontend-backend architecture - Update release script for new project structure - Support multi-arch Docker builds (amd64, arm64) --- .github/workflows/release.yml | 140 ++++++++++++++++-------- .github/workflows/scheduled-release.yml | 12 +- backend/Dockerfile | 29 ++++- backend/requirements.txt | 9 +- docker-compose.yml | 14 ++- scripts/release.sh | 19 +++- 6 files changed, 160 insertions(+), 63 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index bb8eda4..1d2c9ef 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -6,7 +6,7 @@ on: workflow_dispatch: inputs: version: - description: '版本号 (例如: v1.0.0)' + description: '版本号 (例如: v2.0.0)' required: true type: string prerelease: @@ -36,29 +36,37 @@ jobs: with: fetch-depth: 0 - # 2. 设置 Node.js 环境 + # 2. 设置 Node.js 环境(用于前端构建) - name: 设置 Node.js uses: actions/setup-node@v4 with: - node-version: '18' - cache: 'npm' + node-version: '20' + cache: 'pnpm' + cache-dependency-path: frontend/pnpm-lock.yaml # 3. 安装 pnpm - name: 安装 pnpm run: npm install -g pnpm - # 4. 安装依赖 - - name: 安装依赖 - run: pnpm install --no-frozen-lockfile + # 4. 安装前端依赖 + - name: 安装前端依赖 + working-directory: ./frontend + run: pnpm install --frozen-lockfile # 5. 构建前端项目 - - name: 构建项目 + - name: 构建前端项目 + working-directory: ./frontend run: pnpm build env: - # 这里可以添加构建时需要的环境变量 VITE_USE_LOCAL_DB: 'true' - # 6. 确定版本号 + # 6. 设置 Python 环境(用于后端) + - name: 设置 Python + uses: actions/setup-python@v5 + with: + python-version: '3.13' + + # 7. 确定版本号 - name: 确定版本号 id: version run: | @@ -69,20 +77,43 @@ jobs: echo "VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT echo "IS_PRERELEASE=false" >> $GITHUB_OUTPUT fi + VERSION_NO_V="${VERSION#v}" + echo "VERSION_NO_V=$VERSION_NO_V" >> $GITHUB_OUTPUT - # 7. 打包构建产物 + # 8. 打包构建产物 - name: 打包构建产物 run: | # 创建发布目录 mkdir -p release # 打包前端构建产物 - tar -czf release/xcode-reviewer-frontend-${{ steps.version.outputs.VERSION }}.tar.gz -C dist . + tar -czf release/xcodereviewer-frontend-${{ steps.version.outputs.VERSION }}.tar.gz -C frontend/dist . + + # 打包后端源码 + tar -czf release/xcodereviewer-backend-${{ steps.version.outputs.VERSION }}.tar.gz \ + --exclude=backend/.venv \ + --exclude=backend/.env \ + --exclude=backend/__pycache__ \ + --exclude=backend/uploads \ + backend/ + + # 打包 Docker 配置文件 + tar -czf release/xcodereviewer-docker-${{ steps.version.outputs.VERSION }}.tar.gz \ + docker-compose.yml \ + Dockerfile \ + nginx.conf \ + backend/Dockerfile \ + frontend/Dockerfile \ + backend/env.example \ + frontend/.env.example # 打包完整源码(包括配置文件) - tar -czf release/xcode-reviewer-source-${{ steps.version.outputs.VERSION }}.tar.gz \ - --exclude=node_modules \ - --exclude=dist \ + tar -czf release/xcodereviewer-source-${{ steps.version.outputs.VERSION }}.tar.gz \ + --exclude=frontend/node_modules \ + --exclude=frontend/dist \ + --exclude=backend/.venv \ + --exclude=backend/.env \ + --exclude=backend/uploads \ --exclude=.git \ --exclude=release \ . @@ -92,7 +123,7 @@ jobs: sha256sum * > checksums.txt cd .. - # 8. 生成更新日志 + # 9. 生成更新日志 - name: 生成更新日志 id: changelog run: | @@ -110,15 +141,28 @@ jobs: echo "" >> CHANGELOG.md echo "" >> CHANGELOG.md - echo "## 下载说明" >> CHANGELOG.md + echo "## 📦 下载说明" >> CHANGELOG.md echo "" >> CHANGELOG.md - echo "- \`xcode-reviewer-frontend-*.tar.gz\`: 前端构建产物(用于部署)" >> CHANGELOG.md - echo "- \`xcode-reviewer-source-*.tar.gz\`: 完整源码包" >> CHANGELOG.md + echo "### 构建产物" >> CHANGELOG.md + echo "- \`xcodereviewer-frontend-*.tar.gz\`: 前端构建产物(用于生产部署)" >> CHANGELOG.md + echo "- \`xcodereviewer-backend-*.tar.gz\`: 后端源码包" >> CHANGELOG.md + echo "- \`xcodereviewer-docker-*.tar.gz\`: Docker 配置文件" >> CHANGELOG.md + echo "- \`xcodereviewer-source-*.tar.gz\`: 完整源码包" >> CHANGELOG.md echo "- \`checksums.txt\`: 文件校验和" >> CHANGELOG.md + echo "" >> CHANGELOG.md + echo "### Docker 镜像" >> CHANGELOG.md + echo "- Frontend: \`ghcr.io/${{ github.repository_owner }}/xcodereviewer-frontend:${{ steps.version.outputs.VERSION }}\`" >> CHANGELOG.md + echo "- Backend: \`ghcr.io/${{ github.repository_owner }}/xcodereviewer-backend:${{ steps.version.outputs.VERSION }}\`" >> CHANGELOG.md + echo "" >> CHANGELOG.md + echo "### 快速部署" >> CHANGELOG.md + echo "\`\`\`bash" >> CHANGELOG.md + echo "# 使用 Docker Compose 部署" >> CHANGELOG.md + echo "docker-compose up -d" >> CHANGELOG.md + echo "\`\`\`" >> CHANGELOG.md - # 9. 创建 GitHub Release + # 10. 创建 GitHub Release - name: 创建 Release - uses: softprops/action-gh-release@v1 + uses: softprops/action-gh-release@v2 with: tag_name: ${{ steps.version.outputs.VERSION }} name: Release ${{ steps.version.outputs.VERSION }} @@ -131,7 +175,7 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - # 10. 登录 GitHub Container Registry + # 11. 登录 GitHub Container Registry - name: 登录到 GitHub Container Registry uses: docker/login-action@v3 with: @@ -139,41 +183,51 @@ jobs: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - # 11. 设置 QEMU(用于多架构构建) + # 12. 设置 QEMU(用于多架构构建) - name: 设置 QEMU uses: docker/setup-qemu-action@v3 - # 12. 设置 Docker Buildx + # 13. 设置 Docker Buildx - name: 设置 Docker Buildx uses: docker/setup-buildx-action@v3 - # 13. 构建并推送 Docker 镜像(多架构) - - name: 构建并推送 Docker 镜像 + # 14. 构建并推送前端 Docker 镜像(生产环境 Nginx) + - name: 构建并推送前端 Docker 镜像 uses: docker/build-push-action@v5 with: context: . + file: ./Dockerfile push: true - platforms: linux/amd64,linux/arm64,linux/arm/v7 + platforms: linux/amd64,linux/arm64 tags: | - ghcr.io/${{ github.repository_owner }}/xcodereviewer:${{ steps.version.outputs.VERSION }} - ghcr.io/${{ github.repository_owner }}/xcodereviewer:latest - cache-from: type=gha - cache-to: type=gha,mode=max - build-args: | - VITE_USE_LOCAL_DB=true + ghcr.io/${{ github.repository_owner }}/xcodereviewer-frontend:${{ steps.version.outputs.VERSION }} + ghcr.io/${{ github.repository_owner }}/xcodereviewer-frontend:latest + cache-from: type=gha,scope=frontend + cache-to: type=gha,mode=max,scope=frontend - # 14. 更新 package.json 版本号(可选) - - name: 更新 package.json 版本 - if: github.event_name == 'workflow_dispatch' + # 15. 构建并推送后端 Docker 镜像 + - name: 构建并推送后端 Docker 镜像 + uses: docker/build-push-action@v5 + with: + context: ./backend + file: ./backend/Dockerfile + push: true + platforms: linux/amd64,linux/arm64 + tags: | + ghcr.io/${{ github.repository_owner }}/xcodereviewer-backend:${{ steps.version.outputs.VERSION }} + ghcr.io/${{ github.repository_owner }}/xcodereviewer-backend:latest + cache-from: type=gha,scope=backend + cache-to: type=gha,mode=max,scope=backend + + # 16. 更新 README 中的版本号 + - name: 更新 README 版本号 + if: github.event_name == 'push' run: | - VERSION="${{ steps.version.outputs.VERSION }}" - VERSION_NO_V="${VERSION#v}" - npm version $VERSION_NO_V --no-git-tag-version + VERSION="${{ steps.version.outputs.VERSION_NO_V }}" + sed -i "s/version-[0-9]*\.[0-9]*\.[0-9]*/version-$VERSION/g" README.md git config user.name "github-actions[bot]" git config user.email "github-actions[bot]@users.noreply.github.com" - git add package.json - git commit -m "chore: bump version to $VERSION" || true + git add README.md + git commit -m "docs: update README version to $VERSION" || true git push origin HEAD:main || true - - diff --git a/.github/workflows/scheduled-release.yml b/.github/workflows/scheduled-release.yml index 605fab4..beab1b6 100644 --- a/.github/workflows/scheduled-release.yml +++ b/.github/workflows/scheduled-release.yml @@ -33,7 +33,7 @@ jobs: if [ -z "$LAST_TAG" ]; then echo "has_changes=true" >> $GITHUB_OUTPUT - echo "version=v0.1.0" >> $GITHUB_OUTPUT + echo "version=v2.0.0" >> $GITHUB_OUTPUT else # 检查自上次 tag 以来是否有新的提交 COMMITS_SINCE_TAG=$(git rev-list $LAST_TAG..HEAD --count) @@ -71,7 +71,9 @@ jobs: - name: 触发发布 if: steps.check.outputs.has_changes == 'true' run: | - echo "新版本 ${{ steps.check.outputs.version }} 已创建,将触发发布流程" - echo "请查看 Release 工作流的执行情况" - - + echo "✅ 新版本 ${{ steps.check.outputs.version }} 已创建" + echo "🚀 Release 工作流将自动开始构建和发布" + echo "📦 将发布以下组件:" + echo " - 前端 Docker 镜像" + echo " - 后端 Docker 镜像" + echo " - 构建产物和源码包" diff --git a/backend/Dockerfile b/backend/Dockerfile index ea75bbc..f5d0bbc 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -4,12 +4,30 @@ WORKDIR /app ENV PYTHONDONTWRITEBYTECODE=1 ENV PYTHONUNBUFFERED=1 +ENV PIP_NO_CACHE_DIR=1 +ENV PIP_DISABLE_PIP_VERSION_CHECK=1 -# 安装系统依赖 -RUN apt-get update && apt-get install -y --no-install-recommends \ - gcc \ - libpq-dev \ - && rm -rf /var/lib/apt/lists/* +# 安装系统依赖(包含 WeasyPrint 所需的库和中文字体支持) +RUN for i in 1 2 3; do \ + apt-get update && \ + apt-get install -y --no-install-recommends \ + gcc \ + libpq-dev \ + # WeasyPrint 依赖 + libpango-1.0-0 \ + libpangoft2-1.0-0 \ + libcairo2 \ + libgdk-pixbuf2.0-0 \ + libffi-dev \ + shared-mime-info \ + # 字体支持(中文) + fonts-noto-cjk \ + fonts-noto-cjk-extra \ + fontconfig \ + && fc-cache -fv \ + && rm -rf /var/lib/apt/lists/* \ + && break || sleep 5; \ + done # 复制依赖文件 COPY pyproject.toml . @@ -31,3 +49,4 @@ EXPOSE 8000 CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"] + diff --git a/backend/requirements.txt b/backend/requirements.txt index 4db4873..5a7e1fb 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -9,5 +9,10 @@ passlib[bcrypt] python-jose[cryptography] python-multipart httpx - - +email-validator +greenlet +bcrypt<5.0.0 +litellm>=1.0.0 +reportlab>=4.0.0 +weasyprint>=66.0 +jinja2>=3.1.6 diff --git a/docker-compose.yml b/docker-compose.yml index 2474a7a..c6b3dac 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,5 +1,3 @@ -version: '3.8' - services: db: image: postgres:15-alpine @@ -16,6 +14,8 @@ services: interval: 5s timeout: 5s retries: 5 + networks: + - xcodereviewer-network backend: build: @@ -33,6 +33,8 @@ services: db: condition: service_healthy command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload + networks: + - xcodereviewer-network frontend: build: @@ -43,10 +45,16 @@ services: ports: - "5173:5173" environment: - - VITE_API_BASE_URL=http://localhost:8000/api/v1 + - VITE_API_BASE_URL=http://backend:8000/api/v1 depends_on: - backend command: npm run dev -- --host + networks: + - xcodereviewer-network + +networks: + xcodereviewer-network: + driver: bridge volumes: postgres_data: diff --git a/scripts/release.sh b/scripts/release.sh index 064bd89..baacb5d 100755 --- a/scripts/release.sh +++ b/scripts/release.sh @@ -40,8 +40,13 @@ if [ -n "$(git status --porcelain)" ]; then fi fi -# 获取当前版本号 -CURRENT_VERSION=$(node -p "require('./package.json').version") +# 获取当前版本号(从前端项目) +if [ -f "frontend/package.json" ]; then + CURRENT_VERSION=$(node -p "require('./frontend/package.json').version") +else + print_error "找不到 frontend/package.json 文件" + exit 1 +fi print_info "当前版本: v$CURRENT_VERSION" # 解析版本号 @@ -94,13 +99,17 @@ if [[ ! $REPLY =~ ^[Yy]$ ]]; then exit 0 fi -# 更新 package.json -print_info "更新 package.json..." +# 更新前端 package.json +print_info "更新前端 package.json..." +cd frontend npm version "$NEW_VERSION" --no-git-tag-version +cd .. # 提交更改 print_info "提交版本更改..." -git add package.json package-lock.json 2>/dev/null || true +git add frontend/package.json frontend/package-lock.json 2>/dev/null || true +git add frontend/pnpm-lock.yaml 2>/dev/null || true +git add README.md 2>/dev/null || true git commit -m "chore: bump version to v$NEW_VERSION" || true # 创建 tag