Dashboard › cli › Distillation
1b99911b-c3a4-4649-95f5-31e47e07fb35["lore_tm_v1_cQFNZrwzBeViHnbSGv7sQMtV8LDajx0szfYFHRd3Yak","lore_tm_v1_tlZoslgYq9-BkTruXBWZUsXyTwrgfSzg0P1wkyXXRqY"]
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/upgrade.ts, getNightlyGzFilename() returns ${getPlatformBinaryName()}.gz.downloadNightlyToPath(destPath, version?, setMessage?, source = PRIMARY_UPGRADE_SOURCE) gets an anonymous token for the selected UpgradeSource; a pinned version fetches fetchManifest(token, \nightly-${version}`, undefined, source), while latest uses fetchNightlyManifest(token, undefined, source)`.downloadNightlyToPath() finds the platform layer using findLayerByFilename(manifest, getNightlyGzFilename()), downloads it through downloadNightlyBlob(token, layer.digest, undefined, source), throws UpgradeError("execution_failed", "GHCR blob response had no body") when there is no body, and otherwise calls streamDecompressToFile(response.body, destPath, setMessage).downloadStableToPath(version, destPath, setMessage?, source = PRIMARY_UPGRADE_SOURCE) first requests ${getBinaryDownloadUrl(version, source)}.gz with getGitHubHeaders() through fetchWithUpgradeError; an OK response with a body is streamed through streamDecompressToFile().fetchWithUpgradeError(url, { headers }, "GitHub"); a non-OK response throws UpgradeError("execution_failed", \Failed to download binary: HTTP ${response.status}`)`.response.arrayBuffer() before writeFile(destPath, new Uint8Array(body)), avoiding Bun issue https://github.com/oven-sh/bun/issues/13237, where Bun.write(path, Response) with a large streaming body can let the process exit before the download completes.VERIFY_MAX_ATTEMPTS = 6 and VERIFY_BASE_DELAY_MS = 100.probeBinaryFile(path) uses statSync(path, { throwIfNoEntry: false }) and returns the exact file size only when the path is a regular file with stats.size > 0; absent, non-file, and empty paths return null.waitForBinaryVisible(path) addresses Windows + Bun 1.3.9 issue CLI-1D3, where Bun.file().writer().end() may return before the OS exposes the path and a subsequent Bun.spawn reports Executable not found in $PATH.waitForBinaryVisible() performs 6 probes with exponential backoff: 1. probe at 0 ms, sleep 100 ms; 2. probe at 100 ms, sleep 200 ms; 3. probe at 300 ms, sleep 400 ms; 4. probe at 700 ms, sleep 800 ms; 5. probe at 1500 ms, sleep 1600 ms; 6. final probe at 3100 ms with no further sleep.waitForBinaryVisible() returns the verified byte size, logs delayed success as Binary became visible after ${attempt} attempts, and logs each retry with the path, delay, and attempt count.waitForBinaryVisible() throws an UpgradeError when the downloaded file βnever becomes visible or stays empty.β/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/commands/cli/upgrade.ts, explicit offline mode rejects a channel change without versionArg, because the cached version belongs to the old channel and would install the wrong binary type; it throws UpgradeError("unsupported_operation", "Cannot switch channels in offline mode β the cached version belongs to the current channel. Run 'sentry cli upgrade' with network access to switch channels.").resolveOfflineTarget(versionArg) before persistChannelFn(), because setReleaseChannel clears the version cache on channel changes; success logs Offline mode: using cached target ${target} and returns { kind: "target", target, offline: "explicit" }.resolveTargetVersion(resolveOpts) and preserves resolved.source in { kind: "target", target: resolved.target, offline: false, source: resolved.source }.UpgradeError failures with reason === "network_error"; package-manager installs do not receive this fallback.Network unavailable, falling back to cached upgrade target and Using cached target: ${target}, then returns { kind: "target", target, offline: "network-fallback" }; if no cached version exists, the original network error is rethrown.validateMethod(method, versionArg, channel, offline) rejects method === "unknown" with UpgradeError("unknown_method").validateMethod() throws UpgradeError("unsupported_operation", "Homebrew does not support installing a specific version. Run 'brew upgrade getsentry/tools/sentry' to upgrade to the latest formula version.").UpgradeError("unsupported_operation", "Offline upgrade is only supported for curl-installed binaries.").ResolveResult is either { kind: "target"; target: string; source?: UpgradeSource } or { kind: "done"; result: UpgradeResult; source?: UpgradeSource }.resolvePinnedVersion(lookupMethod, target) uses versionExists(lookupMethod, target) for non-curl methods and returns undefined on success; a missing version throws UpgradeError("version_not_found", \Version ${target} not found`)`.resolvePinnedVersion() calls resolveExistingUpgradeVersion(target), throws the same version_not_found error on null, and otherwise returns resolved.source.resolveTargetVersion() treats nightly, curl, and brew resolution as standalone: channel === "nightly" || method === "curl" || method === "brew". Standalone latest lookup uses resolveLatestUpgradeVersion(channel) to preserve source; other methods use fetchLatestVersion(method, channel).versionArg?.replace(VERSION_PREFIX_REGEX, "") ?? latest, while initial source is latestResolution?.source.{ kind: "done", result: buildCheckResult(...), source: latestResolution?.source } before pinned-version existence validation.CLI_VERSION === target, the upgrade is skipped unless flags.force is true or channelChanged is true; the resulting UpgradeResult has action: "up-to-date", current and target versions, channel, method, and forced: false.versionArg exists and is not in CHANNEL_VERSIONS.const lookupMethod = channel === "nightly" ? "curl" : method.source = (await resolvePinnedVersion(lookupMethod, target)) ?? source.buildCheckResult() returns an UpgradeResult with action: "checked", currentVersion: CLI_VERSION, target, channel, method, and forced: flags.force.Run 'sentry cli upgrade ${target}' to update. for an explicit non-channel version, otherwise Run 'sentry cli upgrade' to update.; no warning is added when already on target.SPAWN_MAX_ATTEMPTS = 5 and SPAWN_RETRY_BASE_MS = 500; retry delay is attempt * 500 ms.isEbusyError(error) recognizes only Error objects whose NodeJS.ErrnoException.code is "EBUSY".isEnoentSpawnError(error) recognizes either code === "ENOENT" or a Bun error message containing Executable not found in $PATH.spawnWithRetry(binaryPath, args, env) calls spawn(binaryPath, args, { stdio: "inherit", env }), resolves to code ?? 1 on normal close, and immediately propagates non-EBUSY failures such as EACCES.SIGKILL, spawnWithRetry() rejects with UpgradeError("execution_failed", "Downloaded binary was killed by the operating system (SIGKILL). This usually means the binary has an invalid code signature. Try reinstalling: curl -sL https://sentry.io/get-cli/ | bash"); this specifically surfaces likely macOS AMFI/code-signature rejection.UpgradeError("execution_failed", \Downloaded binary not found at ${binaryPath}. The download may have been interrupted β rerun `sentry cli upgrade`.`); this is a safety net for CLI-1D3, manual .download` removal between verification and spawn, and callers outside the download pipeline.spawnWithRetry() retries EBUSY from Windows Defender/SmartScreen with linear delays of 500 ms, 1000 ms, 1500 ms, and 2000 ms before the fifth/final attempt; each retry logs Binary is locked (antivirus scan?), retrying in ${delay}ms... (attempt ${attempt}/${SPAWN_MAX_ATTEMPTS}).UpgradeError("execution_failed", "Spawn retry loop exhausted").SetupOptions contains binaryPath, method, channel, install, optional installDir, ensureAuthScopes, and noAgentSkills.runSetupOnNewBinary() constructs ordered arguments: 1. "cli", 2. "setup", 3. "--quiet", 4. "--method", 5. method, 6. "--channel", 7. channel, 8. "--no-modify-path"; it conditionally appends "--install", "--ensure-auth-scopes", and "--no-agent-skills" in that order.installDir is supplied, child setup receives { ...process.env, SENTRY_INSTALL_DIR: installDir }, pinning placement and preventing determineInstallDir() from relocating the binary during upgrade.runSetupOnNewBinary() invokes spawnWithRetry() and throws UpgradeError("execution_failed", \Setup failed with exit code ${exitCode}`)` for any nonzero exit code.resolveUpdatedCliPath(execPath, entryPath, pathEnv) resolves the post-package-manager binary in priority order: 1. whichSync("sentry", { PATH: pathEnv }), 2. entryPath, 3. execPath.resolveUpgradeInstallDir(currentInstallDir, pathEnv) normally preserves the current curl installation directory.~/.sentry/bin, resolveUpgradeInstallDir() removes the SENTRY_INSTALL_DIR pin, computes the XDG target through determineInstallDir(homedir(), envWithoutPin), and relocates only if the target differs from the legacy directory and isInPath(xdgInstallDir, pathEnv) is true; otherwise it keeps the legacy location.executeStandardUpgrade() uses rolling NIGHTLY_TAG only for the nightly channel with no versionArg; pinned nightly and stable downloads pass no rolling tag.withProgress({ message: \Downloading ${target}...`, json }, ...)and callsexecuteUpgrade(method, target, downloadTag, offline, setMessage, source)`.downloadResult?.patchBytes is truthy, standard and migration flows log Applied delta patch (${formatBytes(downloadResult.patchBytes)} downloaded).executeStandardUpgrade() derives the current directory from dirname(getCurlInstallPaths().installPath), resolves relocation through resolveUpgradeInstallDir(currentInstallDir, pathEnv), and runs setup on downloadResult.tempBinaryPath with install: true, ensureAuthScopes: !json, and the requested noAgentSkills.downloadResult.lockPath is released in a finally block after the child setup process exits; ppid lock takeover by the child makes duplicate release a harmless no-op.resolveUpdatedCliPath(execPath, entryPath, pathEnv) with install: false, ensureAuthScopes: !json, and noAgentSkills.migrateToStandaloneForNightly() migrates brew/npm/pnpm/bun/yarn users switching to nightly because nightly builds are standalone-only: 1. download the nightly binary to a temp path; 2. install through determineInstallDir(); 3. run setup to update completions, PATH, and metadata; 4. return warnings about the old package-manager installation potentially remaining earlier in PATH.Nightly builds are only available as standalone binaries. and Migrating to standalone installation...; it uses a pinned version tag when versionArg is supplied and rolling NIGHTLY_TAG otherwise.executeUpgrade("curl", target, downloadTag, undefined, setMessage, source) under download progress; a missing downloadResult throws UpgradeError("execution_failed", "Failed to download nightly binary").determineInstallDir(homedir(), process.env) and invokes setup with method: "curl", channel: "nightly", install: true, ensureAuthScopes: !json, and the supplied noAgentSkills; its download lock is always released in finally.npm uninstall -g sentry; pnpm β pnpm remove -g sentry; bun β bun remove -g sentry; yarn β yarn global remove sentry; brew β brew uninstall getsentry/tools/sentry.Your ${method}-installed sentry may still appear earlier in PATH. and, when a mapped uninstall command exists, adds Consider removing it: ${hint}.