Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ Edit an issue alert rule
| `triggers` | object \| null | Conditions on which the alert triggers |
| `actionFilters` | array \| null | Filters to run before actions fire, each with the actions to fire |
| `environment` | string \| null | Name of the environment the alert is limited to. Null for all environments |
| `config` | object | Configuration of the alert, such as frequency in minutes |
| `config` | unknown | Configuration of the alert, such as frequency in minutes |
| `detectorIds` | array \| null | IDs of the monitors connected to the alert |
| `enabled` | boolean | Whether the alert is enabled |
| `lastTriggered` | string \| null | When the alert last fired (ISO 8601) |
Expand Down Expand Up @@ -402,7 +402,7 @@ Edit a metric alert rule
| `dateUpdated` | string | When the monitor was last updated (ISO 8601) |
| `dataSources` | array \| null | Data sources the monitor evaluates, such as a query subscription |
| `conditionGroup` | object \| null | Conditions that decide the monitor's status |
| `config` | object | Configuration of the monitor, which depends on its type |
| `config` | object \| unknown | |
| `enabled` | boolean | Whether the monitor is enabled |
| `org` | string | Organization slug |
| `status` | string | Rule status (active, disabled) |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ View details of one or more events
| `packages` | object | Modules loaded when the event occurred, keyed by module name with their versions |
| `type` | string | Event type, such as error, default or transaction |
| `metadata` | object | Event metadata |
| `occurrence` | object \| null | |
| `occurrence` | object \| unknown \| null | |
| `_meta` | object | Metadata about changes Sentry made to the event's fields, such as data scrubbing or trimming |
| `user` | object \| null | User context of the event |
| `tags` | array | Tags attached to the event |
| `contexts` | object \| null | Contexts of the event, such as device, os, browser and runtime |
| `contexts` | object \| null | Contexts of the event, such as device, os, browser and runtime, keyed by alias |
| `sdk` | object \| null | SDK that sent the event |
| `context` | object \| null | Additional data sent with the event in its extra field |
| `errors` | array | Errors Sentry found while processing the event |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ List releases with adoption and health metrics
| `version` | string | Release version |
| `shortVersion` | string | Shortened release version |
| `versionInfo` | object \| null | Parsed version information |
| `status` | string | Release status (open or archived) |
| `status` | string | Release status |
| `ref` | string \| null | Version control reference, such as a commit SHA or tag |
| `url` | string \| null | Release URL |
| `dateCreated` | string \| null | When the release was created (ISO 8601) |
Expand All @@ -53,7 +53,7 @@ List releases with adoption and health metrics
| `authors` | array | Authors of the release's commits |
| `owner` | object \| null | Release owner |
| `projects` | array | Projects in the release |
| `adoptionStages` | object \| null | Adoption stage of the release in each project |
| `adoptionStages` | object \| null | Adoption stage of the release in each project, keyed by project slug |
| `orgSlug` | string | Organization slug |
| `targetProject` | string | Project slug, when listing several |

Expand Down Expand Up @@ -106,7 +106,7 @@ View release details with health metrics
| `version` | string | Release version |
| `shortVersion` | string | Shortened release version |
| `versionInfo` | object \| null | Parsed version information |
| `status` | string | Release status (open or archived) |
| `status` | string | Release status |
| `ref` | string \| null | Version control reference, such as a commit SHA or tag |
| `url` | string \| null | Release URL |
| `dateCreated` | string \| null | When the release was created (ISO 8601) |
Expand All @@ -121,7 +121,7 @@ View release details with health metrics
| `authors` | array | Authors of the release's commits |
| `owner` | object \| null | Release owner |
| `projects` | array | Projects in the release |
| `adoptionStages` | object \| null | Adoption stage of the release in each project |
| `adoptionStages` | object \| null | Adoption stage of the release in each project, keyed by project slug |

**Examples:**

Expand Down Expand Up @@ -164,7 +164,7 @@ Create a release
| `version` | string | Release version |
| `shortVersion` | string | Shortened release version |
| `versionInfo` | object \| null | Parsed version information |
| `status` | string | Release status (open or archived) |
| `status` | string | Release status |
| `ref` | string \| null | Version control reference, such as a commit SHA or tag |
| `url` | string \| null | Release URL |
| `dateCreated` | string \| null | When the release was created (ISO 8601) |
Expand All @@ -179,7 +179,7 @@ Create a release
| `authors` | array | Authors of the release's commits |
| `owner` | object \| null | Release owner |
| `projects` | array | Projects in the release (only slug with --dry-run) |
| `adoptionStages` | object \| null | Adoption stage of the release in each project |
| `adoptionStages` | object \| null | Adoption stage of the release in each project, keyed by project slug |
| `dryRun` | boolean | True when --dry-run made no change |

