#!/usr/bin/env bash # wiki 同搬通道 5 文档验收脚本(本地模拟生产 = 测试服 weknora-test-v071) # 用法:bash scripts/wiki_e2e_test5.sh # 前置:三条 ssh 隧道(172.17.0.1:25432/29200/28080)已起,dist/release-channel-e2e 已构建 set -uo pipefail cd "$(dirname "$0")/.." REPO=$PWD KB=c12ff4d5-dd87-423b-ab0f-af745b9d54a7 WK=http://127.0.0.1:8080 CFG=/run/release-sim/release.sim.json DIST=$REPO/dist/release-channel-e2e api() { curl -s -K /tmp/wk_curl.cfg "$@"; } prod_sql() { docker run --rm --network host --env-file /tmp/target_pg.env postgres:16-alpine psql -At -P pager=off -c "$1"; } prod_es_count() { # 用 keyword 子字段精确匹配(knowledge_id 是 text 字段,UUID 会被分词) curl -s "http://172.17.0.1:29200/weknora_test_chunks/_count" -H 'Content-Type: application/json' \ -d "{\"query\":{\"bool\":{\"filter\":[{\"term\":{\"knowledge_id.keyword\":\"$1\"}},{\"term\":{\"is_enabled\":true}}]}}}" \ | python3 -c "import sys,json;print(json.load(sys.stdin).get('count'))" } release() { # release docker run --rm --user "$(id -u):$(id -g)" \ --network knowledge-governance-p1_default --network weknora071full-network \ --add-host prod-pg:host-gateway --add-host prod-es:host-gateway --add-host prod-weknora:host-gateway \ -v "$REPO/secrets/release-sim":/run/release-secrets:ro \ -v "$REPO/config/release.sim.json":/run/release-sim/release.sim.json:ro \ -v knowledge-governance-release-bundles:/var/lib/knowledge-governance/release-bundles \ -v "$DIST":/release-channel-e2e:ro \ --entrypoint /release-channel-e2e knowledge-governance-p1-release-worker:latest \ -config "$CFG" -knowledge "$1" -mode "$2" -revision "$3" 2>&1 | grep -E "STEP|bundle|wiki (before|after)|route kb" } echo "### 1. 上传 4 篇同主题文档(与首篇共贡 wiki 页)" write_doc() { cat > "/tmp/wiki_e2e_$1.md"; } write_doc b <<'EOF' # 来源与目录:停止知识的语义 知识治理平台在“来源与目录”视图里可以停止某条知识。停止的含义是:生产端不再检索它。 需要注意,停止不会改动测试端 WeKnora 的 wiki:只有删除文档才会触发 wiki 清理链。 因此 wiki 快照在撤权时由发布通道负责剥离该文档的贡献。 EOF write_doc c <<'EOF' # 发布通道之 PostgreSQL 与 Elasticsearch 发布通道把知识治理平台评审通过的知识写进生产端 WeKnora。 PostgreSQL 负责关系行:knowledges、chunks、knowledge_tags、resources。 Elasticsearch 负责检索分片与向量,索引名称为 weknora_test_chunks。 撤权时 Elasticsearch 通过 delete-by-query 清空该文档分片。 EOF write_doc d <<'EOF' # 发布通道之 OSS 对象与图片资源 文档里的图片与附件存放在对象存储 OSS。发布时先写入暂存路径,再用 CopyObject 拷到生产桶。 resources 表保存 storage:// 定位符,搬运时只替换桶名。 知识治理平台与测试端 WeKnora、生产端 WeKnora 共用同一套对象通道实现。 EOF write_doc e <<'EOF' # 撤权与回滚演练 撤权(withdraw)会把生产端知识置为 disabled 并清空检索分片,同时重放 wiki 快照。 回滚(rollback)会整包还原上一版 revision,包括 wiki 快照。 因此生产端 WeKnora 永远不会出现“检索没了、wiki 还在”的中间态。 EOF for k in b c d e; do id=$(api -X POST -F "file=@/tmp/wiki_e2e_$k.md" -F "fileName=wiki-e2e-$k.md" "$WK/api/v1/knowledge-bases/$KB/knowledge/file" | python3 -c "import sys,json;print(json.load(sys.stdin)['data']['id'])") echo "doc $k -> $id" printf '%s\n' "$id" > "/tmp/wiki_e2e_id_$k" done echo "### 2. 等 5 篇全部收敛(parse=completed 且 wiki 子任务为 0)" for i in $(seq 1 40); do pending=$(docker exec WKNFull-postgres psql -U weknora -d weknora_full -At -c "select count(*) from knowledges where knowledge_base_id='$KB' and deleted_at is null and (parse_status <> 'completed' or pending_subtasks_count > 0)") total=$(docker exec WKNFull-postgres psql -U weknora -d weknora_full -At -c "select count(*) from knowledges where knowledge_base_id='$KB' and deleted_at is null") pages=$(docker exec WKNFull-postgres psql -U weknora -d weknora_full -At -c "select count(*) from wiki_pages where knowledge_base_id='$KB' and deleted_at is null") echo " [$i] docs=$total 未收敛=$pending wiki_pages=$pages" [ "$total" -ge 5 ] && [ "$pending" = "0" ] && break sleep 20 done echo "### 3. 逐篇发布(每次发布会推整库 wiki 快照)" i=0 for id in $(cat /tmp/wiki_e2e_id_b) 9be3e0fa-e699-4a8e-be0c-0d934ee33294 $(cat /tmp/wiki_e2e_id_c) $(cat /tmp/wiki_e2e_id_d) $(cat /tmp/wiki_e2e_id_e); do i=$((i+1)) echo "--- publish #$i $id" release "$id" publish "wiki-e2e-5doc-p$i" | tail -4 done echo "### 4. 生产端证据(5 篇)" prod_sql "select 'enabled='||count(*) filter (where enable_status='enabled')||' total='||count(*) from knowledges where knowledge_base_id='$KB'" prod_sql "select 'wiki_pages='||(select count(*) from wiki_pages where knowledge_base_id='$KB')||' wiki_folders='||(select count(*) from wiki_folders where knowledge_base_id='$KB')" echo "共贡页面(source_refs 多于一条):" prod_sql "select slug||' <- '||source_refs::text from wiki_pages where knowledge_base_id='$KB' and jsonb_array_length(coalesce(source_refs,'[]'::jsonb)) > 1 order by slug limit 8" for id in $(cat /tmp/wiki_e2e_id_b) $(cat /tmp/wiki_e2e_id_c) 9be3e0fa-e699-4a8e-be0c-0d934ee33294; do echo " ES $id count=$(prod_es_count "$id")" done echo "### 5. 撤权其中一篇(doc b),验证共贡页面保留、专属页面消失、其它文档不受影响" release "$(cat /tmp/wiki_e2e_id_b)" withdraw "wiki-e2e-5doc-w1" | tail -5 echo "--- 生产端证据(撤权后)" prod_sql "select id||' enable='||enable_status from knowledges where knowledge_base_id='$KB' order by enable_status, id" prod_sql "select 'wiki_pages='||count(*) from wiki_pages where knowledge_base_id='$KB'" prod_sql "select 'folders='||count(*) from wiki_folders where knowledge_base_id='$KB'" echo "还有引用被撤权文档的页面(应为 0):" prod_sql "select count(*) from wiki_pages where knowledge_base_id='$KB' and source_refs::text like '%$(cat /tmp/wiki_e2e_id_b)%'" echo "共贡页面是否仍在:" prod_sql "select slug||' <- '||source_refs::text from wiki_pages where knowledge_base_id='$KB' and jsonb_array_length(coalesce(source_refs,'[]'::jsonb)) > 0 order by slug limit 8" echo "ES 分片:" for id in $(cat /tmp/wiki_e2e_id_b) $(cat /tmp/wiki_e2e_id_c); do echo " $id count=$(prod_es_count "$id")"; done