From 09d7a68ef811bd6d13e62bb891956a43f16d2c5f Mon Sep 17 00:00:00 2001 From: Nubenetes Bot Date: Sat, 20 Jun 2026 12:37:11 +0200 Subject: [PATCH] fix(rss): derive feed lastBuildDate from content, not wall-clock now() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit rss_generator set to datetime.utcnow(), so every republish rewrote it even when the digest was unchanged — leaving a 1-line develop<->master drift in v2-docs/feed.xml (the residual after the PR Guardian drift fix). Derive it from the digest's _meta.last_updated (the actual analysis date), falling back to the most recent item date, so the feed is a pure function of its input: regenerating unchanged content now yields byte-identical output. Verified deterministic across repeated runs. Co-Authored-By: Claude Opus 4.8 --- src/rss_generator.py | 24 +++++++++++++++++++++++- v2-docs/feed.xml | 2 +- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/rss_generator.py b/src/rss_generator.py index 6482c68e..0ce80f19 100644 --- a/src/rss_generator.py +++ b/src/rss_generator.py @@ -61,7 +61,29 @@ def generate_rss() -> None: ) items = items[:ITEMS_PER_FEED] - build_date = _rfc822(datetime.utcnow()) + # Deterministic build date: derive from the digest's content timestamp + # (_meta.last_updated, the actual analysis date) instead of wall-clock now(). + # Using now() rewrote on every republish, so a regenerated- + # but-unchanged feed still differed between develop and master (perpetual + # cosmetic drift). Mirrors the v2_optimizer pattern that prefers + # _meta.last_updated over file mtime. Falls back to the most recent item + # date, then a fixed constant, so the feed is always a pure function of input. + build_dt = None + meta_updated = digest.get("_meta", {}).get("last_updated", "") + if meta_updated: + try: + build_dt = datetime.fromisoformat(meta_updated) + except Exception: + build_dt = None + if build_dt is None: + item_dates = [] + for _it in items: + try: + item_dates.append(datetime.strptime(_it.get("date", ""), "%Y-%m-%d")) + except Exception: + pass + build_dt = max(item_dates) if item_dates else datetime(2026, 1, 1) + build_date = _rfc822(build_dt) lines = [ '', diff --git a/v2-docs/feed.xml b/v2-docs/feed.xml index c11fb116..8a43206f 100644 --- a/v2-docs/feed.xml +++ b/v2-docs/feed.xml @@ -5,7 +5,7 @@ https://nubenetes.com/ AI-curated top picks from the Cloud Native & Kubernetes ecosystem en - Sat, 20 Jun 2026 10:28:51 -0000 + Sat, 20 Jun 2026 12:28:51 +0200 Kubecost 🌟