From 03c4b5236fdb0a6f1090cd10073392fd8314530d Mon Sep 17 00:00:00 2001 From: phamnazage-jpg Date: Thu, 28 May 2026 10:13:13 +0800 Subject: [PATCH] chore(remote43): standardize stable crm repo root --- docs/DEPLOYMENT.md | 4 ++- docs/EXECUTION_BOARD.md | 6 +++- docs/PROJECT_STRUCTURE.md | 3 ++ docs/REAL_HOST_ACCEPTANCE_RUNBOOK.md | 5 ++++ scripts/README.md | 3 ++ scripts/deploy/remote43_patched_stack_lib.sh | 30 ++++++++++++++++--- .../deploy/setup_remote43_patched_stack.sh | 28 +++++++++++++++-- scripts/test/test_real_host_scripts.sh | 19 ++++++++++-- 8 files changed, 87 insertions(+), 11 deletions(-) diff --git a/docs/DEPLOYMENT.md b/docs/DEPLOYMENT.md index ad9f3524..439166c5 100644 --- a/docs/DEPLOYMENT.md +++ b/docs/DEPLOYMENT.md @@ -45,7 +45,7 @@ SUB2API_CRM_ADMIN_TOKEN=change-me-before-production SUB2API_CRM_LISTEN_ADDR=127. | `SUB2API_CRM_ADMIN_TOKEN` | 控制面 Bearer token | `crm-admin-token` | | `SUB2API_CRM_LISTEN_ADDR` | 监听地址 | `:18081` | | `SUB2API_CRM_SQLITE_DSN` | SQLite DSN | `file:/tmp/sub2api-cn-relay-manager.db?_foreign_keys=on&_busy_timeout=5000` | -| `SUB2API_CRM_REPO_ROOT` | provider 草稿发布到 pack/provider 文件时使用的仓库根目录 | `/home/ubuntu/sub2api-cn-relay-manager-git-20260528-bundle` | +| `SUB2API_CRM_REPO_ROOT` | provider 草稿发布到 pack/provider 文件时使用的仓库根目录 | `/home/ubuntu/sub2api-cn-relay-manager-git-current` | ## 公网 Portal 资产 @@ -93,6 +93,8 @@ SUB2API_CRM_ADMIN_TOKEN=change-me-before-production SUB2API_CRM_LISTEN_ADDR=127. - CRM 进程必须配置 `SUB2API_CRM_REPO_ROOT` - 该目录必须是真实 Git 仓库,而不是普通文件夹 +- remote43 当前推荐固定路径:`/home/ubuntu/sub2api-cn-relay-manager-git-current` +- 推荐由 `scripts/deploy/setup_remote43_patched_stack.sh` 统一准备,不要再手工生成带日期后缀的临时 repo 根目录 - 当前实现会原子完成: - 生成或更新 `packs//providers/.json` - bump `pack.json` patch 版本 diff --git a/docs/EXECUTION_BOARD.md b/docs/EXECUTION_BOARD.md index f92afc72..9f0c91d1 100644 --- a/docs/EXECUTION_BOARD.md +++ b/docs/EXECUTION_BOARD.md @@ -49,7 +49,11 @@ - 发布动作会把草稿 canonicalize 成完整 `pack.ProviderManifest` - 服务端会原子执行:写 `providers/.json`、bump `pack.json` patch 版本、更新 `checksums.txt`、重跑整包校验、`git add` + `git commit` - 运行前提新增:`SUB2API_CRM_REPO_ROOT` 必须指向**真实 Git 仓库** - - remote43 原本的 `/home/ubuntu/sub2api-cn-relay-manager` 只是普通目录,不带 `.git`;当前已改为指向基于本机 `git bundle` 拉起的真实 checkout:`/home/ubuntu/sub2api-cn-relay-manager-git-20260528-bundle` + - remote43 原本的 `/home/ubuntu/sub2api-cn-relay-manager` 只是普通目录,不带 `.git` + - 2026-05-28 已继续把这条路径收成正式部署约定: + - CRM 现在应统一指向 `/home/ubuntu/sub2api-cn-relay-manager-git-current` + - `scripts/deploy/setup_remote43_patched_stack.sh` 会自动生成并刷新该固定 checkout + - 这样 provider 草稿发布链不再依赖任何一次性的时间戳 repo 目录 - 公网 `providers.html` 已新增“发布到仓库”按钮与 commit message 输入框 - remote43 公网真验已通过: - `draft_id=draft_remote43_publish_smoke_1779924243` diff --git a/docs/PROJECT_STRUCTURE.md b/docs/PROJECT_STRUCTURE.md index a316ac18..ebcb4484 100644 --- a/docs/PROJECT_STRUCTURE.md +++ b/docs/PROJECT_STRUCTURE.md @@ -97,6 +97,9 @@ - `scripts/deploy/` - 部署与环境拉起脚本 - 例如 `build_local_image.sh`、`setup_remote43_patched_stack.sh`、`deploy_tksea_portal.sh` + - 其中 `setup_remote43_patched_stack.sh` 现会同步生成 remote43 固定仓库工作副本: + - `/home/ubuntu/sub2api-cn-relay-manager-git-current` + - 供 `SUB2API_CRM_REPO_ROOT` 与 provider 草稿发布链复用 - `scripts/acceptance/` - 真实宿主验收与证据处理脚本 - 例如 `real_host_acceptance.sh`、`import_remote43_provider.sh`、`check_deepseek_completion_split.sh` diff --git a/docs/REAL_HOST_ACCEPTANCE_RUNBOOK.md b/docs/REAL_HOST_ACCEPTANCE_RUNBOOK.md index d5632f68..f9f5dd88 100644 --- a/docs/REAL_HOST_ACCEPTANCE_RUNBOOK.md +++ b/docs/REAL_HOST_ACCEPTANCE_RUNBOOK.md @@ -84,6 +84,8 @@ bash ./scripts/deploy/setup_remote43_patched_stack.sh 脚本会: - 把本地 pack 镜像到 `/tmp/openai-cn-pack-` 并同步到 remote43 同路径 +- 把当前本地 `main` 分支打成 `git bundle`,并在 remote43 固定维护仓库工作副本: + - `/home/ubuntu/sub2api-cn-relay-manager-git-current` - 上传 patched 宿主二进制与当前 CRM server 二进制 - 在 remote43 拉起新的 Postgres / Redis / patched host - 在 remote43 启动独立 SQLite 的临时 CRM @@ -91,6 +93,9 @@ bash ./scripts/deploy/setup_remote43_patched_stack.sh - `local operator env file` - `local tunnel script` +说明: +- 以后 provider 草稿发布链默认依赖这个固定 repo 根,不再依赖人工创建的时间戳 checkout 目录。 + 后续按脚本输出执行: ```bash diff --git a/scripts/README.md b/scripts/README.md index a7ae7264..97a10fd1 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -12,6 +12,9 @@ - `build_local_image.sh` - `deploy_tksea_portal.sh` - `setup_remote43_patched_stack.sh` + - 其中 `setup_remote43_patched_stack.sh` 现会同时准备 remote43 上固定的 Git checkout 路径: + - `/home/ubuntu/sub2api-cn-relay-manager-git-current` + - 供 CRM `SUB2API_CRM_REPO_ROOT` 与 provider 草稿发布链共用 - `scripts/acceptance/` - 真实宿主验收、upstream 直探、artifact 安全化 - 例如: diff --git a/scripts/deploy/remote43_patched_stack_lib.sh b/scripts/deploy/remote43_patched_stack_lib.sh index ebb23c40..5d130ed5 100755 --- a/scripts/deploy/remote43_patched_stack_lib.sh +++ b/scripts/deploy/remote43_patched_stack_lib.sh @@ -72,14 +72,17 @@ render_remote43_crm_env() { local crm_port="$1" local sqlite_dsn="$2" local admin_token="$3" - local sqlite_dsn_q admin_token_q + local repo_root="${4:-}" + local sqlite_dsn_q admin_token_q repo_root_q printf -v sqlite_dsn_q '%q' "$sqlite_dsn" printf -v admin_token_q '%q' "$admin_token" + printf -v repo_root_q '%q' "$repo_root" cat </dev/null +if [[ -f "\$REMOTE_REPO_BUNDLE" ]]; then + if [[ -d "\$REMOTE_REPO_ROOT/.git" ]]; then + git -C "\$REMOTE_REPO_ROOT" fetch "\$REMOTE_REPO_BUNDLE" main + git -C "\$REMOTE_REPO_ROOT" reset --hard FETCH_HEAD + else + rm -rf "\$REMOTE_REPO_ROOT" + git clone "\$REMOTE_REPO_BUNDLE" "\$REMOTE_REPO_ROOT" + git -C "\$REMOTE_REPO_ROOT" checkout main + fi + git -C "\$REMOTE_REPO_ROOT" config user.name "Remote43 CRM" + git -C "\$REMOTE_REPO_ROOT" config user.email "remote43-crm@tksea.top" +fi + python3 - "\$HOST_ENV_FILE" "\$HOST_PORT" <<'PY' import json import pathlib diff --git a/scripts/deploy/setup_remote43_patched_stack.sh b/scripts/deploy/setup_remote43_patched_stack.sh index ca119e25..54c9d9ff 100755 --- a/scripts/deploy/setup_remote43_patched_stack.sh +++ b/scripts/deploy/setup_remote43_patched_stack.sh @@ -28,10 +28,13 @@ HOST_BINARY="${HOST_BINARY:-}" CRM_BINARY="${CRM_BINARY:-$ROOT_DIR/server}" PACK_DIR="${PACK_DIR:-$ROOT_DIR/packs/openai-cn-pack}" LOCAL_SHARED_PACK_DIR="${LOCAL_SHARED_PACK_DIR:-/tmp/openai-cn-pack-${STACK_NAME}}" +LOCAL_REPO_BUNDLE="${LOCAL_REPO_BUNDLE:-/tmp/sub2api-cn-relay-manager-main.bundle}" LOCAL_OPERATOR_ENV_FILE="${LOCAL_OPERATOR_ENV_FILE:-/tmp/remote43-patched-stack-${HOST_PORT}.env}" LOCAL_TUNNEL_SCRIPT="${LOCAL_TUNNEL_SCRIPT:-/tmp/remote43-patched-stack-${HOST_PORT}.tunnel.sh}" REMOTE_ROOT="${REMOTE_ROOT:-/home/ubuntu/${STACK_NAME}_${HOST_PORT}}" REMOTE_PACK_PATH="${REMOTE_PACK_PATH:-$LOCAL_SHARED_PACK_DIR}" +REMOTE_REPO_ROOT="${REMOTE_REPO_ROOT:-/home/ubuntu/sub2api-cn-relay-manager-git-current}" +REMOTE_REPO_BUNDLE="$REMOTE_ROOT/sub2api-cn-relay-manager.bundle" REMOTE_HOST_ENV_FILE="$REMOTE_ROOT/.env.host" REMOTE_CRM_ENV_FILE="$REMOTE_ROOT/.env.crm" REMOTE_BOOTSTRAP_FILE="$REMOTE_ROOT/bootstrap.sh" @@ -87,6 +90,19 @@ prepare_local_shared_pack() { cp -R "$PACK_DIR" "$LOCAL_SHARED_PACK_DIR" } +prepare_local_repo_bundle() { + case "$LOCAL_REPO_BUNDLE" in + /tmp/*) ;; + *) + die "LOCAL_REPO_BUNDLE must stay under /tmp, got: $LOCAL_REPO_BUNDLE" + ;; + esac + + mkdir -p "$(dirname "$LOCAL_REPO_BUNDLE")" + rm -f "$LOCAL_REPO_BUNDLE" + git -C "$ROOT_DIR" bundle create "$LOCAL_REPO_BUNDLE" main +} + write_local_tunnel_script() { cat > "$LOCAL_TUNNEL_SCRIPT" < "$crm_env_file" + "$CRM_ADMIN_TOKEN" \ + "$REMOTE_REPO_ROOT" > "$crm_env_file" render_remote43_bootstrap_script \ "$REMOTE_ROOT" \ "$REMOTE_HOST_ENV_FILE" \ @@ -174,12 +194,15 @@ main() { "$DB_NAME" \ "$HOST_PORT" \ "$CRM_PORT" \ - "$HOST_CONTAINER_PORT" > "$bootstrap_file" + "$HOST_CONTAINER_PORT" \ + "$REMOTE_REPO_ROOT" \ + "$REMOTE_REPO_BUNDLE" > "$bootstrap_file" chmod +x "$bootstrap_file" ssh_remote "mkdir -p $(printf '%q' "$REMOTE_ROOT") $(printf '%q' "$(dirname "$REMOTE_PACK_PATH")") && rm -rf $(printf '%q' "$REMOTE_PACK_PATH")" scp_remote "$HOST_BINARY" "$REMOTE:$REMOTE_HOST_BINARY" scp_remote "$CRM_BINARY" "$REMOTE:$REMOTE_CRM_BINARY" + scp_remote "$LOCAL_REPO_BUNDLE" "$REMOTE:$REMOTE_REPO_BUNDLE" scp_remote "$host_env_file" "$REMOTE:$REMOTE_HOST_ENV_FILE" scp_remote "$crm_env_file" "$REMOTE:$REMOTE_CRM_ENV_FILE" scp_remote "$bootstrap_file" "$REMOTE:$REMOTE_BOOTSTRAP_FILE" @@ -191,6 +214,7 @@ remote43 patched stack prepared remote host base: http://127.0.0.1:${HOST_PORT} remote crm base: http://127.0.0.1:${CRM_PORT} remote host env file: ${REMOTE_HOST_ENV_FILE} +remote repo root: ${REMOTE_REPO_ROOT} local operator env file: ${LOCAL_OPERATOR_ENV_FILE} local tunnel script: ${LOCAL_TUNNEL_SCRIPT} shared pack path: ${LOCAL_SHARED_PACK_DIR} diff --git a/scripts/test/test_real_host_scripts.sh b/scripts/test/test_real_host_scripts.sh index 17fd57d7..57ca5796 100755 --- a/scripts/test/test_real_host_scripts.sh +++ b/scripts/test/test_real_host_scripts.sh @@ -658,7 +658,7 @@ run_test_remote43_patched_stack_renderers() { local host_env crm_env bootstrap host_env="$(render_remote43_host_env "stack-pg" "stack-redis" "db-pass" "sub2api" "admin@sub2api.local" "admin-pass" "jwt-secret" "totp-secret")" - crm_env="$(render_remote43_crm_env "18143" "file:/tmp/sub2api.db?_foreign_keys=on" "crm-token")" + crm_env="$(render_remote43_crm_env "18143" "file:/tmp/sub2api.db?_foreign_keys=on" "crm-token" "/home/ubuntu/sub2api-cn-relay-manager-git-current")" bootstrap="$(render_remote43_bootstrap_script \ "/home/ubuntu/test-stack" \ "/home/ubuntu/test-stack/.env.host" \ @@ -680,7 +680,9 @@ run_test_remote43_patched_stack_renderers() { "sub2api" \ "18139" \ "18143" \ - "8080")" + "8080" \ + "/home/ubuntu/sub2api-cn-relay-manager-git-current" \ + "/home/ubuntu/test-stack/sub2api-cn-relay-manager.bundle")" assert_contains "$host_env" "AUTO_SETUP=true" assert_contains "$host_env" "DATABASE_HOST=stack-pg" @@ -688,23 +690,29 @@ run_test_remote43_patched_stack_renderers() { assert_contains "$crm_env" "SUB2API_CRM_LISTEN_ADDR=127.0.0.1:18143" assert_contains "$crm_env" "SUB2API_CRM_SQLITE_DSN=" assert_contains "$crm_env" "SUB2API_CRM_ADMIN_TOKEN=crm-token" + assert_contains "$crm_env" "SUB2API_CRM_REPO_ROOT=/home/ubuntu/sub2api-cn-relay-manager-git-current" local sourced_dsn sourced_dsn="$(bash -lc 'set -a; source /dev/stdin; set +a; printf "%s" "$SUB2API_CRM_SQLITE_DSN"' <<<"$crm_env")" [[ "$sourced_dsn" == "file:/tmp/sub2api.db?_foreign_keys=on" ]] || fail "crm env dsn did not survive bash source" assert_contains "$bootstrap" 'rm -f "$DATA_DIR/install.lock" "$DATA_DIR/config.yaml" "$DATA_DIR/.installed"' assert_contains "$bootstrap" '-v "$HOST_BINARY:/app/sub2api:ro"' assert_contains "$bootstrap" '-p "127.0.0.1:$HOST_PORT:$HOST_CONTAINER_PORT"' + assert_contains "$bootstrap" 'REMOTE_REPO_ROOT=/home/ubuntu/sub2api-cn-relay-manager-git-current' + assert_contains "$bootstrap" 'REMOTE_REPO_BUNDLE=/home/ubuntu/test-stack/sub2api-cn-relay-manager.bundle' + assert_contains "$bootstrap" 'git -C "$REMOTE_REPO_ROOT" fetch "$REMOTE_REPO_BUNDLE" main' + assert_contains "$bootstrap" 'git clone "$REMOTE_REPO_BUNDLE" "$REMOTE_REPO_ROOT"' assert_contains "$bootstrap" '/api/v1/auth/login' assert_contains "$bootstrap" '/healthz' assert_contains "$bootstrap" 'source "$1"; set +a; exec "$2"' } run_test_setup_remote43_patched_stack_dry_run() { - local tmpdir pack_dir shared_pack_dir host_bin crm_bin operator_env tunnel_script stdout_file ssh_key + local tmpdir pack_dir shared_pack_dir repo_bundle host_bin crm_bin operator_env tunnel_script stdout_file ssh_key tmpdir="$(mktemp -d)" trap 'rm -rf "$tmpdir"' RETURN pack_dir="$tmpdir/pack" shared_pack_dir="$tmpdir/shared-pack" + repo_bundle="$tmpdir/sub2api-cn-relay-manager-main.bundle" host_bin="$tmpdir/sub2api-patched" crm_bin="$tmpdir/server" operator_env="$tmpdir/operator.env" @@ -720,6 +728,8 @@ run_test_setup_remote43_patched_stack_dry_run() { printf '%s\n' 'dummy-key' > "$ssh_key" chmod +x "$host_bin" "$crm_bin" + git -C "$ROOT_DIR" bundle create "$repo_bundle" main >/dev/null + KEY="$ssh_key" \ REMOTE="ubuntu@example.com" \ STACK_NAME="test-stack" \ @@ -729,6 +739,7 @@ run_test_setup_remote43_patched_stack_dry_run() { CRM_BINARY="$crm_bin" \ PACK_DIR="$pack_dir" \ LOCAL_SHARED_PACK_DIR="$shared_pack_dir" \ + LOCAL_REPO_BUNDLE="$repo_bundle" \ LOCAL_OPERATOR_ENV_FILE="$operator_env" \ LOCAL_TUNNEL_SCRIPT="$tunnel_script" \ REMOTE_ROOT="/home/ubuntu/test-stack" \ @@ -746,11 +757,13 @@ run_test_setup_remote43_patched_stack_dry_run() { assert_contains "$stdout_text" "remote43 patched stack prepared" assert_contains "$stdout_text" "local operator env file: $operator_env" + assert_contains "$stdout_text" "remote repo root: /home/ubuntu/sub2api-cn-relay-manager-git-current" assert_contains "$stdout_text" "DRY_RUN: ssh -i $ssh_key" assert_contains "$operator_env_text" "CRM_BASE=http://127.0.0.1:18143" assert_contains "$operator_env_text" "HOST_BASE=http://127.0.0.1:18139" assert_contains "$operator_env_text" "PACK_PATH=$shared_pack_dir" assert_contains "$operator_env_text" "REMOTE_HOST_ENV_FILE=/home/ubuntu/test-stack/.env.host" + assert_contains "$operator_env_text" "REMOTE_REPO_ROOT=/home/ubuntu/sub2api-cn-relay-manager-git-current" assert_contains "$tunnel_text" "-L 18143:127.0.0.1:18143" assert_contains "$tunnel_text" "-L 18139:127.0.0.1:18139" }