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)
This commit is contained in:
parent
9054f0d2c5
commit
9d2d9367b2
|
|
@ -6,7 +6,7 @@ on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
version:
|
version:
|
||||||
description: '版本号 (例如: v1.0.0)'
|
description: '版本号 (例如: v2.0.0)'
|
||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
prerelease:
|
prerelease:
|
||||||
|
|
@ -36,29 +36,37 @@ jobs:
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
# 2. 设置 Node.js 环境
|
# 2. 设置 Node.js 环境(用于前端构建)
|
||||||
- name: 设置 Node.js
|
- name: 设置 Node.js
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: '18'
|
node-version: '20'
|
||||||
cache: 'npm'
|
cache: 'pnpm'
|
||||||
|
cache-dependency-path: frontend/pnpm-lock.yaml
|
||||||
|
|
||||||
# 3. 安装 pnpm
|
# 3. 安装 pnpm
|
||||||
- name: 安装 pnpm
|
- name: 安装 pnpm
|
||||||
run: npm install -g pnpm
|
run: npm install -g pnpm
|
||||||
|
|
||||||
# 4. 安装依赖
|
# 4. 安装前端依赖
|
||||||
- name: 安装依赖
|
- name: 安装前端依赖
|
||||||
run: pnpm install --no-frozen-lockfile
|
working-directory: ./frontend
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
# 5. 构建前端项目
|
# 5. 构建前端项目
|
||||||
- name: 构建项目
|
- name: 构建前端项目
|
||||||
|
working-directory: ./frontend
|
||||||
run: pnpm build
|
run: pnpm build
|
||||||
env:
|
env:
|
||||||
# 这里可以添加构建时需要的环境变量
|
|
||||||
VITE_USE_LOCAL_DB: 'true'
|
VITE_USE_LOCAL_DB: 'true'
|
||||||
|
|
||||||
# 6. 确定版本号
|
# 6. 设置 Python 环境(用于后端)
|
||||||
|
- name: 设置 Python
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: '3.13'
|
||||||
|
|
||||||
|
# 7. 确定版本号
|
||||||
- name: 确定版本号
|
- name: 确定版本号
|
||||||
id: version
|
id: version
|
||||||
run: |
|
run: |
|
||||||
|
|
@ -69,20 +77,43 @@ jobs:
|
||||||
echo "VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
|
echo "VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
|
||||||
echo "IS_PRERELEASE=false" >> $GITHUB_OUTPUT
|
echo "IS_PRERELEASE=false" >> $GITHUB_OUTPUT
|
||||||
fi
|
fi
|
||||||
|
VERSION_NO_V="${VERSION#v}"
|
||||||
|
echo "VERSION_NO_V=$VERSION_NO_V" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
# 7. 打包构建产物
|
# 8. 打包构建产物
|
||||||
- name: 打包构建产物
|
- name: 打包构建产物
|
||||||
run: |
|
run: |
|
||||||
# 创建发布目录
|
# 创建发布目录
|
||||||
mkdir -p release
|
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 \
|
tar -czf release/xcodereviewer-source-${{ steps.version.outputs.VERSION }}.tar.gz \
|
||||||
--exclude=node_modules \
|
--exclude=frontend/node_modules \
|
||||||
--exclude=dist \
|
--exclude=frontend/dist \
|
||||||
|
--exclude=backend/.venv \
|
||||||
|
--exclude=backend/.env \
|
||||||
|
--exclude=backend/uploads \
|
||||||
--exclude=.git \
|
--exclude=.git \
|
||||||
--exclude=release \
|
--exclude=release \
|
||||||
.
|
.
|
||||||
|
|
@ -92,7 +123,7 @@ jobs:
|
||||||
sha256sum * > checksums.txt
|
sha256sum * > checksums.txt
|
||||||
cd ..
|
cd ..
|
||||||
|
|
||||||
# 8. 生成更新日志
|
# 9. 生成更新日志
|
||||||
- name: 生成更新日志
|
- name: 生成更新日志
|
||||||
id: changelog
|
id: changelog
|
||||||
run: |
|
run: |
|
||||||
|
|
@ -110,15 +141,28 @@ jobs:
|
||||||
|
|
||||||
echo "" >> CHANGELOG.md
|
echo "" >> CHANGELOG.md
|
||||||
echo "" >> CHANGELOG.md
|
echo "" >> CHANGELOG.md
|
||||||
echo "## 下载说明" >> CHANGELOG.md
|
echo "## 📦 下载说明" >> CHANGELOG.md
|
||||||
echo "" >> CHANGELOG.md
|
echo "" >> CHANGELOG.md
|
||||||
echo "- \`xcode-reviewer-frontend-*.tar.gz\`: 前端构建产物(用于部署)" >> CHANGELOG.md
|
echo "### 构建产物" >> CHANGELOG.md
|
||||||
echo "- \`xcode-reviewer-source-*.tar.gz\`: 完整源码包" >> 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 "- \`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
|
- name: 创建 Release
|
||||||
uses: softprops/action-gh-release@v1
|
uses: softprops/action-gh-release@v2
|
||||||
with:
|
with:
|
||||||
tag_name: ${{ steps.version.outputs.VERSION }}
|
tag_name: ${{ steps.version.outputs.VERSION }}
|
||||||
name: Release ${{ steps.version.outputs.VERSION }}
|
name: Release ${{ steps.version.outputs.VERSION }}
|
||||||
|
|
@ -131,7 +175,7 @@ jobs:
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
# 10. 登录 GitHub Container Registry
|
# 11. 登录 GitHub Container Registry
|
||||||
- name: 登录到 GitHub Container Registry
|
- name: 登录到 GitHub Container Registry
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
|
|
@ -139,41 +183,51 @@ jobs:
|
||||||
username: ${{ github.actor }}
|
username: ${{ github.actor }}
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
# 11. 设置 QEMU(用于多架构构建)
|
# 12. 设置 QEMU(用于多架构构建)
|
||||||
- name: 设置 QEMU
|
- name: 设置 QEMU
|
||||||
uses: docker/setup-qemu-action@v3
|
uses: docker/setup-qemu-action@v3
|
||||||
|
|
||||||
# 12. 设置 Docker Buildx
|
# 13. 设置 Docker Buildx
|
||||||
- name: 设置 Docker Buildx
|
- name: 设置 Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
# 13. 构建并推送 Docker 镜像(多架构)
|
# 14. 构建并推送前端 Docker 镜像(生产环境 Nginx)
|
||||||
- name: 构建并推送 Docker 镜像
|
- name: 构建并推送前端 Docker 镜像
|
||||||
uses: docker/build-push-action@v5
|
uses: docker/build-push-action@v5
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
|
file: ./Dockerfile
|
||||||
push: true
|
push: true
|
||||||
platforms: linux/amd64,linux/arm64,linux/arm/v7
|
platforms: linux/amd64,linux/arm64
|
||||||
tags: |
|
tags: |
|
||||||
ghcr.io/${{ github.repository_owner }}/xcodereviewer:${{ steps.version.outputs.VERSION }}
|
ghcr.io/${{ github.repository_owner }}/xcodereviewer-frontend:${{ steps.version.outputs.VERSION }}
|
||||||
ghcr.io/${{ github.repository_owner }}/xcodereviewer:latest
|
ghcr.io/${{ github.repository_owner }}/xcodereviewer-frontend:latest
|
||||||
cache-from: type=gha
|
cache-from: type=gha,scope=frontend
|
||||||
cache-to: type=gha,mode=max
|
cache-to: type=gha,mode=max,scope=frontend
|
||||||
build-args: |
|
|
||||||
VITE_USE_LOCAL_DB=true
|
|
||||||
|
|
||||||
# 14. 更新 package.json 版本号(可选)
|
# 15. 构建并推送后端 Docker 镜像
|
||||||
- name: 更新 package.json 版本
|
- name: 构建并推送后端 Docker 镜像
|
||||||
if: github.event_name == 'workflow_dispatch'
|
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: |
|
run: |
|
||||||
VERSION="${{ steps.version.outputs.VERSION }}"
|
VERSION="${{ steps.version.outputs.VERSION_NO_V }}"
|
||||||
VERSION_NO_V="${VERSION#v}"
|
sed -i "s/version-[0-9]*\.[0-9]*\.[0-9]*/version-$VERSION/g" README.md
|
||||||
npm version $VERSION_NO_V --no-git-tag-version
|
|
||||||
|
|
||||||
git config user.name "github-actions[bot]"
|
git config user.name "github-actions[bot]"
|
||||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||||
git add package.json
|
git add README.md
|
||||||
git commit -m "chore: bump version to $VERSION" || true
|
git commit -m "docs: update README version to $VERSION" || true
|
||||||
git push origin HEAD:main || true
|
git push origin HEAD:main || true
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ jobs:
|
||||||
|
|
||||||
if [ -z "$LAST_TAG" ]; then
|
if [ -z "$LAST_TAG" ]; then
|
||||||
echo "has_changes=true" >> $GITHUB_OUTPUT
|
echo "has_changes=true" >> $GITHUB_OUTPUT
|
||||||
echo "version=v0.1.0" >> $GITHUB_OUTPUT
|
echo "version=v2.0.0" >> $GITHUB_OUTPUT
|
||||||
else
|
else
|
||||||
# 检查自上次 tag 以来是否有新的提交
|
# 检查自上次 tag 以来是否有新的提交
|
||||||
COMMITS_SINCE_TAG=$(git rev-list $LAST_TAG..HEAD --count)
|
COMMITS_SINCE_TAG=$(git rev-list $LAST_TAG..HEAD --count)
|
||||||
|
|
@ -71,7 +71,9 @@ jobs:
|
||||||
- name: 触发发布
|
- name: 触发发布
|
||||||
if: steps.check.outputs.has_changes == 'true'
|
if: steps.check.outputs.has_changes == 'true'
|
||||||
run: |
|
run: |
|
||||||
echo "新版本 ${{ steps.check.outputs.version }} 已创建,将触发发布流程"
|
echo "✅ 新版本 ${{ steps.check.outputs.version }} 已创建"
|
||||||
echo "请查看 Release 工作流的执行情况"
|
echo "🚀 Release 工作流将自动开始构建和发布"
|
||||||
|
echo "📦 将发布以下组件:"
|
||||||
|
echo " - 前端 Docker 镜像"
|
||||||
|
echo " - 后端 Docker 镜像"
|
||||||
|
echo " - 构建产物和源码包"
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,30 @@ WORKDIR /app
|
||||||
|
|
||||||
ENV PYTHONDONTWRITEBYTECODE=1
|
ENV PYTHONDONTWRITEBYTECODE=1
|
||||||
ENV PYTHONUNBUFFERED=1
|
ENV PYTHONUNBUFFERED=1
|
||||||
|
ENV PIP_NO_CACHE_DIR=1
|
||||||
|
ENV PIP_DISABLE_PIP_VERSION_CHECK=1
|
||||||
|
|
||||||
# 安装系统依赖
|
# 安装系统依赖(包含 WeasyPrint 所需的库和中文字体支持)
|
||||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
RUN for i in 1 2 3; do \
|
||||||
|
apt-get update && \
|
||||||
|
apt-get install -y --no-install-recommends \
|
||||||
gcc \
|
gcc \
|
||||||
libpq-dev \
|
libpq-dev \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
# 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 .
|
COPY pyproject.toml .
|
||||||
|
|
@ -31,3 +49,4 @@ EXPOSE 8000
|
||||||
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
|
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,5 +9,10 @@ passlib[bcrypt]
|
||||||
python-jose[cryptography]
|
python-jose[cryptography]
|
||||||
python-multipart
|
python-multipart
|
||||||
httpx
|
httpx
|
||||||
|
email-validator
|
||||||
|
greenlet
|
||||||
|
bcrypt<5.0.0
|
||||||
|
litellm>=1.0.0
|
||||||
|
reportlab>=4.0.0
|
||||||
|
weasyprint>=66.0
|
||||||
|
jinja2>=3.1.6
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
version: '3.8'
|
|
||||||
|
|
||||||
services:
|
services:
|
||||||
db:
|
db:
|
||||||
image: postgres:15-alpine
|
image: postgres:15-alpine
|
||||||
|
|
@ -16,6 +14,8 @@ services:
|
||||||
interval: 5s
|
interval: 5s
|
||||||
timeout: 5s
|
timeout: 5s
|
||||||
retries: 5
|
retries: 5
|
||||||
|
networks:
|
||||||
|
- xcodereviewer-network
|
||||||
|
|
||||||
backend:
|
backend:
|
||||||
build:
|
build:
|
||||||
|
|
@ -33,6 +33,8 @@ services:
|
||||||
db:
|
db:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
|
command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
|
||||||
|
networks:
|
||||||
|
- xcodereviewer-network
|
||||||
|
|
||||||
frontend:
|
frontend:
|
||||||
build:
|
build:
|
||||||
|
|
@ -43,10 +45,16 @@ services:
|
||||||
ports:
|
ports:
|
||||||
- "5173:5173"
|
- "5173:5173"
|
||||||
environment:
|
environment:
|
||||||
- VITE_API_BASE_URL=http://localhost:8000/api/v1
|
- VITE_API_BASE_URL=http://backend:8000/api/v1
|
||||||
depends_on:
|
depends_on:
|
||||||
- backend
|
- backend
|
||||||
command: npm run dev -- --host
|
command: npm run dev -- --host
|
||||||
|
networks:
|
||||||
|
- xcodereviewer-network
|
||||||
|
|
||||||
|
networks:
|
||||||
|
xcodereviewer-network:
|
||||||
|
driver: bridge
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
postgres_data:
|
postgres_data:
|
||||||
|
|
|
||||||
|
|
@ -40,8 +40,13 @@ if [ -n "$(git status --porcelain)" ]; then
|
||||||
fi
|
fi
|
||||||
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"
|
print_info "当前版本: v$CURRENT_VERSION"
|
||||||
|
|
||||||
# 解析版本号
|
# 解析版本号
|
||||||
|
|
@ -94,13 +99,17 @@ if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 更新 package.json
|
# 更新前端 package.json
|
||||||
print_info "更新 package.json..."
|
print_info "更新前端 package.json..."
|
||||||
|
cd frontend
|
||||||
npm version "$NEW_VERSION" --no-git-tag-version
|
npm version "$NEW_VERSION" --no-git-tag-version
|
||||||
|
cd ..
|
||||||
|
|
||||||
# 提交更改
|
# 提交更改
|
||||||
print_info "提交版本更改..."
|
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
|
git commit -m "chore: bump version to v$NEW_VERSION" || true
|
||||||
|
|
||||||
# 创建 tag
|
# 创建 tag
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue