Skip to content

fix: Fix installer retries for HTTP/2 download failures#1910

Merged
senamakel merged 4 commits into
tinyhumansai:mainfrom
chiehwangs:fix/installer-http1-fallback
May 17, 2026
Merged

fix: Fix installer retries for HTTP/2 download failures#1910
senamakel merged 4 commits into
tinyhumansai:mainfrom
chiehwangs:fix/installer-http1-fallback

Conversation

@chiehwangs
Copy link
Copy Markdown
Contributor

@chiehwangs chiehwangs commented May 16, 2026

Summary

  • Add HTTP/1.1 retry fallback around installer curl metadata, HEAD, and asset download requests.
  • Cover curl exit 16 / HTTP/2 framing failures in the installer shell tests.
  • Run installer smoke tests in the Unix installer smoke workflow.
  • Document a public installer smoke case for proxy/VPN-sensitive networks and the HTTP/2 fallback path.

Problem

  • On some proxy/VPN/network paths, curl can fail GitHub release requests with HTTP/2 framing errors before the installer can download the OpenHuman app archive.
  • Affected users see the installer resolve the release but fail before the asset download completes, even when retrying later or switching network/VPN state makes the same URL reachable.
  • The existing installer tests did not cover curl's HTTP/2 failure mode, so regressions in the fallback path would not be caught locally or in CI.

Solution

  • Introduce small curl wrapper helpers in scripts/install.sh that first use the existing curl behavior, then retry once with --http1.1 when the initial request fails.
  • Reuse those helpers for latest.json, releases API metadata fallback, digest metadata refresh, asset HEAD reachability checks, and final asset downloads.
  • Preserve existing retry counts, checksum verification, and dry-run behavior while making verbose dry-runs disclose the HTTP/1.1 retry behavior.
  • Extend scripts/test_install.sh with fake-curl cases for metadata fetches, HEAD checks, and asset downloads that fail once with exit 16 and then succeed with --http1.1.
  • Add the shell installer tests to .github/workflows/installer-smoke.yml and update the release manual smoke checklist for public installer runs through proxy/VPN networks.

Submission Checklist

If a section does not apply to this change, mark the item as N/A with a one-line reason. Do not delete items.

  • Tests added or updated (happy path + at least one failure / edge case) per Testing Strategy
  • Diff coverage ≥ 80% — N/A: this change touches shell installer scripts/docs/workflow only; no Vitest/cargo coverage target exists for these shell lines, but scripts/test_install.sh adds focused failure-path coverage.
  • Coverage matrix updated — N/A: installer script robustness is not represented as an app feature row in docs/TEST-COVERAGE-MATRIX.md.
  • All affected feature IDs from the matrix are listed in the PR description under ## Related — N/A: no coverage-matrix feature IDs are affected.
  • No new external network dependencies introduced (mock backend used per Testing Strategy)
  • Manual smoke checklist updated if this touches release-cut surfaces (docs/RELEASE-MANUAL-SMOKE.md)
  • Linked issue closed via Closes #NNN in the ## Related section — N/A: no upstream GitHub issue or Linear issue was provided for this contribution.

Impact

  • Runtime/platform impact: installer-only change for macOS/Linux shell installs; app runtime behavior is unchanged.
  • Compatibility: preserves existing GitHub release asset URLs, retry behavior, checksum verification, and install locations.
  • Network behavior: users behind proxy/VPN/network paths that trigger curl HTTP/2 framing failures get an HTTP/1.1 retry before the installer reports failure.
  • Security: no new network endpoints or unchecked downloads are introduced; checksum validation remains in place.

Related

  • Closes: N/A: no issue was provided.
  • Follow-up PR(s)/TODOs: N/A.

AI Authored PR Metadata (required for Codex/Linear PRs)

Keep this section for AI-authored PRs. For human-only PRs, mark each field N/A.

Linear Issue

  • Key: N/A: no Linear issue was provided.
  • URL: N/A: no Linear issue was provided.