**Examples:**
Expand Down Expand Up @@ -236,7 +236,7 @@ Finalize a release
| `version` | string | Release version |
| `shortVersion` | string | Shortened release version |
| `versionInfo` | object \| null | Parsed version information |
| `status` | string | Release status (open or archived) |
| `status` | string | Release status |
| `ref` | string \| null | Version control reference, such as a commit SHA or tag |
| `url` | string \| null | Release URL |
| `dateCreated` | string \| null | When the release was created (ISO 8601) |
Expand All @@ -251,7 +251,7 @@ Finalize a release
| `authors` | array | Authors of the release's commits |
| `owner` | object \| null | Release owner |
| `projects` | array | Projects in the release |
| `adoptionStages` | object \| null | Adoption stage of the release in each project |
| `adoptionStages` | object \| null | Adoption stage of the release in each project, keyed by project slug |
| `dryRun` | boolean | True when --dry-run made no change |
| `org` | string | Organization slug (--dry-run) |
| `released` | string | Release date to set (--dry-run) |
Expand Down Expand Up @@ -332,7 +332,7 @@ Archive a release
| `version` | string | Release version |
| `shortVersion` | string | Shortened release version |
| `versionInfo` | object \| null | Parsed version information |
| `status` | string | Release status (open or archived) |
| `status` | string | Release status |
| `ref` | string \| null | Version control reference, such as a commit SHA or tag |
| `url` | string \| null | Release URL |
| `dateCreated` | string \| null | When the release was created (ISO 8601) |
Expand All @@ -347,7 +347,7 @@ Archive a release
| `authors` | array | Authors of the release's commits |
| `owner` | object \| null | Release owner |
| `projects` | array | Projects in the release |
| `adoptionStages` | object \| null | Adoption stage of the release in each project |
| `adoptionStages` | object \| null | Adoption stage of the release in each project, keyed by project slug |
| `dryRun` | boolean | True when --dry-run made no change |
| `org` | string | Organization slug (--dry-run) |

Expand Down Expand Up @@ -385,7 +385,7 @@ Restore an archived release
| `version` | string | Release version |
| `shortVersion` | string | Shortened release version |
| `versionInfo` | object \| null | Parsed version information |
| `status` | string | Release status (open or archived) |
| `status` | string | Release status |
| `ref` | string \| null | Version control reference, such as a commit SHA or tag |
| `url` | string \| null | Release URL |
| `dateCreated` | string \| null | When the release was created (ISO 8601) |
Expand All @@ -400,7 +400,7 @@ Restore an archived release
| `authors` | array | Authors of the release's commits |
| `owner` | object \| null | Release owner |
| `projects` | array | Projects in the release |
| `adoptionStages` | object \| null | Adoption stage of the release in each project |
| `adoptionStages` | object \| null | Adoption stage of the release in each project, keyed by project slug |
| `dryRun` | boolean | True when --dry-run made no change |
| `org` | string | Organization slug (--dry-run) |

Expand Down Expand Up @@ -529,7 +529,7 @@ Set commits for a release
| `version` | string | Release version |
| `shortVersion` | string | Shortened release version |
| `versionInfo` | object \| null | Parsed version information |
| `status` | string | Release status (open or archived) |
| `status` | string | Release status |
| `ref` | string \| null | Version control reference, such as a commit SHA or tag |
| `url` | string \| null | Release URL |
| `dateCreated` | string \| null | When the release was created (ISO 8601) |
Expand All @@ -544,7 +544,7 @@ Set commits for a release
| `authors` | array | Authors of the release's commits |
| `owner` | object \| null | Release owner |
| `projects` | array | Projects in the release |
| `adoptionStages` | object \| null | Adoption stage of the release in each project |
| `adoptionStages` | object \| null | Adoption stage of the release in each project, keyed by project slug |

**Examples:**

