From e4170a6900b1addc36c4dd7e4ea2e80f735127d8 Mon Sep 17 00:00:00 2001 From: "Jorge O. Castro" Date: Tue, 14 Apr 2026 12:54:16 -0400 Subject: [PATCH 1/2] feat(lts-card): enrich DX/GDX packages from SBOM allPackages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The lts.YYYYMMDD release format (new as of April 2026) omits the 'Major DX packages' and 'Major GDX packages' tables from the release body. As a result dxPackages and gdxPackages were empty for all lts.20260414+ releases, making Docker, VSCode, Nvidia, and CUDA disappear from the LTS card. Add enrichLtsDxGdxFromSbom() which reads from the bluefin-dx-lts and bluefin-gdx-lts SBOM allPackages maps using the same lts-YYYYMMDD cache key as the main enrichFromSbom pass. Maps: docker-ce → Docker, code → VSCode, incus → Incus (DX) nvidia-driver → Nvidia, nvidia-driver-cuda → CUDA (GDX) Only adds chips that are not already present from release notes, so older releases that do have explicit tables are not affected. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/components/FirehoseFeed.tsx | 70 ++++++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/src/components/FirehoseFeed.tsx b/src/components/FirehoseFeed.tsx index 026b9a90..da8b9581 100644 --- a/src/components/FirehoseFeed.tsx +++ b/src/components/FirehoseFeed.tsx @@ -192,6 +192,72 @@ function enrichLtsFromHistory(events: OsReleaseEvent[]): OsReleaseEvent[] { return enriched.sort((a, b) => b.dateMs - a.dateMs); } +/** RPM package name → display label for the DX section chips */ +const DX_CHIP_MAP: Record = { + "docker-ce": "Docker", + code: "VSCode", + incus: "Incus", +}; + +/** RPM package name → display label for the GDX section chips */ +const GDX_CHIP_MAP: Record = { + "nvidia-driver": "Nvidia", + "nvidia-driver-cuda": "CUDA", +}; + +/** + * Enrich LTS events' dxPackages and gdxPackages from the bluefin-dx-lts / + * bluefin-gdx-lts SBOM allPackages maps. + * + * The "Major DX / GDX packages" tables are absent from lts.YYYYMMDD releases + * (new release format), so dxPackages/gdxPackages are empty after parse. + * This function fills them from authoritative SBOM data. + */ +function enrichLtsDxGdxFromSbom(events: OsReleaseEvent[]): OsReleaseEvent[] { + return events.map((event) => { + if (event.stream !== "lts") return event; + + const dateMatch = event.release.tag.match(/(\d{8})/); + if (!dateMatch) return event; + const cacheKey = `lts-${dateMatch[1]}`; + + const dxAllPkgs = + SBOM_CACHE?.streams?.["bluefin-dx-lts"]?.releases?.[cacheKey]?.packageVersions?.allPackages; + const gdxAllPkgs = + SBOM_CACHE?.streams?.["bluefin-gdx-lts"]?.releases?.[cacheKey]?.packageVersions?.allPackages; + + let dxPackages = [...event.release.dxPackages]; + if (dxAllPkgs) { + const existing = new Set(dxPackages.map((p) => p.name.toLowerCase())); + for (const [rpm, label] of Object.entries(DX_CHIP_MAP)) { + const version = dxAllPkgs[rpm]; + if (version && !existing.has(label.toLowerCase())) { + dxPackages.push({ name: label, version, prevVersion: null }); + } + } + } + + let gdxPackages = [...event.release.gdxPackages]; + if (gdxAllPkgs) { + const existing = new Set(gdxPackages.map((p) => p.name.toLowerCase())); + for (const [rpm, label] of Object.entries(GDX_CHIP_MAP)) { + const version = gdxAllPkgs[rpm]; + if (version && !existing.has(label.toLowerCase())) { + gdxPackages.push({ name: label, version, prevVersion: null }); + } + } + } + + if ( + dxPackages.length === event.release.dxPackages.length && + gdxPackages.length === event.release.gdxPackages.length + ) { + return event; + } + return { ...event, release: { ...event.release, dxPackages, gdxPackages } }; + }); +} + /** * Synthesise OsReleaseEvent entries for stable-daily builds that exist only in * GHCR (no GitHub Release). These are GHCR nightly builds tagged @@ -251,7 +317,9 @@ function loadStableDailyEventsFromSbom(): OsReleaseEvent[] { // All parsed events from both feeds, enriched with SBOM package versions const BLUEFIN_OS_EVENTS: OsReleaseEvent[] = enrichFromSbom(loadOsEvents(bluefinReleasesData)); const STABLE_DAILY_OS_EVENTS: OsReleaseEvent[] = loadStableDailyEventsFromSbom(); -const LTS_OS_EVENTS: OsReleaseEvent[] = enrichLtsFromHistory(enrichFromSbom(loadOsEvents(bluefinLtsReleasesData, "lts"))); +const LTS_OS_EVENTS: OsReleaseEvent[] = enrichLtsDxGdxFromSbom( + enrichLtsFromHistory(enrichFromSbom(loadOsEvents(bluefinLtsReleasesData, "lts"))), +); // Rolling 12-month window for the stream — pinned cards (PINNED_OS_EVENTS) are unaffected. const ALL_OS_STREAM_EVENTS: OsReleaseEvent[] = (() => { From e5f852d3070a1775a8b8811207a6a4a30b8df390 Mon Sep 17 00:00:00 2001 From: "Jorge O. Castro" Date: Tue, 14 Apr 2026 12:58:54 -0400 Subject: [PATCH 2/2] fix(lts-card): use const for dxPackages/gdxPackages arrays (prefer-const) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/components/FirehoseFeed.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/FirehoseFeed.tsx b/src/components/FirehoseFeed.tsx index da8b9581..8d3dce6c 100644 --- a/src/components/FirehoseFeed.tsx +++ b/src/components/FirehoseFeed.tsx @@ -226,7 +226,7 @@ function enrichLtsDxGdxFromSbom(events: OsReleaseEvent[]): OsReleaseEvent[] { const gdxAllPkgs = SBOM_CACHE?.streams?.["bluefin-gdx-lts"]?.releases?.[cacheKey]?.packageVersions?.allPackages; - let dxPackages = [...event.release.dxPackages]; + const dxPackages = [...event.release.dxPackages]; if (dxAllPkgs) { const existing = new Set(dxPackages.map((p) => p.name.toLowerCase())); for (const [rpm, label] of Object.entries(DX_CHIP_MAP)) { @@ -237,7 +237,7 @@ function enrichLtsDxGdxFromSbom(events: OsReleaseEvent[]): OsReleaseEvent[] { } } - let gdxPackages = [...event.release.gdxPackages]; + const gdxPackages = [...event.release.gdxPackages]; if (gdxAllPkgs) { const existing = new Set(gdxPackages.map((p) => p.name.toLowerCase())); for (const [rpm, label] of Object.entries(GDX_CHIP_MAP)) {