Dashboard › cli › Distillation
a551cc77-7407-4796-bf59-523b38ac5bec["lore_tm_v1_8uvbF6EoNve9q8emMJtFpyA-0XBRSvsanG5UR0vaQwU","lore_tm_v1_CGhADkT6-mggMSahi7lApi8bxPGC3vImaV8jlnuWH6M","lore_tm_v1_zcN9KSA5gRdirQW8z9zSUO-tkbn8SN_mLbw1VxAn8rY","lore_tm_v1_AnIz2AN7CMpWCH4RWRxoITomN90atSkgA4MkkAAHR-0","lore_tm_v1_zwGj2M4n0UfAySa-FA_j3quqa7x5zmzXUoefrXh4VAI","lore_tm_v1_GXHKtQvT2QJ-XeFvfIKu4TRIIgYH1yza2TH2iVRsM-I","lore_tm_v1_SZXPIzCHH_fGMROvVks0MTcVu31Q_wKsMSVPeciBo-A"]
packages/cli/install:8-75 implements fire-and-forget Sentry installer error telemetry through the envelope API, using the CLI’s public write-only DSN, collecting no PII, and honoring SENTRY_CLI_NO_TELEMETRY=1. report_error() runs in a background subshell so it “never blocks installation or propagates failures”; inside, set +e enforces that telemetry must “never fail the script.” It generates an event UUID via /proc/sys/kernel/random/uuid, then uuidgen, then an awk fallback; JSON-escapes message, step, channel, and version; tags os, arch, libc, channel, step, and install.version; identifies runtime as Bash; and posts with curl -sf --max-time 2.packages/cli/install:65-75 defines die() to print an error, call report_error, wait for the background telemetry request while ignoring its exit status, and exit 1. An ERR trap reports Unexpected failure at line $LINENO with step "trap" for failures caused by set -euo pipefail.packages/cli/install:213-275 currently resolves nightly builds only from hard-coded getsentry/cli: token scope repository:getsentry/cli:pull, manifest URL https://ghcr.io/v2/getsentry/cli/manifests/nightly, and blob URL https://ghcr.io/v2/getsentry/cli/blobs/${digest}. It parses token, version, and layer digest with awk, selects sentry-${os}-${arch}${libc_suffix}${suffix}.gz, manually extracts the GHCR redirect URL so the authorization header is not forwarded to Azure Blob Storage, then downloads and pipes through gunzip.packages/cli/install:276-303 currently resolves stable releases only from hard-coded getsentry/cli: latest version via https://api.github.com/repos/getsentry/cli/releases/latest and assets via https://github.com/getsentry/cli/releases/download/${version}/${filename}. It strips a leading v, tries the gzip asset first (documented as approximately 37 MB versus 99 MB, about 60% smaller), then falls back to the raw binary.packages/cli/install:308-361 delegates installation to "$tmp_binary" cli setup with --install --method curl --channel nightly|stable, forwarding --no-modify-path, --no-completions, and --no-agent-skills. With SENTRY_INIT=1, it searches SENTRY_INSTALL_DIR, an absolute XDG_BIN_HOME, $HOME/.local/bin, $HOME/bin, and $HOME/.sentry/bin in that order, requires /dev/tty, and executes sentry init </dev/tty.packages/cli/src/lib/binary.ts introduce UpgradeSource with exact fields githubRepo, ghcrRepo, and tagPrefix, plus ordered UPGRADE_SOURCES: 1. { githubRepo: "getsentry/toolkit", ghcrRepo: "getsentry/toolkit", tagPrefix: "cli@" }; 2. { githubRepo: "getsentry/cli", ghcrRepo: "getsentry/cli", tagPrefix: "" }. PRIMARY_UPGRADE_SOURCE is UPGRADE_SOURCES[0], making Toolkit the default and the legacy CLI repository the fallback.getBinaryDownloadUrl(version, source = PRIMARY_UPGRADE_SOURCE) now constructs the release tag as ${source.tagPrefix}${version} and returns https://github.com/${source.githubRepo}/releases/download/${tag}/${getPlatformBinaryName()}. getGitHubReleasesUrl(source = PRIMARY_UPGRADE_SOURCE) returns https://api.github.com/repos/${source.githubRepo}/releases, and GITHUB_RELEASES_URL now points to the primary Toolkit source.resolveUpgradeSource(fetchFn = customFetch, signal?) probes each UPGRADE_SOURCES entry at ${getGitHubReleasesUrl(source)}/latest with getGitHubHeaders() and the optional abort signal. It returns both the selected source and successful response, so the caller “never repeats the request.” It falls through only on HTTP 404; any other HTTP status immediately throws UpgradeError("network_error", "Failed to fetch from GitHub: HTTP ..."); raw network failures propagate immediately; and all sources returning 404 throws UpgradeError("network_error", "No CLI upgrade source was found: every source returned HTTP 404").packages/cli/test/lib/binary.test.ts adds exact source-order coverage and resolveUpgradeSource() tests for: first-source success with one Toolkit request; Toolkit 404 followed by legacy CLI success; no fallback for HTTP 401, 403, 429, or 500; no fallback for TypeError("fetch failed"); and failure after both Toolkit and legacy CLI return 404.packages/cli/test/lib/ghcr.test.ts adds source-selection tests requiring getAnonymousToken(UPGRADE_SOURCES[0]) to request scope repository:getsentry/toolkit:pull and return "toolkit-token", and requiring fetchNightlyManifest("token", undefined, UPGRADE_SOURCES[0]) to request /v2/getsentry/toolkit/manifests/nightly.packages/cli/test/lib/install-script.test.ts adds a synchronization test requiring packages/cli/install to define a single-line shell array matching /^UPGRADE_SOURCES=\(([^)]*)\)$/m, with entries exactly equal to UPGRADE_SOURCES.map((source) => source.githubRepo) in shared order. The displayed 362-line installer does not yet contain UPGRADE_SOURCES, while its stable and nightly URLs remain hard-coded to getsentry/cli.packages/cli/src/lib/release-notes.ts:543-612 uses CHANGELOG_MAX_RELEASES = 30 and fetches ${GITHUB_RELEASES_URL}?per_page=30; because GITHUB_RELEASES_URL now defaults to PRIMARY_UPGRADE_SOURCE, stable changelog requests implicitly target getsentry/toolkit. The function returns [] on network failure, non-OK response, non-JSON data, or a non-array payload, and fetchStableChangelog() can instead consume caller-provided prefetchedReleases.packages/cli/src/lib/release-notes.ts:630-694 still hard-codes nightly changelog commits to https://api.github.com/repos/getsentry/cli/commits?sha=main&since=${sinceDate}&until=${untilDate}&per_page=100, rather than using the selected upgrade source. It derives timestamps from X.Y.Z-dev.<unix-seconds>, adds 1 second to both bounds because GitHub since is inclusive and until is exclusive, and returns null for invalid versions, fetch failures, non-OK responses, malformed JSON, or an empty/non-array response.fetchChangelog() is explicitly best-effort: it dispatches nightly upgrades to fetchNightlyChangelog() and stable upgrades to fetchStableChangelog(), catches all errors and returns null, and is designed to run in parallel with binary download for zero added latency.