Files
PaperClipAI/scripts/check-cargo-network-config.test.mjs
T
Priya RamanandPaperclip 6d643cc068 fix(cargo): raise network retry and timeout to survive a transient stall
Cargo's default network settings abort a crate download after 30
seconds below 10 bytes per second, then retry 3 times. On a shared CI
runner, a brief network stall can cross that 30-second window on every
attempt, so a build with hundreds of uncached crate downloads can fail
even though the network recovers soon after.

Add a repository-root .cargo/config.toml that raises net.retry to 5
and http.timeout to 60 seconds. Cargo finds this file by an upward
directory search from the current working directory, independent of
any --manifest-path argument, so every cargo invocation in the
repository picks it up.

Add a deterministic local harness that serves a synthetic crate over
a stalling HTTP server, then proves the old defaults fail with the
exact CI error text and the new values survive the same stall. Add a
regression test that asserts the config values stay at or above the
chosen minimums, wired into the existing release-registry test list
that CI already runs.

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-09-04 00:07:04 +00:00

49 lines
2.0 KiB
JavaScript

import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import path from "node:path";
import test from "node:test";
import { fileURLToPath } from "node:url";
const scriptsDir = path.dirname(fileURLToPath(import.meta.url));
const repoRoot = path.join(scriptsDir, "..");
const configPath = path.join(repoRoot, ".cargo", "config.toml");
// A cargo build with the default network settings can fail on a short
// stall: cargo aborts a download after 30 seconds below 10 bytes per
// second, then retries only 3 times. These minimums keep the repository
// config wide enough to survive that kind of stall.
const MIN_NET_RETRY = 5;
const MIN_HTTP_TIMEOUT = 60;
function readIntUnderSection(text, sectionName, key) {
const sectionPattern = new RegExp(`\\[${sectionName}\\]([\\s\\S]*?)(?:\\n\\[|$)`);
const sectionMatch = text.match(sectionPattern);
assert.ok(sectionMatch, `expected a [${sectionName}] section in ${configPath}`);
const keyPattern = new RegExp(`^\\s*${key}\\s*=\\s*(\\d+)\\s*$`, "m");
const keyMatch = sectionMatch[1].match(keyPattern);
assert.ok(keyMatch, `expected ${sectionName}.${key} in ${configPath}`);
return Number(keyMatch[1]);
}
test("the repository cargo config file exists at the repository root", () => {
assert.doesNotThrow(() => readFileSync(configPath, "utf8"));
});
test("the repository cargo config raises the network retry count", () => {
const text = readFileSync(configPath, "utf8");
const retry = readIntUnderSection(text, "net", "retry");
assert.ok(
retry >= MIN_NET_RETRY,
`net.retry is ${retry}; it must stay at ${MIN_NET_RETRY} or higher so a transient network stall does not fail the build`,
);
});
test("the repository cargo config raises the http transfer timeout", () => {
const text = readFileSync(configPath, "utf8");
const timeout = readIntUnderSection(text, "http", "timeout");
assert.ok(
timeout >= MIN_HTTP_TIMEOUT,
`http.timeout is ${timeout}; it must stay at ${MIN_HTTP_TIMEOUT} or higher so a transient network stall does not fail the build`,
);
});