Skip to content
Closed
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
26 changes: 21 additions & 5 deletions src/lib/init/tools/create-sentry-project.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { createProjectWithDsn } from "../../api-client.js";
import { ApiError } from "../../errors.js";
import { resolveOrCreateTeam } from "../../resolve-team.js";
import { slugify } from "../../utils.js";
import { tryGetExistingProjectData } from "../existing-project.js";
Expand Down Expand Up @@ -72,15 +73,30 @@ export async function createSentryProject(
};
}

const { project, dsn, url } = await createProjectWithDsn(
context.org,
teamSlug,
{
let createdProject: Awaited<ReturnType<typeof createProjectWithDsn>>;
try {
createdProject = await createProjectWithDsn(context.org, teamSlug, {
name,
platform: payload.params.platform,
});
} catch (error) {
// Platform slug rejected by the API — retry without it. The platform
// label is cosmetic: the wizard installs the correct SDK and generates
// the right code regardless of the project's platform tag.
if (
error instanceof ApiError &&
error.status === 400 &&
error.detail?.includes('"platform"')
) {
createdProject = await createProjectWithDsn(context.org, teamSlug, {
name,
});
} else {
throw error;
}
);
}

const { project, dsn, url } = createdProject;
return {
ok: true,
data: {
Expand Down
39 changes: 39 additions & 0 deletions test/lib/init/tools/create-sentry-project.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,45 @@ describe("createSentryProject", () => {
expect(createProjectWithDsnSpy).not.toHaveBeenCalled();
});

test("retries without platform when API rejects the platform slug", async () => {
getProjectSpy.mockRejectedValueOnce(new ApiError("Not found", 404));
createProjectWithDsnSpy
.mockRejectedValueOnce(
new ApiError(
"Failed to create project: 400 Bad Request",
400,
'{"platform":["Invalid platform"]}'
)
)
.mockResolvedValueOnce({
project: { id: "42", slug: "my-app", name: "my-app" } as any,
dsn: "https://abc@o1.ingest.sentry.io/42",
url: "https://sentry.io/settings/acme/projects/my-app/",
});

const result = await createSentryProject(
makePayload({ platform: "javascript-hono" }),
{ dryRun: false, org: "acme", team: "platform", project: undefined }
);

expect(result.ok).toBe(true);
expect(createProjectWithDsnSpy).toHaveBeenCalledTimes(2);
// First call with the original (rejected) platform
expect(createProjectWithDsnSpy).toHaveBeenNthCalledWith(
1,
"acme",
"platform",
expect.objectContaining({ platform: "javascript-hono" })
);
// Retry without platform
expect(createProjectWithDsnSpy).toHaveBeenNthCalledWith(
2,
"acme",
"platform",
expect.not.objectContaining({ platform: expect.anything() })
);
});

test("resolves the team at project creation time when preflight deferred it", async () => {
getProjectSpy.mockRejectedValueOnce(new ApiError("Not found", 404));

Expand Down
Loading