Dashboard › cli › Distillation
964d3260-0184-4bbe-b898-13173f7dee25["lore_tm_v1_7xLD6VtdrDxpROBAqkXcVdUeOx6zRboszzFd_YTAGBQ","lore_tm_v1_teZoolYlIkigI9lA-nqlTHBA6RFAaZxqie7c7HXxeYY","lore_tm_v1_hfxEWL5Oq4Onk9egyp-qhI9C_EUoLGWXIfxQ2JyF9Yc"]
packages/cli/test/lib/upgrade.test.ts cleanup behavior: startCleanupOldBinary() is fire-and-forget, so the test waits sleep(50) before verifying oldPath is gone; calling it when files do not exist, including a second invocation, must not throw.cleanupOldBinary intentionally does not remove .download files because another process may be upgrading; .download cleanup occurs inside the upgrade flow under the exclusive lock.isNightlyVersion tests: returns true for 0.0.0-dev.1740000000 and 0.0.0-dev.1; returns false for 1.0.0, 0.13.0, 2.0.0-beta.1, and 0.0.0-dev.fetchLatestNightlyVersion cancellation tests: an already-aborted signal with reason object { kind: "cancelled" } must reject with that exact object; a default already-aborted signal must reject with an object whose name is "AbortError".404, fetchLatestNightlyVersion() falls back to legacy getsentry/cli and may resolve the manifest annotation version 0.0.0-dev.1740000000; the requests must include https://ghcr.io/v2/getsentry/cli/manifests/nightly.403 must reject with "HTTP 403" and must not request https://api.github.com/repos/getsentry/cli; a transport exception new Error("HTTP 404") must likewise reject rather than triggering legacy fallback, proving fallback is based on actual HTTP status rather than error text."test-token" and the OCI manifest (Content-Type: application/vnd.oci.image.manifest.v1+json) supplies annotation version 0.0.0-dev.1740000000; exactly 2 GHCR calls are countedβtoken plus manifest.401 must throw UpgradeError with GHCR token exchange failed: HTTP 401; a manifest with annotations: {} must throw UpgradeError with Nightly manifest has no version annotation.nightlyBinDir = join(TEST_TMP_DIR, "upgrade-nightly-test"), nightlyInstallPath = join(nightlyBinDir, "sentry"), and install info { method: "curl", path: nightlyInstallPath, version: "0.0.0" }; teardown restores globalThis.fetch and attempts to unlink installPath, tempPath, oldPath, and lockPath..github/workflows/publish-codemod.yml, .github/workflows/release.yml, .github/workflows/sentry-release.yml, packages/cli/src/commands/cli/upgrade.ts, packages/cli/src/lib/delta-upgrade.ts, packages/cli/src/lib/upgrade.ts, packages/cli/test/commands/cli/upgrade.test.ts, packages/cli/test/e2e/delta-upgrade.test.ts, packages/cli/test/lib/delta-upgrade.mocked.test.ts, packages/cli/test/lib/delta-upgrade.test.ts, and packages/cli/test/lib/upgrade.test.ts.7d62ffa8317f9b98be0dc4afec0a927c1cabb0b7 references GHCR repository getsentry/cli in .github/workflows/ci.yml at lines 470β471 and 553β554; .github/workflows/cleanup-nightlies.yml logs into ghcr.io with ${{ secrets.GITHUB_TOKEN }} at line 28 and sets REPO="ghcr.io/getsentry/cli" at line 34.f1c10a6cb1a753b8c4b8c613cd78735c3f12cba6 is titled fix(cli): preserve pinned upgrade contracts, authored and committed by Burak Yigit Kaya <byk@sentry.io> at 03:45:04 +0000. (meaning Sep 10, 2026)f1c10a6cb1a753b8c4b8c613cd78735c3f12cba6, packages/cli/src/lib/delta-upgrade.ts imports prerelease as semverPrerelease and valid as semverValid from semver.f1c10a6cb1a753b8c4b8c613cd78735c3f12cba6, packages/cli/src/lib/delta-upgrade.ts adds NORMALIZED_RELEASE_SOURCE = Symbol("normalizedReleaseSource") and exported branded array type NormalizedGitHubReleases = GitHubRelease[] & { readonly [NORMALIZED_RELEASE_SOURCE]: string }.f1c10a6cb1a753b8c4b8c613cd78735c3f12cba6, upgradeSourceKey(source) constructs the stable source key ${source.githubRepo}\0${source.ghcrRepo}\0${source.tagPrefix}; exported isNormalizedForSource(releases, source) compares the arrayβs NORMALIZED_RELEASE_SOURCE property to that key.f1c10a6cb1a753b8c4b8c613cd78735c3f12cba6, exported normalizeStableReleases(releases, source) filters values through isGitHubRelease, excludes drafts and prereleases, requires tag_name to start with source.tagPrefix, strips that prefix, then retains only versions satisfying semverValid(tag_name) !== null and semverPrerelease(tag_name) === null; it brands the resulting array via Object.defineProperty(normalized, NORMALIZED_RELEASE_SOURCE, { value: upgradeSourceKey(source) }).f1c10a6cb1a753b8c4b8c613cd78735c3f12cba6, stableSource(source) normalizes successful GitHub release-list responses whenever the request starts with ${releasesUrl}?; the prior additional requirement that source.tagPrefix be truthy was removed, and normalization is delegated to normalizeStableReleases(data, source).f1c10a6cb1a753b8c4b8c613cd78735c3f12cba6, fetchRecentReleases(signal?, source) changes its return type from Promise<GitHubRelease[]> to Promise<NormalizedGitHubReleases> and returns a source-branded normalized empty list for non-OK responses, non-array JSON, and caught fetch failures; valid arrays are returned through normalizeStableReleases(data, source).f1c10a6cb1a753b8c4b8c613cd78735c3f12cba6 version of packages/cli/src/lib/ghcr.ts, isExternalAbort accepts unknown and recognizes an external abort only when externalSignal?.aborted and either the caught value is exactly externalSignal.reason or it is an Error named "AbortError"; rethrowExternalAbort then throws the caught value. This historical behavior was later changed to throw externalSignal?.reason.