mirror of
https://github.com/tinyhumansai/openhuman.git
synced 2026-07-27 21:08:00 +00:00
fix: Fix installer retries for HTTP/2 download failures (#1910)
This commit is contained in:
@@ -20,6 +20,8 @@ jobs:
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
- name: Unit tests (install.sh helpers)
|
||||
run: bash scripts/test_install.sh
|
||||
- name: Run installer dry-run
|
||||
run: bash scripts/install.sh --dry-run --verbose
|
||||
|
||||
|
||||
@@ -21,6 +21,10 @@ This is the **only** acceptable substitute for a `🚫` row in [`TEST-COVERAGE-M
|
||||
|
||||
Applies to every release, all platforms.
|
||||
|
||||
### Public installer script
|
||||
|
||||
- [ ] **`scripts/install.sh` downloads the latest asset on a proxy/VPN network** — From a clean checkout, run `bash scripts/install.sh --dry-run --verbose`, then run the public `curl -fsSL https://raw.githubusercontent.com/tinyhumansai/openhuman/main/scripts/install.sh | bash` flow on one macOS or Linux host. Expected: release metadata resolves, the asset downloads successfully, and transient GitHub/CDN HTTP/2 failures retry over HTTP/1.1 instead of surfacing `curl: (16) Error in the HTTP2 framing layer`.
|
||||
|
||||
### macOS
|
||||
|
||||
- [ ] **Gatekeeper accepts the signed `.app` on first launch** — Double-click the `.app` from a fresh download (Quarantine attribute set). Expected: app opens without `"OpenHuman" cannot be opened because the developer cannot be verified` dialog. If it appears, the build is unsigned or the notarization stapler is missing.
|
||||
|
||||
+42
-6
@@ -200,11 +200,47 @@ PY
|
||||
printf '%s\n' "$url"
|
||||
}
|
||||
|
||||
# curl can fail on GitHub/CDN HTTP/2 framing issues on some networks while the
|
||||
# same URL succeeds over HTTP/1.1. Try the normal path first, then a
|
||||
# compatibility retry before surfacing the failure.
|
||||
curl_get_file() {
|
||||
local url="$1" output="$2" rc
|
||||
if curl -fsSL "$url" -o "$output"; then
|
||||
return 0
|
||||
else
|
||||
rc=$?
|
||||
fi
|
||||
log_warn "Request failed (curl rc=${rc}); retrying with HTTP/1.1."
|
||||
curl --http1.1 -fsSL "$url" -o "$output"
|
||||
}
|
||||
|
||||
curl_download_file() {
|
||||
local url="$1" output="$2" rc
|
||||
if curl -fL "$url" -o "$output"; then
|
||||
return 0
|
||||
else
|
||||
rc=$?
|
||||
fi
|
||||
log_warn "Download failed (curl rc=${rc}); retrying with HTTP/1.1."
|
||||
curl --http1.1 -fL "$url" -o "$output"
|
||||
}
|
||||
|
||||
curl_head_with_http_fallback() {
|
||||
local url="$1" rc
|
||||
if curl -fsSI --max-time 10 "$url" >/dev/null 2>&1; then
|
||||
return 0
|
||||
else
|
||||
rc=$?
|
||||
fi
|
||||
log_warn "Reachability check failed (curl rc=${rc}); retrying with HTTP/1.1."
|
||||
curl --http1.1 -fsSI --max-time 10 "$url" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
# Retries an HTTP HEAD on the asset URL, fails loudly with the URL.
|
||||
verify_asset_reachable() {
|
||||
local url="$1" max_attempts=5 delay=2
|
||||
for i in $(seq 1 $max_attempts); do
|
||||
if curl -fsSI --max-time 10 "$url" >/dev/null 2>&1; then
|
||||
if curl_head_with_http_fallback "$url"; then
|
||||
return 0
|
||||
fi
|
||||
if [[ $i -lt $max_attempts ]]; then
|
||||
@@ -217,7 +253,7 @@ verify_asset_reachable() {
|
||||
}
|
||||
|
||||
resolve_from_latest_json() {
|
||||
if ! curl -fsSL "${LATEST_JSON_URL}" -o "${LATEST_JSON_PATH}"; then
|
||||
if ! curl_get_file "${LATEST_JSON_URL}" "${LATEST_JSON_PATH}"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
@@ -252,7 +288,7 @@ print(d.get('version', ''))
|
||||
}
|
||||
|
||||
resolve_from_release_api() {
|
||||
if ! curl -fsSL "${LATEST_RELEASE_API_URL}" -o "${RELEASE_JSON_PATH}"; then
|
||||
if ! curl_get_file "${LATEST_RELEASE_API_URL}" "${RELEASE_JSON_PATH}"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
@@ -333,7 +369,7 @@ resolve_release_digest() {
|
||||
return 0
|
||||
fi
|
||||
if [ ! -s "${RELEASE_JSON_PATH}" ]; then
|
||||
if ! curl -fsSL "${LATEST_RELEASE_API_URL}" -o "${RELEASE_JSON_PATH}"; then
|
||||
if ! curl_get_file "${LATEST_RELEASE_API_URL}" "${RELEASE_JSON_PATH}"; then
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
@@ -417,9 +453,9 @@ fi
|
||||
DOWNLOAD_PATH="${TMP_DIR}/${ASSET_NAME}"
|
||||
log_info "Downloading ${ASSET_NAME}"
|
||||
if [ "${DRY_RUN}" = true ]; then
|
||||
echo "DRY RUN: curl -fL ${ASSET_URL} -o ${DOWNLOAD_PATH}"
|
||||
echo "DRY RUN: curl -fL ${ASSET_URL} -o ${DOWNLOAD_PATH} (retrying with --http1.1 on failure)"
|
||||
else
|
||||
curl -fL "${ASSET_URL}" -o "${DOWNLOAD_PATH}"
|
||||
curl_download_file "${ASSET_URL}" "${DOWNLOAD_PATH}"
|
||||
fi
|
||||
|
||||
compute_sha256() {
|
||||
|
||||
@@ -30,4 +30,71 @@ if [[ "$missing_platform_rc" -ne 3 ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
assert_retry_shape() {
|
||||
local calls="$1" label="$2"
|
||||
local _ first second extra
|
||||
IFS='|' read -r _ first second extra <<<"${calls}"
|
||||
|
||||
if [[ -z "${first:-}" || -z "${second:-}" || -n "${extra:-}" ]]; then
|
||||
echo "FAIL: ${label} should issue exactly 2 curl calls (base + HTTP/1.1 retry)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "${first}" == *"--http1.1"* || "${second}" != *"--http1.1"* ]]; then
|
||||
echo "FAIL: ${label} should retry with --http1.1 only on the second call"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
(
|
||||
CURL_CALLS=""
|
||||
curl() {
|
||||
CURL_CALLS="${CURL_CALLS}|$*"
|
||||
case " $* " in
|
||||
*" --http1.1 "*) return 0 ;;
|
||||
*) return 16 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
if ! curl_head_with_http_fallback "https://example.invalid/OpenHuman.app.tar.gz"; then
|
||||
echo "FAIL: reachability fallback should succeed when HTTP/1.1 retry succeeds"
|
||||
exit 1
|
||||
fi
|
||||
assert_retry_shape "${CURL_CALLS}" "reachability check"
|
||||
)
|
||||
|
||||
(
|
||||
CURL_CALLS=""
|
||||
curl() {
|
||||
CURL_CALLS="${CURL_CALLS}|$*"
|
||||
case " $* " in
|
||||
*" --http1.1 "*) return 0 ;;
|
||||
*) return 16 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
if ! curl_get_file "https://example.invalid/latest.json" "/tmp/openhuman-test-latest.json"; then
|
||||
echo "FAIL: metadata fetch fallback should succeed when HTTP/1.1 retry succeeds"
|
||||
exit 1
|
||||
fi
|
||||
assert_retry_shape "${CURL_CALLS}" "metadata fetch"
|
||||
)
|
||||
|
||||
(
|
||||
CURL_CALLS=""
|
||||
curl() {
|
||||
CURL_CALLS="${CURL_CALLS}|$*"
|
||||
case " $* " in
|
||||
*" --http1.1 "*) return 0 ;;
|
||||
*) return 16 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
if ! curl_download_file "https://example.invalid/OpenHuman.app.tar.gz" "/tmp/openhuman-test-download"; then
|
||||
echo "FAIL: download fallback should succeed when HTTP/1.1 retry succeeds"
|
||||
exit 1
|
||||
fi
|
||||
assert_retry_shape "${CURL_CALLS}" "download"
|
||||
)
|
||||
|
||||
echo "PASS"
|
||||
|
||||
Reference in New Issue
Block a user