diff --git a/install.sh b/install.sh index 8b12372f1..40a436638 100755 --- a/install.sh +++ b/install.sh @@ -228,6 +228,13 @@ get_latest_maintenance_stable_version() { printf '%s\n' "$latest_version" } +is_maintenance_stable_release_tag() { + local tag="${1:-}" + tag="${tag#v}" + + [[ "$tag" =~ ^5[.]1[.][0-9]+$ ]] +} + resolve_bootstrap_install_script_url() { local requested_version="${1:-}" @@ -2463,11 +2470,7 @@ resolve_target_release() { LATEST_RELEASE=$(echo "$releases_json" | grep -v '"draft": true' | grep '"tag_name":' | head -1 | sed -E 's/.*"([^"]+)".*/\1/' || true) fi else - if command -v jq >/dev/null 2>&1; then - LATEST_RELEASE=$(echo "$releases_json" | jq -r '[.[] | select(.draft == false and .prerelease == false)][0].tag_name' 2>/dev/null || true) - else - LATEST_RELEASE=$(echo "$releases_json" | awk '/"draft": true/,/"tag_name":/ {next} /"prerelease": true/,/"tag_name":/ {next} /"tag_name":/ {print; exit}' | sed -E 's/.*"([^"]+)".*/\1/' || true) - fi + LATEST_RELEASE=$(get_latest_maintenance_stable_version 2>/dev/null || true) fi fi @@ -2475,7 +2478,9 @@ resolve_target_release() { print_info "GitHub API unavailable, trying alternative method..." local redirect_version="" redirect_version=$(get_latest_release_from_redirect 2>/dev/null || true) - if [[ -n "$redirect_version" ]]; then + if [[ "$UPDATE_CHANNEL" == "rc" && -n "$redirect_version" ]]; then + LATEST_RELEASE="$redirect_version" + elif is_maintenance_stable_release_tag "$redirect_version"; then LATEST_RELEASE="$redirect_version" fi fi diff --git a/scripts/tests/test-server-install.sh b/scripts/tests/test-server-install.sh index dad3c0d0d..2f3b9ddb6 100755 --- a/scripts/tests/test-server-install.sh +++ b/scripts/tests/test-server-install.sh @@ -212,6 +212,50 @@ EOF ) } +test_resolve_target_release_skips_prerelease_without_jq() { + ( + load_installer + + FORCE_VERSION="" + FORCE_CHANNEL="" + UPDATE_CHANNEL="" + LATEST_RELEASE="" + + command() { + if [[ "$1" == "-v" && "${2:-}" == "jq" ]]; then + return 1 + fi + builtin command "$@" + } + + curl() { + cat <<'EOF' +[ + { + "tag_name": "v6.0.0-rc.5", + "draft": false, + "prerelease": true + }, + { + "tag_name": "v5.1.30", + "draft": false, + "prerelease": false + } +] +EOF + } + + get_latest_release_from_redirect() { + printf '%s\n' "v6.0.0-rc.5" + } + + resolve_target_release >/dev/null + + [[ "${UPDATE_CHANNEL}" == "stable" ]] + [[ "${LATEST_RELEASE}" == "v5.1.30" ]] + ) +} + test_install_pulse_archive_rejects_mismatched_arch_without_replacing_existing_binary() { ( load_installer @@ -456,6 +500,7 @@ main() { assert_success "download_pulse installs from local archive without network" test_download_pulse_installs_from_local_archive_without_network assert_success "prefetch helper writes archive path via output variable" test_prefetch_pulse_archive_for_container_sets_output_var assert_success "resolve_target_release ignores host-configured rc during fresh LXC bootstrap" test_resolve_target_release_ignores_host_configured_rc_channel_when_requested + assert_success "resolve_target_release skips prereleases without jq" test_resolve_target_release_skips_prerelease_without_jq assert_success "wrong-arch archives fail before replacing the installed binary" test_install_pulse_archive_rejects_mismatched_arch_without_replacing_existing_binary assert_success "parse_args rejects archive with source builds" test_parse_args_rejects_archive_with_source assert_success "installer supports curl-pipe execution via bash stdin" test_installer_runs_when_streamed_over_stdin