Dashboard › cli › Session 1YZ64v9a8cxd
1YZ64v9a8cxdijJxePerform a strictly read-only adversarial correctness review of getsentry/cli PR #1569 at exact base bd065083c and exact head 4094ae9a7 in worktree /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade. Inspect every changed file and relevant surrounding implementation/tests. The contract is: exact ordered source list Toolkit then legacy CLI; fallback only on genuine HTTP 404; every network/fetch/non-404/malformed failure is terminal; successful probe response is reused; one selected source remains attached through stable/nightly discovery, pinned validation, GHCR token/manifest/blob, delta chain, full download, background prefetch, and changelog; installer mirrors exact githubRepo/ghcrRepo/tagPrefix order and telemetry never blocks or propagates failure. Toolkit latest stable must filter cli@ tags and ignore MCP/prerelease entries; legacy retains unprefixed latest. Preserve existing APIs and offline/package-manager/channel behavior. Review only, never modify files or VCS. Report substantive findings first with PASS/CONCERN/MUST-FIX, exact file:line evidence, deterministic regression for each defect, and concrete fix. If no defect exists, state PASS and residual risks. End exactly MERGE or DO-NOT-MERGE.
<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/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. ...
bd065083c3b82677747b97a6cc7f5cf57532d3bc 4094ae9a7670f2bf46898fc7d5b8c7d89cf70819 M .github/workflows/ci.yml M package.json M packages/cli/install M packages/cli/package.json 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/upgrade.test.ts M packages/cli/test/lib/binary.test.ts M packages/cli/test/lib/delta-upgrade.test.ts M packages/cli/test/lib/ghcr.test.ts M packages/cli/test/lib/install-script.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 .github/workflows/ci.yml | 1 + package.json | 3 +- packages/cli/install | 192 +++++++++++--- packages/cli/package.json ...
4094ae9a7670f2bf46898fc7d5b8c7d89cf70819 4094ae9a7 (HEAD -> feat/toolkit-bridge-upgrade, origin/feat/toolkit-bridge-upgrade) feat(cli): add toolkit upgrade bridge
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/.github/workflows/ci.yml</path>
<type>file</type>
<content>
1: name: Build
2:
3: on:
4: push:
5: branches: [main, release/**]
6: pull_request:
7: workflow_call:
8:
9: concurrency:
10: group: ci-${{ github.ref }}
11: cancel-in-progress: true
12:
13: # packages:write is needed for publish-nightly to push to GHCR
14: # issues:write is needed for generate-patches to file issues on failure
15: permissions:
16: contents: read
17: issues: write
18: packages: write
19:
20: env:
21: # Commit timestamp used for deterministic nightly version strings.
22: # Defined at workflow level so build-binary and publish-nightly always agree.
23: COMMIT_TIMESTAMP: ${{ github.event.head_commit.timestamp }}
24: # SENTRY_CLIENT_ID is baked into the binary at build time. Fork PRs can't
25: # read repo vars (getsentry org policy); fall back to a dummy. ...
<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: ...
<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 {
25: acquireLock,
26: cleanupOldBinary,
27: determineInstallDir,
28: fetchWithUpgradeError,
29: ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/upgrade.ts</path>
<type>file</type>
<content>
701: method: InstallationMethod,
702: version: string,
703: source?: UpgradeSource
704: ): Promise<boolean> {
705: if (isNightlyVersion(version) || method === "curl" || method === "brew") {
706: return standaloneVersionExists(version, source);
707: }
708:
709: const response = await fetchWithUpgradeError(
710: `${NPM_REGISTRY_URL}/${version}`,
711: { method: "HEAD" },
712: "npm registry"
713: );
714: return response.ok;
715: }
716:
717: // Upgrade Execution
718:
719: /** Result from downloadBinaryToTemp — includes both the binary path and lock path */
720: export type DownloadResult = {
721: /** Path to the downloaded temporary binary */
722: tempBinaryPath: string;
723: /** Path to the lock file held during download (caller must release after child exits) */
724: ...
<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/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/ghcr.ts</path>
<type>file</type>
<content>
501: }
502: }
503:
504: if (tags.length < TAGS_PAGE_SIZE) {
505: break;
506: }
507:
508: lastTag = tags.at(-1);
509: }
510:
511: return allTags;
512: }
513:
514: /**
515: * Download an OCI layer blob as an ArrayBuffer.
516: *
517: * Uses the same redirect-without-auth pattern as {@link downloadNightlyBlob},
518: * but returns the fully-buffered ArrayBuffer instead of a streaming Response.
519: * Suitable for small payloads like patch files (50-500 KB).
520: *
521: * @param token - Anonymous bearer token from {@link getAnonymousToken}
522: * @param digest - Layer digest to download (e.g., "sha256:abc123...")
523: * @returns Raw blob contents as ArrayBuffer
524: * @throws {UpgradeError} On network failure or bad response
525: */
526: export async function ...
<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: ...
No files found
No files found
No files found
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/node_modules</path> <type>directory</type> <entries> .bin/ .vite-temp/ .vite/ @anthropic-ai/ @biomejs/ @clack/ @hono/ @mastra/ @sentry/ @spotlightjs/ @stricli/ @types/ @vitest/ binpatch/ chalk/ cli-highlight/ consola/ esbuild/ fast-check/ fflate/ fossilize/ hono/ http-cache-semantics/ ignore/ ink-spinner/ ink/ jpeg-js/ marked/ node-sqlite3-wasm/ p-limit/ peggy/ picomatch/ pixelmatch/ pngjs/ pretty-ms/ qrcode-terminal/ react-devtools-core/ react/ semver/ string-width/ tinyglobby/ tsx/ typescript/ ultracite/ uuidv7/ valibot/ vitest/ wrap-ansi/ (48 entries) </entries>
<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>
Found 8 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/node_modules/binpatch/dist/index.d.ts:
Line 589: declare function extractStableChain(opts: ExtractStableChainOpts): StableChainInfo | StableChainFailure;
Line 590: /** Configuration for {@link githubReleaseSource}. */
Line 612: declare function githubReleaseSource(config: GitHubReleaseSourceConfig): SourceStrategy;
Line 614: export { BinpatchError, type BinpatchErrorReason, type ChainMeta, type ChainStep, type DeltaResult, type DeltaSource, type DeltaTelemetry, type DeltaUnavailableReason, type ExtractStableChainOpts, type GhcrSourceConfig, type GitHubAsset, type GitHubRelease, type GitHubReleaseSourceConfig, type InstrumentHook, MAX_NIGHTLY_CHAIN_DEPTH, MAX_OUTPUT_SIZE, MAX_STABLE_CHAIN_DEPTH, type NightlyChainFailure, OciClient, type OciClientConfig, type OciLayer, type OciManifest, PATCH_TAG_PREFIX, type PatchCache, type PatchChain, type ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/node_modules/binpatch/dist/index.js</path>
<type>file</type>
<content>
1140: ),
1141: i(
1142: "list-patch-tags",
1143: () => client.listTags(token, PATCH_TAG_PREFIX, signal)
1144: )
1145: ]);
1146: const gzLayer = targetManifest.layers.find(
1147: (l) => l.annotations?.["org.opencontainers.image.title"] === `${binaryName}.gz`
1148: );
1149: if (!gzLayer) {
1150: report?.("malformed_chain");
1151: return null;
1152: }
1153: return await resolveNightlyChain({
1154: token,
1155: currentVersion,
1156: targetVersion,
1157: fullGzSize: gzLayer.size,
1158: preloadedTags: patchTags,
1159: signal,
1160: report
1161: });
1162: } catch (error) {
1163: ...
<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>
801: const uninstallHints: Record<string, string> = {
802: npm: "npm uninstall -g sentry",
803: pnpm: "pnpm remove -g sentry",
804: bun: "bun remove -g sentry",
805: yarn: "yarn global remove sentry",
806: brew: "brew uninstall getsentry/tools/sentry",
807: };
808: const warnings: string[] = [];
809: warnings.push(
810: `Your ${method}-installed sentry may still appear earlier in PATH.`
811: );
812: const hint = uninstallHints[method];
813: if (hint) {
814: warnings.push(`Consider removing it: ${hint}`);
815: }
816: return warnings;
817: }
818:
819: /**
820: * Resolve the channel, version arg, method, and channel-changed flag from
821: * the positional version argument and flags. Extracted to keep `func()`
822: * complexity under the biome limit. ...
<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/release-notes.ts</path>
<type>file</type>
<content>
701:
702: if (!response.ok) {
703: log.debug(`Nightly commits API returned ${response.status}`);
704: return null;
705: }
706:
707: let commits: unknown;
708: try {
709: commits = await response.json();
710: } catch (parseError) {
711: log.debug("Non-JSON response from GitHub commits", parseError);
712: return null;
713: }
714: if (!Array.isArray(commits) || commits.length === 0) {
715: return null;
716: }
717:
718: return buildNightlyChangelogSummary(
719: commits as GitHubCommit[],
720: fromVersion,
721: toVersion,
722: maxItems
723: );
724: }
725:
726: /** Options for {@link fetchChangelog} */
727: export type FetchChangelogOptions = {
728: /** Release channel */
729: channel: "stable" | "nightly";
730: /** Current version */
731: ...
<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/install</path>
<type>file</type>
<content>
1: #!/bin/bash
2: set -euo pipefail
3:
4: RED='\033[0;31m'
5: MUTED='\033[0;2m'
6: NC='\033[0m'
7:
8: # Sentry error telemetry — fire-and-forget error reporting via envelope API.
9: # Uses the CLI's public write-only DSN. No PII collected.
10: # Opt-out: SENTRY_CLI_NO_TELEMETRY=1
11: SENTRY_DSN_KEY="1188a86f3f8168f089450587b00bca66"
12: SENTRY_INGEST="https://o1.ingest.us.sentry.io"
13: SENTRY_PROJECT_ID="4510776311808000"
14:
15: # UPGRADE_SOURCES_SYNC: keep these github|ghcr|tag-prefix entries in sync with src/lib/binary.ts.
16: UPGRADE_SOURCES=('getsentry/toolkit|getsentry/toolkit|cli@' 'getsentry/cli|getsentry/cli|')
17:
18: # Generate a UUID for the event. Tries /proc, uuidgen, then awk fallback. ...
diff --git a/packages/cli/src/lib/binary.ts b/packages/cli/src/lib/binary.ts
index 75582612a..e30633c7e 100644
--- a/packages/cli/src/lib/binary.ts
+++ b/packages/cli/src/lib/binary.ts
@@ -45,247 +45,381 @@ 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`. ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/binary.test.ts</path>
<type>file</type>
<content>
1: /**
2: * Binary Management Tests
3: *
4: * Tests for shared binary helpers: install directory selection, paths,
5: * download URLs, locking, and binary installation.
6: */
7:
8: import {
9: chmodSync,
10: mkdirSync,
11: readFileSync,
12: realpathSync,
13: rmSync,
14: symlinkSync,
15: writeFileSync,
16: } from "node:fs";
17: import { access, readFile, writeFile } from "node:fs/promises";
18: import { join, sep } from "node:path";
19: import { afterEach, beforeEach, describe, expect, test } from "vitest";
20: import {
21: acquireLock,
22: compareVersions,
23: determineInstallDir,
24: fetchWithUpgradeError,
25: getBinaryDownloadUrl,
26: getBinaryFilename,
27: getBinaryPaths,
28: getGitHubReleaseByTagUrl,
29: getLegacyInstallDirs,
30: getPlatformBinaryName,
31: ...
Found 100 matches (more matches available)
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/version-check.test.ts:
Line 322: ["ApiError 404", new ApiError("not found", 404)],
Line 506: test("passes the Toolkit source from stable discovery to patch prefetch without legacy access", async () => {
Line 507: const toolkitSource = UPGRADE_SOURCES[0]!;
Line 513: throw new Error(`Unexpected legacy access: ${url}`);
Line 520: const prefetch = vi
Line 521: .spyOn(deltaUpgrade, "prefetchStablePatches")
Line 527: expect(prefetch).toHaveBeenCalledWith(
Line 530: toolkitSource
Line 534: "https://api.github.com/repos/getsentry/toolkit/releases?per_page=100",
Line 538: test("keeps stable patch prefetch on the legacy source selected after a Toolkit 404", async () => {
Line 539: const legacySource = UPGRADE_SOURCES[1]!;
Line 544: if ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/upgrade.test.ts</path>
<type>file</type>
<content>
150: // Store original fetch for restoration
151: let originalFetch: typeof globalThis.fetch;
152:
153: /** Helper to mock fetch without TypeScript errors about missing Bun-specific properties */
154: function mockFetch(
155: fn: (url: string | URL | Request, init?: RequestInit) => Promise<Response>
156: ): void {
157: globalThis.fetch = fn as typeof globalThis.fetch;
158: }
159:
160: beforeEach(() => {
161: originalFetch = globalThis.fetch;
162: });
163:
164: afterEach(() => {
165: globalThis.fetch = originalFetch;
166: });
167:
168: describe("parseInstallationMethod", () => {
169: test("parses valid methods", () => {
170: expect(parseInstallationMethod("curl")).toBe("curl");
171: expect(parseInstallationMethod("brew")).toBe("brew");
172: ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/upgrade.test.ts</path>
<type>file</type>
<content>
1040: // If DB says "yarn", respect it even if path says node_modules
1041: setInstallInfo({ method: "yarn", path: "/old/path", version: "0.0.1" });
1042: process.argv[1] = join(
1043: "/usr/local/lib",
1044: "node_modules",
1045: "sentry",
1046: "dist",
1047: "bin.cjs"
1048: );
1049:
1050: const method = await detectInstallationMethod();
1051: expect(method).toBe("yarn");
1052: });
1053:
1054: test("Homebrew still takes priority over node_modules path", async () => {
1055: process.argv[1] = join(
1056: "/usr/local/lib",
1057: "node_modules",
1058: "sentry",
1059: "dist",
1060: "bin.cjs"
1061: );
1062: Object.defineProperty(process, "execPath", {
1063: value: ...
Found 13 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/install-script.test.ts:
Line 35: describe("install script", () => {
Line 218: test("uses the primary source for the latest stable CLI release", async () => {
Line 228: test("filters Toolkit's latest releases by the CLI tag prefix", async () => {
Line 237: test("falls through to the legacy stable source only after a 404", async () => {
Line 248: test("stops source selection on a non-404 response", async () => {
Line 258: test("stops source selection on a network failure", async () => {
Line 268: test("probes and downloads a pinned stable release from the same source", async () => {
Line 278: test("selects a nightly source before requesting source-specific GHCR data", async () => {
Line 296: test("falls back when Toolkit's nightly manifest returns 404", async () => {
Line 311: test("stops when ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/install-script.test.ts</path>
<type>file</type>
<content>
1: /**
2: * Install Script Tests
3: *
4: * Exercises the shell installer with fake download tools so source selection,
5: * argument parsing, and setup delegation can be validated without network access.
6: */
7:
8: import { spawn } from "node:child_process";
9: import {
10: chmodSync,
11: mkdirSync,
12: mkdtempSync,
13: readFileSync,
14: rmSync,
15: writeFileSync,
16: } from "node:fs";
17: import { tmpdir } from "node:os";
18: import { join } from "node:path";
19: import { afterEach, beforeEach, describe, expect, test } from "vitest";
20: import { UPGRADE_SOURCES } from "../../src/lib/binary.js";
21:
22: type InstallerResult = {
23: exitCode: number;
24: stderr: string;
25: stdout: string;
26: };
27:
28: function noop(): void {
29: // Intentionally empty — absorbs ...
Command exited with non-zero status 1 0.00
Found 35 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 204: return new Response("Not Found", { status: 404 });
Line 216: if (urlStr.includes("getsentry/toolkit/releases?per_page=100")) {
Line 231: return new Response("Not Found", { status: 404 });
Line 242: return new Response("Not Found", { status: 404 });
Line 256: if (urlStr === "https://api.github.com/repos/getsentry/toolkit") {
Line 273: return new Response("Not Found", { status: 404 });
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 418: return new Response("Not Found", { status: 404 });
Line 444: ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/commands/cli/upgrade.test.ts</path> <type>file</type> <content> 1: /** 2: * Upgrade Command Tests 3: * 4: * Tests the `sentry cli upgrade` command through Stricli's run(). 5: * Covers resolveTargetVersion branches (check mode, already up-to-date, 6: * version validation) and error paths. 7: * 8: * Status messages go through consola (→ process.stderr). Tests capture stderr 9: * via a spy on process.stderr.write and assert on the collected output. ...
Found 37 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/delta-upgrade.test.ts:
Line 36: prefetchStablePatches,
Line 39: resolveStableChain,
Line 40: resolveStableDelta,
Line 48: throw new Error("Legacy upgrade source is not configured");
Line 837: "api.github.com/repos/getsentry/toolkit/releases"
Line 848: test("uses the selected legacy GitHub repository", async () => {
Line 914: // resolveStableChain (async orchestrator)
Line 916: describe("resolveStableChain", () => {
Line 970: const chain = await resolveStableChain("0.13.0", "0.14.0");
Line 980: test("keeps stable resolution on the selected legacy source", async () => {
Line 988: resolveStableChain("0.13.0", "0.14.0", undefined, LEGACY_UPGRADE_SOURCE)
Line 993: expect(urls.every((url) => !url.includes("getsentry/toolkit"))).toBe(true);
Line 1039: const chain = await ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/delta-upgrade.test.ts</path>
<type>file</type>
<content>
800: });
801: });
802: });
803:
804: // ===================================================================
805: // Async functions (fetch-mocked)
806: // ===================================================================
807:
808: /** Helper to mock globalThis.fetch */
809: function mockFetch(
810: fn: (url: string | URL | Request, init?: RequestInit) => Promise<Response>
811: ): void {
812: globalThis.fetch = fn as typeof globalThis.fetch;
813: }
814:
815: /** Store original fetch for restoration */
816: let originalFetch: typeof globalThis.fetch;
817:
818: beforeEach(() => {
819: originalFetch = globalThis.fetch;
820: });
821:
822: afterEach(() => {
823: globalThis.fetch = originalFetch;
824: });
825:
826: // fetchRecentReleases
827:
828: describe("fetchRecentReleases", () ...
...output truncated... Full output saved to: /home/byk/.local/share/opencode/tool-output/tool_086823fb5001zeoqVQkH4Ze3xZ * assets). When a user on brew/npm/pnpm/bun/yarn switches to nightly we: * 1. Download the nightly binary to a temp path * 2. Install it to `determineInstallDir()` (same logic as the curl installer) * 3. Run setup on the new binary to update completions, PATH, and metadata * 4. Return warnings about the old package-manager installation that may still be in PATH * * @param opts.versionArg - Specific version requested by the user, or undefined * for latest nightly. When a specific version is given, its release tag is * used instead of the rolling "nightly" tag so the correct binary is * downloaded. ...
trap -- 'printf exittrap >&2' EXIT doneexittrap
parent-356212 trap -- 'printf "exittrap-%s\n" "$BASHPID" >&2' EXIT child-356213 doneexittrap-356212
728:async function downloadNightlyToPath(
881: * from GHCR using the OCI blob download protocol via {@link downloadNightlyToPath}.
896: * @param downloadTag - Git tag to use in the download URL. Defaults to `version`.
904: downloadTag?: string,
943: await downloadFullBinary(version, downloadTag, tempPath, setMessage);
1004: * @param downloadTag - Git tag override for the download URL
1007:async function downloadFullBinary(
1009: downloadTag: string | undefined,
1014: await downloadNightlyToPath(destPath, version, setMessage);
1016: await downloadStableToPath(downloadTag ?? version, destPath, setMessage);
1116: * @param downloadTag - Git tag to download from. Defaults to `version`.
1125: downloadTag?: string,
1131: return downloadBinaryToTemp(version, downloadTag, offline, setMessage);
{"body":"## Summary\n\n- check Toolkit before the legacy CLI repositories for stable, nightly, delta, prefetch, and changelog requests\n- fall back only on HTTP 404 and retain one selected source through the complete upgrade operation\n- mirror the ordered source contract in the shell installer and enforce parity in CI\n\nCloses #1244\n\n## Validation\n\n- `pnpm run lint`\n- `pnpm run typecheck`\n- `pnpm run check:deps`\n- `pnpm run check:errors`\n- `pnpm run check:patches`\n- `pnpm run check:stale-refs`\n- `pnpm run check:upgrade-sources`\n- `shellcheck packages/cli/install`\n- focused bridge matrix: 458 tests passed\n- isolated rerun of the 10 full-suite failure files: 252 tests passed; the full coverage run had unrelated temp-directory/SQLite contention and one load timeout","comments":[{"id":"IC_kwDOQm6jAs8AAAABTfVUuQ","author":{"login":"vercel"},"authorAssociation":"NONE","body":"[vc]: ...
[{"url":"https://api.github.com/repos/getsentry/cli/pulls/comments/3969176168","pull_request_review_id":5155217387,"id":3969176168,"node_id":"PRRC_kwDOQm6jAs7slNJo","diff_hunk":"@@ -205,10 +207,151 @@ fi\n # Download binary to a temp location\n tmpdir=\"${TMPDIR:-${TMP:-${TEMP:-/tmp}}}\"\n tmp_binary=\"${tmpdir}/sentry-install-$$${suffix}\"\n+github_response=\"${tmpdir}/sentry-install-github-response-$$\"\n+nightly_manifest_file=\"${tmpdir}/sentry-install-nightly-manifest-$$\"\n version=\"\"\n \n # Clean up temp binary on failure (setup handles cleanup on success)\n-trap 'rm -f \"$tmp_binary\"' EXIT\n+trap 'rm -f \"$tmp_binary\" \"$github_response\" \"$nightly_manifest_file\"' EXIT\n+\n+# Fetch a GitHub API endpoint without collapsing HTTP failures into one curl\n+# error. The caller may fall through on a genuine 404; every transport failure\n+# and every other HTTP status stops source selection.\n+github_get() {\n+ local url=\"$1\"\n+ if ! ...
Found 4 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/node_modules/binpatch/dist/index.js:
Line 633: offline_cache_miss: "Cannot update offline \u2014 no pre-downloaded patch is available."
Line 654: async function resolveAndApply(opts) {
Line 662: offline,
Line 679: if (offline) {
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/node_modules/binpatch/dist/index.js</path>
<type>file</type>
<content>
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: currentVersion,
658: targetVersion,
659: oldPath,
660: destPath,
661: cache,
662: offline,
663: onProgress,
664: telemetry,
665: signal
666: } = opts;
667: const progress = safeProgress(onProgress);
668: if (cache) {
669: const cached = await tryLoadCachedChain(
670: cache,
671: currentVersion,
672: targetVersion
673: );
674: if (cached) {
675: telemetry?.onResolved?.({ source: ...
<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: getAnonymousToken,
20: getNightlyVersion,
21: listTags,
22: type OciManifest,
23: } from "../../src/lib/ghcr.js";
24:
25: /** Store original fetch for restoration */
26: let originalFetch: typeof globalThis.fetch;
27:
28: /** Helper to mock fetch ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/release-notes.test.ts</path>
<type>file</type>
<content>
280: });
281:
282: // ──────────────────── countListItems ────────────────────────────────────────
283:
284: describe("countListItems", () => {
285: test("counts items in a simple list", () => {
286: const tokens = marked.lexer("- item 1\n- item 2\n- item 3");
287: expect(countListItems(tokens)).toBe(3);
288: });
289:
290: test("returns 0 for non-list content", () => {
291: const tokens = marked.lexer("Just a paragraph.");
292: expect(countListItems(tokens)).toBe(0);
293: });
294:
295: test("returns 0 for empty token array", () => {
296: expect(countListItems([])).toBe(0);
297: });
298: });
299:
300: describe("fetchChangelog source affinity", () => {
301: const toolkitSource = UPGRADE_SOURCES[0]!;
302: const legacySource = UPGRADE_SOURCES[1]!;
303: let ...
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 67ec71067..6f018db43 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -228,40 +228,41 @@ jobs:
- uses: actions/setup-node@v6
with:
node-version: ${{ env.NODE_VERSION_22 }}
- uses: actions/cache@v5
id: cache
with:
path: |
node_modules
packages/*/node_modules
apps/*/node_modules
key: node-modules-${{ hashFiles('pnpm-lock.yaml', '.npmrc', 'packages/cli/patches/**') }}
- if: steps.cache.outputs.cache-hit != 'true'
run: pnpm install --frozen-lockfile
- run: pnpm run generate:schema
- run: pnpm run lint
- run: pnpm run typecheck
- run: pnpm run check:deps
- run: pnpm run check:errors
- run: pnpm run check:patches
- run: pnpm run check:stale-refs
+ - run: pnpm run check:upgrade-sources
test-unit:
name: Unit ...
{"body":"Sub-task of the toolkit monorepo merge: getsentry/cli#1248.\n\n## Goal\n\nShip one stable **bridge CLI release from `getsentry/cli` before any CLI history is imported into `getsentry/sentry-mcp`**. The bridge release must remain usable before the Toolkit rename and must discover releases from Toolkit after the rename. Older binaries must continue upgrading through the legacy endpoints.\n\nThis is a hard prerequisite for the repository merge.\n\n## Ordered source contract\n\n- New binaries and the install script always check the ordered source list:\n 1. `getsentry/toolkit` / `ghcr.io/getsentry/toolkit`\n 2. `getsentry/cli` / `ghcr.io/getsentry/cli`\n- Fall through to the next source only on HTTP 404. Network and fetch failures remain transient errors; they never poison a source.\n- Use one shared source definition for TypeScript and the generated install script. A check must fail if the two lists or their ordering diverge.\n- Old binaries only know `getsentry/cli`, so every ...
Found 2 matches /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/commands/cli/upgrade.test.ts: Line 884: await run(app, ["cli", "upgrade", "--method", "npm"], context); Line 1137: await run(app, ["cli", "upgrade", "--method", "npm", "nightly"], context);
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/commands/cli/upgrade.test.ts</path>
<type>file</type>
<content>
740: );
741: mkdirSync(testDir, { recursive: true });
742: mkdirSync(spawnBinDir, { recursive: true });
743: // Redirect getCurlInstallPaths() to temp dir
744: clearInstallInfo();
745: setInstallInfo({
746: method: "curl",
747: path: spawnInstallPath,
748: version: "0.0.0",
749: });
750:
751: originalFetch = globalThis.fetch;
752: spawnedArgs = [];
753:
754: // Spy on child_process.spawn — captures args and resolves with exit 0
755: spawnSpy = vi
756: .spyOn(child_process, "spawn")
757: .mockImplementation((cmd: string, args?: readonly string[]) => {
758: spawnedArgs.push({ cmd, args: [...(args ?? ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/version-check.test.ts</path>
<type>file</type>
<content>
470:
471: test("respects probabilistic checking when recently checked", async () => {
472: // Set a recent lastChecked time by calling setVersionCheckInfo
473: // This will set lastChecked to "now"
474: setVersionCheckInfo("1.0.0");
475:
476: const infoBefore = getVersionCheckInfo();
477: expect(infoBefore.lastChecked).not.toBeNull();
478: expect(infoBefore.latestVersion).toBe("1.0.0");
479:
480: // Call multiple times - with very recent check, probability is near 0
481: // so it's unlikely to trigger a new check
482: for (let i = 0; i < 5; i++) {
483: maybeCheckForUpdateInBackground();
484: }
485:
486: // Wait briefly
487: await sleep(50);
488: abortPendingVersionCheck();
489: });
490:
491: test("aborts cleanly when ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/delta-upgrade.test.ts</path>
<type>file</type>
<content>
1880: });
1881:
1882: // prefetch functions (background version-check optimization)
1883: // CLI_VERSION is "0.0.0-dev" in test, so canAttemptDelta bails early.
1884: // This exercises the function entry and the guard in prefetchAndCache.
1885:
1886: describe("prefetchNightlyPatches", () => {
1887: test("returns immediately when CLI_VERSION is dev", async () => {
1888: // Should not make any fetch calls since canAttemptDelta returns false
1889: mockFetch(async () => {
1890: throw new Error("fetch should not be called");
1891: });
1892:
1893: await prefetchNightlyPatches("0.14.0-dev.123");
1894: });
1895: });
1896:
1897: describe("prefetchStablePatches", () => {
1898: test("returns immediately when CLI_VERSION is dev", async () => {
1899: mockFetch(async () => ...
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
Test Files 8 passed (8)
Tests 458 passed (458)
Start at 14:16:57
Duration 13.60s (transform 12.32s, setup 311ms, import 20.68s, tests 10.83s, environment 1ms)
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/node_modules/binpatch/dist/index.d.ts</path>
<type>file</type>
<content>
530: /**
531: * Build a {@link SourceStrategy} backed by OCI patch-manifest tags (GHCR).
532: */
533: declare function ghcrSource(config: GhcrSourceConfig): SourceStrategy;
534:
535: /**
536: * GitHub Release-asset patch source (the "stable" channel).
537: *
538: * Resolves a patch chain from GitHub Release assets. Each release for the
539: * target platform publishes three assets:
540: * - `<binaryName>` — the binary (its digest → expected SHA-256)
541: * - `<binaryName>.gz` — gzipped binary (its size → the ratio gate)
542: * - `<binaryName>.patch` — the delta patch from the previous release
543: *
544: * The chain is the releases between current and target, oldest-first, capped
545: * at {@link MAX_STABLE_CHAIN_DEPTH} and by {@link SIZE_THRESHOLD_RATIO}. ...
Found 23 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/upgrade.test.ts:
Line 601: await expect(versionExists("curl", "1.0.0")).resolves.toBe(true);
Line 616: await expect(versionExists("curl", "1.0.0")).resolves.toBe(true);
Line 631: versionExists("curl", "1.0.0", UPGRADE_SOURCES[0])
Line 641: const exists = await versionExists("curl", "1.0.0");
Line 648: const exists = await versionExists("curl", "99.99.99");
Line 655: const exists = await versionExists("npm", "1.0.0");
Line 662: const exists = await versionExists("npm", "99.99.99");
Line 669: const exists = await versionExists("pnpm", "1.0.0");
Line 676: const exists = await versionExists("bun", "1.0.0");
Line 683: const exists = await versionExists("brew", "1.0.0");
Line 690: const exists = await versionExists("brew", "99.99.99");
Line 697: const exists = await ...
Found 8 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/version-check.ts:
Line 24: } from "./delta-upgrade.js";
Line 34: } from "./upgrade.js";
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/upgrade.ts:
Line 49: import { attemptDeltaUpgrade, type DeltaResult } from "./delta-upgrade.js";
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/release-notes.ts:
Line 24: import type { GitHubRelease } from "./delta-upgrade.js";
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/commands/cli/upgrade.ts:
Line 62: } from ...
(no output)
> toolkit-cli-workspace@0.0.0 check:upgrade-sources /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade
> pnpm --filter sentry run check:upgrade-sources
> sentry@0.45.0-dev.0 check:upgrade-sources /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli
> vitest run test/lib/install-script.test.ts -t 'embeds the shared ordered upgrade source list'
RUN v4.1.10 /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli
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
Test Files 1 passed (1)
Tests 1 passed | 11 skipped (12)
Start at 14:19:40
Duration 818ms (transform 448ms, setup 150ms, import 419ms, tests 7ms, environment 0ms)
4094ae9a7670f2bf46898fc7d5b8c7d89cf70819
{"chain":null,"urls":["https://api.github.com/repos/getsentry/toolkit/releases?per_page=12"]}
{"result":null,"urls":["https://api.github.com/repos/getsentry/toolkit/releases/tags/cli%400.45.0"]}
{"error":"Failed to fetch from GitHub: HTTP 500","urls":["https://api.github.com/repos/getsentry/toolkit","https://ghcr.io/token?scope=repository:getsentry/toolkit:pull","https://ghcr.io/v2/getsentry/toolkit/manifests/nightly","https://api.github.com/repos/getsentry/cli"]}
stableSource() changes only the repository URL; it never filters Toolkit releases or removes the cli@ prefix:
packages/cli/src/lib/delta-upgrade.ts:127-134packages/cli/src/lib/delta-upgrade.ts:561-568packages/cli/src/lib/delta-upgrade.ts:634-647binpatch compares release.tag_name directly with the unprefixed current and target versions:
packages/cli/node_modules/binpatch/dist/index.js:1191-1193Therefore, real Toolkit tags such as cli@0.45.0 never match target 0.45.0. Interactive delta upgrades and background stable prefetch always report no patches and fall back to the full binary.
The current test masks this defect by hitting Toolkit while supplying legacy-shaped, unprefixed tags:
packages/cli/test/lib/delta-upgrade.test.ts:947-977Deterministic regression: Return releases tagged cli@0.45.0 and cli@0.44.0, then call:
resolveStableChain("0.44.0", "0.45.0", undefined, UPGRADE_SOURCES[0])
At this exact head, the result was null; it fetched only:
https://api.github.com/repos/getsentry/toolkit/releases?per_page=12
It never requested the patch asset.
Fix: Adapt Toolkit releases before passing them to binpatch: filter by source.tagPrefix, exclude draft and prerelease releases, and strip the prefix from tag_name while preserving asset URLs. Alternatively, add explicit tagPrefix support to binpatch. Replace the misleading default-source tests with prefixed Toolkit fixtures, including unrelated MCP releases.
The low-level resolver correctly falls through only on response.status === 404, but higher layers discard that classification and inspect error text:
packages/cli/src/lib/binary.ts:313-316.isUpgradeSourceNotFound() searches that text at ...* 🔴 (14:18) User showed `packages/cli/node_modules/binpatch/dist/index.d.ts` lines 535–612 define the stable-channel GitHub Release patch source: each target-platform release publishes `<binaryName>`, `<binaryName>.gz`, and `<binaryName>.patch`; chains run from current to target oldest-first and are capped by `MAX_STABLE_CHAIN_DEPTH` and `SIZE_THRESHOLD_RATIO`. * 🔴 (14:18) User showed `GitHubAs…
* 🔴 (14:15) User showed `.github/workflows/ci.yml` adds `pnpm run check:upgrade-sources` to the lint/check job after `pnpm run check:stale-refs`. * 🔴 (14:15) User showed root `package.json` adds `"check:upgrade-sources": "pnpm --filter sentry run check:upgrade-sources"`. * 🔴 (14:15) User showed `packages/cli/package.json` adds `"check:upgrade-sources": "vitest run test/lib/install-script.test.…
* 🔴 (14:13) Cursor Bugbot comment `3969176168` on PR `getsentry/cli#1569`, commit `4094ae9a7670f2bf46898fc7d5b8c7d89cf70819`, reported a Medium Severity installer bug at `packages/cli/install#L324-L334` (`BUGBOT_BUG_ID: ed4075b4-8534-400f-b7a9-385dce20569e`): the Toolkit latest-release parser accepts the first stable-looking `cli@X.Y.Z` `tag_name` and never inspects GitHub `prerelease` or `draft…
* 🔴 (14:11) User showed source propagation changes in `packages/cli/src/commands/cli/upgrade.ts`: `UpgradeSource` is carried from `resolveTargetWithFallback()` through `startChangelogFetch()`, `fetchChangelog()`, `executeStandardUpgrade()`, and `migrateToStandaloneForNightly()`; the latter passes it to `executeUpgrade("curl", target, downloadTag, undefined, setMessage, source)`, ensuring one sel…
Date: Sep 9, 2026 * 🔴 (14:08) User showed the install-script test harness in `packages/cli/test/lib/install-script.test.ts`: `runInstaller()` spawns `bash` with `[installScript, ...args]`, prepends a temporary fake-tool directory to `PATH`, sets `SENTRY_CLI_NO_TELEMETRY=1`, `SENTRY_TEST_ARGS_FILE`, `SENTRY_TEST_REQUESTS_FILE`, `SENTRY_TEST_SCENARIO`, and `TMPDIR`, and captures exact `stdout`, `s…
* 🔴 (14:07) User stated `buildKnownCurlPaths()` in `packages/cli/test/lib/upgrade.test.ts` must normalize a trailing slash on `XDG_BIN_HOME` so every known directory ends with exactly one `sep`, never a double `sep` which would break `process.execPath.startsWith()` directory-boundary checks; non-absolute `XDG_BIN_HOME` values are ignored. * 🔴 (14:07) User showed `getCurlInstallPaths()` tests re…
* 🔴 (14:06) User stated that `~/.local/bin` and `~/bin` are valid current installation targets, never migration sources; this policy appears in `packages/cli/test/lib/binary.test.ts` near line 247. * 🔴 (14:06) User showed `packages/cli/test/lib/version-check.test.ts` tests enforcing source affinity: stable discovery passes `UPGRADE_SOURCES[0]` (Toolkit) to `deltaUpgrade.prefetchStablePatches` w…
* 🔴 (14:05) User showed changes to `packages/cli/src/lib/binary.ts`, `packages/cli/src/lib/ghcr.ts`, and `packages/cli/src/lib/version-check.ts` that add ordered fallback upgrade sources and propagate the selected source through stable/nightly version discovery and delta-patch prefetching. * 🔴 (14:05) In `packages/cli/src/lib/binary.ts`, `stripTrailingSep(p)` strips one trailing platform separa…
* 🔴 (14:05) User showed `/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/install`, a 488-line Bash installer using `set -euo pipefail`. * 🔴 (14:05) In `packages/cli/install`, Sentry installer error telemetry uses the envelope API with `SENTRY_INGEST="https://o1.ingest.us.sentry.io"` and `SENTRY_PROJECT_ID="4510776311808000"`;…
* 🔴 (14:02) User showed `/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/release-notes.ts`, which parses stable GitHub Release bodies and nightly conventional commits into `ChangelogSummary`; only `features`, `fixes`, and `performance` categories are retained and displayed in that order. * 🔴 (14:02) In `packages/cli/s…
* 🔴 (13:57) User provided search results showing 8 matches for `extractStableChain`/`githubReleaseSource` and related exports in `/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/node_modules/binpatch/dist/index.d.ts` and `/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/p…
* 🟡 (13:53) `packages/cli/node_modules/binpatch` contained exactly 4 entries: `dist/`, `LICENSE`, `package.json`, and `README.md`.
* 🟡 (13:51) `packages/cli/src/lib/delta-upgrade.ts` is a 648-line binpatch-backed delta-upgrade implementation. It imports `applyPatchChainInMemory`, stable/nightly source strategies, OCI support, patch-chain validation, caching, telemetry types, `MAX_NIGHTLY_CHAIN_DEPTH`, `PATCH_TAG_PREFIX`, and `SIZE_THRESHOLD_RATIO` from `binpatch`. * 🟡 (13:51) `packages/cli/src/lib/delta-upgrade.ts:50-70` p…
* 🟡 (13:50) `packages/cli/src/lib/binary.ts:29-54` defines curl-install locations: `KNOWN_CURL_DIRS = [".local/bin", "bin", ".sentry/bin"]`, `LEGACY_INSTALL_SUBDIR = join(".sentry", "bin")`, and `LEGACY_INSTALL_SUBDIRS = [LEGACY_INSTALL_SUBDIR]`. Migration is deliberately limited to pre-XDG `~/.sentry/bin`; `~/.local/bin` and `~/bin` are valid current XDG targets and must not be relocated. * 🔴 …
Date: Sep 9, 2026 * 🟡 (13:50) `packages/cli/src/lib/upgrade.ts:701-714` defines `versionExists(method, version, source?)`: nightly, curl, and brew installations use `standaloneVersionExists(version, source)`; npm-style installations send `HEAD` to `${NPM_REGISTRY_URL}/${version}` through `fetchWithUpgradeError()` and return `response.ok`. * 🟡 (13:50) `packages/cli/src/lib/upgrade.ts:719-727` de…
Date: Sep 9, 2026 * 🔴 [requested-review] (13:45) User requested a strictly read-only adversarial correctness review of getsentry/cli PR #1569 at exact base `bd065083c` and exact head `4094ae9a7`, using worktree `/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade`. * 🔴 (13:45) User required inspection of every changed file plus relevant surro…