From d9df55ae63d685814aa61e3ffd47b58cc12b6eda Mon Sep 17 00:00:00 2001 From: Phil Skentelbery Date: Tue, 25 Nov 2025 09:56:10 -0700 Subject: [PATCH] fix: RSS feed now shows newest posts first MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixed bug where feedgen library was reversing the order of feed items. Database returns notes in DESC order (newest first), but feedgen was displaying them oldest-first in the RSS XML. Added reversed() wrapper to maintain correct chronological order in the feed. Added regression test to verify feed order matches database order. Bug confirmed by testing: - Database: [Note 2, Note 1, Note 0] (newest first) - Old feed: [Note 0, Note 1, Note 2] (oldest first) ❌ - New feed: [Note 2, Note 1, Note 0] (newest first) ✅ 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- starpunk/feed.py | 5 +++-- tests/test_feed.py | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/starpunk/feed.py b/starpunk/feed.py index 0fe9d02..494da78 100644 --- a/starpunk/feed.py +++ b/starpunk/feed.py @@ -92,8 +92,9 @@ def generate_feed( # Set last build date to now fg.lastBuildDate(datetime.now(timezone.utc)) - # Add items (limit to configured maximum) - for note in notes[:limit]: + # Add items (limit to configured maximum, newest first) + # Notes from database are DESC but feedgen reverses them, so we reverse back + for note in reversed(notes[:limit]): # Create feed entry fe = fg.add_entry() diff --git a/tests/test_feed.py b/tests/test_feed.py index 0005041..d3555d9 100644 --- a/tests/test_feed.py +++ b/tests/test_feed.py @@ -133,6 +133,47 @@ class TestGenerateFeed: # Should only have 3 items (respecting limit) assert len(items) == 3 + def test_generate_feed_newest_first(self, app): + """Test feed displays notes in newest-first order""" + with app.app_context(): + # Create notes with distinct timestamps (oldest to newest in creation order) + import time + for i in range(3): + create_note( + content=f"# Note {i}\n\nContent {i}.", + published=True, + ) + time.sleep(0.01) # Ensure distinct timestamps + + # Get notes from database (should be DESC = newest first) + from starpunk.notes import list_notes + notes = list_notes(published_only=True, limit=10) + + # Verify database returns newest first + assert "Note 2" in notes[0].title + assert "Note 0" in notes[-1].title + + # Generate feed with notes from database + feed_xml = generate_feed( + site_url="https://example.com", + site_name="Test Blog", + site_description="A test blog", + notes=notes, + ) + + root = ET.fromstring(feed_xml) + channel = root.find("channel") + items = channel.findall("item") + + # Feed should also show newest first (matching database order) + # First item should be newest (Note 2) + # Last item should be oldest (Note 0) + first_title = items[0].find("title").text + last_title = items[-1].find("title").text + + assert "Note 2" in first_title + assert "Note 0" in last_title + def test_generate_feed_requires_site_url(self): """Test feed generation requires site_url""" with pytest.raises(ValueError, match="site_url is required"):