Dashboard › cli › Distillation
beb0adc8-3e15-4965-8fc4-5b93cf6e72eb["lore_tm_v1_tP-7UAVrE7BALAkX7EGjs4DMysizl0KBTE2AxmHlfms","lore_tm_v1_OZawRrHGhjt7n3sMNWuK6moPssnGPMyr930E5dlyQnA","lore_tm_v1_vnIPFC7HaTkh2WPANynegOg6MLUIZXKePghgJTzC7Eo","lore_tm_v1_YNLogI7xI3VKO9hMOeFiB8_-Au1q3IqveejQji2xI5E","lore_tm_v1_HVumCQLOAbQkAxro_Yee8DuHxeVufegFkrvDsA1bL4o","lore_tm_v1_9G4ZOfjH4QYgWl7j8xvKihf6zOwws-kv_UJXCBfuhK8","lore_tm_v1_W789N54XeU-CDPolNDw36F7SiBuZj_yNL3BrOUHclWc","lore_tm_v1__9l84bn41nOFHwvwQX6KgpMCnbEmVqXwcHmzSzT35sQ"]
Date: September 9, 2026
binpatch package is a reusable binary delta-update engine with two parts joined by one wire contract: an apply core for parsing/applying TRDIFF10/bsdiff patch chains, and discovery via pluggable SourceStrategy implementations for OCI/GHCR tags or GitHub Release assets; it uses only node:* built-ins and has zero product coupling.binpatch public API exports apply-core symbols addDiffChunk, applyPatch, applyPatchChainInMemory, applyPatchToMemory, MAX_OUTPUT_SIZE, offtin, parsePatchHeader, and PatchHeader; cache symbols ChainMeta, chainFileName, makeCache, PatchCache, patchFileName, and PatchStepMeta; contract symbols ChainStep, DeltaResult, InstrumentHook, MAX_NIGHTLY_CHAIN_DEPTH, MAX_STABLE_CHAIN_DEPTH, PATCH_TAG_PREFIX, PatchChain, PatchLink, and SIZE_THRESHOLD_RATIO; error symbols BinpatchError and BinpatchErrorReason.binpatch public API exports progress symbols ProgressEvent, ProgressHandler, ProgressPhase, and safeProgress; the library never renders progress and only emits these events.binpatch public API exports discovery/orchestration symbols DeltaSource, DeltaTelemetry, DeltaUnavailableReason, resolveAndApply, ResolveAndApplyOpts, SourceStrategy, and UnavailableReporter.binpatch public API exports GHCR source symbols GhcrSourceConfig, ghcrSource, getPatchFromVersion, getPatchTargetSha256, filterAndSortChainTags, NightlyChainFailure, StepFailureReason, and validateChainStep; GitHub Release source symbols extractSha256, extractStableChain, ExtractStableChainOpts, GitHubAsset, GitHubRelease, GitHubReleaseSourceConfig, githubReleaseSource, getStableTargetSha256, StableChainFailure, and StableChainInfo; OCI symbols OciClient, OciClientConfig, OciLayer, and OciManifest.packages/cli/src/lib/binary.ts, packages/cli/src/lib/ghcr.ts, packages/cli/test/lib/binary.test.ts, packages/cli/test/lib/ghcr.test.ts, and packages/cli/test/lib/install-script.test.ts; diff size was 335 insertions and 25 deletions.packages/cli/src/lib/binary.ts adds UpgradeSource with exact readonly fields githubRepo, ghcrRepo, and tagPrefix.UPGRADE_SOURCES is ordered: 1. { githubRepo: "getsentry/toolkit", ghcrRepo: "getsentry/toolkit", tagPrefix: "cli@" }; 2. { githubRepo: "getsentry/cli", ghcrRepo: "getsentry/cli", tagPrefix: "" }. The resolver falls through only on HTTP 404.PRIMARY_UPGRADE_SOURCE = UPGRADE_SOURCES[0] and is the default for direct helper calls that do not first resolve a source.getBinaryDownloadUrl(version, source = PRIMARY_UPGRADE_SOURCE) now creates tag ${source.tagPrefix}${version} and returns https://github.com/${source.githubRepo}/releases/download/${tag}/${getPlatformBinaryName()}.packages/cli/src/lib/binary.ts: getGitHubReleasesUrl(source) returns https://api.github.com/repos/${source.githubRepo}/releases; getGitHubReleaseByTagUrl(version, source) appends /tags/${encodeURIComponent(tag)}; getGitHubLatestReleaseUrl(source) uses ?per_page=100 when source.tagPrefix is nonempty and /latest otherwise; getGitHubRepositoryUrl(source) returns https://api.github.com/repos/${source.githubRepo}; all default to PRIMARY_UPGRADE_SOURCE.GITHUB_RELEASES_URL remains available as the primary-source API base URL and is now initialized through getGitHubReleasesUrl().ResolvedUpgradeSource contains readonly source: UpgradeSource and readonly response: Response; returning the successful probe response ensures the caller never repeats the request.ResolveUpgradeSourceOptions contains getProbeUrl: (source: UpgradeSource) => string, optional fetch?: typeof fetch defaulting to the CLI CA-aware customFetch, and optional signal?: AbortSignal shared by every source probe.resolveUpgradeSource(options): Promise<ResolvedUpgradeSource> probes UPGRADE_SOURCES in order with getGitHubHeaders() and the shared signal; a successful response returns { source, response }; only HTTP 404 advances to the next source; every other HTTP or network failure aborts immediately.resolveUpgradeSource() rethrows AbortError; maps TLS certificate errors detected by isTlsCertError(error) to new UpgradeError("network_error", buildTlsErrorDetail(error)); maps other fetch failures to new UpgradeError("network_error", "Failed to connect to GitHub: ..."); maps non-404 HTTP failures to new UpgradeError("network_error", \Failed to fetch from GitHub: HTTP ${response.status}`); and after all sources return 404 throws new UpgradeError("network_error", "No CLI upgrade source was found: every source returned HTTP 404")`.compareVersions documentation in packages/cli/src/lib/binary.ts was corrected from saying it uses Bun.semver.order to saying it uses semver.compare, including numeric SemVer prerelease comparison for nightly versions such as X.Y.Z-dev.<unix-seconds>.packages/cli/src/lib/version-check.ts defines maybePrefetchPatches(channel, latestVersion, signal) as best-effort: it returns unless semverCompare(latestVersion, CLI_VERSION) === 1, calls prefetchNightlyPatches() for "nightly" or prefetchStablePatches() for "stable", logs prefetch failures with logger.debug("Delta patch pre-fetch failed (best-effort)", error), then opportunistically calls cleanupPatchCache() and logs cleanup failures with logger.debug("Patch cache cleanup failed (best-effort)", error).checkForUpdateInBackgroundImpl() does not block and never throws; errors are caught and reported to Sentry.checkForUpdateInBackgroundImpl() catches failures from shouldCheckForUpdate(), calls Sentry.captureException(error), and returns without crashing the CLI.pendingAbortController, choose fetchLatestNightlyVersion(signal) for the nightly channel or fetchLatestFromGitHub(signal) for stable, call setVersionCheckInfo(latestVersion), then maybePrefetchPatches(channel, latestVersion, signal) so sentry cli upgrade can apply prefetched delta patches offline.Sentry.startSpanManual with { name: "version-check", op: "version.check", forceTransaction: true }; success sets span status code 1; errors set status code 2; finally clears pendingAbortController and ends the span.AbortErrors are not reported by the background version check; other errors store version_check.error and version_check.error_type as span attributes rather than using captureException, because network failures, JSON parse errors, GitHub rate limits, and CDN errors are treated as transient infrastructure issues that should remain queryable in Discover without cluttering the Issues feed.isStderrTTY() returns Boolean(process.stderr.isTTY); update banners are suppressed for non-TTY stderr such as pipelines, CI logs, and editor-captured output, matching gh CLI behavior.notifiedThisProcess prevents a single process from counting the same update notification twice, including when sentry help is piped into less and separate code paths read the notification.canNotifyAgain(lastNotified) returns true for a first-ever notification where lastNotified === null; otherwise it requires Date.now() - lastNotified >= NOTIFICATION_INTERVAL_MS, with the DB-backed last_notified timestamp preserving the rate limit across CLI invocations.null when up to date, when cached version information is absent, when rate-limited, on non-TTY stderr, or on error; it never throws because errors are caught and reported to Sentry.packages/cli/test/lib/upgrade.test.ts tests for fetchLatestFromGitHub() expected: tag_name: "v1.2.3" → "1.2.3"; tag_name: "v0.5.0" → "0.5.0"; tag_name: "1.0.0" → "1.0.0"; HTTP 404 → UpgradeError containing "Failed to fetch from GitHub: 404"; thrown TypeError("fetch failed") → UpgradeError containing "Failed to connect to GitHub: fetch failed"; missing tag_name → "No version found in GitHub release".packages/cli/test/lib/upgrade.test.ts tests for fetchLatestFromNpm() expected: registry version "1.2.3" → "1.2.3"; HTTP 500 → UpgradeError containing "Failed to fetch from npm: 500"; thrown TypeError("fetch failed") → UpgradeError containing "Failed to connect to npm registry: fetch failed".