name: Deploy to Cloudflare Workers on: push: branches: - main workflow_dispatch: jobs: deploy: runs-on: ubuntu-latest permissions: contents: read name: Deploy steps: - name: Checkout uses: actions/checkout@v4 - name: Check Required Secrets env: JWT_SECRET: ${{ secrets.JWT_SECRET }} ENCRYPTION_KEY: ${{ secrets.ENCRYPTION_KEY }} OAUTH_ALLOWED_USERS: ${{ secrets.OAUTH_ALLOWED_USERS }} CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} CLOUDFLARE_D1_DATABASE_ID: ${{ secrets.CLOUDFLARE_D1_DATABASE_ID }} run: | REQUIRED_VARS=( "JWT_SECRET" "ENCRYPTION_KEY" "OAUTH_ALLOWED_USERS" "CLOUDFLARE_API_TOKEN" "CLOUDFLARE_ACCOUNT_ID" "CLOUDFLARE_D1_DATABASE_ID" ) MISSING_VARS=() for VAR in "${REQUIRED_VARS[@]}"; do if [ -z "${!VAR}" ]; then MISSING_VARS+=("$VAR") fi done if [ ${#MISSING_VARS[@]} -ne 0 ]; then echo "❌ Error: The following required secrets are missing or empty:" for VAR in "${MISSING_VARS[@]}"; do echo " - $VAR" done echo "Please configure them in your repository's Settings > Secrets and variables > Actions." exit 1 fi echo "✅ All required secrets are present." - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '20' cache: 'npm' cache-dependency-path: | package.json # 安装全部依赖 - name: Install Dependencies run: npm install # 准备配置文件 - name: Prepare Wrangler Config env: CONFIG_FILE: ${{ env.WRANGLER_CONFIG || 'wrangler.toml' }} run: | cp wrangler.toml wrangler.toml.bak if [ "$CONFIG_FILE" != "wrangler.toml" ]; then cp "$CONFIG_FILE" wrangler.toml fi # 注入 Cloudflare Workers 名称 - name: Inject Workers Name env: CONFIG_FILE: ${{ env.WRANGLER_CONFIG || 'wrangler.toml' }} CLOUDFLARE_WORKERS_NAME: ${{ secrets.CLOUDFLARE_WORKERS_NAME || '2fauth-worker' }} run: | sed -i "0,/name =/s/name = \".*\"/name = \"$CLOUDFLARE_WORKERS_NAME\"/" "wrangler.toml" # 注入 D1 数据库配置 - name: Inject D1 Database ID env: CONFIG_FILE: ${{ env.WRANGLER_CONFIG || 'wrangler.toml' }} CLOUDFLARE_D1_DATABASE_ID: ${{ secrets.CLOUDFLARE_D1_DATABASE_ID }} CLOUDFLARE_D1_DATABASE_NAME: ${{ secrets.CLOUDFLARE_D1_DATABASE_NAME || 'nodeauth-db' }} run: | sed -i '/^\[\[d1_databases\]\]/d; /^[[:space:]]*database_name[[:space:]]*=/d; /^[[:space:]]*database_id[[:space:]]*=/d; /^[[:space:]]*binding[[:space:]]*=[[:space:]]*"DB"/d' wrangler.toml if grep -q "\[env.dev\]" wrangler.toml; then sed -i '/\[env.dev\]/,$d' wrangler.toml fi printf "\n[[d1_databases]]\nbinding = \"DB\"\ndatabase_name = \"$CLOUDFLARE_D1_DATABASE_NAME\"\ndatabase_id = \"$CLOUDFLARE_D1_DATABASE_ID\"\n" >> wrangler.toml # 数据库初始化与同步:基础 Schema 创建。后续增量演进由后端代码自愈完成。 - name: Sync Database Schema uses: cloudflare/wrangler-action@da0e0dfe58b7a431659754fdf3f186c529afbe65 # v3 with: apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} command: d1 execute ${{ secrets.CLOUDFLARE_D1_DATABASE_NAME || 'nodeauth-db' }} --remote --file=backend/schema.sql # 动态生成 Secrets 列表 (仅包含已配置的变量) - name: Generate Secret List id: secret_list env: OAUTH_GITHUB_CLIENT_ID: ${{ secrets.OAUTH_GITHUB_CLIENT_ID }} OAUTH_GITHUB_CLIENT_SECRET: ${{ secrets.OAUTH_GITHUB_CLIENT_SECRET }} OAUTH_GITHUB_REDIRECT_URI: ${{ secrets.OAUTH_GITHUB_REDIRECT_URI }} OAUTH_CLOUDFLARE_CLIENT_ID: ${{ secrets.OAUTH_CLOUDFLARE_CLIENT_ID }} OAUTH_CLOUDFLARE_CLIENT_SECRET: ${{ secrets.OAUTH_CLOUDFLARE_CLIENT_SECRET }} OAUTH_CLOUDFLARE_ORG_DOMAIN: ${{ secrets.OAUTH_CLOUDFLARE_ORG_DOMAIN }} OAUTH_CLOUDFLARE_REDIRECT_URI: ${{ secrets.OAUTH_CLOUDFLARE_REDIRECT_URI }} OAUTH_NODELOC_CLIENT_ID: ${{ secrets.OAUTH_NODELOC_CLIENT_ID }} OAUTH_NODELOC_CLIENT_SECRET: ${{ secrets.OAUTH_NODELOC_CLIENT_SECRET }} OAUTH_NODELOC_REDIRECT_URI: ${{ secrets.OAUTH_NODELOC_REDIRECT_URI }} OAUTH_GITEE_CLIENT_ID: ${{ secrets.OAUTH_GITEE_CLIENT_ID }} OAUTH_GITEE_CLIENT_SECRET: ${{ secrets.OAUTH_GITEE_CLIENT_SECRET }} OAUTH_GITEE_REDIRECT_URI: ${{ secrets.OAUTH_GITEE_REDIRECT_URI }} OAUTH_TELEGRAM_BOT_NAME: ${{ secrets.OAUTH_TELEGRAM_BOT_NAME }} OAUTH_TELEGRAM_BOT_TOKEN: ${{ secrets.OAUTH_TELEGRAM_BOT_TOKEN }} OAUTH_GOOGLE_CLIENT_ID: ${{ secrets.OAUTH_GOOGLE_CLIENT_ID }} OAUTH_GOOGLE_CLIENT_SECRET: ${{ secrets.OAUTH_GOOGLE_CLIENT_SECRET }} OAUTH_GOOGLE_REDIRECT_URI: ${{ secrets.OAUTH_GOOGLE_REDIRECT_URI }} OAUTH_MICROSOFT_CLIENT_ID: ${{ secrets.OAUTH_MICROSOFT_CLIENT_ID }} OAUTH_MICROSOFT_CLIENT_SECRET: ${{ secrets.OAUTH_MICROSOFT_CLIENT_SECRET }} OAUTH_BAIDU_CLIENT_ID: ${{ secrets.OAUTH_BAIDU_CLIENT_ID }} OAUTH_BAIDU_CLIENT_SECRET: ${{ secrets.OAUTH_BAIDU_CLIENT_SECRET }} OAUTH_DROPBOX_CLIENT_ID: ${{ secrets.OAUTH_DROPBOX_CLIENT_ID }} OAUTH_DROPBOX_CLIENT_SECRET: ${{ secrets.OAUTH_DROPBOX_CLIENT_SECRET }} OAUTH_WALLETCONNECT_PROJECT_ID: ${{ secrets.OAUTH_WALLETCONNECT_PROJECT_ID }} OAUTH_WALLETCONNECT_SELF_PROXY: ${{ secrets.OAUTH_WALLETCONNECT_SELF_PROXY }} run: | SECRETS=" OAUTH_ALLOW_ALL OAUTH_ALLOWED_USERS ENCRYPTION_KEY JWT_SECRET" OPTIONAL_VARS=( "OAUTH_GITHUB_CLIENT_ID" "OAUTH_GITHUB_CLIENT_SECRET" "OAUTH_GITHUB_REDIRECT_URI" "OAUTH_CLOUDFLARE_CLIENT_ID" "OAUTH_CLOUDFLARE_CLIENT_SECRET" "OAUTH_CLOUDFLARE_ORG_DOMAIN" "OAUTH_CLOUDFLARE_REDIRECT_URI" "OAUTH_NODELOC_CLIENT_ID" "OAUTH_NODELOC_CLIENT_SECRET" "OAUTH_NODELOC_REDIRECT_URI" "OAUTH_GITEE_CLIENT_ID" "OAUTH_GITEE_CLIENT_SECRET" "OAUTH_GITEE_REDIRECT_URI" "OAUTH_TELEGRAM_BOT_NAME" "OAUTH_TELEGRAM_BOT_TOKEN" "OAUTH_GOOGLE_CLIENT_ID" "OAUTH_GOOGLE_CLIENT_SECRET" "OAUTH_GOOGLE_REDIRECT_URI" "OAUTH_MICROSOFT_CLIENT_ID" "OAUTH_MICROSOFT_CLIENT_SECRET" "OAUTH_BAIDU_CLIENT_ID" "OAUTH_BAIDU_CLIENT_SECRET" "OAUTH_DROPBOX_CLIENT_ID" "OAUTH_DROPBOX_CLIENT_SECRET" "OAUTH_WALLETCONNECT_PROJECT_ID" "OAUTH_WALLETCONNECT_SELF_PROXY" ) for VAR in "${OPTIONAL_VARS[@]}"; do if [ -n "${!VAR}" ]; then SECRETS="$SECRETS $VAR" fi done echo "secrets<> $GITHUB_OUTPUT echo "$SECRETS" >> $GITHUB_OUTPUT echo "EOF" >> $GITHUB_OUTPUT - name: Mask Sensitive Domain run: | if [ -n "${{ secrets.CLOUDFLARE_WORKER_SUBDOMAIN }}" ]; then echo "::add-mask::${{ secrets.CLOUDFLARE_WORKER_SUBDOMAIN }}" fi # 部署到 Cloudflare Workers - name: Deploy to Cloudflare Workers uses: cloudflare/wrangler-action@da0e0dfe58b7a431659754fdf3f186c529afbe65 # v3 with: apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} command: deploy --minify secrets: ${{ steps.secret_list.outputs.secrets }} env: OAUTH_ALLOW_ALL: ${{ secrets.OAUTH_ALLOW_ALL || 'false' }} OAUTH_ALLOWED_USERS: ${{ secrets.OAUTH_ALLOWED_USERS }} OAUTH_GITHUB_CLIENT_ID: ${{ secrets.OAUTH_GITHUB_CLIENT_ID }} OAUTH_GITHUB_CLIENT_SECRET: ${{ secrets.OAUTH_GITHUB_CLIENT_SECRET }} OAUTH_GITHUB_REDIRECT_URI: ${{ secrets.OAUTH_GITHUB_REDIRECT_URI }} OAUTH_CLOUDFLARE_CLIENT_ID: ${{ secrets.OAUTH_CLOUDFLARE_CLIENT_ID }} OAUTH_CLOUDFLARE_CLIENT_SECRET: ${{ secrets.OAUTH_CLOUDFLARE_CLIENT_SECRET }} OAUTH_CLOUDFLARE_ORG_DOMAIN: ${{ secrets.OAUTH_CLOUDFLARE_ORG_DOMAIN }} OAUTH_CLOUDFLARE_REDIRECT_URI: ${{ secrets.OAUTH_CLOUDFLARE_REDIRECT_URI }} OAUTH_NODELOC_CLIENT_ID: ${{ secrets.OAUTH_NODELOC_CLIENT_ID }} OAUTH_NODELOC_CLIENT_SECRET: ${{ secrets.OAUTH_NODELOC_CLIENT_SECRET }} OAUTH_NODELOC_REDIRECT_URI: ${{ secrets.OAUTH_NODELOC_REDIRECT_URI }} OAUTH_GITEE_CLIENT_ID: ${{ secrets.OAUTH_GITEE_CLIENT_ID }} OAUTH_GITEE_CLIENT_SECRET: ${{ secrets.OAUTH_GITEE_CLIENT_SECRET }} OAUTH_GITEE_REDIRECT_URI: ${{ secrets.OAUTH_GITEE_REDIRECT_URI }} OAUTH_TELEGRAM_BOT_NAME: ${{ secrets.OAUTH_TELEGRAM_BOT_NAME }} OAUTH_TELEGRAM_BOT_TOKEN: ${{ secrets.OAUTH_TELEGRAM_BOT_TOKEN }} OAUTH_GOOGLE_CLIENT_ID: ${{ secrets.OAUTH_GOOGLE_CLIENT_ID }} OAUTH_GOOGLE_CLIENT_SECRET: ${{ secrets.OAUTH_GOOGLE_CLIENT_SECRET }} OAUTH_GOOGLE_REDIRECT_URI: ${{ secrets.OAUTH_GOOGLE_REDIRECT_URI }} OAUTH_MICROSOFT_CLIENT_ID: ${{ secrets.OAUTH_MICROSOFT_CLIENT_ID }} OAUTH_MICROSOFT_CLIENT_SECRET: ${{ secrets.OAUTH_MICROSOFT_CLIENT_SECRET }} OAUTH_BAIDU_CLIENT_ID: ${{ secrets.OAUTH_BAIDU_CLIENT_ID }} OAUTH_BAIDU_CLIENT_SECRET: ${{ secrets.OAUTH_BAIDU_CLIENT_SECRET }} OAUTH_DROPBOX_CLIENT_ID: ${{ secrets.OAUTH_DROPBOX_CLIENT_ID }} OAUTH_DROPBOX_CLIENT_SECRET: ${{ secrets.OAUTH_DROPBOX_CLIENT_SECRET }} OAUTH_WALLETCONNECT_PROJECT_ID: ${{ secrets.OAUTH_WALLETCONNECT_PROJECT_ID }} OAUTH_WALLETCONNECT_SELF_PROXY: ${{ secrets.OAUTH_WALLETCONNECT_SELF_PROXY }} ENCRYPTION_KEY: ${{ secrets.ENCRYPTION_KEY }} JWT_SECRET: ${{ secrets.JWT_SECRET }} # 恢复配置文件 - name: Restore Wrangler Config if: always() run: | if [ -f wrangler.toml.bak ]; then mv wrangler.toml.bak wrangler.toml fi