docs: add release channels page; link from installing.mdx#2549
docs: add release channels page; link from installing.mdx#2549
Conversation
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.
There was a problem hiding this comment.
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 -- 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. SycophancyNone detected. A acknowledges the prose quality briefly and then issues CHANGES_REQUESTED with substantive findings. False positivesNone detected. Each finding was verified:
Missed issuesNone significant. One very minor omission: the Verdict alignmentCHANGES_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. ConvergenceAligned with A. All findings are valid, none need retracting, and CHANGES_REQUESTED is the right call. Marking |
…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)").
* 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>
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.mdxSelf-contained guide covering:
wheels --versionreportswheels --versionoutputconflicts_with)vendor/wheels/is unaffected; only nextwheels newfollows the channel switchwheels-snapshotsrepo rationale, auto-update propagation chain (~5-10min from develop merge to user-installable)Modified:
start-here/installing.mdxAdds 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.mdxisorder: 5, placed after the tutorial happy path: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:
snapshot.ymlfires on the merge commitrelease.ymlbuilds artifacts, publishesv4.0.0-snapshot.<run>to wheels-dev/wheels-snapshots (gates ForgeBox publish + CommandBox install on main).deb/.rpmland in the release (path-resolution bug fixed in fix: resolve Linux package output path before cd-ing into build dir #2548)channel=bleeding-edgein payloadbleeding-edge-update.yml(the new tap workflow) fires — NOTauto-update.ymlFormula/wheels-be.rbwith the new version + sha256sbrew audit+brew fetch)brew upgrade wheels-belands the new snapshotAfter this PR merges, I'll watch each step and surface any failure.
Refs
Test plan
https://guides.wheels.dev/v4-0-0-snapshot/start-here/release-channels/after the docs site rebuild