mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-27 19:35:13 +01:00
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>
49 lines
2.0 KiB
JavaScript
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`,
|
|
);
|
|
});
|