max / quasi-type
1 file changed,
+26 insertions,
-1 deletion
| @@ -615,6 +615,22 @@ | |||
| 615 | 615 | /// be the largest thing in the dependency tree and would drag in the crypto | |
| 616 | 616 | /// provider question for no gain: the integrity guarantee here is the sha256 | |
| 617 | 617 | /// below, not the transport. | |
| 618 | + | /// | |
| 619 | + | /// **It retries, and that is not defensive coding.** The pins point at | |
| 620 | + | /// raw.githubusercontent.com, which rate-limits by IP, and a machine that builds | |
| 621 | + | /// Alloy asks it four times in one build: the image cuts two slots, and shop's | |
| 622 | + | /// build script cuts a third face into its own cache. Measured 2026-08-17, that | |
| 623 | + | /// is enough to earn a 429 on a developer's own laptop, and without a retry the | |
| 624 | + | /// image build fails on somebody else's rate limiter with the pinned bytes | |
| 625 | + | /// sitting one second away. curl retries 408, 429 and the 5xx family on | |
| 626 | + | /// `--retry` by itself; `--retry-all-errors` adds the connection failures, which | |
| 627 | + | /// are the other half of what a shared network does to a build. | |
| 628 | + | /// | |
| 629 | + | /// This bounds the damage rather than fixing the cause. The cause is that four | |
| 630 | + | /// fetches of the same two files leave the machine, and the real answer is a | |
| 631 | + | /// mirror on infrastructure we own — the same conversation as mirroring the | |
| 632 | + | /// Fedora base images (GO alloy `ebf30337`, and the fragility itself is alloy | |
| 633 | + | /// `3d41d15a`). | |
| 618 | 634 | fn fetch(url: &str, dest: &Path) -> Result<(), Error> { | |
| 619 | 635 | if let Some(parent) = dest.parent() { | |
| 620 | 636 | std::fs::create_dir_all(parent).map_err(|e| Error::Io(parent.to_path_buf(), e))?; | |
| @@ -626,6 +642,11 @@ | |||
| 626 | 642 | "--location", | |
| 627 | 643 | "--silent", | |
| 628 | 644 | "--show-error", | |
| 645 | + | "--retry", | |
| 646 | + | "5", | |
| 647 | + | "--retry-delay", | |
| 648 | + | "2", | |
| 649 | + | "--retry-all-errors", | |
| 629 | 650 | "--output", | |
| 630 | 651 | ]) | |
| 631 | 652 | .arg(&partial) | |
| @@ -634,7 +655,11 @@ | |||
| 634 | 655 | .map_err(|e| Error::Fetch(format!("could not run curl: {e}")))?; | |
| 635 | 656 | if !status.success() { | |
| 636 | 657 | let _ = std::fs::remove_file(&partial); | |
| 637 | - | return Err(Error::Fetch(format!("curl failed on {url} ({status})"))); | |
| 658 | + | return Err(Error::Fetch(format!( | |
| 659 | + | "curl failed on {url} ({status}), after retrying. A 429 here is this \ | |
| 660 | + | machine's IP being rate-limited by the host the base is pinned at, and \ | |
| 661 | + | the fix is a mirror rather than another retry." | |
| 662 | + | ))); | |
| 638 | 663 | } | |
| 639 | 664 | std::fs::rename(&partial, dest).map_err(|e| Error::Io(dest.to_path_buf(), e))?; | |
| 640 | 665 | Ok(()) |