143 lines
4.2 KiB
Markdown
143 lines
4.2 KiB
Markdown
# Production Deployment
|
|
|
|
Use this runbook only after a target host has passed the zero-to-running
|
|
bootstrap and staging gate.
|
|
|
|
## Inputs
|
|
|
|
- clean repository snapshot;
|
|
- active validated profile for the target runtime user;
|
|
- configured production Python;
|
|
- operator-provided SSH alias and local privilege elevation;
|
|
- ready WeChat main window on display `:1`.
|
|
|
|
Do not place hostnames, addresses, usernames, passwords, private keys, or
|
|
profile values in the repository or command history.
|
|
|
|
## Local Gate
|
|
|
|
```sh
|
|
PATH="$PWD/.venv/bin:$PATH" ./tools/check-local.sh
|
|
./tools/check-secrets.py --history
|
|
```
|
|
|
|
## Staging
|
|
|
|
Transfer a clean snapshot without `.git`, local profiles, virtualenvs, debug
|
|
state, captures, databases, or archives. On the target:
|
|
|
|
```sh
|
|
JWEBOT_RUNTIME_PYTHON=/opt/jwebot/venv/bin/python \
|
|
PATH="/opt/jwebot/venv/bin:$PATH" \
|
|
./tools/check-local.sh
|
|
```
|
|
|
|
Verify the active profile:
|
|
|
|
```sh
|
|
/opt/jwebot/venv/bin/python -m jwebot_config status
|
|
/opt/jwebot/venv/bin/python -m jwebot_config validate <profile>
|
|
```
|
|
|
|
## Pre-Cutover
|
|
|
|
Confirm:
|
|
|
|
1. WeChat main window is visible and meets minimum geometry.
|
|
2. Edge and adaptive recorder are active with stable restart counts.
|
|
3. Adaptive and legacy OCR queues are empty.
|
|
4. Edge direct/cloud outboxes have no failed backlog.
|
|
5. Edge SQLite `quick_check` is `ok`.
|
|
6. Legacy OCR services are disabled and inactive.
|
|
7. A restorable baseline exists.
|
|
|
|
## Coordinated Cutover
|
|
|
|
Elevate locally on the target and run:
|
|
|
|
```sh
|
|
JWEBOT_RUNTIME_PYTHON=/opt/jwebot/venv/bin/python \
|
|
./deploy/scripts/deploy-jwebot-production.sh \
|
|
/path/to/staged/JWeBot \
|
|
jwebot
|
|
```
|
|
|
|
The deployer prints an eight-stage progress bar and:
|
|
|
|
- records root and user service topology;
|
|
- copies root and user runtime files;
|
|
- backs up generated configuration;
|
|
- creates a SQLite online backup and runs `quick_check`;
|
|
- refuses non-empty queues or an unready WeChat window;
|
|
- installs the runtime;
|
|
- leaves legacy OCR disabled;
|
|
- verifies Edge health and adaptive restart stability;
|
|
- writes and verifies backup SHA-256 checksums;
|
|
- rolls back files, state, and unit topology on cutover failure;
|
|
- after rollback is disarmed, grants each existing account 200 Mora, records a
|
|
version-labelled movement, and sends the guarded group update announcement.
|
|
|
|
The first bullet in the current `CHANGELOG.md` release section is the canonical
|
|
one-sentence announcement summary. Keep it concise and user-facing.
|
|
|
|
## Post-Cutover
|
|
|
|
```sh
|
|
systemctl --user is-active jwebot-edge.service
|
|
systemctl --user is-active wechat-ocr-adaptive-recorder.service
|
|
systemctl --user show wechat-ocr-adaptive-recorder.service \
|
|
-p NRestarts --value
|
|
```
|
|
|
|
```sh
|
|
printf '%s\n' '{"op":"health"}' |
|
|
/opt/jwebot/venv/bin/python \
|
|
~/.local/lib/wechat-health-watch/jwebot_edge.py respond
|
|
```
|
|
|
|
```sh
|
|
/opt/jwebot/venv/bin/python - <<'PY'
|
|
import sqlite3
|
|
from pathlib import Path
|
|
|
|
path = Path.home() / ".local/state/jwebot-edge/edge.sqlite3"
|
|
print(sqlite3.connect(f"file:{path}?mode=ro", uri=True)
|
|
.execute("pragma quick_check").fetchone()[0])
|
|
PY
|
|
```
|
|
|
|
Player-visible acceptance must use deliberate synthetic messages in the
|
|
configured group and confirm exactly one ACK and one final response.
|
|
|
|
The deployer also runs the installed release settlement tool. Its successful
|
|
JSON result must report the expected account count and announcement delivery.
|
|
The operation is idempotent by the full release string, so rerunning the same
|
|
command never grants Mora twice:
|
|
|
|
```sh
|
|
/opt/jwebot/venv/bin/python \
|
|
~/.local/lib/wechat-health-watch/jwebot_release_update.py
|
|
```
|
|
|
|
If it reports `AnnouncementUncertainError`, inspect the configured group first.
|
|
Only when the announcement is confirmed absent may the operator retry:
|
|
|
|
```sh
|
|
/opt/jwebot/venv/bin/python \
|
|
~/.local/lib/wechat-health-watch/jwebot_release_update.py \
|
|
--retry-uncertain-announcement
|
|
```
|
|
|
|
Do not repeat the full deployment to repair an uncertain announcement. The
|
|
runtime cutover and version-keyed compensation may already be complete.
|
|
|
|
## Rollback
|
|
|
|
If any gate fails:
|
|
|
|
1. stop further cutover attempts;
|
|
2. verify the coordinated deployer's rollback result;
|
|
3. confirm unit topology and SQLite integrity;
|
|
4. archive privacy-safe evidence under the active profile;
|
|
5. fix and rerun staging before another production attempt.
|