Dashboard › cli › Session 19EhpL9Xqlhl
19EhpL9Xqlhl1cDjWREAD-ONLY correctness merge-gate review of getsentry/cli PR #1569 at exact base ec83887a16f780f32fba4b7d710bad262dba3a22 and exact head c8c815bbecf472061ec02ab96d1a31f23f078d01 in worktree /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade. Verify immutable revisions and clean state; inspect all changed files and relevant tests. Focus on 404-only fallback, source affinity, stable/nightly resolution, SemVer, GitHub pagination including canonical /repositories/{id} links reconstructed onto selected source, malformed/off-origin/page/cycle handling, GHCR cancellation, explicit status classification, delta/cache/offline, prefetch and normalized prefetched changelogs, API compatibility. Intentional contracts: GitHub repository probe precedes nightly GHCR because package absence is ambiguous; verified version-pair delta cache is source-neutral because dual-published artifacts are byte-identical. Return a NON-EMPTY findings-first report labeled PASS/CONCERN/MUST-FIX/BLOCKED with exact current file:line evidence and deterministic regressions for defects. Include residual gaps. Final line exactly MERGE or DO-NOT-MERGE. Do not modify anything.
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/package.json /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/AGENTS.md /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/.lore.md /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/package.json
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/AGENTS.md</path> <type>file</type> <content> 1: # Jared (Outpost agent) 2: 3: Autonomous GitHub coding agent. Work in `/workspace/repo`. 4: 5: ## Model tiers 6: 7: The primary model is chosen per event (see `src/agents/models.ts`): heavy for 8: code-producing situations, cheaper for lightweight ones. 9: 10: | Role | Subagent | Model | 11: | --- | --- | --- | 12: | Triage / plan / review (heavy) | (primary Jared) | Claude Opus 4.8 | 13: | Triage / plan / review (light) | (primary Jared) | xAI Grok 4.3 | 14: | Explore | `explore` | OpenAI gpt-5-mini | 15: | Implement | `implement` | Moonshot kimi-k2.7-code | 16: | Ship (commit/push/PR) | `ship` | xAI Grok (`grok-build-0.1`) | 17: 18: Pipeline: triage → explore → plan → implement → review → ship. 19: (`worker` is a deprecated alias of `implement`.) 20: 21: Operators also talk to Jared directly from the Outpost dashboard. ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/.lore.md</path>
<type>file</type>
<content>
1: <!-- Managed by lore (https://github.com/BYK/loreai) — manual edits are imported on next session. -->
2:
3: ## Long-term Knowledge
4:
5: ### Architecture
6:
7: <!-- lore:01a02357-f0a8-7fdb-9e9d-b0710cfe65c9 -->
8: * **API output binary and HTTP contracts**: Always preserve strict output-mode and binary-safety contracts. `sentry api` must preserve `rawApiRequest()` status text; empty textual non-2xx bodies must produce an HTTP status/request fallback, and JSON mode must expose `{status, statusText, body}` so empty success and error responses are distinguishable. Binary `Uint8Array` successes bypass formatters and remain raw; binary errors emit only status/content-type/byte-count summaries, never bytes or JSON coercion. Prompts must never block scripted runs or interleave with stdout JSON.
9:
10: <!-- ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/package.json</path>
<type>file</type>
<content>
1: {
2: "name": "toolkit-cli-workspace",
3: "version": "0.0.0",
4: "private": true,
5: "type": "module",
6: "packageManager": "pnpm@10.11.0",
7: "engines": {
8: "node": ">=20.0"
9: },
10: "scripts": {
11: "tsx": "pnpm --filter sentry run tsx",
12: "cli": "pnpm --filter sentry run cli",
13: "dev": "pnpm --filter sentry run dev",
14: "build": "pnpm --filter sentry run build",
15: "build:all": "pnpm --filter sentry run build:all",
16: "bundle": "pnpm --filter sentry run bundle",
17: "typecheck": "pnpm --filter sentry run typecheck",
18: "lint": "pnpm --filter sentry run lint",
19: "lint:fix": "pnpm --filter sentry run lint:fix",
20: "test": "pnpm --filter sentry run test",
21: "test:unit": "pnpm --filter sentry run test:unit",
22: "test:changed": "pnpm --filter ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/package.json</path>
<type>file</type>
<content>
1: {
2: "name": "sentry",
3: "version": "0.45.0-dev.0",
4: "description": "Sentry CLI - A command-line interface for using Sentry built by robots and humans for robots and humans",
5: "repository": {
6: "type": "git",
7: "url": "git+https://github.com/getsentry/cli.git"
8: },
9: "main": "./dist/index.cjs",
10: "type": "module",
11: "types": "./dist/index.d.cts",
12: "exports": {
13: ".": {
14: "import": {
15: "types": "./dist/index.d.mts",
16: "default": "./dist/index.mjs"
17: },
18: "require": {
19: "types": "./dist/index.d.cts",
20: "default": "./dist/index.cjs"
21: }
22: }
23: },
24: "bin": {
25: "sentry": "./dist/bin.cjs"
26: },
27: "files": [
28: "dist/bin.cjs",
29: "dist/index.cjs",
30: ...
c8c815bbecf472061ec02ab96d1a31f23f078d01 ec83887a16f780f32fba4b7d710bad262dba3a22 c8c815bbecf472061ec02ab96d1a31f23f078d01 ec83887a16f780f32fba4b7d710bad262dba3a22 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/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 packages/cli/src/commands/cli/upgrade.ts | 114 ++++-- packages/cli/src/lib/binary.ts | 154 +++++++- packages/cli/src/lib/delta-upgrade.ts ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/upgrade.ts</path>
<type>file</type>
<content>
1: /**
2: * Upgrade Module
3: *
4: * Detects how the CLI was installed and provides self-upgrade functionality.
5: * Binary management helpers (download URLs, locking, replacement) live in
6: * binary.ts and are shared with the setup --install flow.
7: */
8:
9: import { spawn } from "node:child_process";
10: import {
11: chmodSync,
12: closeSync,
13: existsSync,
14: openSync,
15: realpathSync,
16: statSync,
17: unlinkSync,
18: writeSync,
19: } from "node:fs";
20: import { writeFile } from "node:fs/promises";
21: import { homedir } from "node:os";
22: import { dirname, isAbsolute, join, sep } from "node:path";
23: import { setTimeout } from "node:timers/promises";
24: import { valid as semverValid } from "semver";
25: import {
26: acquireLock,
27: cleanupOldBinary,
28: ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/binary.ts</path>
<type>file</type>
<content>
1: /**
2: * Binary Management
3: *
4: * Shared utilities for installing, replacing, and managing the CLI binary.
5: * Used by both `setup --install` (fresh installs) and `upgrade` (self-updates).
6: */
7:
8: import { spawnSync } from "node:child_process";
9: import {
10: existsSync,
11: mkdirSync,
12: readFileSync,
13: renameSync,
14: unlinkSync,
15: writeFileSync,
16: } from "node:fs";
17: import { chmod, copyFile, mkdir, realpath, unlink } from "node:fs/promises";
18: import { delimiter, dirname, isAbsolute, join, resolve, sep } from "node:path";
19: import { compare as semverCompare } from "semver";
20: import { getUserAgent } from "./constants.js";
21: import {
22: buildTlsErrorDetail,
23: customFetch,
24: isTlsCertError,
25: } from "./custom-ca.js";
26: import { stringifyUnknown, ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/delta-upgrade.ts</path>
<type>file</type>
<content>
1: /** Delta upgrade discovery and application backed by binpatch. */
2:
3: import { join } from "node:path";
4: // biome-ignore lint/performance/noNamespaceImport: Sentry SDK recommends namespace import
5: import * as Sentry from "@sentry/node-core/light";
6: import {
7: applyPatchChainInMemory,
8: extractStableChain as binpatchExtractStableChain,
9: filterAndSortChainTags as binpatchFilterAndSortChainTags,
10: validateChainStep as binpatchValidateChainStep,
11: type DeltaTelemetry,
12: type DeltaUnavailableReason,
13: type ExtractStableChainOpts,
14: type GitHubRelease,
15: getPatchFromVersion,
16: getPatchTargetSha256,
17: ghcrSource,
18: githubReleaseSource,
19: type InstrumentHook,
20: MAX_NIGHTLY_CHAIN_DEPTH,
21: makeCache,
22: OciClient,
23: type OciManifest,
24: ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/ghcr.ts</path> <type>file</type> <content> 1: /** 2: * GHCR (GitHub Container Registry) Client 3: * 4: * Encapsulates the OCI download protocol for fetching nightly CLI binaries 5: * from ghcr.io/getsentry/cli. Nightly builds are pushed as OCI artifacts 6: * via ORAS with the version baked into the manifest annotation. 7: * 8: * Key design decisions: 9: * - Anonymous access: nightly package is public; no token needed beyond the 10: * standard ghcr.io anonymous token exchange. 11: * - Version discovery from manifest annotation: `annotations.version` in the 12: * OCI manifest holds the nightly version. Checking the latest version only 13: * requires a token exchange + manifest fetch (2 HTTP requests total). 14: * - Redirect quirk: ghcr.io blob downloads return 307 to Azure Blob Storage. ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/release-notes.ts</path> <type>file</type> <content> 1: /** 2: * Release Notes Parser & Aggregation 3: * 4: * Extracts user-facing changelog entries from GitHub Release bodies (stable) 5: * or conventional commit messages (nightly). Uses `marked.lexer()` for 6: * AST-based section extraction and produces structured data that can be 7: * re-serialized as filtered markdown for rendering via `renderMarkdown()`. ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/version-check.ts</path>
<type>file</type>
<content>
1: /**
2: * Background version check for "new version available" notifications.
3: *
4: * For nightly builds (CLI_VERSION contains "-dev.<timestamp>"), checks GHCR for the
5: * latest nightly version via the OCI manifest annotation. For stable builds,
6: * checks GitHub Releases. Results are cached in the database and shown on
7: * subsequent runs.
8: */
9:
10: // biome-ignore lint/performance/noNamespaceImport: Sentry SDK recommends namespace import
11: import * as Sentry from "@sentry/node-core/light";
12: import { compare as semverCompare } from "semver";
13: import type { UpgradeSource } from "./binary.js";
14: import { CLI_VERSION } from "./constants.js";
15: import { getReleaseChannel } from "./db/release-channel.js";
16: import {
17: getVersionCheckInfo,
18: markUpdateNotified,
19: ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/commands/cli/upgrade.ts</path> <type>file</type> <content> 1: /** 2: * sentry cli upgrade 3: * 4: * Self-update the Sentry CLI to the latest or a specific version. 5: * After upgrading, spawns the NEW binary with `cli setup` to update 6: * completions, agent skills, and record installation metadata. 7: * 8: * Supports two release channels: 9: * - stable (default): tracks the latest GitHub release 10: * - nightly: tracks the rolling nightly prerelease built from main 11: * 12: * The channel can be set via --channel or by passing "nightly"/"stable" 13: * as the version argument. The choice is persisted in the local database 14: * so that subsequent bare `sentry cli upgrade` calls use the same channel. ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/commands/cli/upgrade.ts</path>
<type>file</type>
<content>
990: })
991: );
992: // Early exit for check-only (online) and up-to-date results.
993: if (resolved.kind === "done") {
994: const result = resolved.result;
995: // For --check with a version diff, fetch changelog before returning.
996: if (
997: result.action === "checked" &&
998: result.currentVersion !== result.targetVersion
999: ) {
1000: result.changelog = await startChangelogFetch({
1001: channel,
1002: currentVersion: CLI_VERSION,
1003: targetVersion: result.targetVersion,
1004: offline: false,
1005: source: resolved.source,
1006: });
1007: }
1008: return yield new CommandOutput(result);
1009: }
1010:
1011: const { target, offline, source } = ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/upgrade.ts</path> <type>file</type> <content> 1200: } 1201: } 1202: 1203: /** 1204: * Attempt delta upgrade using binary patches. 1205: * 1206: * Uses the currently running binary as the base for patching. 1207: * Returns null silently on any failure so the caller can fall back. 1208: * 1209: * @param version - Target version to upgrade to 1210: * @param destPath - Path to write the patched binary 1211: * @returns Delta result with SHA-256 and size info, or null if delta is unavailable 1212: */ 1213: // biome-ignore lint/nursery/useMaxParams: mirrors the established download helper while forwarding source affinity. 1214: async function tryDeltaUpgrade( 1215: version: string, 1216: destPath: string, 1217: offline?: boolean, 1218: setMessage?: SetMessage, 1219: source: UpgradeSource = PRIMARY_UPGRADE_SOURCE 1220: ): Promise<DeltaResult ...
Found 100 matches (more matches available)
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/delta-upgrade.mocked.test.ts:
Line 148: return new Response(JSON.stringify(releases), { status: 200 });
Line 152: status: 200,
Line 155: return new Response("Not Found", { status: 404 });
Line 179: mockFetch(async () => new Response("Error", { status: 500 }));
Line 209: status: 200,
Line 233: { status: 200 }
Line 236: // listTags runs in parallel with fetchManifest — must not 404
Line 238: return new Response(JSON.stringify({ tags: [] }), { status: 200 });
Line 240: return new Response("Not Found", { status: 404 });
Line 265: status: 200,
Line 289: { status: 200 }
Line 293: return new Response(JSON.stringify({ tags: [] }), { status: 200 });
Line 295: return new Response("Not ...
Found 100 matches (more matches available)
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/upgrade.test.ts:
Line 72: emitter.emit("close", exitCode);
Line 89: queueMicrotask(() => emitter.emit("error", new Error(message)));
Line 169: describe("parseInstallationMethod", () => {
Line 170: test("parses valid methods", () => {
Line 179: test("parses case-insensitively", () => {
Line 185: test("throws on invalid method", () => {
Line 192: describe("fetchLatestFromGitHub", () => {
Line 193: test("selects the latest CLI-prefixed Toolkit release", async () => {
Line 214: test("follows Toolkit release pagination to find the latest CLI release", async () => {
Line 245: test("rejects GitHub release pagination outside the selected source", async () => {
Line 263: test("classifies malformed GitHub release pagination as a network error", async () => {
Line 280: ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/upgrade.test.ts</path>
<type>file</type>
<content>
180: expect(parseInstallationMethod("NPM")).toBe("npm");
181: expect(parseInstallationMethod("Curl")).toBe("curl");
182: expect(parseInstallationMethod("YARN")).toBe("yarn");
183: });
184:
185: test("throws on invalid method", () => {
186: expect(() => parseInstallationMethod("pip")).toThrow("Invalid method: pip");
187: expect(() => parseInstallationMethod("apt")).toThrow("Invalid method: apt");
188: expect(() => parseInstallationMethod("")).toThrow("Invalid method: ");
189: });
190: });
191:
192: describe("fetchLatestFromGitHub", () => {
193: test("selects the latest CLI-prefixed Toolkit release", async () => {
194: const requests: string[] = [];
195: mockFetch(async (url) => {
196: requests.push(String(url));
197: return new Response(
198: ...
Found 9 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/upgrade.test.ts:
Line 185: test("throws on invalid method", () => {
Line 258: "GitHub returned an invalid release pagination URL"
Line 263: test("classifies malformed GitHub release pagination as a network error", async () => {
Line 269: Link: '<https://[invalid>; rel="next"',
Line 276: message: "GitHub returned an invalid release pagination URL",
Line 1465: test("handles lock file with invalid content", () => {
Line 1466: // Create lock with invalid PID
Line 1900: test("throws UpgradeError when manifest has no version annotation", async () => {
Line 1917: "Nightly manifest has no version annotation"
Found 21 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/release-notes.test.ts:
Line 42: - Add \`sentry sourcemap inject\` and upload commands by @BYK in [#547](https://github.com/getsentry/cli/pull/547)
Line 85: expect(features!.markdown).toContain("sourcemap");
Line 186: test("handles v-prefix in tag names", () => {
Line 303: describe("fetchChangelog source affinity", () => {
Line 316: test("fetches stable releases only from the explicitly selected Toolkit source", async () => {
Line 323: "mcp@99.0.0",
Line 324: "### New Features ✨\n\n- Unrelated Toolkit package release"
Line 327: "cli@0.21.0",
Line 328: "### Bug Fixes 🐛\n\n- Keep release stages source-affine"
Line 339: source: toolkitSource,
Line 344: "Unrelated Toolkit package release"
Line 354: test("builds a Toolkit changelog from ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/release-notes.test.ts</path>
<type>file</type>
<content>
160: expect(summary).not.toBeNull();
161: const allMarkdown = summary!.sections.map((s) => s.markdown).join("\n");
162: expect(allMarkdown).not.toContain("by @user in");
163: });
164:
165: test("merges same categories across releases", () => {
166: const summary = buildChangelogSummary(releases, "0.18.0", "0.21.0");
167: expect(summary).not.toBeNull();
168:
169: // Features from both 0.19, 0.20, and 0.21 should be in one section
170: const features = summary!.sections.filter((s) => s.category === "features");
171: expect(features).toHaveLength(1);
172: });
173:
174: test("sections appear in order: features, fixes, performance", () => {
175: const summary = buildChangelogSummary(releases, "0.18.0", "0.21.0");
176: ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/ghcr.test.ts</path>
<type>file</type>
<content>
1: /**
2: * GHCR Client Tests
3: *
4: * Unit tests for the GHCR/OCI download protocol helpers.
5: * All HTTP calls are mocked via globalThis.fetch to avoid network access.
6: */
7:
8: import { afterEach, beforeEach, describe, expect, test } from "vitest";
9: import { UPGRADE_SOURCES } from "../../src/lib/binary.js";
10: import { UpgradeError } from "../../src/lib/errors.js";
11: import {
12: downloadLayerBlob,
13: downloadNightlyBlob,
14: fetchManifest,
15: fetchNightlyManifest,
16: findLayerByFilename,
17: GHCR_REPO,
18: GHCR_TAG,
19: GhcrManifestHttpError,
20: getAnonymousToken,
21: getNightlyVersion,
22: listTags,
23: type OciManifest,
24: } from "../../src/lib/ghcr.js";
25:
26: /** Store original fetch for restoration */
27: let originalFetch: typeof globalThis.fetch;
28: ...
diff --git a/packages/cli/src/lib/binary.ts b/packages/cli/src/lib/binary.ts
index 75582612a..61e10568d 100644
--- a/packages/cli/src/lib/binary.ts
+++ b/packages/cli/src/lib/binary.ts
@@ -100,10 +100,37 @@ export type InstallationMethod =
| "pnpm"
| "bun"
| "yarn"
| "unknown";
+/** A repository pair that hosts CLI stable releases and nightly OCI images. */
+export type UpgradeSource = {
+ /** GitHub `owner/repository` containing CLI release assets. */
+ readonly githubRepo: string;
+ /** GHCR `owner/package` containing CLI nightly images and delta patches. */
+ readonly ghcrRepo: string;
+ /** Prefix attached to CLI release tags in this repository. */
+ readonly tagPrefix: string;
+};
+
+/** Ordered CLI release sources. The resolver falls through only on HTTP 404. ...
diff --git a/packages/cli/src/commands/cli/upgrade.ts b/packages/cli/src/commands/cli/upgrade.ts
index 8d8282368..610a12025 100644
--- a/packages/cli/src/commands/cli/upgrade.ts
+++ b/packages/cli/src/commands/cli/upgrade.ts
@@ -24,8 +24,9 @@ import {
isDowngrade,
LEGACY_INSTALL_SUBDIR,
releaseLock,
samePath,
+ type UpgradeSource,
} from "../../lib/binary.js";
import { buildCommand } from "../../lib/command.js";
import { CLI_VERSION } from "../../lib/constants.js";
import {
@@ -53,8 +54,10 @@ import {
type InstallationMethod,
NIGHTLY_TAG,
type OfflineMode,
parseInstallationMethod,
+ resolveExistingUpgradeVersion,
+ resolveLatestUpgradeVersion,
VERSION_PREFIX_REGEX,
versionExists,
} from "../../lib/upgrade.js";
import { whichSync } from "../../lib/which.js";
@@ -171,10 +174,15 @@ async function resolveTargetWithFallback(opts: {
/** Persist the channel after offline target resolution (deferred to avoid
* clearing the version cache before ...
No files found
No files found
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/node_modules/binpatch</path> <type>directory</type> <entries> dist/ LICENSE package.json README.md (4 entries) </entries>
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/node_modules/binpatch/dist/index.d.ts /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/node_modules/binpatch/dist/index.js.map /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/node_modules/binpatch/dist/index.js
Found 7 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/node_modules/binpatch/dist/index.js:
Line 688: const chain = await source.resolveChain(
Line 1133: async resolveChain(currentVersion, targetVersion, signal, report) {
Line 1225: function githubReleaseSource(config) {
Line 1227: const { releasesUrl, binaryName, userAgent } = config;
Line 1235: () => doFetch(`${releasesUrl}?per_page=${perPage}`, {
Line 1266: async resolveChain(currentVersion, targetVersion, signal, report) {
Line 1318: export { BinpatchError, MAX_NIGHTLY_CHAIN_DEPTH, MAX_OUTPUT_SIZE, MAX_STABLE_CHAIN_DEPTH, OciClient, PATCH_TAG_PREFIX, SIZE_THRESHOLD_RATIO, addDiffChunk, applyPatch, applyPatchChainInMemory, applyPatchToMemory, chainFileName, extractSha256, extractStableChain, filterAndSortChainTags, getPatchFromVersion, getPatchTargetSha256, getStableTargetSha256, ghcrSource, githubReleaseSource, ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/node_modules/binpatch/dist/index.js</path>
<type>file</type>
<content>
1210: totalSize += patchAsset.size;
1211: if (totalSize > fullGzSize * SIZE_THRESHOLD_RATIO) {
1212: return { failure: "over_budget" };
1213: }
1214: }
1215: patchUrls.reverse();
1216: const reversedReleases = [...chainReleases].reverse();
1217: const steps = [];
1218: let prevVersion = currentVersion;
1219: for (const release of reversedReleases) {
1220: steps.push({ fromVersion: prevVersion, toVersion: release.tag_name });
1221: prevVersion = release.tag_name;
1222: }
1223: return { patchUrls, expectedSha256, steps };
1224: }
1225: function githubReleaseSource(config) {
1226: const doFetch = config.fetch ?? fetch;
1227: const { releasesUrl, binaryName, userAgent } = config;
1228: const i = (name, fn) => config.instrument ? ...
diff --git a/packages/cli/test/commands/cli.test.ts b/packages/cli/test/commands/cli.test.ts
index cd1514eb0..187ae70f4 100644
--- a/packages/cli/test/commands/cli.test.ts
+++ b/packages/cli/test/commands/cli.test.ts
@@ -125,5 +125,5 @@ describe("upgradeCommand.func", () => {
test("shows installation info with specified method", async () => {
globalThis.fetch = (async () =>
- new Response(JSON.stringify({ tag_name: "v0.0.0-dev" }), {
+ new Response(JSON.stringify([{ tag_name: "cli@0.0.0-dev" }]), {
status: 200,
headers: { "Content-Type": "application/json" },
@@ -145,7 +145,7 @@ describe("upgradeCommand.func", () => {
test("check mode shows update available", async () => {
- // curl uses GitHub API which returns { tag_name: "vX.X.X" }
+ // Curl uses the Toolkit GitHub release list with product-prefixed tags.
globalThis.fetch = (async () =>
- new Response(JSON.stringify({ tag_name: "v99.0.0" }), {
+ new ...
diff --git a/packages/cli/test/lib/delta-upgrade.mocked.test.ts b/packages/cli/test/lib/delta-upgrade.mocked.test.ts
index cd0a2fddc..f6186ab59 100644
--- a/packages/cli/test/lib/delta-upgrade.mocked.test.ts
+++ b/packages/cli/test/lib/delta-upgrade.mocked.test.ts
@@ -100,8 +100,8 @@ describe("resolveStableDelta", () => {
// Since applyPatch will fail (we don't have a real TRDIFF10 matching this binary),
// we expect resolveStableDelta to throw, but the chain resolution should succeed
- const patchUrl = `https://github.com/getsentry/cli/releases/download/0.14.0/${BINARY_NAME}.patch`;
+ const patchUrl = `https://github.com/getsentry/toolkit/releases/download/cli@0.14.0/${BINARY_NAME}.patch`;
const releases = [
{
- tag_name: "0.14.0",
+ tag_name: "cli@0.14.0",
assets: [
{
@@ -124,5 +124,5 @@ describe("resolveStableDelta", () => {
},
{
- tag_name: "0.13.0",
+ tag_name: "cli@0.13.0",
assets: ...
Found 30 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/commands/cli/upgrade.test.ts:
Line 175: if (urlStr === "https://api.github.com/repos/getsentry/toolkit") {
Line 216: if (urlStr.includes("getsentry/toolkit/releases?per_page=100")) {
Line 217: return new Response(JSON.stringify([{ tag_name: `cli@${version}` }]), {
Line 226: return new Response(JSON.stringify({ tag_name: `cli@${version}` }), {
Line 256: if (urlStr === "https://api.github.com/repos/getsentry/toolkit") {
Line 412: test("uses the selected legacy source for the check-mode changelog", async () => {
Line 417: if (request.includes("getsentry/toolkit/releases?per_page=100")) {
Line 444: "https://api.github.com/repos/getsentry/toolkit/releases?per_page=30"
Line 454: if (urlStr.includes("getsentry/toolkit/releases?per_page=100")) {
Line 455: return ...
Found 30 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/upgrade.test.ts:
Line 210: "https://api.github.com/repos/getsentry/toolkit/releases?per_page=100",
Line 240: "https://api.github.com/repos/getsentry/toolkit/releases?per_page=100",
Line 241: "https://api.github.com/repos/getsentry/toolkit/releases?per_page=100&page=2",
Line 245: test("rejects GitHub release pagination outside the selected source", async () => {
Line 312: "https://api.github.com/repos/getsentry/toolkit/releases?per_page=100",
Line 330: "https://api.github.com/repos/getsentry/toolkit/releases?per_page=100",
Line 621: if (urlStr === "https://api.github.com/repos/getsentry/toolkit") {
Line 646: if (urlStr === "https://api.github.com/repos/getsentry/toolkit") {
Line 682: test("probes prefixed Toolkit tags and retains the selected source", async () => {
Line ...
REPORT ONLY. Your exact-head review returned an empty task_result. Do not inspect further or call tools. Return the substantive correctness report from your completed review of base ec83887a16f780f32fba4b7d710bad262dba3a22 and head c8c815bbecf472061ec02ab96d1a31f23f078d01 now. Required: findings first labeled PASS/CONCERN/MUST-FIX/BLOCKED with exact current file:line evidence; deterministic regression for every defect; residual gaps; final line exactly MERGE or DO-NOT-MERGE. If prior context is unavailable, return BLOCKED with that exact reason and DO-NOT-MERGE. Empty output is forbidden.
--check skips version resolution and can use the wrong sourceresolveTargetVersion() returns immediately for --check at:
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/commands/cli/upgrade.ts:339-345Pinned-version resolution happens only afterward:
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/commands/cli/upgrade.ts:362-368As a result, sentry cli upgrade 1.2.3 --check never verifies that 1.2.3 exists. It also associates the pinned target with the source that supplied the latest release. If Toolkit supplies the latest release but the pinned version exists only in the legacy repository, the check-mode changelog queries Toolkit instead of the legacy source.
The test at /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/commands/cli.test.ts:166-192 prepares an exact-tag response but never asserts that the request occurs, so it misses this path.
Fix: Resolve and validate an explicit pinned version before the flags.check return, then return the pinned version’s selected source.
Deterministic regression: Mock Toolkit latest as successful, Toolkit’s pinned tag as 404, and the legacy pinned tag as 200. Run cli upgrade 1.2.3 --check; assert both exact-tag probes occur in order, the changelog uses only getsentry/cli, and a both-404 variant returns version_not_found.
Each page is sorted internally at:
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/upgrade.ts:118-135But discovery returns as soon as any valid CLI version appears on the current page: