#!/usr/bin/env bash # =========================================================================== # artalk-cf 一键部署(第 2~8 步) # # 前置:已经跑过 `npx wrangler login` # 用法: # export ADMIN_PASSWORD='你的后台密码' # bash tools/deploy.sh # # 可选环境变量: # TOKEN_SECRET 不传则自动生成随机串 # DB_NAME 默认 artalk-cf # SKIP_IMPORT=1 跳过数据导入 # =========================================================================== set -euo pipefail cd "$(dirname "$0")/.." DB_NAME="${DB_NAME:-artalk-cf}" WR="node node_modules/wrangler/bin/wrangler.js" if [ ! -f node_modules/wrangler/package.json ]; then echo "缺少依赖,先跑:npm install" >&2 exit 1 fi if [ -z "${ADMIN_PASSWORD:-}" ]; then echo "请先设置管理员密码:export ADMIN_PASSWORD='...'" >&2 exit 1 fi echo "==> 1/8 检查登录状态" # 兼容三种情况:OAuth 登录、作用域 Token(cfut_)、账户 Token(cfat_) WHOAMI=$($WR whoami 2>&1 || true) if ! printf '%s' "$WHOAMI" | grep -qiE 'associated with the email|Account Name|Account ID|accounts'; then echo "$WHOAMI" | tail -5 echo echo "没检测到可用的凭据。二选一:" >&2 echo " a) 交互登录: npx wrangler login" >&2 echo " b) 用作用域 Token: export CLOUDFLARE_API_TOKEN='cfut_...'(可再加 CLOUDFLARE_ACCOUNT_ID)" >&2 exit 1 fi echo "$WHOAMI" | grep -iE 'Account Name|Account ID|associated with' | head -4 | sed 's/^/ /' echo "==> 2/8 创建 D1 数据库(已存在则复用)" DB_ID=$($WR d1 list --json 2>/dev/null \ | node -e "let s='';process.stdin.on('data',d=>s+=d).on('end',()=>{try{const a=JSON.parse(s);const m=a.find(x=>x.name===process.argv[1]);if(m)console.log(m.uuid)}catch{}})" "$DB_NAME") if [ -z "$DB_ID" ]; then OUT=$($WR d1 create "$DB_NAME" 2>&1) echo "$OUT" DB_ID=$(printf '%s' "$OUT" | grep -oE '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}' | head -1) fi if [ -z "$DB_ID" ]; then echo "拿不到 database_id,请手动去控制台复制后填进 wrangler.toml" >&2 exit 1 fi echo " database_id = $DB_ID" echo "==> 3/8 写入 wrangler.toml" node -e " const fs=require('fs'); const p='wrangler.toml'; let s=fs.readFileSync(p,'utf8'); const before=s; s=s.replace(/database_id\s*=\s*\"[^\"]*\"/, 'database_id = \"' + process.argv[1] + '\"'); s=s.replace(/database_name\s*=\s*\"[^\"]*\"/, 'database_name = \"' + process.argv[2] + '\"'); if(s===before){console.error('wrangler.toml 里没找到 database_id,请手动填');process.exit(1);} fs.writeFileSync(p,s); console.log(' ok'); " "$DB_ID" "$DB_NAME" echo "==> 4/8 写入机密" TOKEN_SECRET="${TOKEN_SECRET:-$(node -e "console.log(require('crypto').randomBytes(48).toString('base64url'))")}" printf '%s' "$TOKEN_SECRET" | $WR secret put TOKEN_SECRET printf '%s' "$ADMIN_PASSWORD" | $WR secret put ADMIN_PASSWORD echo "==> 5/8 建表" $WR d1 execute "$DB_NAME" --remote -y --file=./schema.sql echo "==> 6/8 部署" DEPLOY_OUT=$($WR deploy 2>&1 | tee /dev/stderr) BASE=$(printf '%s' "$DEPLOY_OUT" \ | grep -oE 'https://[A-Za-z0-9._-]+\.workers\.dev' | head -1) if [ -z "$BASE" ]; then read -r -p "请手动粘贴部署输出里的地址(如 https://artalk-cf.xxx.workers.dev): " BASE fi BASE="${BASE%/}" echo " BASE = $BASE" echo "==> 7/8 导入评论数据(必须在初始化管理员之前——导入会清空 users 表)" if [ "${SKIP_IMPORT:-}" != "1" ]; then if command -v python >/dev/null 2>&1; then python tools/import_artrans.py else python3 tools/import_artrans.py fi bash tools/import-out/run.sh --remote else echo " (SKIP_IMPORT=1,跳过)" fi echo "==> 8/8 初始化站点与管理员" curl -sS -X POST "$BASE/api/v2/setup" -H 'Content-Type: application/json' -d '{}' echo echo echo "============================================================" echo " 完成。接下来:" echo " 1) 验证:bash tools/smoke.sh $BASE" echo " 2) 域名:见 部署清单.md 第 9 步(NS 必须在 Cloudflare)" echo " 3) 切博客:hugo.toml 的 [params.artalk] server = $BASE" echo "============================================================"