Deploy to Cloudflare #103
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Deploy to Cloudflare | |
| on: | |
| push: | |
| branches: | |
| - multi-tenant | |
| paths-ignore: | |
| - 'README.md' | |
| - 'LICENSE' | |
| - '.gitignore' | |
| - 'docs/**' | |
| - '*.md' | |
| schedule: | |
| # 每 3 天检查一次更新并部署 | |
| - cron: '0 0 */3 * *' | |
| workflow_dispatch: | |
| inputs: | |
| force_deploy: | |
| description: '强制部署(忽略版本检查)' | |
| required: false | |
| type: boolean | |
| default: false | |
| deploy_frontend: | |
| description: '是否部署前端(auto=仅版本变化时,deploy=强制部署,skip=跳过)' | |
| required: false | |
| type: choice | |
| default: auto | |
| options: | |
| - auto | |
| - deploy | |
| - skip | |
| env: | |
| SUBSTORE_REPO: sub-store-org/Sub-Store | |
| FRONTEND_REPO: sub-store-org/Sub-Store-Front-End | |
| jobs: | |
| check-updates: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| deploy_backend: ${{ steps.check.outputs.deploy_backend }} | |
| deploy_frontend_needed: ${{ steps.check.outputs.deploy_frontend_needed }} | |
| backend_version: ${{ steps.check.outputs.backend_version }} | |
| frontend_version: ${{ steps.check.outputs.frontend_version }} | |
| deploy_frontend: ${{ steps.frontend-check.outputs.deploy_frontend }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Restore Last Version Cache | |
| uses: actions/cache/restore@v5 | |
| with: | |
| path: | | |
| .last-backend-version | |
| .last-frontend-version | |
| key: version-cache-${{ github.ref_name }}-${{ github.run_id }} | |
| restore-keys: | | |
| version-cache-${{ github.ref_name }}- | |
| - name: Check for New Releases | |
| id: check | |
| env: | |
| GITHUB_TOKEN: ${{ github.token }} | |
| SUBSTORE_REPO: ${{ env.SUBSTORE_REPO }} | |
| FRONTEND_REPO: ${{ env.FRONTEND_REPO }} | |
| FORCE_DEPLOY: ${{ github.event.inputs.force_deploy || 'false' }} | |
| EVENT_NAME: ${{ github.event_name }} | |
| DEPLOY_FRONTEND_MODE: ${{ github.event.inputs.deploy_frontend || 'auto' }} | |
| RUN_ID: ${{ github.run_id }} | |
| run: node scripts/check-updates.js | |
| - name: Check If Frontend Deploy Is Enabled | |
| id: frontend-check | |
| env: | |
| DEPLOY_SUB_STORE_FRONTEND: ${{ vars.DEPLOY_SUB_STORE_FRONTEND }} | |
| run: | | |
| if [ -n "$DEPLOY_SUB_STORE_FRONTEND" ]; then | |
| echo "deploy_frontend=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "deploy_frontend=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| deploy-backend: | |
| needs: check-updates | |
| if: contains(needs.check-updates.outputs.deploy_backend, 'ACTION_START') | |
| runs-on: ubuntu-latest | |
| name: Deploy Backend | |
| steps: | |
| - name: Validate JWT_SECRET | |
| run: | | |
| if [ -z "${{ secrets.JWT_SECRET }}" ]; then | |
| echo "::error::JWT_SECRET 未设置!" | |
| exit 1 | |
| fi | |
| - name: Checkout Workers Adapter Code | |
| uses: actions/checkout@v6 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: 24 | |
| - name: Setup pnpm | |
| uses: pnpm/action-setup@v6 | |
| with: | |
| version: latest | |
| - name: Download Sub-Store Source Code | |
| env: | |
| GITHUB_TOKEN: ${{ github.token }} | |
| run: | | |
| VERSION=${{ needs.check-updates.outputs.backend_version }} | |
| echo "Downloading Sub-Store source $VERSION..." | |
| # 使用仓库内脚本拉取后端源码(支持 GITHUB_TOKEN 降低限流概率) | |
| SUBSTORE_REPO='${{ env.SUBSTORE_REPO }}' \ | |
| SUBSTORE_VERSION="$VERSION" \ | |
| bash scripts/fetch-substore.sh | |
| # 复制整个项目到构建目录(包含 sub-store/backend) | |
| mkdir -p build | |
| rsync -av --exclude='.git' --exclude='build' --exclude='node_modules' . build/ | |
| - name: Configure wrangler.toml | |
| run: | | |
| cd build | |
| cp wrangler.toml.example wrangler.toml | |
| JWT_SECRET='${{ secrets.JWT_SECRET }}' | |
| ESCAPED_JWT_SECRET=$(printf '%s' "$JWT_SECRET" | sed -e 's/[\\/&]/\\\\&/g') | |
| sed -i "s|__JWT_SECRET__|$ESCAPED_JWT_SECRET|g" wrangler.toml | |
| - name: Install backend dependencies | |
| working-directory: build | |
| run: pnpm run install:backend | |
| - name: Install dependencies | |
| working-directory: build | |
| run: pnpm install | |
| - name: Inject commit info | |
| working-directory: build | |
| env: | |
| COMMIT_HASH: ${{ github.sha }} | |
| COMMIT_REPO: ${{ github.repository }} | |
| run: | | |
| SHORT_SHA=$(echo "$COMMIT_HASH" | cut -c1-7) | |
| sed -i "s/'__COMMIT_HASH__'/'${SHORT_SHA}'/g" dashboard/components/Footer.jsx | |
| sed -i "s|'__COMMIT_REPO__'|'${COMMIT_REPO}'|g" dashboard/components/Footer.jsx | |
| - name: Build with Vite | |
| working-directory: build | |
| run: pnpm run build:workers | |
| - name: Deploy to Cloudflare Workers | |
| working-directory: build | |
| env: | |
| CLOUDFLARE_API_TOKEN: ${{ secrets.CF_API_TOKEN }} | |
| CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CF_ACCOUNT_ID }} | |
| run: | | |
| pnpm run deploy:workers:action | |
| echo "Deploy completed" | |
| deploy-frontend: | |
| needs: check-updates | |
| if: ${{ startsWith(needs.check-updates.outputs.deploy_frontend_needed, 'ACTION_START_') && (needs.check-updates.outputs.deploy_frontend == 'true' || (github.event_name == 'workflow_dispatch' && inputs.deploy_frontend == 'deploy')) }} | |
| runs-on: ubuntu-latest | |
| name: Deploy Frontend | |
| steps: | |
| - name: Download Sub-Store Frontend dist | |
| run: | | |
| VERSION=${{ needs.check-updates.outputs.frontend_version }} | |
| echo "Downloading Sub-Store Frontend $VERSION..." | |
| # 直接下载 release 中的 dist.zip(已构建好) | |
| curl -L "https://github.com/${{ env.FRONTEND_REPO }}/releases/download/${VERSION}/dist.zip" -o dist.zip | |
| unzip dist.zip -d frontend-dist | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: 24 | |
| - name: Deploy to Cloudflare Pages | |
| env: | |
| CLOUDFLARE_API_TOKEN: ${{ secrets.CF_API_TOKEN }} | |
| CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CF_ACCOUNT_ID }} | |
| run: | | |
| set -o pipefail | |
| npx wrangler pages deploy frontend-dist/dist --project-name=sub-store-frontend 2>&1 | sed -E '/https:\/\/[^[:space:]]+\.pages\.dev/d' | |
| update-version-cache: | |
| needs: [check-updates, deploy-backend, deploy-frontend] | |
| if: always() && (needs.deploy-backend.result == 'success' || needs.deploy-frontend.result == 'success') | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Restore Last Version Cache | |
| uses: actions/cache/restore@v5 | |
| with: | |
| path: | | |
| .last-backend-version | |
| .last-frontend-version | |
| key: version-cache-${{ github.ref_name }}-${{ github.run_id }} | |
| restore-keys: | | |
| version-cache-${{ github.ref_name }}- | |
| - name: Update version files | |
| run: | | |
| # 只在对应组件部署成功后,才推进它的“上次部署版本” | |
| if [[ "${{ needs.deploy-backend.result }}" == "success" ]]; then | |
| echo "${{ needs.check-updates.outputs.backend_version }}" > .last-backend-version | |
| else | |
| test -f .last-backend-version || echo "none" > .last-backend-version | |
| fi | |
| if [[ "${{ needs.deploy-frontend.result }}" == "success" ]]; then | |
| echo "${{ needs.check-updates.outputs.frontend_version }}" > .last-frontend-version | |
| else | |
| test -f .last-frontend-version || echo "none" > .last-frontend-version | |
| fi | |
| - name: Save version cache | |
| uses: actions/cache/save@v5 | |
| with: | |
| path: | | |
| .last-backend-version | |
| .last-frontend-version | |
| key: version-cache-${{ github.ref_name }}-${{ github.run_id }} | |
| summary: | |
| needs: [check-updates, deploy-backend, deploy-frontend] | |
| if: always() | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Deploy Summary | |
| run: | | |
| echo "## 部署摘要报告" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "**触发方式**: \`${{ github.event_name }}\`" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "| 组件 | 版本 | 状态 |" >> $GITHUB_STEP_SUMMARY | |
| echo "|------|------|------|" >> $GITHUB_STEP_SUMMARY | |
| echo "| 后端 | \`${{ needs.check-updates.outputs.backend_version }}\` | \`${{ needs.deploy-backend.result }}\` |" >> $GITHUB_STEP_SUMMARY | |
| echo "| 前端 | \`${{ needs.check-updates.outputs.frontend_version }}\` | \`${{ needs.deploy-frontend.result }}\` |" >> $GITHUB_STEP_SUMMARY |