Dashboard › cli › Session 02ActtPxnthO
02ActtPxnthO8pbEDREAD-ONLY immutable correctness/adversarial merge gate for getsentry/cli PR #1569. Repository: /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade. Review exact base ec83887a16f780f32fba4b7d710bad262dba3a22 and exact head 9525f72c70fabbb23ec21d13cf86add58f6287cc using immutable Git objects only; never inspect or modify the worktree, branch, commits, VCS state, or files outside this repo. Inspect every changed source and test object and verify merge base, trees, diff/checksum, and git diff --check. Re-evaluate all prior defects, especially: npm 404 vs 401/403/429/500 at library and npm/pnpm/bun/yarn command entry points; malformed npm JSON runtime shape and zero subprocess; canonical Toolkit cli@VERSION versus legacy vVERSION; malformed/prerelease standalone pins before network; draft/prerelease exact release metadata; GHCR strict token/annotation/OCI validation; repeated tag cursor termination; response-body cancellation and transport classification; exact source propagation through discovery, changelog, delta, prefetch, token, manifest, blob, and setup; strengthened nightly command fixture reaching Toolkit blob/setup/success; 404-only fallback, trusted pagination, abort identity, channel routing, offline behavior, and delta final SHA. IMPORTANT settled contract: patch cache identity is intentionally source-neutral (patch-chain:{from}-{to}) because bridge dual-publishing requires byte-identical artifacts for a version pair, each cached chain records/verifies final output SHA-256, and source-qualified entries would duplicate state and break offline reuse. Do not reopen this rejected design absent a concrete correctness flaw that survives byte identity and final-SHA verification. Return a substantive non-empty findings-first report with PASS/CONCERN/MUST-FIX/BLOCKED and exact head file:line evidence. Every defect needs a deterministic regression and concrete fix. State residual risks even if no findings. ...
object-types commit commit resolved-commits-and-trees ec83887a16f780f32fba4b7d710bad262dba3a22 9525f72c70fabbb23ec21d13cf86add58f6287cc 110d6530e57ca4fbfb2a3f98e52013d2668b5b5e 22f49363a13e32c36dcd9e1ca95916809c2dc271 merge-bases ec83887a16f780f32fba4b7d710bad262dba3a22 ancestor-exit=0 commit-headers commit ec83887a16f780f32fba4b7d710bad262dba3a22 tree 110d6530e57ca4fbfb2a3f98e52013d2668b5b5e parents e7beceb6ba09b64dc277ae1732df04e65500062b author sentry[bot] <39604003+sentry[bot]@users.noreply.github.com> subject fix(event): Prevent immediate retry of rate-limited org in event view fallback (#1566) commit 9525f72c70fabbb23ec21d13cf86add58f6287cc tree 22f49363a13e32c36dcd9e1ca95916809c2dc271 parents a84012184c79c2566c7466aa6beda5f767199218 author Burak Yigit Kaya <byk@sentry.io> subject fix(cli): harden upgrade metadata validation
patch-sha256 4950719273dc17d5a9e061b8cfe70c62131fe3299dc1799d9c09bb522b112193 - diff-check diff-check-exit=0 diff-raw :100644 100644 8d8282368 b3039d86b M packages/cli/src/commands/cli/upgrade.ts :100644 100644 75582612a e64f5059e M packages/cli/src/lib/binary.ts :100644 100644 ec709b8c8 204875dce M packages/cli/src/lib/delta-upgrade.ts :100644 100644 f81b8c70c b21505cd1 M packages/cli/src/lib/errors.ts :100644 100644 43d6deb7e 5bca7c061 M packages/cli/src/lib/ghcr.ts :100644 100644 ddf617535 903ca51f6 M packages/cli/src/lib/release-notes.ts :100644 100644 945adc48d b29d67ff2 M packages/cli/src/lib/upgrade.ts :100644 100644 c69ff0466 34393b1c7 M packages/cli/src/lib/version-check.ts :100644 100644 cd1514eb0 4eec11e9d M packages/cli/test/commands/cli.test.ts :100644 100644 ca9688e46 b7fead58f M packages/cli/test/commands/cli/upgrade.test.ts :100644 100644 6fcfb3b1a 29ead3828 M packages/cli/test/lib/binary.test.ts :100644 100644 cd0a2fddc f6186ab59 ...
M packages/cli/src/commands/cli/upgrade.ts M packages/cli/src/lib/binary.ts M packages/cli/src/lib/delta-upgrade.ts M packages/cli/src/lib/errors.ts M packages/cli/src/lib/ghcr.ts M packages/cli/src/lib/release-notes.ts M packages/cli/src/lib/upgrade.ts M packages/cli/src/lib/version-check.ts M packages/cli/test/commands/cli.test.ts M packages/cli/test/commands/cli/upgrade.test.ts M packages/cli/test/lib/binary.test.ts M packages/cli/test/lib/delta-upgrade.mocked.test.ts M packages/cli/test/lib/delta-upgrade.test.ts M packages/cli/test/lib/ghcr.test.ts M packages/cli/test/lib/release-notes.test.ts M packages/cli/test/lib/upgrade.test.ts M packages/cli/test/lib/version-check.test.ts changed-object-map packages/cli/src/commands/cli/upgrade.ts 8d8282368307f48d894a54c6315a9c94af9f3ed2 packages/cli/src/commands/cli/upgrade.ts b3039d86b5935a806f265c906460686d83ee2c64 packages/cli/src/lib/binary.ts 75582612a31fba6ee68111fcfb144f34c28eb58b packages/cli/src/lib/binary.ts e64f5059e53d1321c3910ba...
1114 lines 37246 bytes packages/cli/src/commands/cli/upgrade.ts 768 lines 25572 bytes packages/cli/src/lib/binary.ts 725 lines 21916 bytes packages/cli/src/lib/delta-upgrade.ts 1012 lines 34040 bytes packages/cli/src/lib/errors.ts 659 lines 20203 bytes packages/cli/src/lib/ghcr.ts 793 lines 25097 bytes packages/cli/src/lib/release-notes.ts 1502 lines 48462 bytes packages/cli/src/lib/upgrade.ts 501 lines 16463 bytes packages/cli/src/lib/version-check.ts 230 lines 7592 bytes packages/cli/test/commands/cli.test.ts 1584 lines 50894 bytes packages/cli/test/commands/cli/upgrade.test.ts 974 lines 29842 bytes packages/cli/test/lib/binary.test.ts 500 lines 15975 bytes packages/cli/test/lib/delta-upgrade.mocked.test.ts 2034 lines 60262 bytes packages/cli/test/lib/delta-upgrade.test.ts 773 lines 24007 bytes packages/cli/test/lib/ghcr.test.ts 512 lines 17683 bytes packages/cli/test/lib/release-notes.test.ts 2819 lines 90045 ...
diff --git a/packages/cli/src/commands/cli/upgrade.ts b/packages/cli/src/commands/cli/upgrade.ts index 8d8282368..b3039d86b 100644 --- a/packages/cli/src/commands/cli/upgrade.ts +++ b/packages/cli/src/commands/cli/upgrade.ts @@ -1,434 +1,485 @@ /** * sentry cli upgrade * * Self-update the Sentry CLI to the latest or a specific version. * After upgrading, spawns the NEW binary with `cli setup` to update * completions, agent skills, and record installation metadata. * * Supports two release channels: * - stable (default): tracks the latest GitHub release * - nightly: tracks the rolling nightly prerelease built from main * * The channel can be set via --channel or by passing "nightly"/"stable" * as the version argument. The choice is persisted in the local database * so that subsequent bare `sentry cli upgrade` calls use the same channel. ...
diff --git a/packages/cli/src/lib/binary.ts b/packages/cli/src/lib/binary.ts
index 75582612a..e64f5059e 100644
--- a/packages/cli/src/lib/binary.ts
+++ b/packages/cli/src/lib/binary.ts
@@ -1,470 +1,641 @@
/**
* Binary Management
*
* Shared utilities for installing, replacing, and managing the CLI binary.
* Used by both `setup --install` (fresh installs) and `upgrade` (self-updates).
*/
import { spawnSync } from "node:child_process";
import {
existsSync,
mkdirSync,
readFileSync,
renameSync,
unlinkSync,
writeFileSync,
} from "node:fs";
import { chmod, copyFile, mkdir, realpath, unlink } from "node:fs/promises";
import { delimiter, dirname, isAbsolute, join, resolve, sep } from "node:path";
import { compare as semverCompare } from "semver";
import { getUserAgent } from "./constants.js";
import {
buildTlsErrorDetail,
customFetch,
isTlsCertError,
} from "./custom-ca.js";
-import { stringifyUnknown, UpgradeError } from "./errors.js";
+import ...
9525f72c70fabbb23ec21d13cf86add58f6287cc:packages/cli/src/commands/api.ts:973: const isBinary = response.body instanceof Uint8Array; 9525f72c70fabbb23ec21d13cf86add58f6287cc:packages/cli/src/commands/api.ts:978: response.body as Uint8Array 9525f72c70fabbb23ec21d13cf86add58f6287cc:packages/cli/src/commands/api.ts:980: : response.body; 9525f72c70fabbb23ec21d13cf86add58f6287cc:packages/cli/src/commands/api.ts:994: response.body === null || 9525f72c70fabbb23ec21d13cf86add58f6287cc:packages/cli/src/commands/api.ts:995: response.body === undefined || 9525f72c70fabbb23ec21d13cf86add58f6287cc:packages/cli/src/commands/api.ts:996: (typeof response.body === "string" && response.body.trim() === "") 9525f72c70fabbb23ec21d13cf86add58f6287cc:packages/cli/src/commands/api.ts:1007: throw new OutputError(response.body); 9525f72c70fabbb23ec21d13cf86add58f6287cc:packages/cli/src/commands/api.ts:1043: ? filterFields(response.body, ...
diff --git a/packages/cli/src/lib/delta-upgrade.ts b/packages/cli/src/lib/delta-upgrade.ts
index ec709b8c8..204875dce 100644
--- a/packages/cli/src/lib/delta-upgrade.ts
+++ b/packages/cli/src/lib/delta-upgrade.ts
@@ -1,388 +1,481 @@
/** Delta upgrade discovery and application backed by binpatch. */
import { join } from "node:path";
// biome-ignore lint/performance/noNamespaceImport: Sentry SDK recommends namespace import
import * as Sentry from "@sentry/node-core/light";
import {
applyPatchChainInMemory,
extractStableChain as binpatchExtractStableChain,
filterAndSortChainTags as binpatchFilterAndSortChainTags,
validateChainStep as binpatchValidateChainStep,
type DeltaTelemetry,
type DeltaUnavailableReason,
type ExtractStableChainOpts,
type GitHubRelease,
getPatchFromVersion,
getPatchTargetSha256,
ghcrSource,
githubReleaseSource,
type InstrumentHook,
MAX_NIGHTLY_CHAIN_DEPTH,
makeCache,
OciClient,
type OciManifest,
...
9525f72c70fabbb23ec21d13cf86add58f6287cc:packages/cli/src/lib/api-scope.ts:4: * (getsentry/cli#785 #9). 9525f72c70fabbb23ec21d13cf86add58f6287cc:packages/cli/src/lib/api/alerts.ts:222:// now returns HTTP 410 during recurring brownouts (getsentry/cli#1182). The 9525f72c70fabbb23ec21d13cf86add58f6287cc:packages/cli/src/lib/api/alerts.ts:365:// 2026-08-17 (getsentry/cli#1274, #1182). Detectors return a nested shape, so 9525f72c70fabbb23ec21d13cf86add58f6287cc:packages/cli/src/lib/api/alerts.ts:547:// `/alert-rules/` endpoint (getsentry/cli#1274, #1277). 9525f72c70fabbb23ec21d13cf86add58f6287cc:packages/cli/src/lib/api/releases.ts:146: * @param version - Release version string (e.g., "1.0.0", "sentry-cli@0.24.0") 9525f72c70fabbb23ec21d13cf86add58f6287cc:packages/cli/src/lib/auth-hint.ts:9: * in the CLI UX feedback issue (getsentry/cli#785 #4). The hint surfaces 9525f72c70fabbb23ec21d13cf86add58f6287cc:packages/cli/src/lib/auth-hint.ts:97: * the source — the user set a config file, not an ...
diff --git a/packages/cli/src/lib/upgrade.ts b/packages/cli/src/lib/upgrade.ts
index 945adc48d..b29d67ff2 100644
--- a/packages/cli/src/lib/upgrade.ts
+++ b/packages/cli/src/lib/upgrade.ts
@@ -1,189 +1,287 @@
/**
* Upgrade Module
*
* Detects how the CLI was installed and provides self-upgrade functionality.
* Binary management helpers (download URLs, locking, replacement) live in
* binary.ts and are shared with the setup --install flow.
*/
import { spawn } from "node:child_process";
import {
chmodSync,
closeSync,
existsSync,
openSync,
realpathSync,
statSync,
unlinkSync,
writeSync,
} from "node:fs";
import { writeFile } from "node:fs/promises";
import { homedir } from "node:os";
import { dirname, isAbsolute, join, sep } from "node:path";
import { setTimeout } from "node:timers/promises";
+import { prerelease as semverPrerelease, valid as semverValid } from "semver";
import {
acquireLock,
cleanupOldBinary,
+ compareVersions,
...
diff --git a/packages/cli/src/lib/ghcr.ts b/packages/cli/src/lib/ghcr.ts index 43d6deb7e..5bca7c061 100644 --- a/packages/cli/src/lib/ghcr.ts +++ b/packages/cli/src/lib/ghcr.ts @@ -1,520 +1,659 @@ /** * GHCR (GitHub Container Registry) Client * * Encapsulates the OCI download protocol for fetching nightly CLI binaries * from ghcr.io/getsentry/cli. Nightly builds are pushed as OCI artifacts * via ORAS with the version baked into the manifest annotation. * * Key design decisions: * - Anonymous access: nightly package is public; no token needed beyond the * standard ghcr.io anonymous token exchange. * - Version discovery from manifest annotation: `annotations.version` in the * OCI manifest holds the nightly version. Checking the latest version only * requires a token exchange + manifest fetch (2 HTTP requests total). * - Redirect quirk: ghcr.io blob downloads return 307 to Azure Blob Storage. ...
diff --git a/packages/cli/src/lib/release-notes.ts b/packages/cli/src/lib/release-notes.ts index ddf617535..903ca51f6 100644 --- a/packages/cli/src/lib/release-notes.ts +++ b/packages/cli/src/lib/release-notes.ts @@ -1,142 +1,149 @@ /** * Release Notes Parser & Aggregation * * Extracts user-facing changelog entries from GitHub Release bodies (stable) * or conventional commit messages (nightly). Uses `marked.lexer()` for * AST-based section extraction and produces structured data that can be * re-serialized as filtered markdown for rendering via `renderMarkdown()`. ...
diff --git a/packages/cli/src/lib/errors.ts b/packages/cli/src/lib/errors.ts
index f81b8c70c..b21505cd1 100644
--- a/packages/cli/src/lib/errors.ts
+++ b/packages/cli/src/lib/errors.ts
@@ -561,120 +561,128 @@ export class ValidationError extends CliError {
constructor(message: string, field?: string) {
super(message, EXIT.VALIDATION);
this.name = "ValidationError";
this.field = field;
}
}
/**
* OAuth device flow errors (RFC 8628).
*
* @param code - OAuth error code (e.g., "authorization_pending", "slow_down")
* @param description - Human-readable error description
*/
export class DeviceFlowError extends CliError {
readonly code: string;
constructor(code: string, description?: string) {
super(description ?? code, EXIT.DEVICE_FLOW);
this.name = "DeviceFlowError";
this.code = code;
}
}
// Upgrade Errors
export type UpgradeErrorReason =
| "unknown_method"
| "unsupported_operation"
| "network_error"
| ...
diff --git a/packages/cli/test/lib/binary.test.ts b/packages/cli/test/lib/binary.test.ts
index 6fcfb3b1a..29ead3828 100644
--- a/packages/cli/test/lib/binary.test.ts
+++ b/packages/cli/test/lib/binary.test.ts
@@ -1,143 +1,270 @@
/**
* Binary Management Tests
*
* Tests for shared binary helpers: install directory selection, paths,
* download URLs, locking, and binary installation.
*/
import {
chmodSync,
mkdirSync,
readFileSync,
realpathSync,
rmSync,
symlinkSync,
writeFileSync,
} from "node:fs";
import { access, readFile, writeFile } from "node:fs/promises";
import { join, sep } from "node:path";
import { afterEach, beforeEach, describe, expect, test } from "vitest";
import {
acquireLock,
compareVersions,
determineInstallDir,
fetchWithUpgradeError,
getBinaryDownloadUrl,
getBinaryFilename,
getBinaryPaths,
+ getGitHubReleaseByTagUrl,
getLegacyInstallDirs,
getPlatformBinaryName,
installBinary,
isDowngrade,
...
diff --git a/packages/cli/test/lib/upgrade.test.ts b/packages/cli/test/lib/upgrade.test.ts
index 7c6f63a4b..d10f21dd6 100644
--- a/packages/cli/test/lib/upgrade.test.ts
+++ b/packages/cli/test/lib/upgrade.test.ts
@@ -103,60 +103,62 @@ const { spawnImpl } = vi.hoisted(() => ({
// Initialize with the real default now that fakeProcess is defined
spawnImpl.fn = () => fakeProcess(0);
vi.mock("node:child_process", async (importOriginal) => {
const orig = await importOriginal<typeof import("node:child_process")>();
return {
...orig,
spawn: (cmd: string, args: string[], opts: object) =>
spawnImpl.fn(cmd, args, opts),
};
});
// Dynamic imports: must run AFTER vi.mock() so upgrade.ts picks up the
// mocked spawn.
import { isEnoentSpawnError } from "../../src/commands/cli/upgrade.js";
import {
acquireLock,
getBinaryDownloadUrl,
isNightlyVersion,
releaseLock,
+ UPGRADE_SOURCES,
} from "../../src/lib/binary.js";
import {
clearInstallInfo,
...
diff --git a/packages/cli/test/commands/cli/upgrade.test.ts b/packages/cli/test/commands/cli/upgrade.test.ts
index ca9688e46..b7fead58f 100644
--- a/packages/cli/test/commands/cli/upgrade.test.ts
+++ b/packages/cli/test/commands/cli/upgrade.test.ts
@@ -13,60 +13,61 @@
import * as child_process from "node:child_process";
import { chmodSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
import { unlink } from "node:fs/promises";
import { homedir } from "node:os";
import { delimiter, join } from "node:path";
import { gzipSync } from "node:zlib";
import { run } from "@stricli/core";
import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
// Make child_process namespace mutable so vi.spyOn works on ESM exports
vi.mock("node:child_process", async (importOriginal) => {
const orig = await importOriginal<typeof import("node:child_process")>();
return { ...orig };
});
import { app } from "../../../src/app.js";
import {
isEbusyError,
...
diff --git a/packages/cli/test/commands/cli.test.ts b/packages/cli/test/commands/cli.test.ts
index cd1514eb0..4eec11e9d 100644
--- a/packages/cli/test/commands/cli.test.ts
+++ b/packages/cli/test/commands/cli.test.ts
@@ -97,140 +97,134 @@ describe("feedbackCommand.func", () => {
// Sentry is disabled in test environment (no DSN)
await expect(
func.call(mockContext, {}, "test", "feedback")
).rejects.toThrow("Feedback not sent: telemetry is disabled.");
});
});
// Test the upgrade command func
describe("upgradeCommand.func", () => {
let originalFetch: typeof globalThis.fetch;
let restoreStderr: (() => void) | undefined;
beforeEach(() => {
originalFetch = globalThis.fetch;
});
afterEach(() => {
restoreStderr?.();
restoreStderr = undefined;
globalThis.fetch = originalFetch;
});
// Note: We skip testing "unknown installation method" case because
// detectInstallationMethod() runs actual shell commands (npm ...
diff --git a/packages/cli/test/lib/delta-upgrade.test.ts b/packages/cli/test/lib/delta-upgrade.test.ts
index 3752d4ae6..68d1cfbdf 100644
--- a/packages/cli/test/lib/delta-upgrade.test.ts
+++ b/packages/cli/test/lib/delta-upgrade.test.ts
@@ -1,60 +1,69 @@
/**
* Unit Tests for Delta Upgrade Module
*
* Tests the exported pure-computation functions that drive chain resolution
* for both stable (GitHub Releases) and nightly (GHCR) channels, plus
* async orchestration functions tested via fetch mocking.
*/
import { createHash } from "node:crypto";
import { existsSync, unlinkSync } from "node:fs";
import { access, readFile } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
-import { afterEach, beforeEach, describe, expect, test } from "vitest";
-import { getPlatformBinaryName } from "../../src/lib/binary.js";
+import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
+import {
+ getPlatformBinaryName,
+ ...
diff --git a/packages/cli/test/lib/ghcr.test.ts b/packages/cli/test/lib/ghcr.test.ts
index e5c81d532..a55612b5a 100644
--- a/packages/cli/test/lib/ghcr.test.ts
+++ b/packages/cli/test/lib/ghcr.test.ts
@@ -1,232 +1,340 @@
/**
* GHCR Client Tests
*
* Unit tests for the GHCR/OCI download protocol helpers.
* All HTTP calls are mocked via globalThis.fetch to avoid network access.
*/
import { afterEach, beforeEach, describe, expect, test } from "vitest";
+import { UPGRADE_SOURCES } from "../../src/lib/binary.js";
import { UpgradeError } from "../../src/lib/errors.js";
import {
downloadLayerBlob,
downloadNightlyBlob,
fetchManifest,
fetchNightlyManifest,
findLayerByFilename,
GHCR_REPO,
GHCR_TAG,
+ GhcrManifestHttpError,
getAnonymousToken,
getNightlyVersion,
listTags,
type OciManifest,
} from "../../src/lib/ghcr.js";
/** Store original fetch for restoration */
let originalFetch: typeof globalThis.fetch;
/** Helper to mock fetch without ...
9525f72c70fabbb23ec21d13cf86add58f6287cc:packages/cli/test/lib/ghcr.test.ts:39: schemaVersion: 2,
9525f72c70fabbb23ec21d13cf86add58f6287cc:packages/cli/test/lib/ghcr.test.ts:40: mediaType: "application/vnd.oci.image.manifest.v1+json",
9525f72c70fabbb23ec21d13cf86add58f6287cc:packages/cli/test/lib/ghcr.test.ts:42: digest: `sha256:${"0".repeat(64)}`,
9525f72c70fabbb23ec21d13cf86add58f6287cc:packages/cli/test/lib/ghcr.test.ts:43: mediaType: "application/vnd.oci.empty.v1+json",
9525f72c70fabbb23ec21d13cf86add58f6287cc:packages/cli/test/lib/ghcr.test.ts:44: size: 2,
9525f72c70fabbb23ec21d13cf86add58f6287cc:packages/cli/test/lib/ghcr.test.ts:48: digest: `sha256:${"a".repeat(64)}`,
9525f72c70fabbb23ec21d13cf86add58f6287cc:packages/cli/test/lib/ghcr.test.ts:49: mediaType: "application/octet-stream",
9525f72c70fabbb23ec21d13cf86add58f6287cc:packages/cli/test/lib/ghcr.test.ts:50: size: ...
diff --git a/packages/cli/test/lib/release-notes.test.ts b/packages/cli/test/lib/release-notes.test.ts
index 78963b471..ffccf4901 100644
--- a/packages/cli/test/lib/release-notes.test.ts
+++ b/packages/cli/test/lib/release-notes.test.ts
@@ -1,46 +1,52 @@
/**
* Unit Tests for Release Notes Parser & Aggregation
*
* Tests core invariants (section extraction, version filtering, truncation)
* that are hard to express as property-based tests due to format specifics.
*
* Core random-input invariants (category validity, filtering, commit parsing)
* are tested via property-based tests in release-notes.property.test.ts.
*/
import { marked } from "marked";
-import { describe, expect, test } from "vitest";
-import type { GitHubRelease } from "../../src/lib/delta-upgrade.js";
+import { afterEach, beforeEach, describe, expect, test } from "vitest";
+import { UPGRADE_SOURCES } from "../../src/lib/binary.js";
+import {
+ fetchRecentReleases,
+ type GitHubRelease,
+} from ...
diff --git a/packages/cli/test/lib/version-check.test.ts b/packages/cli/test/lib/version-check.test.ts
index 20172cd83..dd047a5cb 100644
--- a/packages/cli/test/lib/version-check.test.ts
+++ b/packages/cli/test/lib/version-check.test.ts
@@ -1,36 +1,39 @@
/**
* Version Check Logic Tests
*/
import { setTimeout as sleep } from "node:timers/promises";
-import { afterEach, beforeEach, describe, expect, test } from "vitest";
+import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
+import { UPGRADE_SOURCES } from "../../src/lib/binary.js";
import { setReleaseChannel } from "../../src/lib/db/release-channel.js";
import {
getVersionCheckInfo,
setVersionCheckInfo,
} from "../../src/lib/db/version-check.js";
+// biome-ignore lint/performance/noNamespaceImport: Vitest requires the module namespace to spy on an ESM export
+import * as deltaUpgrade from "../../src/lib/delta-upgrade.js";
import {
ApiError,
ContextError,
ValidationError,
} from ...
@@ -1,70 +1,79 @@
@@ -792,77 +801,111 @@ describe("validateChainStep", () => {
@@ -894,197 +937,214 @@ describe("resolveStableChain", () => {
expect(chain?.expectedSha256).toBe(versionHex("0.14.0"));
@@ -1154,60 +1214,80 @@ describe("resolveNightlyChain", () => {
expect(chain?.expectedSha256).toBe("aabb1122");
@@ -1817,30 +1897,138 @@ describe("attemptDeltaUpgrade", () => {
+describe("selected source affinity", () => {
packages/cli/src/lib/patch-cache.ts packages/cli/test/lib/patch-cache.test.ts
Your prior exact-head correctness review returned EMPTY and cannot satisfy the merge gate. Resume the SAME immutable review now. Review getsentry/cli PR #1569 exact base ec83887a16f780f32fba4b7d710bad262dba3a22 and exact head 9525f72c70fabbb23ec21d13cf86add58f6287cc using Git objects only in /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade; never inspect/modify worktree or mutate VCS. Return substantive evidence. If a tool fails, report BLOCKED first with exact command/error. Inspect all changed source/test objects and verify ancestry, trees, changed paths, complete diff and diff-check. Re-evaluate all bridge contracts, especially exact genuine-404 fallback, source stickiness, trusted pagination, body cancellation/transport/malformed classification, canonical Toolkit cli@VERSION versus legacy vVERSION, strict npm body/status behavior across npm/pnpm/bun/yarn, stable/nightly pin validation, draft/prerelease rejection, GHCR token/OCI/tag runtime shape and repeated cursor, redirect auth isolation, channel routing, offline behavior, delta final SHA/cleanup, and the end-to-end nightly blob/setup regression. Settled contract: source-neutral patch caching is intentional under mandatory byte-identical dual publication and final SHA verification; only raise a proven defect surviving both guarantees. Findings first with PASS/CONCERN/MUST-FIX/BLOCKED, exact HEAD file:line evidence, deterministic regression and concrete fix for defects, inspected scope and residual risks. Empty output is forbidden. End exactly MERGE or DO-NOT-MERGE.
95 * Defined here (alongside other installation constants like
96 * {@link KNOWN_CURL_DIRS}) so that both `upgrade.ts` and
97 * `db/install-info.ts` can import it without creating a circular
98 * dependency.
99 */
100 export type InstallationMethod =
101 | "curl"
102 | "brew"
103 | "npm"
104 | "pnpm"
105 | "bun"
106 | "yarn"
107 | "unknown";
108
109 /** A repository pair that hosts CLI stable releases and nightly OCI images. */
110 export type UpgradeSource = {
111 /** GitHub `owner/repository` containing CLI release assets. */
112 readonly githubRepo: string;
113 /** GHCR `owner/package` containing CLI nightly images and delta patches. */
114 readonly ghcrRepo: string;
115 /** Prefix attached to CLI release tags in this repository. */
116 readonly tagPrefix: string;
117 };
118
119 /** Ordered CLI release sources. The resolver falls through only on HTTP 404. ...
9525f72c70fabbb23ec21d13cf86add58f6287cc:.craft.yml:27: urlTemplate: 'https://github.com/getsentry/cli/releases/download/{{version}}/{{file}}'
9525f72c70fabbb23ec21d13cf86add58f6287cc:.craft.yml:46: url "https://github.com/getsentry/cli/releases/download/{{version}}/sentry-darwin-arm64.gz"
9525f72c70fabbb23ec21d13cf86add58f6287cc:.craft.yml:49: url "https://github.com/getsentry/cli/releases/download/{{version}}/sentry-darwin-x64.gz"
9525f72c70fabbb23ec21d13cf86add58f6287cc:.craft.yml:56: url "https://github.com/getsentry/cli/releases/download/{{version}}/sentry-linux-arm64.gz"
9525f72c70fabbb23ec21d13cf86add58f6287cc:.craft.yml:59: url "https://github.com/getsentry/cli/releases/download/{{version}}/sentry-linux-x64.gz"
9525f72c70fabbb23ec21d13cf86add58f6287cc:apps/cli-docs/src/fragments/commands/issue.md:220:sentry issue resolve CLI-G5 --in ...