Dashboard › cli › Distillation
881581a7-a506-4467-aaf7-3041a305fa8d["lore_tm_v1_CG3LusErwVDlf4tP7nb-kjDAaqPByY6su3So4qnxS-g","lore_tm_v1_ADZ0yEYygMSNO3CjW_gTG2YX6xwFlBchIg28BuR62Fg","lore_tm_v1_77kuFc7ZF9V7ZWHmvX9Cvsw4ftNtSUTrUgICEL4Ienw","lore_tm_v1_5ihWtJgdf7ofFEibDewAFTHcYMx_kkfpOIq7sOb7ABM","lore_tm_v1_C8moWNfxApzrY6eAyJ1MbKiULthLdVyfd30pZ59Zkro","lore_tm_v1_oqqm7GFhY3k4vFAG-vsgg9A2ANqyaArXjHlEs1HPy3Q","lore_tm_v1_xKINMOzGrvkemDWrBQS6xGnCDhSLIGgPXmKQRrEvKxc","lore_tm_v1_vRFiIGng6kmfvaG12ik3yQ8AgTZ22f0q5VQBVX867YE","lore_tm_v1_4_rbDvyEy1AONvFkCBRQ3OLbuBMZSUtrZzZNiuIoYTY","lore_tm_v1_DGj73wReJw38gilLctf_NaomphTWvzSdUUsnphUSZd8"]
packages/cli/src/lib/release-notes.ts defines CHANGELOG_MAX_RELEASES = 30, requests ${getGitHubReleasesUrl(source)}?per_page=${CHANGELOG_MAX_RELEASES}, and builds commit-history URLs as https://api.github.com/repos/${source.githubRepo}/commits?sha=main&since=${sinceDate}&until=${untilDate}&per_page=100.packages/cli/test/lib/delta-upgrade.mocked.test.ts is isolated from delta-upgrade.test.ts because its vi.mock() assumptions conflict with dev-mode null-return tests; under bun test --isolate, each file receives a fresh module graph and mocks do not leak.packages/cli/test/lib/delta-upgrade.mocked.test.ts mocks ../../src/lib/constants.js so CLI_VERSION is "0.13.0" instead of test modeβs "0.0.0-dev", allowing canAttemptDelta() to pass its dev-build guard.globalThis.fetch in beforeEach()/afterEach(), defines mockFetch(fn), derives BINARY_NAME using getPlatformBinaryName(), and generates temporary paths with delta-iso-${Date.now()}-${Math.random().toString(36).slice(2)}-${name}."resolves and applies a stable delta patch" test in packages/cli/test/lib/delta-upgrade.mocked.test.ts models a single hop from "0.13.0" to "0.14.0" with a 500-byte patch, 100_000-byte binary and .gz assets, and patch URL https://github.com/getsentry/cli/releases/download/0.14.0/${BINARY_NAME}.patch."TRDIFF10" and whose control/diff/new sizes remain zero; chain resolution and download succeed, patching creates empty output, and resolveStableDelta("0.14.0", oldBinaryPath, destPath) is expected to throw "SHA-256 mismatch"."returns null when no chain is available" test makes every fetch return HTTP 500 and expects resolveStableDelta("0.14.0", oldBinaryPath, destPath) to return null."returns null when nightly manifest has no .gz layer" uses GHCR token "test-token" and models a nightly manifest without a .gz layer.instrumentCache(base) in packages/cli/src/lib/delta-upgrade.ts traces cache loads as cache.get and saves as cache.put; keys use patch-chain:${fromVersion}-${toVersion}, load spans set cache.key, cache.hit, and conditional cache.item_size, while save spans calculate cache.item_size from the sum of patch sizes.getPatchCache() creates an instrumented binpatch cache at join(getConfigDir(), "patch-cache").canAttemptDelta(targetVersion) returns false when CLI_VERSION === "0.0.0-dev", when current and target versions belong to different stable/nightly channels, or when the target is a downgrade; otherwise it returns true.fetchRecentReleases() in packages/cli/src/lib/delta-upgrade.ts returns [] for non-OK responses, non-array JSON, and caught errors; malformed JSON shape logs "GitHub releases response is not an array", while caught failures log "Failed to fetch recent releases from GitHub".<binaryName>, <binaryName>.gz, and <binaryName>.patch; the binary digest supplies expected SHA-256, .gz size supplies the ratio budget, and .patch supplies the delta from the prior release.extractSha256(asset) accepts digest values matching /^sha256:([0-9a-f]+)$/i and returns lowercase hexadecimal; absent or malformed digests return null. getStableTargetSha256(release, binaryName) looks up the exact binary asset and delegates to extractSha256().extractStableChain(opts) classifies failures as "no_patches", "malformed_chain", "too_long", or "over_budget": missing/misordered current or target releases produce "no_patches"; depth above MAX_STABLE_CHAIN_DEPTH produces "too_long"; a missing target digest or missing patch asset produces "malformed_chain"; and cumulative patch size above fullGzSize * SIZE_THRESHOLD_RATIO produces "over_budget".{ fromVersion, toVersion } steps beginning at currentVersion.githubReleaseSource(config) injects releasesUrl, binaryName, userAgent, optional fetch, and optional InstrumentHook; it fetches ${releasesUrl}?per_page=${MAX_STABLE_CHAIN_DEPTH + 2} under instrumentation name "fetch-releases" and downloads patches under "download-patch".githubReleaseSource.resolveChain() reports "network" for release-fetch failures and listed patch assets that fail to download, "no_patches" when the target release is absent, "malformed_chain" when the target has no ${binaryName}.gz, and otherwise forwards the classified extractStableChain() failure.packages/cli/src/lib/custom-ca.ts resolves custom CA sources once per process in priority order: 1. the SQLite-backed sentry cli defaults ca-cert path; 2. NODE_EXTRA_CA_CERTS. The first readable PEM wins.readCaCertFile(path) in packages/cli/src/lib/custom-ca.ts returns { ok: false, reason: \CA certificate file not found or not readable: ${path}` }for read failures and rejects content lacking"-----BEGIN CERTIFICATE-----"with reason"File does not contain PEM certificate data (expected -----BEGIN CERTIFICATE-----)."`.tryReadPem(path) delegates to readCaCertFile(path), logs result.reason and returns undefined on failure, and returns PEM content on success, implementing the non-throwing missing-CA requirement.injectIntoNodeTls(customPem) calls tls.setDefaultCACertificates([...rootCertificates, customPem]) to modify the process-wide trust store; on Node 22 or Bun, absence of that function makes it a no-op. Injection failures are caught and logged rather than thrown.*.sentry.io; a CA configured through sentry cli defaults ca-cert suppresses the warning because it represents explicit acknowledgment.getCustomCaCerts() calls resolve() and returns the raw PEM at resolved?.tls.ca, suitable for Node https.RequestOptions.ca and Sentry SDK NodeTransportOptions.caCerts, or undefined when no custom CA is configured.customFetch(input, init?) in packages/cli/src/lib/custom-ca.ts calls bare fetch(input, init) when getCustomTlsOptions() returns nothing; otherwise it calls fetch(input, { ...init, ...tlsOpts }). Non-authenticated fetch sites should use customFetch(), while authenticated API calls use fetchWithTimeout() in sentry-client.ts.__resetForTests() resets custom-CA cached state: resolved = undefined, resolvedSource = "none", resolvedLabel = "", hasResolved = false, and warnedSaas = false.resolveNightlyChain(opts) uses preloadedTags when supplied or calls OciClient.listTags(opts.token, PATCH_TAG_PREFIX, opts.signal); it returns null when the filtered chain has zero tags or exceeds MAX_NIGHTLY_CHAIN_DEPTH, and also returns null if concurrent manifest fetching fails.resolveNightlyChain(opts) intentionally uses its local validateChainStep() rather than binpatchβs validator to preserve telemetry reasons "version-mismatch", "missing-layer", and "size-exceeded" instead of binpatchβs coarser "malformed" and "over_budget" reasons.opts.fullGzSize * SIZE_THRESHOLD_RATIO - totalSize, records each { fromVersion, toVersion } step, and sets "telemetry_reason" on the active Sentry span for validation failures. A final version mismatch or absent expected SHA-256 sets "version-mismatch" and returns null.applyPatchChain() traces "apply-patches" with operation "upgrade.delta.apply", records patches.count and patches.total_bytes, applies patch data through applyPatchChainInMemory(), and throws SHA-256 mismatch after patching: got ${sha256}, expected ${chain.expectedSha256} when output verification fails.makeProgressHandler() shows byte counts for "download"/"read" phases but percentage-only output for "apply" because multi-hop application totals every hopβs newSize and can otherwise display an inflated count such as 930 MB for a 310 MB install.onResolved sets "delta.source" and logs patch count plus formatted total size; onOfflineMiss sets source to "offline_miss"; onUnavailable sets "telemetry_reason".attemptDeltaUpgrade() records "delta.from_version", "delta.to_version", patch byte count, and chain length; emits Sentry distributions "upgrade.delta.patch_bytes" and "upgrade.delta.chain_length" with { channel }; marks unavailable results with "delta.result" = "unavailable"; and marks successful completion with span status code 1.attemptDeltaUpgrade() captures the exception at warning level with tags "delta.from_version", "delta.to_version", and "delta.channel", preserves any previously resolved "delta.source", logs Delta upgrade failed (${message}), falling back to full download, sets span status code 2, sets "delta.result" = "error" and "delta.error" = message, and returns null.prefetch() exits when delta is ineligible or the signal is aborted, resolves a chain using CLI_VERSION, and saves it only when chain.steps exists and the signal remains active.