Dashboard › cli › Distillation
03d5cbeb-e6a7-4358-953e-9fc49088704a["lore_tm_v1_Gq2-qXt0jLsnLcNG5JEQHHgsxQHIh4Th8c5GNLZBGEY","lore_tm_v1_9ds2jS_yhx0iB8tw8MqDyNiJUvM-lsXfWplfdKa1UUA","lore_tm_v1_9HH4jd0_JDbioNIitITwCKYnxrIlGK_x-RUHSGDgljI","lore_tm_v1_FiWs-rx9WIyDU8KHRNnWFtzOTuHc4YVB6SaEd16H4uM"]
getsentry/cli#1244#issuecomment-4978828102 (id: 4978828102) by BYK, created and last updated 2026-07-15T09:05:00Z, whose body is Master tracking issue: https://github.com/getsentry/cli/issues/1248.extractSha256: a binary asset digest sha256:ABCDEF01 becomes lowercase abcdef01; a missing digest or non-SHA-256 digest such as md5:deadbeef returns null.getStableTargetSha256: it reads the selected binary asset’s sha256: digest (cafe in the test) and returns null when that binary asset is absent.1.2.0, 1.1.0, 1.0.0 and binary tool-linux-x64: extractStableChain must produce oldest-first steps 1.0.0 → 1.1.0 → 1.2.0, apply patch URLs in the order 1.1.0/tool-linux-x64.patch, then 1.2.0/tool-linux-x64.patch, and use target SHA-256 aaaa. Missing an in-chain patch yields { failure: "malformed_chain" }; exceeding the patch/full-gzip ratio gate yields { failure: "over_budget" }; a target not newer than current yields { failure: "no_patches" }.filterAndSortChainTags tests: keep only tags in (current, target], sort ascending, and strip invalid/out-of-range entries; for current 1.0.0 and target 1.3.0, the expected order is patch-1.1.0, patch-1.2.0, patch-1.3.0. A malformed tag such as patch-not-a-version whose comparator throws TypeError("Invalid Version") must be skipped without crashing the chain. The malformed-current test with bogus-current expects [].validateChainStep tests: a manifest with matching annotation "from-version": "1.0.0", layer title tool-linux-x64.patch, digest sha256:deadbeef, size 50, and size limit 100 returns { ok: true, digest: "sha256:deadbeef", size: 50 }; a mismatched from-version or absent named platform patch layer returns { ok: false, reason: "malformed" }; a patch size 500 against limit 100 returns { ok: false, reason: "over_budget" }.getPatchFromVersion() reads "from-version" and otherwise returns null; getPatchTargetSha256(manifest, binaryName) reads the per-binary annotation sha256-${BINARY} and returns null for an unmatched binary.ghcrSource.resolveChain SourceStrategy contract treats registry/network resolution failures as null, allowing fallback to a full download reported as unavailable, rather than throwing a system error. An unreachable registry must report "network" exactly once.from-version but contains a bogus non-platform layer such as @dep__thing@1.2.3.patch is a poisoned publish and must cause resolveChain() to return null and report "malformed_chain" exactly once.503, must report "network" and never a false malformed_chain poison alert; genuine poison is distinguished by an HTTP-200 manifest rejected by chain validation.OciClient.downloadBlob’s manually redirected blob request always carries a timeout signal, even when the caller passes signal=undefined (including prefetch), so a stalled Azure Blob Storage download can never hang the CLI forever. The redirect’s signal must be a live, non-aborted AbortSignal.OciClient must route every request through its injected fetch, never the global fetch, to preserve custom-CA and corporate-proxy interception. This applies to token exchange, manifest fetches, initial blob requests, and manually followed external blob redirects; if no fetch is injected, it defaults to globalThis.fetch.getAnonymousToken(), fetchManifest(), and downloadBlob(), with the global fetch called 0 times; a 307 redirect to https://blob.example.com/obj must also pass through the injected fetch.InstrumentHook telemetry requirements: every ghcrSource HTTP step must flow through the hook under the names ghcr-token, fetch-target-manifest, list-patch-tags, fetch-chain-manifest, and download-patch; the hook must transparently return the inner call’s value. githubReleaseSource must symmetrically instrument fetch-releases and download-patch.packages/cli/src/lib/ghcr.ts at lines 25, 197, 242, 280, 350, 446, 491, and 534, and in packages/cli/src/lib/binary.ts at lines 106, 116, 130, 236, 244, 250, 252, 259, 260, 268, 269, 278, 280, 286, 288, 302, 303, 304, and 306.packages/cli/src/lib/ghcr.ts network configuration: GHCR_REQUEST_TIMEOUT = 10_000, GHCR_MAX_RETRIES = 1, GHCR_BLOB_TIMEOUT = 30_000, TAGS_PAGE_SIZE = 100, GHCR_TAG = "nightly", GHCR_REGISTRY = "https://ghcr.io", and OCI manifest media type application/vnd.oci.image.manifest.v1+json.packages/cli/src/lib/ghcr.ts: isRetryableError() accepts TimeoutError, AbortError, and messages containing timeout, econnreset, econnrefused, network, or fetch failed; buildSignal() combines AbortSignal.timeout(timeout) with an optional external signal via AbortSignal.any; external caller aborts stop retries; fetchWithRetry() currently invokes imported customFetch and throws UpgradeError("network_error", ...) after attempts are exhausted.packages/cli/src/lib/ghcr.ts: GHCR_REPO = PRIMARY_UPGRADE_SOURCE.ghcrRepo; getAnonymousToken(sourceOrSignal, signal) supports either UpgradeSource or backward-compatible AbortSignal; fetchManifest, fetchNightlyManifest, downloadNightlyBlob, fetchTagPage, listTags, and downloadLayerBlob accept source: UpgradeSource = PRIMARY_UPGRADE_SOURCE and build URLs from source.ghcrRepo.packages/cli/src/lib/ghcr.ts: downloadNightlyBlob() uses customFetch directly for both the initial authenticated GHCR request and the manual redirect, and the redirected request receives only the caller’s raw signal at line 405. Thus, when signal is omitted, the redirected fetch currently has no timeout, contrary to the requirement that it always carry a timeout and never hang the CLI forever.packages/cli/src/lib/ghcr.ts constraint relevant to the new tests: fetchWithRetry() and downloadNightlyBlob() are hard-wired to imported customFetch; the required OciClient behavior is instead to consistently use the instance-injected fetch for all requests and redirects, never the global fetch when injection is present./v2/${source.ghcrRepo}/blobs/${digest} with bearer authorization and redirect: "manual"; accept direct HTTP 200 or redirects 301, 302, 307, and 308; require a Location header; follow the redirect without Authorization; otherwise throw UpgradeError("network_error", ...).