ci(docs): soft-fail badge localization on transient fetch errors

The Docs Testing workflow has been the top CI flake source on master
(61 failures in the last 2 weeks), and almost every one fails with the
same signature:

  Cause: [remark-localize-badges] Failed to download badge:
    https://img.shields.io/badge/slack-join-orange.svg
  Error: fetch failed
  Build cannot continue with broken badges.

`remark-localize-badges` already retries 3× with backoff and a 30s
timeout. When shields.io rate-limits the CI runner anyway (very common
from GitHub Actions IP ranges), the plugin currently throws and the
entire docs build dies — even though the badge URL is fine and the
docs would render correctly via the remote URL.

Change the terminal failure path to log a warning and fall back to the
original remote URL. The rendered docs still show the badge (just
unlocalized for this build); the docs build keeps going. Add a
`REMARK_BADGES_STRICT=true` env var as an opt-in for the old
fail-the-build behavior, in case a release pipeline wants to catch
genuinely broken badge URLs.
This commit is contained in:
Claude Code
2026-05-18 23:54:22 -05:00
parent ac5e8f1308
commit 39e5cfa99c

View File

@@ -206,12 +206,26 @@ async function downloadBadge(url, staticDir) {
badgeCache.set(url, webPath);
return webPath;
} catch (error) {
// Fail the build on badge download failure
throw new Error(
`[remark-localize-badges] Failed to download badge: ${url}\n` +
`Error: ${error.message}\n` +
`Build cannot continue with broken badges. Please fix the badge URL or remove it.`,
// Soft fallback: keep the original remote URL in the rendered output
// so the badge still appears for readers, and the docs build continues.
// External badge services (notably img.shields.io) rate-limit CI IPs
// aggressively, and a transient fetch failure shouldn't take the whole
// docs build down with it. Set REMARK_BADGES_STRICT=true to opt back
// into hard-fail-the-build behavior (e.g. for release builds where you
// want to catch genuinely broken badge URLs).
if (process.env.REMARK_BADGES_STRICT === 'true') {
throw new Error(
`[remark-localize-badges] Failed to download badge: ${url}\n` +
`Error: ${error.message}\n` +
`Build cannot continue with broken badges (REMARK_BADGES_STRICT=true).`,
);
}
console.warn(
`[remark-localize-badges] Could not localize ${url} ` +
`(${error.message}); falling back to remote URL.`,
);
badgeCache.set(url, url);
return url;
} finally {
// Clean up the in-flight tracker
inFlightDownloads.delete(url);