feat(update): channel-aware guided update (Spec 079 US2)#818
Open
Dumbris wants to merge 11 commits into
Open
Conversation
…Spec 079 US2) Add install-channel detection (internal/updatecheck/channel.go) with a build-time marker that wins over runtime heuristics: - marker: -X github.com/smart-mcp-proxy/mcpproxy-go/internal/updatecheck.buildChannel (full module path; Go silently ignores -X with a wrong path) - heuristics in confidence order: Homebrew paths (symlink-resolved, incl. Intel-mac Cellar), /.dockerenv, deb/rpm (require BOTH /usr/bin/mcpproxy AND the owning package db — AUR/manual copies fall to unknown), .app/Contents/MacOS bundle -> dmg, go-install via debug.ReadBuildInfo Main.Version with no ldflags version, else unknown. Ambiguity never guesses (FR-008/FR-009). Add guidance (internal/updatecheck/guidance.go): exact one-line update_command only for homebrew/deb/rpm/go-install; dmg/windows-installer/ docker/tarball/unknown get channel-appropriate guidance text instead (docker guidance names no registry — no official image is published). Surface both as additive fields install_channel (always set once detected) and update_command (only when an update is available and a command exists) on VersionInfo/InfoResponseUpdate/contracts.UpdateInfo; contract test pins the six pre-existing update fields (FR-021). Pin prerelease-on-stable semantics (spec L82): v0.48.0-rc.1 vs stable v0.47.0 -> no nudge; v0.47.0-rc.4 vs v0.47.0 -> nudge to stable.
…pec 079 US2) mcpproxy status appends 'Run: <update_command>' — or the channel guidance line when no command is safe — to the Version update annotation; older daemons without install_channel keep the legacy format. mcpproxy doctor prints the same action line after its Download line. Guidance passes an empty release URL because both surfaces already print it (no duplication).
…sion (Spec 079 FR-011) isHomebrewInstallation missed /usr/local/Cellar/ and never resolved the /usr/local/bin symlink Homebrew actually exposes on Intel macs, so those installs could be offered a conflicting in-app self-update. Resolve symlinks first and add the Cellar prefix. No other tray changes (minimal-fix policy); the tray check convergence is FR-001a, out of this slice.
…Spec 079 US2) UpdateBanner.vue shows the channel's one-line update command in a copyable code block with a copy button when update_command is present; dismissal logic is untouched (per-version, FR-005). system.ts exposes installChannel/updateCommand getters. contracts.ts gains the additive UpdateInfo fields via the cmd/generate-types generator (the file is auto-generated). OpenAPI artifacts regenerated (make swagger).
…ec 079 US2) Dockerfile stamps buildChannel=docker; build-windows-installer.ps1 stamps buildChannel=windows-installer on both core and tray ldflags. The release.yml matrix builds intentionally stay unstamped (one binary feeds tarball + Homebrew + DMG, so any single value would be wrong for some consumers) — a comment at the ldflags site documents this. Makefile/ build.sh/build.ps1/pr-build.yml stay unstamped: dev builds use heuristics.
… 079 US2) rest-api.md documents the additive update.install_channel/update_command fields; version-updates.md gains 'How the Install Channel Is Detected' plus the per-channel command/guidance table.
Deploying mcpproxy-docs with
|
| Latest commit: |
0e9b2f6
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://e80ce283.mcpproxy-docs.pages.dev |
| Branch Preview URL: | https://079-upgrade-nudge-us2.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 28876786527 --repo smart-mcp-proxy/mcpproxy-go
|
…e (Spec 079 US2) Cross-model review round 1 fixes: - rpm channel: the RPM database existing only proves the host is RPM-based; a manual tarball copy to /usr/bin/mcpproxy on Fedora was misclassified as rpm and shown a wrong 'sudo dnf upgrade' command. Ownership is now confirmed with a one-shot 'rpm -qf /usr/bin/mcpproxy' probe (3s timeout, fails closed to unknown per FR-009). - dmg channel: DMG installs run the core from the tray-staged ~/Library/Application Support/mcpproxy/bin/mcpproxy (and the bundled source lives under Contents/Resources/bin), so the .app/Contents/MacOS check never matched the process serving /api/v1/info and DMG installs reported unknown. Both paths now classify as dmg; that staged directory is written only by the tray's bundle-staging, so it uniquely implies a DMG install.
…; banner guidance fallback (Spec 079 US2) Cross-model review round 2 fixes: - Prerelease targets (rc channel / MCPPROXY_ALLOW_PRERELEASE_UPDATES): prereleases are published only to the GitHub pre-release channel, so the generic package-manager commands would not deliver them — brew/ apt/dnf serve stable artifacts and Go's @latest resolves to the newest stable. When the offered version is a prerelease only go-install now gets a command, pinned to the exact version; every other channel omits the command and falls back to guidance (FR-009). - Web UI banner: channels that intentionally have no safe command (dmg/windows-installer/docker/tarball/unknown) now render the same guidance line as status/doctor instead of nothing, mirroring internal/updatecheck.GuidanceLine (FR-009/FR-010).
…ack for prerelease command channels (Spec 079 US2) Cross-model review round 3 fixes: - go-install builds carry no ldflags version (the checker received the non-semver 'development' default), so Start/CheckNow skipped checks and the go-install channel command was unreachable. The Go toolchain records the exact module version (tagged or pseudo-version) in build info — promote it into the checker's current version for that channel. - Prerelease targets on command channels (homebrew/deb/rpm/go-install without a pinnable version) had their command suppressed AND GuidanceLine returned empty for those channels, leaving status/doctor/ Web UI with no action line at all. GuidanceLine (and its Web UI mirror) now falls back to the generic release-page line; callers only invoke it when no command accompanies the update, so nothing double-renders.
…ce promoted go-install version (Spec 079 US2) Cross-model review round 4 fixes: - deb/rpm detection additionally requires the MCPProxy repository config (/etc/apt/sources.list.d/mcpproxy.list resp. /etc/yum.repos.d/mcpproxy.repo, as written by the documented setup). A standalone .deb/.rpm downloaded from a GitHub release is dpkg/rpm- owned but has no apt/dnf upgrade candidate, so the channel commands would be no-ops; those installs now degrade to unknown and get the release-page guidance (FR-009). - /api/v1/info top-level version now prefers the update checker's current version: identical for packaged builds, but for go-install builds the checker promotes the build-info module version while the ldflags default would render 'development' on status/Web UI next to a real go-install update command.
isHomebrewPath matches Unix Homebrew prefixes with forward slashes, but TestIsHomebrewPath_ResolvesSymlinks builds Cellar paths via filepath.Join, which yields backslash paths on Windows that can never match. Homebrew is macOS/Linux only, so the symlink scenario is inapplicable on Windows; skip it there while keeping full darwin/linux coverage.
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.
What / Why
Spec 079 User Story 2: a user told an update exists now sees the exact one-line command for their install channel — or safe channel-appropriate guidance when no command can be trusted. Builds on the US1 foundation (#798/#805):
internal/updatecheckstays the single source of truth; everything here is additive (FR-021).Spec:
specs/079-upgrade-nudge/spec.md(US2, FR-008..FR-011, FR-021, edge cases: prerelease-on-stable, channel mis-identification).Locked design decisions (implemented as specified)
internal/updatecheck/channel.go): build marker-X github.com/smart-mcp-proxy/mcpproxy-go/internal/updatecheck.buildChannel=<v>(full module path — documented in-code why) wins; heuristics in confidence order: Homebrew paths (symlink-resolved incl./Cellar/),/.dockerenv, deb/rpm (require BOTH/usr/bin/mcpproxyAND the owning package DB; AUR/manual copies and dual-DB ambiguity →unknown),.app/Contents/MacOS→ dmg, go-install viadebug.ReadBuildInfo()Main.Version + no ldflags version, elseunknown. Traced reality for go-install: the checker receives the"development"default (internal/server/server.go→httpapi.GetBuildVersion()), so the heuristic requires a non-semver ldflags version plus a valid non-(devel)module version. All probes injected via func fields for table tests.guidance.go): commands only for homebrew / deb / rpm / go-install (exact strings per spec); dmg / windows-installer / docker / tarball / unknown get guidance text (docker guidance names no registry — no official image is published today). Release URL deep link preserved on every path (FR-010).install_channel(always set once detected) +update_command(only when update available AND a command exists) onVersionInfo/InfoResponseUpdate/contracts.UpdateInfo/ frontendUpdateInfo. Contract tests pin all six pre-existing update fields (FR-021).docker) andscripts/build-windows-installer.ps1(windows-installer, core + tray). release.yml matrix builds intentionally unstamped (one binary feeds tarball+homebrew+dmg) with an explanatory comment at the ldflags site; dev builds rely on heuristics.mcpproxy statusappends— Run: <cmd>or the guidance line (legacy format kept for older daemons);mcpproxy doctorprintsRun:/Update:after its Download line; Web UI banner shows the command in a copyable code block with a copy button (dismissal logic untouched);system.tsgainsinstallChannel/updateCommandgetters./usr/local/Cellar/behind a/usr/local/binsymlink) were missed; now symlink-resolved + Cellar prefix. No other tray changes.v0.48.0-rc.1vs stablev0.47.0→ no nudge/no command;v0.47.0-rc.4vsv0.47.0→ nudge to stable (documented reading of spec edge case L82).make swagger(fields documented from Go comments);docs/api/rest-api.md+docs/features/version-updates.md("How the Install Channel Is Detected" + command table).Also updated
cmd/generate-types/main.go(frontendcontracts.tsis auto-generated; a hand edit is overwritten on every build).Testing
channel_test.go(marker-wins, each heuristic isolated, deb/rpm both-signals + ambiguity→unknown, go-install traced-version cases),guidance_test.go(exact commands, no-command channels, no-ghcr.io pin),checker_channel_test.go(channel always set, command gating, prerelease pins, FR-021 field-survival), status/doctor rendering tests, tray Homebrew-path tests (incl. real symlink resolution).go build ./cmd/mcpproxy+go build -tags server ./cmd/mcpproxy✅;go test -racefor updatecheck / httpapi / contracts / cmd/mcpproxy / tray ✅;golangci-lint run --config .github/.golangci.yml ./...→ 0 issues.buildChannel=homebrew+v0.40.0— also proves the full-Xpath works):/api/v1/inforeturnsinstall_channel=homebrew+update_command="brew upgrade mcpproxy";mcpproxy statusshows… — Run: brew upgrade mcpproxy;doctorshowsRun: brew upgrade mcpproxyafter Download.