Dashboard › cli › Distillation
448dead2-d125-4a14-9cf2-045d912a12d8["lore_tm_v1_OD0h2YpPIiclX_0ift0zwh-4zDf0bgnPDiMkTGYdi8s","lore_tm_v1_E-48fHst5CYmKZNXlhwD3zi3u4sp60JXmnDZpnCKN98","lore_tm_v1_2nUOBOrpt4bW5G2qc5JYyyFzFDdg6Ok1KIk-ZSqAIaE","lore_tm_v1_B_TNpk7PQ-ZTLvGXbrm2_H0qQ3YPRP7ZyhLNW8PXrog","lore_tm_v1_i2lxIsUKC21AZGgEfZ4uLgqtxFcBsJTO0-zyjwHAfYE"]
packages/cli/src/lib/upgrade.ts, detectInstallationMethod() prioritizes isHomebrewInstall() before getInstallInfo(), then legacy detection, and best-effort persistence through setInstallInfo().isHomebrewInstall() in packages/cli/src/lib/upgrade.ts resolves process.execPath with realpathSync() and checks for "/Cellar/"; if realpath resolution throws because the binary was deleted or moved, it checks the unresolved path.detectInstallationMethod() uses this exact priority: 1. Homebrew realpath check, 2. stored DB install info, 3. legacy detection via curl paths → package-manager subprocesses → node_modules path, 4. auto-save a non-"unknown" result with { method: legacyMethod, path: process.execPath, version: CLI_VERSION }; persistence failure only logs Failed to persist install info (DB may be read-only).getCurlInstallPaths() in packages/cli/src/lib/upgrade.ts trusts a stored path only when stored.method === "curl" and existsSync(dirname(stored.path)); root problem was stale DB paths left by temporary SENTRY_INSTALL_DIR installs after directory deletion, causing ENOENT ... open '.../sentry.lock'. The fallback order is stored valid curl path, process.execPath in a known curl directory, then the XDG-aware default from determineInstallDir().buildKnownCurlPaths(homeDir, env) builds directory-boundary-safe paths from KNOWN_CURL_DIRS with trailing sep, adds absolute XDG_BIN_HOME as join(xdgBinHome, ".") + sep, and is lazily memoized by getKnownCurlPaths() to avoid circular-import TDZ issues.runCommand() in packages/cli/src/lib/upgrade.ts uses spawn(command, args, { stdio: ["ignore", "pipe", "pipe"], shell: process.platform === "win32" }); Windows uses a shell because npm, pnpm, and yarn executables are .cmd files, while stderr is drained and discarded to prevent blocking.["npm", "pnpm", "bun", "yarn"] in that exact order using isInstalledWith(). Yarn runs ["global", "list", "--depth=0"]; the others run ["list", "-g", "sentry"]; success requires exit code 0 and stdout containing "sentry@".detectPackageManagerFromPath() examines process.argv[1]: it returns null outside node_modules, "pnpm" when a .pnpm segment exists, "bun" when a .bun segment exists, and otherwise "npm" for npm or Yarn Classic layouts.fetchLatestNightlyVersion() performs exactly 2 HTTP requests—anonymous token plus OCI manifest—and reads the version annotation without downloading a blob.nightlyVersionExists(version) checks GHCR tag nightly-${version}; HTTP 404 and HTTP 403 map to false, while other network errors propagate. Stable versionExists() uses a GitHub Releases HEAD request for curl/Homebrew and an npm registry HEAD request for package-manager installs.executeUpgrade(method, version, downloadTag?, offline?, setMessage?) in packages/cli/src/lib/upgrade.ts returns downloadBinaryToTemp(version, downloadTag, offline, setMessage) for "curl", runs executeUpgradeHomebrew() and returns null for "brew", runs executeUpgradePackageManager(method, version) and returns null for "npm", "pnpm", "bun", or "yarn", and throws new UpgradeError("unknown_method") otherwise.DownloadResult contains required tempBinaryPath and lockPath, plus optional patchBytes?: number; the lock must remain held during download and be released by the caller after the spawned child exits.packages/cli/package.json identifies package sentry version 0.45.0-dev.0, requires Node >=20.0, specifies development runtime Node >=22.15, uses pnpm@10.11.0, and declares binpatch as dev dependency "^0.4.2".binpatch metadata reports version 0.4.2, ESM package type, Node engine >=22.15.0, entry point ./dist/index.js, types ./dist/index.d.ts, sideEffects: false, and describes support for TRDIFF10/bsdiff+zstd patch chains with pluggable OCI/GHCR or GitHub Releases sources.