Skip to content

(feat): Add setting for toggling auto-downloading updates#2106

Open
KieranBond wants to merge 11 commits intoPostHog:mainfrom
KieranBond:codex-auto-download-updates-setting
Open

(feat): Add setting for toggling auto-downloading updates#2106
KieranBond wants to merge 11 commits intoPostHog:mainfrom
KieranBond:codex-auto-download-updates-setting

Conversation

@KieranBond
Copy link
Copy Markdown

@KieranBond KieranBond commented May 8, 2026

Problem

This is for anybody who wants to avoid auto-updating. Users may not have spare bandwidth to automatically pull the latest updates, or may be waiting for larger/more stable releases before updating, so this allows them to opt out of automatic downloads of the latest changes until they're ready.

Contributes to #1930 - More to come, but this solves the immediate need.

Changes

  • Adds a persisted auto-download updates setting exposed through the updates service and tRPC router.
  • Skips startup and periodic update checks when auto-download is disabled, while leaving manual checks available.
  • Updates the settings UI with optimistic switch behaviour, rollback on mutation failure, and setting-change analytics.
  • Fixes a forever-spinning 'Checking for updates' message when updater errored
image

Caveats

UX isn't the best when new updates are available.
The current logic around updates being available is tied to downloading/installing, too.

  • This means that users can only find out there's a new version by going into the settings page and manually checking. Manually checking will lead to auto-downloading.
  • I'll follow this up with a refactor to split the logic so we can push out events/state when a new version is available, thus allowing us to add a toast or other UI
    • This opens the door for things like reminders about pending updates, scheduling updates, and probably other nice-to-haves

How did you test this?

  • Added more automated tests
  • Verified by running automated tests
  • Ran locally, changed the setting, then restarted and found the setting persisted.
    • Didn't verify it didn't download the latest version, as I'm building from Windows and can't use Squirrel updates (leading to it spinning).

Publish to changelog?

yes

Copy link
Copy Markdown

@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: e23b1f0fd9

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 8, 2026

Prompt To Fix All With AI
Fix the following 3 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 3
apps/code/src/renderer/features/settings/components/sections/UpdatesSettings.tsx:136-153
Analytics fires before the mutation succeeds. If the mutation fails and the UI is rolled back, the event is already sent with the new (incorrect) value, polluting analytics data. Move `track` into `onSuccess` so it only fires once the setting change is actually persisted.

```suggestion
            setAutoDownloadEnabled(checked);

            setAutoDownloadMutation.mutate(
              { enabled: checked },
              {
                onError: () => {
                  setAutoDownloadEnabled(previous);
                },
                onSuccess: (result) => {
                  setAutoDownloadEnabled(result.enabled);
                  track(ANALYTICS_EVENTS.SETTING_CHANGED, {
                    setting_name: "auto_download_updates",
                    old_value: previous,
                    new_value: result.enabled,
                  });
                },
              },
            );
```

### Issue 2 of 3
apps/code/src/renderer/features/settings/components/sections/UpdatesSettings.tsx:24
The switch is initialized as `true` regardless of the persisted value, so users who have disabled auto-download will briefly see it toggle from "on" to "off" once the query resolves. Initializing to `undefined` and deferring render until the value is known avoids this flash.

```suggestion
  const [autoDownloadEnabled, setAutoDownloadEnabled] = useState<boolean | undefined>(undefined);
```

### Issue 3 of 3
apps/code/src/main/services/updates/service.test.ts:427-435
These two tests each only exercise one value (`false`). The project rule prefers parameterised tests, so covering both `true` and `false` in a single `it.each` is preferred here.

```suggestion
    it.each([true, false])(
      "reads auto-download toggle from settings store (%s)",
      (value) => {
        mockAutoDownloadUpdatesEnabled.mockReturnValue(value);
        expect(service.autoDownloadUpdatesEnabled).toBe(value);
      },
    );

    it.each([true, false])(
      "persists auto-download toggle changes (%s)",
      (value) => {
        service.setAutoDownloadUpdatesEnabled(value);
        expect(mockSetAutoDownloadUpdatesEnabled).toHaveBeenCalledWith(value);
      },
    );
```

Reviews (1): Last reviewed commit: "Merge branch 'main' into codex-auto-down..." | Re-trigger Greptile

Comment thread apps/code/src/renderer/features/settings/components/sections/UpdatesSettings.tsx Outdated
Comment thread apps/code/src/renderer/features/settings/components/sections/UpdatesSettings.tsx Outdated
Comment thread apps/code/src/main/services/updates/service.test.ts Outdated
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 8, 2026

Reviews (2): Last reviewed commit: "Address auto-update settings review feed..." | Re-trigger Greptile

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 8, 2026

Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 2
apps/code/src/main/services/updates/schemas.ts:20-26
**Missing TypeScript type exports for new schemas**

