docs: ship Blog 09 + fix Social 4 verb count and resolve-chain claim#2434
Merged
docs: ship Blog 09 + fix Social 4 verb count and resolve-chain claim#2434
Conversation
Two follow-ups from a fact-check pass on Social 4 (post #2430): 1. Slack post claimed "Full Kamal subcommand surface (~25 verbs)" — actual is 57 distinct command paths (9 top-level + 48 across 9 sub-command groups). The original count appeared to conflate top-level verbs with sub-command groups and undercount roughly 2x. Replaced with "50+ commands across 9 sub-command groups" plus an explicit list of the top-level rollback/audit/details verbs the original line implied were sub-command groups. 2. GitHub Discussions post claimed `${VAR}` interpolation chain begins with "CLI overrides", but no production CLI passes envOverride to ConfigLoader — every Deploy*Cli.cfc instantiates `new ConfigLoader()` with no args, so envOverride is always empty in production. The parameter exists for test injection only. Replaced with the truer 3-step user-observable chain: ".kamal/secrets → process environment variables → empty string". Matches what someone reading ConfigLoader.$resolveVar will actually see. Also fixes the stale ConfigLoader.cfc line-7 pipeline comment that listed "envOverride → System.getenv → \"\"" — it omitted .kamal/secrets, contradicting the line-13 comment in the same docstring that has the correct 4-step chain. Now matches. No code changes — the .cfc edit is a one-line comment.
Adds the launch-day blog post (Social 4 companion) to web/content/blog/posts/. Authored via the blog admin tool at localhost:8080; PostExporter wrote the file atomically. Merging this PR triggers web-deploy.yml (paths watcher on web/**), which runs the Astro build for site-blog and deploys to Cloudflare Pages — no manual `pnpm build` needed. Frontmatter: title, slug=wheels-deploy-kamal-port, publishedAt=2026-05-06, tags=[deployment, wheels-4, kamal], hand-tuned excerpt. Body matches the skeleton at docs/releases/blog-skeletons/09-wheels-deploy.md verbatim (135 lines, all 24 em-dashes preserved as proper UTF-8 — the EasyMDE-paste mojibake on initial save was repaired by rewriting the DB body and re-running the export through /jobs/runScheduledPublish). Companion social text for Slack/LinkedIn/X/Discussions is in docs/releases/blog-skeletons/social-announcements.md (Post 4) and ships unchanged via this same PR.
The post title contains a colon ("Porting Kamal to CFML: How wheels
deploy..."), and YAML treats `title: A: B` as a nested mapping. Astro
build failed with "bad indentation of a mapping entry" at line 1 col 28
(the second colon). The skeleton at docs/releases/blog-skeletons/
09-wheels-deploy.md had this correctly quoted; the blog admin tool's
YamlFrontmatter serializer dropped the quotes during export.
Quoting the title alone is enough — js-yaml now parses the frontmatter
correctly, all other fields round-tripped cleanly (publishedAt is already
quoted, excerpt uses folded-scalar `>-` syntax, etc.).
Follow-up bug to file in wheels-dev/blog: YamlFrontmatter.serialize
should always quote string values that contain `: ` (or the broader set
of YAML reserved characters), not just publishedAt/updatedAt timestamps.
Blog 09 ("Porting Kamal to CFML") now appears as the most-recent post
on the blog index — 48,980 pixels differ vs the previous baseline,
which dates from 2026-04-26 (before this post existed).
Verified the diff is solely the new post entry: top-of-index now shows
"Porting Kamal to CFML: How wheels deploy Ships 4.0 Apps Without Ruby"
with author, May 6 2026 date, hand-tuned excerpt, and tags (#deployment,
#wheels-4, #kamal). The previously-most-recent post ("Why We Rebuilt
Our CI Pipeline") shifted to second place. No other layout, sidebar,
or theme changes — landing/guides/api/packages/sentry baselines all
matched within threshold.
Baseline image taken from the visual-regression-diffs artifact of the
prior failed run (job 74642066575) — i.e. the actual PNG that CI
rendered, not a re-shot local copy.
This was referenced May 6, 2026
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.
Summary
Three coordinated changes for today's
wheels deploylaunch (Social 4 + Blog 09):1. Ship Blog 09 —
web/content/blog/posts/wheels-deploy-kamal-port.mdLaunch-day blog post, authored via the blog admin tool and exported atomically by
PostExporter. Body matches the skeleton atdocs/releases/blog-skeletons/09-wheels-deploy.mdverbatim — 135 body lines, 24 em-dashes preserved as proper UTF-8.CI auto-publishes: merging this PR triggers
web-deploy.yml(paths watcher onweb/**), which buildssite-blogvia Astro and deploys to Cloudflare Pages. No manualpnpm buildstep needed.Note on the export: the EasyMDE-paste path corrupted UTF-8 em-dashes to MacRoman mojibake (
—→‚Äî) on the initial save; the body was repaired by rewriting the DB column with the source skeleton bytes and re-firing the export through/jobs/runScheduledPublish. Title and summary were unaffected (different paste path). A follow-up bug for the EasyMDE charset issue is worth filing for the next blog post.2. Slack — "~25 verbs" → "50+ commands across 9 sub-command groups"
The Slack post under-counted the actual subcommand surface by ~2x. Counted on
develop:init,setup,rollback,config,version,details,audit,remove,docs)app(boot/start/stop/details/containers/images/logs/live/maintenance/remove)proxy(boot/reboot/start/stop/restart/details/logs/remove)accessory(boot/reboot/start/stop/restart/details/logs/remove)build(deliver/push/pull/create/remove/details/dev)registry(setup/login/logout/remove)server(exec/bootstrap)prune(all/images/containers)lock(acquire/release/status)secrets(fetch/extract/print)Replaced with
(50+ commands across 9 sub-command groups). Also reworded the trailing list to make it clear thatrollback/audit/detailsare top-level verbs, not sub-command groups.3. GitHub Discussions — drop the "CLI overrides" claim from the resolve chain
Original Discussions copy:
Reality: every production
Deploy*Cli.cfcinstantiatesnew ConfigLoader()with no args, soenvOverrideis always empty in production. It exists for test injection only. No CLI flag like--env=KEY=VALships. Replaced with the truer 3-step user-observable chain:(.kamal/secrets → process environment variables → empty string).4. Cleanup — fix the stale
ConfigLoader.cfcline-7 commentLine 7 listed
(envOverride → System.getenv → ""), omitting.kamal/secrets. Eight lines below, the correct 4-step chain is documented. Now both match — closes the doc-drift loop opened by #2430.Diff stat
The .cfc change is one line, comment-only — no functional code changes.
Test plan
docs:type, no scope, header < 100 chars per commit)web-deploy.ymljob runs on merge — buildssite-blog, deploys to Cloudflare Pageshttps://blog.wheels.dev/wheels-deploy-kamal-portrenders with em-dashes as—, code blocks intact,${VAR}shown literallysocial-announcements.mdfor fluency before posting