fix(desktop): don't report a bogus update count for a shallow checkout - #51979
fix(desktop): don't report a bogus update count for a shallow checkout#51979briandevans wants to merge 2 commits into
Conversation
The desktop installer clones with `--depth 1`, so a public install's local history often shares no merge-base with the freshly fetched origin tip. In that state `git rev-list HEAD..origin/<branch> --count` enumerates the entire remote ancestry and returns a meaningless huge number, surfacing as e.g. "v0.17.0 (+12104)" in the update indicator (NousResearch#51922). The official-SSH branch of checkUpdates() already sidesteps this by reporting a binary up-to-date check (`behind: currentSha === targetSha ? 0 : 1`), and hermes_cli/banner.py guards the identical class for the CLI banner. The passive desktop count path was the one place the shallow guard was missing. Detect shallow + no-merge-base up front and fall back to the same SHA-based binary check; full clones (developers / Docker dev images) keep the exact count path unchanged. The resolution logic lives in a pure update-count.cjs helper so it is unit-testable without booting Electron.
There was a problem hiding this comment.
Pull request overview
Fixes the desktop client update indicator showing a bogus “(+N)” behind count when running from a shallow git checkout that has no merge-base with the fetched origin tip (e.g. installer --depth 1 clones).
Changes:
- Adds a small helper (
resolveBehindCount) that falls back to a SHA-based binary behind check when the repo is shallow andmerge-baseis unavailable. - Wires the helper into the non-SSH
checkUpdates()path by also probing--is-shallow-repositoryandgit merge-base. - Adds
node:testcoverage for shallow/full and merge-base/no-merge-base cases, and registers the new test in the desktop platforms test script.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| apps/desktop/package.json | Adds the new update-count unit test to the desktop platforms test suite. |
| apps/desktop/electron/update-count.cjs | Introduces resolveBehindCount() to avoid trusting rev-list --count in shallow/no-merge-base checkouts. |
| apps/desktop/electron/update-count.test.cjs | Adds unit tests covering the behind-count resolution matrix. |
| apps/desktop/electron/main.cjs | Uses shallow + merge-base probes and the helper to compute behind safely in the non-SSH update-check path. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const [currentSha, targetSha, countStr, dirtyStr, currentBranch, shallowStr, mergeBaseStr] = await Promise.all([ | ||
| git(['rev-parse', 'HEAD']), | ||
| git(['rev-parse', `origin/${branch}`]), | ||
| git(['rev-list', `HEAD..origin/${branch}`, '--count']), | ||
| git(['status', '--porcelain']), |
checkUpdates() ran `git rev-list HEAD..origin/<branch> --count` unconditionally in the parallel probe batch, even on the shallow + no-merge-base path where resolveBehindCount() ignores the result and falls back to a SHA compare. In the NousResearch#51922 failure mode that count walks the entire remote ancestry (thousands of commits), so the work was pure latency on every update check for the exact case the fix targets. Split the probes into two phases: resolve --is-shallow-repository and merge-base first, then run rev-list --count only when shouldCountCommits says the number is meaningful (full clone, or shallow-with-merge-base). The shallow/no-merge-base SHA fallback is preserved unchanged.
|
@copilot Good catch — addressed in e25d97e.
|
|
Closing to keep the queue lean — this branch has drifted into a merge conflict with |
What does this PR do?
A public desktop install is cloned with
--depth 1, so its local history often shares no merge-base with the freshly fetched origin tip. In that stategit rev-list HEAD..origin/<branch> --countenumerates the entire remote ancestry and returns a meaningless huge number, which the update indicator renders as e.g.v0.17.0 (+12104)(#51922).This mirrors the shallow-guard already present elsewhere in the codebase and brings the passive desktop update-check count path to parity:
checkUpdates()already avoids the count entirely with a binary SHA check (behind: currentSha === targetSha ? 0 : 1), andhermes_cli/banner.py(count_commits_behind) already detects shallow checkouts up front to avoid the same bogus number for the CLI banner.The non-SSH desktop count path was the one place the guard was missing. It now detects shallow + no-merge-base up front and falls back to the same SHA-based binary check; full clones (developers / Docker dev images) keep the exact count path unchanged.
Audited siblings: the SSH-remote branch of
checkUpdatesandhermes_cli/banner.pyalready guard shallow/no-merge-base; this PR brings the non-SSH desktop count path to parity. No further widening needed.Related Issue
Fixes #51922
Type of Change
Changes Made
apps/desktop/electron/update-count.cjs(new): pureresolveBehindCount()helper — returns the exactrev-listcount for full clones, but for a shallow checkout with no merge-base falls back to a binary0/1by comparing HEAD vs target SHA. Extracted so the logic is unit-testable without booting Electron (matches the existingupdate-remote.cjs/update-marker.cjsconvention).apps/desktop/electron/main.cjs: in the non-SSH branch ofcheckUpdates(), also fetchgit rev-parse --is-shallow-repositoryandgit merge-base HEAD origin/<branch>, and computebehindvia the new helper.apps/desktop/electron/update-count.test.cjs(new):node:testcoverage for the shallow/full × merge-base matrix.apps/desktop/package.json: register the new test intest:desktop:platforms.How to Test
cd apps/desktop && node --test electron/update-count.test.cjs— 6 tests pass.Number.parseInt(countStr) || 0makes the two shallow-checkout tests fail (the bogus12104count is surfaced instead of1/0); restoring the guard makes all 6 pass.npm run test:desktop:platforms— the full platforms suite still passes with the new entry (one unrelatedwindows-child-processfailure is a pre-existing baseline on cleanmain, untouched by this PR).Checklist
Code
fix(scope):,feat(scope):, etc.)node --testoverelectron/*.test.cjs) and tests passDocumentation & Housekeeping
docs/, docstrings) — or N/Acli-config.yaml.exampleif I added/changed config keys — or N/ACONTRIBUTING.mdorAGENTS.mdif I changed architecture or workflows — or N/A