Dashboard › cli › Session 1MdjcVXvtwTd
1MdjcVXvtwTdyCecnREAD-ONLY security/supply-chain merge-gate review of getsentry/cli PR #1569 exact base ec83887a16f780f32fba4b7d710bad262dba3a22 and head 2f9b5d0d26124d445a916b8bfc584ad518720584. Worktree /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade. Verify clean immutable state, inspect all changed files/tests. Focus on typed 404-only fallback/fail-closed errors; direct pinned source resolution without unrelated latest; trusted pagination; source affinity; strict/exact nightly binding; raw Toolkit changelog provenance and prefetched normalization; GHCR AbortError identity/token/redirect; SHA/delta/cache/offline; installer unchanged. Intentional nightly repo probe and source-neutral verified cache. Return NON-EMPTY findings-first report labeled PASS/CONCERN/MUST-FIX/BLOCKED with exact current file:line evidence, deterministic regression per defect, residual gaps. Final line exactly MERGE or DO-NOT-MERGE. Never modify files. Empty output forbidden.
/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/packages/cli/package.json /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/apps/local/package.json /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/codemods/sentry-v3-to-v4/package.json /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/apps/cli-docs/package.json /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/AGENTS.md /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade...
<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. ...
<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`. ...
<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/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: ...
No files found
Found 17 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\`. ...
2f9b5d0d26124d445a916b8bfc584ad518720584 ec83887a16f780f32fba4b7d710bad262dba3a22 2f9b5d0d26124d445a916b8bfc584ad518720584 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 e09b531a57734a11d4114214239aadefb6bca3fc16092f87989f71d825611552 -
packages/cli/src/commands/cli/upgrade.ts | 149 ++++-- packages/cli/src/lib/binary.ts | 154 +++++- packages/cli/src/lib/delta-upgrade.ts | 139 ++++-- packages/cli/src/lib/ghcr.ts | 91 +++- packages/cli/src/lib/release-notes.ts | 140 ++++-- packages/cli/src/lib/upgrade.ts | 414 ++++++++++++++--- packages/cli/src/lib/version-check.ts | 21 +- packages/cli/test/commands/cli.test.ts | 23 +- packages/cli/test/commands/cli/upgrade.test.ts | 134 +++++- packages/cli/test/lib/binary.test.ts | 130 +++++- packages/cli/test/lib/delta-upgrade.mocked.test.ts | 14 +- packages/cli/test/lib/delta-upgrade.test.ts | 201 +++++++- packages/cli/test/lib/ghcr.test.ts | 107 ++++- packages/cli/test/lib/release-notes.test.ts | 185 +++++++- packages/cli/test/lib/upgrade.test.ts | 517 +++++++++++++++++++-- ...
<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/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/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/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/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/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: ...
...output truncated...
Full output saved to: /home/byk/.local/share/opencode/tool-output/tool_0893ed4ae001sMS02fh6y0nys6
*
* @param homeDir - User's home directory
* @param env - Process environment variables
* @returns Absolute path to the install directory
*/
export function determineInstallDir(
homeDir: string,
env: NodeJS.ProcessEnv
): string {
const pathDirs = (env.PATH ?? "").split(delimiter);
// 1. Explicit override via environment variable
if (env.SENTRY_INSTALL_DIR) {
return env.SENTRY_INSTALL_DIR;
}
// 2. XDG_BIN_HOME override — honored only when absolute, per the XDG spec
const xdgBinHome = env.XDG_BIN_HOME;
if (xdgBinHome && isAbsolute(xdgBinHome)) {
return xdgBinHome;
}
diff --git a/packages/cli/src/lib/ghcr.ts b/packages/cli/src/lib/ghcr.ts
index 43d6deb7e..dbdef1fb6 100644
--- a/packages/cli/src/lib/ghcr.ts
+++ b/packages/cli/src/lib/ghcr.ts
@@ -1,520 +1,567 @@
/**
* GHCR (GitHub Container Registry) Client
...
Found 100 matches (more matches available)
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/upgrade.test.ts:
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("selects the highest CLI SemVer across Toolkit release pages", async () => {
Line 265: test("rejects GitHub release pagination outside the selected source", async () => {
Line 283: test("classifies malformed GitHub release pagination as a network error", async () => {
Line 300: test("rejects cyclic GitHub ...
...output truncated...
Full output saved to: /home/byk/.local/share/opencode/tool-output/tool_0893f586b001otYHplXIa64w9S
+ test("resolves prefixed Toolkit CLI releases and ignores other products", async () => {
const binaryName = getPlatformBinaryName();
const patchBytes = new Uint8Array([10, 20, 30]);
- const patchUrl = `https://github.com/getsentry/cli/releases/download/0.14.0/${binaryName}.patch`;
+ const patchUrl = `https://github.com/getsentry/toolkit/releases/download/cli@0.14.0/${binaryName}.patch`;
const releases: GitHubRelease[] = [
- makeRelease("0.14.0", [
+ makeRelease("mcp@9.0.0", [makeAsset({ name: binaryName })]),
+ makeRelease("cli@0.14.0", [
makeAsset({
name: binaryName,
digest: `sha256:${versionHex("0.14.0")}`,
@@ -939,7 +964,7 @@ describe("resolveStableChain", () => {
}),
makeAsset({ name: `${binaryName}.gz`, size: 100_000 }),
]),
- makeRelease("0.13.0", ...
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>
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/node_modules/binpatch/dist</path> <type>directory</type> <entries> index.d.ts index.js index.js.map (3 entries) </entries>
Found 22 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/node_modules/binpatch/dist/index.js:
Line 440: expectedSha256: chain.expectedSha256,
Line 510: let expectedSha256 = "";
Line 512: if (meta.toVersion === targetVersion && meta.expectedSha256) {
Line 513: expectedSha256 = meta.expectedSha256;
Line 517: if (!expectedSha256) return null;
Line 540: return { patches, totalSize, expectedSha256 };
Line 610: function makeCache(cacheDir) {
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) {
Line 707: return await cache.load(currentVersion, targetVersion);
Line 734: if (sha256 !== chain.expectedSha256) {
Line 736: `SHA-256 mismatch after patching: got ${sha256}, expected ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/node_modules/binpatch/dist/index.js</path>
<type>file</type>
<content>
580: join(cacheDir, chainFileName(meta.fromVersion, meta.toVersion))
581: ).catch(() => {
582: })
583: );
584: }
585: await Promise.all(deletions);
586: }
587: async function cleanupPatchCache(cacheDir) {
588: let files;
589: try {
590: files = await readdir(cacheDir);
591: } catch (err) {
592: if (isNotFound(err)) return;
593: throw err;
594: }
595: await removeExpiredEntries(cacheDir, files, Date.now());
596: }
597: async function clearPatchCache(cacheDir) {
598: let files;
599: try {
600: files = await readdir(cacheDir);
601: } catch (err) {
602: if (isNotFound(err)) return;
603: throw err;
604: }
605: await Promise.all(
606: files.map((file) => unlink(join(cacheDir, file)).catch(() => {
607: }))
608: );
609: ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/node_modules/binpatch/dist/index.js</path>
<type>file</type>
<content>
380: if (patches.length === 0) {
381: throw new Error("Cannot apply an empty patch chain");
382: }
383: let reader = await loadOldBinary(oldPath);
384: try {
385: for (let i = 0; i < patches.length - 1; i++) {
386: const patch = patches[i];
387: if (!patch) {
388: throw new Error(`Missing patch at index ${i}`);
389: }
390: const next = await applyReaderToMemory(reader, patch, onBytes);
391: await reader.close();
392: reader = new MemoryOldReader(next);
393: }
394: const finalPatch = patches.at(-1);
395: if (!finalPatch) {
396: throw new Error("Missing final patch");
397: }
398: return await applyReaderToFile(reader, finalPatch, destPath, onBytes);
399: } finally {
400: await reader.close();
401: ...
...output truncated...
Full output saved to: /home/byk/.local/share/opencode/tool-output/tool_089407a1d001pB8UNhH38teAaU
// (no specific version was requested). A specific version arg always
// uses its own tag so the correct release is downloaded.
const downloadTag =
channel === "nightly" && !versionArg ? NIGHTLY_TAG : undefined;
const downloadResult = await withProgress(
{ message: `Downloading ${target}...`, json },
async (setMessage) =>
- executeUpgrade(method, target, downloadTag, offline, setMessage)
+ executeUpgrade(method, target, downloadTag, offline, setMessage, source)
);
if (downloadResult?.patchBytes) {
log.info(
`Applied delta patch (${formatBytes(downloadResult.patchBytes)} downloaded)`
);
}
// Run setup on the new binary to update completions, agent skills,
// and record installation metadata.
if (downloadResult) {
// Curl: new binary is at temp path, setup --install will place it. ...
Found 23 matches /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/upgrade.ts: Line 31: getBinaryDownloadUrl, Line 36: getGitHubReleaseByTagUrl, Line 45: UPGRADE_SOURCES, Line 488: sources: readonly UpgradeSource[] = UPGRADE_SOURCES Line 543: source ? [source] : UPGRADE_SOURCES Line 590: sources: readonly UpgradeSource[] = UPGRADE_SOURCES Line 642: source ? [source] : UPGRADE_SOURCES Line 672: export function resolveLatestUpgradeVersion( Line 695: export async function resolveExistingUpgradeVersion( Line 703: UPGRADE_SOURCES Line 709: getProbeUrl: (source) => getGitHubReleaseByTagUrl(version, source), Line 757: getGitHubReleaseByTagUrl(version, source), Line 772: const resolved = await resolveExistingUpgradeVersion(version); Line 1004: const url = getBinaryDownloadUrl(version, ...
Found 84 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/commands/cli/upgrade.test.ts:
Line 168: * Mock fetch to simulate GHCR manifest returning a specific nightly version.
Line 187: // GHCR OCI manifest for :nightly tag
Line 188: if (urlStr.includes("/manifests/nightly")) {
Line 204: return new Response("Not Found", { status: 404 });
Line 231: return new Response("Not Found", { status: 404 });
Line 242: return new Response("Not Found", { status: 404 });
Line 247: * Mock fetch for the nightly version.json endpoint.
Line 250: * Mock fetch for GHCR nightly version checks (token exchange + manifest).
Line 251: * Used by nightly channel tests — replaces the old GitHub version.json mock.
Line 265: if (urlStr.includes("/manifests/nightly")) {
Line 273: return new Response("Not Found", { status: 404 });
Line 358: test("resolves a pinned ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/commands/cli/upgrade.test.ts</path>
<type>file</type>
<content>
320:
321: const { context, getOutput, restore } = createMockContext({
322: homeDir: testDir,
323: });
324: restoreStderr = restore;
325:
326: await run(
327: app,
328: ["cli", "upgrade", "--check", "--method", "curl"],
329: context
330: );
331:
332: const combined = getOutput();
333: expect(combined).toContain("99.99.99");
334: expect(combined).toContain("Run 'sentry cli upgrade' to update.");
335: });
336:
337: test("shows version-specific upgrade hint when user-specified version", async () => {
338: mockGitHubVersion("88.88.88");
339:
340: const { context, getOutput, restore } = createMockContext({
341: homeDir: testDir,
342: });
343: restoreStderr = restore;
344:
345: ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/commands/cli/upgrade.test.ts</path>
<type>file</type>
<content>
950: await run(app, ["cli", "upgrade", "--method", "brew", "--json"], context);
951:
952: const setupCall = spawnedArgs.find((entry) => entry.args.includes("setup"));
953: expect(setupCall?.cmd).toBe(binaryPath);
954: expect(setupCall?.args).not.toContain("--ensure-auth-scopes");
955: });
956:
957: test("reports setup failure when spawn exits non-zero", async () => {
958: // Use a unified mock that handles both the version endpoint and binary download
959: const fakeContent = new Uint8Array([0x7f, 0x45, 0x4c, 0x46]);
960: const gzipped = gzipSync(fakeContent);
961: mockFetch(async (url) => {
962: const urlStr = String(url);
963: if (urlStr.includes("getsentry/toolkit/releases?per_page=100")) {
964: return new Response(JSON.stringify([{ ...
Found 1 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/errors.ts:
Line 739: export class AbortError extends Error {
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/errors.ts</path>
<type>file</type>
<content>
730: // Error Utilities
731:
732: /**
733: * Thrown when an operation is cancelled via an AbortSignal.
734: *
735: * Matches the `error.name === "AbortError"` convention used throughout the
736: * codebase (version-check.ts, sentry-client.ts, binary.ts) to detect and
737: * silently swallow cancellation errors.
738: */
739: export class AbortError extends Error {
740: override name = "AbortError" as const;
741: constructor() {
742: super("The operation was aborted");
743: }
744: }
745:
746: /**
747: * Convert an unknown value to a human-readable string.
748: *
749: * Handles Error instances (`.message`), plain objects (`JSON.stringify`),
750: * strings (as-is), and other primitives (`String()`). ...
<path>/home/byk/.local/share/opencode/tool-output/tool_0893f586b001otYHplXIa64w9S</path>
<type>file</type>
<content>
1: diff --git a/packages/cli/test/commands/cli.test.ts b/packages/cli/test/commands/cli.test.ts
2: index cd1514eb0..187ae70f4 100644
3: --- a/packages/cli/test/commands/cli.test.ts
4: +++ b/packages/cli/test/commands/cli.test.ts
5: @@ -124,7 +124,7 @@ describe("upgradeCommand.func", () => {
6:
7: test("shows installation info with specified method", async () => {
8: globalThis.fetch = (async () =>
9: - new Response(JSON.stringify({ tag_name: "v0.0.0-dev" }), {
10: + new Response(JSON.stringify([{ tag_name: "cli@0.0.0-dev" }]), {
11: status: 200,
12: headers: { "Content-Type": "application/json" },
13: })) as typeof fetch;
14: @@ -144,9 +144,9 @@ describe("upgradeCommand.func", () => {
15: });
16:
17: test("check mode shows update available", async () => {
18: - // curl uses GitHub API which returns { tag_name: ...
<path>/home/byk/.local/share/opencode/tool-output/tool_0893f586b001otYHplXIa64w9S</path>
<type>file</type>
<content>
1433: + return new Response(JSON.stringify([{ tag_name: "mcp@9.0.0" }]), {
1434: + status: 200,
1435: + });
1436: + });
1437: +
1438: + await expect(fetchLatestFromGitHub()).rejects.toThrow(
1439: + "No version found in GitHub release"
1440: + );
1441: + expect(requests).toEqual([
1442: + "https://api.github.com/repos/getsentry/toolkit/releases?per_page=100",
1443: + ]);
1444: + });
1445: +
1446: + test("returns version from GitHub API", async () => {
1447: + mockFetch(
1448: + async () =>
1449: + new Response(JSON.stringify([{ tag_name: "cli@v1.2.3" }]), {
1450: + status: 200,
1451: + headers: { "Content-Type": "application/json" },
1452: + })
1453: );
1454:
1455: const version = await fetchLatestFromGitHub();
1456: @@ -209,15 +367,10 @@ describe("fetchLatestFromGitHub", () ...
Found 1 matches /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/custom-ca.ts: Line 305: export function customFetch(
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/custom-ca.ts</path>
<type>file</type>
<content>
280: " export NODE_EXTRA_CA_CERTS=/path/to/corporate-ca.pem"
281: );
282: }
283:
284: /**
285: * Get the combined CA certificate PEM string for Node.js `http.request()`.
286: * Returns undefined when no custom CAs are configured.
287: *
288: * Unlike {@link getCustomTlsOptions} (which returns Bun's `{ tls: { ca } }` shape),
289: * this returns the raw PEM string suitable for Node's `https.RequestOptions.ca`
290: * and the Sentry SDK's `NodeTransportOptions.caCerts`.
291: */
292: export function getCustomCaCerts(): string | undefined {
293: resolve();
294: return resolved?.tls.ca;
295: }
296:
297: /**
298: * Drop-in replacement for `fetch()` that injects custom CA certificates
299: * when configured. ...
No files found
4a1d5bad105c006193c68459175f5eb3c7f78e08 ec83887a16f780f32fba4b7d710bad262dba3a22 e09b531a57734a11d4114214239aadefb6bca3fc16092f87989f71d825611552 -
M packages/cli/test/commands/cli.test.ts 6ff55d3ba14c37ed40c650351727ab26b90fe8c43fe6dd4f31b327039161619d -
diff --git a/packages/cli/test/commands/cli.test.ts b/packages/cli/test/commands/cli.test.ts
index 187ae70f4..124e91b8f 100644
--- a/packages/cli/test/commands/cli.test.ts
+++ b/packages/cli/test/commands/cli.test.ts
@@ -195,45 +195,37 @@ describe("upgradeCommand.func", () => {
globalThis.fetch = (async () =>
new Response(JSON.stringify([{ tag_name: "cli@0.0.0-dev" }]), {
status: 200,
headers: { "Content-Type": "application/json" },
})) as typeof fetch;
const func = await upgradeCommand.loader();
const { context, getStdout, restore } = createMockContext();
restoreStderr = restore;
await func.call(context, { check: true, method: "curl", json: true });
const data = JSON.parse(getStdout()) as UpgradeResult;
expect(data.action).toBe("checked");
expect(data.currentVersion).toBe(data.targetVersion);
// No warnings when already on target
expect(data.warnings).toBeUndefined();
});
test("throws ...
The immutable review target changed during inspection.
2f9b5d0d26124d445a916b8bfc584ad5187205844a1d5bad105c006193c68459175f5eb3c7f78e08ec83887a16f780f32fba4b7d710bad262dba3a22e09b531a57734a11d4114214239aadefb6bca3fc16092f87989f71d825611552/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/commands/cli.test.tsThis invalidates the merge-gate verdict despite inspection of all 16 requested changed files.
extractReleaseVersions() rejects releases marked prerelease: true, but accepts a prerelease tag when GitHub metadata marks it false or omits the field. It then sorts that version alongside stable releases:
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/upgrade.ts:124-135A Toolkit release such as cli@99.0.0-dev.1 with prerelease: false can become the stable upgrade target. This violates strict channel binding and can install an unintended development build.
Fix: Exclude versions whose parsed SemVer contains prerelease identifiers, independent of GitHub’s release flag.
Deterministic regression: Return both cli@99.0.0-dev.1 with draft:false, prerelease:false and cli@1.2.3 from Toolkit. Assert stable discovery returns 1.2.3 and never contacts legacy.
The generic resolver treats every HTTP 2xx as proof of source availability:
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/binary.ts:341-345Pinned stable resolution then ...