Skip to content

Comments

🤖 feat: add stable/nightly Electron update channels#2430

Merged
ibetitsmike merged 13 commits intomainfrom
mike/stable-latest-update-channels
Feb 20, 2026
Merged

🤖 feat: add stable/nightly Electron update channels#2430
ibetitsmike merged 13 commits intomainfrom
mike/stable-latest-update-channels

Conversation

@ibetitsmike
Copy link
Contributor

@ibetitsmike ibetitsmike commented Feb 14, 2026

Summary

Adds a user-selectable update channel (Stable / Nightly) to the Mux Electron app. Users can switch channels from the About dialog; the choice is persisted in ~/.mux/config.json and takes effect immediately at runtime.

Background

The Electron app currently updates only from official GitHub Releases ("Stable"). This PR adds support for a "Nightly" channel that pulls pre-release builds published from main. This gives users who want bleeding-edge features an opt-in path without disrupting the default stable experience.

Implementation

Config layer (src/node/config.ts)

  • New UpdateChannel type ("stable" | "nightly") with parseUpdateChannel() validation.
  • Persisted in config.json — only non-default values are written (stable is the default, so the key is omitted when on stable).

Desktop updater (src/desktop/updater.ts)

  • applyChannel() configures autoUpdater: allowPrerelease, channel, feed URL releaseType.
  • setChannel() method with state guards (blocks switching during download/install).
  • Transient error filtering (404s, network timeouts) to avoid noisy errors during manifest propagation.

oRPC surface (src/common/orpc/schemas/api.ts, src/node/orpc/router.ts)

  • update.getChannel / update.setChannel endpoints with Zod-validated UpdateChannelSchema.

Frontend (src/browser/components/About/AboutDialog.tsx)

  • Channel picker using standard ToggleGroup segmented control (size="sm", matching other consumers).
  • Race condition protection via channelRequestTokenRef counter.
  • Channel state initialized to null until fetched, preventing layout flicker.
  • Local pendingAction state gives immediate click feedback (spinner + disabled) for Check, Download, and Install buttons while waiting for the backend status stream to catch up.

Button press feedback (src/browser/components/ui/button.tsx)

  • Added active:scale-[0.98] press animation and transition-all so all buttons give tactile click feedback.

CI: manifest naming (scripts/set-package-version.js)

  • Detects prerelease suffix (e.g. -nightly.N) and sets build.publish.channel in package.json so electron-builder generates channel-specific manifests (nightly.yml, nightly-mac.yml) instead of latest.yml.

Validation

  • All static checks pass locally (make static-check: typecheck, lint, fmt, broken links).
  • Updater test suite (src/desktop/updater.test.ts) covers channel switching, state guards, and transient error handling.

Risks

  • macOS code signing: The manifest naming fix (set-package-version.js) ensures electron-updater finds the correct nightly-mac.yml manifest. Previously, the build produced latest-mac.yml which caused signature validation failures when the client expected nightly-mac.yml.

Generated with mux • Model: anthropic:claude-opus-4-6 • Thinking: xhigh • Cost: $26.04

@ibetitsmike ibetitsmike changed the title 🤖 feat: add stable/latest Electron update channels 🤖 feat: add stable/nightly Electron update channels Feb 15, 2026
@ibetitsmike ibetitsmike force-pushed the mike/stable-latest-update-channels branch 2 times, most recently from 78b1466 to 1db6499 Compare February 18, 2026 08:58
@ibetitsmike ibetitsmike force-pushed the mike/stable-latest-update-channels branch from 1db6499 to 15a6196 Compare February 20, 2026 12:12
When the version string includes a prerelease suffix like '-nightly.N',
set build.publish.channel in package.json so electron-builder generates
channel-specific manifests (e.g. nightly.yml, nightly-mac.yml) instead
of the default latest.yml. This is required for electron-updater to
resolve the correct manifest when autoUpdater.channel is set to 'nightly'.
Remove custom border/rounded-none overrides that clashed with the
component's built-in segmented control appearance. Use the standard
size='sm' variant which matches other ToggleGroup consumers
(e.g. SecretsModal, SecretsSection).
@ibetitsmike
Copy link
Contributor Author

@codex review

@chatgpt-codex-connector
Copy link

Codex Review: Didn't find any major issues. Hooray!

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@ibetitsmike
Copy link
Contributor Author

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2c7bca4f4e

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@ibetitsmike
Copy link
Contributor Author

@codex review

Addressed P2 feedback: replaced hardcoded owner: "coder", repo: "mux" in applyChannel() with getGitHubRepo() helper that derives owner/repo from package.json's repository.url field (with fallback).

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9dcb939a7c

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@ibetitsmike ibetitsmike force-pushed the mike/stable-latest-update-channels branch from 9dcb939 to f0cb920 Compare February 20, 2026 14:20
@ibetitsmike
Copy link
Contributor Author

@codex review

Fixed the regex in getGitHubRepo() to handle dots in repo names (e.g. mux.desktop): changed ([^/.]+) to ([^/]+?)(?:\.git)?$ which captures the full repo name and strips the .git suffix via a non-capturing group.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f0cb920f24

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@ibetitsmike
Copy link
Contributor Author

@codex review

Fixed: all three action handlers now use .catch(console.error).finally(() => setPendingAction(...)) to clear the pending spinner even when the backend no-ops (e.g. clicking "Check" while already in downloaded state). The .finally() callback only clears if pendingAction still matches the action that set it, avoiding race conditions with other user actions.

@chatgpt-codex-connector
Copy link

Codex Review: Didn't find any major issues. You're on a roll.

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@ibetitsmike ibetitsmike added this pull request to the merge queue Feb 20, 2026
Merged via the queue into main with commit 0a5565b Feb 20, 2026
23 checks passed
@ibetitsmike ibetitsmike deleted the mike/stable-latest-update-channels branch February 20, 2026 15:55
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.

1 participant