feat(updates): persist a Stable / Pre-Release channel selector in Settings > Updates#6359
feat(updates): persist a Stable / Pre-Release channel selector in Settings > Updates#6359gatsby74 wants to merge 3 commits into
Conversation
…tings > Updates Add a Release Channel segmented control (Stable / Pre-Release) under Settings > Updates so users can opt into release-candidate builds without the hidden Shift-click menu shortcut. The choice persists via the existing -> IPC channel and is honored by both manual menu checks and the auto background check (24h timer, focus resume, nudge-driven). - shared/types: add to PersistedUIState. - main/updater: inject a callback at setupAutoUpdater and consult it through , which opts into the RC feed when the persisted channel is 'prerelease' OR a Shift-click one-shot fires. runBackgroundUpdateCheck enables prerelease before pinDefaultReleaseFeed so the right tags are fetched. - main/window: store.getUI().releaseChannel feeds the new callback. - store/slices/ui: hydrate the persisted channel via normalizeReleaseChannel; setReleaseChannel short-circuits unchanged writes and persists via window.api.ui.set, mirroring the setupGuideSidebarDismissed pattern. - settings: new SearchableSetting row with SettingsSegmentedControl. - Shift-click affordance in register-app-menu is preserved as a power-user one-shot that overrides a single check. Tests: - updater.test.ts: persisted 'prerelease' drives a menu check, the startup background check, and a stable-channel check onto the right feed tags. Feed URL and allowPrerelease assertions mirror the existing Shift-click test. - updater.test.ts: persisted 'prerelease' is honored on the startup background check. - updater.test.ts: persisted 'stable' keeps the stable feed pinned. - ui.test.ts: idempotent persistence (call once, no double-write); hydration restores explicit 'prerelease' and falls back to 'stable'.
📝 WalkthroughWalkthroughAdds persisted 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: db7ef256-c102-41fb-afcb-c4ae0a9a7c78
📒 Files selected for processing (12)
src/main/updater.test.tssrc/main/updater.tssrc/main/window/attach-main-window-services.tssrc/renderer/src/components/settings/GeneralUpdateSettingsSection.tsxsrc/renderer/src/i18n/locales/en.jsonsrc/renderer/src/i18n/locales/es.jsonsrc/renderer/src/i18n/locales/ja.jsonsrc/renderer/src/i18n/locales/ko.jsonsrc/renderer/src/i18n/locales/zh.jsonsrc/renderer/src/store/slices/ui.test.tssrc/renderer/src/store/slices/ui.tssrc/shared/types.ts
…ts to stable CodeRabbit (🟠 Major) on PR stablyai#6359: once `includePrereleaseActive` becomes true (via Shift-click or the persisted Pre-Release channel), there was no disable path — switching the channel back to 'stable' in Settings > Updates left subsequent menu and background checks still consuming release-candidate tags until the process restarted. Add `disableIncludePrerelease()` mirroring `enableIncludePrerelease()` and a `syncIncludePrereleaseToPersistedChannel()` wrapper. Both the menu and the background check now mirror the persisted channel onto the auto-updater's `allowPrerelease` flag before pinning the release feed: - Shift-click (`includePrerelease:true`) still wins as a per-click override and calls `enableIncludePrerelease` directly. - A plain menu check or background check now enables OR disables based on the persisted channel, so a UI revert Pre-Release -> Stable takes effect on the very next check. Test: - New: 'clears a session-sticky RC flag when a plain menu check runs after the channel reverts to stable' — captures the regression from CodeRabbit's sticky-state analysis: Shift-click sets autoUpdater.allowPrerelease = true, the persisted channel then flips to 'stable', the next plain menu check resets the flag and fetches the stable feed (tag count = 1, includePrerelease = false). Verification: - pnpm typecheck clean. - pnpm lint clean (incl. switch-exhaustiveness + localization catalog/parity). - pnpm vitest run src/main/updater.test.ts --config config/vitest.config.ts -> 76 tests pass (added 1, total +1 vs prior commit's 75).
Searching "updates" in Settings revealed the Updates section (because the section-level check matched the existing "Check for Updates" entry) but the Release Channel SearchableSetting returned null — its own inline keywords list omitted "update"/"updates"/"channel", so the row was hidden while the section was visible, leaving the title appearing without its segmented control. - inline keywords on the Release Channel SearchableSetting now include update / updates / channel in addition to release channel / stable / prerelease / rc / release candidate / beta. - getGeneralUpdateSearchEntries now includes the Release Channel row (title + description + matching localized keyword set) so section-level filter logic matches against the row content as well. Verification: - pnpm typecheck clean, pnpm lint clean (incl. localization catalog/parity). - 224 tests pass (updater + ui slice + GeneralPane). - Dev-run confirms searching "updates" / "channel" now renders the Release Channel row with its Stable / Pre-Release segmented control.
|
Caution Failed to replace (edit) comment. This is likely due to insufficient permissions or the comment being deleted. Error details |
Summary
Adds a Release Channel selector (Stable / Pre-Release) under Settings > Updates so users can opt into release-candidate builds without the hidden Shift-click menu shortcut. The choice persists through the existing
updateUI({releaseChannel}) -> 'ui:set'IPC channel and is honored by manual menu checks, the auto 24h background check, focus-resume triggers, and nudge-driven checks. Shift-click stays as a per-click power-user one-shot override.Today the only way to receive RC builds is Shift-clicking the "Check for Updates" button — undocumented and undiscoverable. Users who want to live on RCs (or want to skip them permanently) had no persisted toggle. This surfaces the option where it belongs, alongside the existing "Check for Updates" row.
Screenshots
Settings > Updates search hit for "updates" now renders the Release Channel row with its Stable / Pre-Release segmented control fully intact — the row is matched at the section-level search catalog as well, so the interactive control no longer disappears from filtered search results.
Changes
PersistedUIState.releaseChannel?: 'stable' | 'prerelease'(optional; defaults to stable on hydration).setupAutoUpdateraccepts a newgetReleaseChannelcallback. AshouldIncludePrerelease(perClick)helper returns true whenperClick === true(Shift-click) OR_getReleaseChannel?.() === 'prerelease'. Wired intocheckForUpdatesFromMenu(outer opt-in) andrunBackgroundUpdateCheckbeforepinDefaultReleaseFeedso the right tags are fetched. The in-flight requeue branch still keys offoptions?.includePrerelease === trueonly (Shift-click) — when the persisted channel isprereleasethe in-flight is already RC, so no fresh queue is needed.disableIncludePrerelease()mirrorsenableIncludePrerelease(), plus asyncIncludePrereleaseToPersistedChannel()wrapper. Both menu and background checks now enable OR disable the auto-updater'sallowPrereleaseflag based on the current persisted channel — so a UI revert Pre-Release → Stable takes effect on the very next check instead of waiting for a process restart (this was the gap CodeRabbit flagged in the first review).store.getUI().releaseChannelfeeds the newgetReleaseChannelcallback at the existingsetupAutoUpdatercall site.normalizeReleaseChannelcoerces undefined/hydrated values to the slice literal type.setReleaseChannelshort-circuits unchanged values and persists viawindow.api.ui.set({ releaseChannel }), mirroring thesetSetupGuideSidebarDismissedidiom. Hydrate restores explicit'prerelease'and falls back to'stable'for pre-feature installs.SearchableSettingrow appended under Updates with aSettingsSegmentedControl(Stable / Pre-Release). Strings go through the standard i18ntranslate('auto.components.settings.GeneralUpdateSettingsSection.releaseChannel.*')keys (synced into en/es/ja/ko/zh catalogs).getGeneralUpdateSearchEntriesand the row's inline keywords now includeupdate/updates/channelso filtering "updates" in the Settings search shows the row WITH its segmented control (instead of hiding the content via mismatched section vs row-level keyword filters).register-app-menu.tsand the Updates button is preserved unchanged as a per-click override.Behavior matrix
Testing checklist
updater.test.ts— 4 new:prereleasewithout explicit Shift-click (assertsallowPrerelease === trueand the RC feed URL).getLastUpdateCheckAt: () => null) honors persistedprerelease(asserts the RC feed URL and tag fetch count).stablekeeps the stable feed pinned (tag count = 1,allowPrereleasestays false).allowPrerelease === falseand that the next fetch usesincludePrerelease: false).ui.test.ts— 2 new:setReleaseChannel('prerelease')called twice writeswindow.api.ui.setexactly once (idempotent persistence).prereleaseand falls back tostablewhen missing.pnpm typecheckclean.pnpm lintclean (incl. switch-exhaustiveness + localization catalog/parity across en/es/ja/ko/zh).pnpm vitest run src/main/updater.test.ts src/main/updater-prerelease-feed.test.ts src/main/updater.check-failure.test.ts src/renderer/src/store/slices/ui.test.ts src/renderer/src/components/settings/GeneralPane.test.ts --config config/vitest.config.ts— 224 tests pass.pnpm dev:the Release Channel row appears (with the Stable/Pre-Release segmented control) both when scrolling to Updates directly, and when filtering on "updates" via the Settings search bar.AI Review Report
CodeRabbit ran an automated review across the two updated commits (179c2bd → 85b47e7) and afterwards re-ran for the search-index fix (2557a2f). Findings:
enableIncludePrerelease()lacks a disable path, so reverting to Stable is ignored until restart. Fixed by addingdisableIncludePrerelease()+syncIncludePrereleaseToPersistedChannel()in commit85b47e79f— both menu and background checks now mirror the persisted channel onto the auto-updater flag. New regression testclears a session-sticky RC flag when a plain menu check runs after the channel reverts to stablecovers the disable path.Screenshots,Testing checklist,AI Review Report,Security Audit, andNotessections.shouldIncludePrerelease,disableIncludePrerelease,syncIncludePrereleaseToPersistedChannel,normalizeReleaseChannel); the residual delta is from pre-existing code in the touched files, not from these additions.No outstanding actionable threads remain on the PR.
Security Audit
Store.updateUI({...}) -> 'ui:set' -> 'ui:stateChanged'pipeline; the persistedreleaseChannelvalue is one of two closed-set literals ('stable' | 'prerelease') and validates to'stable'on the read path when corrupted or missing.stablyai/orcareleases only; no new download domains or signature-skip paths introduced.Cross-platform impact: none — no platform branches touched, no menu accelerators changed, no
metaKey/ctrlKeyshortcuts added or removed. SSH use case unaffected (the channel selection is a renderer/main-process setting; it governs the host Orca app's own auto-updater, not the SSH session lifecycle).Side effects / migrations
None. The new field is optional and defaults to
stable; pre-feature installs hydrate asstableand behave unchanged. No IPC plumbing additions, no schema migration — Orca's existingupdateUImerge +ui:stateChangedre-broadcast handles the new key automatically.Notes
powerMonitorresume, resets to the persisted choice).