The file already exports derived types for every existing schema (`IsEnabledOutput`, `CheckForUpdatesOutput`, `InstallUpdateOutput`), but `autoDownloadUpdatesOutput` and `setAutoDownloadUpdatesInput` have no corresponding `export type` declarations. When callers outside tRPC's inference chain (e.g. the service or test helpers) need the types directly, they'd have to re-derive them themselves, breaking the OnceAndOnlyOnce pattern.

### Issue 2 of 2
apps/code/src/renderer/features/settings/components/sections/UpdatesSettings.tsx:84-88
**Stale query cache causes no visual feedback after enabling auto-download from UI**

The startup-check effect fires only when `autoDownload?.enabled` (the *query* value) transitions to `true`. Because `setAutoDownloadMutation` never invalidates the `getAutoDownload` query, the query cache stays `false` after the user enables the toggle — even though the setting is persisted and the backend starts checking immediately. As a result, the frontend never calls `handleCheckForUpdates()`, `checkingForUpdates` stays `false`, and no spinner is shown while the backend check is in flight. The subscription will eventually surface the result (e.g. "You're on the latest version"), but there is no intermediate visual feedback.

Calling `queryClient.invalidateQueries(trpcReact.updates.getAutoDownload.queryKey())` in the mutation's `onSuccess` would keep the two data sources in sync and allow the effect to retrigger correctly.

Reviews (3): Last reviewed commit: "Merge branch 'main' into codex-auto-down..." | Re-trigger Greptile

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 8, 2026

Reviews (4): Last reviewed commit: "Merge branch 'main' into codex-auto-down..." | Re-trigger Greptile

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 8, 2026

Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
apps/code/src/renderer/features/settings/components/sections/UpdatesSettings.tsx:76-83
**Startup check re-triggers after toggling auto-download on**

When the app starts with auto-download already persisted as `false`, the startup effect exits early and leaves `hasCheckedRef.current === false`. If the user then enables auto-download via the switch, the mutation's `onSuccess` invalidates the query, `autoDownload.enabled` changes from `false``true`, and this effect fires again — calling `handleCheckForUpdates()` a second time. The service's `setAutoDownloadUpdatesEnabled(true)` path has already called `startAutoDownloadChecks()` (and thus `checkForUpdates("periodic")`), so you end up with two concurrent check attempts. The service's `already_checking` guard absorbs the duplicate in practice, but the intent of `hasCheckedRef` — fire at most once on mount — is violated for this re-enable path.

A simple guard is to also set `hasCheckedRef.current = true` in the mutation's `onSuccess` when auto-download is being enabled, so the startup effect doesn't consider it an "initial load" check.

Reviews (5): Last reviewed commit: "Handle auto-update settings follow-up re..." | Re-trigger Greptile

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 8, 2026

Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
apps/code/src/renderer/features/settings/components/sections/UpdatesSettings.tsx:76-83
When auto-download is **disabled on mount** then enabled mid-session, `hasCheckedRef.current` is never set (the early return fires on initial load), so it remains `false`. When `autoDownload?.enabled` later changes to `true` the effect fires again and calls `handleCheckForUpdates()` — but the service's `startAutoDownloadChecks()` (triggered by the tRPC mutation) already started a background check. The service returns `already_checking`, but not before `handleCheckForUpdates` has called `setCheckingForUpdates(true)`, causing the "Check for updates" button to flash the spinner briefly. The fix is to mark the ref as consumed on the **first received boolean value**, regardless of whether it is `true` or `false`, so subsequent setting changes don't re-trigger the UI check.

```suggestion
  useEffect(() => {
    if (typeof autoDownload?.enabled !== "boolean") {
      return; // Still loading
    }
    if (hasCheckedRef.current) {
      return; // Already ran initial check
    }

    hasCheckedRef.current = true;
    if (autoDownload.enabled) {
      handleCheckForUpdates();
    }
  }, [autoDownload?.enabled, handleCheckForUpdates]);
```

Reviews (6): Last reviewed commit: "Merge branch 'main' into codex-auto-down..." | Re-trigger Greptile

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 8, 2026

Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
apps/code/src/renderer/features/settings/components/sections/UpdatesSettings.tsx:151-163
The `if (result.enabled !== previous)` guard is always true and can never suppress the `track` call. The `onCheckedChange` handler already returns early when `previous === checked`, so `checked !== previous`. The server echoes back `input.enabled` unchanged, so `result.enabled === checked !== previous`. The condition is dead code — simplify it away so the analytics intent is clearly unconditional here.

```suggestion
                  onSuccess: (result) => {
                    setAutoDownloadEnabled(result.enabled);
                    void queryClient.invalidateQueries(
                      trpcReact.updates.getAutoDownload.queryFilter(),
                    );
                    track(ANALYTICS_EVENTS.SETTING_CHANGED, {
                      setting_name: "auto_download_updates",
                      old_value: previous,
                      new_value: result.enabled,
                    });
                  },
```

Reviews (7): Last reviewed commit: "Fix auto-update startup check guard" | Re-trigger Greptile

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 8, 2026

Reviews (8): Last reviewed commit: "Simplify auto-update analytics tracking" | Re-trigger Greptile

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