Dashboard › cli › Session 0iDPC6CIqNZE
0iDPC6CIqNZE1vpbSRead-only exploration in /home/byk/Code/getsentry/cli-pr-1558. Do not modify files. Inspect every source command with positional.kind === "array" (all 33 matches under packages/cli/src/commands). Determine the runtime minimum number of positional values from each command's own function, flags, tests, docs, and semantics. Stricli's array minimum is the source of parser cardinality; absent means zero values accepted. Return a concise table with file path, command path, whether zero values are valid, required minimum if any, evidence (exact function check/test/flag-only behavior), and recommendation on whether to add minimum. Pay special attention to issue merge, project create, event send, help, and commands with --web/--into/other flag-only modes. Do not assume prose means parser-level required if the command deliberately emits a semantic ContextError/ValidationError. Flag any place where adding minimum would alter an established error class or valid mode.
/home/byk/Code/getsentry/cli-pr-1558/AGENTS.md /home/byk/Code/getsentry/cli-pr-1558/packages/cli/AGENTS.md
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/CONTRIBUTING.md
/home/byk/Code/getsentry/cli-pr-1558/package.json /home/byk/Code/getsentry/cli-pr-1558/codemods/sentry-v3-to-v4/package.json /home/byk/Code/getsentry/cli-pr-1558/apps/local/package.json /home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/init-eval/templates/sveltekit-app/package.json /home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/init-eval/templates/react-vite-app/package.json /home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/init-eval/templates/nextjs-app/package.json /home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/init-eval/templates/express-app/package.json /home/byk/Code/getsentry/cli-pr-1558/apps/cli-docs/package.json /home/byk/Code/getsentry/cli-pr-1558/packages/cli/package.json
Found 33 matches /home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/help.ts: Line 36: kind: "array", /home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/debug-files/upload.ts: Line 567: kind: "array", /home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/log/view.ts: Line 512: kind: "array", /home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/log/list.ts: Line 730: kind: "array", /home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/trace/view.ts: Line 484: kind: "array", /home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/debug-files/find.ts: Line 131: kind: "array", /home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/trace/logs.ts: Line 130: kind: "array", /home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/event/view.ts: Line 1082: kind: ...
Skill "repo-setup" not found. Available skills: ast-grep, customize-opencode, jj-create-pr, jj-guide, jj-update-pr, jj-workflow
<path>/home/byk/Code/getsentry/cli-pr-1558/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/Code/getsentry/cli-pr-1558/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`. 8: 9: ### Goals 10: 11: - **Zero-config experience** - Auto-detect project context from DSNs in source code and env files 12: - **AI-powered debugging** - Integrate Seer AI for root cause analysis and fix plans 13: - **Developer-friendly** - Follow `gh` CLI conventions for intuitive UX 14: - **Agent-friendly** - JSON output and predictable behavior for AI coding agents 15: - **Fast** - Native binaries via Node SEA (fossilize), SQLite caching for API responses 16: 17: ### Key Features 18: 19: - **DSN Auto-Detection** - ...
<path>/home/byk/Code/getsentry/cli-pr-1558/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)* - Auto-detect from DSN or config 24: 25: **Rationale**: Positional ...
<path>/home/byk/Code/getsentry/cli-pr-1558/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: "dist/index.mjs",
31: "dist/index.d.cts",
32: "dist/index.d.mts",
33: ...
No files found
Found 100 matches (more matches available)
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/trial/start.ts:
Line 23: import { ContextError, ValidationError } from "../../lib/errors.js";
Line 111: async *func(
Line 139: throw new ContextError("Organization", "sentry trial start <name> <org>");
Line 181: async function promptOpenBrowser(url: string): Promise<boolean> {
Line 217: async function* handlePlanTrial(
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/trial/list.ts:
Line 12: import { ContextError } from "../../lib/errors.js";
Line 229: async *func(this: SentryContext, flags: ListFlags, org?: string) {
Line 236: throw new ContextError("Organization", "sentry trial list <org>");
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/trace/view.ts:
Line 25: ContextError,
Line 61: /** Usage hint for ContextError messages */
Line 145: if (args.length === 0) {
Line 155: if (args.length === 1 ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/help.ts</path>
<type>file</type>
<content>
1: /**
2: * Help Command
3: *
4: * Provides help information for the CLI.
5: * - `sentry help` or `sentry` (no args): Shows branded help with banner
6: * - `sentry help <command>`: Shows detailed help for that command
7: * - `sentry help --json`: Emits full command tree as structured JSON
8: * - `sentry help --json <command>`: Emits specific command/group metadata as JSON
9: */
10:
11: import type { SentryContext } from "../context.js";
12: import { buildCommand } from "../lib/command.js";
13: import { OutputError } from "../lib/errors.js";
14: import { CommandOutput } from "../lib/formatters/output.js";
15: import {
16: formatHelpHuman,
17: introspectAllCommands,
18: introspectCommand,
19: } from "../lib/help.js";
20:
21: export const helpCommand = buildCommand({
22: auth: false,
23: docs: {
24: brief: "Display help for a command",
25: ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/debug-files/find.ts</path>
<type>file</type>
<content>
1: /**
2: * sentry debug-files find <id>...
3: *
4: * Locate debug-information files for one or more debug identifiers by searching
5: * well-known locations (Xcode DerivedData), the current directory, and any
6: * extra `--path` directories. Local-only — no API calls.
7: *
8: * Exits non-zero when any requested id could not be located, mirroring the
9: * legacy `sentry-cli difutil find`.
10: */
11:
12: import { stat } from "node:fs/promises";
13: import { homedir } from "node:os";
14: import { join } from "node:path";
15: import type { SentryContext } from "../../context.js";
16: import { buildCommand } from "../../lib/command.js";
17: import {
18: FIND_DIF_TYPES,
19: type FindResult,
20: findDebugFiles,
21: } from "../../lib/dif/find.js";
22: import { ValidationError } from "../../lib/errors.js";
23: import { colorTag, renderMarkdown } from ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/trace/logs.ts</path>
<type>file</type>
<content>
1: /**
2: * sentry trace logs
3: *
4: * View logs associated with a distributed trace.
5: */
6:
7: import type { SentryContext } from "../../context.js";
8: import { type LogSortDirection, listTraceLogs } from "../../lib/api-client.js";
9: import {
10: buildProjectQuery,
11: parseLogSort,
12: validateLimit,
13: } from "../../lib/arg-parsing.js";
14: import { openInBrowser } from "../../lib/browser.js";
15: import { buildCommand } from "../../lib/command.js";
16: import { toSearchQueryError } from "../../lib/errors.js";
17: import { filterFields } from "../../lib/formatters/json.js";
18: import { formatLogTable } from "../../lib/formatters/log.js";
19: import { CommandOutput, formatFooter } from "../../lib/formatters/output.js";
20: import {
21: applyFreshFlag,
22: FRESH_ALIASES,
23: FRESH_FLAG,
24: LIST_MAX_LIMIT,
25: } from ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/event/send.ts</path>
<type>file</type>
<content>
1: /**
2: * `sentry event send` — Send a Sentry event from CLI flags or a JSON file.
3: *
4: * Unlike most commands, this authenticates via a DSN (not a Bearer token),
5: * so no `sentry auth login` is required. The DSN can be provided via:
6: * 1. --dsn flag
7: * 2. SENTRY_DSN environment variable
8: */
9:
10: import type { DsnComponents, Event } from "@sentry/core";
11: import { createEventEnvelope, makeDsn, serializeEnvelope } from "@sentry/core";
12: import type { SentryContext } from "../../context.js";
13: import { buildCommand } from "../../lib/command.js";
14: import {
15: buildEventFromFlags,
16: type SendEventFlags,
17: } from "../../lib/envelope/event-builder.js";
18: import {
19: readFileBytes,
20: requireDsn,
21: sendEnvelopeRequest,
22: } from "../../lib/envelope/transport.js";
23: import { ConfigError, ValidationError } from ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/event/send.ts</path>
<type>file</type>
<content>
251: brief: "Parse 'CATEGORY: message' prefixes from logfile breadcrumbs",
252: default: false,
253: optional: true,
254: },
255: raw: {
256: kind: "boolean",
257: brief: "Send file contents as-is without parsing",
258: default: false,
259: optional: true,
260: },
261: },
262: aliases: {
263: m: "message",
264: a: "message-arg",
265: l: "level",
266: r: "release",
267: d: "dist",
268: E: "env",
269: p: "platform",
270: t: "tag",
271: e: "extra",
272: u: "user",
273: f: "fingerprint",
274: },
275: },
276: async *func(
277: this: SentryContext,
278: flags: SendEventFlags & {
279: dsn?: string;
280: raw?: boolean;
281: json?: boolean;
282: },
283: ...files: string[]
284: ) {
285: ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/docs/query.ts</path>
<type>file</type>
<content>
1: import type { SentryContext } from "../../context.js";
2: import { buildCommand } from "../../lib/command.js";
3: import { detectDocsContext } from "../../lib/docs-context.js";
4: import { queryDocs } from "../../lib/docs-service.js";
5: import { ValidationError } from "../../lib/errors.js";
6: import { CommandOutput } from "../../lib/formatters/output.js";
7: import { withProgress } from "../../lib/polling.js";
8:
9: type QueryFlags = { readonly fields?: string[]; readonly json: boolean };
10: type QueryOutput = {
11: answer: string;
12: detectedContext: Awaited<ReturnType<typeof detectDocsContext>>;
13: sources: string[];
14: };
15:
16: /** Friendly wait messages for a docs-MCP request without measurable stages. ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/docs/list.ts</path>
<type>file</type>
<content>
1: import type { SentryContext } from "../../context.js";
2: import { validateLimit } from "../../lib/arg-parsing.js";
3: import { buildCommand } from "../../lib/command.js";
4: import { type DocsListResponse, listDocs } from "../../lib/docs-service.js";
5: import { ValidationError } from "../../lib/errors.js";
6: import { muted } from "../../lib/formatters/colors.js";
7: import { CommandOutput } from "../../lib/formatters/output.js";
8: import { formatTable } from "../../lib/formatters/table.js";
9:
10: type ListFlags = {
11: readonly fields?: string[];
12: readonly json: boolean;
13: readonly limit: number;
14: };
15:
16: function parseLimit(value: string): number {
17: return validateLimit(value, 1, 20);
18: }
19:
20: function formatListHuman(data: DocsListResponse): string {
21: if (data.results.length === 0) {
22: return muted("No documentation ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/send-envelope.ts</path>
<type>file</type>
<content>
1: /**
2: * `sentry send-envelope` — Deprecated. Suggests `sentry event send --raw`.
3: *
4: * Kept as a hidden backward-compat alias that prints a deprecation notice
5: * and forwards to `sentry event send --raw`.
6: */
7:
8: import type { SentryContext } from "../context.js";
9: import { buildCommand } from "../lib/command.js";
10: import { CliError, EXIT } from "../lib/errors.js";
11:
12: export const sendEnvelopeCommand = buildCommand({
13: docs: {
14: brief: "Send a Sentry envelope file (deprecated)",
15: fullDescription:
16: "This command has been replaced by `sentry event send --raw <file>`.\n\n" +
17: "Use `sentry event send --raw ./captured.envelope` instead.",
18: },
19: auth: false,
20: skipRcUrlCheck: true,
21: output: {
22: human: () => "",
23: },
24: parameters: {
25: positional: {
26: kind: ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/issue/merge.ts</path> <type>file</type> <content> 1: /** 2: * sentry issue merge 3: * 4: * Merge 2+ issues into a single canonical group. Sentry's web UI has this 5: * as a bulk action; here we expose it as a direct command. 6: * 7: * ## Flow 8: * 9: * 1. Collect 2+ issue args (variadic positional) 10: * 2. Resolve each to a numeric group ID + org via `resolveIssue` 11: * 3. Verify all issues are in the same org (cross-org merge rejected by API) 12: * 4. Optionally pin the canonical parent via `--into` 13: * 5. Call `mergeIssues(org, groupIds)` — the API auto-picks the parent 14: * unless we pre-sort with our chosen parent first 15: * 6. Emit the merge result 16: * 17: * Sentry picks the parent by size (largest by event count). ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/schema.ts</path>
<type>file</type>
<content>
280:
281: // ---------------------------------------------------------------------------
282: // Command definition
283: // ---------------------------------------------------------------------------
284:
285: type SchemaFlags = {
286: readonly all: boolean;
287: readonly search?: string;
288: };
289:
290: export const schemaCommand = buildCommand({
291: auth: false,
292: docs: {
293: brief: "Browse the Sentry API schema",
294: fullDescription:
295: "Browse and search the Sentry API schema. Shows available resources, " +
296: "operations, and endpoint details. Use with --json for machine-readable output.\n\n" +
297: "Examples:\n" +
298: " sentry schema List all API resources\n" +
299: " sentry schema issues Show endpoints for a resource\n" +
300: " sentry schema issues list ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/monitor/run.ts</path> <type>file</type> <content> 1: /** 2: * sentry monitor run 3: * 4: * Wrap an arbitrary command with cron monitor check-ins. Sends an 5: * `in_progress` check-in when the command starts, then `ok`/`error` (with 6: * duration) on completion based on the child's exit code. 7: * 8: * Check-ins are sent via DSN (not an auth token), reusing the envelope 9: * transport in `src/lib/envelope/`. The DSN is resolved from `--dsn`, the 10: * `SENTRY_DSN` env var, or by auto-detecting it from the project sources. 11: * 12: * The wrapped command inherits the parent's stdio and signals (SIGINT/SIGTERM 13: * are forwarded), and its exit code is preserved. Check-in send failures are 14: * non-fatal — they are logged and the wrapped command still runs and exits 15: * with its own code. ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/monitor/run.ts</path>
<type>file</type>
<content>
255: async *func(this: SentryContext, flags: RunFlags, ...rawArgs: string[]) {
256: const { cwd } = this;
257:
258: // The scanner consumes the "--" escape token (allowArgumentEscapeSequence
259: // is enabled in app.ts), but strip a leading one defensively in case it is
260: // ever passed through (e.g. via a wrapping shell).
261: const args = rawArgs[0] === "--" ? rawArgs.slice(1) : rawArgs;
262: const monitorSlug = args[0];
263: const command = args.slice(1);
264:
265: if (!monitorSlug) {
266: throw new ValidationError(
267: `No monitor slug provided. Usage: ${USAGE_HINT}`,
268: "monitor-slug"
269: );
270: }
271: if (command.length === 0) {
272: throw new ValidationError(
273: `No command provided. ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/project/create.ts</path>
<type>file</type>
<content>
1: /**
2: * sentry project create
3: *
4: * Create one or more Sentry projects.
5: * Supports `[<org>/]<name>:<platform>` pairs for one or more projects.
6: *
7: * ## Flow
8: *
9: * 1. Parse one or more name:platform pairs and extract any org prefix
10: * 2. Resolve org → positional prefix > env vars > config defaults > DSN auto-detection
11: * (all names must share one org)
12: * 3. For each name: resolve team + create project (fetch DSN, build URL)
13: * 4. Display results (one block per project)
14: *
15: * Every project is a `name:platform` pair (e.g. `sentry project create
16: * web:javascript api:python-django`). The platform must always be attached
17: * with `:` — there is no space-separated form, with or without an explicit
18: * org. Project names cannot contain whitespace.
19: */
20:
21: import type { SentryContext } from ...
Found 12 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/project/create.ts:
Line 34: ContextError,
Line 382: function parseProjectName(
Line 411: throw new ContextError("Project name", USAGE_HINT, [
Line 417: throw new ContextError("Project name", USAGE_HINT, []);
Line 422: function parseProjectPlatform(rawName: string, rawPlatform: string): string {
Line 443: function parsePairedProjectSpec(rawSpec: string): ParsedProjectSpec {
Line 465: function parseProjectSpecs(rawSpecs: readonly string[]): {
Line 470: throw new ContextError("Project specification", USAGE_HINT, []);
Line 609: customUsage: ["[<org>/]<name>:<platform>..."],
Line 635: parameters: {
Line 655: async *func(this: SentryContext, flags: CreateFlags, ...args: string[]) {
Line 663: throw new ContextError("Organization", USAGE_HINT, [
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/project/create.ts</path>
<type>file</type>
<content>
360: }
361: if (error.status === 404) {
362: return await handleCreateProject404(opts);
363: }
364: return handleCreateApiError(error, opts);
365: }
366: }
367:
368: /** A validated project specification parsed from the command positionals. */
369: type ParsedProjectSpec = {
370: /** Explicit organization slug, when the name used org/name syntax. */
371: org?: string;
372: /** Project display name. */
373: name: string;
374: /** Validated Sentry platform identifier. */
375: platform: string;
376: };
377:
378: /**
379: * Parse and validate a project name independently from its platform source.
380: * Project names cannot contain whitespace in either supported syntax.
381: */
382: function parseProjectName(
383: rawName: string,
384: platform: string
385: ): ParsedProjectSpec {
386: if (rawName.trim() === "") {
387: ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/cli/feedback.ts</path>
<type>file</type>
<content>
1: /**
2: * Feedback Command
3: *
4: * Allows users to submit feedback about the CLI.
5: * All arguments after 'feedback' are joined into a single message.
6: *
7: * @example sentry cli feedback i love this tool
8: * @example sentry cli feedback the issue view is confusing
9: */
10:
11: import { isatty } from "node:tty";
12: // biome-ignore lint/performance/noNamespaceImport: Sentry SDK recommends namespace import
13: import * as Sentry from "@sentry/node-core/light";
14: import type { SentryContext } from "../../context.js";
15: import { buildCommand } from "../../lib/command.js";
16: import { ConfigError, ValidationError } from "../../lib/errors.js";
17: import { formatFeedbackResult } from "../../lib/formatters/human.js";
18: import { CommandOutput } from "../../lib/formatters/output.js";
19: import { logger } from "../../lib/logger.js";
20:
21: /** ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/cli/defaults.ts</path>
<type>file</type>
<content>
250: telemetryEffective?: {
251: enabled: boolean;
252: source: string;
253: };
254: /** What was changed (for set/clear actions) */
255: changed?: {
256: key: string;
257: previousValue: string | boolean | null;
258: newValue: string | boolean | null;
259: };
260: };
261:
262: // ---------------------------------------------------------------------------
263: // Command
264: // ---------------------------------------------------------------------------
265:
266: const log = logger.withTag("defaults");
267:
268: export const defaultsCommand = buildCommand({
269: auth: false,
270: docs: {
271: brief: "View and manage default settings",
272: fullDescription:
273: "View and manage persistent CLI default settings.\n\n" +
274: "With no arguments, shows all current defaults. ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/cli/defaults.ts</path>
<type>file</type>
<content>
390:
391: const handler = DEFAULTS_REGISTRY[canonical];
392:
393: // Key + --clear → clear specific default
394: if (flags.clear) {
395: if (valueArg !== undefined) {
396: throw new ValidationError(
397: `Cannot use --clear with a value. Use either 'sentry cli defaults ${keyArg} --clear' or 'sentry cli defaults ${keyArg} <value>'.`,
398: "args"
399: );
400: }
401: const previous = handler.get();
402: handler.clear();
403: yield new CommandOutput({
404: action: "clear" as const,
405: defaults: getAllDefaults(),
406: changed: { key: canonical, previousValue: previous, newValue: null },
407: });
408: return;
409: }
410:
411: // Key only, no value → show specific default
412: if (valueArg === undefined) {
413: yield new ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/dashboard/widget/add.ts</path>
<type>file</type>
<content>
1: /**
2: * sentry dashboard widget add
3: *
4: * Add a widget to an existing dashboard using inline flags.
5: */
6:
7: import type { SentryContext } from "../../../context.js";
8: import { getDashboard, updateDashboard } from "../../../lib/api-client.js";
9: import { parseOrgProjectArg } from "../../../lib/arg-parsing.js";
10: import { buildCommand, numberParser } from "../../../lib/command.js";
11: import { ValidationError } from "../../../lib/errors.js";
12: import { formatWidgetAdded } from "../../../lib/formatters/human.js";
13: import { CommandOutput } from "../../../lib/formatters/output.js";
14: import { buildDashboardUrl } from "../../../lib/sentry-urls.js";
15: import {
16: assignDefaultLayout,
17: type DashboardDetail,
18: type DashboardWidget,
19: FALLBACK_LAYOUT,
20: prepareDashboardForUpdate,
21: validateWidgetLayout,
22: type ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/dashboard/widget/add.ts</path>
<type>file</type>
<content>
190: },
191: },
192: aliases: {
193: d: "display",
194: q: "query",
195: w: "where",
196: g: "group-by",
197: s: "sort",
198: n: "limit",
199: l: "layout",
200: x: "col",
201: y: "row",
202: },
203: },
204: async *func(this: SentryContext, flags: AddFlags, ...args: string[]) {
205: const { cwd } = this;
206:
207: const { dashboardArgs, title } = parseAddPositionalArgs(args);
208:
209: // Resolve dataset aliases (e.g. "errors" → "error-events") once, up front.
210: // Every downstream consumer — enum validation, dataset-aware aggregate
211: // validation, the PUT body — must see the canonical name, so we thread
212: // the normalized value and never reference flags.dataset below.
213: const dataset = normalizeDataset(flags.dataset);
214:
215: // ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/dashboard/widget/delete.ts</path>
<type>file</type>
<content>
1: /**
2: * sentry dashboard widget delete
3: *
4: * Remove a widget from an existing dashboard.
5: *
6: * Uses `buildDeleteCommand` — auto-injects `--yes`/`--force`/`--dry-run`
7: * flags. Non-interactive guard is disabled (`noNonInteractiveGuard`) because
8: * widget deletion is reversible (re-add the widget). `--yes`/`--force` are
9: * accepted but have no effect today (no confirmation prompt); `--dry-run`
10: * shows which widget would be removed without modifying the dashboard.
11: */
12:
13: import type { SentryContext } from "../../../context.js";
14: import { getDashboard, updateDashboard } from "../../../lib/api-client.js";
15: import { parseOrgProjectArg } from "../../../lib/arg-parsing.js";
16: import { numberParser } from "../../../lib/command.js";
17: import { ValidationError } from "../../../lib/errors.js";
18: import { ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/dashboard/widget/edit.ts</path>
<type>file</type>
<content>
1: /**
2: * sentry dashboard widget edit
3: *
4: * Edit a widget in an existing dashboard using inline flags.
5: */
6:
7: import type { SentryContext } from "../../../context.js";
8: import { getDashboard, updateDashboard } from "../../../lib/api-client.js";
9: import { parseOrgProjectArg } from "../../../lib/arg-parsing.js";
10: import { buildCommand, numberParser } from "../../../lib/command.js";
11: import { ValidationError } from "../../../lib/errors.js";
12: import { formatWidgetEdited } from "../../../lib/formatters/human.js";
13: import { CommandOutput } from "../../../lib/formatters/output.js";
14: import { buildDashboardUrl } from "../../../lib/sentry-urls.js";
15: import {
16: type DashboardDetail,
17: type DashboardWidget,
18: type DashboardWidgetQuery,
19: FALLBACK_LAYOUT,
20: parseAggregate,
21: parseSortExpression,
22: ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/dashboard/widget/edit.ts</path>
<type>file</type>
<content>
308: },
309: aliases: {
310: i: "index",
311: t: "title",
312: d: "display",
313: q: "query",
314: w: "where",
315: g: "group-by",
316: s: "sort",
317: n: "limit",
318: x: "col",
319: y: "row",
320: },
321: },
322: async *func(this: SentryContext, flags: EditFlags, ...args: string[]) {
323: const { cwd } = this;
324:
325: if (flags.index === undefined && !flags.title) {
326: throw new ValidationError(
327: "Specify --index or --title to identify the widget to edit.\n\n" +
328: "Example:\n" +
329: " sentry dashboard widget edit <dashboard> --title 'My Widget' --display bar",
330: "index"
331: );
332: }
333:
334: // Resolve dataset aliases (e.g. "errors" → "error-events") once, up front.
335: // Replace ...
Found 1 matches /home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/dashboard/resolve.ts: Line 159: export function parseDashboardPositionalArgs(
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/dashboard/resolve.ts</path>
<type>file</type>
<content>
130: dashboardRef: args[1] as string,
131: targetArg: `${urlParsed.org}/`,
132: };
133: }
134: throw new ValidationError(
135: "Dashboard ID or title is required.\n\n" +
136: "The URL provided contains an org but no dashboard ID.\n" +
137: `Try: sentry dashboard <command> ${urlParsed.org}/ <id-or-title>`,
138: "dashboard"
139: );
140: }
141: return null;
142: }
143:
144: /**
145: * Parse a dashboard reference and optional target from array positional args. ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/dashboard/view.ts</path>
<type>file</type>
<content>
1: /**
2: * sentry dashboard view
3: *
4: * View a dashboard with rendered widget data (sparklines, tables, big numbers).
5: * Supports --refresh for auto-refreshing live display.
6: */
7:
8: import type { SentryContext } from "../../context.js";
9: import { getDashboard, queryAllWidgets } from "../../lib/api-client.js";
10: import { parseOrgProjectArg } from "../../lib/arg-parsing.js";
11: import { openInBrowser } from "../../lib/browser.js";
12: import { buildCommand } from "../../lib/command.js";
13: import type { DashboardViewData } from "../../lib/formatters/dashboard.js";
14: import { createDashboardViewRenderer } from "../../lib/formatters/dashboard.js";
15: import { ClearScreen, CommandOutput } from "../../lib/formatters/output.js";
16: import {
17: applyFreshFlag,
18: FRESH_ALIASES,
19: FRESH_FLAG,
20: } from "../../lib/list-command.js";
21: ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/dashboard/revisions.ts</path>
<type>file</type>
<content>
1: /**
2: * sentry dashboard revisions
3: *
4: * List revision history for a Sentry dashboard with cursor-based pagination.
5: */
6:
7: import type { SentryContext } from "../../context.js";
8: import { MAX_PAGINATION_PAGES } from "../../lib/api/infrastructure.js";
9: import {
10: API_MAX_PER_PAGE,
11: listDashboardRevisionsPaginated,
12: } from "../../lib/api-client.js";
13: import { parseOrgProjectArg } from "../../lib/arg-parsing.js";
14: import { buildCommand } from "../../lib/command.js";
15: import {
16: advancePaginationState,
17: buildPaginationContextKey,
18: hasPreviousPage,
19: resolveCursor,
20: } from "../../lib/db/pagination.js";
21: import { filterFields } from "../../lib/formatters/json.js";
22: import { colorTag, escapeMarkdownCell } from "../../lib/formatters/markdown.js";
23: import { CommandOutput } from ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/dashboard/restore.ts</path>
<type>file</type>
<content>
1: /**
2: * sentry dashboard restore
3: *
4: * Restore a dashboard to a previous revision.
5: */
6:
7: import type { SentryContext } from "../../context.js";
8: import { restoreDashboardRevision } from "../../lib/api-client.js";
9: import { parseOrgProjectArg } from "../../lib/arg-parsing.js";
10: import { buildCommand } from "../../lib/command.js";
11: import { ValidationError } from "../../lib/errors.js";
12: import { colorTag, escapeMarkdownCell } from "../../lib/formatters/markdown.js";
13: import { CommandOutput } from "../../lib/formatters/output.js";
14: import { formatRelativeTime } from "../../lib/formatters/time-utils.js";
15: import { withProgress } from "../../lib/polling.js";
16: import { buildDashboardUrl } from "../../lib/sentry-urls.js";
17: import type { DashboardDetail } from "../../types/dashboard.js";
18: import {
19: ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/dashboard/create.ts</path>
<type>file</type>
<content>
1: /**
2: * sentry dashboard create
3: *
4: * Create a new dashboard in a Sentry organization.
5: */
6:
7: import type { SentryContext } from "../../context.js";
8: import { createDashboard, getProject } from "../../lib/api-client.js";
9: import {
10: type ParsedOrgProject,
11: parseOrgProjectArg,
12: } from "../../lib/arg-parsing.js";
13: import { buildCommand } from "../../lib/command.js";
14: import { ContextError, ValidationError } from "../../lib/errors.js";
15: import { formatDashboardCreated } from "../../lib/formatters/human.js";
16: import { CommandOutput } from "../../lib/formatters/output.js";
17: import {
18: fetchProjectId,
19: resolveAllTargets,
20: resolveOrg,
21: resolveProjectBySlug,
22: toNumericId,
23: } from "../../lib/resolve-target.js";
24: import { buildDashboardUrl } from "../../lib/sentry-urls.js";
25: import { ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/dashboard/list.ts</path>
<type>file</type>
<content>
240: // When resuming mid-page, find the afterId and skip everything up to and
241: // including it. If the afterId was deleted between requests, fall through
242: // and process the entire page from the start (no results lost).
243: let startIdx = 0;
244: if (opts.afterId) {
245: const afterPos = data.findIndex((d) => d.id === opts.afterId);
246: if (afterPos !== -1) {
247: startIdx = afterPos + 1;
248: }
249: }
250:
251: for (let i = startIdx; i < data.length; i++) {
252: const item = data[i] as DashboardListItem;
253: if (!opts.glob || opts.glob((item.title ?? "").toLowerCase())) {
254: results.push(item);
255: if (results.length >= opts.limit) {
256: return {
257: filled: true,
258: bookmark: encodeCursor(opts.serverCursor, item.id),
259: };
260: }
261: }
262: ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/trace/view.ts</path>
<type>file</type>
<content>
45: import {
46: parseTraceTargetWithRecovery,
47: resolveTraceOrgOptionalProject,
48: warnIfNormalized,
49: } from "../../lib/trace-target.js";
50: import type { TraceSpan } from "../../types/index.js";
51:
52: type ViewFlags = {
53: readonly json: boolean;
54: readonly web: boolean;
55: readonly spans: number;
56: readonly fresh: boolean;
57: readonly full: boolean;
58: readonly fields?: string[];
59: };
60:
61: /** Usage hint for ContextError messages */
62: const USAGE_HINT = "sentry trace view [<org>/<project>/]<trace-id>";
63:
64: /**
65: * Build a contextual hint with real values for easy copy-paste. ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/trace/view.ts</path>
<type>file</type>
<content>
440: options: {
441: org: string;
442: fallbackProject: string;
443: traceId: string;
444: }
445: ): Promise<Map<string, TraceItemDetail>> {
446: const log = logger.withTag("trace.view");
447: const flat = flattenSpanTree(spans);
448:
449: if (totalCount > LARGE_TRACE_WARN_THRESHOLD) {
450: log.warn(
451: `Trace has ${totalCount} spans \u2014 this may take a moment. ` +
452: "Use 'sentry span view' for specific spans."
453: );
454: }
455:
456: return fetchMultiSpanDetails(flat, {
457: ...options,
458: onProgress:
459: flat.length > PROGRESS_THRESHOLD
460: ? (done, total) => {
461: log.info(`Fetching span data (${done}/${total})...`);
462: }
463: : undefined,
464: });
465: }
466:
467: export const viewCommand = buildCommand({
468: docs: {
469: brief: "View ...
Found 24 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/lib/trace-target.ts:
Line 20: import { ContextError, ValidationError } from "./errors.js";
Line 113: * @throws {ContextError} If no arguments are provided
Line 116: export function parseTraceTarget(
Line 120: if (args.length === 0) {
Line 121: throw new ContextError("Trace ID", usageHint, []);
Line 126: throw new ContextError("Trace ID", usageHint, []);
Line 130: if (args.length > 2) {
Line 137: if (args.length === 1) {
Line 175: throw new ContextError("Trace ID", usageHint, []);
Line 203: throw new ContextError("Trace ID", usageHint, []);
Line 277: * Used by {@link parseTraceTargetWithRecovery} to peek at the raw input
Line 284: if (args.length === 0) {
Line 287: if (args.length === 1) {
Line 322: export async function parseTraceTargetWithRecovery(
Line 383: if (args.length === 1) {
Line 422: * @throws {ContextError} If auto-detection ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/lib/trace-target.ts</path>
<type>file</type>
<content>
100: * - `<org>/<trace-id>` → org-scoped
101: * - `<org>/<project>/<trace-id>` → explicit
102: *
103: * **Two arguments (space-separated):**
104: * - `<org>/<project> <trace-id>` → explicit
105: * - `<org> <trace-id>` → project-search (bare slug)
106: *
107: * Extra positional arguments beyond the first two are ignored with a
108: * warning, matching the established pattern across CLI commands.
109: *
110: * @param args - Positional arguments from CLI
111: * @param usageHint - Usage example for error messages
112: * @returns Parsed trace target with type discrimination
113: * @throws {ContextError} If no arguments are provided
114: * @throws {ValidationError} If the trace ID format is invalid
115: */
116: export function parseTraceTarget(
117: args: string[],
118: usageHint: string
119: ): ParsedTraceTarget {
120: if (args.length === 0) {
121: ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/span/view.ts</path>
<type>file</type>
<content>
45:
46: type ViewFlags = {
47: readonly json: boolean;
48: readonly spans: number;
49: readonly fresh: boolean;
50: readonly fields?: string[];
51: };
52:
53: /** Usage hint for ContextError messages */
54: const USAGE_HINT =
55: "sentry span view [<org>/<project>/]<trace-id> <span-id> [<span-id>...]";
56:
57: /** Result of the initial positional-arg parse for `span view`. */
58: type SpanViewArgs =
59: | {
60: /** Args are already resolved (auto-split `<trace-id>/<span-id>`). */
61: kind: "resolved";
62: traceTarget: ReturnType<typeof parseSlashSeparatedTraceTarget>;
63: rawSpanIds: string[];
64: }
65: | {
66: /**
67: * First arg is the raw trace target (needs async recovery); the rest
68: * are raw span IDs. Command layer calls `parseTraceTargetWithRecovery`. ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/span/view.ts</path>
<type>file</type>
<content>
340: [result.span],
341: data.spansDepth
342: );
343: if (treeLines.length > 0) {
344: parts.push(`${treeLines.join("\n")}\n`);
345: }
346: }
347: }
348: return parts.join("");
349: }
350:
351: /**
352: * Transform span view data for JSON output.
353: * Applies `--fields` filtering per element.
354: */
355: function jsonTransformSpanView(data: SpanViewData, fields?: string[]): unknown {
356: const mapped = buildJsonResults(data.results, data.traceId, data.details);
357: if (fields && fields.length > 0) {
358: return mapped.map((item) => filterFields(item, fields));
359: }
360: return mapped;
361: }
362:
363: export const viewCommand = buildCommand({
364: docs: {
365: brief: "View details of specific spans",
366: fullDescription:
367: "View detailed information about one or more spans ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/span/list.ts</path>
<type>file</type>
<content>
130: for (const a of alias) {
131: expanded.add(a);
132: }
133: } else {
134: expanded.add(f);
135: }
136: }
137:
138: // Remove anything already requested by SPAN_FIELDS or its output aliases
139: for (const known of KNOWN_SPAN_FIELDS) {
140: expanded.delete(known);
141: }
142:
143: return expanded.size > 0 ? Array.from(expanded) : undefined;
144: }
145:
146: /** Accepted values for the --sort flag (matches trace list) */
147: const VALID_SORT_VALUES: SpanSortValue[] = ["date", "duration"];
148:
149: /** Default sort order for span results */
150: const DEFAULT_SORT: SpanSortValue = "date";
151:
152: /** Default time period for span queries */
153: const DEFAULT_PERIOD = "7d";
154:
155: /** Pagination storage key for trace-scoped span listing */
156: export const PAGINATION_KEY = "span-list";
157:
158: /** ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/span/list.ts</path>
<type>file</type>
<content>
520: }
521:
522: return {
523: output: {
524: flatSpans,
525: hasMore,
526: hasPrev,
527: nextCursor,
528: org,
529: project,
530: extraAttributes: extraApiFields,
531: },
532: hint,
533: };
534: }
535:
536: // ---------------------------------------------------------------------------
537: // Command definition
538: // ---------------------------------------------------------------------------
539:
540: export const listCommand = buildListCommand("span", {
541: docs: {
542: brief: "List spans in a project or trace",
543: fullDescription:
544: "List spans from a Sentry project, or within a specific trace.\n\n" +
545: "Project mode (no trace ID):\n" +
546: " sentry span list # auto-detect from DSN or config\n" +
547: " sentry span list <org>/<project> ...
Found 1 matches /home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/lib/trace-target.ts: Line 604: export function parseDualModeArgs(
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/lib/trace-target.ts</path>
<type>file</type>
<content>
570: /**
571: * Result from dual-mode argument disambiguation.
572: *
573: * Used by commands that support both project-scoped listing (no trace ID)
574: * and trace-scoped listing (trace ID provided), like `span list` and
575: * `log list`.
576: *
577: * Discriminated on `mode`:
578: * - `"project"` — no trace ID detected; `target` is the optional org/project arg
579: * - `"trace"` — a 32-char hex trace ID was found; `parsed` contains the full target
580: */
581: export type ParsedDualModeArgs =
582: | { mode: "project"; target?: string }
583: | { mode: "trace"; parsed: ParsedTraceTarget };
584:
585: /**
586: * Disambiguate positional arguments for dual-mode list commands. ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/log/list.ts</path>
<type>file</type>
<content>
650:
651: if (state.headerEmitted && state.table) {
652: text += state.table.footer();
653: }
654:
655: if (hint) {
656: if (state.headerEmitted) {
657: text += `${text ? "\n" : ""}${formatFooter(hint)}`;
658: } else {
659: text += `${hint}\n`;
660: }
661: }
662:
663: return text;
664: },
665: };
666: }
667:
668: /**
669: * Transform log output into the JSON shape.
670: *
671: * Discriminates between {@link LogListResult} (single-fetch) and bare
672: * {@link LogLike} items (follow mode). Single-fetch yields a JSON envelope
673: * with `data` and `hasMore`; follow mode yields one JSON object per line (JSONL).
674: */
675: function jsonTransformLogOutput(data: LogOutput, fields?: string[]): unknown {
676: if (isLogListResult(data)) {
677: // Batch (single-fetch): return ...
Found 2 matches /home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/log/list.ts: Line 163: function parseLogListArgs( Line 785: const parsed = parseLogListArgs(args);
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/log/list.ts</path>
<type>file</type>
<content>
130: const num = Number.parseInt(value, 10);
131: if (Number.isNaN(num) || num < 1) {
132: throw new Error("--follow interval must be a positive integer");
133: }
134: return num;
135: }
136:
137: /**
138: * Extends the base {@link BaseLogLike} from formatters with the
139: * `timestamp_precise` field needed for follow-mode dedup tracking.
140: */
141: type LogLike = BaseLogLike & {
142: /** Nanosecond-precision timestamp used for dedup in follow mode.
143: * Optional because TraceLog may omit it when the API response doesn't include it. */
144: timestamp_precise?: number;
145: };
146:
147: /** Result from a single fetch: logs to yield + hint for the footer. ...
Found 23 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/log/view.ts:
Line 23: ContextError,
Line 69: /** Usage hint for ContextError messages */
Line 78: * throws `ContextError` for any single-slash arg, treating it as `org/project`
Line 113: * @throws {ContextError} If no arguments provided
Line 116: export function parsePositionalArgs(args: string[]): {
Line 122: if (args.length === 0) {
Line 123: throw new ContextError("Log ID", USAGE_HINT, []);
Line 128: throw new ContextError("Log ID", USAGE_HINT, []);
Line 131: if (args.length === 1) {
Line 135: // throws ContextError for "org/logId" thinking it's "org/project" with no ID.
Line 145: throw new ContextError("Log ID", USAGE_HINT, []);
Line 158: throw new ContextError("Log ID", USAGE_HINT, []);
Line 173: throw new ContextError("Log ID", USAGE_HINT, []);
Line 188: if (args.length === 2) {
Line 201: throw new ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/log/view.ts</path>
<type>file</type>
<content>
60: const LOG_DETAIL_CONCURRENCY = 15;
61:
62: type ViewFlags = {
63: readonly json: boolean;
64: readonly web: boolean;
65: readonly fresh: boolean;
66: readonly fields?: string[];
67: };
68:
69: /** Usage hint for ContextError messages */
70: const USAGE_HINT = "sentry log view <org>/<project> <log-id> [<log-id>...]";
71:
72: /**
73: * Resolve a single-slash positional arg (`before/after`) as `org/log-id`, or
74: * return `null` when `after` is not a valid 32-char hex log ID and should fall
75: * through to `parseSlashSeparatedArg`.
76: *
77: * This guard must run before `parseSlashSeparatedArg` because that function
78: * throws `ContextError` for any single-slash arg, treating it as `org/project`
79: * with a missing log ID (CLI-1AK). ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/log/view.ts</path>
<type>file</type>
<content>
470: const parts: string[] = [];
471: for (let i = 0; i < data.logs.length; i++) {
472: if (parts.length > 0) {
473: parts.push("\n---\n");
474: }
475: parts.push(
476: formatLogDetails(
477: // biome-ignore lint/style/noNonNullAssertion: index is bounded by data.logs.length
478: data.logs[i]!,
479: data.orgSlug,
480: data.details?.[i]?.attributes,
481: data.extraFields
482: )
483: );
484: }
485: return parts.join("\n");
486: }
487:
488: export const viewCommand = buildCommand({
489: docs: {
490: brief: "View details of one or more log entries",
491: fullDescription:
492: "View detailed information about Sentry log entries by their IDs.\n\n" +
493: "Target specification:\n" +
494: " sentry log view <log-id> # auto-detect from DSN or ...
Found 28 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/event/view.ts:
Line 32: ContextError,
Line 169: /** Usage hint for ContextError messages */
Line 177: * the org/project prefix so `parsePositionalArgs` can extract the target.
Line 202: * ContextError for single-slash args like "org/SHORT-ID", which looks like
Line 208: // which throws ContextError for single-slash args.
Line 239: throw new ContextError("Issue ID", BARE_LATEST_HINT, [
Line 319: /** Return type for parsePositionalArgs */
Line 354: export function parsePositionalArgs(args: string[]): ParsedPositionalArgs {
Line 355: if (args.length === 0) {
Line 356: throw new ContextError("Event ID", USAGE_HINT, []);
Line 361: throw new ContextError("Event ID", USAGE_HINT, []);
Line 384: throw new ContextError("Event ID", USAGE_HINT, [
Line 390: if (args.length === 1) {
Line 414: const extraEventIds = args.length > 2 ? args.slice(2) : ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/event/view.ts</path>
<type>file</type>
<content>
155: * Build a CLI-native replay hint when the event is linked to a replay.
156: */
157: function replayHint(org: string, event: SentryEvent): string | undefined {
158: const replayId = getReplayIdFromEvent(event);
159: return replayId
160: ? `Related replay: sentry replay view ${org}/${replayId}`
161: : undefined;
162: }
163:
164: function joinHintParts(parts: Array<string | undefined>): string | undefined {
165: const hints = parts.filter((part): part is string => Boolean(part));
166: return hints.length > 0 ? hints.join(" | ") : undefined;
167: }
168:
169: /** Usage hint for ContextError messages */
170: const USAGE_HINT = "sentry event view <org>/<project> <event-id>";
171:
172: /**
173: * Expand positional args by splitting each on newlines. ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/event/view.ts</path>
<type>file</type>
<content>
1045: for (let i = 0; i < results.length; i++) {
1046: const result = results[i];
1047: if (result?.status === "fulfilled") {
1048: events.push(result.value);
1049: } else if (result?.status === "rejected") {
1050: log.warn(`Failed to fetch event ${eventIds[i]}: ${result.reason}`);
1051: }
1052: }
1053:
1054: if (events.length === 0) {
1055: const firstResult = results[0];
1056: if (firstResult?.status === "rejected") {
1057: throw firstResult.reason;
1058: }
1059: }
1060:
1061: return events;
1062: }
1063:
1064: export const viewCommand = buildCommand({
1065: docs: {
1066: brief: "View details of one or more events",
1067: fullDescription:
1068: "View detailed information about Sentry events by their IDs.\n\n" +
1069: "Target specification:\n" +
1070: " sentry event view <event-id> ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/replay/view.ts</path>
<type>file</type>
<content>
60: readonly fields?: string[];
61: };
62:
63: type ParsedPositionalArgs = {
64: replayId: string;
65: targetArg: string | undefined;
66: warning?: string;
67: };
68:
69: const USAGE_HINT =
70: "sentry replay view [<org>/<project>/]<replay-id> | <replay-url>";
71: const MAX_ACTIVITY_EVENTS = 6;
72: const MAX_RELATED_ERRORS = 3;
73: const MAX_RELATED_TRACES = 2;
74:
75: const log = logger.withTag("replay.view");
76:
77: /**
78: * Parse a single positional argument as a replay target.
79: *
80: * Handles bare replay IDs, `<org>/<replay-id>`, `<org>/<project>/<replay-id>`,
81: * and Sentry replay URLs. The single-slash case (`org/id`) needs special
82: * handling because 32-char hex replay IDs look valid to the generic
83: * `parseSlashSeparatedArg` which would misinterpret the org as a project. ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/replay/view.ts</path>
<type>file</type>
<content>
320: ]);
321:
322: return { activity, relatedIssues, relatedTraces };
323: }
324:
325: export const viewCommand = buildCommand({
326: docs: {
327: brief: "View a Session Replay",
328: fullDescription:
329: "View detailed information about a Session Replay.\n\n" +
330: "Replay ID formats:\n" +
331: " <replay-id> - auto-detect org from config or DSN\n" +
332: " <org>/<replay-id> - explicit organization\n" +
333: " <org>/<project>/<id> - explicit org/project context\n" +
334: " <replay-url> - parse org and replay ID from a Sentry URL\n\n" +
335: "Examples:\n" +
336: " sentry replay view 346789a703f6454384f1de473b8b9fcc\n" +
337: " sentry replay view sentry/346789a703f6454384f1de473b8b9fcc\n" +
338: " sentry replay view ...
Found 7 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/local/run.ts:
Line 27: import { CliError, EXIT, ValidationError } from "../../lib/errors.js";
Line 105: throw new ValidationError(
Line 270: if (!(err instanceof ValidationError && err.field === "port")) {
Line 339: throw new ValidationError(AUTO_DETECT_ERROR_MESSAGE, "command");
Line 364: parameters: {
Line 433: async *func(this: SentryContext, flags: RunFlags, ...rawArgs: string[]) {
Line 435: throw new ValidationError("--open cannot be used with --verify.", "open");
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/local/run.ts</path>
<type>file</type>
<content>
300: " - go.mod (Go)",
301: " - docker-compose.yml / compose.yml (Docker Compose)",
302: ].join("\n");
303:
304: /** Build the env vars for the child process. */
305: function buildChildEnv(
306: spotlightUrl: string,
307: commandSource: string,
308: cwd: string
309: ): Record<string, string | undefined> {
310: const clientSpotlightVars = Object.fromEntries(
311: CLIENT_SPOTLIGHT_PREFIXES.map((prefix) => [
312: `${prefix}SENTRY_SPOTLIGHT`,
313: spotlightUrl,
314: ])
315: );
316: let env: Record<string, string | undefined> = {
317: ...process.env,
318: ...clientSpotlightVars,
319: SENTRY_SPOTLIGHT: spotlightUrl,
320: SENTRY_TRACES_SAMPLE_RATE: process.env.SENTRY_TRACES_SAMPLE_RATE ?? "1",
321: SENTRY_RELEASE: process.env.SENTRY_RELEASE ?? ...
Found 11 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/react-native/xcode.ts:
Line 30: import { ContextError, ValidationError } from "../../lib/errors.js";
Line 109: throw new ValidationError(
Line 121: throw new ValidationError(
Line 167: throw new ValidationError(
Line 178: throw new ValidationError(
Line 186: throw new ValidationError(
Line 200: * `$NODE_BINARY <args>` would run plain Node and never re-enter the wrapper;
Line 302: throw new ContextError("Organization and project", USAGE_HINT);
Line 307: // at build time, and the wrapper copies it into the Hermes sourcemap. We must
Line 436: parameters: {
Line 499: async *func(this: SentryContext, flags: XcodeFlags, ...scriptArgs: string[]) {
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/react-native/xcode.ts</path>
<type>file</type>
<content>
380: /** Resolve the bundle/sourcemap pair via the packager (fetch) or a wrapped build. */
381: async function preparePair(
382: ctx: SentryContext,
383: script: string,
384: scriptArgs: string[],
385: fetchUrl: string | undefined
386: ): Promise<PrepareResult> {
387: const tempDir = mkdtempSync(join(tmpdir(), "sentry-rn-xcode-"));
388: if (fetchUrl) {
389: log.info(`Fetching sourcemaps from ${fetchUrl}`);
390: return {
391: kind: "pair",
392: mode: "fetch",
393: pair: await fetchFromPackager(fetchUrl, tempDir),
394: };
395: }
396: const result = runWrappedBuild(script, scriptArgs, ctx, tempDir);
397: // A failed build must not publish artifacts (matches the legacy CLI, which
398: // exits on a non-zero build status before uploading).
399: if (result.status !== 0) {
400: return {
401: kind: ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/proguard/upload.ts</path>
<type>file</type>
<content>
1: /**
2: * sentry proguard upload <path>...
3: *
4: * Upload ProGuard/R8 mapping files to Sentry using the DIF
5: * chunk-upload protocol. Each mapping file is bundled as
6: * `proguard/<uuid>.txt` where UUID is derived from the file content.
7: * Org/project resolved via standard cascade (DSN auto-detection,
8: * env vars, config defaults).
9: */
10:
11: import { readFile } from "node:fs/promises";
12: import type { SentryContext } from "../../context.js";
13: import type { ProguardMapping } from "../../lib/api/proguard.js";
14: import { uploadProguardMappings } from "../../lib/api/proguard.js";
15: import { buildCommand } from "../../lib/command.js";
16: import { ContextError, ValidationError } from "../../lib/errors.js";
17: import { mdKvTable, renderMarkdown } from "../../lib/formatters/markdown.js";
18: import { CommandOutput } from ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/build/upload.ts</path>
<type>file</type>
<content>
1: /**
2: * sentry build upload <paths...>
3: *
4: * Upload mobile builds to Sentry for preprod size analysis. Each build is
5: * normalized into a deterministic wrapper ZIP and uploaded via the
6: * chunk-upload + preprod-artifacts assemble protocol.
7: *
8: * This PR supports Android APK/AAB. iOS XCArchive/IPA is ported separately;
9: * git/VCS metadata collection is added in a follow-up. Sentry SaaS only.
10: */
11:
12: import { mkdtemp, rm, stat } from "node:fs/promises";
13: import { tmpdir } from "node:os";
14: import { join } from "node:path";
15: import type { SentryContext } from "../../context.js";
16: import {
17: type BuildUploadMetadata,
18: uploadBuild,
19: } from "../../lib/api/preprod-artifacts.js";
20: import {
21: detectBuildFormatFromFile,
22: normalizeBuildDirectory,
23: normalizeBuildFile,
24: normalizeIpa,
25: ...
Found 48 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/debug-files/upload.ts:
Line 9: * vars, config defaults), so `--no-upload` (dry-run) needs no credentials.
Line 51: import { ContextError, ValidationError } from "../../lib/errors.js";
Line 107: /** Assembly state after upload (omitted for `--no-upload`). */
Line 115: /** Organization slug. Omitted when `--no-upload` short-circuits. */
Line 117: /** Project slug. Omitted when `--no-upload` short-circuits. */
Line 119: /** Whether files were actually uploaded (false for `--no-upload`). */
Line 123: /** Number of files uploaded (0 for `--no-upload`). */
Line 131: "require-all"?: boolean;
Line 162: String(data.files.length),
Line 305: * Determine which explicitly requested `--id` values were not found among the
Line 306: * uploaded files. Returns an empty array when `--id` was not used. ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/debug-files/upload.ts</path>
<type>file</type>
<content>
510: setExitCode(1);
511: return {
512: hint: `Missing requested debug id(s): ${params.missingRequestedIds.join(", ")}`,
513: };
514: }
515:
516: return {
517: hint: `Uploaded ${results.length} debug file(s) to ${params.org}/${params.project}`,
518: };
519: }
520:
521: export const uploadCommand = buildCommand({
522: // Auth is not required for --no-upload (dry-run). The upload path calls
523: // resolveOrgAndProject which triggers auth resolution.
524: auth: false,
525: docs: {
526: brief: "Upload debug information files to Sentry",
527: fullDescription:
528: "Scan files and directories for native debug information files and " +
529: "upload them to Sentry using the chunk-upload protocol. ...
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/trial/start.test.ts /home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/trial/list.test.ts /home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/trace/view.test.ts /home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/trace/view.property.test.ts /home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/trace/view.func.test.ts /home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/trace/logs.test.ts /home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/trace/list.test.ts /home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/team/list.test.ts /home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/status/show.test.ts /home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/span/view.test.ts /home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/span/list.test.ts /home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/sourcemap/...
Found 100 matches (more matches available)
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/alert/rule-resolve.test.ts:
Line 58: import { ValidationError } from "../../../src/lib/errors.js";
Line 108: test("empty string throws ValidationError", () => {
Line 109: expect(() => parseIssueRuleArg("", HINT)).toThrow(ValidationError);
Line 126: test("single slash throws ValidationError (missing rule)", () => {
Line 128: ValidationError
Line 146: test("trailing slash after two slashes throws ValidationError", () => {
Line 148: ValidationError
Line 161: test("empty string throws ValidationError", () => {
Line 162: expect(() => parseMetricRuleArg("", HINT)).toThrow(ValidationError);
Line 186: test("trailing slash throws ValidationError (missing rule ref)", () => {
Line 187: expect(() => parseMetricRuleArg("org/", HINT)).toThrow(ValidationError);
Line 191: expect(() => parseMetricRuleArg("my-org/", ...
Found 63 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/issue/list.test.ts:
Line 58: ValidationError,
Line 350: test("converts a search-query parse 400 to a ValidationError when --query is set", async () => {
Line 381: expect(error).toBeInstanceOf(ValidationError);
Line 382: expect((error as ValidationError).field).toBe("query");
Line 784: // Previously, --cursor threw ValidationError for non-org-all modes.
Line 968: test("throws ValidationError when 'last' cursor not in cache", async () => {
Line 970: throw new ValidationError(
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/issue/resolve-commit-spec.test.ts:
Line 4: * expects. Every failure mode must throw a ValidationError (never silently
Line 12: import { ValidationError } from "../../../src/lib/errors.js";
Line 73: test("throws ValidationError when repo is not registered in Sentry", async () => {
Line 84: ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/issue/merge.func.test.ts</path>
<type>file</type>
<content>
75: }
76:
77: describe("mergeCommand.func()", () => {
78: let resolveIssueSpy: ReturnType<typeof spyOn>;
79: let mergeSpy: ReturnType<typeof spyOn>;
80:
81: beforeEach(() => {
82: resolveIssueSpy = vi.spyOn(issueUtils, "resolveIssue");
83: mergeSpy = vi.spyOn(apiClient, "mergeIssues");
84: });
85:
86: afterEach(() => {
87: resolveIssueSpy.mockRestore();
88: mergeSpy.mockRestore();
89: });
90:
91: test("rejects when fewer than 2 issues are provided (0 positionals, no --into)", async () => {
92: const { context } = createMockContext();
93: const func = await mergeCommand.loader();
94: const err = await func
95: .call(context, { json: false })
96: .catch((e: Error) => e);
97:
98: expect(err).toBeInstanceOf(Error);
99: expect(err.message).toContain("needs at least 2 issue IDs");
100: ...
Found 24 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/project/create.test.ts:
Line 6: * command behavior without real HTTP calls.
Line 35: ContextError,
Line 211: ["without an org", ["my-app", "python-flask"]],
Line 314: test("errors when user is member of multiple teams without --team", async () => {
Line 323: expect(err).toBeInstanceOf(ContextError);
Line 346: expect(err).toBeInstanceOf(ContextError);
Line 364: expect(err).toBeInstanceOf(ContextError);
Line 405: ).rejects.toThrow(ContextError);
Line 512: test("rejects invalid platform client-side without API call", async () => {
Line 704: // Should still show project info without DSN
Line 716: ).rejects.toThrow(ContextError);
Line 752: // Plain mode renders code spans as plain text without padding
Line 773: expect(err).toBeInstanceOf(ContextError);
Line 774: expect(err.message).toContain("Project specification is ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/project/create.test.ts</path>
<type>file</type>
<content>
750:
751: const output = stdoutWrite.mock.calls.map((c) => c[0]).join("");
752: // Plain mode renders code spans as plain text without padding
753: expect(output).toContain("Slug my-app-0g was assigned");
754: expect(output).toContain("my-app is already taken");
755: });
756:
757: test("does not show slug note when slug matches name", async () => {
758: const { context, stdoutWrite } = createMockContext();
759: const func = await createCommand.loader();
760: await func.call(context, { json: false }, "my-app:node");
761:
762: const output = stdoutWrite.mock.calls.map((c) => c[0]).join("");
763: expect(output).not.toContain("was assigned");
764: });
765:
766: test("shows helpful error when name is missing", async () => {
767: const { context } = createMockContext();
768: const func = await ...
Found 7 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/event/send.test.ts:
Line 9: import { ValidationError } from "../../../src/lib/errors.js";
Line 48: test("inline message sends an envelope and prints event ID", async () => {
Line 94: test("missing DSN throws ConfigError", async () => {
Line 120: test("nonexistent file throws ValidationError (not raw stack trace)", async () => {
Line 129: ).rejects.toBeInstanceOf(ValidationError);
Line 132: test("--raw requires file arguments", async () => {
Line 137: ).rejects.toBeInstanceOf(ValidationError);
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/event/send.test.ts</path>
<type>file</type>
<content>
35: let sendSpy: ReturnType<typeof vi.spyOn>;
36:
37: beforeEach(async () => {
38: func = await sendCommand.loader();
39: sendSpy = vi
40: .spyOn(transport, "sendEnvelopeRequest")
41: .mockResolvedValue(undefined);
42: });
43:
44: afterEach(() => {
45: sendSpy.mockRestore();
46: });
47:
48: test("inline message sends an envelope and prints event ID", async () => {
49: const { ctx, writes } = makeContext();
50: await func.call(ctx, {
51: dsn: SAAS_DSN,
52: message: ["Test message"],
53: level: "error",
54: "no-environ": true,
55: });
56:
57: expect(sendSpy).toHaveBeenCalledTimes(1);
58: const [calledDsn, calledBody] = sendSpy.mock.calls[0] as [string, string];
59: expect(calledDsn).toBe(SAAS_DSN);
60: expect(calledBody).toContain('"type":"event"');
61:
62: const output ...
Found 15 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/help.test.ts:
Line 4: * Tests `sentry help --json` output for full tree, specific groups,
Line 43: describe("sentry help --json", () => {
Line 45: const output = await runHelp(["--json"]);
Line 60: const output = await runHelp(["--json"]);
Line 71: const output = await runHelp(["--json"]);
Line 92: describe("sentry help --json <group>", () => {
Line 94: const output = await runHelp(["--json", "issue"]);
Line 105: const output = await runHelp(["--json", "issue"]);
Line 114: describe("sentry help --json <group> <command>", () => {
Line 116: const output = await runHelp(["--json", "issue", "list"]);
Line 128: const output = await runHelp(["--json", "issue", "list"]);
Line 138: const output = await runHelp(["--json", "api"]);
Line 146: describe("sentry help --json nested routes (dashboard widget)", () => {
Line 148: const output = ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/help.test.ts</path>
<type>file</type>
<content>
35: },
36: stdin: process.stdin,
37: };
38:
39: await run(app, ["help", ...args], mockContext);
40: return output;
41: }
42:
43: describe("sentry help --json", () => {
44: test("outputs full route tree as JSON", async () => {
45: const output = await runHelp(["--json"]);
46: const parsed = JSON.parse(output);
47:
48: expect(parsed).toHaveProperty("routes");
49: expect(Array.isArray(parsed.routes)).toBe(true);
50: expect(parsed.routes.length).toBeGreaterThan(0);
51:
52: // Check structure of first route
53: const firstRoute = parsed.routes[0];
54: expect(firstRoute).toHaveProperty("name");
55: expect(firstRoute).toHaveProperty("brief");
56: expect(firstRoute).toHaveProperty("commands");
57: });
58:
59: test("full tree contains known routes", async () => {
60: const output = await ...
Found 5 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/dashboard/list.test.ts:
Line 262: test("shows empty state message when no dashboards exist", async () => {
Line 278: // --web flag
Line 281: test("--web flag opens browser instead of listing", async () => {
Line 286: await func.call(context, defaultFlags({ web: true }));
Line 626: test("decodes empty string to all undefined", () => {
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/dashboard/list.test.ts</path>
<type>file</type>
<content>
270: const func = await listCommand.loader();
271: await func.call(context, defaultFlags());
272:
273: const output = stdoutWrite.mock.calls.map((c) => c[0]).join("");
274: expect(output).toContain("No dashboards found.");
275: });
276:
277: // -------------------------------------------------------------------------
278: // --web flag
279: // -------------------------------------------------------------------------
280:
281: test("--web flag opens browser instead of listing", async () => {
282: resolveOrgSpy.mockResolvedValue({ org: "test-org" });
283:
284: const { context } = createMockContext();
285: const func = await listCommand.loader();
286: await func.call(context, defaultFlags({ web: true }));
287:
288: expect(openInBrowserSpy).toHaveBeenCalled();
289: ...
Found 6 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/local/run.test.ts:
Line 5: * exit code propagation, auto-detection, --verify, --timeout, and error cases.
Line 103: test("throws ValidationError when no command and no auto-detect", async () => {
Line 117: "No command provided and could not auto-detect"
Line 137: test("auto-detects dev command from package.json", async () => {
Line 146: // No args provided — should auto-detect and run "echo hello"
Line 153: // If we get here without throwing, auto-detection worked and
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/local/run.test.ts</path>
<type>file</type>
<content>
90: stdout: { write: vi.fn(() => true) },
91: stderr: { write: vi.fn(() => true) },
92: cwd: cwd ?? tmpDir,
93: };
94: }
95:
96: describe("sentry local run", () => {
97: beforeEach(() => {
98: spawnCapture.args = undefined;
99: spawnCapture.env = undefined;
100: spawnCapture.stdio = undefined;
101: });
102:
103: test("throws ValidationError when no command and no auto-detect", async () => {
104: const func = (await runCommand.loader()) as unknown as RunFunc;
105: const ctx = makeContext();
106: try {
107: await func.call(ctx, {
108: port: 0,
109: host: "localhost",
110: verify: false,
111: timeout: 0,
112: });
113: expect.unreachable("should have thrown");
114: } catch (err) {
115: expect(err).toBeInstanceOf(ValidationError);
116: expect((err as ...
Found 2 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/react-native/xcode.test.ts:
Line 4: * The build-script spawn, sourcemap upload, org/project resolution, and debug-id
Line 70: await func.call(createContext(env), { "build-script": script, ...flags });
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/react-native/xcode.test.ts</path>
<type>file</type>
<content>
45: env,
46: process: { ...process, execPath: "/usr/bin/sentry", exitCode: undefined },
47: } as unknown as Parameters<
48: Awaited<ReturnType<typeof xcodeCommand.loader>>
49: >[0];
50: }
51:
52: beforeEach(() => {
53: dir = mkdtempSync(join(tmpdir(), "rn-xcode-"));
54: script = join(dir, "react-native-xcode.sh");
55: writeFileSync(script, "#!/bin/sh\ntrue\n");
56: spawnMock.mockClear();
57: vi.spyOn(resolveTarget, "resolveOrgAndProject").mockResolvedValue({
58: org: "acme",
59: project: "mobile",
60: });
61: vi.spyOn(sourcemaps, "uploadSourcemaps").mockResolvedValue(undefined);
62: });
63: afterEach(() => {
64: vi.restoreAllMocks();
65: rmSync(dir, { recursive: true, force: true });
66: });
67:
68: async function runXcode(env: NodeJS.ProcessEnv, flags = {}): Promise<void> {
69: const func = await ...
Found 15 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/debug-files/upload.test.ts:
Line 154: test("no paths exits non-zero", async () => {
Line 159: test("--wait and --wait-for together exits non-zero", async () => {
Line 171: test("unknown --type exits non-zero", async () => {
Line 182: // ── --derived-data ───────────────────────────────────────────────
Line 184: test("--derived-data is additive: explicit paths still scan", async () => {
Line 188: "--derived-data",
Line 199: "--derived-data alone on non-macOS exits non-zero (no scan targets)",
Line 201: const { exitCode } = await runUpload(["--derived-data", "--no-upload"]);
Line 301: test("--require-all with a missing id exits non-zero", async () => {
Line 355: test("server maxFileSize gating all files exits non-zero with a clear error", async () => {
Line 380: test("a partial size-drop still uploads the rest but exits non-zero", async () => ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/debug-files/upload.test.ts</path>
<type>file</type>
<content>
130: stdout: {
131: write(data: string | Uint8Array) {
132: output +=
133: typeof data === "string" ? data : new TextDecoder().decode(data);
134: return true;
135: },
136: },
137: stderr: {
138: write(data: string | Uint8Array) {
139: error +=
140: typeof data === "string" ? data : new TextDecoder().decode(data);
141: return true;
142: },
143: },
144: stdin: process.stdin,
145: };
146:
147: await run(app, ["debug-files", "upload", ...args], mockContext);
148: return { output, error, exitCode: mockContext.process.exitCode };
149: }
150:
151: describe("sentry debug-files upload", () => {
152: // ── Input validation ─────────────────────────────────────────────
153:
154: test("no paths exits non-zero", async () => {
155: const { exitCode } = await ...
Found 2 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/debug-files/upload.ts:
Line 81: function collectScanPaths(paths: string[], derivedData: boolean): string[] {
Line 664: const scanTargets = collectScanPaths(paths, Boolean(flags["derived-data"]));
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/debug-files/upload.ts</path> <type>file</type> <content> 65: /** Relative path to Xcode's DerivedData folder under the user's home dir. */ 66: const DERIVED_DATA_SUBPATH = "Library/Developer/Xcode/DerivedData"; 67: 68: /** 69: * Resolve the effective scan paths, optionally appending Xcode's DerivedData 70: * folder when `--derived-data` is set. 71: * 72: * DerivedData only exists on macOS; on other platforms the flag is a no-op 73: * (with a warning). The folder is appended only when it actually exists, so the 74: * stricter `scanPaths` existence check (which throws on a missing explicit 75: * path) is never tripped by an absent DerivedData directory. 76: * 77: * @param paths - Positional paths supplied on the command line. 78: * @param derivedData - Whether `--derived-data` was passed. 79: * @returns The effective list of paths to scan. ...
Found 2 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/debug-files/find.test.ts:
Line 87: test("exits successfully when there is nothing to find (no ids)", async () => {
Line 97: test("exits 1 with a missing hint when nothing matches", async () => {
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/debug-files/find.test.ts</path>
<type>file</type>
<content>
75: expect(parsed.matches).toHaveLength(1);
76: expect(parsed.matches[0]).toMatchObject({
77: type: "breakpad",
78: id: BREAKPAD_ID,
79: });
80: // A breakpad match does not satisfy the request.
81: expect(parsed.missing.map((m: { id: string }) => m.id)).toContain(
82: BREAKPAD_ID
83: );
84: expect(exitCode).toBe(1);
85: });
86:
87: test("exits successfully when there is nothing to find (no ids)", async () => {
88: const { exitCode } = await runFind(["--no-cwd", "--no-well-known"]);
89: expect(exitCode ?? 0).toBe(0);
90: });
91:
92: test("rejects an unknown --type", async () => {
93: const { exitCode } = await runFind([BREAKPAD_ID, "--type", "bogus"]);
94: expect(exitCode).not.toBe(0);
95: });
96:
97: test("exits 1 with a missing hint when nothing matches", async () => {
98: ...
No files found
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/schema.test.ts</path>
<type>file</type>
<content>
1: /**
2: * Schema Command Tests
3: *
4: * Covers resolveResourceQuery — in particular the no-match paths that used to
5: * dump the full resource list (byte-identical to a successful browse) instead
6: * of reporting that nothing matched. See getsentry/cli#1424.
7: */
8:
9: import { describe, expect, test } from "vitest";
10: import { resolveResourceQuery } from "../../src/commands/schema.js";
11: import { OutputError, ResolutionError } from "../../src/lib/errors.js";
12:
13: describe("resolveResourceQuery", () => {
14: test("returns endpoints for a known resource", () => {
15: const result = resolveResourceQuery("issues");
16: expect(result.kind).toBe("endpoints");
17: if (result.kind === "endpoints") {
18: expect(result.endpoints.length).toBeGreaterThan(0);
19: for (const ep of result.endpoints) {
20: ...
Found 2 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/cli/defaults.test.ts:
Line 181: describe("empty string validation", () => {
Line 393: test("show action with empty defaults", () => {
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/cli/defaults.test.ts</path>
<type>file</type>
<content>
1: /**
2: * Tests for `sentry cli defaults` command.
3: *
4: * Verifies show/set/clear/clear-all modes, validation, formatter output,
5: * and the telemetry/URL integration points.
6: */
7:
8: import chalk from "chalk";
9: import { describe, expect, test } from "vitest";
10: import {
11: clearAllDefaults,
12: getAgentSkillsPreference,
13: getAllDefaults,
14: getDefaultHeaders,
15: getDefaultOrganization,
16: getDefaultProject,
17: getDefaultUrl,
18: getTelemetryPreference,
19: setAgentSkillsPreference,
20: setDefaultOrganization,
21: setDefaultProject,
22: setDefaultUrl,
23: setTelemetryPreference,
24: } from "../../../src/lib/db/defaults.js";
25: import { getDatabase } from "../../../src/lib/db/index.js";
26: import { formatDefaultsResult } from "../../../src/lib/formatters/human.js";
27: import { stripAnsi } from ...
Found 12 matches /home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/cli.test.ts: Line 75: "Please provide a feedback message." Line 87: "Please provide a feedback message." /home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/auth/login.test.ts: Line 10: * to stub node:tty (so isatty(0) returns true) and the logger module (so Line 16: // Mock isatty to simulate interactive terminal for the re-auth prompt path. Line 24: isatty: _mockIsatty, Line 531: * Uses the module-level `vi.mock()` on node:tty (so `isatty(0)` returns /home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/project/delete.test.ts: Line 13: // Mock isatty so deleteCommand's non-interactive guard passes. Line 21: isatty: _mockIsatty, Line 229: // isatty(0) returns false in test environments (non-TTY) Line 414: * (so `isatty(0)` returns true) and the logger (so `.prompt()` returns ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/cli.test.ts</path>
<type>file</type>
<content>
35: return true;
36: }) as typeof process.stderr.write;
37:
38: const context = {
39: process: { execPath: overrides.execPath ?? "/test/path/sentry" },
40: stdout: {
41: write: (s: string) => {
42: stdoutChunks.push(s);
43: return true;
44: },
45: },
46: stderr: {
47: write: (s: string) => {
48: errors.push(s);
49: return true;
50: },
51: },
52: };
53:
54: return {
55: context,
56: getStderr: () => stderrChunks.join(""),
57: getStdout: () => stdoutChunks.join(""),
58: errors,
59: restore: () => {
60: process.stderr.write = origWrite;
61: },
62: };
63: }
64:
65: describe("feedbackCommand.func", () => {
66: test("throws ValidationError for empty message", async () => {
67: // Access func through loader
68: const func = await ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/send-envelope.test.ts</path>
<type>file</type>
<content>
1: /**
2: * Tests for `sentry send-envelope` deprecation shim.
3: */
4:
5: import { beforeEach, describe, expect, test, vi } from "vitest";
6: import { sendEnvelopeCommand } from "../../src/commands/send-envelope.js";
7: import { CliError } from "../../src/lib/errors.js";
8: import { useTestConfigDir } from "../helpers.js";
9:
10: useTestConfigDir("send-envelope-");
11:
12: function makeContext() {
13: return {
14: stdout: { write: vi.fn(() => true) },
15: stderr: { write: vi.fn(() => true) },
16: cwd: "/tmp",
17: };
18: }
19:
20: describe("sendEnvelopeCommand (deprecation shim)", () => {
21: let func: Awaited<ReturnType<typeof sendEnvelopeCommand.loader>>;
22:
23: beforeEach(async () => {
24: func = await sendEnvelopeCommand.loader();
25: });
26:
27: test("throws CliError suggesting event send --raw", async () => {
28: ...
Found 7 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/monitor/run.test.ts:
Line 13: import { CliError, ValidationError } from "../../../src/lib/errors.js";
Line 143: test("missing command throws ValidationError", async () => {
Line 147: ).rejects.toBeInstanceOf(ValidationError);
Line 150: test("missing monitor slug throws ValidationError", async () => {
Line 154: ).rejects.toBeInstanceOf(ValidationError);
Line 157: test("dependent flag without --schedule throws ValidationError", async () => {
Line 168: ).rejects.toBeInstanceOf(ValidationError);
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/monitor/run.test.ts</path>
<type>file</type>
<content>
125: dsn: SAAS_DSN,
126: environment: "production",
127: schedule: "0 * * * *",
128: "max-runtime": 30,
129: },
130: "scheduled-job",
131: NODE,
132: "-e",
133: "process.exit(0)"
134: );
135:
136: const openBody = sendSpy.mock.calls[0]?.[1] as string;
137: const closeBody = sendSpy.mock.calls[1]?.[1] as string;
138: expect(openBody).toContain('"monitor_config"');
139: expect(openBody).toContain('"0 * * * *"');
140: expect(closeBody).not.toContain('"monitor_config"');
141: });
142:
143: test("missing command throws ValidationError", async () => {
144: const { ctx } = makeContext();
145: await expect(
146: func.call(ctx, { dsn: SAAS_DSN, environment: "production" }, "my-job")
147: ).rejects.toBeInstanceOf(ValidationError);
148: });
149:
150: ...
No files found
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/docs.test.ts</path>
<type>file</type>
<content>
1: import { buildApplication, run } from "@stricli/core";
2: import { beforeEach, describe, expect, test, vi } from "vitest";
3: import { docsRoute } from "../../src/commands/docs/index.js";
4: import type { SentryContext } from "../../src/context.js";
5:
6: const { detectDocsContext, listDocs, queryDocs, withProgress } = vi.hoisted(
7: () => ({
8: detectDocsContext: vi.fn(),
9: listDocs: vi.fn(),
10: queryDocs: vi.fn(),
11: withProgress: vi.fn(),
12: })
13: );
14:
15: vi.mock("../../src/lib/docs-context.js", () => ({ detectDocsContext }));
16: vi.mock("../../src/lib/docs-service.js", () => ({ listDocs, queryDocs }));
17: vi.mock("../../src/lib/polling.js", () => ({ withProgress }));
18:
19: import { listCommand } from "../../src/commands/docs/list.js";
20: import { queryCommand } from "../../src/commands/docs/query.js";
21:
22: function ...
Found 71 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/dashboard/widget/edit.test.ts:
Line 25: import { ValidationError } from "../../../../src/lib/errors.js";
Line 165: test("throws ValidationError when neither --index nor --title provided", async () => {
Line 172: expect(err).toBeInstanceOf(ValidationError);
Line 176: test("throws ValidationError for invalid aggregate", async () => {
Line 183: expect(err).toBeInstanceOf(ValidationError);
Line 349: test("throws ValidationError for col out of range", async () => {
Line 355: expect(err).toBeInstanceOf(ValidationError);
Line 359: test("throws ValidationError for negative width", async () => {
Line 365: expect(err).toBeInstanceOf(ValidationError);
Line 369: test("throws ValidationError when --col overflows with fallback width on layoutless widget", async () => {
Line 396: expect(err).toBeInstanceOf(ValidationError);
Line 400: test("throws ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/dashboard/resolve.test.ts</path>
<type>file</type>
<content>
65: ])
66: );
67: });
68:
69: // biome-ignore lint/performance/noNamespaceImport: needed for spyOn mocking
70: import * as resolveTarget from "../../../src/lib/resolve-target.js";
71:
72: // ---------------------------------------------------------------------------
73: // parseDashboardPositionalArgs
74: // ---------------------------------------------------------------------------
75:
76: describe("parseDashboardPositionalArgs", () => {
77: test("throws ValidationError for empty args", () => {
78: expect(() => parseDashboardPositionalArgs([])).toThrow(ValidationError);
79: });
80:
81: test("error message contains 'Dashboard ID or title'", () => {
82: try {
83: parseDashboardPositionalArgs([]);
84: expect.unreachable("Should have thrown");
85: } catch (error) {
86: ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/dashboard/widget/add.test.ts</path>
<type>file</type>
<content>
175: test("human output contains 'Added widget' and title", async () => {
176: const { context, stdoutWrite } = createMockContext();
177: const func = await addCommand.loader();
178: await func.call(
179: context,
180: { json: false, display: "line", query: ["count"] },
181: "123",
182: "Error Rate"
183: );
184:
185: const output = stdoutWrite.mock.calls.map((c) => c[0]).join("");
186: expect(output).toContain("Added widget");
187: expect(output).toContain("Error Rate");
188: });
189:
190: test("throws ValidationError when title is missing (less than 2 positional args)", async () => {
191: const { context } = createMockContext();
192: const func = await addCommand.loader();
193:
194: const err = await func
195: .call(context, { json: false, display: "line" }, "123")
196: ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/dashboard/create.test.ts</path>
<type>file</type>
<content>
115:
116: const output = stdoutWrite.mock.calls.map((c) => c[0]).join("");
117: const parsed = JSON.parse(output);
118: expect(parsed.id).toBe("123");
119: expect(parsed.title).toBe("My Dashboard");
120: expect(parsed.url).toContain("dashboard/123");
121: });
122:
123: test("human output contains 'Created dashboard' and title", async () => {
124: const { context, stdoutWrite } = createMockContext();
125: const func = await createCommand.loader();
126: await func.call(context, { json: false }, "My Dashboard");
127:
128: const output = stdoutWrite.mock.calls.map((c) => c[0]).join("");
129: expect(output).toContain("Created dashboard");
130: expect(output).toContain("My Dashboard");
131: });
132:
133: test("throws ValidationError when title is missing", async () => {
134: const { context } = ...
Found 25 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/trace/view.test.ts:
Line 79: test("returns empty args unchanged", () => {
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/trace/view.property.test.ts:
Line 20: import { ContextError, ValidationError } from "../../../src/lib/errors.js";
Line 115: test("empty args always throws ContextError", () => {
Line 116: expect(() => parseTraceTarget([], HINT)).toThrow(ContextError);
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/trace/view.func.test.ts:
Line 48: ContextError,
Line 278: test("opens browser when --web flag is set", async () => {
Line 291: // Should NOT call getDetailedTrace when using --web
Line 336: test("throws ContextError when auto-detect cannot resolve a target", async () => {
Line 341: new ContextError("Organization and project", "sentry trace view <id>")
Line 353: ).rejects.toThrow(ContextError);
Line ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/trace/view.property.test.ts</path>
<type>file</type>
<content>
105: property(tuple(slugArb, traceIdArb), ([target, traceId]) => {
106: const args = [target, traceId];
107: const result1 = parseTraceTarget(args, HINT);
108: const result2 = parseTraceTarget(args, HINT);
109: expect(result1).toEqual(result2);
110: }),
111: { numRuns: DEFAULT_NUM_RUNS }
112: );
113: });
114:
115: test("empty args always throws ContextError", () => {
116: expect(() => parseTraceTarget([], HINT)).toThrow(ContextError);
117: });
118:
119: test("result always has traceId property defined", async () => {
120: await fcAssert(
121: property(traceIdArb, (traceId) => {
122: const result = parseTraceTarget([traceId], HINT);
123: expect(result.traceId).toBeDefined();
124: expect(typeof result.traceId).toBe("string");
125: }),
126: { ...
Found 45 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/span/list.test.ts:
Line 100: test("no args → project mode", () => {
Line 558: test("calls listSpans without trace filter when no trace ID given", async () => {
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/span/view.test.ts:
Line 29: import { ContextError, ValidationError } from "../../../src/lib/errors.js";
Line 117: test("slash-separated target is deferred intact", () => {
Line 118: const slashForm = `my-org/my-project/${VALID_TRACE_ID}`;
Line 119: const result = parsePositionalArgs([slashForm, VALID_SPAN_ID]);
Line 122: expect(result.rawTraceArg).toBe(slashForm);
Line 126: test("slash-separated target with multiple span IDs", () => {
Line 127: const slashForm = `my-org/my-project/${VALID_TRACE_ID}`;
Line 129: slashForm,
Line 135: expect(result.rawTraceArg).toBe(slashForm);
Line 140: ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/span/list.test.ts</path>
<type>file</type>
<content>
85:
86: test("throws for invalid value", () => {
87: expect(() => parseSort("name")).toThrow("Invalid sort value");
88: });
89:
90: test("throws for empty string", () => {
91: expect(() => parseSort("")).toThrow("Invalid sort value");
92: });
93: });
94:
95: // ============================================================================
96: // parseSpanListArgs — positional argument disambiguation
97: // ============================================================================
98:
99: describe("parseSpanListArgs", () => {
100: test("no args → project mode", () => {
101: const result = parseSpanListArgs([]);
102: expect(result).toEqual({ mode: "project" });
103: });
104:
105: test("org/project → project mode with target", () => {
106: const result = parseSpanListArgs(["my-org/my-project"]);
107: ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/span/view.test.ts</path>
<type>file</type>
<content>
135: expect(result.rawTraceArg).toBe(slashForm);
136: expect(result.rawSpanIds).toEqual([VALID_SPAN_ID, VALID_SPAN_ID_2]);
137: });
138: });
139:
140: describe("auto-split traceId/spanId single-arg format", () => {
141: test("auto-splits traceId/spanId single-arg format (resolved path)", () => {
142: const result = parsePositionalArgs([
143: "aaaa1111bbbb2222cccc3333dddd4444/a1b2c3d4e5f67890",
144: ]);
145: expect(result.kind).toBe("resolved");
146: if (result.kind !== "resolved") throw new Error("unreachable");
147: expect(result.traceTarget.traceId).toBe(
148: "aaaa1111bbbb2222cccc3333dddd4444"
149: );
150: expect(result.traceTarget.type).toBe("auto-detect");
151: expect(result.rawSpanIds).toEqual(["a1b2c3d4e5f67890"]);
152: });
153:
154: test("auto-splits with ...
Found 43 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/log/view.func.test.ts:
Line 39: import { ContextError, ResolutionError } from "../../../src/lib/errors.js";
Line 292: describe("--web flag", () => {
Line 303: // Should NOT fetch logs when using --web
Line 346: test("org/ target (org-all) throws ContextError", async () => {
Line 354: expect(error).toBeInstanceOf(ContextError);
Line 355: expect((error as ContextError).message).toContain("Specific project");
Line 385: test("throws ContextError when auto-detect returns null", async () => {
Line 395: expect(error).toBeInstanceOf(ContextError);
Line 396: expect((error as ContextError).message).toContain(
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/log/view.property.test.ts:
Line 17: import { ContextError } from "../../../src/lib/errors.js";
Line 50: test("single arg with one slash: throws ContextError ...
Found 42 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/log/list.test.ts:
Line 370: await func.call(context, BATCH_FLAGS, `${ORG}/${PROJECT}`);
Line 388: await func.call(context, BATCH_FLAGS, `${ORG}/${PROJECT}`);
Line 423: await func.call(context, HUMAN_FLAGS, `${ORG}/${PROJECT}`);
Line 435: await func.call(context, HUMAN_FLAGS, `${ORG}/${PROJECT}`);
Line 449: await func.call(context, HUMAN_FLAGS, `${ORG}/${PROJECT}`);
Line 462: await func.call(context, { json: false, limit: 3 }, `${ORG}/${PROJECT}`);
Line 474: await func.call(context, HUMAN_FLAGS, `${ORG}/${PROJECT}`);
Line 540: await func.call(context, { json: true, limit: 3 }, `${ORG}/${PROJECT}`);
Line 553: await func.call(context, BATCH_FLAGS, `${ORG}/${PROJECT}`);
Line 595: await func.call(context, BATCH_FLAGS, TRACE_ID);
Line 616: func.call(context, { ...BATCH_FLAGS, query: "bad:::query" }, TRACE_ID)
Line 629: ...
Found 23 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/event/view.test.ts:
Line 57: ContextError,
Line 184: // parseSlashSeparatedArg will throw ContextError as expected.
Line 233: test("throws ContextError for empty args", () => {
Line 234: expect(() => parsePositionalArgs([])).toThrow(ContextError);
Line 237: test("throws ContextError with usage hint", () => {
Line 242: expect(error).toBeInstanceOf(ContextError);
Line 243: expect((error as ContextError).message).toContain("Event ID");
Line 271: test("bare 'latest' (single arg) throws ContextError", () => {
Line 272: expect(() => parsePositionalArgs(["latest"])).toThrow(ContextError);
Line 275: test("'latest' as second arg throws ContextError", () => {
Line 277: ContextError
Line 286: expect(error).toBeInstanceOf(ContextError);
Line 287: expect((error as ContextError).message).toContain("Issue ...
Found 6 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/replay/view.test.ts:
Line 40: ContextError,
Line 131: test("throws ContextError for org/project with no replay ID", () => {
Line 132: expect(() => parsePositionalArgs(["test-org/cli"])).toThrow(ContextError);
Line 256: test("opens the replay in the browser with --web", async () => {
Line 273: test("opens the replay URL target from a replay URL with --web", async () => {
Line 290: test("converts missing replays into ResolutionError", async () => {
Found 13 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/proguard/upload.test.ts:
Line 17: import { ContextError, ValidationError } from "../../../src/lib/errors.js";
Line 21: "no-upload"?: boolean;
Line 22: "require-one"?: boolean;
Line 69: test("no paths: throws ContextError", async () => {
Line 75: expect(err).toBeInstanceOf(ContextError);
Line 79: test("no paths with --require-one: throws ValidationError", async () => {
Line 82: await func.call(ctx, { "require-one": true });
Line 86: expect((err as Error).message).toContain("--require-one");
Line 148: // ── --no-upload (dry-run) ────────────────────────────────────────
Line 150: test("--no-upload: succeeds without uploading", async () => {
Line 155: await func.call(ctx, { "no-upload": true }, f);
Line 161: test("--no-upload: does not require credentials", async () => {
Line 171: func.call(ctx, { "no-upload": true }, f)
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/proguard/upload.test.ts</path>
<type>file</type>
<content>
55:
56: afterEach(() => {
57: rmSync(dir, { recursive: true, force: true });
58: for (const [k, v] of Object.entries(savedEnv)) {
59: if (v === undefined) {
60: delete process.env[k];
61: } else {
62: process.env[k] = v;
63: }
64: }
65: });
66:
67: // ── Input validation ─────────────────────────────────────────────
68:
69: test("no paths: throws ContextError", async () => {
70: const ctx = makeContext();
71: try {
72: await func.call(ctx, {});
73: expect.unreachable("should have thrown");
74: } catch (err) {
75: expect(err).toBeInstanceOf(ContextError);
76: }
77: });
78:
79: test("no paths with --require-one: throws ValidationError", async () => {
80: const ctx = makeContext();
81: try {
82: await func.call(ctx, { "require-one": true });
83: ...
No files found
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/build/upload.test.ts</path>
<type>file</type>
<content>
1: /**
2: * Tests for `sentry build upload`.
3: *
4: * Drives the command through its wrapper `loader()`. Real detection +
5: * normalization run against in-memory ZIP fixtures (a "fake APK" is a ZIP with
6: * an AndroidManifest.xml entry); the API `uploadBuild` and org/project
7: * resolution are spied so no network is touched.
8: */
9:
10: import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
11: import { tmpdir } from "node:os";
12: import { join } from "node:path";
13: import { run } from "@stricli/core";
14: import { strToU8, zipSync } from "fflate";
15: import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
16: import { app } from "../../../src/app.js";
17: import { uploadCommand } from "../../../src/commands/build/upload.js";
18: import type { SentryContext } from "../../../src/context.js";
19: // biome-ignore ...
Found 15 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/build/upload.test.ts:
Line 45: process: { ...process, exitCode: undefined } as typeof process,
Line 48: get exitCode() {
Line 49: return this.context.process.exitCode;
Line 66: async function runViaApp(
Line 68: ): Promise<{ stderr: string; exitCode: number | undefined }> {
Line 71: process: { ...process, exitCode: undefined } as typeof process,
Line 86: return { stderr, exitCode: context.process.exitCode };
Line 121: expect(harness.exitCode).toBeUndefined();
Line 177: expect(harness.exitCode).toBe(1);
Line 200: expect(harness.exitCode).toBeUndefined();
Line 214: expect(harness.exitCode).toBe(1);
Line 233: expect(harness.exitCode).toBeUndefined();
Line 246: expect(harness.exitCode).toBe(1);
Line 256: const { stderr, exitCode } = await runViaApp([apk]);
Line 260: expect(exitCode ?? 0).toBe(0);
Resume and return the missing substantive report. Read-only only; do not modify files. Inspect every packages/cli/src/commands command whose positional definition has kind: "array". Determine whether zero positional values are valid from actual function behavior, flags, tests, and docs. Stricli array cardinality is controlled only by minimum; element optional does not control cardinality. Return a concise table with command path, source file, current minimum, zero-valid yes/no, evidence, and whether adding/changing minimum would preserve or alter established behavior. Explicitly cover issue merge, project create, event send, help, and any flag-only modes. If blocked, report the exact blocker rather than returning empty.
Found 33 matches /home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/trace/view.ts: Line 484: kind: "array", /home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/trace/logs.ts: Line 130: kind: "array", /home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/issue/merge.ts: Line 276: kind: "array", /home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/help.ts: Line 36: kind: "array", /home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/event/view.ts: Line 1082: kind: "array", /home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/event/send.ts: Line 142: kind: "array", /home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/docs/query.ts: Line 40: kind: "array", /home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/docs/list.ts: Line 54: kind: "array", /home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/debug-files/upload.ts: ...
No files found
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/dashboard/resolve.ts</path>
<type>file</type>
<content>
253: export function parseDashboardListArgs(args: string[]): ListArgResult {
254: // buildListCommand's interceptSubcommand may replace args[0] with undefined
255: // when the first positional matches a subcommand name (e.g. "view", "create").
256: // Filter those out so we don't crash on .includes("/").
257: const filtered = args.filter(
258: (a): a is string => a !== null && a !== undefined && a !== ""
259: );
260: if (filtered.length === 0) {
261: return { targetArg: undefined, titleFilter: undefined };
262: }
263:
264: // URL detection — extract org or suggest `view` for dashboard-specific URLs
265: const urlResult = tryExtractListUrl(filtered[0] as string, filtered.slice(1));
266: if (urlResult) {
267: return urlResult;
268: }
269:
270: if (filtered.length >= 2) {
271: // First arg is the target, remaining args are ...
Found 11 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/react-native/xcode.ts:
Line 48: const DEFAULT_PACKAGER_URL = "http://127.0.0.1:8081/";
Line 49: const DEFAULT_BUILD_SCRIPT =
Line 118: function resolveScript(flags: XcodeFlags, cwd: string): string {
Line 119: const script = resolve(cwd, flags["build-script"] ?? DEFAULT_BUILD_SCRIPT);
Line 219: scriptArgs: string[],
Line 241: const status = runScript(script, scriptArgs, env);
Line 384: scriptArgs: string[],
Line 396: const result = runWrappedBuild(script, scriptArgs, ctx, tempDir);
Line 499: async *func(this: SentryContext, flags: XcodeFlags, ...scriptArgs: string[]) {
Line 512: const status = runScript(script, scriptArgs, this.env);
Line 520: const prep = await preparePair(this, script, scriptArgs, fetchUrl);
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/react-native/xcode.ts</path>
<type>file</type>
<content>
42: } from "../../lib/react-native/xcode-env.js";
43: import { resolveOrgAndProject } from "../../lib/resolve-target.js";
44:
45: const log = logger.withTag("react-native.xcode");
46:
47: const USAGE_HINT = "sentry react-native xcode";
48: const DEFAULT_PACKAGER_URL = "http://127.0.0.1:8081/";
49: const DEFAULT_BUILD_SCRIPT =
50: "../node_modules/react-native/scripts/react-native-xcode.sh";
51:
52: /** Matches one or more trailing slashes. */
53: const TRAILING_SLASHES = /\/+$/;
54:
55: /** Flags accepted by `react-native xcode`. */
56: type XcodeFlags = {
57: force?: boolean;
58: "allow-fetch"?: boolean;
59: "fetch-from"?: string;
60: "build-script"?: string;
61: dist?: string[];
62: wait?: boolean;
63: "wait-for"?: number;
64: "no-auto-release"?: boolean;
65: "allow-xcode-infoplist-preprocessing"?: boolean;
66: };
67:
68: /** ...
No files found
* 🟡 (15:48) [requested-audit] User requested a read-only audit of every command under `packages/cli/src/commands` whose positional definition uses `kind: "array"`; instructed not to modify files and to determine zero-positional validity from actual function behavior, flags, tests, and docs. * 🔴 (15:48) User stated Stricli array cardinality is controlled only by `minimum`; an element’s `optional…
* 🔴 (15:39) `packages/cli/test/commands/event/view.test.ts` verifies `parsePositionalArgs([])` throws `ContextError`; the usage-hint error mentions `"Event ID"`. * 🔴 (15:39) Event-view positional parsing rejects bare `"latest"`, `"latest"` as the second argument, and uppercase `"LATEST"` with `ContextError`; one tested error specifically mentions `"Issue ID"`. * 🔴 (15:39) Event-view positional…
* 🔴 (15:36) In `packages/cli/src/commands/debug-files/upload.ts`, `collectScanPaths(paths: string[], derivedData: boolean): string[]` appends `Library/Developer/Xcode/DerivedData` under `homedir()` only on macOS and only when the directory exists; otherwise it warns and returns explicit paths unchanged. * 🔴 (15:36) The `--derived-data` path handling ensures the stricter `scanPaths` existence ch…
* 🔴 (15:33) In `packages/cli/src/commands/debug-files/upload.ts`, real uploads fetch `ChunkServerOptions` before scanning and use the server-advertised positive `maxFileSize` instead of `DEFAULT_MAX_DIF_SIZE`, ensuring a file the server would reject is never read into memory. * 🔴 (15:33) Debug-file upload dry runs remain authentication-free, use `DEFAULT_MAX_DIF_SIZE`, and are purely informatio…
* 🔴 (15:32) `packages/cli/src/commands/replay/view.ts` defines `USAGE_HINT = "sentry replay view [<org>/<project>/]<replay-id> | <replay-url>"`, `MAX_ACTIVITY_EVENTS = 6`, `MAX_RELATED_ERRORS = 3`, and `MAX_RELATED_TRACES = 2`. * 🔴 (15:32) Replay-view `parseSingleArg()` accepts a bare replay ID, `<org>/<replay-id>`, `<org>/<project>/<replay-id>`, or Sentry replay URL. It handles the one-slash `…
* 🔴 (15:30) `packages/cli/src/commands/span/list.ts` defines valid `--sort` values as `["date", "duration"]`, with `DEFAULT_SORT = "date"`, `DEFAULT_PERIOD = "7d"`, trace pagination key `PAGINATION_KEY = "span-list"`, project pagination key `PROJECT_PAGINATION_KEY = "span-search"`, and trace usage hint `sentry span list [<org>/<project>/]<trace-id>`. * 🔴 (15:30) `parseSpanListArgs()` is a thin …
* 🔴 (15:29) `packages/cli/src/commands/dashboard/revisions.ts` defines `revisionsCommand` for cursor-paginated dashboard revision history. It resolves `[<org/project>] <dashboard-id-or-title>` through `parseDashboardPositionalArgs()`, `parseOrgProjectArg()`, `resolveOrgFromTarget()`, and `resolveDashboardId()`. * 🔴 (15:29) Dashboard revisions use pagination key `dashboard-revisions`, context `$…
* 🔴 (15:28) `packages/cli/src/commands/cli/defaults.ts` defines unauthenticated `defaultsCommand` for viewing and managing persistent CLI defaults. Recognized keys are `org`, `project`, `telemetry`, `agent-skills`, `graphics`, `url`, `headers`, and `ca-cert`; key aliases are accepted through `KEY_ALIASES`. * 🔴 (15:28) `defaultsCommand` accepts at most 2 positional arguments, `<key> [<value>]`; …
* 🔴 (15:27) In the issue-merge command, `--into` always designates an issue that participates in the merge as the preferred parent; it is appended to the positional issue list before resolution. * 🔴 (15:27) Issue-merge parent selection is advisory: resolved issues are pre-sorted with the requested parent first to influence API tie-breaking, but event count takes precedence and Sentry may still …
Date: Sep 10, 2026 * 🔴 (15:26) `packages/cli/src/commands/help.ts` defines unauthenticated `helpCommand`: `sentry help`/no args yields `new CommandOutput(introspectAllCommands())`; `sentry help <command>` uses `introspectCommand(commandPath)`; invalid paths throw `new OutputError(result)`. * 🔴 (15:26) User stated `--json` mode in `packages/cli/src/commands/help.ts` always gets structured output…
Date: Sep 10, 2026 * 🔴 (15:26) `packages/cli/package.json` defines package `sentry` version `0.45.0-dev.0`, description `Sentry CLI - A command-line interface for using Sentry built by robots and humans for robots and humans`, license `FSL-1.1-Apache-2.0`, repository `git+https://github.com/getsentry/cli.git`, and `"type": "module"`. * 🔴 (15:26) `packages/cli/package.json` entrypoints are `"mai…
Date: Sep 10, 2026 * 🔴 (15:25) Repository CLI design states `org view` and `project view` mirror `gh repo view`: each works from detected DSN context or with an explicit argument. * 🔴 (15:25) Repository CLI design states missing-context errors must use the `ContextError` class. * 🔴 (15:25) Repository conventions specify Node.js APIs/helpers by task: `await readFile(path, "utf-8")` and `await w…
Date: Sep 10, 2026 * 🔴 [enforced-workflow] (15:25) User stated repository workflow requires loading `repo-setup` before situation skills. * 🟡 (15:25) Attempt to load skill `repo-setup` failed because it was not found; available skills were `ast-grep`, `customize-opencode`, `jj-create-pr`, `jj-guide`, `jj-update-pr`, and `jj-workflow`. * 🔴 [enforced-workflow] (15:25) User stated to always check…
Date: Sep 10, 2026 * 🔴 [enforced-read-only] (15:24) User required read-only exploration of `/home/byk/Code/getsentry/cli-pr-1558` and explicitly prohibited modifying files. * 🟡 [requested-code-audit] (15:24) User asked to inspect every source command under `packages/cli/src/commands` whose positional configuration has `kind: "array"`—33 matches total—and determine each command’s runtime minimum…