Skip to content

Repair what the WordPress database dump found, and retire three cutover deadlines - #63

Merged
FDelporte merged 5 commits into
mainfrom
wp-dump-repairs
Sep 21, 2026
Merged

FDelporte merged 5 commits into
mainfrom
wp-dump-repairs

Conversation

@FDelporte

Copy link
Copy Markdown
Contributor

Validating the WordPress SQL dump (Foojay/WordPress backup/sftp96438_wpengine_com.sql, taken 2026-09-21 08:34 UTC) against content/ turned up a short list of real gaps. This is that list, fixed.

The migration itself came out clean. All 2,255 published posts are here, all 326 post authors have a profile, post dates match the URL paths exactly, no post is missing a description, and every approved comment is archived. What follows is the remainder.

What changed

Eight posts were edited on WordPress after this repo took its copy. Seven re-fetched with transfer/Posts.java --url; boxlang-1-16-0-released is frozen so its four added categories went in by hand. Mostly categories, plus a moved sample repo in the two Hibernate/MongoDB posts and a section reorder in the Payara release post.

Four things only the database has, because in each case the live HTML is not where the fact lives:

keeping-your-fonts-in-embedded-svg had no body at all — live on the site as a title and nothing else. WordPress serves an empty .article__main-content, so every scrape rewrites it empty and says so. Rebuilt from post_content (90 KB) through the repo's own HtmlToMarkdown, images pulled into the bundle, now frozen.
calling-microservices-in-java the only post with a featured image in WordPress and none here. Its og:image URL contains a narrow no-break space (U+202F) that WordPress emits unencoded and the scraper cannot fetch.
11 redirects nine from _wp_old_slug — the postmeta WordPress writes on a rename and redirects from for ever, invisible to the plugin export the aliases were built from — plus plugin rules 106/107, added after that export.
5 author social links Maximillian Arruda routes his through link.maxdearruda.com, and the scraper classifies a social link by host, so it writes "" over both on every run. His profile is frozen; the usermeta keys name the network outright.

