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
13 changes: 13 additions & 0 deletions packages/cli/src/lib/api/releases.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,17 @@ export type ListReleasesOptions = {
status?: string;
};

/**
* Sorts the releases endpoint only accepts with `flatten=1`; otherwise it
* responds 400 "sorting by crash statistics requires flattening".
*/
const SESSION_SORTS = new Set([
"sessions",
"users",
"crash_free_sessions",
"crash_free_users",
]);

export async function listReleasesPaginated(
orgSlug: string,
options: ListReleasesOptions = {},
Expand All @@ -76,6 +87,7 @@ export async function listReleasesPaginated(
per_page: options.perPage ?? 25,
query: options.query,
sort: options.sort,
flatten: options.sort && SESSION_SORTS.has(options.sort) ? 1 : undefined,
health: options.health ? 1 : undefined,
project: options.project,
environment: options.environment,
Expand All @@ -86,6 +98,7 @@ export async function listReleasesPaginated(
per_page?: number;
query?: string;
sort?: string;
flatten?: number;
health?: number;
project?: number[];
environment?: string[];
Expand Down
46 changes: 46 additions & 0 deletions packages/cli/test/lib/api/releases.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -614,4 +614,50 @@ describe("listReleasesPaginated", () => {

expect(result.data).toHaveLength(0);
});

test.each(["sessions", "users", "crash_free_sessions", "crash_free_users"])(
"requests flattened results when sorting by %s",
async (sort) => {
let flatten: string | null = null;
globalThis.fetch = mockFetch(async (input, init) => {
const url = new URL(new Request(input!, init).url);
flatten = url.searchParams.get("flatten");
// Sentry rejects session sorts unless the results are flattened.
if (flatten !== "1") {
return new Response(
JSON.stringify({
detail:
"sorting by crash statistics requires flattening (flatten=1)",
}),
{ status: 400, headers: { "Content-Type": "application/json" } },
);
}
return new Response(JSON.stringify([SAMPLE_RELEASE]), {
status: 200,
headers: { "Content-Type": "application/json" },
});
});

const result = await listReleasesPaginated("test-org", { sort });

expect(flatten).toBe("1");
expect(result.data).toHaveLength(1);
},
);

test("does not flatten date-sorted results", async () => {
let flatten: string | null = "unset";
globalThis.fetch = mockFetch(async (input, init) => {
const url = new URL(new Request(input!, init).url);
flatten = url.searchParams.get("flatten");
return new Response(JSON.stringify([]), {
status: 200,
headers: { "Content-Type": "application/json" },
});
});

await listReleasesPaginated("test-org", { sort: "date" });

expect(flatten).toBeNull();
});
});
Loading