Dashboard › cli › Distillation
2ac54315-39f3-4d51-8fab-617c0c6d78df["lore_tm_v1_CFHOTpS6H6BrpXNzlxQaeZjbKsVvKzBE89nHJSr9w3Q","lore_tm_v1_oLEMDDelB5tpNxeFxAIGnuIprxhX-SOIKzUsMJeio0w","lore_tm_v1_FvaIzkj2BXLNEkTQnL_yQrHjGngD52-27R5rfq2IWuE","lore_tm_v1__AMiRHT8WkvrR5fws3Ha4_36HwuduRlsMM7vNuCFMBs","lore_tm_v1_TGgeFHYry_shR8MZcbuZwuFtn1tDyn_DWuBPfcQKoYE","lore_tm_v1_OaIeffc14RoJ0JgnkBwq1w9XPRdZ1PxcgRZP4P9zx7c","lore_tm_v1_t_Pyb4gYQAQcPLETb9a0PSNoXvwkkpcw-cZuDyywIeY","lore_tm_v1_ltoiKS4yrS2H7ZcNS5RO3Gji5ibRxN7U55Lf1k16mmw","lore_tm_v1_GRBwh_EPvY-bFJCUNTa6kRZIXwgNB-U47lOTAHTB2KM","lore_tm_v1_uF9xO3UdMhI9n4fsdldv-ESuQvehCuAo0uuvZYrtm5U","lore_tm_v1_lz7J2HpeR9Ab1fff54segAnai0xs8OFXbAznfMaA5n0","lore_tm_v1_3fNEgY9ku89pFqm75XEEi-12RYxxm-gTLHhRnBCLtKI","lore_tm_v1_cRGFJCi5FXmEg-_6g3qWo5IRoFYX0TPmqhC8BmSFVKo","lore_tm_v1_-2o9SIm8wScqm0R6LLFFGITk2ZsE_dYdKJ1Veex0xzk","lore_tm_v1_42lcQCiSHZlmoo9q5iK0bgXU2NvZjmE3aUGqrU6wxGY"]
v4.1.10 reported that test.poolOptions was removed in Vitest 4 and all former poolOptions are now top-level options; migration guide: https://vitest.dev/guide/migration#pool-rework.packages/cli had exactly 110 tests: 106 passed and 4 failed across 3 failed test files; duration was 899ms, with transform 1.17s, setup 236ms, import 1.42s, tests 275ms, and environment 0ms.test/lib/binary.test.ts:45 failed getBinaryDownloadUrl > builds correct URL for current platform: getBinaryDownloadUrl("1.0.0") returned https://github.com/getsentry/toolkit/releases/download/cli@1.0.0/sentry-linux-x64, while the existing test expected the URL to contain /1.0.0/ and start with https://github.com/getsentry/cli/releases/download/.test/lib/ghcr.test.ts:105 failed getAnonymousToken > uses the selected source's GHCR repository: getAnonymousToken(UPGRADE_SOURCES[0]) was expected to resolve to "toolkit-token" but treated the source object as a signal, causing The "signals[1]" argument must be an instance of AbortSignal. Received an instance of Object; fetchWithRetry() wrapped this as UpgradeError reason network_error, exit code 50.test/lib/ghcr.test.ts:183 failed fetchNightlyManifest > uses the selected source's GHCR repository: fetchNightlyManifest("token", undefined, UPGRADE_SOURCES[0]) still requested a manifest under /v2/getsentry/cli/ instead of expected /v2/getsentry/toolkit/manifests/nightly; the resulting UpgradeError had reason network_error and exit code 50.test/lib/install-script.test.ts:115 failed install script > embeds the shared ordered upgrade source list: regex /^UPGRADE_SOURCES=\(([^)]*)\)$/m found no assignment, yielding undefined instead of the expected ordered repositories ["getsentry/toolkit", "getsentry/cli"]..craft.yml uses minVersion: '2.21.1', automatic changelog and versioning policies, preReleaseCommand: bash -c 'cd packages/cli && node --experimental-strip-types script/bump-version.ts --pre', and the corresponding --post command as postReleaseCommand..craft.yml configures GitHub artifact provider Build artifacts as /^sentry-.*$/, npm-package, and vercel; targets are ordered npm, github, vercel, registry, and brew. The Vercel project ID is prj_wVkOnIwI3eIQbGD1Gw7qS1MqFFIK..craft.yml registry app 'app:sentry' is named 'Sentry CLI', with package URL https://www.npmjs.com/package/sentry, docs URL https://cli.sentry.dev, release URL template https://github.com/getsentry/cli/releases/download/{{version}}/{{file}}, include pattern /^sentry-.*\.gz$/, and hexadecimal SHA-256 checksums..craft.yml Homebrew target uses tap getsentry/tools, formula sentry, path Formula, and include pattern /^sentry-(darwin|linux)-(arm64|x64)\.gz$/; its template downloads four .gz assets from getsentry/cli, installs the first sentry-* file as sentry, runs sentry cli setup --method brew --no-modify-path in post_install, and checks sentry --version in its test.packages/cli/src/commands/cli/upgrade.ts defines isEnoentSpawnError(error): it recognizes either code === "ENOENT" or Bunβs message substring Executable not found in $PATH.spawnWithRetry(binaryPath, args, env) in packages/cli/src/commands/cli/upgrade.ts retries EBUSY through SPAWN_MAX_ATTEMPTS with delay attempt * SPAWN_RETRY_BASE_MS; the warning is Binary is locked (antivirus scan?), retrying in ${delay}ms... (attempt ${attempt}/${SPAWN_MAX_ATTEMPTS}). Non-EBUSY errors are thrown immediately.spawnWithRetry() maps a spawned processβs SIGKILL to UpgradeError("execution_failed", "Downloaded binary was killed by the operating system (SIGKILL). This usually means the binary has an invalid code signature. Try reinstalling: curl -sL https://sentry.io/get-cli/ | bash"); a missing binary maps to an actionable execution_failed error naming binaryPath and instructing the user to rerun sentry cli upgrade.SetupOptions fields are binaryPath, method, channel, install, optional installDir, ensureAuthScopes, and noAgentSkills. runSetupOnNewBinary() always passes cli setup --quiet --method <method> --channel <channel> --no-modify-path, conditionally adds --install, --ensure-auth-scopes, and --no-agent-skills, and sets SENTRY_INSTALL_DIR when installDir is supplied.runSetupOnNewBinary() calls spawnWithRetry() and throws UpgradeError("execution_failed", "Setup failed with exit code ${exitCode}") for a nonzero exit code.resolveUpdatedCliPath(execPath, entryPath, pathEnv) resolves in order: whichSync("sentry", { PATH: pathEnv }), then entryPath, then execPath.resolveUpgradeInstallDir(currentInstallDir, pathEnv) keeps nonlegacy curl installs in place. For legacy join(homedir(), LEGACY_INSTALL_SUBDIR), it removes the SENTRY_INSTALL_DIR pin, obtains the XDG target via determineInstallDir(homedir(), envWithoutPin), and relocates only if the target differs from the legacy directory and isInPath(xdgInstallDir, pathEnv) is true.executeStandardUpgrade() uses rolling NIGHTLY_TAG only for latest-nightly requests with no versionArg; a specifically requested nightly version uses its own release tag. It invokes executeUpgrade(method, target, downloadTag, offline, setMessage) inside withProgress(), and logs Applied delta patch (${formatBytes(downloadResult.patchBytes)} downloaded) when applicable.executeStandardUpgrade() derives the current directory from getCurlInstallPaths().installPath, resolves it through resolveUpgradeInstallDir(), runs setup on downloadResult.tempBinaryPath with install: true, ensureAuthScopes: !json, and the chosen noAgentSkills, then releases downloadResult.lockPath in finally. Package-manager upgrades instead resolve the newly installed sentry path and run setup with install: false.migrateToStandaloneForNightly() implements package-manager/Homebrew-to-nightly migration in this order: 1. download the nightly standalone binary to a temporary path, 2. install it using determineInstallDir(), 3. run setup to update completions, PATH, and metadata, 4. return warnings that the old package-manager installation may still shadow it.migrateToStandaloneForNightly() logs Nightly builds are only available as standalone binaries. and Migrating to standalone installation...; latest nightly uses NIGHTLY_TAG, while a pinned version uses its specific tag. A missing download result throws UpgradeError("execution_failed", "Failed to download nightly binary").npm β npm uninstall -g sentry, pnpm β pnpm remove -g sentry, bun β bun remove -g sentry, yarn β yarn global remove sentry, and brew β brew uninstall getsentry/tools/sentry. Returned warnings first say Your ${method}-installed sentry may still appear earlier in PATH., followed by Consider removing it: ${hint} when a hint exists.resolveContext(version, flags) calls resolveChannelAndVersion(version), compares the resolved channel with getReleaseChannel(), resolves the method from flags.method ?? (await detectInstallationMethod()), calls validateMethod(method, versionArg, channel, flags.offline), and returns { channel, versionArg, channelChanged, method }.persistChannel() must run after offline target resolution because setReleaseChannel() clears the version-check cache on channel changes, which would otherwise prevent resolveOfflineTarget() from reading the cached version.packages/cli/test/lib/delta-upgrade.test.tsβs fetchRecentReleases tests currently expect the API URL to contain api.github.com/repos/getsentry/cli/releases and per_page=, return releases in API order, and return [] on HTTP 500 or TypeError("fetch failed").downloadStablePatch tests expect a successful https://example.com/patch.bin response containing Uint8Array([1, 2, 3, 4, 5]) to return the same bytes, while HTTP 404 and network failure return null.resolveStableChain tests cover: a single hop 0.13.0 β 0.14.0; a parallel two-hop chain applied oldest-first as 0.13.0 β 0.14.0 β 0.15.0; target absent from releases; releases API failure; patch-download failure; and a 15-release/14-hop chain exceeding MAX_STABLE_CHAIN_DEPTH (10).package.json exposes check scripts check:fragments, check:deps, check:errors, check:patches, check:docs-sections, and check:stale-refs; .github/workflows/ci.yml invokes pnpm run check:fragments, pnpm run check:deps, pnpm run check:patches, and pnpm run check:stale-refs.packages/cli/package.json maps checks to pnpm tsx script/check-fragments.ts, script/check-no-deps.ts, script/check-patches.ts, script/check-env-coverage.ts, and script/check-stale-references.ts.package.json identifies the private ESM workspace as toolkit-cli-workspace version 0.0.0, requires Node >=20.0, and pins package manager pnpm@10.11.0.package.json delegates scripts through pnpm --filter sentry run: tsx, cli, dev, build, build:all, bundle, typecheck, lint, lint:fix, test, test:unit, test:changed, test:e2e, test:init-eval, generate:parser, generate:sdk, generate:skill, generate:banner, generate:docs, generate:docs-sections, generate:schema, generate:command-docs, eval:skill, bench, bench:save, bench:compare, bench:sweep, check:fragments, check:deps, check:errors, check:patches, check:docs-sections, and check:stale-refs.package.json patched dependencies are @stricli/core@1.2.8, @sentry/core@10.63.0, and @sentry/node-core@10.63.0, with patch files under packages/cli/patches/; onlyBuiltDependencies contains only esbuild.package.json overrides are esbuild@>=0.17.0 <0.28.1 β 0.28.1, js-yaml@<3.15.1 β 3.15.1, js-yaml@>=4.0.0 <4.3.1 β 4.3.1, shell-quote@<1.9.0 β 1.9.0, qs@>=6.11.1 <=6.15.1 β 6.15.2, form-data@<4.0.6 β 4.0.6, vite@>=8.0.0 <8.0.16 β 8.0.16, @hono/node-server@<2.0.5 β 2.0.12, fast-uri@<=3.1.3 β 3.1.5, brace-expansion@<5.0.8 β 5.0.9, undici@>=7.0.0 <7.29.0 β 7.29.0, nanoid@<3.3.18 β 3.3.18, and ip-address@<10.3.1 β 10.4.0.apps/cli-docs/public contains exactly 10 entries: .well-known/, CNAME, favicon.png, favicon.svg, glyph.svg, install, og-image-twitter.png, og-image.png, wordmark-light.svg, and wordmark.svg.apps/cli-docs/public/install is a symbolic link to ../../../packages/cli/install.main returned HTTP 404 with No commit found for the ref main.master, not main..github, .github/workflows, .github/workflows/build.yml, .github/workflows/changelog-preview.yml, .github/workflows/docs-preview.yml, .github/workflows/enforce-license-compliance.yml, .github/workflows/image.yml, .github/workflows/lint.yml, .github/workflows/release.yml, docs/astro.config.mjs, docs/src/content.config.ts, docs/src/content/docs/configuration.md, docs/src/content/docs/github-actions.md, docs/src/content/docs/targets/github.md, docs/tsconfig.json, eslint.config.mjs, src/__tests__/config.test.ts, src/artifact_providers/__tests__/github.test.ts, src/artifact_providers/github.ts, src/commands/config.ts, src/commands/workspace.ts, src/commands/workspace_cmds, src/commands/workspace_cmds/__tests__, src/commands/workspace_cmds/__tests__/list.test.ts, src/commands/workspace_cmds/list.ts, src/config.ts, src/schemas, src/schemas/project_config.ts, src/status_providers/__tests__/github.test.ts, src/status_providers/github.ts, src/targets/__tests__/github.test.ts, src/targets/github.ts, src/utils/__fixtures__/workspaces, src/utils/__fixtures__/workspaces/no-workspace, src/utils/__fixtures__/workspaces/no-workspace/package.json, src/utils/__fixtures__/workspaces/npm-workspace, src/utils/__fixtures__/workspaces/npm-workspace/package.json, src/utils/__fixtures__/workspaces/npm-workspace/packages, src/utils/__fixtures__/workspaces/npm-workspace/packages/pkg-a, src/utils/__fixtures__/workspaces/npm-workspace/packages/pkg-a/package.json, src/utils/__fixtures__/workspaces/npm-workspace/packages/pkg-b, src/utils/__fixtures__/workspaces/npm-workspace/packages/pkg-b/package.json, src/utils/__fixtures__/workspaces/pnpm-workspace, src/utils/__fixtures__/workspaces/pnpm-workspace/package.json, src/utils/__fixtures__/workspaces/pnpm-workspace/packages, src/utils/__fixtures__/workspaces/pnpm-workspace/packages/pkg-a, src/utils/__fixtures__/workspaces/pnpm-workspace/packages/pkg-a/package.json, src/utils/__fixtures__/workspaces/pnpm-workspace/packages/pkg-b, src/utils/__fixtures__/workspaces/pnpm-workspace/packages/pkg-b/package.json, src/utils/__fixtures__/workspaces/pnpm-workspace/pnpm-workspace.yaml, src/utils/__tests__/githubApi.test.ts, src/utils/__tests__/workspaces.test.ts, src/utils/githubApi.ts, src/utils/workspaces.ts, tsconfig.build.json, tsconfig.json, and vitest.config.mts.releaseUnitFields shared by the top-level implicit/default release unit and explicit entries under top-level workspaces; workspace fields inherit top-level values and override only declared fields. This independently versioned release-unit concept is distinct from the npm targetβs workspaces: true, which publishes discovered npm packages at one version.WorkspaceSchema spreads releaseUnitFields; its github block is partial so a workspace can override owner and/or repo while inheriting the remaining top-level GitHub configuration.WorkspaceNameSchema rejects "__proto__" because assigning that key to a regular object mutates its prototype, and rejects "." and "..".workspaces: z.record(WorkspaceNameSchema, WorkspaceSchema).optional(). When named workspaces exist, releases must select one using --workspace <name> or CRAFT_WORKSPACE; without workspaces, Craft retains the previous single implicit release-unit behavior.workspaces is nonempty and config.github?.projectPath is also set.