fix(installer): time out stalled runtime downloads (#108619)

* fix(installer): bound curl download stalls

* chore: format installer timeout tests

* fix(installer): limit timeout to true download stalls

* fix(installer): scope timeout to transfer stalls
This commit is contained in:
Alix-007
2026-07-15 23:01:31 -07:00
committed by GitHub
parent d8b723fb00
commit 5f2828b50a
4 changed files with 52 additions and 2 deletions
+5 -1
View File
@@ -137,7 +137,11 @@ download_file() {
detect_downloader
fi
if [[ "$DOWNLOADER" == "curl" ]]; then
curl -fsSL --proto '=https' --tlsv1.2 --retry 3 --retry-delay 1 --retry-connrefused -o "$output" "$url"
# Bound post-connect stalls without imposing a total download duration.
curl -fsSL --proto '=https' --tlsv1.2 \
--speed-limit 1 --speed-time 30 \
--retry 3 --retry-delay 1 --retry-connrefused \
-o "$output" "$url"
return
fi
wget -q --https-only --secure-protocol=TLSv1_2 --tries=3 --timeout=20 -O "$output" "$url"
+5 -1
View File
@@ -114,7 +114,11 @@ download_file() {
detect_downloader
fi
if [[ "$DOWNLOADER" == "curl" ]]; then
curl -fsSL --proto '=https' --tlsv1.2 --retry 3 --retry-delay 1 --retry-connrefused -o "$output" "$url"
# Bound post-connect stalls without imposing a total download duration.
curl -fsSL --proto '=https' --tlsv1.2 \
--speed-limit 1 --speed-time 30 \
--retry 3 --retry-delay 1 --retry-connrefused \
-o "$output" "$url"
return
fi
wget -q --https-only --secure-protocol=TLSv1_2 --tries=3 --timeout=20 -O "$output" "$url"
+21
View File
@@ -41,6 +41,27 @@ function linkRequiredShellTools(bin: string) {
describe("install-cli.sh", () => {
const script = readFileSync(SCRIPT_PATH, "utf8");
it("bounds stalled curl downloads and propagates timeout failures", () => {
const result = runInstallCliShell(`
set -euo pipefail
source "${SCRIPT_PATH}"
curl() {
printf 'curl=%s\n' "$*"
return 28
}
DOWNLOADER=curl
set +e
download_file "https://example.invalid/node.tar.gz" "/tmp/node.tar.gz"
printf 'status=%s\n' "$?"
`);
expect(result.status).toBe(0);
expect(result.stdout).toContain("--speed-limit 1 --speed-time 30");
expect(result.stdout).not.toContain("--connect-timeout");
expect(result.stdout).toContain("--retry 3 --retry-delay 1 --retry-connrefused");
expect(result.stdout).toContain("status=28");
});
it("does not clean an unrelated legacy checkout during the default npm install", () => {
const main = script.slice(script.indexOf("\nmain() {"));
expect(main).not.toContain("cleanup_legacy_submodules");
+21
View File
@@ -82,6 +82,27 @@ describe("install.sh", () => {
}
});
it("bounds stalled curl downloads and propagates timeout failures", () => {
const result = runInstallShell(`
set -euo pipefail
source "${SCRIPT_PATH}"
curl() {
printf 'curl=%s\n' "$*"
return 28
}
DOWNLOADER=curl
set +e
download_file "https://example.invalid/archive.tgz" "/tmp/archive.tgz"
printf 'status=%s\n' "$?"
`);
expect(result.status).toBe(0);
expect(result.stdout).toContain("--speed-limit 1 --speed-time 30");
expect(result.stdout).not.toContain("--connect-timeout");
expect(result.stdout).toContain("--retry 3 --retry-delay 1 --retry-connrefused");
expect(result.stdout).toContain("status=28");
});
it("runs apt-get through noninteractive wrappers", () => {
expect(script).toContain("apt_get()");
expect(script).toContain('DEBIAN_FRONTEND="${DEBIAN_FRONTEND:-noninteractive}"');