Dashboard › cli › Distillation
1d36f7c3-4006-4d97-b056-e4572a01a95c["lore_tm_v1_kKaTeS_L7AuNLaZ9BOBGmLDSk2ZSy12lDUMq8B60CxU","lore_tm_v1_8Z5Bsq3fwbHMUU640A6E9uWYL5miY6harQ8WURsuv34"]
Date: Sep 10, 2026
packages/cli/src/lib/upgrade.ts expanded from 169 to 267+ lines and added source-aware upgrade resolution, GitHub release pagination, semver validation, nightly GHCR handling, and platform-specific package-manager execution.packages/cli/src/lib/upgrade.ts added imports prerelease as semverPrerelease and valid as semverValid from semver, plus compareVersions; it removed direct use of GITHUB_RELEASES_URL.packages/cli/src/lib/upgrade.ts filters out releases where release.draft || release.prerelease, tracks pagination using visitedPages.add(nextPage), and reports malformed pagination with "GitHub returned an invalid release pagination URL".packages/cli/src/lib/upgrade.ts returns Promise<ResolvedUpgradeVersion>, uses UPGRADE_SOURCES, and rejects malformed version metadata with GitHub returned invalid metadata for version ${version}.detectInstallationMethod() in packages/cli/src/lib/upgrade.ts now uses this exact priority: 1. Homebrew via cheap realpath check, overriding stale stored information; 2. stored install information in the DB as a fast path; 3. legacy detection in the order curl paths β subprocess calls β node_modules path; 4. auto-save the detected method for future runs. It returns "unknown" if detection fails.getNightlyGzFilename() in packages/cli/src/lib/upgrade.ts returns `${getPlatformBinaryName()}.gz`. GHCR nightly layers use names such as sentry-<os>-<arch>.gz, or sentry-windows-x64.exe.gz on Windows, as the matching OCI layerβs org.opencontainers.image.title annotation.UpgradeError when the downloaded file never becomes visible or stays empty.Downloaded binary is missing or empty at ${path}. .packages/cli/src/lib/upgrade.ts call spawn(pm, args, { stdio: "inherit", shell: process.platform === "win32" }); shell: true is required on Windows because npm/pnpm/yarn executables are .cmd batch files and otherwise fail with ENOENT.packages/cli/src/lib/version-check.ts now imports UpgradeSource from ./binary.js and replaces fetchLatestFromGitHub / fetchLatestNightlyVersion with fetchLatestFromGitHubWithSource / fetchLatestNightlyVersionWithSource from ./upgrade.js.maybePrefetchPatches(channel, latestVersion, signal, source) now accepts source: UpgradeSource; it calls prefetchNightlyPatches(latestVersion, signal, source) for nightly releases and prefetchStablePatches(latestVersion, signal, source) for stable releases. It only prefetches when semverCompare(latestVersion, CLI_VERSION) === 1, catches failures as best-effort, logs "Delta patch pre-fetch failed (best-effort)", and subsequently cleans stale cached patches.fetchLatestNightlyVersionWithSource(signal), stable uses fetchLatestFromGitHubWithSource(signal), both return { version: latestVersion, source }, and that exact source is passed into delta-patch prefetching.checkForUpdateInBackgroundImpl() never throws; errors are caught and reported to Sentry.checkForUpdateInBackgroundImpl() catches failures from shouldCheckForUpdate(), calls Sentry.captureException(error), and returns without crashing the CLI. Its detached manual Sentry span is named "version-check", uses operation "version.check", and sets forceTransaction: true.getUpdateNotificationWithCopy(formatNotification) returns string | null; it returns null when the CLI is up to date, cached version information is absent, notification is rate-limited, stderr is non-TTY, or an error occurs. When it returns a non-null message, it persists last_notified = now via markUpdateNotified, causing later calls inside the rate-limit window to return null.shouldSuppressNotification(args) suppresses known arguments and the management commands cli setup and cli fix. It locates the cli group and resolves its subcommand past interleaved global flags, supporting forms such as --verbose cli setup and cli --verbose setup, while avoiding false positives such as --project setup.abortPendingVersionCheck() aborts pendingAbortController if present and then sets it to null, allowing the process to exit after the main CLI work completes.