From ad81644668e0035be0763e5eccffaeb3af355782 Mon Sep 17 00:00:00 2001 From: PRADDZY <64481960+PRADDZY@users.noreply.github.com> Date: Sat, 20 Jun 2026 22:23:43 +0530 Subject: [PATCH 1/2] Fix legacy recognizer feedback task payload handling --- .../service/jdbi3/TaskRepository.java | 44 +++++++++++++++++++ .../migration/utils/v200/MigrationUtil.java | 6 +-- .../tasks/TaskFormExecutionResolver.java | 8 +++- .../utils/v200/MigrationUtilTest.java | 31 +++++++++++++ .../tasks/TaskFormExecutionResolverTest.java | 33 ++++++++++++++ 5 files changed, 117 insertions(+), 5 deletions(-) diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TaskRepository.java b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TaskRepository.java index c9f3e42d9aaf..da49f2839002 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TaskRepository.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TaskRepository.java @@ -24,6 +24,9 @@ import static org.openmetadata.service.governance.workflows.WorkflowVariableHandler.getNamespacedVariableName; import static org.openmetadata.service.governance.workflows.elements.TriggerFactory.getTriggerWorkflowId; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; import jakarta.json.JsonPatch; import jakarta.ws.rs.core.SecurityContext; import jakarta.ws.rs.core.UriInfo; @@ -273,6 +276,7 @@ private String intersectDomainIds(String requestedDomainId, String allowedDomain @Override public void setFields(Task task, Fields fields, RelationIncludes relationIncludes) { + normalizeDataQualityReviewPayload(task); task.setAssignees(fields.contains(FIELD_ASSIGNEES) ? getAssignees(task) : task.getAssignees()); task.setReviewers( fields.contains(FIELD_REVIEWERS) ? getTaskReviewers(task) : task.getReviewers()); @@ -284,6 +288,46 @@ public void setFields(Task task, Fields fields, RelationIncludes relationInclude fields.contains(FIELD_CREATED_BY) ? getTaskCreatedBy(task) : task.getCreatedBy()); } + private void normalizeDataQualityReviewPayload(Task task) { + if (task == null || task.getType() != TaskEntityType.DataQualityReview) { + return; + } + + Object payload = task.getPayload(); + if (payload == null) { + return; + } + + JsonNode payloadNode = JsonUtils.valueToTree(payload); + if (!payloadNode.isObject()) { + return; + } + + ObjectNode normalizedPayload = ((ObjectNode) payloadNode).deepCopy(); + boolean updated = false; + + if (!normalizedPayload.has("feedback") + && normalizedPayload.has("data") + && !normalizedPayload.get("data").isNull()) { + normalizedPayload.set("feedback", normalizedPayload.get("data")); + updated = true; + } + + JsonNode metadataNode = normalizedPayload.get("metadata"); + if (!normalizedPayload.has("recognizer") + && metadataNode != null + && metadataNode.has("recognizer") + && !metadataNode.get("recognizer").isNull()) { + normalizedPayload.set("recognizer", metadataNode.get("recognizer")); + updated = true; + } + + if (updated) { + task.setPayload( + JsonUtils.convertValue(normalizedPayload, new TypeReference>() {})); + } + } + @Override public void setFieldsInBulk(Fields fields, java.util.List entities) { if (entities == null || entities.isEmpty()) { diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/migration/utils/v200/MigrationUtil.java b/openmetadata-service/src/main/java/org/openmetadata/service/migration/utils/v200/MigrationUtil.java index d1eec1ebceb8..dfac91c7a6b2 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/migration/utils/v200/MigrationUtil.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/migration/utils/v200/MigrationUtil.java @@ -839,12 +839,10 @@ private static ObjectNode buildThreadTaskPayload( case "RecognizerFeedbackApproval" -> { ObjectNode payload = JsonUtils.getObjectNode(); if (taskDetails.has("feedback") && !taskDetails.get("feedback").isNull()) { - payload.set("data", taskDetails.get("feedback")); + payload.set("feedback", taskDetails.get("feedback")); } if (taskDetails.has("recognizer") && !taskDetails.get("recognizer").isNull()) { - ObjectNode metadata = JsonUtils.getObjectNode(); - metadata.set("recognizer", taskDetails.get("recognizer")); - payload.set("metadata", metadata); + payload.set("recognizer", taskDetails.get("recognizer")); } yield payload; } diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/tasks/TaskFormExecutionResolver.java b/openmetadata-service/src/main/java/org/openmetadata/service/tasks/TaskFormExecutionResolver.java index 04517c127c0f..9de53f7757f5 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/tasks/TaskFormExecutionResolver.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/tasks/TaskFormExecutionResolver.java @@ -14,6 +14,7 @@ package org.openmetadata.service.tasks; +import com.fasterxml.jackson.databind.JsonNode; import java.util.List; import java.util.Map; import lombok.extern.slf4j.Slf4j; @@ -345,7 +346,12 @@ private static TaskExecutionPlan merge(TaskExecutionPlan defaults, TaskExecution } private static boolean hasFeedbackPayload(Task task) { - return task.getPayload() != null && JsonUtils.valueToTree(task.getPayload()).has("feedback"); + if (task.getPayload() == null) { + return false; + } + + JsonNode payload = JsonUtils.valueToTree(task.getPayload()); + return payload.has("feedback") || payload.has("data"); } private static String stringValue(Object value) { diff --git a/openmetadata-service/src/test/java/org/openmetadata/service/migration/utils/v200/MigrationUtilTest.java b/openmetadata-service/src/test/java/org/openmetadata/service/migration/utils/v200/MigrationUtilTest.java index c7dea2da01b3..36a82e4069b1 100644 --- a/openmetadata-service/src/test/java/org/openmetadata/service/migration/utils/v200/MigrationUtilTest.java +++ b/openmetadata-service/src/test/java/org/openmetadata/service/migration/utils/v200/MigrationUtilTest.java @@ -352,6 +352,37 @@ void buildThreadTaskPayloadMapsTagSuggestionList() throws Exception { assertEquals("User", payload.get("source").asText()); } + @Test + void buildThreadTaskPayloadMapsRecognizerFeedbackPayloadToModernKeys() throws Exception { + JsonNode taskDetails = + JsonUtilsHolder.readTree( + """ + { + "feedback": { + "feedbackType": "FalsePositive" + }, + "recognizer": { + "id": "pii-recognizer" + } + } + """); + + ObjectNode payload = + (ObjectNode) + invokePrivateStatic( + "buildThreadTaskPayload", + new Class[] {String.class, JsonNode.class, MessageParser.EntityLink.class}, + "RecognizerFeedbackApproval", + taskDetails, + null); + + assertNotNull(payload); + assertEquals("FalsePositive", payload.get("feedback").get("feedbackType").asText()); + assertEquals("pii-recognizer", payload.get("recognizer").get("id").asText()); + assertNull(payload.get("data")); + assertNull(payload.get("metadata")); + } + @Test void buildActivityEventFromLegacyThreadMapsDescriptionUpdate() throws Exception { UUID threadId = UUID.randomUUID(); diff --git a/openmetadata-service/src/test/java/org/openmetadata/service/tasks/TaskFormExecutionResolverTest.java b/openmetadata-service/src/test/java/org/openmetadata/service/tasks/TaskFormExecutionResolverTest.java index 0714c3ab210f..c240ade0f051 100644 --- a/openmetadata-service/src/test/java/org/openmetadata/service/tasks/TaskFormExecutionResolverTest.java +++ b/openmetadata-service/src/test/java/org/openmetadata/service/tasks/TaskFormExecutionResolverTest.java @@ -273,6 +273,39 @@ void resolveTreatsReviewFeedbackTasksAsFeedbackApproval() { } } + @Test + void resolveTreatsLegacyReviewFeedbackPayloadAsFeedbackApproval() { + Task task = + new Task() + .withId(UUID.randomUUID()) + .withType(TaskEntityType.DataQualityReview) + .withCategory(TaskCategory.Review) + .withPayload( + Map.of( + "data", + Map.of("feedbackType", "FalsePositive"), + "metadata", + Map.of("recognizer", "PII"))); + TaskFormSchemaRepository repository = mock(TaskFormSchemaRepository.class); + + try (MockedStatic entityMock = Mockito.mockStatic(Entity.class)) { + entityMock + .when(() -> Entity.getEntityRepository(Entity.TASK_FORM_SCHEMA)) + .thenReturn(repository); + when(repository.resolve( + TaskEntityType.DataQualityReview.value(), + TaskCategory.Review.value(), + task.getPayload())) + .thenReturn(Optional.empty()); + + TaskExecutionBinding binding = TaskFormExecutionResolver.resolve(task); + + assertEquals(HandlerType.FEEDBACK_APPROVAL, binding.handlerType()); + assertEquals(MetadataOperation.EDIT_ALL, binding.permissionOperation()); + assertNull(binding.fieldPathField()); + } + } + @Test void resolveDisambiguatesSuggestionSchemasUsingPayloadType() { Task task = From cacaea898c93c16f8b2cf55724978e9dba6c9c56 Mon Sep 17 00:00:00 2001 From: PRADDZY <64481960+PRADDZY@users.noreply.github.com> Date: Sun, 21 Jun 2026 01:04:48 +0530 Subject: [PATCH 2/2] fix: tighten recognizer feedback payload normalization --- .../service/jdbi3/TaskRepository.java | 29 ++-- .../migration/utils/v200/MigrationUtil.java | 19 ++- .../RecognizerFeedbackTaskPayloadKeys.java | 25 ++++ .../tasks/TaskFormExecutionResolver.java | 8 +- .../service/jdbi3/TaskRepositoryTest.java | 133 ++++++++++++++++++ .../tasks/TaskFormExecutionResolverTest.java | 25 ++++ 6 files changed, 220 insertions(+), 19 deletions(-) create mode 100644 openmetadata-service/src/main/java/org/openmetadata/service/tasks/RecognizerFeedbackTaskPayloadKeys.java create mode 100644 openmetadata-service/src/test/java/org/openmetadata/service/jdbi3/TaskRepositoryTest.java diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TaskRepository.java b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TaskRepository.java index da49f2839002..074512534448 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TaskRepository.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TaskRepository.java @@ -24,7 +24,6 @@ import static org.openmetadata.service.governance.workflows.WorkflowVariableHandler.getNamespacedVariableName; import static org.openmetadata.service.governance.workflows.elements.TriggerFactory.getTriggerWorkflowId; -import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; import jakarta.json.JsonPatch; @@ -78,6 +77,7 @@ import org.openmetadata.service.tasks.TaskFieldValidator; import org.openmetadata.service.tasks.TaskFormExecutionResolver; import org.openmetadata.service.tasks.TaskIdGenerator; +import org.openmetadata.service.tasks.RecognizerFeedbackTaskPayloadKeys; import org.openmetadata.service.tasks.TaskWorkflowHandler; import org.openmetadata.service.tasks.TaskWorkflowLifecycleResolver; import org.openmetadata.service.util.EntityUtil; @@ -303,28 +303,31 @@ private void normalizeDataQualityReviewPayload(Task task) { return; } - ObjectNode normalizedPayload = ((ObjectNode) payloadNode).deepCopy(); + ObjectNode normalizedPayload = (ObjectNode) payloadNode; boolean updated = false; - if (!normalizedPayload.has("feedback") - && normalizedPayload.has("data") - && !normalizedPayload.get("data").isNull()) { - normalizedPayload.set("feedback", normalizedPayload.get("data")); + if (!normalizedPayload.has(RecognizerFeedbackTaskPayloadKeys.FEEDBACK) + && normalizedPayload.has(RecognizerFeedbackTaskPayloadKeys.LEGACY_DATA) + && !normalizedPayload.get(RecognizerFeedbackTaskPayloadKeys.LEGACY_DATA).isNull()) { + normalizedPayload.set( + RecognizerFeedbackTaskPayloadKeys.FEEDBACK, + normalizedPayload.get(RecognizerFeedbackTaskPayloadKeys.LEGACY_DATA)); updated = true; } - JsonNode metadataNode = normalizedPayload.get("metadata"); - if (!normalizedPayload.has("recognizer") + JsonNode metadataNode = normalizedPayload.get(RecognizerFeedbackTaskPayloadKeys.METADATA); + if (!normalizedPayload.has(RecognizerFeedbackTaskPayloadKeys.RECOGNIZER) && metadataNode != null - && metadataNode.has("recognizer") - && !metadataNode.get("recognizer").isNull()) { - normalizedPayload.set("recognizer", metadataNode.get("recognizer")); + && metadataNode.has(RecognizerFeedbackTaskPayloadKeys.RECOGNIZER) + && !metadataNode.get(RecognizerFeedbackTaskPayloadKeys.RECOGNIZER).isNull()) { + normalizedPayload.set( + RecognizerFeedbackTaskPayloadKeys.RECOGNIZER, + metadataNode.get(RecognizerFeedbackTaskPayloadKeys.RECOGNIZER)); updated = true; } if (updated) { - task.setPayload( - JsonUtils.convertValue(normalizedPayload, new TypeReference>() {})); + task.setPayload(JsonUtils.convertValue(normalizedPayload, Map.class)); } } diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/migration/utils/v200/MigrationUtil.java b/openmetadata-service/src/main/java/org/openmetadata/service/migration/utils/v200/MigrationUtil.java index dfac91c7a6b2..a1794607f4ae 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/migration/utils/v200/MigrationUtil.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/migration/utils/v200/MigrationUtil.java @@ -36,6 +36,7 @@ import org.openmetadata.service.jdbi3.RoleRepository; import org.openmetadata.service.jdbi3.locator.ConnectionType; import org.openmetadata.service.resources.feeds.MessageParser; +import org.openmetadata.service.tasks.RecognizerFeedbackTaskPayloadKeys; import org.openmetadata.service.util.EntityUtil; import org.openmetadata.service.util.FullyQualifiedName; @@ -838,18 +839,26 @@ private static ObjectNode buildThreadTaskPayload( } case "RecognizerFeedbackApproval" -> { ObjectNode payload = JsonUtils.getObjectNode(); - if (taskDetails.has("feedback") && !taskDetails.get("feedback").isNull()) { - payload.set("feedback", taskDetails.get("feedback")); + if (taskDetails.has(RecognizerFeedbackTaskPayloadKeys.FEEDBACK) + && !taskDetails.get(RecognizerFeedbackTaskPayloadKeys.FEEDBACK).isNull()) { + payload.set( + RecognizerFeedbackTaskPayloadKeys.FEEDBACK, + taskDetails.get(RecognizerFeedbackTaskPayloadKeys.FEEDBACK)); } - if (taskDetails.has("recognizer") && !taskDetails.get("recognizer").isNull()) { - payload.set("recognizer", taskDetails.get("recognizer")); + if (taskDetails.has(RecognizerFeedbackTaskPayloadKeys.RECOGNIZER) + && !taskDetails.get(RecognizerFeedbackTaskPayloadKeys.RECOGNIZER).isNull()) { + payload.set( + RecognizerFeedbackTaskPayloadKeys.RECOGNIZER, + taskDetails.get(RecognizerFeedbackTaskPayloadKeys.RECOGNIZER)); } yield payload; } case "Generic" -> { ObjectNode payload = JsonUtils.getObjectNode(); if (taskDetails.has("suggestion") && !taskDetails.get("suggestion").isNull()) { - payload.put("data", taskDetails.get("suggestion").asText()); + payload.put( + RecognizerFeedbackTaskPayloadKeys.LEGACY_DATA, + taskDetails.get("suggestion").asText()); } yield payload; } diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/tasks/RecognizerFeedbackTaskPayloadKeys.java b/openmetadata-service/src/main/java/org/openmetadata/service/tasks/RecognizerFeedbackTaskPayloadKeys.java new file mode 100644 index 000000000000..1d7be5939518 --- /dev/null +++ b/openmetadata-service/src/main/java/org/openmetadata/service/tasks/RecognizerFeedbackTaskPayloadKeys.java @@ -0,0 +1,25 @@ +/* + * Copyright 2026 Collate + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openmetadata.service.tasks; + +public final class RecognizerFeedbackTaskPayloadKeys { + + public static final String FEEDBACK = "feedback"; + public static final String LEGACY_DATA = "data"; + public static final String RECOGNIZER = "recognizer"; + public static final String METADATA = "metadata"; + + private RecognizerFeedbackTaskPayloadKeys() {} +} diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/tasks/TaskFormExecutionResolver.java b/openmetadata-service/src/main/java/org/openmetadata/service/tasks/TaskFormExecutionResolver.java index 9de53f7757f5..3b55f14f72a6 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/tasks/TaskFormExecutionResolver.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/tasks/TaskFormExecutionResolver.java @@ -22,6 +22,7 @@ import org.openmetadata.schema.entity.tasks.Task; import org.openmetadata.schema.type.MetadataOperation; import org.openmetadata.schema.type.TaskCategory; +import org.openmetadata.schema.type.TaskEntityType; import org.openmetadata.schema.utils.JsonUtils; import org.openmetadata.service.Entity; import org.openmetadata.service.jdbi3.TaskFormSchemaRepository; @@ -351,7 +352,12 @@ private static boolean hasFeedbackPayload(Task task) { } JsonNode payload = JsonUtils.valueToTree(task.getPayload()); - return payload.has("feedback") || payload.has("data"); + if (payload.has(RecognizerFeedbackTaskPayloadKeys.FEEDBACK)) { + return true; + } + + return task.getType() == TaskEntityType.DataQualityReview + && payload.has(RecognizerFeedbackTaskPayloadKeys.LEGACY_DATA); } private static String stringValue(Object value) { diff --git a/openmetadata-service/src/test/java/org/openmetadata/service/jdbi3/TaskRepositoryTest.java b/openmetadata-service/src/test/java/org/openmetadata/service/jdbi3/TaskRepositoryTest.java new file mode 100644 index 000000000000..20ddd2c874d0 --- /dev/null +++ b/openmetadata-service/src/test/java/org/openmetadata/service/jdbi3/TaskRepositoryTest.java @@ -0,0 +1,133 @@ +/* + * Copyright 2026 Collate + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openmetadata.service.jdbi3; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.when; + +import com.fasterxml.jackson.databind.JsonNode; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Map; +import java.util.UUID; +import org.junit.jupiter.api.Test; +import org.mockito.MockedStatic; +import org.openmetadata.schema.entity.tasks.Task; +import org.openmetadata.schema.type.TaskEntityType; +import org.openmetadata.schema.utils.JsonUtils; +import org.openmetadata.service.Entity; +import org.openmetadata.service.jobs.JobDAO; +import org.openmetadata.service.search.SearchRepository; +import org.openmetadata.service.tasks.RecognizerFeedbackTaskPayloadKeys; +import org.openmetadata.service.util.EntityUtil.Fields; +import org.openmetadata.service.util.EntityUtil.RelationIncludes; + +class TaskRepositoryTest { + + @Test + void setFieldsNormalizesLegacyRecognizerFeedbackPayload() { + try (MockedStatic entityMock = mockStatic(Entity.class)) { + TaskRepository repository = createRepository(entityMock); + Task task = + new Task() + .withId(UUID.randomUUID()) + .withType(TaskEntityType.DataQualityReview) + .withPayload( + Map.of( + RecognizerFeedbackTaskPayloadKeys.LEGACY_DATA, + Map.of("feedbackType", "FalsePositive"), + RecognizerFeedbackTaskPayloadKeys.METADATA, + Map.of(RecognizerFeedbackTaskPayloadKeys.RECOGNIZER, Map.of("id", "pii")))); + + repository.setFields(task, Fields.EMPTY_FIELDS, RelationIncludes.fromInclude(null)); + + JsonNode payload = JsonUtils.valueToTree(task.getPayload()); + assertTrue(payload.has(RecognizerFeedbackTaskPayloadKeys.FEEDBACK)); + assertTrue(payload.has(RecognizerFeedbackTaskPayloadKeys.RECOGNIZER)); + assertEquals( + "FalsePositive", + payload.get(RecognizerFeedbackTaskPayloadKeys.FEEDBACK).get("feedbackType").asText()); + assertEquals( + "pii", + payload.get(RecognizerFeedbackTaskPayloadKeys.RECOGNIZER).get("id").asText()); + } + } + + @Test + void setFieldsLeavesNonObjectPayloadUnchanged() { + try (MockedStatic entityMock = mockStatic(Entity.class)) { + TaskRepository repository = createRepository(entityMock); + Task task = + new Task().withId(UUID.randomUUID()).withType(TaskEntityType.DataQualityReview).withPayload("legacy"); + + repository.setFields(task, Fields.EMPTY_FIELDS, RelationIncludes.fromInclude(null)); + + assertEquals("legacy", task.getPayload()); + } + } + + @Test + void setFieldsLeavesNonDataQualityReviewPayloadUnchanged() { + try (MockedStatic entityMock = mockStatic(Entity.class)) { + TaskRepository repository = createRepository(entityMock); + Task task = + new Task() + .withId(UUID.randomUUID()) + .withType(TaskEntityType.PipelineReview) + .withPayload( + Map.of( + RecognizerFeedbackTaskPayloadKeys.LEGACY_DATA, + Map.of("feedbackType", "FalsePositive"), + RecognizerFeedbackTaskPayloadKeys.METADATA, + Map.of(RecognizerFeedbackTaskPayloadKeys.RECOGNIZER, Map.of("id", "pii")))); + + repository.setFields(task, Fields.EMPTY_FIELDS, RelationIncludes.fromInclude(null)); + + JsonNode payload = JsonUtils.valueToTree(task.getPayload()); + assertTrue(payload.has(RecognizerFeedbackTaskPayloadKeys.LEGACY_DATA)); + assertFalse(payload.has(RecognizerFeedbackTaskPayloadKeys.FEEDBACK)); + assertFalse(payload.has(RecognizerFeedbackTaskPayloadKeys.RECOGNIZER)); + } + } + + private TaskRepository createRepository(MockedStatic entityMock) { + CollectionDAO dao = mock(CollectionDAO.class); + CollectionDAO.TaskDAO taskDAO = mock(CollectionDAO.TaskDAO.class); + when(dao.taskDAO()).thenReturn(taskDAO); + entityMock.when(Entity::getCollectionDAO).thenReturn(dao); + entityMock.when(Entity::getJobDAO).thenReturn(mock(JobDAO.class)); + entityMock.when(Entity::getSearchRepository).thenReturn(mock(SearchRepository.class)); + entityMock + .when(() -> Entity.getEntityFields(Task.class)) + .thenReturn( + new HashSet<>( + Arrays.asList( + TaskRepository.FIELD_ASSIGNEES, + TaskRepository.FIELD_REVIEWERS, + TaskRepository.FIELD_WATCHERS, + TaskRepository.FIELD_ABOUT, + TaskRepository.FIELD_COMMENTS, + TaskRepository.FIELD_RESOLUTION, + TaskRepository.FIELD_CREATED_BY, + TaskRepository.FIELD_PAYLOAD, + Entity.FIELD_DOMAINS))); + + return new TaskRepository(); + } +} diff --git a/openmetadata-service/src/test/java/org/openmetadata/service/tasks/TaskFormExecutionResolverTest.java b/openmetadata-service/src/test/java/org/openmetadata/service/tasks/TaskFormExecutionResolverTest.java index c240ade0f051..9722604ef254 100644 --- a/openmetadata-service/src/test/java/org/openmetadata/service/tasks/TaskFormExecutionResolverTest.java +++ b/openmetadata-service/src/test/java/org/openmetadata/service/tasks/TaskFormExecutionResolverTest.java @@ -306,6 +306,31 @@ void resolveTreatsLegacyReviewFeedbackPayloadAsFeedbackApproval() { } } + @Test + void resolveDoesNotTreatPipelineReviewDataPayloadAsFeedbackApproval() { + Task task = + new Task() + .withId(UUID.randomUUID()) + .withType(TaskEntityType.PipelineReview) + .withCategory(TaskCategory.Review) + .withPayload(Map.of("data", Map.of("status", "pending"))); + TaskFormSchemaRepository repository = mock(TaskFormSchemaRepository.class); + + try (MockedStatic entityMock = Mockito.mockStatic(Entity.class)) { + entityMock + .when(() -> Entity.getEntityRepository(Entity.TASK_FORM_SCHEMA)) + .thenReturn(repository); + when(repository.resolve( + TaskEntityType.PipelineReview.value(), TaskCategory.Review.value(), task.getPayload())) + .thenReturn(Optional.empty()); + + TaskExecutionBinding binding = TaskFormExecutionResolver.resolve(task); + + assertEquals(HandlerType.CUSTOM, binding.handlerType()); + assertNull(binding.permissionOperation()); + } + } + @Test void resolveDisambiguatesSuggestionSchemasUsingPayloadType() { Task task =