Expand Down
9 changes: 7 additions & 2 deletions packages/cli/src/lib/api/issue-app-links.ts
Original file line number Diff line number Diff line change
Expand Up @@ -318,8 +318,13 @@ async function getLinkForm(
JSON.stringify(component.error),
);
}
// App-defined form schemas are intentionally untyped in the API contract.
const form = safeParse(LinkFormSchema, component.schema.link);
// The component schema is typed per component type, but its form fields
// are app-defined, so validate the link form here.
const { schema } = component;
const form = safeParse(
LinkFormSchema,
schema.type === "issue-link" ? schema.link : undefined,
);
if (!form.success) {
throw new ValidationError(
`App ${installation.app.slug} does not expose a supported issue-link form`,
Expand Down
17 changes: 15 additions & 2 deletions packages/cli/src/lib/formatters/human.ts
Original file line number Diff line number Diff line change
Expand Up @@ -797,6 +797,19 @@ function formatPriorityLabel(priority?: string | null): string {
}
}

/**
* Display version of an issue's first or last release. Sentry returns only
* `version` for a release it can't load, so fall back to it.
*/
function releaseVersion(
release: SentryIssue["firstRelease"],
): string | undefined {
if (!release) {
return;
}
return "shortVersion" in release ? release.shortVersion : release.version;
}

/**
* Format detailed issue information as rendered markdown.
*
Expand Down Expand Up @@ -850,8 +863,8 @@ export function formatIssueDetails(issue: SentryIssue): string {
]);
}

const firstReleaseVersion = issue.firstRelease?.shortVersion;
const lastReleaseVersion = issue.lastRelease?.shortVersion;
const firstReleaseVersion = releaseVersion(issue.firstRelease);
const lastReleaseVersion = releaseVersion(issue.lastRelease);
if (firstReleaseVersion || lastReleaseVersion) {
const first = text(stringifyUnknown(firstReleaseVersion ?? ""));
const last = text(stringifyUnknown(lastReleaseVersion ?? ""));
Expand Down
31 changes: 23 additions & 8 deletions packages/cli/test/lib/api/issue-app-links.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,16 @@ const LINK: AppIssueLink = {
displayName: "ENG-42",
webUrl: URL,
};
const APP_UUID = "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d";
const INSTALLATION = {
uuid: "install-uuid",
uuid: "8d9f5e2a-3b4c-4d6e-9f01-2a3b4c5d6e7f",
status: "installed",
organization: { slug: ORG },
app: { uuid: "app-uuid", slug: "linear", sentryAppId: 12 },
app: {
uuid: APP_UUID,
slug: "linear",
sentryAppId: 12,
},
};
const FORM = {
uri: "/hooks/sentry/issues/link",
Expand All @@ -46,12 +51,17 @@ const FORM = {
],
};
const COMPONENT = {
uuid: "component-uuid",
uuid: "5c6d7e8f-9a0b-4c1d-8e2f-3a4b5c6d7e8f",
type: "issue-link",
error: "",
sentryApp: { uuid: "app-uuid", slug: "linear", name: "Linear", avatars: [] },
sentryApp: {
uuid: APP_UUID,
slug: "linear",
name: "Linear",
avatars: [],
},
installationUuid: INSTALLATION.uuid,
schema: { link: FORM },
schema: { type: "issue-link", link: FORM, create: FORM },
};

let originalFetch: typeof globalThis.fetch;
Expand Down Expand Up @@ -90,7 +100,9 @@ beforeEach(async () => {
return json([installation]);
}
if (path.endsWith("/sentry-app-components/")) {
return json([{ ...COMPONENT, schema: { link: form } }]);
return json([
{ ...COMPONENT, schema: { ...COMPONENT.schema, link: form } },
]);
}
if (path.endsWith("/external-requests/")) {
return json({ choices });
Expand Down Expand Up @@ -128,7 +140,7 @@ describe("app issue-link action", () => {
request.url.includes("external-requests"),
);
expect(search?.url).toContain(
"https://sentry.io/api/0/sentry-app-installations/install-uuid/",
`https://sentry.io/api/0/sentry-app-installations/${INSTALLATION.uuid}/`,
);
expect(search?.url).toContain("query=ENG-42");
expect(search?.url).toContain("projectId=77");
Expand Down Expand Up @@ -394,7 +406,10 @@ describe("app issue-link action", () => {
});

test("rejects unsupported app link forms instead of using direct registration", async () => {
form = undefined;
form = {
uri: "/hooks/sentry/issues/link",
required_fields: [{ name: "issueId", type: "checkbox" }],
};
await expect(resolveAppIssueLink(OPTIONS)).rejects.toThrow(
"does not expose",
);
Expand Down
11 changes: 11 additions & 0 deletions packages/cli/test/lib/formatters/human.details.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,17 @@ describe("formatIssueDetails", () => {
expect(result).toContain("→");
});

test("falls back to version for releases Sentry could not load", () => {
// Sentry returns only `version` when the release row no longer exists.
const issue = createMockIssue({
firstRelease: { version: "backend@1.0.0" },
lastRelease: { version: "backend@2.0.0" },
});

const result = stripAnsi(formatIssueDetails(issue));
expect(result).toContain("backend@1.0.0 → backend@2.0.0");
});

test("includes assignee name", () => {
const issue = createMockIssue({
assignedTo: { name: "John Doe" },
Expand Down
16 changes: 8 additions & 8 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions pnpm-workspace.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ catalog:
"@modelcontextprotocol/server": 2.4.0
"@radix-ui/react-accordion": ^1.2.20
"@radix-ui/react-slot": ^1.2.3
"@sentry/api": 1.51.0
"@sentry/api": 1.53.0
"@sentry/cloudflare": 11.6.0
"@sentry/core": 11.6.0
"@sentry/node": 11.6.0
Expand Down Expand Up @@ -168,7 +168,7 @@ minimumReleaseAgeExclude:
- "@oxlint/binding-win32-x64-msvc@1.87.0"
- oxfmt@0.72.0
- oxlint@1.87.0
- "@sentry/api@1.51.0"
- "@sentry/api@1.53.0"
- miniflare@5.20261101.0-beta
- wrangler@4.156.1
- "@sentry/symbolic@14.0.0-alpha.5"
Expand Down
Loading