Dashboard › cli › Distillation
6afce052-40f4-4c09-bcf4-2e1ed71cb55c["lore_tm_v1_e_EDaW1_8QJZSu_8gNEiTqrd-W62U0_v9zSRbalNjKg","lore_tm_v1_5Jj9Qcpxet6cLgeXHBWKKwOAVALcQpRvKdgWOHwbas4","lore_tm_v1_LoYkmknqHYrsT5wSOGQOpXrxCEg9Q8tI2vJDzJaNgJE","lore_tm_v1_ga3hrrOQamMXMTUz0-N0s8PrBRly6WPPkxkcYC1vMK8","lore_tm_v1_nkWEUlXTTny4409vlq7qEDrJD9E9K7vXZSQ9ZqK61n4","lore_tm_v1_sCoKXUXhDOIyL-eLuQ5X1A2GNZ4UtrGrcJ-m3iP5d2A","lore_tm_v1_jd39oNlBTrDLe1J_xs9Q9wcTWtGFRPoI8aFuuVKRQjg"]
packages/cli/src/lib/ghcr.ts defines request controls GHCR_REQUEST_TIMEOUT = 10_000, GHCR_MAX_RETRIES = 1, and GHCR_BLOB_TIMEOUT = 30_000.packages/cli/src/lib/ghcr.ts:isRetryableError() treats TimeoutError and AbortError names, plus messages containing timeout, econnreset, econnrefused, network, or fetch failed, as retryable; HTTP-level errors are not retryable at this layer.packages/cli/src/lib/ghcr.ts:buildSignal(timeout, externalSignal?) uses AbortSignal.timeout(timeout) and combines it with a caller signal via AbortSignal.any([timeoutSignal, externalSignal]).packages/cli/src/lib/ghcr.ts:isExternalAbort(error, externalSignal?) returns true only when the caller-provided signal is aborted and error.name === "AbortError"; fetchWithRetry() then stops immediately rather than retrying caller cancellation.packages/cli/src/lib/ghcr.ts:fetchWithRetry() makes up to 2 attempts because its loop runs from attempt 0 through GHCR_MAX_RETRIES = 1; it defaults to a 10-second per-attempt timeout and throws UpgradeError("network_error", \${context}: ${lastError?.message ?? "unknown error"}`)` when exhausted.packages/cli/src/lib/ghcr.ts: observed cold-start latency spikes from 126ms to 30s; a short timeout plus retry keeps the stated worst case near 20s.packages/cli/src/lib/ghcr.ts exports GHCR_TAG = "nightly" and uses OCI manifest media type application/vnd.oci.image.manifest.v1+json.packages/cli/src/lib/ghcr.ts defines exported types OciLayer (digest, mediaType, size, optional annotations) and OciManifest (schemaVersion, optional mediaType, optional config, layers, optional annotations).getAnonymousToken(signal?) sends User-Agent: getUserAgent(), maps non-OK token exchange responses to UpgradeError("network_error", "GHCR token exchange failed: HTTP <status>"), and maps a missing JSON token field to "GHCR token exchange returned no token".fetchManifest(token, tag, signal?) sends Authorization: Bearer <token>, Accept: application/vnd.oci.image.manifest.v1+json, and User-Agent; a non-OK response becomes UpgradeError("network_error", \Failed to fetch manifest for tag "${tag}": HTTP ${status}`)`.fetchNightlyManifest(token) is a convenience wrapper calling fetchManifest(token, GHCR_TAG) and does not currently accept or forward an external AbortSignal.getNightlyVersion(manifest) reads manifest.annotations?.version and throws UpgradeError("network_error", "Nightly manifest has no version annotation") when absent.findLayerByFilename(manifest, filename) matches layer.annotations?.["org.opencontainers.image.title"] === filename; if absent, it throws UpgradeError("version_not_found", \No nightly build found for ${filename}`)`.downloadNightlyBlob(token, digest, signal?) gives the authenticated GHCR request a 30-second timeout, uses redirect: "manual", and wraps connection failure as UpgradeError("network_error", "Failed to connect to GHCR: <message>").downloadNightlyBlob() requires a Location header, follows it with only User-Agent and the caller signal, and deliberately applies no AbortSignal.timeout() to the redirected fetch because the timeout would cover body streaming; the comment notes a full nightly binary is about 30 MB and a 30-second timeout would require sustained throughput near 8 Mbps."Failed to download from blob storage: <message>" for fetch errors and "Blob storage download failed: HTTP <status>" for non-OK responses; unsupported initial statuses map to "Unexpected GHCR blob response: HTTP <status>".TAGS_PAGE_SIZE = 100; fetchTagPage() adds &last=${encodeURIComponent(lastTag)} after the first page, returns data.tags ?? [], and maps non-OK responses to UpgradeError("network_error", "Failed to list GHCR tags: HTTP <status>").listTags(token, prefix?, signal?) repeatedly fetches pages until an empty page or a page shorter than 100 entries, advances with tags.at(-1), and includes tags only when no prefix was supplied or tag.startsWith(prefix).downloadLayerBlob(token, digest, signal?) delegates to downloadNightlyBlob() and returns response.arrayBuffer(); it is intended for small patch payloads documented as 50-500 KB.packages/cli/test/ are: lib/version-check.test.ts, lib/upgrade.test.ts, lib/scan/binary.test.ts, lib/scan/binary.property.test.ts, lib/release-notes.test.ts, lib/release-notes.property.test.ts, lib/ghcr.test.ts, lib/delta-upgrade.test.ts, lib/delta-upgrade.mocked.test.ts, lib/binary.test.ts, lib/binary.mocked.test.ts, e2e/delta-upgrade.test.ts, and commands/cli/upgrade.test.ts.packages/cli/src/lib/version-check.ts, packages/cli/src/lib/upgrade.ts, packages/cli/src/lib/scan/binary.ts, packages/cli/src/lib/release-notes.ts, packages/cli/src/lib/ghcr.ts, packages/cli/src/lib/delta-upgrade.ts, packages/cli/src/lib/db/version-check.ts, packages/cli/src/lib/binary.ts, and packages/cli/src/commands/cli/upgrade.ts.version-check.ts choosing fetchLatestNightlyVersion(signal) versus fetchLatestFromGitHub(signal), upgrade.ts checking versioned nightly tags with fetchManifest(token, \nightly-${version}`), and upgrade.tsdownloading either the requested versionβs manifest or the rolling nightly manifest before callingdownloadNightlyBlob(token, layer.digest)`.chore/preshape-monorepo tracking deleted remote origin/chore/preshape-monorepo [gone], with .lore.md modified.packages/cli/package.json defines package sentry version 0.40.0-dev.0, repository git+https://github.com/getsentry/cli.git, license FSL-1.1-Apache-2.0, "type": "module", main ./dist/index.cjs, types ./dist/index.d.cts, and binary mapping "sentry": "./dist/bin.cjs.packages/cli/package.json exports ESM through ./dist/index.mjs with ./dist/index.d.mts, and CommonJS through ./dist/index.cjs with ./dist/index.d.cts.packages/cli are dist/bin.cjs, dist/index.cjs, dist/index.mjs, dist/index.d.cts, dist/index.d.mts, dist/ink-app.js, dist/node-sqlite3-wasm.wasm, dist/vendor/symbolic_bg.wasm, LICENSE.md, and README.md.packages/cli/package.json requires Node.js >=18.0, declares development runtime Node.js >=22.15, and uses package manager pnpm@10.11.0.packages/cli/package.json contains only devDependencies, including runtime/build/test packages such as @biomejs/biome 2.3.8, @sentry/core 10.63.0, @sentry/node-core 10.63.0, @sentry/symbolic 13.7.0, @stricli/core 1.2.8, @vitest/coverage-v8 ^4.1.9, binpatch ^0.3.1, esbuild ^0.28.1, fast-check ^4.8.0, fflate ^0.8.3, fossilize ^0.10.1, hono ^4.12.27, ink ^7.1.0, node-sqlite3-wasm 0.8.59, react ^19.2.7, semver ^7.8.5, tsx ^4.22.4, typescript ^5.9.3, ultracite 6.3.10, vitest ^4.1.9, and zod ^3.25.76.packages/cli/src/lib/version-check.ts sets both CHECK_INTERVAL_MS and NOTIFICATION_INTERVAL_MS to 24 * 60 * 60 * 1000, uses JITTER_FACTOR = 0.2, and suppresses CLI subcommands "setup" and "fix".packages/cli/src/lib/upgrade.ts defines PackageManager = "npm" | "pnpm" | "bun" | "yarn", OfflineMode = false | "explicit" | "network-fallback", VERSION_PREFIX_REGEX = /^v/, VERIFY_MAX_ATTEMPTS = 6, and VERIFY_BASE_DELAY_MS = 100.packages/cli/src/lib/release-notes.ts defines change categories "features" | "fixes" | "performance", CHANGELOG_MAX_RELEASES = 30, nightly regex /^[\d.]+(?:-\w+)?-dev\.(\d+)$/, conventional-commit regex /^(\w+)(?:\([^)]*\))?:\s*(.+)$/, and version-prefix regex /^v/.package.json for the latest scripts before running project commands.devDependencies, never dependencies, because everything is bundled at build time through esbuild; CI enforces this with pnpm run check:deps.pnpm add -D <package> and specifically requires the -D flag.us.sentry.io and de.sentry.io.buildRouteMap from ../../lib/route-map.js, never directly from @stricli/core; the wrapper auto-injects standard aliases based on route keys, including delete β remove, rm.isPlainOutput() precedence is SENTRY_PLAIN_OUTPUT > NO_COLOR > FORCE_COLOR (TTY only) > !isTTY.