Dashboard › cli › Session 01Gq9Q4pTHLg
01Gq9Q4pTHLgw4vbPRead-only analysis in /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade. Analyze packages/cli/src/lib/upgrade.ts, src/commands/cli/upgrade.ts, src/lib/version-check.ts, src/lib/release-notes.ts, and their relevant tests. Map the smallest type/signature changes needed to return and retain a resolved UpgradeSource for stable latest, explicit stable versions, rolling nightly, and pinned nightly. Contract: sources are getsentry/toolkit cli@ first then getsentry/cli unprefixed; fallback only on HTTP 404; non-404 and transport/malformed failures stop; source success never contacts legacy; package-manager stable upgrades remain npm-based and need no GitHub source; direct helpers may default primary, production standalone paths explicitly pass source. Flag compatibility concerns and exact regressions. Do not edit files or run broad tests. Return concise file/symbol recommendations.
<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/ LICENSE.md node_modules/ package.json packages/ pnpm-lock.yaml pnpm-workspace.yaml README.md (18 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/.lore.md</path>
<type>file</type>
<content>
1: <!-- Managed by lore (https://github.com/BYK/loreai) — manual edits are imported on next session. -->
2:
3: ## Long-term Knowledge
4:
5: ### Architecture
6:
7: <!-- lore:01a02357-f0a8-7fdb-9e9d-b0710cfe65c9 -->
8: * **API output binary and HTTP contracts**: Always preserve strict output-mode and binary-safety contracts. `sentry api` must preserve `rawApiRequest()` status text; empty textual non-2xx bodies must produce an HTTP status/request fallback, and JSON mode must expose `{status, statusText, body}` so empty success and error responses are distinguishable. Binary `Uint8Array` successes bypass formatters and remain raw; binary errors emit only status/content-type/byte-count summaries, never bytes or JSON coercion. Prompts must never block scripted runs or interleave with stdout JSON.
9:
10: <!-- ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/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/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/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 { CLI_VERSION } from "./constants.js";
14: import { getReleaseChannel } from "./db/release-channel.js";
15: import {
16: getVersionCheckInfo,
17: markUpdateNotified,
18: setVersionCheckInfo,
19: } from ...
<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()`. ...
Found 82 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/upgrade.test.ts:
Line 137: fetchLatestFromGitHub,
Line 190: describe("fetchLatestFromGitHub", () => {
Line 205: const version = await fetchLatestFromGitHub();
Line 223: const version = await fetchLatestFromGitHub();
Line 241: const version = await fetchLatestFromGitHub();
Line 253: await expect(fetchLatestFromGitHub()).rejects.toThrow(UpgradeError);
Line 254: await expect(fetchLatestFromGitHub()).rejects.toThrow(
Line 264: await expect(fetchLatestFromGitHub()).rejects.toThrow(UpgradeError);
Line 265: await expect(fetchLatestFromGitHub()).rejects.toThrow(
Line 279: await expect(fetchLatestFromGitHub()).rejects.toThrow(
Line 551: const exists = await versionExists("curl", "1.0.0");
Line 558: const exists = await versionExists("curl", "99.99.99");
Line 565: const ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/binary.ts</path>
<type>file</type>
<content>
80: /**
81: * Absolute legacy install directories for the given home. See
82: * {@link LEGACY_INSTALL_SUBDIRS} for why this is scoped to pre-XDG locations.
83: */
84: export function getLegacyInstallDirs(homeDir: string): string[] {
85: return LEGACY_INSTALL_SUBDIRS.map((dir) => join(homeDir, dir));
86: }
87:
88: /**
89: * How the CLI was installed. Determines the upgrade strategy.
90: *
91: * Defined here (alongside other installation constants like
92: * {@link KNOWN_CURL_DIRS}) so that both `upgrade.ts` and
93: * `db/install-info.ts` can import it without creating a circular
94: * dependency. ...
Found 3 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/binary.ts:
Line 273: headers: getGitHubHeaders(),
Line 408: export function getGitHubHeaders(): Record<string, string> {
Line 426: export async function fetchWithUpgradeError(
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/binary.ts</path>
<type>file</type>
<content>
390: // 3-4. Check well-known directories that are already in PATH. samePath keeps
391: // the membership check case-insensitive on Windows/macOS, where a PATH entry
392: // can differ in casing from the computed directory yet be the same dir.
393: const candidates = [join(homeDir, ".local", "bin"), join(homeDir, "bin")];
394:
395: for (const dir of candidates) {
396: if (existsSync(dir) && pathDirs.some((p) => samePath(p, dir))) {
397: return dir;
398: }
399: }
400:
401: // 5. XDG-aligned fallback — setup will handle adding this to PATH
402: return join(homeDir, ".local", "bin");
403: }
404:
405: /**
406: * Build headers for GitHub API requests.
407: */
408: export function getGitHubHeaders(): Record<string, string> {
409: return {
410: Accept: ...
<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/delta-upgrade.ts</path>
<type>file</type>
<content>
480: offline,
481: onProgress: makeProgressHandler(setMessage),
482: telemetry: tel,
483: }).then((result) => ({ result, source: tel._source.current }));
484: }
485:
486: // biome-ignore lint/nursery/useMaxParams: preserve the existing public API
487: export function resolveStableDelta(
488: targetVersion: string,
489: oldBinaryPath: string,
490: destPath: string,
491: offline?: boolean,
492: setMessage?: SetMessage
493: ): Promise<DeltaResult | null> {
494: return resolveDelta(
495: stableSource(),
496: targetVersion,
497: oldBinaryPath,
498: destPath,
499: offline,
500: setMessage
501: ).then(({ result }) => result);
502: }
503:
504: // biome-ignore lint/nursery/useMaxParams: preserve the existing public API
505: export function ...
<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>
256: /**
257: * Fetch the OCI manifest for the `:nightly` tag.
258: *
259: * Convenience wrapper around {@link fetchManifest} for the rolling nightly tag.
260: *
261: * @param token - Anonymous bearer token from {@link getAnonymousToken}
262: * @returns Parsed OCI manifest
263: * @throws {UpgradeError} On network failure or non-200 response
264: */
265: export async function fetchNightlyManifest(
266: token: string
267: ): Promise<OciManifest> {
268: return await fetchManifest(token, GHCR_TAG);
269: }
270:
271: /**
272: * Extract the nightly version string from a manifest's annotations.
273: *
274: * The version is set via `--annotation "version=<ver>"` during `oras push`.
275: *
276: * @param manifest - OCI manifest from {@link fetchNightlyManifest}
277: * @returns Version string (e.g., ...
M packages/cli/src/lib/binary.ts M packages/cli/test/lib/binary.test.ts M packages/cli/test/lib/ghcr.test.ts M packages/cli/test/lib/install-script.test.ts 0e661a5f5 fix(org): log region URL parse failures in org list (#1539) 9d0901b10 feat(local): Add agent debugging stream (#1538) 72c307f47 fix(cli): log UID resolution failures in sentry cli fix (#1541) e710ce905 fix(telemetry): log process-tree walk failures in agent detection (#1542) 6e3e7e13a feat(config): follow XDG Base Directory spec for config location (#1503)
diff --git a/packages/cli/src/lib/binary.ts b/packages/cli/src/lib/binary.ts
index 75582612a..a50bc0949 100644
--- a/packages/cli/src/lib/binary.ts
+++ b/packages/cli/src/lib/binary.ts
@@ -102,6 +102,33 @@ export type InstallationMethod =
| "yarn"
| "unknown";
+/** A repository pair that hosts CLI stable releases and nightly OCI images. */
+export type UpgradeSource = {
+ /** GitHub `owner/repository` containing CLI release assets. */
+ readonly githubRepo: string;
+ /** GHCR `owner/package` containing CLI nightly images and delta patches. */
+ readonly ghcrRepo: string;
+ /** Prefix attached to CLI release tags in this repository. */
+ readonly tagPrefix: string;
+};
+
+/** Ordered CLI release sources. The resolver falls through only on HTTP 404. ...
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/upgrade.test.ts /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/commands/cli/upgrade.test.ts /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/delta-upgrade.test.ts /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/delta-upgrade.mocked.test.ts /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/e2e/delta-upgrade.test.ts
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/version-check.test.ts
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/release-notes.test.ts /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/release-notes.property.test.ts
Found 100 matches (more matches available)
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/upgrade.test.ts:
Line 6: * The `executeUpgrade` and `detectInstallationMethod` subprocess tests use
Line 135: downloadBinaryToTemp,
Line 136: executeUpgrade,
Line 137: fetchLatestFromGitHub,
Line 140: fetchLatestVersion,
Line 144: versionExists,
Line 190: describe("fetchLatestFromGitHub", () => {
Line 205: const version = await fetchLatestFromGitHub();
Line 223: const version = await fetchLatestFromGitHub();
Line 241: const version = await fetchLatestFromGitHub();
Line 253: await expect(fetchLatestFromGitHub()).rejects.toThrow(UpgradeError);
Line 254: await expect(fetchLatestFromGitHub()).rejects.toThrow(
Line 264: await expect(fetchLatestFromGitHub()).rejects.toThrow(UpgradeError);
Line 265: await ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/upgrade.test.ts</path>
<type>file</type>
<content>
1: /**
2: * Upgrade Module Tests
3: *
4: * Tests for upgrade detection and logic.
5: *
6: * The `executeUpgrade` and `detectInstallationMethod` subprocess tests use
7: * `vi.mock("node:child_process", ...)` at the top of this file to
8: * intercept `spawn()` calls via a swappable `spawnImpl`. Non-spawn exports
9: * pass through to the real `node:child_process`. ...
Found 12 matches /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/ghcr.test.ts: Line 91: const token = await getAnonymousToken(); Line 105: await expect(getAnonymousToken(UPGRADE_SOURCES[0])).resolves.toBe( Line 113: await expect(getAnonymousToken()).rejects.toThrow(UpgradeError); Line 114: await expect(getAnonymousToken()).rejects.toThrow( Line 124: await expect(getAnonymousToken()).rejects.toThrow(UpgradeError); Line 125: await expect(getAnonymousToken()).rejects.toThrow( Line 139: await expect(getAnonymousToken()).rejects.toThrow(UpgradeError); Line 140: await expect(getAnonymousToken()).rejects.toThrow( /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/ghcr.ts: Line 192: export async function getAnonymousToken(signal?: AbortSignal): Promise<string> ...
Found 46 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/upgrade.ts:
Line 482: const manifest = await fetchNightlyManifest(token);
Line 525: await fetchManifest(token, `nightly-${version}`);
Line 735: ? await fetchManifest(token, `nightly-${version}`)
Line 736: : await fetchNightlyManifest(token);
Line 739: const response = await downloadNightlyBlob(token, layer.digest);
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/ghcr.test.ts:
Line 164: const result = await fetchNightlyManifest("my-token");
Line 182: fetchNightlyManifest("token", undefined, UPGRADE_SOURCES[0])
Line 189: await expect(fetchNightlyManifest("token")).rejects.toThrow(UpgradeError);
Line 190: await expect(fetchNightlyManifest("token")).rejects.toThrow(
Line 200: await ...
Found 100 matches (more matches available)
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/commands/cli/upgrade.test.ts:
Line 6: * version validation) and error paths.
Line 45: /** Store original fetch for restoration */
Line 46: let originalFetch: typeof globalThis.fetch;
Line 48: /** Helper to mock fetch */
Line 52: globalThis.fetch = fn as typeof globalThis.fetch;
Line 168: * Mock fetch to simulate GHCR manifest returning a specific nightly version.
Line 169: * Handles token exchange and manifest fetch.
Line 171: function mockGhcrNightlyVersion(version: string): void {
Line 176: if (urlStr.includes("ghcr.io/token")) {
Line 183: // GHCR OCI manifest for :nightly tag
Line 184: if (urlStr.includes("/manifests/nightly")) {
Line 189: annotations: { version },
Line 194: "content-type": "application/vnd.oci.image.manifest.v1+json",
Line ...
<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. ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/commands/cli/upgrade.test.ts</path>
<type>file</type>
<content>
521: });
522:
523: describe("resolveChannelAndVersion", () => {
524: test("'nightly' positional sets channel to nightly", async () => {
525: mockNightlyVersion(CLI_VERSION);
526:
527: const { context, getOutput, restore } = createMockContext({
528: homeDir: testDir,
529: });
530: restoreStderr = restore;
531:
532: await run(
533: app,
534: ["cli", "upgrade", "--check", "--method", "curl", "nightly"],
535: context
536: );
537:
538: const combined = getOutput();
539: expect(combined).toContain("Channel: nightly");
540: });
541:
542: test("'stable' positional sets channel to stable", async () => {
543: mockGitHubVersion(CLI_VERSION);
544: setReleaseChannel("nightly");
545:
546: ...
Found 19 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/version-check.test.ts:
Line 197: test("uses 'New nightly available:' label when on nightly channel", () => {
Line 198: setReleaseChannel("nightly");
Line 203: expect(notification).toContain("New nightly available:");
Line 208: test("uses 'Update available:' label when on stable channel", () => {
Line 209: setReleaseChannel("stable");
Line 215: expect(notification).not.toContain("New nightly available:");
Line 418: let originalFetch: typeof globalThis.fetch;
Line 424: // Silence background fetch calls to GitHub API that would otherwise
Line 425: // hit the preload mock and produce "unexpected fetch" warnings.
Line 426: originalFetch = globalThis.fetch;
Line 427: globalThis.fetch = mockFetch(
Line 438: globalThis.fetch = originalFetch;
Line 447: // The actual ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/version-check.test.ts</path>
<type>file</type>
<content>
1: /**
2: * Version Check Logic Tests
3: */
4:
5: import { setTimeout as sleep } from "node:timers/promises";
6: import { afterEach, beforeEach, describe, expect, test } from "vitest";
7: import { setReleaseChannel } from "../../src/lib/db/release-channel.js";
8: import {
9: getVersionCheckInfo,
10: setVersionCheckInfo,
11: } from "../../src/lib/db/version-check.js";
12: import {
13: ApiError,
14: ContextError,
15: ValidationError,
16: } from "../../src/lib/errors.js";
17: import {
18: abortPendingVersionCheck,
19: getErrorUpdateNotification,
20: getUpdateNotification,
21: maybeCheckForUpdateInBackground,
22: resetUpdateNotificationState,
23: shouldSuppressNotification,
24: } from "../../src/lib/version-check.js";
25: import { mockFetch, useTestConfigDir } from ...
Found 21 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/release-notes.test.ts:
Line 112: const releases: GitHubRelease[] = [
Line 125: test("filters releases within version range", () => {
Line 126: const summary = buildChangelogSummary(releases, "0.19.0", "0.21.0");
Line 138: test("returns null when no releases in range", () => {
Line 139: expect(buildChangelogSummary(releases, "0.21.0", "0.22.0")).toBeNull();
Line 149: expect(buildChangelogSummary(releases, "0.17.0", "0.18.0")).toBeNull();
Line 153: const summary = buildChangelogSummary(releases, "0.19.0", "0.20.0");
Line 159: test("merges same categories across releases", () => {
Line 160: const summary = buildChangelogSummary(releases, "0.18.0", "0.21.0");
Line 169: const summary = buildChangelogSummary(releases, "0.18.0", "0.21.0");
Line 190: const summary = ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/release-notes.test.ts</path>
<type>file</type>
<content>
1: /**
2: * Unit Tests for Release Notes Parser & Aggregation
3: *
4: * Tests core invariants (section extraction, version filtering, truncation)
5: * that are hard to express as property-based tests due to format specifics.
6: *
7: * Core random-input invariants (category validity, filtering, commit parsing)
8: * are tested via property-based tests in release-notes.property.test.ts.
9: */
10:
11: import { marked } from "marked";
12: import { describe, expect, test } from "vitest";
13: import type { GitHubRelease } from "../../src/lib/delta-upgrade.js";
14: import {
15: buildChangelogSummary,
16: type ChangeCategory,
17: countListItems,
18: extractNightlyTimestamp,
19: extractSections,
20: parseCommitMessages,
21: } from "../../src/lib/release-notes.js";
22:
23: // ...
Found 33 matches /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/pnpm-lock.yaml: Line 1548: '@sentry/cli@2.58.6': Line 4207: trpc-cli@0.12.4: Line 6000: '@sentry/cli@2.58.6': Line 9255: trpc-cli@0.12.4(@trpc/server@11.18.0(typescript@5.9.3))(valibot@1.4.2(typescript@5.9.3))(zod@4.4.3): /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/apps/cli-docs/src/fragments/commands/issue.md: Line 220: sentry issue resolve CLI-G5 --in @commit:getsentry/cli@abc123def /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/issue.md: Line 288: sentry issue resolve CLI-G5 --in ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/binary.ts</path>
<type>file</type>
<content>
228: /**
229: * Build the download URL for a platform-specific binary from GitHub releases.
230: *
231: * @param version - Version to download (without 'v' prefix)
232: * @returns Download URL for the binary
233: */
234: export function getBinaryDownloadUrl(
235: version: string,
236: source: UpgradeSource = PRIMARY_UPGRADE_SOURCE
237: ): string {
238: const tag = `${source.tagPrefix}${version}`;
239: return `https://github.com/${source.githubRepo}/releases/download/${tag}/${getPlatformBinaryName()}`;
240: }
241:
242: /** Build the GitHub API base URL for a release source. */
243: export function getGitHubReleasesUrl(
244: source: UpgradeSource = PRIMARY_UPGRADE_SOURCE
245: ): string {
246: return `https://api.github.com/repos/${source.githubRepo}/releases`;
247: }
248:
249: /** Build the ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/binary.ts</path>
<type>file</type>
<content>
295: /**
296: * Select the first available upgrade source.
297: *
298: * The caller receives the successful probe response so it never repeats the
299: * request. Only HTTP 404 advances to the next source. Every other HTTP or
300: * network failure aborts immediately.
301: */
302: export async function resolveUpgradeSource(
303: options: ResolveUpgradeSourceOptions
304: ): Promise<ResolvedUpgradeSource> {
305: const fetchFn = options.fetch ?? customFetch;
306: for (const source of UPGRADE_SOURCES) {
307: let response: Response;
308: try {
309: response = await fetchFn(options.getProbeUrl(source), {
310: headers: getGitHubHeaders(),
311: signal: options.signal,
312: });
313: } catch (error) {
314: if (error instanceof Error && error.name === "AbortError") ...
M packages/cli/src/lib/binary.ts M packages/cli/src/lib/ghcr.ts M packages/cli/test/lib/binary.test.ts M packages/cli/test/lib/ghcr.test.ts M packages/cli/test/lib/install-script.test.ts packages/cli/src/lib/binary.ts | 139 +++++++++++++++++++++++++-- packages/cli/src/lib/ghcr.ts | 52 ++++++---- packages/cli/test/lib/binary.test.ts | 129 ++++++++++++++++++++++++- packages/cli/test/lib/ghcr.test.ts | 30 ++++++ packages/cli/test/lib/install-script.test.ts | 10 ++ 5 files changed, 335 insertions(+), 25 deletions(-) diff --git a/packages/cli/src/lib/binary.ts b/packages/cli/src/lib/binary.ts index 75582612a..bebf1da0c 100644 --- a/packages/cli/src/lib/binary.ts +++ b/packages/cli/src/lib/binary.ts @@ -102,6 +102,33 @@ export type InstallationMethod = | "yarn" | "unknown"; +/** A repository pair that hosts CLI stable releases and nightly OCI images. ...
<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 17 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/binary.test.ts:
Line 28: getGitHubReleaseByTagUrl,
Line 35: resolveUpgradeSource,
Line 84: describe("resolveUpgradeSource", () => {
Line 88: const resolved = await resolveUpgradeSource({
Line 89: getProbeUrl: (source) => getGitHubReleaseByTagUrl("0.45.0", source),
Line 110: const resolved = await resolveUpgradeSource({
Line 111: getProbeUrl: (source) => getGitHubReleaseByTagUrl("0.45.0", source),
Line 136: resolveUpgradeSource({
Line 137: getProbeUrl: (source) => getGitHubReleaseByTagUrl("0.45.0", source),
Line 155: resolveUpgradeSource({
Line 156: getProbeUrl: (source) => getGitHubReleaseByTagUrl("0.45.0", source),
Line 173: resolveUpgradeSource({
Line 174: getProbeUrl: (source) => getGitHubReleaseByTagUrl("0.45.0", ...
Found 28 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"; /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/upgrade.test.ts: Line 980: "https://github.com/getsentry/cli/releases/download/" /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/commands/issue/resolve-commit-spec.test.ts: Line 21: url: "https://github.com/getsentry/cli", /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/release-notes.test.ts: Line 30: - Add pagination and glob filtering to dashboard list by @BYK in [#560](https://github.com/getsentry/cli/pull/560) Line 31: - Add a ...
Found 28 matches /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/version-check.ts: Line 237: await prefetchNightlyPatches(latestVersion, signal); Line 239: await prefetchStablePatches(latestVersion, signal); /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/upgrade.ts: Line 991: return await attemptDeltaUpgrade( /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/release-notes.ts: Line 554: * Uses a higher `per_page` than `fetchRecentReleases()` in delta-upgrade /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/delta-upgrade.test.ts: Line 834: const result = await fetchRecentReleases(); Line 842: const result = await fetchRecentReleases(); ...
No files found
No files found
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/node_modules/binpatch</path> <type>directory</type> <entries> dist/ LICENSE package.json README.md (4 entries) </entries>
No files found
<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>
Ripgrep JSON record exceeded 65536 bytes
<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> 1: /** 2: * Streaming TRDIFF10 Binary Patch Application 3: * 4: * Implements the bspatch algorithm for applying binary delta patches in the 5: * TRDIFF10 format (produced by zig-bsdiff with `--use-zstd`). Designed for 6: * minimal memory usage during CLI self-upgrades: 7: * 8: * - Old binary: read windows on demand via positional `read()` (`pread`) 9: * through a single-block read-ahead cache, so the base never sits fully in 10: * the JS heap — only the windows actually referenced are pulled in, served 11: * from the OS page cache populated by the reflink copy. 12: * - Diff/extra blocks: streamed via `node:zlib` `createZstdDecompress()` 13: * - Output: written incrementally to disk via `fs.openSync` + `fs.writeSync` 14: * with the fd `closeSync`'d before the function ...
diff --git a/packages/cli/test/lib/binary.test.ts b/packages/cli/test/lib/binary.test.ts
index 6fcfb3b1a..aba47466e 100644
--- a/packages/cli/test/lib/binary.test.ts
+++ b/packages/cli/test/lib/binary.test.ts
@@ -25,14 +25,17 @@ import {
getBinaryDownloadUrl,
getBinaryFilename,
getBinaryPaths,
+ getGitHubReleaseByTagUrl,
getLegacyInstallDirs,
getPlatformBinaryName,
installBinary,
isDowngrade,
isMusl,
releaseLock,
+ resolveUpgradeSource,
replaceBinarySync,
samePath,
+ UPGRADE_SOURCES,
} from "../../src/lib/binary.js";
import { UpgradeError } from "../../src/lib/errors.js";
@@ -40,9 +43,9 @@ describe("getBinaryDownloadUrl", () => {
test("builds correct URL for current platform", () => {
const url = getBinaryDownloadUrl("1.0.0");
- expect(url).toContain("/1.0.0/");
+ expect(url).toContain("/cli@1.0.0/");
expect(url).toStartWith(
- "https://github.com/getsentry/cli/releases/download/"
+ ...
Found 1 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.
No files found
No files found
Found 16 matches /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/version-check.ts: Line 286: ? await fetchLatestNightlyVersion(signal) Line 287: : await fetchLatestFromGitHub(signal); /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/upgrade.ts: Line 399: export async function fetchLatestFromGitHub( Line 467: export async function fetchLatestNightlyVersion( Line 498: export function fetchLatestVersion( Line 503: return fetchLatestNightlyVersion(); Line 506: ? fetchLatestFromGitHub() Line 551: export async function versionExists( Line 902: export async function downloadBinaryToTemp( Line 1122: export async function executeUpgrade( Line 1131: return downloadBinaryToTemp(version, downloadTag, offline, ...
Found 15 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/upgrade.ts:
Line 29: GITHUB_RELEASES_URL,
Line 403: `${GITHUB_RELEASES_URL}/latest`,
Line 562: `${GITHUB_RELEASES_URL}/tags/${version}`,
Line 766: const url = getBinaryDownloadUrl(version);
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/binary.ts:
Line 234: export function getBinaryDownloadUrl(
Line 243: export function getGitHubReleasesUrl(
Line 255: return `${getGitHubReleasesUrl(source)}/tags/${encodeURIComponent(tag)}`;
Line 263: ? `${getGitHubReleasesUrl(source)}?per_page=100`
Line 264: : `${getGitHubReleasesUrl(source)}/latest`;
Line 275: export const GITHUB_RELEASES_URL = ...
Found 2 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/errors.ts:
Line 586: export type UpgradeErrorReason =
Line 600: export class UpgradeError extends CliError {
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/errors.ts</path>
<type>file</type>
<content>
570: *
571: * @param code - OAuth error code (e.g., "authorization_pending", "slow_down")
572: * @param description - Human-readable error description
573: */
574: export class DeviceFlowError extends CliError {
575: readonly code: string;
576:
577: constructor(code: string, description?: string) {
578: super(description ?? code, EXIT.DEVICE_FLOW);
579: this.name = "DeviceFlowError";
580: this.code = code;
581: }
582: }
583:
584: // Upgrade Errors
585:
586: export type UpgradeErrorReason =
587: | "unknown_method"
588: | "unsupported_operation"
589: | "network_error"
590: | "execution_failed"
591: | "version_not_found"
592: | "offline_cache_miss";
593:
594: /**
595: * Upgrade-related errors. ...
1225:function githubReleaseSource(config) {
1227: const { releasesUrl, binaryName, userAgent } = config;
1235: () => doFetch(`${releasesUrl}?per_page=${perPage}`, {
1318:tractStableChain, 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>
1220: steps.push({ fromVersion: prevVersion, toVersion: release.tag_name });
1221: prevVersion = release.tag_name;
1222: }
1223: return { patchUrls, expectedSha256, steps };
1224: }
1225: function githubReleaseSource(config) {
1226: const doFetch = config.fetch ?? fetch;
1227: const { releasesUrl, binaryName, userAgent } = config;
1228: const i = (name, fn) => config.instrument ? config.instrument(name, fn) : fn();
1229: async function fetchRecentReleases(signal) {
1230: const perPage = MAX_STABLE_CHAIN_DEPTH + 2;
1231: let response;
1232: try {
1233: response = await i(
1234: "fetch-releases",
1235: () => doFetch(`${releasesUrl}?per_page=${perPage}`, {
1236: headers: {
1237: Accept: ...
Found 14 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/commands/cli/upgrade.ts:
Line 45: fetchChangelog,
Line 50: executeUpgrade,
Line 51: fetchLatestVersion,
Line 58: versionExists,
Line 113: function resolveChannelAndVersion(positional: string | undefined): {
Line 136: * fallback when `fetchLatestVersion()` hits a network error.
Line 289: const latest = await fetchLatestVersion(method, channel);
Line 325: const exists = await versionExists(lookupMethod, target);
Line 637: const downloadTag =
Line 642: executeUpgrade(method, target, downloadTag, offline, setMessage)
Line 723: const downloadTag = versionArg ? undefined : NIGHTLY_TAG;
Line 727: executeUpgrade("curl", target, downloadTag, undefined, setMessage)
Line 794: const { channel, versionArg } = resolveChannelAndVersion(version);
Line 834: return fetchChangelog({
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/commands/cli/upgrade.ts</path>
<type>file</type>
<content>
100: readonly method?: InstallationMethod;
101: /** Injected by buildCommand output wrapper — suppresses spinners */
102: readonly json?: boolean;
103: };
104:
105: /**
106: * Resolve effective channel and version arg from the positional `version`
107: * parameter. "nightly" and "stable" are treated as channel selectors, not
108: * literal version strings.
109: *
110: * @returns `{ channel, versionArg }` where versionArg is undefined when the
111: * positional was a channel name (so we resolve to latest) or was omitted. ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/commands/cli/upgrade.ts</path>
<type>file</type>
<content>
600: return xdgInstallDir;
601: }
602: return currentInstallDir;
603: }
604:
605: /**
606: * Execute the standard upgrade path: download via curl or package manager,
607: * then run setup on the new binary.
608: */
609: async function executeStandardUpgrade(opts: {
610: method: InstallationMethod;
611: channel: ReleaseChannel;
612: versionArg: string | undefined;
613: target: string;
614: execPath: string;
615: entryPath?: string;
616: pathEnv?: string;
617: offline?: OfflineMode;
618: json?: boolean;
619: noAgentSkills: boolean;
620: }): Promise<void> {
621: const {
622: method,
623: channel,
624: versionArg,
625: target,
626: execPath,
627: entryPath,
628: pathEnv,
629: offline,
630: json,
631: noAgentSkills,
632: } = ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/commands/cli/upgrade.ts</path>
<type>file</type>
<content>
850: channel: ReleaseChannel;
851: flags: UpgradeFlags;
852: offline: OfflineMode;
853: changelogPromise: Promise<ChangelogSummary | undefined>;
854: }): Promise<UpgradeResult> {
855: const result = buildCheckResult(opts);
856: if (opts.offline) {
857: result.offline = true;
858: }
859: result.changelog = await opts.changelogPromise;
860: return result;
861: }
862:
863: export const upgradeCommand = buildCommand({
864: auth: false,
865: docs: {
866: brief: "Update the Sentry CLI to the latest version",
867: fullDescription:
868: "Check for updates and upgrade the Sentry CLI to the latest or a specific version.\n\n" +
869: "By default, detects how the CLI was installed (npm, curl, etc.) and uses the same method to upgrade.\n\n" +
870: "Two release ...
6e3e7e13a feat(config): follow XDG Base Directory spec for config location (#1503) b0b22fe82 feat(errors): wire up no-silent-catch lint rule, drop ratchet baseline (#1532) d9af07158 fix(version-check): log errors in maybePrefetchPatches catch blocks (#1512) 1837850d6 feat(upgrade): add --no-agent-skills flag (#1407) 5a584348b fix(auth): request team admin OAuth scope (#1373) 2c54e1a1f ref(cli): replace argv-hoist preprocessor with a Stricli top-level-flags patch (#1340) 7b429edd1 fix(upgrade): use generated-patch from-version + close output fd synchronously (#1327) 96390e5f6 chore: pre-shape repo into pnpm-workspace monorepo layout (#1254)
<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>
720: *
721: * When `version` is provided, fetches the pinned versioned tag
722: * (`nightly-{version}`). Otherwise fetches the rolling `:nightly` tag.
723: *
724: * @param destPath - File path to write the decompressed binary
725: * @param version - Specific nightly version to download (omit for latest)
726: * @throws {UpgradeError} When GHCR fetch or blob download fails
727: */
728: async function downloadNightlyToPath(
729: destPath: string,
730: version?: string,
731: setMessage?: SetMessage
732: ): Promise<void> {
733: const token = await getAnonymousToken();
734: const manifest = version
735: ? ...
<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 { CLI_VERSION } from "./constants.js";
14: import { getReleaseChannel } from "./db/release-channel.js";
15: import {
16: getVersionCheckInfo,
17: markUpdateNotified,
18: setVersionCheckInfo,
19: } from ...
<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/release-notes.ts</path>
<type>file</type>
<content>
500:
501: for (const { commit } of commits) {
502: const message = commit.message;
503:
504: if (message.includes("#skip-changelog")) {
505: continue;
506: }
507:
508: const firstLine = message.split("\n")[0]?.trim();
509: if (!firstLine) {
510: continue;
511: }
512:
513: const ccMatch = CONVENTIONAL_COMMIT_RE.exec(firstLine);
514: if (!(ccMatch?.[1] && ccMatch[2])) {
515: continue;
516: }
517:
518: const category = COMMIT_PREFIX_TO_CATEGORY.get(ccMatch[1]);
519: if (!category) {
520: continue;
521: }
522:
523: const description = ccMatch[2].trim();
524: const existing = items.get(category) ?? [];
525: existing.push(description);
526: items.set(category, existing);
527: }
528:
529: const sections: ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/release-notes.ts</path>
<type>file</type>
<content>
655: // GitHub's `since` is inclusive — offset by +1s to exclude the current
656: // version's commit (the user already has it).
657: // GitHub's `until` is exclusive — offset by +1s to include the target
658: // version's commit (the commit the user is upgrading to).
659: const sinceDate = new Date((fromTs + 1) * 1000).toISOString();
660: const untilDate = new Date((toTs + 1) * 1000).toISOString();
661:
662: const url = `https://api.github.com/repos/getsentry/cli/commits?sha=main&since=${sinceDate}&until=${untilDate}&per_page=100`;
663:
664: let response: Response;
665: try {
666: response = await customFetch(url, { headers: getGitHubHeaders() });
667: } catch {
668: log.debug("Failed to fetch nightly commits");
669: return null;
670: }
671:
672: if (!response.ok) ...
<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. ...
Found 2 matches /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/release-notes.ts: Line 47: const VERSION_PREFIX_RE = /^v/; Line 436: const version = r.tag_name.replace(VERSION_PREFIX_RE, "");
* 🔴 (09:54) `packages/cli/src/lib/delta-upgrade.ts` is a 627-line delta-upgrade implementation backed by `binpatch`; it preserves the existing public API through re-exports of `ExtractStableChainOpts`, `GitHubAsset`, `GitHubRelease`, `PatchChain`, `StableChainInfo`, `extractSha256`, `getPatchFromVersion`, `getPatchTargetSha256`, `getStableTargetSha256`, and `PATCH_TAG_PREFIX`. * 🔴 (09:54) `Delt…
* 🔴 (09:53) Repository history listed 8 commits in order: 1. `6e3e7e13a feat(config): follow XDG Base Directory spec for config location (#1503)`; 2. `b0b22fe82 feat(errors): wire up no-silent-catch lint rule, drop ratchet baseline (#1532)`; 3. `d9af07158 fix(version-check): log errors in maybePrefetchPatches catch blocks (#1512)`; 4. `1837850d6 feat(upgrade): add --no-agent-skills flag (#1407)`…
* 🔴 (09:52) `packages/cli/src/lib/errors.ts` defines `UpgradeErrorReason` as exactly `"unknown_method" | "unsupported_operation" | "network_error" | "execution_failed" | "version_not_found" | "offline_cache_miss"`; `UpgradeError` uses `EXIT.UPGRADE`, sets `this.name = "UpgradeError"`, and stores the typed `reason`. * 🔴 (09:52) `UpgradeError` default messages are: `unknown_method` → `"Could not …
* 🔴 (09:44) A search found exactly 28 references to delta-upgrade entry points: production calls are in `packages/cli/src/lib/version-check.ts` (`prefetchNightlyPatches()` line 237 and `prefetchStablePatches()` line 239), `packages/cli/src/lib/upgrade.ts` (`attemptDeltaUpgrade()` line 991), and `packages/cli/src/lib/release-notes.ts` (line 554); implementations are in `packages/cli/src/lib/delta…
* 🔴 (09:38) `packages/cli/test/lib/release-notes.test.ts` is 295 lines and imports `marked`, Vitest’s `describe`/`expect`/`test`, `GitHubRelease`, and `buildChangelogSummary`, `ChangeCategory`, `countListItems`, `extractNightlyTimestamp`, `extractSections`, and `parseCommitMessages`. * 🔴 (09:38) `SAMPLE_RELEASE_BODY` models a simplified `0.21.0` release with New Features, Bug Fixes, Documentati…
Date: Sep 9, 2026 * 🔴 (09:37) User chose `"0.0.0-alpha"` as a clearly older cached version for the `getUpdateNotification()` test, replacing the ambiguous `"0.0.0"` comparison against test `CLI_VERSION` `"0.0.0-dev"`; expected result is `null`. * 🔴 (09:37) User identified the no-`lastChecked` state as `"never checked before"`; in `packages/cli/test/lib/version-check.test.ts`, this state must ca…
Date: Sep 9, 2026 * 🔴 (09:36) The full-upgrade tests in `packages/cli/test/commands/cli/upgrade.test.ts` use `fakeChildProcess(exitCode)`, which creates a `node:events` `EventEmitter` and emits `"close"` with the specified exit code on the next microtask. * 🔴 (09:36) The `sentry cli upgrade — curl full upgrade path (child_process.spawn spy)` suite redirects curl installation to `join(TEST_TMP_D…
* 🔴 (09:35) `/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/upgrade.test.ts` is 2,153 lines; the displayed section covered lines 1–730. * 🔴 (09:35) `packages/cli/test/lib/upgrade.test.ts` mocks `node:child_process` with a hoisted, swappable `spawnImpl.fn`; `fakeProcess(exitCode, stdoutData)` emits stdout chunks and …
* 🔴 (09:33) `packages/cli/src/lib/ghcr.ts` is a GHCR OCI client for nightly CLI binaries. Nightly artifacts are public, use anonymous token exchange, and store the nightly version in the manifest-level `annotations.version`; latest-version discovery requires 2 HTTP requests: token exchange and manifest fetch. * 🔴 (09:33) `packages/cli/src/lib/ghcr.ts` documents a GHCR redirect quirk: blob reque…
* 🔴 (09:31) `packages/cli/src/lib/release-notes.ts` implements stable and nightly release-note parsing and aggregation. It keeps only 3 categories in display order: 1. `"features"` / `### New Features` / `feat:`, 2. `"fixes"` / `### Bug Fixes` / `fix:`, 3. `"performance"` / `### Performance` / `perf:`. * 🔴 (09:31) `ChangeSection` contains `category: ChangeCategory` and raw `markdown: string`. `…
Date: Sep 9, 2026 * 🔴 (09:31) `packages/cli/src/commands/cli/upgrade.ts` implements `sentry cli upgrade`: self-updates to the latest or a specific version, then spawns the new binary with `cli setup` to refresh completions and agent skills and record installation metadata. * 🔴 (09:31) Upgrade supports persisted `"stable"` and `"nightly"` release channels. Stable is the default and tracks the la…
Date: Sep 9, 2026 * 🔴 (09:31) `packages/cli/src/lib/upgrade.ts` defines upgrade detection and self-upgrade behavior; shared binary-management helpers—including download URLs, locking, replacement, install-directory detection, and platform binary naming—come from `./binary.js`. * 🔴 (09:31) `packages/cli/src/lib/upgrade.ts` re-exports `InstallationMethod` and `parseInstallationMethod` from `./bin…
Date: Sep 9, 2026 * 🔴 (09:31) `packages/cli/package.json` defines package `sentry` version `0.45.0-dev.0`, described as “Sentry CLI - A command-line interface for using Sentry built by robots and humans for robots and humans”; repository is `git+https://github.com/getsentry/cli.git`, license is `FSL-1.1-Apache-2.0`, and module type is `module`. * 🔴 (09:31) `packages/cli/package.json` entry poin…
Date: Sep 9, 2026 * 🔴 (09:30) Repository guidance in `AGENTS.md` states to always load the `repo-setup` skill before situation skills; skills under `.agents/skills/` are generated from the canonical `skills/` tree by `scripts/sync-skills.mjs`. * 🔴 (09:30) Repository agent pipeline is `triage → explore → plan → implement → review → ship`; `worker` is a deprecated alias of `implement`. Direct `Ne…
Date: Sep 9, 2026 * 🔴 [requested-review] (09:30) User requested read-only analysis in `/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade`; explicitly instructed not to edit files or run broad tests. * 🟡 (09:30) User asked to analyze `packages/cli/src/lib/upgrade.ts`, `src/commands/cli/upgrade.ts`, `src/lib/version-check.ts`, `src/lib/releas…