fix(update): loud appcast publishing + unified channel precedence - #1026
Merged
Conversation
The v0.60.0 release exposed a silent failure chain: the repository-dispatch that tells mcpproxy.app to serve the fresh Sparkle feeds 401'd on an expired MARKETING_SITE_DISPATCH_TOKEN under continue-on-error, so the site kept serving the 0.59.0 feed. Sparkle told users they were up to date while the tray menu line and doctor (GitHub API) offered v0.60.0 — and every stale window makes updates look sequential, since the single-item feed then offers exactly N-1. CI: - release.yml / prerelease.yml: drop continue-on-error from the publish-appcast dispatch steps. They run after all release assets (feeds included) are uploaded, so a red job blocks nothing — it is the recovery signal. - Add a 'Verify live feeds are fresh' step to both sparkle-appcast jobs: poll mcpproxy.app until the live bytes sha256-match the just-generated feeds (one shared 15-min deadline), mirroring the site's own verify but on the side of the broken link that actually failed. Go (divergence found while auditing the surfaces): - mcpproxy update now applies the same build-version-authoritative channel precedence as the daemon's checker (exported as updatecheck.IncludePrereleasesForBuild): a stable build never resolves against the prerelease list, even with a stale 'channel: rc' config or env opt-in, and go-install builds promote their module version first (updatecheck.PromoteGoInstallVersion) exactly like the checker. - Fix the stale 'every 4 hours' doc comment on VersionInfo.
Deploying mcpproxy-docs with
|
| Latest commit: |
6a5c442
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://14f17a6c.mcpproxy-docs.pages.dev |
| Branch Preview URL: | https://fix-autoupdate-feed-consiste.mcpproxy-docs.pages.dev |
|
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
📦 Build ArtifactsWorkflow Run: View Run Available Artifacts
How to DownloadOption 1: GitHub Web UI (easiest)
Option 2: GitHub CLI gh run download 32563959390 --repo smart-mcp-proxy/mcpproxy-go
|
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.
Problem
Two update mechanisms disagreed on v0.60.0: the Sparkle dialog said "0.59.0 is currently the newest version available" while the tray menu line and
mcpproxy doctoroffered v0.60.0.Root cause: the release run's repository-dispatch to the website repo failed with
Bad credentials(expiredMARKETING_SITE_DISPATCH_TOKEN) undercontinue-on-error: true— the release stayed green while https://mcpproxy.app/appcast-*.xml kept serving the 0.59.0 feed. Sparkle reads that feed; the menu line and doctor read the GitHub API. Because each feed carries a single item, any stale window also makes updates look sequential (users offered exactly N-1). No code path ever picks a non-latest version — the Go side always resolves/releases/latest(verified across checker, tray, doctor,update).The 0.60.0 feeds have already been backfilled manually (all four live feeds now serve 0.60.0); this PR prevents the silent recurrence.
Changes
CI
release.yml/prerelease.yml: dropcontinue-on-errorfrom the publish-appcast dispatch steps. They run after every release asset (feeds included) is uploaded, so a red job blocks nothing — it is the recovery signal. The beta feed is the only stable URL for the rc channel (GitHubreleases/latest/downloadnever resolves prereleases), so a lost beta dispatch strands every RC user.sparkle-appcastjobs get a Verify live feeds are fresh step: poll mcpproxy.app until the live bytes sha256-match the just-generated feeds (one shared 15-min deadline, check-first per feed) — mirroring the site's own verify step, but on the side of the link that actually broke.Go (divergence found while auditing all update surfaces)
mcpproxy updatenow applies the same build-version-authoritative channel precedence as the daemon's checker, via new exportedupdatecheck.IncludePrereleasesForBuild: a stable build never resolves against the prerelease list, even with a stalechannel: rcconfig or env opt-in; go-install builds promote their module version first (updatecheck.PromoteGoInstallVersion), exactly like the checker (Spec 079 FR-014/FR-023).VersionInfo(actual: 24h + failure backoff).Operational note (not in this PR)
MARKETING_SITE_DISPATCH_TOKENis still dead and needs rotation — it also broketrigger-marketing-updateon v0.60.0. With this PR, the next release will fail loudly instead of silently if the token is still invalid.Testing
TestPrereleasePreference_BuildIdentityAuthoritative(env pinned against ambient opt-ins)go test ./internal/updatecheck/... ./cmd/mcpproxy/...green; server edition green./scripts/test-api-e2e.sh: 65/65