49 lines
2.3 KiB
Bash
49 lines
2.3 KiB
Bash
#!/usr/bin/env bash
|
|
# 替换 2 个后端文件、新增 2 个后端文件和 /m/ 前端、更新 Dockerfile;切换镜像,只重建 api 容器。
|
|
# 任何一步失败自动调用 rollback.sh。
|
|
set -euo pipefail
|
|
test "${REMOTE_RELEASE_APPROVED:-}" = mobile-remote-20260928
|
|
release=/home/ps/mobile-remote-20260928
|
|
cd "$release"
|
|
test -f candidate-passed
|
|
test -f backup.json
|
|
python3 remote_server_guard.py baseline
|
|
cd /opt/im-admin/deploy/im-admin
|
|
docker compose config --quiet
|
|
rollback_on_error() { rc=$?; trap - ERR; bash "$release/rollback.sh"; exit "$rc"; }
|
|
trap rollback_on_error ERR
|
|
python3 - <<'PY'
|
|
from pathlib import Path
|
|
import json, hashlib, os
|
|
r = Path('/home/ps/mobile-remote-20260928'); target = Path('/opt/im-admin')
|
|
plan = json.loads((r / 'release-plan.json').read_text())
|
|
reference = (target / 'wechat_rpa/admin_api.py').stat().st_mode & 0o777
|
|
rows = [row for row in json.loads((r / 'manifest.json').read_text()) if row['path'].startswith('payload/')]
|
|
frontend = plan['frontendDir']
|
|
# 前端整体先放临时目录,写完再一次性改名,外面看不到半套静态文件。
|
|
staging = target / (frontend + '.mobile-remote.tmp'); assert not staging.exists()
|
|
for row in rows:
|
|
rel = row['path'][len('payload/'):]
|
|
data = (r / row['path']).read_bytes(); assert hashlib.sha256(data).hexdigest() == row['sha256'], rel
|
|
if rel.startswith(frontend + '/'):
|
|
dest = staging / rel[len(frontend) + 1:]
|
|
dest.parent.mkdir(parents=True, exist_ok=True)
|
|
dest.write_bytes(data); os.chmod(dest, 0o644)
|
|
continue
|
|
dest = (target / rel).resolve(); assert dest.is_relative_to(target)
|
|
tmp = dest.with_name(dest.name + '.mobile-remote.tmp'); assert not tmp.exists()
|
|
with tmp.open('xb') as f:
|
|
f.write(data)
|
|
os.chmod(tmp, dest.stat().st_mode & 0o777 if dest.exists() else reference); os.replace(tmp, dest)
|
|
for directory in [staging] + [p for p in staging.rglob('*') if p.is_dir()]:
|
|
os.chmod(directory, 0o755)
|
|
final = target / frontend; assert not final.exists()
|
|
final.parent.mkdir(parents=True, exist_ok=True)
|
|
os.replace(staging, final)
|
|
PY
|
|
docker tag zyt/wecom-admin:mobile-remote-20260928 zyt/wecom-admin:current
|
|
docker compose up -d --no-deps --no-build --wait --wait-timeout 180 api
|
|
bash "$release/04-verify.sh"
|
|
trap - ERR
|
|
printf '%s\n' 'Mobile remote console deployed and verified.'
|