Commit & Branch

  • Branch: fix/installer-http1-fallback
  • Commit SHA: 28cabc62e6b9fa35208b563def3a26caa285e088

Validation Run

  • pnpm --filter openhuman-app format:check
  • pnpm typecheck
  • Focused tests: bash scripts/test_install.sh; bash -n scripts/install.sh && bash -n scripts/test_install.sh; bash scripts/install.sh --dry-run --verbose; git diff --check; sh .husky/pre-push
  • Rust fmt/check (if changed): N/A: no root Rust files changed.
  • Tauri fmt/check (if changed): N/A: no Tauri files changed.

Validation Blocked

  • command: N/A
  • error: N/A
  • impact: N/A

Behavior Changes

  • Intended behavior change: installer curl requests now retry once with --http1.1 after an initial failure, addressing VPN/proxy-sensitive HTTP/2 framing failures.
  • User-visible effect: installs that previously failed with curl HTTP/2 framing errors can complete without requiring users to disable VPN or manually retry on another network.

Parity Contract

  • Legacy behavior preserved: release resolution, asset selection, checksum verification, dry-run flow, and install destination behavior are preserved.
  • Guard/fallback/dispatch parity checks: fake-curl tests assert that metadata, HEAD, and archive download paths only fall back to HTTP/1.1 after the first curl attempt fails.

Duplicate / Superseded PR Handling

  • Duplicate PR(s): N/A: no existing PR found or provided for this branch.
  • Canonical PR: this PR.
  • Resolution (closed/superseded/updated): N/A.

Summary by CodeRabbit

  • New Features

    • Installer now automatically retries with an HTTP/1.1 fallback when transient HTTP/2 errors occur during downloads from GitHub/CDN.
  • Tests

    • Added smoke tests that simulate network failures to verify the installer's HTTP/1.1 retry/fallback behavior.
  • Documentation

    • Release manual updated with a public installer checklist covering proxy/VPN verification and expected retry behavior.
  • Chores

    • CI smoke step added to run installer verification before the dry-run step.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 16, 2026

📝 Walkthrough

Walkthrough

This pull request adds HTTP/1.1 fallback support to the installer script to handle transient GitHub/CDN HTTP/2 framing errors. Three curl wrapper functions retry failed requests using HTTP/1.1, are integrated into metadata and asset downloads, verified by new smoke tests, and documented in CI and the release manual.

Changes

HTTP/1.1 Fallback for Curl Operations

Layer / File(s) Summary
HTTP/1.1 curl wrapper functions
scripts/install.sh
Three new wrapper functions (curl_head_with_http_fallback, curl_get_file, curl_download_file) are added to retry curl operations using --http1.1 when initial requests fail.
Metadata fetches with curl_get_file wrapper
scripts/install.sh
Metadata fetches for LATEST_JSON_URL, LATEST_RELEASE_API_URL, and the release digest are switched to curl_get_file instead of direct curl calls.
Asset download with HTTP/1.1 retry
scripts/install.sh
Dry-run messaging updated to note HTTP/1.1 retry; real downloads now use curl_download_file to perform an HTTP/1.1 retry on failure.
Unit tests for HTTP/1.1 fallback behavior
scripts/test_install.sh
Three smoke tests stub curl and verify curl_head_with_http_fallback, curl_get_file, and curl_download_file retry correctly and include --http1.1 on the retry call; includes a shared assertion helper.
CI integration and release documentation
.github/workflows/installer-smoke.yml, docs/RELEASE-MANUAL-SMOKE.md
CI adds a "Unit tests (install.sh helpers)" step that runs scripts/test_install.sh; release manual adds a "Public installer script" checklist item describing proxy/VPN validation and HTTP/1.1 retry expectation.

🎯 3 (Moderate) | ⏱️ ~20 minutes

🐰 A hop, a skip, a fallback flight,
When HTTP/2 framing isn't quite right.
We retry with 1.1, steady and spry,
Curl takes two tries and waves problems goodbye.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 23.08% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and specifically describes the main change: adding HTTP/1.1 retry fallback for HTTP/2 download failures in the installer, which is the core objective across all modified files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@chiehwangs chiehwangs marked this pull request as ready for review May 16, 2026 11:13
@chiehwangs chiehwangs requested a review from a team May 16, 2026 11:13
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
scripts/test_install.sh (1)

