plan 0012: backfill /updates with a post per historical release#360
Open
TheAngryRaven wants to merge 3 commits into
Open
plan 0012: backfill /updates with a post per historical release#360TheAngryRaven wants to merge 3 commits into
TheAngryRaven wants to merge 3 commits into
Conversation
The Updates blog shipped in v3.1.1 with nothing in it. Backfill one post per shipped release — V1.0.0 (March 2026) through v3.1.1 — reconstructed from CHANGELOG.md, the git history, and the GitHub release pages, so the blog opens with real history instead of a single post, and the landing page's "Latest updates" panel has something to show. Delivered as a hand-run SQL script rather than a migration: posts are content, not schema, and which project gets them (prod, beta, a preview branch) is a deliberate choice. Adds supabase/seeds/ for that class of script, with a README drawing the line against migrations/. Details worth knowing: - Every insert is `on conflict (slug) do nothing`, so a re-run is a no-op and never overwrites a post edited in the admin UI. - Slugs are the exact output of slugify() from lib/blogPosts.ts, so they match what the admin editor would have generated for each title. - published_at is each release's real GitHub publish timestamp, which keeps the index in true release order (a couple of changelog dates differ from their release date by a day or two). - All tagged `web update` (WEB_UPDATE_TAG) so LatestUpdates picks them up, and ai_assisted = true, since the bodies were drafted from the changelog with AI assistance. - v2.5.1 gets its own post: it was a real release with a release page, but its work was folded into the 2.6.0 changelog entry. The 2.6.0 post leads with i18n and the phone datalogger so the two do not duplicate. Verified by running the script against a throwaway Postgres 16 cluster with a stub of the posts schema: 23 rows insert, a second run inserts 0, author_id resolves, and the body_preview generated column populates. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AnnSz2nYNcY9HPn5ypmDPn
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
lapwing | c23f1b9 | Commit Preview URL Branch Preview URL |
Jul 26 2026, 05:08 AM |
|
Updates to Preview Branch (claude/changelog-posts-migration-d7v0jp) ↗︎
Tasks are run on every commit but only new migration files are pushed.
View logs for this Workflow Run ↗︎. |
Coverage SummaryLines: 56.4% (6833/12115) · Statements: 55.45% · Functions: 53.08% · Branches: 52.36% Per-file coverage
|
…ditor The first version wrote each post body as a dollar-quoted string ($post$...$post$) across 23 INSERTs wrapped in BEGIN/COMMIT, with a temp table holding the resolved author id. Postgres parses that fine -- it was verified against a real server -- but the Supabase SQL editor does not: it failed with a syntax error at a timestamp literal in the middle of the second INSERT, meaning it had already lost track of statement boundaries. Rewritten as a single INSERT ... SELECT over a VALUES list, using only standard single-quoted literals with doubled apostrophes. That removes both things the editor had trouble with: dollar-quoting, and any state shared between statements (the temp table and the transaction block). The author lookup is now an inline scalar subquery, and a lone statement is atomic on its own, so nothing is lost by dropping BEGIN/COMMIT. Content is unchanged. Verified by loading both versions and comparing: all 23 bodies are byte-identical to the original prose, slugs still match slugify(), published_at ordering is intact, and a second run still inserts 0 rows. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AnnSz2nYNcY9HPn5ypmDPn
Companion to 0001. One post per shipped DovesDataLogger (BirdsEye) firmware release -- v1.0.0 through v3.0.1, 9 posts -- written from that repo's CHANGELOG.md and its GitHub release pages. Tagged 'hardware update' + 'fledgling'. Neither is WEB_UPDATE_TAG, so the landing page's first "Latest updates" panel keeps showing the newest web-app release while the second now shows the newest firmware post, instead of the two streams competing for one slot. Verified against the real splitLatestByTag with both seeds loaded. Sourcing notes: the firmware changelog has no 2.0.0 or 2.1.0 headings -- its [2.2.0] entry is a rollup of everything since 1.0.0 -- so those two posts were reconstructed from the release pages' PR lists and the matching rollup sections. 1.0.0 is headed "2024" in the changelog but was tagged 2026-03-03; the post uses the tag date and says in the body that the work goes back to 2024. Same structural rules as 0001: one statement, plain single-quoted literals, no dollar-quoting, ON CONFLICT (slug) DO NOTHING. Slugs are prefixed "firmware-" so they cannot collide with the web app's posts (both repos have a v2.2.0); checked, no cross-file collisions. Verified by loading 0001 and 0002 into a throwaway Postgres 16: 23 + 9 rows insert, a re-run inserts 0, slugs match slugify(), published_at ordering is strictly increasing, and all 9 release links resolve to real tags on the logger repo. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AnnSz2nYNcY9HPn5ypmDPn
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The Updates blog shipped in v3.1.1 with nothing in it. Backfill one post
per shipped release — V1.0.0 (March 2026) through v3.1.1 — reconstructed
from CHANGELOG.md, the git history, and the GitHub release pages, so the
blog opens with real history instead of a single post, and the landing
page's "Latest updates" panel has something to show.
Delivered as a hand-run SQL script rather than a migration: posts are
content, not schema, and which project gets them (prod, beta, a preview
branch) is a deliberate choice. Adds supabase/seeds/ for that class of
script, with a README drawing the line against migrations/.
Details worth knowing:
on conflict (slug) do nothing, so a re-run is a no-opand never overwrites a post edited in the admin UI.
match what the admin editor would have generated for each title.
keeps the index in true release order (a couple of changelog dates
differ from their release date by a day or two).
web update(WEB_UPDATE_TAG) so LatestUpdates picks them up,and ai_assisted = true, since the bodies were drafted from the changelog
with AI assistance.
its work was folded into the 2.6.0 changelog entry. The 2.6.0 post leads
with i18n and the phone datalogger so the two do not duplicate.
Verified by running the script against a throwaway Postgres 16 cluster
with a stub of the posts schema: 23 rows insert, a second run inserts 0,
author_id resolves, and the body_preview generated column populates.
Co-Authored-By: Claude Opus 5 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01AnnSz2nYNcY9HPn5ypmDPn