Files
wehub-resource-sync 91e75e620b
CI: cua-driver distro-compat matrix / debian:12 (glibc 2.36) (push) Has been cancelled
CI: SPDX Headers / Check SPDX headers (warn-only) (push) Has been cancelled
CD: Docs MCP Server / build (linux/amd64) (push) Has been cancelled
CD: Docs MCP Server / build (linux/arm64) (push) Has been cancelled
CD: Docs MCP Server / merge (push) Has been cancelled
CI: cua-driver distro-compat matrix / Resolve release version (push) Has been cancelled
CI: cua-driver distro-compat matrix / fedora:41 (glibc 2.40) (push) Has been cancelled
CI: cua-driver distro-compat matrix / rockylinux:9 (glibc 2.34) (push) Has been cancelled
CI: cua-driver distro-compat matrix / ubuntu:22.04 (glibc 2.35) (push) Has been cancelled
CI: cua-driver distro-compat matrix / ubuntu:24.04 (glibc 2.39) (push) Has been cancelled
CI: cua-driver distro-compat matrix / Distro compat summary (push) Has been cancelled
CI: Rust Linux unit / Rust Linux unit and compile (push) Has been cancelled
CI: Rust Windows unit / Rust Windows unit and compile (push) Has been cancelled
CI: Nix Linux Rust source / Nix / compositor build (push) Has been cancelled
CI: Nix Linux Rust source / Nix / driver package (push) Has been cancelled
CI: Nix Linux Rust source / Nix / Rust unit tests (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:03:19 +08:00

205 lines
5.7 KiB
Bash
Executable File

#!/usr/bin/env bash
# Sync this host checkout to verification VMs and pull logs/artifacts back.
#
# Source changes should flow from this host to VMs. The guarded pull-code mode
# exists only for recovering intentional VM-side edits.
set -euo pipefail
usage() {
cat <<'USAGE'
Usage:
sync-vm-worktree.sh push <ssh-target> [remote-dir]
sync-vm-worktree.sh pull-artifacts <ssh-target> [remote-dir]
ALLOW_PULL_CODE=1 sync-vm-worktree.sh pull-code <ssh-target> [remote-dir]
Modes:
push
Sync this host checkout to a VM. This is the normal way to update Linux
and Windows verification machines.
pull-artifacts
Pull VM logs/artifacts from <remote-dir>/vm-out into this host checkout.
pull-code
Pull source changes made on a VM back to this host checkout. This is
intentionally gated by ALLOW_PULL_CODE=1 because this host is the only
checkout that should commit or push.
Environment:
REMOTE_ARTIFACT_DIR Remote artifact directory, relative to remote-dir.
Default: vm-out
RSYNC_SSH SSH command for rsync. Default: ssh
SYNC_TRANSPORT rsync or tar. Default: rsync
REMOTE_OS posix or windows. Only needed for tar push mkdir.
Default: posix
USAGE
}
if [[ $# -lt 2 || $# -gt 3 ]]; then
usage >&2
exit 2
fi
mode="$1"
target="$2"
remote_dir="${3:-~/cua}"
remote_artifact_dir="${REMOTE_ARTIFACT_DIR:-vm-out}"
rsync_ssh="${RSYNC_SSH:-ssh}"
transport="${SYNC_TRANSPORT:-rsync}"
remote_os="${REMOTE_OS:-posix}"
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
repo_root="$(cd "$script_dir/../../.." && pwd)"
source_sha="$(git -C "$repo_root" rev-parse HEAD)"
artifact_root="$repo_root/libs/cua-driver/docs/vm-artifacts"
target_slug="$(printf '%s' "$target" | tr -c 'A-Za-z0-9_.-' '_')"
timestamp="$(date -u +%Y%m%dT%H%M%SZ)"
exclude_args=(
# A linked worktree stores `.git` as a file, while a normal checkout stores
# it as a directory. Neither host-specific form belongs on a verification VM.
--exclude=.git
--exclude=.DS_Store
--exclude='._*'
--exclude=target/
--exclude=libs/cua-driver/rust/test-apps/
--exclude=node_modules/
--exclude=.venv/
--exclude=__pycache__/
--exclude='*.pyc'
--exclude=dist/
--exclude=vm-out/
)
tar_exclude_args=(
--exclude ./.git
--exclude ./.DS_Store
--exclude '._*'
--exclude ./target
--exclude ./libs/cua-driver/rust/test-apps
--exclude ./node_modules
--exclude ./.venv
--exclude '*/__pycache__'
--exclude '*.pyc'
--exclude ./dist
--exclude ./vm-out
)
remote_mkdir() {
case "$remote_os" in
windows)
"$rsync_ssh" "$target" \
"powershell -NoProfile -Command \"New-Item -ItemType Directory -Force '$remote_dir' | Out-Null\""
;;
posix)
"$rsync_ssh" "$target" "mkdir -p $remote_dir"
;;
*)
echo "REMOTE_OS must be posix or windows, got: $remote_os" >&2
exit 2
;;
esac
}
push_rsync() {
ssh_cmd=${remote_dir/#\~/"\$HOME"}
"$rsync_ssh" "$target" "mkdir -p $ssh_cmd"
rsync -az --delete -e "$rsync_ssh" "${exclude_args[@]}" "$repo_root/" "$target:$remote_dir/"
}
push_tar() {
remote_mkdir
remote_path=${remote_dir/#\~/'$HOME'}
COPYFILE_DISABLE=1 tar --no-xattrs "${tar_exclude_args[@]}" -czf - -C "$repo_root" . \
| "$rsync_ssh" "$target" "tar -xzf - -C \"$remote_path\""
}
write_source_marker() {
case "$remote_os" in
windows)
"$rsync_ssh" "$target" \
"powershell -NoProfile -Command \"Set-Content -NoNewline -Path '$remote_dir/.cua-e2e-source-sha' -Value '$source_sha'\""
;;
posix)
marker_dir=${remote_dir/#\~/"\$HOME"}
printf '%s\n' "$source_sha" \
| "$rsync_ssh" "$target" "mkdir -p $marker_dir && tee $marker_dir/.cua-e2e-source-sha >/dev/null"
;;
esac
}
ensure_remote_runtime_dirs() {
case "$remote_os" in
windows)
"$rsync_ssh" "$target" \
"powershell -NoProfile -Command \"New-Item -ItemType Directory -Force '$remote_dir/libs/cua-driver/rust/test-apps' | Out-Null\""
;;
posix)
remote_path=${remote_dir/#\~/'$HOME'}
"$rsync_ssh" "$target" \
"mkdir -p \"$remote_path/libs/cua-driver/rust/test-apps\""
;;
esac
}
pull_artifacts_rsync() {
rsync -az -e "$rsync_ssh" "$target:$remote_dir/$remote_artifact_dir/" "$dest/"
}
pull_artifacts_tar() {
remote_path=${remote_dir/#\~/'$HOME'}
"$rsync_ssh" "$target" "tar -czf - -C \"$remote_path/$remote_artifact_dir\" ." \
| tar -xzf - -C "$dest"
}
pull_code_rsync() {
rsync -az --backup --suffix=".vm-backup-$timestamp" -e "$rsync_ssh" \
"${exclude_args[@]}" "$target:$remote_dir/" "$repo_root/"
}
pull_code_tar() {
remote_path=${remote_dir/#\~/'$HOME'}
"$rsync_ssh" "$target" "tar -czf - -C \"$remote_path\" ." \
| COPYFILE_DISABLE=1 tar --no-xattrs "${tar_exclude_args[@]}" -xzf - -C "$repo_root"
}
case "$mode" in
push)
case "$transport" in
rsync) push_rsync ;;
tar) push_tar ;;
*) echo "SYNC_TRANSPORT must be rsync or tar, got: $transport" >&2; exit 2 ;;
esac
ensure_remote_runtime_dirs
write_source_marker
;;
pull-artifacts)
dest="$artifact_root/$target_slug/$timestamp"
mkdir -p "$dest"
case "$transport" in
rsync) pull_artifacts_rsync ;;
tar) pull_artifacts_tar ;;
*) echo "SYNC_TRANSPORT must be rsync or tar, got: $transport" >&2; exit 2 ;;
esac
echo "Pulled artifacts into $dest"
;;
pull-code)
if [[ "${ALLOW_PULL_CODE:-}" != "1" ]]; then
echo "Refusing to pull VM source without ALLOW_PULL_CODE=1." >&2
exit 2
fi
case "$transport" in
rsync) pull_code_rsync ;;
tar) pull_code_tar ;;
*) echo "SYNC_TRANSPORT must be rsync or tar, got: $transport" >&2; exit 2 ;;
esac
;;
*)
usage >&2
exit 2
;;
esac