From d23c05755a3d7163f5d0d4b2f3f24afa57d6f4f2 Mon Sep 17 00:00:00 2001 From: zheng861 Date: Wed, 28 Jan 2026 09:57:32 -0500 Subject: [PATCH 1/3] Add projectId to retry --- frontend/src/pages/app/OverviewTab.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/frontend/src/pages/app/OverviewTab.tsx b/frontend/src/pages/app/OverviewTab.tsx index 6031fd3e..fed74f64 100644 --- a/frontend/src/pages/app/OverviewTab.tsx +++ b/frontend/src/pages/app/OverviewTab.tsx @@ -438,7 +438,10 @@ const RetryDeploymentPrompt = ({ onClick={async () => { await updateApp({ params: { path: { appId: app.id } }, - body: { config: app.config }, + body: { + projectId: app.projectId, + config: app.config, + }, }); await refetchDeployments(); }} From 381b167a6f787bcc0403e02f74e6f193fde63a64 Mon Sep 17 00:00:00 2001 From: zheng861 Date: Wed, 28 Jan 2026 09:58:06 -0500 Subject: [PATCH 2/3] console.error --- frontend/src/lib/api.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src/lib/api.ts b/frontend/src/lib/api.ts index f9319f06..b11612e3 100644 --- a/frontend/src/lib/api.ts +++ b/frontend/src/lib/api.ts @@ -54,6 +54,7 @@ const onError = ( toast.error( `Something went wrong: ${error.message ?? JSON.stringify(error)}`, ); + console.error(error); }; export const queryClient = new QueryClient({ From 583616928a3e2ff2e7ec1b14ba100d8a942fed68 Mon Sep 17 00:00:00 2001 From: zheng861 Date: Wed, 28 Jan 2026 10:49:10 -0500 Subject: [PATCH 3/3] Indicate empty body in api responses --- backend/src/handlers/acceptInvitation.ts | 2 +- backend/src/handlers/claimOrg.ts | 2 +- backend/src/handlers/createAppGroup.ts | 2 +- backend/src/handlers/deleteApp.ts | 2 +- backend/src/handlers/deleteOrgByID.ts | 2 +- backend/src/handlers/githubWebhook.ts | 4 ++-- backend/src/handlers/ingestLogs.ts | 2 +- backend/src/handlers/setAppCD.ts | 2 +- backend/src/handlers/updateApp.ts | 2 +- backend/src/handlers/updateDeployment.ts | 2 +- backend/src/types.ts | 5 ++++- frontend/src/lib/api.ts | 1 - openapi/openapi.yaml | 20 ++++++++++---------- 13 files changed, 25 insertions(+), 23 deletions(-) diff --git a/backend/src/handlers/acceptInvitation.ts b/backend/src/handlers/acceptInvitation.ts index c03b9f94..9c8f56ee 100644 --- a/backend/src/handlers/acceptInvitation.ts +++ b/backend/src/handlers/acceptInvitation.ts @@ -21,5 +21,5 @@ export const acceptInvitationHandler: HandlerMap["acceptInvitation"] = async ( throw e; } - return empty(200, res); + return empty(204, res); }; diff --git a/backend/src/handlers/claimOrg.ts b/backend/src/handlers/claimOrg.ts index 3f49101a..42debedf 100644 --- a/backend/src/handlers/claimOrg.ts +++ b/backend/src/handlers/claimOrg.ts @@ -30,5 +30,5 @@ export const claimOrgHandler: HandlerMap["claimOrg"] = async ( } throw e; } - return empty(200, res); + return empty(204, res); }; diff --git a/backend/src/handlers/createAppGroup.ts b/backend/src/handlers/createAppGroup.ts index a2873021..ec65baba 100644 --- a/backend/src/handlers/createAppGroup.ts +++ b/backend/src/handlers/createAppGroup.ts @@ -18,7 +18,7 @@ export const createAppGroupHandler: HandlerMap["createAppGroup"] = async ( try { await createAppGroup(req.user.id, data.orgId, data.name, data.apps); - return empty(200, res); + return empty(204, res); } catch (e) { if (e instanceof AppCreateError) { const ex = e.cause!; diff --git a/backend/src/handlers/deleteApp.ts b/backend/src/handlers/deleteApp.ts index 8527af2a..87f0d9ae 100644 --- a/backend/src/handlers/deleteApp.ts +++ b/backend/src/handlers/deleteApp.ts @@ -12,7 +12,7 @@ export const deleteAppHandler: HandlerMap["deleteApp"] = async ( const appId = ctx.request.params.appId; try { await deleteApp(appId, req.user.id, ctx.request.requestBody.keepNamespace); - return empty(200, res); + return empty(204, res); } catch (e) { if (e instanceof AppNotFoundError) { return json(404, res, { code: 404, message: "App not found" }); diff --git a/backend/src/handlers/deleteOrgByID.ts b/backend/src/handlers/deleteOrgByID.ts index 481ad55c..993c19b4 100644 --- a/backend/src/handlers/deleteOrgByID.ts +++ b/backend/src/handlers/deleteOrgByID.ts @@ -18,5 +18,5 @@ export const deleteOrgByIDHandler: HandlerMap["deleteOrgByID"] = async ( } } - return empty(200, res); + return empty(204, res); }; diff --git a/backend/src/handlers/githubWebhook.ts b/backend/src/handlers/githubWebhook.ts index 9a46a233..385cf7ff 100644 --- a/backend/src/handlers/githubWebhook.ts +++ b/backend/src/handlers/githubWebhook.ts @@ -35,13 +35,13 @@ export const githubWebhookHandler: HandlerMap["githubWebhook"] = async ( try { await processGitHubWebhookPayload(requestType, action, JSON.parse(data)); - return empty(200, res); + return empty(204, res); } catch (e) { if (e instanceof ValidationError) { return json(400, res, { code: 400, message: e.message }); } else if (e instanceof AppNotFoundError) { // GitHub sent a webhook about a repository, but it's not linked to any apps - nothing to do here - return empty(200, res); + return empty(204, res); } else if (e instanceof UnknownWebhookRequestTypeError) { // GitHub sent a webhook payload that we don't care about return empty(422, res); diff --git a/backend/src/handlers/ingestLogs.ts b/backend/src/handlers/ingestLogs.ts index 300a0138..d128f2e2 100644 --- a/backend/src/handlers/ingestLogs.ts +++ b/backend/src/handlers/ingestLogs.ts @@ -32,7 +32,7 @@ export const ingestLogsHandler: HandlerMap["ingestLogs"] = async ( logType, ctx.request.requestBody.lines, ); - return empty(200, res); + return empty(204, res); } catch (e) { if (e instanceof DeploymentNotFoundError) { // No deployment matches the ID and secret diff --git a/backend/src/handlers/setAppCD.ts b/backend/src/handlers/setAppCD.ts index 5c868472..8cc812e2 100644 --- a/backend/src/handlers/setAppCD.ts +++ b/backend/src/handlers/setAppCD.ts @@ -14,7 +14,7 @@ export const setAppCDHandler: HandlerMap["setAppCD"] = async ( req.user.id, ctx.request.requestBody.enable, ); - return empty(200, res); + return empty(204, res); } catch (e) { if (e instanceof AppNotFoundError) { return json(404, res, { code: 404, message: "App not found." }); diff --git a/backend/src/handlers/updateApp.ts b/backend/src/handlers/updateApp.ts index 3f011129..cd17bc6f 100644 --- a/backend/src/handlers/updateApp.ts +++ b/backend/src/handlers/updateApp.ts @@ -15,7 +15,7 @@ export const updateAppHandler: HandlerMap["updateApp"] = async ( const appData = ctx.request.requestBody; try { await updateApp(ctx.request.params.appId, req.user.id, appData); - return empty(200, res); + return empty(204, res); } catch (e) { if (e instanceof AppNotFoundError) { return json(404, res, { code: 404, message: "App not found" }); diff --git a/backend/src/handlers/updateDeployment.ts b/backend/src/handlers/updateDeployment.ts index 5d9c67d2..5aacea3a 100644 --- a/backend/src/handlers/updateDeployment.ts +++ b/backend/src/handlers/updateDeployment.ts @@ -14,7 +14,7 @@ export const updateDeploymentHandler: HandlerMap["updateDeployment"] = async ( const { secret, status } = ctx.request.requestBody; try { await updateDeployment(secret, status); - return empty(200, res); + return empty(204, res); } catch (e) { if (e instanceof ValidationError) { return json(404, res, { code: 400, message: e.message }); diff --git a/backend/src/types.ts b/backend/src/types.ts index 34856390..39374410 100644 --- a/backend/src/types.ts +++ b/backend/src/types.ts @@ -87,7 +87,10 @@ export const empty = < : "Error: This status code expects a body in the OpenAPI spec. Use json() instead.", res: HandlerResponse, ): HandlerResponse => { - return res.status(statusCode as unknown as number).end(); + return res + .status(statusCode as unknown as number) + .setHeader("Content-Length", 0) + .end(); }; export const redirect = < diff --git a/frontend/src/lib/api.ts b/frontend/src/lib/api.ts index b11612e3..f9319f06 100644 --- a/frontend/src/lib/api.ts +++ b/frontend/src/lib/api.ts @@ -54,7 +54,6 @@ const onError = ( toast.error( `Something went wrong: ${error.message ?? JSON.stringify(error)}`, ); - console.error(error); }; export const queryClient = new QueryClient({ diff --git a/openapi/openapi.yaml b/openapi/openapi.yaml index b8f4579c..7efcea09 100644 --- a/openapi/openapi.yaml +++ b/openapi/openapi.yaml @@ -254,7 +254,7 @@ paths: - $ref: "./ghes-3.16.yaml#/components/schemas/webhook-repository-transferred" - $ref: "./ghes-3.16.yaml#/components/schemas/webhook-repository-deleted" responses: - "200": + "204": description: Success "400": description: Validation failed @@ -386,7 +386,7 @@ paths: description: Deletes organization by id operationId: deleteOrgByID responses: - "200": + "204": description: Success "400": description: Validation failed @@ -433,7 +433,7 @@ paths: format: int64 required: [unclaimedInstallationId] responses: - "200": + "204": description: Success "400": description: Validation failed @@ -532,7 +532,7 @@ paths: description: Accepts an invitation operationId: acceptInvitation responses: - "200": + "204": description: Success (invitation accepted) "400": description: Validation failed @@ -1096,7 +1096,7 @@ paths: - orgId - apps responses: - "200": + "204": description: Success "400": description: Validation failed @@ -1167,7 +1167,7 @@ paths: schema: $ref: "#/components/schemas/AppUpdate" responses: - "200": + "204": description: Success "400": description: Validation failed @@ -1214,7 +1214,7 @@ paths: type: boolean required: [keepNamespace] responses: - "200": + "204": description: Success "400": description: Validation failed @@ -1262,7 +1262,7 @@ paths: type: boolean required: [enable] responses: - "200": + "204": description: Success "400": description: Validation failed @@ -1690,7 +1690,7 @@ paths: description: The hostname of the pod that produced the log line, which should equal the pod name type: string responses: - "200": + "204": description: Success "400": description: Validation failed @@ -1836,7 +1836,7 @@ paths: status: type: string responses: - "200": + "204": description: Success "400": description: Validation failed