Add optional Cosmos/Engine-X/act-runner templates, CWUSDC/EI-matrix tooling, non-EVM route planner in multi-chain-execution (tests passing), token list and extraction updates, and documentation (MetaMask matrix, GRU/CWUSDC packets). Ignore institutional evidence tarballs/sha256 under reports/status. Validated with: bash scripts/verify/run-all-validation.sh --skip-genesis Co-authored-by: Cursor <cursoragent@cursor.com>
155 lines
4.8 KiB
Bash
Executable File
155 lines
4.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# One-way sync: local workstation project tree → Dev VM (5700) /srv/projects
|
|
# for coordinated development over SSH (Cursor Remote-SSH, shared tree).
|
|
#
|
|
# Prerequisites:
|
|
# - CT 5700 exists, ssh dev1@IP_DEV_VM works, /srv/projects is writable (see setup-dev-vm-users-and-gitea.sh).
|
|
# - Run from a machine that has your local clone (default: ~/projects).
|
|
#
|
|
# Usage:
|
|
# ./scripts/deployment/sync-local-projects-to-dev-vm.sh --dry-run
|
|
# ./scripts/deployment/sync-local-projects-to-dev-vm.sh
|
|
# ./scripts/deployment/sync-local-projects-to-dev-vm.sh --delete-remote # mirror: remove remote files absent locally
|
|
# RSYNC_RSH='ssh -o ProxyCommand="cloudflared access ssh --hostname ssh.dev.d-bis.org"' \
|
|
# DEV_VM_HOST=ssh.dev.d-bis.org ./scripts/deployment/sync-local-projects-to-dev-vm.sh
|
|
#
|
|
# Env:
|
|
# SOURCE — local directory (default: ~/projects)
|
|
# DEV_VM_USER — SSH user on dev VM (default: dev1)
|
|
# DEV_VM_HOST — override IP/hostname (default: IP_DEV_VM from config)
|
|
# DEV_VM_PROJECTS — remote path (default: /srv/projects)
|
|
# RSYNC_EXTRA_OPTS — extra rsync args (quoted string)
|
|
# RSYNC_RSH — passed to rsync as SSH transport (e.g. cloudflared ProxyCommand)
|
|
#
|
|
# If --delete-remote fails with rsync code 23 (Permission denied on delete), run:
|
|
# ./scripts/deployment/fix-dev-vm-srv-projects-ownership.sh
|
|
# See: docs/04-configuration/DEV_VM_WORKSTATION_MIGRATION_RUNBOOK.md
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
|
# shellcheck source=/dev/null
|
|
source "${PROJECT_ROOT}/scripts/lib/load-project-env.sh" 2>/dev/null || true
|
|
# shellcheck source=/dev/null
|
|
source "${PROJECT_ROOT}/config/ip-addresses.conf" 2>/dev/null || true
|
|
|
|
SOURCE="${SOURCE:-${HOME}/projects}"
|
|
DEV_VM_USER="${DEV_VM_USER:-dev1}"
|
|
DEV_VM_HOST="${DEV_VM_HOST:-${IP_DEV_VM:-192.168.11.59}}"
|
|
DEV_VM_PROJECTS="${DEV_VM_PROJECTS:-/srv/projects}"
|
|
RSYNC_EXTRA_OPTS="${RSYNC_EXTRA_OPTS:-}"
|
|
|
|
DRY_RUN=()
|
|
DELETE_REMOTE=0
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--dry-run) DRY_RUN=(-n); shift ;;
|
|
--delete-remote) DELETE_REMOTE=1; shift ;;
|
|
--help|-h)
|
|
sed -n '1,35p' "$0" | tail -n +2
|
|
exit 0
|
|
;;
|
|
*)
|
|
echo "ERROR: unknown argument: $1 (try --help)" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
if [[ ! -d "$SOURCE" ]]; then
|
|
echo "ERROR: SOURCE is not a directory: $SOURCE" >&2
|
|
exit 1
|
|
fi
|
|
|
|
REMOTE="${DEV_VM_USER}@${DEV_VM_HOST}:${DEV_VM_PROJECTS}/"
|
|
|
|
RSYNC_DELETE=()
|
|
if [[ "$DELETE_REMOTE" == "1" ]]; then
|
|
RSYNC_DELETE=(--delete-delay)
|
|
echo "WARNING: --delete-remote — files on Dev VM under DEST not present locally (after excludes) will be REMOVED."
|
|
echo ""
|
|
else
|
|
echo "Safe mode: no remote delete (omit files only on VM). Use --delete-remote to mirror (destructive)."
|
|
echo ""
|
|
fi
|
|
|
|
echo "=== Sync local projects → Dev VM ==="
|
|
echo "SOURCE: $SOURCE"
|
|
echo "DEST: $REMOTE"
|
|
echo "Mode: ${DRY_RUN[*]:-live}"
|
|
if [[ -n "${RSYNC_RSH:-}" ]]; then
|
|
echo "RSYNC_RSH: set (custom SSH / cloudflared)"
|
|
fi
|
|
echo ""
|
|
echo "NOTE: Review secrets after sync — chmod 600 remote .env; share only with trusted dev users."
|
|
echo ""
|
|
|
|
# Heavy / reproducible artifacts (keep .git; omit bulky caches)
|
|
RSYNC_EXCLUDES=(
|
|
--exclude=node_modules
|
|
--exclude=__pycache__
|
|
--exclude=.pnpm-store
|
|
--exclude=.pnpm
|
|
--exclude=venv
|
|
--exclude=.venv
|
|
--exclude=.venv-*
|
|
--exclude=dist
|
|
--exclude=build
|
|
--exclude=.next
|
|
--exclude=out
|
|
--exclude=.turbo
|
|
--exclude=.cache
|
|
--exclude=.parcel-cache
|
|
--exclude=coverage
|
|
--exclude=.pytest_cache
|
|
--exclude=.mypy_cache
|
|
--exclude=.ruff_cache
|
|
--exclude=forge-cache
|
|
--exclude=artifacts
|
|
--exclude=broadcast
|
|
--exclude=tmp
|
|
--exclude=.tmp
|
|
--exclude=.codex-artifacts
|
|
)
|
|
|
|
# Optional: skip known multi-GB trees (re-clone or sync later with --no-skip-large)
|
|
if [[ "${SKIP_LARGE_LOCAL_TREES:-1}" == "1" ]]; then
|
|
RSYNC_EXCLUDES+=(
|
|
--exclude=MEV_Bot
|
|
--exclude=the-order
|
|
)
|
|
echo "SKIP_LARGE_LOCAL_TREES=1: excluding MEV_Bot, the-order (set SKIP_LARGE_LOCAL_TREES=0 to include)."
|
|
echo ""
|
|
fi
|
|
|
|
if [[ -n "${RSYNC_RSH:-}" ]]; then
|
|
export RSYNC_RSH
|
|
else
|
|
unset RSYNC_RSH 2>/dev/null || true
|
|
fi
|
|
|
|
set -x
|
|
# shellcheck disable=SC2086
|
|
set +e
|
|
rsync -av "${DRY_RUN[@]}" "${RSYNC_DELETE[@]}" --omit-dir-times \
|
|
"${RSYNC_EXCLUDES[@]}" \
|
|
${RSYNC_EXTRA_OPTS} \
|
|
"${SOURCE}/" "${REMOTE}"
|
|
rsync_ec=$?
|
|
set -e
|
|
set +x
|
|
|
|
if [[ "$rsync_ec" -ne 0 ]]; then
|
|
echo "" >&2
|
|
echo "ERROR: rsync exited with code $rsync_ec." >&2
|
|
if [[ "$rsync_ec" -eq 23 && "$DELETE_REMOTE" == "1" ]]; then
|
|
echo " Common cause: root-owned files on the VM block deletes. From repo root (Proxmox root SSH to the node that runs CT 5700):" >&2
|
|
echo " ./scripts/deployment/fix-dev-vm-srv-projects-ownership.sh" >&2
|
|
fi
|
|
exit "$rsync_ec"
|
|
fi
|
|
|
|
echo ""
|
|
echo "Done. Next: SSH to dev VM, open /srv/projects/proxmox in Cursor (Remote-SSH), run pnpm/npm install where needed."
|