set -euo pipefail cd /opt/im-admin/deploy/im-admin docker image inspect zyt/wecom-admin:before-knowledge-v3-20260916 >/dev/null test -f /home/ps/knowledge-v3-20260916/source-before.tar.gz docker compose stop knowledge-worker python3 - <<'PY' from pathlib import Path import tarfile,shutil root=Path('/opt/im-admin') with tarfile.open('/home/ps/knowledge-v3-20260916/source-before.tar.gz') as tf: for item in tf.getmembers(): if item.isfile(): target=(root/item.name).resolve() assert root in target.parents target.parent.mkdir(parents=True,exist_ok=True) with tf.extractfile(item) as source,target.open('wb') as output: shutil.copyfileobj(source,output) PY docker tag zyt/wecom-admin:before-knowledge-v3-20260916 zyt/wecom-admin:current # V2 cannot consume V3's pending candidate checkpoint. Keep worker stopped if one exists. pending=$(docker run --rm --network=none --mount type=bind,source=/opt/im-admin/deploy/im-admin/data,target=/data,readonly zyt/wecom-admin:before-knowledge-v3-20260916 python -c "import sqlite3,json; db=sqlite3.connect('file:/data/backend.db?mode=ro',uri=True); print(sum(bool(json.loads(r[0]).get('_pending')) for r in db.execute(\"SELECT state_json FROM knowledge_job WHERE status NOT IN ('completed','cancelled')\")))") if [ "$pending" = 0 ]; then docker compose up -d --no-build --wait --wait-timeout 180 api gateway knowledge-worker else docker compose up -d --no-build --wait --wait-timeout 180 api gateway echo 'Worker remains stopped to preserve pending V3 checkpoints. Redeploy V3 before processing jobs.' fi echo 'Previous services restored; live database retained.'