33-91: ⚡ Quick win

Harden fallback tests to assert retry order, not just flag presence.

These checks should also verify exactly two curl calls and that --http1.1 is used only on the second call, so the “normal path first, fallback second” contract is protected.

♻️ Suggested test hardening
+assert_retry_shape() {
+  local calls="$1" label="$2"
+  IFS='|' read -r _ first second extra <<< "${calls}"
+  if [[ -z "${second:-}" || -n "${extra:-}" ]]; then
+    echo "FAIL: ${label} should issue exactly 2 curl calls (base + http1.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() {
@@
   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
-  if [[ "${CURL_CALLS}" != *"--http1.1"* ]]; then
-    echo "FAIL: reachability check did not retry with --http1.1"
-    exit 1
-  fi
+  assert_retry_shape "${CURL_CALLS}" "reachability check"
 )

Apply the same assert_retry_shape call to the metadata and download blocks.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/test_install.sh` around lines 33 - 91, The tests currently only
assert that "--http1.1" appears in CURL_CALLS; update each of the three test
blocks (the ones invoking curl_head_with_http_fallback, curl_get_file, and
curl_download_file) to assert the retry shape: ensure CURL_CALLS contains
exactly two recorded curl invocations and that only the second invocation
includes "--http1.1" (i.e., the normal path is first, the fallback second). Use
the existing CURL_CALLS variable and pattern checks to count entries and verify
the second entry includes "--http1.1" while the first does not.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@scripts/test_install.sh`:
- Around line 33-91: The tests currently only assert that "--http1.1" appears in
CURL_CALLS; update each of the three test blocks (the ones invoking
curl_head_with_http_fallback, curl_get_file, and curl_download_file) to assert
the retry shape: ensure CURL_CALLS contains exactly two recorded curl
invocations and that only the second invocation includes "--http1.1" (i.e., the
normal path is first, the fallback second). Use the existing CURL_CALLS variable
and pattern checks to count entries and verify the second entry includes
"--http1.1" while the first does not.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 974c29d3-b7da-4d08-a34f-382ac2fc38f1

📥 Commits

Reviewing files that changed from the base of the PR and between 8f93ca0 and 32aa59e.

📒 Files selected for processing (4)
  • .github/workflows/installer-smoke.yml
  • docs/RELEASE-MANUAL-SMOKE.md
  • scripts/install.sh
  • scripts/test_install.sh

coderabbitai[bot]
coderabbitai Bot previously approved these changes May 16, 2026
@chiehwangs
Copy link
Copy Markdown
Contributor Author

chiehwangs commented May 16, 2026

Completed the reinforcement of retry-shape tests as requested by CodeRabbit.

What changed:

  • Added assert_retry_shape in scripts/test_install.sh.
  • Each HTTP/1.1 fallback test now verifies exactly two curl calls.
  • The first call must use the normal curl path, and only the second retry may include --http1.1.

Validation run:

  • bash -n scripts/install.sh && bash -n scripts/test_install.sh
  • bash scripts/test_install.sh
  • git diff --check
  • git push pre-push hook passed

@chiehwangs
Copy link
Copy Markdown
Contributor Author

Heads up: the failing e2e / E2E (Linux / Appium Chromium) check looks unrelated to this installer change.

It fails during Appium setup before the E2E tests start:

A driver named "chromium" is already installed.

I triggered a fresh CI run with an empty Rerun CI commit and the same setup failure reproduced. This PR only changes installer scripts/tests/docs, so this looks like a CI Appium driver idempotency issue rather than a regression from this change.

@chiehwangs chiehwangs changed the title [codex] Fix installer retries for HTTP/2 download failures fix: Fix installer retries for HTTP/2 download failures May 16, 2026
@senamakel senamakel merged commit f0690aa into tinyhumansai:main May 17, 2026
21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants