From 09adb458c7195c93c860f4ad82f01add1040ec61 Mon Sep 17 00:00:00 2001 From: key Date: Tue, 4 Aug 2026 22:43:03 +0800 Subject: [PATCH] fix(release): handle Windows remote path conversion --- scripts/release-backend.sh | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/scripts/release-backend.sh b/scripts/release-backend.sh index 2fc3c421..6a1f6ea7 100644 --- a/scripts/release-backend.sh +++ b/scripts/release-backend.sh @@ -11,6 +11,23 @@ PREFLIGHT_SCRIPT="$ROOT_DIR/scripts/release-preflight.sh" MIN_FREE_RESERVE_BYTES=$((512 * 1024 * 1024)) PUBLIC_HEALTH_READY_TIMEOUT_SECONDS=90 +# Git for Windows converts POSIX-looking arguments before invoking native +# ssh/scp. Keep fixed remote paths opaque while converting only the local +# artifact path for Windows scp. +remote_ssh() { + MSYS_NO_PATHCONV=1 command ssh "$@" +} + +remote_scp() { + local -a args=("$@") + local local_index=$(( ${#args[@]} - 2 )) + if [[ "$local_index" -ge 0 && "${args[$local_index]}" == /[a-zA-Z]/* ]] \ + && command -v cygpath >/dev/null 2>&1; then + args[$local_index]="$(cygpath -m "${args[$local_index]}")" + fi + MSYS_NO_PATHCONV=1 command scp "${args[@]}" +} + fail() { echo "release-backend: $*" >&2 exit 1 @@ -179,7 +196,7 @@ remote_value() { inspect_remote_target() { local output output="$( - ssh -o BatchMode=yes -o ConnectTimeout=10 "$REMOTE_SSH" bash -s -- \ + remote_ssh -o BatchMode=yes -o ConnectTimeout=10 "$REMOTE_SSH" bash -s -- \ "$REMOTE_PATH" "$REMOTE_SERVICE" "$REMOTE_BACKUP_ROOT" <<'REMOTE_INSPECT' set -euo pipefail target="$1" @@ -307,7 +324,7 @@ run_deploy_plan() { } backup_remote_target() { - ssh -o BatchMode=yes -o ConnectTimeout=10 "$REMOTE_SSH" bash -s -- \ + remote_ssh -o BatchMode=yes -o ConnectTimeout=10 "$REMOTE_SSH" bash -s -- \ "$REMOTE_PATH" "$REMOTE_BACKUP_ROOT" "$REMOTE_SERVICE" \ "$remote_current_sha256" "$artifact_sha256" "$artifact_commit_sha" <<'REMOTE_BACKUP' set -euo pipefail @@ -335,7 +352,7 @@ REMOTE_BACKUP activate_remote_candidate() { local staging_path="$1" - ssh -o BatchMode=yes -o ConnectTimeout=10 "$REMOTE_SSH" bash -s -- \ + remote_ssh -o BatchMode=yes -o ConnectTimeout=10 "$REMOTE_SSH" bash -s -- \ "$REMOTE_PATH" "$staging_path" "$REMOTE_SERVICE" \ "$remote_current_sha256" "$artifact_sha256" <<'REMOTE_ACTIVATE' set -euo pipefail @@ -368,7 +385,7 @@ restore_remote_backup() { local source_jar="$1" local expected_restore_sha="$2" local expected_target_sha="$3" - ssh -o BatchMode=yes -o ConnectTimeout=10 "$REMOTE_SSH" bash -s -- \ + remote_ssh -o BatchMode=yes -o ConnectTimeout=10 "$REMOTE_SSH" bash -s -- \ "$source_jar" "$REMOTE_PATH" "$REMOTE_SERVICE" \ "$expected_restore_sha" "$expected_target_sha" <<'REMOTE_RESTORE' set -euo pipefail @@ -402,7 +419,7 @@ REMOTE_RESTORE } get_remote_target_sha() { - ssh -o BatchMode=yes -o ConnectTimeout=10 "$REMOTE_SSH" \ + remote_ssh -o BatchMode=yes -o ConnectTimeout=10 "$REMOTE_SSH" \ sha256sum "$REMOTE_PATH" | awk '{print tolower($1)}' } @@ -419,9 +436,9 @@ perform_deploy() { || fail "remote backup hash does not match the pre-deploy target" staging_path="${REMOTE_PATH}.candidate-${artifact_sha256:0:12}-$(date +%Y%m%d%H%M%S)" - ssh -o BatchMode=yes -o ConnectTimeout=10 "$REMOTE_SSH" \ + remote_ssh -o BatchMode=yes -o ConnectTimeout=10 "$REMOTE_SSH" \ test ! -e "$staging_path" || fail "remote candidate staging path already exists" - if ! scp -q -o BatchMode=yes -o ConnectTimeout=10 -- "$artifact" "$REMOTE_SSH:$staging_path"; then + if ! remote_scp -q -o BatchMode=yes -o ConnectTimeout=10 -- "$artifact" "$REMOTE_SSH:$staging_path"; then fail "candidate upload failed; production target was not changed; backup is $backup_path" fi @@ -486,7 +503,7 @@ inspect_rollback() { validate_backup_path local output output="$( - ssh -o BatchMode=yes -o ConnectTimeout=10 "$REMOTE_SSH" bash -s -- \ + remote_ssh -o BatchMode=yes -o ConnectTimeout=10 "$REMOTE_SSH" bash -s -- \ "$backup_dir/ruoyi-admin.jar" "$REMOTE_PATH" "$REMOTE_SERVICE" <<'REMOTE_ROLLBACK_INSPECT' set -euo pipefail backup_jar="$1" @@ -520,7 +537,7 @@ perform_rollback() { || fail "remote backend already matches the requested rollback JAR" safety_output="$( - ssh -o BatchMode=yes -o ConnectTimeout=10 "$REMOTE_SSH" bash -s -- \ + remote_ssh -o BatchMode=yes -o ConnectTimeout=10 "$REMOTE_SSH" bash -s -- \ "$REMOTE_PATH" "$REMOTE_BACKUP_ROOT" "$REMOTE_SERVICE" \ "$current_sha" "$expected_sha256" <<'REMOTE_ROLLBACK_SAFETY' set -euo pipefail