Skip to content

fix(update): derive RC/stable channel from the running build, not config - #978

Merged
github-actions[bot] merged 5 commits into
mainfrom
fix/update-channel-build-identity
Aug 14, 2026
Merged

fix(update): derive RC/stable channel from the running build, not config#978
github-actions[bot] merged 5 commits into
mainfrom
fix/update-channel-build-identity

Conversation

@Dumbris

@Dumbris Dumbris commented Aug 14, 2026

Copy link
Copy Markdown
Member

Problem

A user on a stable build was being offered RC updates. The update channel was resolved purely from update_check.channel / MCPPROXY_ALLOW_PRERELEASE_UPDATES, so a stale rc opt-in left over from a previously-installed RC kept a stable build on the rc channel. The core then reported update_policy.channel=rc over GET /api/v1/info, and both the Swift Sparkle tray (allowedChannels + feed selection) and the Go checker offered the next RC.

Fix

The running build's own version is now authoritative (Checker.IncludePrereleases):

Running build Channel Config/env opt-in
stable (v0.56.0) stable — never RC ignored
RC (v0.56.0-rc.1) rc (next RC + graduating stable) not needed
dev/unstamped config/env decides honored

An RC build tracks the rc channel by default, so an RC user is offered the next RC and — via the existing pure-semver comparison — its graduating stable (-rc.1 → stable). update_check.channel and the env flag now only affect dev builds (documented in the field comment + docs/prerelease-builds.md).

This one core change governs every surface: the Go checker's GitHub query, the policy the Swift Sparkle tray consumes over /api/v1/info, and the legacy Go-tray self-update path (App.includePrereleases, gated identically).

Verification

  • TDD: build-identity + policy tests (internal/updatecheck), tray gate test (internal/tray); full packages green under -race; both editions build; lint clean.
  • Live /api/v1/info proof: a stable v0.56.0 core with update_check.channel: rc reports channel: stable; an rc-stamped core reports channel: rc.

Behavior decision confirmed with maintainer: the stable→never-RC rule is absolute (build identity overrides the config/env opt-in), fixing the bug even when a stale rc config lingers.

A stable user was being offered RC updates. Root cause: the update channel
was resolved purely from update_check.channel / MCPPROXY_ALLOW_PRERELEASE_UPDATES,
so a stale `rc` opt-in left over from a previously-installed RC kept a stable
build on the rc channel — the core then reported update_policy.channel=rc over
/api/v1/info, and the Swift Sparkle tray (allowedChannels + feed selection) plus
the Go checker offered the next RC.

Make the running build's own version authoritative (Checker.IncludePrereleases):
- stable build (valid semver, no prerelease suffix) → NEVER offered an RC,
  regardless of config/env;
- RC build (-rc.N / -next.*) → tracks the rc channel by default (offered the
  next RC, and its graduating stable via existing pure-semver comparison);
- dev/unstamped build (invalid semver) → keeps the config/env opt-in, the only
  path that can exercise the rc channel without a released RC binary.

This one core change governs every surface: the Go checker's GitHub query, the
policy the Swift tray consumes over /api/v1/info, and the legacy Go-tray
self-update path (App.includePrereleases, gated the same way). Config
update_check.channel and the env flag now only affect dev builds; documented in
the field comment and docs/prerelease-builds.md.

Verified: TDD (build-identity + policy tests, tray gate test); full
internal/updatecheck and internal/tray green under -race; both editions build;
lint clean; live /api/v1/info proof — a stable v0.56.0 core with
update_check.channel=rc reports channel=stable, an rc-stamped core reports
channel=rc.
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Aug 14, 2026

Copy link
Copy Markdown

Deploying mcpproxy-docs with  Cloudflare Pages  Cloudflare Pages

Latest commit: 3212433
Status: ✅  Deploy successful!
Preview URL: https://b66dae3d.mcpproxy-docs.pages.dev
Branch Preview URL: https://fix-update-channel-build-ide.mcpproxy-docs.pages.dev

