diff --git a/actions/setup/js/update_handler_factory.cjs b/actions/setup/js/update_handler_factory.cjs index 49ec276c99..f25e866d64 100644 --- a/actions/setup/js/update_handler_factory.cjs +++ b/actions/setup/js/update_handler_factory.cjs @@ -117,8 +117,12 @@ function createUpdateHandlerFactory(handlerConfig) { const updateData = updateDataResult.data; // Validate that we have something to update + // Note: Fields starting with "_" are internal (e.g., _rawBody, _operation) + // and will be processed by executeUpdate. We should NOT skip if _rawBody exists. const updateFields = Object.keys(updateData).filter(k => !k.startsWith("_")); - if (updateFields.length === 0) { + const hasRawBody = updateData._rawBody !== undefined; + + if (updateFields.length === 0 && !hasRawBody) { core.info(`No update fields provided for ${itemTypeName} #${itemNumber} - treating as no-op (skipping update)`); return { success: true, diff --git a/actions/setup/js/update_handler_factory.test.cjs b/actions/setup/js/update_handler_factory.test.cjs index d7dbf19c4c..ad3b6ebdfe 100644 --- a/actions/setup/js/update_handler_factory.test.cjs +++ b/actions/setup/js/update_handler_factory.test.cjs @@ -233,6 +233,35 @@ describe("update_handler_factory.cjs", () => { expect(mockCore.info).toHaveBeenCalledWith(expect.stringContaining('["title"]')); }); + it("should NOT skip when _rawBody is present (body updates)", async () => { + const mockResolveItemNumber = vi.fn().mockReturnValue({ success: true, number: 42 }); + const mockBuildUpdateData = vi.fn().mockReturnValue({ + success: true, + data: { _rawBody: "New body content", _operation: "append" }, + }); + const mockExecuteUpdate = vi.fn().mockResolvedValue({ html_url: "https://example.com" }); + const mockFormatSuccessResult = vi.fn().mockReturnValue({ success: true }); + + const handlerFactory = factoryModule.createUpdateHandlerFactory({ + itemType: "update_issue", + itemTypeName: "issue", + supportsPR: false, + resolveItemNumber: mockResolveItemNumber, + buildUpdateData: mockBuildUpdateData, + executeUpdate: mockExecuteUpdate, + formatSuccessResult: mockFormatSuccessResult, + }); + + const handler = await handlerFactory({}); + const result = await handler({ body: "New body content" }); + + // Should NOT skip - _rawBody indicates a body update + expect(result.success).toBe(true); + expect(result.skipped).toBeUndefined(); + // Should proceed to execute the update + expect(mockExecuteUpdate).toHaveBeenCalled(); + }); + it("should handle execution errors gracefully", async () => { const mockResolveItemNumber = vi.fn().mockReturnValue({ success: true, number: 42 }); const mockBuildUpdateData = vi.fn().mockReturnValue({ success: true, data: { title: "Test" } });