#!/usr/bin/env bash # Test, then replace the Python MCP host checkout on ns1. # Does not restart verae-mcp-timestamping (the live listener is the Go binary), # verae-timestamping-svc, or forgejo-runner, and does not read secret files. set -euo pipefail LOCK="${LOCK:-/tmp/verae-mcp-py-deploy.lock}" DEST="${DEST:-/opt/verae/verae-mcp-timestamping-server}" BACKUP_ROOT="${BACKUP_ROOT:-/SSD2/verae-deploy-backups}" ROOT="$(cd "$(dirname "$0")/.." && pwd)" SCHEMA_FILE="src/verae_mcp_timestamping_server/metadata_history.py" mkdir -p "$(dirname "$LOCK")" exec 9>"$LOCK" if ! flock -w 900 9; then echo "another python mcp deploy holds the lock" >&2 exit 1 fi prepare_cache() { sudo mkdir -p "$BACKUP_ROOT" sudo chmod 1777 "$BACKUP_ROOT" sudo mkdir -p "$BACKUP_ROOT/uv-cache-$USER" sudo chown "$USER:$USER" "$BACKUP_ROOT/uv-cache-$USER" export UV_CACHE_DIR="$BACKUP_ROOT/uv-cache-$USER" export UV_LINK_MODE=copy } run_tests() { prepare_cache cd "$ROOT" uv sync --frozen --group dev uv run pytest -q if ! grep -q 'verae-meta-git/1' "$SCHEMA_FILE"; then echo "checkout is missing verae-meta-git/1" >&2 exit 1 fi } probe_tree() { local tree="$1" grep -q 'verae-meta-git/1' "$tree/$SCHEMA_FILE" sudo -u verae-mcp env HOME=/var/lib/verae-mcp \ "$tree/.venv/bin/python" -c 'import verae_mcp_timestamping_server.metadata_history as m; assert m.SCHEMA == "verae-meta-git/1"' } install_tree() { local stage previous ts sha ts="$(date -u +%Y%m%dT%H%M%SZ)" sha="$(git -C "$ROOT" rev-parse HEAD)" stage="$(mktemp -d "$BACKUP_ROOT/py-mcp-stage.XXXXXX")" sudo rsync -a \ --exclude '.git/' \ --exclude '.venv/' \ --exclude '__pycache__/' \ --exclude '.pytest_cache/' \ --exclude 'debug-trace/' \ "$ROOT/" "$stage/" printf '%s\n' "$sha" | sudo tee "$stage/DEPLOYED_SHA" >/dev/null if [[ -d "$DEST/.venv" ]]; then sudo mv "$DEST/.venv" "$stage/.venv" fi sudo chown -R verae-mcp:verae-mcp "$stage" sudo mkdir -p "$BACKUP_ROOT/uv-cache-verae-mcp" sudo chown verae-mcp:verae-mcp "$BACKUP_ROOT/uv-cache-verae-mcp" if ! sudo -u verae-mcp env HOME=/var/lib/verae-mcp UV_CACHE_DIR="$BACKUP_ROOT/uv-cache-verae-mcp" UV_LINK_MODE=copy \ uv sync --frozen --group dev --directory "$stage"; then sudo rm -rf "$stage" echo "uv sync failed" >&2 return 1 fi if ! probe_tree "$stage"; then sudo rm -rf "$stage" echo "staged python checkout failed probe" >&2 return 1 fi previous="" if [[ -d "$DEST" ]]; then previous="$BACKUP_ROOT/py-mcp-src-${ts}" sudo mv "$DEST" "$previous" fi if ! sudo mv "$stage" "$DEST"; then if [[ -n "$previous" ]]; then sudo mv "$previous" "$DEST" fi echo "could not move the python checkout into place" >&2 return 1 fi sudo chown -R verae-mcp:verae-mcp "$DEST" echo "deployed ${ts} ${sha} checkout probe ok" } run_tests if [[ "${1:-}" == "--test-only" ]]; then echo "tests ok" exit 0 fi install_tree