Dashboard › cli › Session 0PXds8Ug8qsC
0PXds8Ug8qsCIJ68nREAD-ONLY final correctness merge-gate review of getsentry/cli PR #1569. Exact base ec83887a16f780f32fba4b7d710bad262dba3a22, exact head b6484e0fb1eb0f8bce68272d538f5c3b26cd5bd5, worktree /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade. Verify exact clean immutable state, inspect all changed files and relevant tests. Prior findings fixed here include pinned --check exact-source validation, highest SemVer across all canonical GitHub pagination pages, strict nightly X.Y.Z-dev.<digits> annotation validation, raw Toolkit changelog prefix filtering while normalized prefetched releases remain composable, genuine-404-only fallback, and GHCR cancellation. Review all bridge behavior including source affinity/delta/cache/offline/API compatibility. Intentional: nightly GitHub repository probe; source-neutral verified version-pair cache. Return NON-EMPTY findings-first report with PASS/CONCERN/MUST-FIX/BLOCKED labels, exact current file:line evidence, deterministic regression for defects, residual gaps. Final line exactly MERGE or DO-NOT-MERGE. Never modify files.
/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/.git /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. ...
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/AGENTS.md /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/CONTRIBUTING.md /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/AGENTS.md
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/AGENTS.md</path> <type>file</type> <content> 1: # AGENTS.md 2: 3: Guidelines for AI agents working in this codebase. 4: 5: ## Project Overview 6: 7: **Sentry CLI** is a command-line interface for [Sentry](https://sentry.io), built with Node.js, [pnpm](https://pnpm.io), and [Stricli](https://bloomberg.github.io/stricli/). It lives in `packages/cli` of a pnpm workspace; the docs site lives in `apps/cli-docs`. ...
No files found
No files found
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/CONTRIBUTING.md</path> <type>file</type> <content> 1: # Contributing to Sentry CLI 2: 3: This guide documents the patterns and conventions used in this CLI for consistency. 4: 5: ## Command Patterns 6: 7: We follow [gh CLI](https://cli.github.com/) conventions for best-in-class developer experience. 8: 9: ### List Commands 10: 11: List commands use **optional positional arguments** for context with smart auto-detection. 12: 13: ```bash 14: sentry org list [--limit N] [--json] 15: sentry project list [org] [--limit N] [--json] 16: sentry issue list [<org>/<project>] [--json] 17: ``` 18: 19: **Target syntax**: 20: - `<org>/<project>` - Explicit organization and project (e.g., `my-org/frontend`) 21: - `<org>/` - All projects in the specified organization 22: - `<project>` - Search for project by name across all accessible organizations 23: - *(omit)* - ...
<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: ...
Found 14 matches /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/.lore.md: Line 17: * **binpatch TRDIFF10 wire format + OCI tag scheme constants**: binpatch wire format (TRDIFF10): 8-byte magic \`TRDIFF10\x00\`, then LE int64 \`controlLen\`/\`diffLen\`/\`newSize\` (sign-magnitude), 24-byte control tuples with \`readDiffBy\`/\`readExtraBy\`/\`seekBy\` fields, zstd-compressed control/diff/extra blocks. OCI tag scheme: \`\<repo>:nightly\` (mutable pointer), \`\<repo>:nightly-\<version>\` (immutable), \`\<repo>:patch-\<version>\` (patches). Annotations: \`from-version=\<prev>\` (pointer, NOT hash — trust model), \`sha256-\<binaryName>=\<hex>\` (final binary hash only), \`org.opencontainers.image.title\`. Artifact type: \`application/vnd.\<prefix>.patch\`. Security limits: \`MAX\_OUTPUT\_SIZE=2\_147\_483\_648\` (2 GiB), \`MAX\_NIGHTLY\_CHAIN\_DEPTH=30\`, \`MAX\_STABLE\_CHAIN\_DEPTH=10\`, \`SIZE\_THRESHOLD\_RATIO=0.6\`. ...
b6484e0fb1eb0f8bce68272d538f5c3b26cd5bd5 ec83887a16f780f32fba4b7d710bad262dba3a22 b6484e0fb1eb0f8bce68272d538f5c3b26cd5bd5 0eda1b538486336e1cb906fff799ed481109a353 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 | 126 ++++-- packages/cli/src/lib/binary.ts | 154 +++++++- packages/cli/src/lib/delta-upgrade.ts ...
diff --git a/packages/cli/src/commands/cli/upgrade.ts b/packages/cli/src/commands/cli/upgrade.ts index 8d8282368..274789d10 100644 --- a/packages/cli/src/commands/cli/upgrade.ts +++ b/packages/cli/src/commands/cli/upgrade.ts @@ -1,414 +1,448 @@ /** * 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..61e10568d 100644
--- a/packages/cli/src/lib/binary.ts
+++ b/packages/cli/src/lib/binary.ts
@@ -45,247 +45,389 @@ export const LEGACY_INSTALL_SUBDIR = join(".sentry", "bin");
/**
* Legacy install sub-directories (relative to home) that predate the XDG
* layout and that migration is allowed to move a binary out of. Deliberately
* limited to the pre-XDG `~/.sentry/bin`: `~/.local/bin` and `~/bin` (also in
* {@link KNOWN_CURL_DIRS}) are valid *current* XDG install targets, so treating
* them as migration sources would relocate a working binary out of an active
* directory. An array so more legacy locations can be added if they ever exist.
*/
export const LEGACY_INSTALL_SUBDIRS = [LEGACY_INSTALL_SUBDIR];
/**
* Strip a trailing path separator (but never from a bare root like `/`) so a
* PATH entry such as `~/.local/bin/` compares equal to `~/.local/bin`. ...
diff --git a/packages/cli/src/lib/upgrade.ts b/packages/cli/src/lib/upgrade.ts
index 945adc48d..b669cd87b 100644
--- a/packages/cli/src/lib/upgrade.ts
+++ b/packages/cli/src/lib/upgrade.ts
@@ -1,139 +1,226 @@
/**
* 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 { valid as semverValid } from "semver";
import {
acquireLock,
cleanupOldBinary,
+ compareVersions,
determineInstallDir,
...
diff --git a/packages/cli/src/lib/delta-upgrade.ts b/packages/cli/src/lib/delta-upgrade.ts
index ec709b8c8..37f4b7d54 100644
--- a/packages/cli/src/lib/delta-upgrade.ts
+++ b/packages/cli/src/lib/delta-upgrade.ts
@@ -1,348 +1,418 @@
/** 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,
...
diff --git a/packages/cli/src/lib/release-notes.ts b/packages/cli/src/lib/release-notes.ts index ddf617535..07d43e54f 100644 --- a/packages/cli/src/lib/release-notes.ts +++ b/packages/cli/src/lib/release-notes.ts @@ -1,79 +1,81 @@ /** * 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/test/lib/binary.test.ts b/packages/cli/test/lib/binary.test.ts
index 6fcfb3b1a..5eaa53474 100644
--- a/packages/cli/test/lib/binary.test.ts
+++ b/packages/cli/test/lib/binary.test.ts
@@ -8,76 +8,202 @@
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,
isMusl,
releaseLock,
replaceBinarySync,
+ resolveUpgradeSource,
samePath,
+ UPGRADE_SOURCES,
+ UpgradeSourceNotFoundError,
} from "../../src/lib/binary.js";
import ...
diff --git a/packages/cli/test/lib/upgrade.test.ts b/packages/cli/test/lib/upgrade.test.ts
index 7c6f63a4b..2427fc34d 100644
--- a/packages/cli/test/lib/upgrade.test.ts
+++ b/packages/cli/test/lib/upgrade.test.ts
@@ -108,50 +108,52 @@ vi.mock("node:child_process", async (importOriginal) => {
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,
setInstallInfo,
} from "../../src/lib/db/install-info.js";
import { UpgradeError } from "../../src/lib/errors.js";
import { isProcessRunning } from "../../src/lib/process-utils.js";
const {
buildKnownCurlPaths,
...
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
@@ -115,116 +115,119 @@ describe("upgradeCommand.func", () => {
restoreStderr?.();
restoreStderr = undefined;
globalThis.fetch = originalFetch;
});
// Note: We skip testing "unknown installation method" case because
// detectInstallationMethod() runs actual shell commands (npm list, etc.)
// which can be slow/flaky in CI. The unknown method handling is tested
// indirectly through the upgrade.ts unit tests in lib/upgrade.test.ts.
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": ...
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
@@ -87,55 +87,55 @@ function tempFile(name: string): string {
// ============================================================================
// resolveStableDelta
// ============================================================================
describe("resolveStableDelta", () => {
test("resolves and applies a stable delta patch", async () => {
// Create a "current binary" to patch from
const oldBinaryPath = tempFile("old-binary.bin");
const destPath = tempFile("patched-binary.bin");
writeFileSync(oldBinaryPath, Buffer.from("old binary content for testing"));
// Set up fetch mocks — releases API + patch download
// Since applyPatch will fail (we don't have a real TRDIFF10 matching ...
No files found
No files found
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade</path> <type>directory</type> <entries> .craft.yml .git .github/ .gitignore .lore.md .nojekyll .npmrc AGENTS.md apps/ CHANGELOG.md codemods/ docs/ LICENSE.md node_modules/ package.json packages/ pnpm-lock.yaml pnpm-workspace.yaml README.md (19 entries) </entries>
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/node_modules</path> <type>directory</type> <entries> .modules.yaml .pnpm-workspace-state.json .pnpm/ (3 entries) </entries>
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 6 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/node_modules/binpatch/dist/index.js:
Line 654: async function resolveAndApply(opts) {
Line 707: return await cache.load(currentVersion, targetVersion);
Line 1225: function githubReleaseSource(config) {
Line 1227: const { releasesUrl, binaryName, userAgent } = config;
Line 1235: () => doFetch(`${releasesUrl}?per_page=${perPage}`, {
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, makeCache, offtin, parsePatchHeader, patchFileName, resolveAndApply, safeProgress, validateChainStep };
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/node_modules/binpatch/dist/index.js</path>
<type>file</type>
<content>
630: network_error: "Failed to fetch update information.",
631: execution_failed: "Applying the update failed.",
632: version_not_found: "The specified version was not found.",
633: offline_cache_miss: "Cannot update offline \u2014 no pre-downloaded patch is available."
634: };
635: super(message ?? defaultMessages[reason]);
636: this.name = "BinpatchError";
637: this.reason = reason;
638: }
639: };
640:
641: // src/events.ts
642: function safeProgress(handler) {
643: if (!handler) return () => {
644: };
645: return (event) => {
646: try {
647: handler(event);
648: } catch {
649: }
650: };
651: }
652:
653: // src/discover.ts
654: async function resolveAndApply(opts) {
655: const {
656: source,
657: ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/node_modules/binpatch/dist/index.js</path>
<type>file</type>
<content>
1200: const targetRelease = chainReleases[0];
1201: if (!targetRelease) return { failure: "no_patches" };
1202: const expectedSha256 = getStableTargetSha256(targetRelease, binaryName) ?? "";
1203: if (!expectedSha256) return { failure: "malformed_chain" };
1204: const patchUrls = [];
1205: let totalSize = 0;
1206: for (const release of chainReleases) {
1207: const patchAsset = release.assets.find((a) => a.name === patchAssetName);
1208: if (!patchAsset) return { failure: "malformed_chain" };
1209: patchUrls.push(patchAsset.browser_download_url);
1210: totalSize += patchAsset.size;
1211: if (totalSize > fullGzSize * SIZE_THRESHOLD_RATIO) {
1212: return { failure: "over_budget" };
1213: }
1214: }
1215: patchUrls.reverse();
1216: const ...
Found 100 matches (more matches available)
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/upgrade.test.ts:
Line 208: await expect(fetchLatestFromGitHub()).resolves.toBe("1.3.0");
Line 238: await expect(fetchLatestFromGitHub()).resolves.toBe("1.2.3");
Line 261: await expect(fetchLatestFromGitHub()).resolves.toBe("1.3.0");
Line 277: await expect(fetchLatestFromGitHub()).rejects.toThrow(
Line 294: await expect(fetchLatestFromGitHub()).rejects.toMatchObject({
Line 312: await expect(fetchLatestFromGitHub()).rejects.toThrow(
Line 330: await expect(fetchLatestFromGitHub()).resolves.toBe("1.2.3");
Line 346: await expect(fetchLatestFromGitHub()).rejects.toThrow(
Line 363: const version = await fetchLatestFromGitHub();
Line 376: const version = await fetchLatestFromGitHub();
Line 389: const version = await fetchLatestFromGitHub();
Line ...
Found 39 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/upgrade.ts:
Line 536: export async function fetchLatestFromGitHub(
Line 621: const token = await getAnonymousToken(source, signal);
Line 622: const manifest = await fetchManifest(token, tag, signal, source);
Line 635: export async function fetchLatestNightlyVersion(
Line 664: return fetchLatestNightlyVersion();
Line 667: ? fetchLatestFromGitHub()
Line 722: const token = await getAnonymousToken(source);
Line 724: await fetchManifest(token, `nightly-${version}`, undefined, source);
Line 948: const token = await getAnonymousToken(source);
Line 950: ? ...
Found 5 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/binary.ts:
Line 318: if (error instanceof Error && error.name === "AbortError") {
Line 488: * @throws {Error} AbortError if signal is aborted (re-thrown as-is)
Line 490: export async function fetchWithUpgradeError(
Line 498: // Re-throw AbortError as-is so callers can handle it specifically
Line 499: if (error instanceof Error && error.name === "AbortError") {
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/binary.ts</path>
<type>file</type>
<content>
280: readonly source: UpgradeSource;
281: /** The successful response from the source probe. */
282: readonly response: Response;
283: };
284:
285: /** All configured upgrade sources returned an HTTP 404 response. */
286: export class UpgradeSourceNotFoundError extends UpgradeError {
287: constructor() {
288: super(
289: "network_error",
290: "No CLI upgrade source was found: every source returned HTTP 404"
291: );
292: this.name = "UpgradeSourceNotFoundError";
293: }
294: }
295:
296: /** Configuration for selecting the first available upgrade source. */
297: export type ResolveUpgradeSourceOptions = {
298: /** Build the source-specific URL whose response proves source availability. ...
b6484e0fb (HEAD -> feat/toolkit-bridge-upgrade, origin/feat/toolkit-bridge-upgrade) fix(cli): validate resolved upgrade metadata c8c815bbe fix(cli): validate GitHub release pagination 5ffa5cd0f fix(cli): harden upgrade source resolution dbee7e9f2 test(cli): update toolkit upgrade fixtures 723375b6c fix(cli): address upgrade review findings 9c874298e fix(cli): address toolkit bridge review 04867eaf9 feat(cli): add toolkit upgrade bridge
DEPRECATED `test.poolOptions` was removed in Vitest 4. All previous `poolOptions` are now top-level options. Please, refer to the migration guide: https://vitest.dev/guide/migration#pool-rework
RUN v4.1.10 /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli
[warn] [delta-upgrade] Delta upgrade failed (Patch too small: 4 bytes (need at least 32)), falling back to full download
Test Files 8 passed (8)
Tests 334 passed (334)
Start at 02:25:22
Duration 10.81s (transform 10.48s, setup 377ms, import 18.26s, tests 5.81s, environment 1ms)
(no output)
Checked 16 files in 3s. No fixes applied.
b6484e0fb fix(cli): validate resolved upgrade metadata
packages/cli/src/commands/cli/upgrade.ts | 16 +++----
packages/cli/src/lib/ghcr.ts | 10 ++++
packages/cli/src/lib/release-notes.ts | 20 ++++----
packages/cli/src/lib/upgrade.ts | 18 +++----
packages/cli/test/commands/cli/upgrade.test.ts | 65 ++++++++++++++++++++++----
packages/cli/test/lib/ghcr.test.ts | 12 +++++
packages/cli/test/lib/release-notes.test.ts | 7 +++
packages/cli/test/lib/upgrade.test.ts | 20 ++++++++
8 files changed, 131 insertions(+), 37 deletions(-)
commit b6484e0fb1eb0f8bce68272d538f5c3b26cd5bd5
Author: Burak Yigit Kaya <byk@sentry.io>
Date: Thu Sep 10 02:19:10 2026 +0000
fix(cli): validate resolved upgrade metadata
diff --git a/packages/cli/src/lib/ghcr.ts b/packages/cli/src/lib/ghcr.ts
index 313ecced2..f556b35fc 100644
--- a/packages/cli/src/lib/ghcr.ts
+++ b/packages/cli/src/lib/ghcr.ts
@@ -1,70 +1,74 @@
/**
* GHCR ...
Found 14 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/version-check.ts:
Line 221: pendingAbortController?.abort();
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/init/wizard-runner.ts:
Line 1046: // AbortController.abort() is spec-idempotent, so no guard needed.
Line 1047: abortController.abort();
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/init/readiness.ts:
Line 40: const timer = setTimeout(() => controller.abort(), HEALTH_CHECK_TIMEOUT_MS);
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/sentry-client.ts:
Line 206: controller.abort();
Line 209: signal.addEventListener("abort", () => controller.abort(), { once: true ...
Found 100 matches (more matches available)
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/upgrade.test.ts:
Line 136: downloadBinaryToTemp,
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 265: test("rejects GitHub release pagination outside the selected source", async () => {
Line 318: test("falls back to the legacy latest release only on Toolkit HTTP 404", async () => {
Line 323: return new Response("Not Found", { status: 404 });
Line 332: "https://api.github.com/repos/getsentry/toolkit/releases?per_page=100",
Line 350: "https://api.github.com/repos/getsentry/toolkit/releases?per_page=100",
Line 397: status: 404,
...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/upgrade.test.ts</path>
<type>file</type>
<content>
1940:
1941: test("aborts early if signal is already aborted", async () => {
1942: const controller = new AbortController();
1943: controller.abort();
1944:
1945: await expect(
1946: fetchLatestNightlyVersion(controller.signal)
1947: ).rejects.toMatchObject({ name: "AbortError" });
1948: });
1949: });
1950:
1951: describe("executeUpgrade with curl method (nightly)", () => {
1952: const nightlyBinDir = join(TEST_TMP_DIR, "upgrade-nightly-test");
1953: const nightlyInstallPath = join(nightlyBinDir, "sentry");
1954:
1955: function getTestPaths() {
1956: return getCurlInstallPaths();
1957: }
1958:
1959: beforeEach(() => {
1960: clearInstallInfo();
1961: mkdirSync(nightlyBinDir, { recursive: true });
1962: setInstallInfo({
1963: method: ...
Found 7 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/commands/cli/upgrade.test.ts:
Line 217: return new Response(JSON.stringify([{ tag_name: `cli@${version}` }]), {
Line 226: return new Response(JSON.stringify({ tag_name: `cli@${version}` }), {
Line 364: return new Response(JSON.stringify([{ tag_name: "cli@99.99.99" }]), {
Line 461: test("uses the selected legacy source for the check-mode changelog", async () => {
Line 504: return new Response(JSON.stringify([{ tag_name: "cli@99.99.99" }]), {
Line 840: return new Response(JSON.stringify([{ tag_name: `cli@${version}` }]), {
Line 966: return new Response(JSON.stringify([{ tag_name: "cli@99.99.99" }]), {
Found 1 matches /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/e2e/delta-upgrade.test.ts: Line 64: const baseUrl = "https://github.com/getsentry/cli/releases/download";