View logs

…ion handling

Codex cross-review round 1 on #978, all four findings:

- [P1] Swift Sparkle tray clamped against the CORE's version, not the app's.
  Mixed app+core versions are supported (a stable app can attach to a newer
  external RC core reporting channel=rc), so a stable app would inherit rc and
  offer ITSELF an RC. UpdatePolicyResolver.resolve now takes the app's own
  CFBundleShortVersionString and pins a stable bundle to the stable channel
  regardless of core policy; UpdateService resolves it once (injectable for
  deterministic tests). All three Sparkle hooks (feed URL, allowedChannels,
  comparator) inherit the clamp.
- [P2] go-install pseudo-versions (valid semver WITH a prerelease component,
  e.g. v0.47.1-0.2026...-abc) were force-tracked onto rc like a real -rc build.
  versionChannelKind now classifies module.IsPseudoVersion as unknown/dev, so
  the config/env opt-in governs them.
- [P2] Corrected the dev/unstamped comment: invalid-semver builds are skipped
  by the Start/CheckNow semver guard entirely; the reachable "unknown" path is
  the pseudo-version go-install build.
- [P2] Updated the docs/spec that still asserted the old config/env precedence:
  version-updates.md, configuration.md, rest-api.md, and a build-identity
  amendment (FR-013a) to specs/079.

New tests: pseudo-version classification (Go); host-bundle clamp at the
resolver and end-to-end through UpdateService→feed (Swift). Full Go
updatecheck/tray green under -race; Swift UpdatePolicy/UpdateServiceFeed green
(the remaining AppLifecycle journal failure is a pre-existing environmental
tray-lifecycle.jsonl issue, untouched by this diff).
… narrowing

Codex round 2: prerelease-builds.md said the tray simply inherits the core
channel and 'all surfaces agree', which is intentionally false for a stable
tray attached to a newer RC core — the tray narrows to stable on top of the
core policy. Document core policy as an input followed by the host-bundle
clamp.
internal/tray is //go:build !nogui && !headless && !linux (the systray App type
does not exist on Linux), so an untagged test referencing App.version /
includePrereleases broke the Linux unit-test build — cascading to all CI jobs.
Match the constraint the other tray tests carry. Local darwin builds masked it.
@codecov-commenter

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

…s link check)

The relative ../prerelease-builds.md link broke the docs build — Docusaurus
resolves it to /prerelease-builds (prerelease-builds.md is a repo doc, not a
routed site page). Match the sibling convention in docs/features/auto-update.md,
which links it via the GitHub blob URL.
@github-actions

github-actions Bot commented Aug 14, 2026

Copy link
Copy Markdown

📦 Build Artifacts

Workflow Run: View Run
Branch: fix/update-channel-build-identity

Available Artifacts

  • archive-darwin-amd64 (29 MB)
  • archive-darwin-arm64 (26 MB)
  • archive-linux-amd64 (17 MB)
  • archive-linux-arm64 (15 MB)
  • archive-windows-amd64 (28 MB)
  • archive-windows-arm64 (25 MB)
  • frontend-dist-pr (0 MB)
  • installer-dmg-darwin-amd64 (22 MB)
  • installer-dmg-darwin-arm64 (20 MB)

How to Download

Option 1: GitHub Web UI (easiest)

  1. Go to the workflow run page linked above
  2. Scroll to the bottom "Artifacts" section
  3. Click on the artifact you want to download

Option 2: GitHub CLI

gh run download 31774197969 --repo smart-mcp-proxy/mcpproxy-go

Note: Artifacts expire in 14 days.

@github-actions github-actions Bot 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.

Update-channel build-identity fix — Codex CLEAN (3 rounds); Go+Swift TDD; live /api/v1/info proof; qa-gate success

@github-actions
github-actions Bot merged commit a109a5b into main Aug 14, 2026
38 checks passed
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