Skip to content

docs: add release channels page; link from installing.mdx#2549

Merged
bpamiri merged 1 commit intodevelopfrom
peter/docs-release-channels
May 10, 2026
Merged

docs: add release channels page; link from installing.mdx#2549
bpamiri merged 1 commit intodevelopfrom
peter/docs-release-channels

Conversation

@bpamiri
Copy link
Copy Markdown
Collaborator

@bpamiri bpamiri commented May 10, 2026

Summary

Documents the new bleeding-edge channel (wheels-be) alongside stable (wheels). Doubles as the end-to-end soft-launch validation for the BE pipeline that just went live in #2545, #2547, #2548 + homebrew-wheels#174.

What's in the diff

New: start-here/release-channels.mdx

Self-contained guide covering:

  • Comparison table: package name, tracking branch, update cadence, source repo, version string shape, what wheels --version reports
  • How to tell which channel you're on — channel-aware wheels --version output
  • Install steps for each channel on macOS / Windows / Linux
  • Switching channels — uninstall one, install the other (mutually exclusive via brew's conflicts_with)
  • What happens to your apps — already-scaffolded vendor/wheels/ is unaffected; only next wheels new follows the channel switch
  • Decision guide: when to pick stable vs bleeding-edge
  • Optional "How channels work under the hood" section — snapshot version format, separate wheels-snapshots repo rationale, auto-update propagation chain (~5-10min from develop merge to user-installable)

Modified: start-here/installing.mdx

Adds a "Choose a channel" section at the top of the install instructions, pointing at the new page. Doesn't disrupt the happy path — stable is still the default and all subsequent install steps are unchanged.

Sidebar order

release-channels.mdx is order: 5, placed after the tutorial happy path:

  1. Welcome
  2. Why Wheels?
  3. Installing Wheels
  4. Your First 15 Minutes
  5. Release Channels (new)
  6. CFML Engines

Users new to Wheels follow 1→2→3→4→tutorial without bumping into channel discussion. Users who care about channels find the page from the install page's pointer or the sidebar.

Validation goals (the soft-launch part)

When this merges to develop, all of the following should happen automatically within ~10 minutes:

  1. snapshot.yml fires on the merge commit
  2. release.yml builds artifacts, publishes v4.0.0-snapshot.<run> to wheels-dev/wheels-snapshots (gates ForgeBox publish + CommandBox install on main)
  3. ✅ Linux .deb/.rpm land in the release (path-resolution bug fixed in fix: resolve Linux package output path before cd-ing into build dir #2548)
  4. ✅ Dispatch fires to homebrew-wheels with channel=bleeding-edge in payload
  5. bleeding-edge-update.yml (the new tap workflow) fires — NOT auto-update.yml
  6. ✅ Auto-bump PR opens against Formula/wheels-be.rb with the new version + sha256s
  7. ✅ Tap CI validates (brew audit + brew fetch)
  8. brew upgrade wheels-be lands the new snapshot

After this PR merges, I'll watch each step and surface any failure.

Refs

Test plan

  • CI green (commitlint, docs-validation, etc.)
  • Docs site preview deploys correctly (Starlight build)
  • After merge: validation chain steps 1-8 above all green
  • Visit https://guides.wheels.dev/v4-0-0-snapshot/start-here/release-channels/ after the docs site rebuild

Documents the new bleeding-edge channel (wheels-be) alongside stable
(wheels). Covers:

- Comparison table: package name, source repo, cadence, version shape,
  channel-aware --version output
- Install steps for each channel on macOS / Windows / Linux
- Switching channels (uninstall one, install the other — they're
  mutually exclusive via brew's conflicts_with)
- "Already-scaffolded apps are unaffected" reassurance
- Decision guide: when to pick stable vs bleeding-edge
- "How channels work under the hood" optional section explaining the
  snapshot version format, where snapshots live (wheels-snapshots
  repo), and the auto-update propagation chain

Also adds a "Choose a channel" section to installing.mdx pointing at
the new page so first-time installers see the option before they brew
install. Doesn't disrupt the happy path: stable remains the default
and the install steps below the new section are unchanged.

Sidebar order: release-channels.mdx is order 5, after the tutorial
happy path (installing → first-15-minutes → tutorial), so users new
to Wheels don't get distracted by channel discussion before they've
seen the framework run.

Doubles as a soft-launch validation: this PR's merge to develop will
fire the snapshot pipeline that just went live (PR #2545, #2547,
#2548 + homebrew-wheels#174). If the dispatch chain works end-to-end,
this commit's snapshot will land at wheels-dev/wheels-snapshots and
the brew tap's bleeding-edge-update.yml will auto-bump wheels-be.rb
to the new version within ~5 minutes.
Copy link
Copy Markdown
Contributor

@wheels-bot wheels-bot Bot left a comment

Choose a reason for hiding this comment

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

Wheels Bot — Reviewer A

TL;DR: This PR adds a well-structured release channels guide and a clean pointer in the install page. The prose and table are clear. However, three correctness issues need fixing before merge: the wheels upgrade command shown is wrong (missing subcommand, wrong semantics), the bleeding-edge RPM filename is missing the -be package name, and the /releases/latest/download/ URL pattern will silently 404 for pre-release tags on the snapshots repo.


Correctness

1. wheels upgrade --to=<version> is not the right command

release-channels.mdx, line 121:

```bash title="inside the app"
wheels upgrade --to=<version>

The actual CLI surface is `wheels upgrade check [--to=<version>]` (requires the `check` subcommand — `cli/lucli/Module.cfc` line 2361). Worse, the command explicitly says "Does not perform the upgrade — use 'brew upgrade wheels' for that" (line 2364). Presenting `wheels upgrade --to=<version>` as a way to update `vendor/wheels/` is misleading; users who run it will get a usage error and then a scan, not an in-place upgrade.

Suggested replacement prose:

```mdx
```bash title="inside the app — check for breaking changes first"
wheels upgrade check --to=<version>

Then update vendor/wheels/ manually (e.g. brew upgrade wheels-be picks up the
new runtime; your app's bundled vendor/wheels/ is refreshed on the next wheels new
or a manual copy).


Or omit the command entirely and just say "upgrade `vendor/wheels/` by re-running `wheels new` into a fresh directory and copying the `vendor/wheels/` subtree."

---

**2. Bleeding-edge RPM filename is missing `-be`**

`release-channels.mdx`, lines 88–90:
```mdx
```bash title="Fedora / RHEL (bleeding-edge)"
curl -fsSLO https://github.com/wheels-dev/wheels-snapshots/releases/latest/download/wheels-<version>.x86_64.rpm
sudo dnf install ./wheels-<version>.x86_64.rpm

The build script (`tools/distribution-drafts/linux-packages/build-linux-packages.sh` line 176) templates the filename as `${PKG_NAME}-${DEB_RPM_VERSION}.x86_64.rpm` where, for the bleeding-edge channel, `PKG_NAME="wheels-be"` (line 34). The nfpm config comment also confirms: `nfpm pkg --packager rpm --target dist/wheels-be-${WHEELS_VERSION}.x86_64.rpm`.

The correct filename is `wheels-be-<version>.x86_64.rpm`, not `wheels-<version>.x86_64.rpm`. A user copy-pasting the shown `sudo dnf install` line will get "No such file or directory."

---

**3. `/releases/latest/download/` does not resolve for pre-release tags**

`release-channels.mdx`, line 89:

https://github.com/wheels-dev/wheels-snapshots/releases/latest/download/...


GitHub's `/releases/latest` permalink resolves to the **most recent non-prerelease** release. Every bleeding-edge snapshot is tagged with a SemVer pre-release suffix (`4.0.0-snapshot.N`), so GitHub never promotes any of them to "latest." On a repo that has only pre-release tags, this URL either 404s or falls through to whatever the last GA release was — which is the wrong artifact.

The stable deb example uses the same pattern against `wheels-dev/wheels` where GA releases exist, so that one is fine. For the bleeding-edge RPM (and deb), the link should be to the specific release page (e.g. the snapshots releases index) or a documented pattern using `gh release download --repo wheels-dev/wheels-snapshots`. Alternatively, document that users should visit the releases page and download manually until proper package repos (`apt.wheels.dev` / `yum.wheels.dev`) ship.

---

### Conventions

**4. `Steps` component imported but unused**

`release-channels.mdx`, line 9:
```mdx
import { Aside, Tabs, TabItem, Steps, CardGrid, LinkCard } from '@astrojs/starlight/components';

Steps is imported but not used anywhere in the file. This is a dead import — remove it to keep the import line clean. Starlight won't error on it, but it's unnecessary.


5. Linux tab examples are asymmetric

release-channels.mdx, lines 78–95: The tab shows a stable .deb curl example and a bleeding-edge .rpm curl example, but nothing for:

  • Stable .rpm (Fedora/RHEL users wanting stable)
  • Bleeding-edge .deb (Debian/Ubuntu users wanting bleeding-edge)

This is confusing — a Fedora user who wants stable has to mentally extrapolate the package name and repo. Either show both channels per distro family, or add a note explaining the asymmetry is intentional and point to the respective releases pages.


6. Version string base in comparison table vs examples

release-channels.mdx, line 22: table shows 4.0.1-snapshot.1700 as the version shape example; line 40 and the "What snapshot means" section use 4.0.0-snapshot.1787. The differing base versions (4.0.0 vs 4.0.1) are both valid illustrations, but using the same base version across the whole doc would reduce cognitive load. Minor nit.


Commits

docs: add release channels page; link from installing.mdx — valid type (docs), no scope (fine for cross-concern docs), subject sentence-case, 56 chars. Passes commitlint.


Tests

Not applicable — documentation-only change.


Security

No concerns. No code paths touched, no credentials in fixtures.

@wheels-bot
Copy link
Copy Markdown
Contributor

wheels-bot Bot commented May 10, 2026

Wheels Bot -- Reviewer B (round 1)

A's review is accurate. All six findings hold up against the actual source, the verdict is appropriate, and there is no sycophancy. I'm aligning with CHANGES_REQUESTED and marking convergence.

Sycophancy

None detected. A acknowledges the prose quality briefly and then issues CHANGES_REQUESTED with substantive findings.

False positives

None detected. Each finding was verified:

  • Finding 1 (wheels upgrade): cli/lucli/Module.cfc line 2360 confirms: if the first arg is not check, the function prints the usage hint and returns immediately. wheels upgrade --to=<version> silently no-ops. A's finding is correct.

  • Finding 2 (RPM filename): tools/distribution-drafts/linux-packages/build-linux-packages.sh lines 32-38 set PKG_NAME="wheels-be" for the bleeding-edge channel; line 176 produces wheels-be-<version>.x86_64.rpm (via the PKG_NAME-DEB_RPM_VERSION.x86_64.rpm template), so the correct filename is wheels-be-<version>.x86_64.rpm. A's finding is correct. (Note: the build script's own header comment on line 14 shows the same wrong pattern, but that's outside this PR's scope.)

  • Finding 3 (/releases/latest/download/ for pre-releases): GitHub's /releases/latest resolves to the most recent non-prerelease, non-draft release. On a repo whose tags are all 4.0.0-snapshot.N pre-releases, the endpoint returns nothing useful. The stable deb points at wheels-dev/wheels where GA releases exist, so A is correct that the stable example is fine and the bleeding-edge one is broken.

  • Findings 4-6 (Steps import, asymmetric Linux tabs, version string inconsistency): All confirmed by reading the diff directly. Steps is imported and never used; only stable-deb and bleeding-edge-RPM examples appear; table uses 4.0.1-snapshot.1700 while body examples use 4.0.0-snapshot.1787.

Missed issues

None significant. One very minor omission: the <Aside> about filename normalization says what dpkg --info reports -- dpkg is Debian-specific; an RPM reader would use rpm -qip. The aside applies to both .deb and .rpm, so mentioning only the dpkg tool is slightly incomplete. This is below the bar for requesting changes.

Verdict alignment

CHANGES_REQUESTED is consistent with the findings. Three of the six are correctness issues (wrong CLI surface, wrong RPM filename, broken URL pattern) and any one of them warrants blocking.

Convergence

Aligned with A. All findings are valid, none need retracting, and CHANGES_REQUESTED is the right call. Marking converged-changes so the address-review pass can apply the consensus.

@bpamiri bpamiri merged commit 3b8da41 into develop May 10, 2026
14 checks passed
@bpamiri bpamiri deleted the peter/docs-release-channels branch May 10, 2026 22:13
bpamiri added a commit that referenced this pull request May 10, 2026
…loy.yml) (#2550)

* fix: pass explicit commit-message to wrangler in deploy-api-snapshot

Run 25641189988 failed at the Deploy to Cloudflare Pages step with:

  ERROR: A request to the Cloudflare API (.../pages/.../deployments) failed.
  Invalid commit message, it must be a valid UTF-8 string. [code: 8000111]

Root cause: when --commit-message is omitted, wrangler auto-derives it
from the latest git commit. The auto-generated GitHub merge commit body
for PR #2549 contained em-dashes and arrows which are valid UTF-8 but
which Cloudflare's API apparently rejects (their error message says
"UTF-8" but the actual rule appears stricter — possibly ASCII-only).

Fix: pass --commit-message explicitly with an ASCII-only string
composed of the snapshot version + workflow run ID. Both are
controlled values, no merge-commit content flows into the API call.

Reads VERSION from wheels.json inline since the Deploy step doesn't
inherit the earlier "Generate snapshot markdown" step's local VERSION
variable.

* fix: pass explicit commit-message to wrangler in web-deploy.yml too

Same wrangler/CF Pages bug as snapshot.yml — fixed in PR #2550 for the
snapshot deploy job, but web-deploy.yml has an identical wrangler
invocation that runs on every push to develop/main for all 5 sites
(guides, blog, api, landing, packages).

Without this fix, tomorrow's v4.0.0 GA tag push would trigger
web-deploy.yml across 5 sites in parallel, and if the tag commit body
or auto-derived message has non-ASCII characters (highly likely in
release notes), all 5 deploys would fail with the same CF API rejection:

  Invalid commit message, it must be a valid UTF-8 string. [code: 8000111]

Same fix as snapshot.yml: pass --commit-message explicitly with an
ASCII-only string. Bonus: deploys are now self-describing in CF Pages's
deployment list ("deploy guides from main (run 12345)").
bpamiri added a commit that referenced this pull request May 11, 2026
* ci: retry blog visual baseline auto-push with fetch+rebase loop

The "Commit pre-refreshed blog baseline" step in web-deploy.yml's visual-regression job
pushed to develop with a single `git push origin HEAD:develop` — no retry. When develop
moved during the ~3 min job runtime (e.g., another PR merging right behind a blog content
push), the push was rejected with `! [rejected] HEAD -> develop (fetch first)` and the
auto-refreshed baseline was silently dropped.

Effect: every subsequent non-blog PR tripped visual-regression on a stale baseline until
someone manually refreshed. Concrete trigger this week: PRs #2549 + #2551 merging
back-to-back left blog.png predating both "Background Jobs Without Redis" and
"Multi-Tenancy Built In" posts, blocking PR #2559 with 38,581-pixel diff.

Fix: wrap the push in a 5-attempt fetch+rebase+push loop. Rebase conflict path exits
clean (would only happen if a parallel run already refreshed the baseline, making ours
redundant). Push-rejected path retries with a short randomized backoff.

See run 25647803649 for the failure mode.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* ci: refresh stale blog baseline and address review nits

Two pieces, both fallout from the race-condition bug this PR fixes:

1. Refresh `web/tests/visual-baselines/blog.png`. The May 9 → present
   auto-refresh pushes were dropped by the bug, so develop's baseline
   predates `Background Jobs Without Redis` and `Multi-Tenancy Built In`
   posts. Without this commit, PR #2560's own visual-regression check
   stays red and every non-blog PR keeps tripping. Regenerated locally
   via `pnpm --filter @wheels-dev/site-blog build` + `node
   scripts/visual-regression.mjs --update --site blog`; verified the
   freshly-written baseline passes a subsequent check run with 0-pixel
   diff.

2. Two minor nits from Reviewer A on the retry loop:
   - Guard the final-iteration `sleep` behind `[ "$attempt" -lt 5 ]` so
     the 5th rejected push doesn't sleep 2-6s before exiting.
   - Add `|| true` to `git rebase --abort` so a failed abort (e.g.,
     already-clean rebase state) doesn't flip the intended exit-0
     conflict path to exit-1 under `set -euo pipefail`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* ci: don't print misleading "will retry" message on final attempt

Reviewer B noted that the "Push rejected on attempt $attempt; will fetch + rebase + retry."
echo runs unconditionally inside the for-loop body, so on attempt 5 it lies — there's no
retry coming, the loop falls through to exit 1. Move the echo inside the same
`[ "$attempt" -lt 5 ]` guard that already skips the backoff sleep, and emit a distinct
"final attempt, no retry" message in the else branch.

Pure cosmetic; no control-flow change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.

1 participant