Dashboard › cli › Distillation
ed4c3034-cd61-404e-845a-d82e61d31195["lore_tm_v1_9KJ6CEKufkE1dXj5pBQnz30CJqIwinmUmLrfSZoaMh8","lore_tm_v1_H_3edEui042Fzziz8quR9R0okQEAx2glCxmuIg3nL2U","lore_tm_v1_rdCEySSb2sjyuNZUvBpHGMcmoI45nEn5ZF5AqnNsiKQ"]
Date: September 9, 2026
InstallationMethod in packages/cli/src/lib/binary.ts as the exact union "curl" | "brew" | "npm" | "pnpm" | "bun" | "yarn" | "unknown"; VALID_METHODS excludes "unknown", and parseInstallationMethod() lowercases input and throws Invalid method: ${value}. Must be one of: ${VALID_METHODS.join(", ")} for an unsupported method.UPGRADE_SOURCES in packages/cli/src/lib/binary.ts: 1. { githubRepo: "getsentry/toolkit", ghcrRepo: "getsentry/toolkit", tagPrefix: "cli@" }, 2. { githubRepo: "getsentry/cli", ghcrRepo: "getsentry/cli", tagPrefix: "" }; PRIMARY_UPGRADE_SOURCE is the first source.packages/cli/src/lib/binary.ts: getBinaryDownloadUrl() builds https://github.com/${source.githubRepo}/releases/download/${source.tagPrefix}${version}/${getPlatformBinaryName()}; getGitHubReleasesUrl() builds the repository releases API URL; getGitHubReleaseByTagUrl() URL-encodes the prefixed tag; getGitHubLatestReleaseUrl() uses ?per_page=100 for prefixed sources and /latest otherwise; getGitHubRepositoryUrl() builds the repository API URL.resolveUpgradeSource() returns the successful probe Response so the caller “never repeats the request”; it probes UPGRADE_SOURCES in order, falls through only on HTTP 404, returns { source, response } on success, and aborts immediately on every other HTTP or network failure.resolveUpgradeSource() error mapping in packages/cli/src/lib/binary.ts: AbortError is rethrown; TLS certificate failures become UpgradeError("network_error", buildTlsErrorDetail(error)); other connection failures become UpgradeError("network_error", \Failed to connect to GitHub: ${stringifyUnknown(error)}`); non-404 HTTP failures report Failed to fetch from GitHub: HTTP ${response.status}; exhausting all sources reports "No CLI upgrade source was found: every source returned HTTP 404"`.isMusl() in packages/cli/src/lib/binary.ts: it returns false off Linux, caches its first Linux result, first checks /lib/ld-musl-${muslArch}.so.1 where muslArch is "x86_64" for x64 and "aarch64" otherwise, then runs ldd --version and searches combined stdout/stderr case-insensitively for "musl"; a failed/missing ldd defaults to glibc (false).getPlatformBinaryName() emits sentry-<os>-<arch>[-musl][.exe]: OS is "darwin", "windows", or "linux"; architecture is "arm64" or "x64"; musl adds "-musl"; Windows adds ".exe".buildKnownCurlPaths() in packages/cli/src/lib/upgrade.ts: it adds a trailing path separator to each KNOWN_CURL_DIRS path, includes XDG_BIN_HOME only when absolute, normalizes it with join(xdgBinHome, "."), and is lazily memoized by getKnownCurlPaths() to avoid circular-import TDZ issues.getCurlInstallPaths(): a prior test install using SENTRY_INSTALL_DIR could leave a DB path to a purged directory, causing ENOENT ... open '.../sentry.lock'; the fix trusts stored info only when stored.method === "curl", stored.path exists, and existsSync(dirname(stored.path)) is true, otherwise it checks process.execPath against known curl directories and finally uses the XDG-aware determineInstallDir() default.runCommand(): spawn(command, args) uses shell: process.platform === "win32" because npm/pnpm/yarn executables are .cmd files on Windows; stdout is captured and trimmed, stderr is drained, and a null close code maps to exit code 1.packages/cli/src/lib/upgrade.ts: isInstalledWith() runs Yarn as yarn global list --depth=0, other managers as <pm> list -g sentry, and requires exit code 0 plus stdout containing "sentry@"; detectPackageManagerFromPath() requires a node_modules segment, maps a ".pnpm" segment to "pnpm", a ".bun" segment to "bun", and other npm/Yarn Classic layouts to "npm".detectInstallationMethod() prioritizes: 1. isHomebrewInstall() via a realpath containing "/Cellar/", 2. stored DB method, 3. legacy detection of known curl paths then package managers ["npm", "pnpm", "bun", "yarn"] then node_modules path, 4. best-effort persistence through setInstallInfo({ method: legacyMethod, path: process.execPath, version: CLI_VERSION }).isHomebrewInstall() resolves process.execPath through realpathSync() before testing for "/Cellar/", because the executable commonly appears through a prefix-bin symlink; if realpath resolution fails because the binary was deleted or moved, it checks the unresolved path.fetchLatestVersion(): nightly always calls fetchLatestNightlyVersion(); stable "curl" and "brew" call fetchLatestFromGitHub(); stable package-manager and unknown methods call fetchLatestFromNpm().fetchLatestFromGitHub() currently requests ${GITHUB_RELEASES_URL}/latest, requires tag_name, and strips VERSION_PREFIX_REGEX; fetchLatestFromNpm() requests https://registry.npmjs.org/sentry/latest, requires version, and both map missing data or unsuccessful responses to UpgradeError("network_error", ...).fetchLatestNightlyVersion() uses exactly 2 HTTP requests—anonymous GHCR token exchange and the :nightly OCI manifest—then extracts the version annotation with getNightlyVersion(); it checks signal?.aborted before each network call and throws AbortError.versionExists() registry routing: nightly versions call nightlyVersionExists() and check GHCR tag nightly-${version}, returning false only when the UpgradeError message contains HTTP 404 or 403; stable curl/brew versions issue a GitHub HEAD request to ${GITHUB_RELEASES_URL}/tags/${version}; other stable methods issue an npm HEAD request to ${NPM_REGISTRY_URL}/${version}.DownloadResult in packages/cli/src/lib/upgrade.ts contains tempBinaryPath, lockPath, and optional patchBytes; the caller must retain and release lockPath after the child process exits.writeChunkSync() handles interrupted/short writes by repeatedly calling writeSync() until the full Uint8Array is written; a return value <= 0 throws writeSync returned ${n} for chunk of ${chunk.byteLength - written} bytes to prevent an infinite loop.