One post is frozen against its own source. The WordPress edit that gave did-your-ai-agent-run-the-debugger a better title also mangled six links in the body — schemes stripped, doubled (http:https://...///), one anchor text spliced into another. The dump confirms the damage is in post_content, so the live copy is the broken one and a re-scrape reproduces it faithfully. This keeps the new title and the old body. Worth fixing on WordPress too if the post is going to be edited there again.

Also: three converter regressions the re-scrape introduced (two eaten spaces, three &\&), and alt text for the five images in the restored post, where WordPress had none and the images are the argument.

What this changes about cutover day

CUTOVER.md Phase 1 is built around scraping a site that is about to be switched off, and three of its items say some version of this cannot be re-run after cutover. A database dump makes all three false, so the phase now opens by saying to take the dump first.

The view counts are the one to read closely. wp_post_views WHERE type='4' is the per-post total, exactly, in one query — and on 2026-09-21 the crawl-built data/legacy-views.json was 87,617 views light across 2,169 posts, and missing 91 posts outright. Nothing was over-counted, so every difference is something the crawl did not see. Rebuild that file from the final dump rather than crawling for it.

The comment archive and CloudflareEmails similarly stop being deadlines (wp_comments is complete; obfuscation happens at Cloudflare's edge, so post_content is clean — 233 posts carry a raw address there). The hero-image and canonical audits are untouched: those probe third-party URLs and still need the network.

Not in this PR

  • ~71,000 indexed URLs under /today/<type>/… with no Hugo equivalent and no redirect family: /today/options/ (41,672 — the JVM options explorer, now /jvm-options/), /today/fixes/ (23,813), /today/event/ (5,430), and smaller sets. All index in wpseo_titles, none carrying a recorded page view. Wants a decision — a rule, or a bulk 410 — before cutover; the full URL list is in the dump.
  • Three WordPress category descriptions (Podcast, CRaC, JBang). _default/term.html renders only {{ .Title }}, so carrying them needs a layout change, not just content.
  • Two author website: fields the diff flagged: for iryna-dohndorf and micksembwever the WordPress user_url is the same LinkedIn URL their profile already shows, so adding it would print one link twice.
  • stefan-richthofer's website: is apidia.net here and x.com/stewori on the live page, so the next full Authors.java run will flip it. Pre-existing, left alone.

A README.md now sits next to the dump on local disk with provenance, the table inventory, a loader script (no MySQL needed) and the queries behind every number above.

Verification

hugo builds clean, validate/Frontmatter.java --changed-since main passes, validate/BuiltSite.java reports only pre-existing dead links in untouched posts, and all eleven new aliases plus both repaired posts were checked in public/.

🤖 Generated with Claude Code

Frank Delporte and others added 5 commits September 21, 2026 11:30
Diffing the 2026-09-21 database dump against content/ found eight published
posts whose wp_posts.post_modified is newer than the lastmod here -- authors
still editing on WordPress after this repo had taken its copy. Seven were
re-fetched with transfer/Posts.java --url; boxlang-1-16-0-released is frozen,
so its four added categories were applied by hand.

What actually changed, beyond lastmod:

  hibernate-orm-and-mongodb (both parts)  the sample repo moved to
                                          mongodb-jvm-showcase and the
                                          per-article git tags were dropped
  whats-new-...-azul-payara-release       two sections reordered
  foojay-podcast-75                       + DuckDB
  foojay-podcast-101                      - OpenJDK
  building-an-agentic-wms-part-1          + Java, + Mongo
  boxlang-1-16-0-released                 + Developer Tools, Java, Java Core,
                                          Release Notes
  did-your-ai-agent-run-the-debugger      title only -- see below

Three converter regressions the re-scrape introduced are corrected in the same
commit, because they are noise rather than author intent: a space eaten after
an inline link in each hibernate post, and `&` escaped to `\&` three times in
the Payara post.

did-your-ai-agent-run-the-debugger is the awkward one: the WordPress edit that
produced its new title ALSO mangled six links in the body -- schemes stripped
("github.com/obra/superpowers"), doubled ("http:https://...///"), one anchor
text spliced into the middle of another. The dump confirms the damage is in
post_content itself, so it is the live copy that is broken and a re-scrape
reproduces it faithfully. That post keeps the new title and the old body, and
is now frozen so the next run cannot re-import the damage.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The 2026-09-21 SQL dump is the first source for this migration that is not a
scrape, and diffing it against content/ turned up four gaps the scraper could
not have closed, because in each case the live HTML is not where the fact
lives.

1. keeping-your-fonts-in-embedded-svg had NO BODY at all -- frontmatter and
   nothing else, live on the site that way. The WordPress page serves an empty
   .article__main-content, so transfer/Posts.java rewrites it to empty on every
   run and says so ("body is only 0 word(s) and REST offered nothing better").
   wp_posts.post_content holds the real 90 KB article; it is rebuilt here
   through the repo's own HtmlToMarkdown, with the two body images pulled into
   the bundle. Frozen, or the next run blanks it again. The one departure from
   what WordPress held -- an 81,661-character base64 font payload elided inside
   the self-contained-SVG listing -- is argued in the frontmatter.

2. calling-microservices-in-java was the only post with a featured image in
   WordPress and none here. Its og:image URL contains a NARROW NO-BREAK SPACE
   (U+202F) that WordPress emits unencoded, which the scraper cannot fetch.
   Pulled by hand with the space percent-encoded, renamed with a hyphen (no
   other file under content/ has a space in its name). Frozen for the same
   reason as above.

3. Eleven redirects that would have 404'd. Nine come from `_wp_old_slug`, the
   postmeta WordPress writes when a post is renamed and then redirects from for
   ever -- invisible to the Redirection plugin export the aliases were built
   from, which lists only redirects somebody added. The other two are plugin
   rules 106/107, added after that export was taken. Same blind spot as
   CUTOVER's rules 4 and 5, and the CUTOVER note now says to re-run the query
   against the final dump.

4. Five author social links, on two profiles. Stefan Richthofer's three the
   scraper would pick up today; Maximillian Arruda's LinkedIn and YouTube it
   never will -- he routes them through link.maxdearruda.com and the scraper
   classifies a social link by host, so it writes "" over both on every run.
   The usermeta keys in the dump name the network outright. His profile is
   frozen; verified by re-running Authors.java over both.

Two more flagged by the diff are NOT changed here, on purpose. The `user_url`
of iryna-dohndorf and micksembwever is the same LinkedIn URL their profiles
already carry, so carrying it into `website:` would print one link twice.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
WordPress had alt="" on all five, so there was nothing to carry over, and the
whole point of this article is what the pictures show: the same drawing with
the handwritten Virgil font and with the browser's fallback. Without a
description a screen-reader user gets the argument with the evidence removed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Phase 1 is built around scraping a site that is about to be switched off, and
three of its items say some version of "this cannot be re-run after cutover".
A phpMyAdmin dump of wp_foojay makes all three false, so the phase now opens by
saying to take the dump FIRST.

  view counts      wp_post_views WHERE type='4' is the per-post total, exactly,
                   in one query. Not merely tidier than the crawl: on
                   2026-09-21 the crawl-built data/legacy-views.json was 87,617
                   views light across 2,169 posts and missing 91 posts
                   outright. Nothing was over-counted, so every difference is
                   something the crawl did not see. Rebuild the file from the
                   dump before seeding.

  comment archive  wp_comments holds every comment. The 2026-09-21 diff found
                   content/posts/**/comments.json already complete -- 590
                   approved on 276 posts -- so this stops being a deadline.

  CloudflareEmails obfuscation happens at Cloudflare's edge, so post_content is
                   clean; 233 posts carry a raw address there. Still worth
                   running the script while WordPress is up, but a missed
                   address is now recoverable rather than gone. One is not, and
                   the note says which and why: that placeholder is baked into
                   post_content too.

Two things the intro is explicit about, because both are easy to assume wrong:
the dump does NOT contain the media files, and it holds password hashes and
commenter IPs, so it lives outside this repo with its own README.

The redirect section gains the `_wp_old_slug` blind spot -- a third family the
plugin export never knew about, alongside rules 4 and 5 -- with the query to
re-run against the final dump, and the alias count moves 86/89 -> 88/92.

The hero-image and canonical-URL audits are untouched: those probe third-party
URLs and still need the network.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings September 21, 2026 09:38
@coderabbitai

coderabbitai Bot commented Sep 21, 2026

Copy link
Copy Markdown

Review Change StackReview Change Stack

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 742f3023-6cc8-4e76-a783-f7d08b277e8f

📥 Commits

Reviewing files that changed from the base of the PR and between cf6e13e and 1a80e64.

⛔ Files ignored due to path filters (3)
  • content/posts/2024/01/23/keeping-your-fonts-in-embedded-svg/sample-with-font.png is excluded by !**/*.png
  • content/posts/2024/01/23/keeping-your-fonts-in-embedded-svg/sample.png is excluded by !**/*.png
  • content/posts/2024/05/17/calling-microservices-in-java/Screenshot-1445-10-05-at-7.23.37-AM.png is excluded by !**/*.png
📒 Files selected for processing (23)
  • CUTOVER.md
  • content/authors/maximillian-arruda/_index.md
  • content/authors/stefan-richthofer/_index.md
  • content/posts/2020/08/24/container-awareness-for-java/index.md
  • content/posts/2020/08/26/monitoring-rest-apis-with-custom-flight-recorder-events/index.md
  • content/posts/2020/10/22/peter-lawrey-latency-performance/index.md
  • content/posts/2020/11/25/native-applications-for-multiple-devices-from-a-single-javafx-project-with-gluon-mobile-and-github-actions/index.md
  • content/posts/2020/12/15/how-when-to-use-jdk-flight-recorder-in-production/index.md
  • content/posts/2021/02/11/safe-writing-to-files-in-iot-and-industrial-systems/index.md
  • content/posts/2021/04/28/beginning-javafx-with-intellij/index.md
  • content/posts/2021/11/11/visual-recognition-for-chess-with-deep-learning-in-java-on-android/index.md
  • content/posts/2021/11/25/book-review-effortless-cloud-native-app-development-using-skaffold-2/index.md
  • content/posts/2024/01/23/keeping-your-fonts-in-embedded-svg/index.md
  • content/posts/2024/05/17/calling-microservices-in-java/index.md
  • content/posts/2025/07/14/foojay-podcast-75/index.md
  • content/posts/2025/11/04/getting-started-with-hibernate-orm-and-mongodb/index.md
  • content/posts/2025/11/04/modeling-relationships-with-hibernate-orm-and-mongodb/index.md
  • content/posts/2026/08/25/boxlang-1-16-0-released/index.md
  • content/posts/2026/09/03/building-an-agentic-warehouse-management-system-part-1-where-ai-agents-add-value/index.md
  • content/posts/2026/09/03/did-your-ai-agent-run-the-debugger-one-jvm-bug-two-agent-runs/index.md
  • content/posts/2026/09/08/commit-created-no-no-no-what-the-the-agents-word-needs-external-verification-what-the-mistake-costs/index.md
  • content/posts/2026/09/14/foojay-podcast-101/index.md
  • content/posts/2026/09/16/whats-new-in-the-september-2026-azul-payara-release/index.md
 ___________________________________________________________
< Your API returns 200 OK; your users return 404 Not Found. >
 -----------------------------------------------------------
  \
   \   \
        \ /\
        ( )
      .( o ).
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@FDelporte
FDelporte merged commit 1a80e64 into main Sep 21, 2026
1 of 3 checks passed
@FDelporte
FDelporte deleted the wp-dump-repairs branch September 21, 2026 09:39

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

This branch was successfully deployed

1 active deployment
github-pages 1a80e64e Deployed Sep 21, 2026 by FDelporte via deploy #387
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants