From 9aae8801fd268af4320e2c638c7f43cb38432547 Mon Sep 17 00:00:00 2001 From: Paulo Santos Date: Wed, 13 Aug 2025 12:25:08 -0400 Subject: [PATCH 01/18] IALERT-3868: Disable adding comments in the backend and remove from UI. --- .../jira/cloud/descriptor/JiraCloudDescriptor.java | 1 - .../accessor/DefaultJiraServerJobDetailsAccessor.java | 4 ++-- .../jira/server/descriptor/JiraServerDescriptor.java | 1 - .../jira/cloud/JiraCloudDistributionConfiguration.js | 11 ----------- .../server/JiraServerDistributionConfiguration.js | 11 ----------- 5 files changed, 2 insertions(+), 26 deletions(-) diff --git a/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/descriptor/JiraCloudDescriptor.java b/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/descriptor/JiraCloudDescriptor.java index e91f2920e5..ed20036489 100644 --- a/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/descriptor/JiraCloudDescriptor.java +++ b/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/descriptor/JiraCloudDescriptor.java @@ -45,7 +45,6 @@ public class JiraCloudDescriptor extends ChannelDescriptor { public static final String JIRA_URL = "jira"; public static final String JIRA_DESCRIPTION = "Configure the Jira Cloud instance that Alert will send issue updates to."; - public static final String LABEL_ADD_COMMENTS = "Add Comments"; public static final String LABEL_ISSUE_CREATOR = "Issue Creator"; public static final String LABEL_JIRA_PROJECT = "Jira Project"; public static final String LABEL_ISSUE_TYPE = "Issue Type"; diff --git a/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/database/accessor/DefaultJiraServerJobDetailsAccessor.java b/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/database/accessor/DefaultJiraServerJobDetailsAccessor.java index d2070c3d51..2f9cc7a6d2 100644 --- a/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/database/accessor/DefaultJiraServerJobDetailsAccessor.java +++ b/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/database/accessor/DefaultJiraServerJobDetailsAccessor.java @@ -64,7 +64,7 @@ public JiraServerJobDetailsModel saveJobDetails(UUID jobId, DistributionJobDetai public JiraServerJobDetailsModel saveConcreteJobDetails(UUID jobId, JiraServerJobDetailsModel jobDetails) { JiraServerJobDetailsEntity jiraServerJobDetailsToSave = new JiraServerJobDetailsEntity( jobId, - jobDetails.isAddComments(), + true, jobDetails.getIssueCreatorUsername(), jobDetails.getProjectNameOrKey(), jobDetails.getIssueType(), @@ -91,7 +91,7 @@ private JiraServerJobDetailsModel convertToModel(JiraServerJobDetailsEntity jobD .toList(); return new JiraServerJobDetailsModel( jobDetails.getJobId(), - jobDetails.getAddComments(), + true, jobDetails.getIssueCreatorUsername(), jobDetails.getProjectNameOrKey(), jobDetails.getIssueType(), diff --git a/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/descriptor/JiraServerDescriptor.java b/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/descriptor/JiraServerDescriptor.java index e8e5b22e5c..07fe80eb83 100644 --- a/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/descriptor/JiraServerDescriptor.java +++ b/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/descriptor/JiraServerDescriptor.java @@ -46,7 +46,6 @@ public class JiraServerDescriptor extends ChannelDescriptor { public static final String JIRA_DESCRIPTION = "Configure the Jira Server instance that Alert will send issue updates to."; public static final String LABEL_FIELD_MAPPING = "Field Mapping"; - public static final String LABEL_ADD_COMMENTS = "Add comments"; public static final String LABEL_ISSUE_CREATOR = "Issue Creator"; public static final String LABEL_JIRA_PROJECT = "Jira Project"; public static final String LABEL_ISSUE_TYPE = "Issue Type"; diff --git a/ui/src/main/js/page/channel/jira/cloud/JiraCloudDistributionConfiguration.js b/ui/src/main/js/page/channel/jira/cloud/JiraCloudDistributionConfiguration.js index 335fe455e6..766e941b87 100644 --- a/ui/src/main/js/page/channel/jira/cloud/JiraCloudDistributionConfiguration.js +++ b/ui/src/main/js/page/channel/jira/cloud/JiraCloudDistributionConfiguration.js @@ -23,17 +23,6 @@ const JiraCloudDistributionConfiguration = ({ return ( <> - - Date: Wed, 13 Aug 2025 13:26:04 -0400 Subject: [PATCH 02/18] IALERT-3868: remove the comments field from the models and UI. --- .../job/details/JiraCloudJobDetailsModel.java | 7 ------- .../job/details/JiraServerJobDetailsModel.java | 7 ------- ...DistributionJobDetailsModelJsonAdapterTest.java | 10 ++++------ .../alert/database/job/api/StaticJobAccessor.java | 1 - .../database/job/api/StaticJobAccessorTest.java | 8 ++++---- .../cloud/DefaultJiraCloudJobDetailsAccessor.java | 2 -- .../job/jira/cloud/JiraCloudJobDetailsEntity.java | 14 +------------- .../cloud/action/JiraCloudJobDetailsExtractor.java | 1 - .../delegate/JiraCloudIssueCommenter.java | 2 +- .../jira/cloud/JiraCloudIssueCreatorTest.java | 2 -- .../cloud/JiraCloudSummaryFieldLengthTestIT.java | 1 - .../event/JiraCloudCommentEventHandlerTest.java | 1 - .../JiraCloudCreateIssueEventHandlerTest.java | 1 - .../event/JiraCloudTransitionEventHandlerTest.java | 1 - .../action/JiraServerJobDetailsExtractor.java | 1 - .../DefaultJiraServerJobDetailsAccessor.java | 2 -- .../database/job/JiraServerJobDetailsEntity.java | 14 +------------- .../delegate/JiraServerIssueCommenter.java | 2 +- .../server/JiraServerExternalConnectionTest.java | 1 - .../server/JiraServerSummaryFieldLengthTestIT.java | 1 - .../accessor/JiraServerJobDetailsAccessorTest.java | 4 ++-- .../delegate/JiraServerIssueCreatorTest.java | 2 -- .../event/JiraServerCommentEventHandlerTest.java | 1 - .../JiraServerCreateIssueEventHandlerTest.java | 1 - .../JiraServerTransitionEventHandlerTest.java | 1 - .../database/job/api/StaticJobAccessorTestIT.java | 2 -- .../web/api/job/JobFieldModelPopulationUtils.java | 2 -- 27 files changed, 14 insertions(+), 78 deletions(-) diff --git a/alert-common/src/main/java/com/blackduck/integration/alert/common/persistence/model/job/details/JiraCloudJobDetailsModel.java b/alert-common/src/main/java/com/blackduck/integration/alert/common/persistence/model/job/details/JiraCloudJobDetailsModel.java index 3f296ceb57..3668fb07ec 100644 --- a/alert-common/src/main/java/com/blackduck/integration/alert/common/persistence/model/job/details/JiraCloudJobDetailsModel.java +++ b/alert-common/src/main/java/com/blackduck/integration/alert/common/persistence/model/job/details/JiraCloudJobDetailsModel.java @@ -13,7 +13,6 @@ import com.blackduck.integration.alert.api.descriptor.model.ChannelKeys; public class JiraCloudJobDetailsModel extends DistributionJobDetailsModel { - private final boolean addComments; private final String issueCreatorEmail; private final String projectNameOrKey; private final String issueType; @@ -24,7 +23,6 @@ public class JiraCloudJobDetailsModel extends DistributionJobDetailsModel { public JiraCloudJobDetailsModel( UUID jobId, - boolean addComments, String issueCreatorEmail, String projectNameOrKey, String issueType, @@ -34,7 +32,6 @@ public JiraCloudJobDetailsModel( String issueSummary ) { super(ChannelKeys.JIRA_CLOUD, jobId); - this.addComments = addComments; this.issueCreatorEmail = issueCreatorEmail; this.projectNameOrKey = projectNameOrKey; this.issueType = issueType; @@ -44,10 +41,6 @@ public JiraCloudJobDetailsModel( this.issueSummary = issueSummary; } - public boolean isAddComments() { - return addComments; - } - public String getIssueCreatorEmail() { return issueCreatorEmail; } diff --git a/alert-common/src/main/java/com/blackduck/integration/alert/common/persistence/model/job/details/JiraServerJobDetailsModel.java b/alert-common/src/main/java/com/blackduck/integration/alert/common/persistence/model/job/details/JiraServerJobDetailsModel.java index 2661c458ba..26272da839 100644 --- a/alert-common/src/main/java/com/blackduck/integration/alert/common/persistence/model/job/details/JiraServerJobDetailsModel.java +++ b/alert-common/src/main/java/com/blackduck/integration/alert/common/persistence/model/job/details/JiraServerJobDetailsModel.java @@ -13,7 +13,6 @@ import com.blackduck.integration.alert.api.descriptor.model.ChannelKeys; public class JiraServerJobDetailsModel extends DistributionJobDetailsModel { - private final boolean addComments; private final String issueCreatorUsername; private final String projectNameOrKey; private final String issueType; @@ -24,7 +23,6 @@ public class JiraServerJobDetailsModel extends DistributionJobDetailsModel { public JiraServerJobDetailsModel( UUID jobId, - boolean addComments, String issueCreatorUsername, String projectNameOrKey, String issueType, @@ -34,7 +32,6 @@ public JiraServerJobDetailsModel( String issueSummary ) { super(ChannelKeys.JIRA_SERVER, jobId); - this.addComments = addComments; this.issueCreatorUsername = issueCreatorUsername; this.projectNameOrKey = projectNameOrKey; this.issueType = issueType; @@ -44,10 +41,6 @@ public JiraServerJobDetailsModel( this.issueSummary = issueSummary; } - public boolean isAddComments() { - return addComments; - } - public String getIssueCreatorUsername() { return issueCreatorUsername; } diff --git a/alert-common/src/test/java/com/blackduck/integration/alert/common/persistence/model/job/details/DistributionJobDetailsModelJsonAdapterTest.java b/alert-common/src/test/java/com/blackduck/integration/alert/common/persistence/model/job/details/DistributionJobDetailsModelJsonAdapterTest.java index 7a71027af0..40969c87e0 100644 --- a/alert-common/src/test/java/com/blackduck/integration/alert/common/persistence/model/job/details/DistributionJobDetailsModelJsonAdapterTest.java +++ b/alert-common/src/test/java/com/blackduck/integration/alert/common/persistence/model/job/details/DistributionJobDetailsModelJsonAdapterTest.java @@ -65,7 +65,7 @@ public void serializeEmailJobDetailsModelTest() { @Test public void serializeJiraCloudJobDetailsModelTest() { UUID jobId = UUID.randomUUID(); - JiraCloudJobDetailsModel baseModel = new JiraCloudJobDetailsModel(jobId, true, "unknown", "JIRA-X", "bug", "done", "undone", List.of(), null); + JiraCloudJobDetailsModel baseModel = new JiraCloudJobDetailsModel(jobId, "unknown", "JIRA-X", "bug", "done", "undone", List.of(), null); JsonElement baseJson = gson.toJsonTree(baseModel); serializeAndAssert(baseModel, baseJson); } @@ -73,7 +73,7 @@ public void serializeJiraCloudJobDetailsModelTest() { @Test public void serializeJiraServerJobDetailsModelTest() { UUID jobId = UUID.randomUUID(); - JiraServerJobDetailsModel baseModel = new JiraServerJobDetailsModel(jobId, true, "user_name01", "JIRA-Y", "other", "finished", "unfinished", List.of(), "issueSummary"); + JiraServerJobDetailsModel baseModel = new JiraServerJobDetailsModel(jobId, "user_name01", "JIRA-Y", "other", "finished", "unfinished", List.of(), "issueSummary"); JsonElement baseJson = gson.toJsonTree(baseModel); serializeAndAssert(baseModel, baseJson); } @@ -144,13 +144,12 @@ public void deserializeEmailJobDetailsModelTest() { @Test public void deserializeJiraCloudJobDetailsModelTest() { UUID jobId = UUID.randomUUID(); - JiraCloudJobDetailsModel baseModel = new JiraCloudJobDetailsModel(jobId, true, "unknown", "JIRA-X", "bug", "done", "undone", List.of(), null); + JiraCloudJobDetailsModel baseModel = new JiraCloudJobDetailsModel(jobId, "unknown", "JIRA-X", "bug", "done", "undone", List.of(), null); DistributionJobDetailsModel deserializedModel = runDeserializerAndAssert(baseModel, (distributionJobDetailsModel -> distributionJobDetailsModel.isA(ChannelKeys.JIRA_CLOUD))); JiraCloudJobDetailsModel jobDetails = deserializedModel.getAs(DistributionJobDetailsModel.JIRA_CLOUD); assertEquals(baseModel.getJobId(), jobDetails.getJobId()); - assertEquals(baseModel.isAddComments(), jobDetails.isAddComments()); assertEquals(baseModel.getIssueCreatorEmail(), jobDetails.getIssueCreatorEmail()); assertEquals(baseModel.getProjectNameOrKey(), jobDetails.getProjectNameOrKey()); assertEquals(baseModel.getIssueType(), jobDetails.getIssueType()); @@ -161,13 +160,12 @@ public void deserializeJiraCloudJobDetailsModelTest() { @Test public void deserializeJiraServerJobDetailsModelTest() { UUID jobId = UUID.randomUUID(); - JiraServerJobDetailsModel baseModel = new JiraServerJobDetailsModel(jobId, true, "user_name01", "JIRA-Y", "other", "finished", "unfinished", List.of(), "issueSummary"); + JiraServerJobDetailsModel baseModel = new JiraServerJobDetailsModel(jobId, "user_name01", "JIRA-Y", "other", "finished", "unfinished", List.of(), "issueSummary"); DistributionJobDetailsModel deserializedModel = runDeserializerAndAssert(baseModel, (distributionJobDetailsModel -> distributionJobDetailsModel.isA(ChannelKeys.JIRA_SERVER))); JiraServerJobDetailsModel jobDetails = deserializedModel.getAs(DistributionJobDetailsModel.JIRA_SERVER); assertEquals(baseModel.getJobId(), jobDetails.getJobId()); - assertEquals(baseModel.isAddComments(), jobDetails.isAddComments()); assertEquals(baseModel.getIssueCreatorUsername(), jobDetails.getIssueCreatorUsername()); assertEquals(baseModel.getProjectNameOrKey(), jobDetails.getProjectNameOrKey()); assertEquals(baseModel.getIssueType(), jobDetails.getIssueType()); diff --git a/alert-database-job/src/main/java/com/blackduck/integration/alert/database/job/api/StaticJobAccessor.java b/alert-database-job/src/main/java/com/blackduck/integration/alert/database/job/api/StaticJobAccessor.java index b61ce7ec5c..17d0e300b6 100644 --- a/alert-database-job/src/main/java/com/blackduck/integration/alert/database/job/api/StaticJobAccessor.java +++ b/alert-database-job/src/main/java/com/blackduck/integration/alert/database/job/api/StaticJobAccessor.java @@ -264,7 +264,6 @@ private DistributionJobModel convertToDistributionJobModel(DistributionJobEntity .collect(Collectors.toList()); distributionJobDetailsModel = new JiraCloudJobDetailsModel( jobId, - jobDetails.getAddComments(), jobDetails.getIssueCreatorEmail(), jobDetails.getProjectNameOrKey(), jobDetails.getIssueType(), diff --git a/alert-database-job/src/test/java/com/blackduck/integration/alert/database/job/api/StaticJobAccessorTest.java b/alert-database-job/src/test/java/com/blackduck/integration/alert/database/job/api/StaticJobAccessorTest.java index 4c63b489ae..e589ec2ee9 100644 --- a/alert-database-job/src/test/java/com/blackduck/integration/alert/database/job/api/StaticJobAccessorTest.java +++ b/alert-database-job/src/test/java/com/blackduck/integration/alert/database/job/api/StaticJobAccessorTest.java @@ -406,10 +406,10 @@ void createEmailJobTest() { @Test void createJiraCloudJobTest() { UUID jobId = UUID.randomUUID(); - JiraCloudJobDetailsModel jiraCloudJobDetailsModel = new JiraCloudJobDetailsModel(jobId, false, null, null, null, null, null, List.of(), null); + JiraCloudJobDetailsModel jiraCloudJobDetailsModel = new JiraCloudJobDetailsModel(jobId, null, null, null, null, null, List.of(), null); DistributionJobRequestModel distributionJobRequestModel = createDistributionJobEntity(ChannelKeys.JIRA_CLOUD.getUniversalKey(), jiraCloudJobDetailsModel); - JiraCloudJobDetailsEntity jiraCloudJobDetailsEntity = new JiraCloudJobDetailsEntity(null, false, null, null, null, null, null, null); + JiraCloudJobDetailsEntity jiraCloudJobDetailsEntity = new JiraCloudJobDetailsEntity(null, null, null, null, null, null, null); jiraCloudJobDetailsEntity.setJobCustomFields(List.of()); DistributionJobEntity distributionJobEntity = createDistributionJobEntity(jobId, distributionJobRequestModel); distributionJobEntity.setJiraCloudJobDetails(jiraCloudJobDetailsEntity); @@ -428,10 +428,10 @@ void createJiraCloudJobTest() { @Test void createJiraServerJobTest() { UUID jobId = UUID.randomUUID(); - JiraServerJobDetailsModel jiraServerJobDetailsModel = new JiraServerJobDetailsModel(jobId, false, null, null, null, null, null, List.of(), "issueSummary"); + JiraServerJobDetailsModel jiraServerJobDetailsModel = new JiraServerJobDetailsModel(jobId, null, null, null, null, null, List.of(), "issueSummary"); DistributionJobRequestModel distributionJobRequestModel = createDistributionJobEntity(ChannelKeys.JIRA_SERVER.getUniversalKey(), jiraServerJobDetailsModel); - JiraServerJobDetailsEntity jiraServerJobDetailsEntity = new JiraServerJobDetailsEntity(null, false, null, null, null, null, null, null); + JiraServerJobDetailsEntity jiraServerJobDetailsEntity = new JiraServerJobDetailsEntity(null, null, null, null, null, null, null); jiraServerJobDetailsEntity.setJobCustomFields(List.of()); DistributionJobEntity distributionJobEntity = createDistributionJobEntity(jobId, distributionJobRequestModel); distributionJobEntity.setJiraServerJobDetails(jiraServerJobDetailsEntity); diff --git a/alert-database/src/main/java/com/blackduck/integration/alert/database/job/jira/cloud/DefaultJiraCloudJobDetailsAccessor.java b/alert-database/src/main/java/com/blackduck/integration/alert/database/job/jira/cloud/DefaultJiraCloudJobDetailsAccessor.java index f3eb7d5606..9fe03419e2 100644 --- a/alert-database/src/main/java/com/blackduck/integration/alert/database/job/jira/cloud/DefaultJiraCloudJobDetailsAccessor.java +++ b/alert-database/src/main/java/com/blackduck/integration/alert/database/job/jira/cloud/DefaultJiraCloudJobDetailsAccessor.java @@ -44,7 +44,6 @@ public Optional retrieveDetails(UUID jobId) { public JiraCloudJobDetailsEntity saveJiraCloudJobDetails(UUID jobId, JiraCloudJobDetailsModel jiraCloudJobDetails) { JiraCloudJobDetailsEntity jiraCloudJobDetailsToSave = new JiraCloudJobDetailsEntity( jobId, - jiraCloudJobDetails.isAddComments(), jiraCloudJobDetails.getIssueCreatorEmail(), jiraCloudJobDetails.getProjectNameOrKey(), jiraCloudJobDetails.getIssueType(), @@ -77,7 +76,6 @@ private JiraCloudJobDetailsModel convertToModel(JiraCloudJobDetailsEntity jobDet .toList(); return new JiraCloudJobDetailsModel( jobDetails.getJobId(), - jobDetails.getAddComments(), jobDetails.getIssueCreatorEmail(), jobDetails.getProjectNameOrKey(), jobDetails.getIssueType(), diff --git a/alert-database/src/main/java/com/blackduck/integration/alert/database/job/jira/cloud/JiraCloudJobDetailsEntity.java b/alert-database/src/main/java/com/blackduck/integration/alert/database/job/jira/cloud/JiraCloudJobDetailsEntity.java index 67a33e5030..8d92633a9b 100644 --- a/alert-database/src/main/java/com/blackduck/integration/alert/database/job/jira/cloud/JiraCloudJobDetailsEntity.java +++ b/alert-database/src/main/java/com/blackduck/integration/alert/database/job/jira/cloud/JiraCloudJobDetailsEntity.java @@ -26,9 +26,6 @@ public class JiraCloudJobDetailsEntity { @Column(name = "job_id") private UUID jobId; - @Column(name = "add_comments") - private Boolean addComments; - @Column(name = "issue_creator_email") private String issueCreatorEmail; @@ -54,9 +51,8 @@ public class JiraCloudJobDetailsEntity { public JiraCloudJobDetailsEntity() { } - public JiraCloudJobDetailsEntity(UUID jobId, Boolean addComments, String issueCreatorEmail, String projectNameOrKey, String issueType, String resolveTransition, String reopenTransition, String issueSummary) { + public JiraCloudJobDetailsEntity(UUID jobId, String issueCreatorEmail, String projectNameOrKey, String issueType, String resolveTransition, String reopenTransition, String issueSummary) { this.jobId = jobId; - this.addComments = addComments; this.issueCreatorEmail = issueCreatorEmail; this.projectNameOrKey = projectNameOrKey; this.issueType = issueType; @@ -73,14 +69,6 @@ public void setJobId(UUID jobId) { this.jobId = jobId; } - public Boolean getAddComments() { - return addComments; - } - - public void setAddComments(Boolean addComments) { - this.addComments = addComments; - } - public String getIssueCreatorEmail() { return issueCreatorEmail; } diff --git a/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/action/JiraCloudJobDetailsExtractor.java b/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/action/JiraCloudJobDetailsExtractor.java index d3db403d4c..726bf43d93 100644 --- a/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/action/JiraCloudJobDetailsExtractor.java +++ b/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/action/JiraCloudJobDetailsExtractor.java @@ -34,7 +34,6 @@ public JiraCloudJobDetailsExtractor(JiraCloudChannelKey channelKey, Distribution public DistributionJobDetailsModel extractDetails(UUID jobId, Map configuredFieldsMap) { return new JiraCloudJobDetailsModel( jobId, - fieldExtractor.extractFieldValue(JiraCloudDescriptor.KEY_ADD_COMMENTS, configuredFieldsMap).map(Boolean::valueOf).orElse(false), fieldExtractor.extractFieldValueOrEmptyString(JiraCloudDescriptor.KEY_ISSUE_CREATOR, configuredFieldsMap), fieldExtractor.extractFieldValueOrEmptyString(JiraCloudDescriptor.KEY_JIRA_PROJECT_NAME, configuredFieldsMap), fieldExtractor.extractFieldValueOrEmptyString(JiraCloudDescriptor.KEY_ISSUE_TYPE, configuredFieldsMap), diff --git a/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/distribution/delegate/JiraCloudIssueCommenter.java b/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/distribution/delegate/JiraCloudIssueCommenter.java index 36af3bfc32..bf8534b676 100644 --- a/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/distribution/delegate/JiraCloudIssueCommenter.java +++ b/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/distribution/delegate/JiraCloudIssueCommenter.java @@ -26,7 +26,7 @@ public JiraCloudIssueCommenter(IssueTrackerIssueResponseCreator issueResponseCre @Override protected boolean isCommentingEnabled() { - return distributionDetails.isAddComments(); + return true; } @Override diff --git a/channel-jira-cloud/src/test/java/com/blackduck/integration/alert/channel/jira/cloud/JiraCloudIssueCreatorTest.java b/channel-jira-cloud/src/test/java/com/blackduck/integration/alert/channel/jira/cloud/JiraCloudIssueCreatorTest.java index f4297897f5..72c9d58b4f 100644 --- a/channel-jira-cloud/src/test/java/com/blackduck/integration/alert/channel/jira/cloud/JiraCloudIssueCreatorTest.java +++ b/channel-jira-cloud/src/test/java/com/blackduck/integration/alert/channel/jira/cloud/JiraCloudIssueCreatorTest.java @@ -42,7 +42,6 @@ public void verifyIssueSummaryReplacement() throws IntegrationException { String projectNameOrKey = "FakeProject"; JiraCloudJobDetailsModel jiraCloudJobDetailsModel = new JiraCloudJobDetailsModel( UUID.randomUUID(), - false, "my@email.com", projectNameOrKey, "Task", @@ -72,7 +71,6 @@ public void verifySummaryReplacingValues() throws IntegrationException { String projectNameOrKey = "FakeProject"; JiraCloudJobDetailsModel jiraCloudJobDetailsModel = new JiraCloudJobDetailsModel( UUID.randomUUID(), - false, "my@email.com", projectNameOrKey, "Task", diff --git a/channel-jira-cloud/src/test/java/com/blackduck/integration/alert/channel/jira/cloud/JiraCloudSummaryFieldLengthTestIT.java b/channel-jira-cloud/src/test/java/com/blackduck/integration/alert/channel/jira/cloud/JiraCloudSummaryFieldLengthTestIT.java index b6c642b3a6..91d0a7c647 100644 --- a/channel-jira-cloud/src/test/java/com/blackduck/integration/alert/channel/jira/cloud/JiraCloudSummaryFieldLengthTestIT.java +++ b/channel-jira-cloud/src/test/java/com/blackduck/integration/alert/channel/jira/cloud/JiraCloudSummaryFieldLengthTestIT.java @@ -125,7 +125,6 @@ private static JiraCloudJobDetailsModel createJiraCloudJobDetails(TestProperties return new JiraCloudJobDetailsModel( UUID.randomUUID(), - true, issueCreator, projectName, issueType, diff --git a/channel-jira-cloud/src/test/java/com/blackduck/integration/alert/channel/jira/cloud/distribution/event/JiraCloudCommentEventHandlerTest.java b/channel-jira-cloud/src/test/java/com/blackduck/integration/alert/channel/jira/cloud/distribution/event/JiraCloudCommentEventHandlerTest.java index 922a27b83b..db12f40880 100644 --- a/channel-jira-cloud/src/test/java/com/blackduck/integration/alert/channel/jira/cloud/distribution/event/JiraCloudCommentEventHandlerTest.java +++ b/channel-jira-cloud/src/test/java/com/blackduck/integration/alert/channel/jira/cloud/distribution/event/JiraCloudCommentEventHandlerTest.java @@ -167,7 +167,6 @@ void handleCommentTest() throws IntegrationException { private JiraCloudJobDetailsModel createJobDetails(UUID jobId) { return new JiraCloudJobDetailsModel( jobId, - true, "user", "jiraProject", "Task", diff --git a/channel-jira-cloud/src/test/java/com/blackduck/integration/alert/channel/jira/cloud/distribution/event/JiraCloudCreateIssueEventHandlerTest.java b/channel-jira-cloud/src/test/java/com/blackduck/integration/alert/channel/jira/cloud/distribution/event/JiraCloudCreateIssueEventHandlerTest.java index 89d2bcb68b..1138419059 100644 --- a/channel-jira-cloud/src/test/java/com/blackduck/integration/alert/channel/jira/cloud/distribution/event/JiraCloudCreateIssueEventHandlerTest.java +++ b/channel-jira-cloud/src/test/java/com/blackduck/integration/alert/channel/jira/cloud/distribution/event/JiraCloudCreateIssueEventHandlerTest.java @@ -344,7 +344,6 @@ void handleIssueIssueExistsTest() throws IntegrationException { private JiraCloudJobDetailsModel createJobDetails(UUID jobId) { return new JiraCloudJobDetailsModel( jobId, - true, "user", "jiraProject", "Task", diff --git a/channel-jira-cloud/src/test/java/com/blackduck/integration/alert/channel/jira/cloud/distribution/event/JiraCloudTransitionEventHandlerTest.java b/channel-jira-cloud/src/test/java/com/blackduck/integration/alert/channel/jira/cloud/distribution/event/JiraCloudTransitionEventHandlerTest.java index a8b4c4adfd..e28080b74d 100644 --- a/channel-jira-cloud/src/test/java/com/blackduck/integration/alert/channel/jira/cloud/distribution/event/JiraCloudTransitionEventHandlerTest.java +++ b/channel-jira-cloud/src/test/java/com/blackduck/integration/alert/channel/jira/cloud/distribution/event/JiraCloudTransitionEventHandlerTest.java @@ -175,7 +175,6 @@ void handleTransitionTest() throws IntegrationException { private JiraCloudJobDetailsModel createJobDetails(UUID jobId) { return new JiraCloudJobDetailsModel( jobId, - true, "user", "jiraProject", "Task", diff --git a/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/action/JiraServerJobDetailsExtractor.java b/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/action/JiraServerJobDetailsExtractor.java index a5850b5d34..6c8b7a1f4f 100644 --- a/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/action/JiraServerJobDetailsExtractor.java +++ b/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/action/JiraServerJobDetailsExtractor.java @@ -36,7 +36,6 @@ public JiraServerJobDetailsExtractor(JiraServerChannelKey channelKey, Distributi public DistributionJobDetailsModel extractDetails(UUID jobId, Map configuredFieldsMap) { return new JiraServerJobDetailsModel( jobId, - fieldExtractor.extractFieldValue(JiraServerDescriptor.KEY_ADD_COMMENTS, configuredFieldsMap).map(Boolean::valueOf).orElse(false), fieldExtractor.extractFieldValueOrEmptyString(JiraServerDescriptor.KEY_ISSUE_CREATOR, configuredFieldsMap), fieldExtractor.extractFieldValueOrEmptyString(JiraServerDescriptor.KEY_JIRA_PROJECT_NAME, configuredFieldsMap), fieldExtractor.extractFieldValueOrEmptyString(JiraServerDescriptor.KEY_ISSUE_TYPE, configuredFieldsMap), diff --git a/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/database/accessor/DefaultJiraServerJobDetailsAccessor.java b/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/database/accessor/DefaultJiraServerJobDetailsAccessor.java index 2f9cc7a6d2..387c2d70b6 100644 --- a/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/database/accessor/DefaultJiraServerJobDetailsAccessor.java +++ b/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/database/accessor/DefaultJiraServerJobDetailsAccessor.java @@ -64,7 +64,6 @@ public JiraServerJobDetailsModel saveJobDetails(UUID jobId, DistributionJobDetai public JiraServerJobDetailsModel saveConcreteJobDetails(UUID jobId, JiraServerJobDetailsModel jobDetails) { JiraServerJobDetailsEntity jiraServerJobDetailsToSave = new JiraServerJobDetailsEntity( jobId, - true, jobDetails.getIssueCreatorUsername(), jobDetails.getProjectNameOrKey(), jobDetails.getIssueType(), @@ -91,7 +90,6 @@ private JiraServerJobDetailsModel convertToModel(JiraServerJobDetailsEntity jobD .toList(); return new JiraServerJobDetailsModel( jobDetails.getJobId(), - true, jobDetails.getIssueCreatorUsername(), jobDetails.getProjectNameOrKey(), jobDetails.getIssueType(), diff --git a/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/database/job/JiraServerJobDetailsEntity.java b/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/database/job/JiraServerJobDetailsEntity.java index 3d9803dff5..fbfb996c8a 100644 --- a/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/database/job/JiraServerJobDetailsEntity.java +++ b/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/database/job/JiraServerJobDetailsEntity.java @@ -26,9 +26,6 @@ public class JiraServerJobDetailsEntity { @Column(name = "job_id") private UUID jobId; - @Column(name = "add_comments") - private Boolean addComments; - @Column(name = "issue_creator_username") private String issueCreatorUsername; @@ -54,9 +51,8 @@ public class JiraServerJobDetailsEntity { public JiraServerJobDetailsEntity() { } - public JiraServerJobDetailsEntity(UUID jobId, Boolean addComments, String issueCreatorUsername, String projectNameOrKey, String issueType, String resolveTransition, String reopenTransition, String issueSummary) { + public JiraServerJobDetailsEntity(UUID jobId, String issueCreatorUsername, String projectNameOrKey, String issueType, String resolveTransition, String reopenTransition, String issueSummary) { this.jobId = jobId; - this.addComments = addComments; this.issueCreatorUsername = issueCreatorUsername; this.projectNameOrKey = projectNameOrKey; this.issueType = issueType; @@ -73,14 +69,6 @@ public void setJobId(UUID jobId) { this.jobId = jobId; } - public Boolean getAddComments() { - return addComments; - } - - public void setAddComments(Boolean addComments) { - this.addComments = addComments; - } - public String getIssueCreatorUsername() { return issueCreatorUsername; } diff --git a/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/distribution/delegate/JiraServerIssueCommenter.java b/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/distribution/delegate/JiraServerIssueCommenter.java index fe5888013d..345fa77303 100644 --- a/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/distribution/delegate/JiraServerIssueCommenter.java +++ b/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/distribution/delegate/JiraServerIssueCommenter.java @@ -26,7 +26,7 @@ public JiraServerIssueCommenter(IssueTrackerIssueResponseCreator issueResponseCr @Override protected boolean isCommentingEnabled() { - return distributionDetails.isAddComments(); + return true; } @Override diff --git a/channel-jira-server/src/test/java/com/blackduck/integration/alert/channel/jira/server/JiraServerExternalConnectionTest.java b/channel-jira-server/src/test/java/com/blackduck/integration/alert/channel/jira/server/JiraServerExternalConnectionTest.java index b0b3fd3a56..ccfbb16986 100644 --- a/channel-jira-server/src/test/java/com/blackduck/integration/alert/channel/jira/server/JiraServerExternalConnectionTest.java +++ b/channel-jira-server/src/test/java/com/blackduck/integration/alert/channel/jira/server/JiraServerExternalConnectionTest.java @@ -146,7 +146,6 @@ private JiraServerJobDetailsModel createDistributionDetails() { return new JiraServerJobDetailsModel( uuid, - Boolean.parseBoolean(testProperties.getProperty(TestPropertyKey.TEST_JIRA_SERVER_ADD_COMMENTS)), testProperties.getOptionalProperty(TestPropertyKey.TEST_JIRA_SERVER_ISSUE_CREATOR).orElse(null), testProperties.getProperty(TestPropertyKey.TEST_JIRA_SERVER_PROJECT_NAME), testProperties.getProperty(TestPropertyKey.TEST_JIRA_SERVER_ISSUE_TYPE), diff --git a/channel-jira-server/src/test/java/com/blackduck/integration/alert/channel/jira/server/JiraServerSummaryFieldLengthTestIT.java b/channel-jira-server/src/test/java/com/blackduck/integration/alert/channel/jira/server/JiraServerSummaryFieldLengthTestIT.java index 1862368ab7..2f25504faf 100644 --- a/channel-jira-server/src/test/java/com/blackduck/integration/alert/channel/jira/server/JiraServerSummaryFieldLengthTestIT.java +++ b/channel-jira-server/src/test/java/com/blackduck/integration/alert/channel/jira/server/JiraServerSummaryFieldLengthTestIT.java @@ -135,7 +135,6 @@ private static JiraServerJobDetailsModel createJiraServerJobDetails(TestProperti return new JiraServerJobDetailsModel( UUID.randomUUID(), - true, issueCreator, projectName, issueType, diff --git a/channel-jira-server/src/test/java/com/blackduck/integration/alert/channel/jira/server/database/accessor/JiraServerJobDetailsAccessorTest.java b/channel-jira-server/src/test/java/com/blackduck/integration/alert/channel/jira/server/database/accessor/JiraServerJobDetailsAccessorTest.java index 896cb1e1ed..b9ae625313 100644 --- a/channel-jira-server/src/test/java/com/blackduck/integration/alert/channel/jira/server/database/accessor/JiraServerJobDetailsAccessorTest.java +++ b/channel-jira-server/src/test/java/com/blackduck/integration/alert/channel/jira/server/database/accessor/JiraServerJobDetailsAccessorTest.java @@ -91,12 +91,12 @@ void retrieveDetailsUnknownIdTest() { } private JiraServerJobDetailsModel createDetailsModel(JiraServerJobDetailsEntity jobDetailsModel) { - return new JiraServerJobDetailsModel(jobDetailsModel.getJobId(), jobDetailsModel.getAddComments(), jobDetailsModel.getIssueCreatorUsername(), jobDetailsModel.getProjectNameOrKey(), + return new JiraServerJobDetailsModel(jobDetailsModel.getJobId(), jobDetailsModel.getIssueCreatorUsername(), jobDetailsModel.getProjectNameOrKey(), jobDetailsModel.getIssueType(), jobDetailsModel.getResolveTransition(), jobDetailsModel.getReopenTransition(), createCustomFieldModels(), jobDetailsModel.getIssueSummary()); } private JiraServerJobDetailsEntity createDetailsEntity(UUID jobId) { - return new JiraServerJobDetailsEntity(jobId, false, "user", "project", + return new JiraServerJobDetailsEntity(jobId, "user", "project", "Task", "Resolve", "Reopen", "summary"); } diff --git a/channel-jira-server/src/test/java/com/blackduck/integration/alert/channel/jira/server/distribution/delegate/JiraServerIssueCreatorTest.java b/channel-jira-server/src/test/java/com/blackduck/integration/alert/channel/jira/server/distribution/delegate/JiraServerIssueCreatorTest.java index ea8a6537d1..98302efef0 100644 --- a/channel-jira-server/src/test/java/com/blackduck/integration/alert/channel/jira/server/distribution/delegate/JiraServerIssueCreatorTest.java +++ b/channel-jira-server/src/test/java/com/blackduck/integration/alert/channel/jira/server/distribution/delegate/JiraServerIssueCreatorTest.java @@ -54,7 +54,6 @@ public class JiraServerIssueCreatorTest { final String TEST_TITLE = "title"; final JiraServerJobDetailsModel distributionDetails = new JiraServerJobDetailsModel( UUID.randomUUID(), - true, TEST_ISSUE_CREATOR_NAME, TEST_PROJECT_NAME_OR_KEY, TEST_ISSUE_TYPE, @@ -121,7 +120,6 @@ void createRequestxUsingIssueSummaryAsTitle() throws AlertException { void createRequestReturnsCorrectModelUsingTitle() throws AlertException { JiraServerJobDetailsModel distDetailsEmptyIssueSummary = new JiraServerJobDetailsModel( UUID.randomUUID(), - true, TEST_ISSUE_CREATOR_NAME, TEST_PROJECT_NAME_OR_KEY, TEST_ISSUE_TYPE, diff --git a/channel-jira-server/src/test/java/com/blackduck/integration/alert/channel/jira/server/distribution/event/JiraServerCommentEventHandlerTest.java b/channel-jira-server/src/test/java/com/blackduck/integration/alert/channel/jira/server/distribution/event/JiraServerCommentEventHandlerTest.java index d26d837ea3..578810842b 100644 --- a/channel-jira-server/src/test/java/com/blackduck/integration/alert/channel/jira/server/distribution/event/JiraServerCommentEventHandlerTest.java +++ b/channel-jira-server/src/test/java/com/blackduck/integration/alert/channel/jira/server/distribution/event/JiraServerCommentEventHandlerTest.java @@ -181,7 +181,6 @@ void handleCommentTest() throws IntegrationException { private JiraServerJobDetailsModel createJobDetails(UUID jobId) { return new JiraServerJobDetailsModel( jobId, - true, "user", "jiraProject", "Task", diff --git a/channel-jira-server/src/test/java/com/blackduck/integration/alert/channel/jira/server/distribution/event/JiraServerCreateIssueEventHandlerTest.java b/channel-jira-server/src/test/java/com/blackduck/integration/alert/channel/jira/server/distribution/event/JiraServerCreateIssueEventHandlerTest.java index d132d7ed11..7432a3fc7d 100644 --- a/channel-jira-server/src/test/java/com/blackduck/integration/alert/channel/jira/server/distribution/event/JiraServerCreateIssueEventHandlerTest.java +++ b/channel-jira-server/src/test/java/com/blackduck/integration/alert/channel/jira/server/distribution/event/JiraServerCreateIssueEventHandlerTest.java @@ -352,7 +352,6 @@ void handleIssueIssueExistsTest() throws IntegrationException { private JiraServerJobDetailsModel createJobDetails(UUID jobId) { return new JiraServerJobDetailsModel( jobId, - true, "user", "jiraProject", "Task", diff --git a/channel-jira-server/src/test/java/com/blackduck/integration/alert/channel/jira/server/distribution/event/JiraServerTransitionEventHandlerTest.java b/channel-jira-server/src/test/java/com/blackduck/integration/alert/channel/jira/server/distribution/event/JiraServerTransitionEventHandlerTest.java index 8fac835c5c..220be6e363 100644 --- a/channel-jira-server/src/test/java/com/blackduck/integration/alert/channel/jira/server/distribution/event/JiraServerTransitionEventHandlerTest.java +++ b/channel-jira-server/src/test/java/com/blackduck/integration/alert/channel/jira/server/distribution/event/JiraServerTransitionEventHandlerTest.java @@ -189,7 +189,6 @@ void handleTransitionTest() throws IntegrationException { private JiraServerJobDetailsModel createJobDetails(UUID jobId) { return new JiraServerJobDetailsModel( jobId, - true, "user", "jiraProject", "Task", diff --git a/src/test/java/com/blackduck/integration/alert/database/job/api/StaticJobAccessorTestIT.java b/src/test/java/com/blackduck/integration/alert/database/job/api/StaticJobAccessorTestIT.java index cb8cf19612..7dff4cda29 100644 --- a/src/test/java/com/blackduck/integration/alert/database/job/api/StaticJobAccessorTestIT.java +++ b/src/test/java/com/blackduck/integration/alert/database/job/api/StaticJobAccessorTestIT.java @@ -73,7 +73,6 @@ void verifyAzureSavesTest() { void verifyJiraServerSavesTest() { JiraServerJobDetailsModel jiraServerJobDetailsModel = new JiraServerJobDetailsModel( UUID.randomUUID(), - true, "issueCreatorUsername", "projectNameOrKey", "issueType", @@ -91,7 +90,6 @@ void verifyJiraServerSavesTest() { void verifyJiraCloudSavesTest() { JiraCloudJobDetailsModel jiraCloudJobDetailsModel = new JiraCloudJobDetailsModel( UUID.randomUUID(), - true, "issueCreatorEmail", "projectNameOrKey", "issueType", diff --git a/web/src/main/java/com/blackduck/integration/alert/web/api/job/JobFieldModelPopulationUtils.java b/web/src/main/java/com/blackduck/integration/alert/web/api/job/JobFieldModelPopulationUtils.java index 1badf7f36d..cf1a658624 100644 --- a/web/src/main/java/com/blackduck/integration/alert/web/api/job/JobFieldModelPopulationUtils.java +++ b/web/src/main/java/com/blackduck/integration/alert/web/api/job/JobFieldModelPopulationUtils.java @@ -156,7 +156,6 @@ private static void populateEmailFields(FieldModel channelFieldModel, EmailJobDe private static void populateJiraCloudFields(FieldModel channelFieldModel, JiraCloudJobDetailsModel jiraCloudJobDetails) { if (null != jiraCloudJobDetails) { - putField(channelFieldModel, JiraCloudDescriptor.KEY_ADD_COMMENTS, Boolean.toString(jiraCloudJobDetails.isAddComments())); putField(channelFieldModel, JiraCloudDescriptor.KEY_ISSUE_CREATOR, jiraCloudJobDetails.getIssueCreatorEmail()); putField(channelFieldModel, JiraCloudDescriptor.KEY_JIRA_PROJECT_NAME, jiraCloudJobDetails.getProjectNameOrKey()); putField(channelFieldModel, JiraCloudDescriptor.KEY_ISSUE_TYPE, jiraCloudJobDetails.getIssueType()); @@ -169,7 +168,6 @@ private static void populateJiraCloudFields(FieldModel channelFieldModel, JiraCl private static void populateJiraServerFields(FieldModel channelFieldModel, JiraServerJobDetailsModel jiraServerJobDetails) { if (null != jiraServerJobDetails) { - putField(channelFieldModel, JiraServerDescriptor.KEY_ADD_COMMENTS, Boolean.toString(jiraServerJobDetails.isAddComments())); putField(channelFieldModel, JiraServerDescriptor.KEY_ISSUE_CREATOR, jiraServerJobDetails.getIssueCreatorUsername()); putField(channelFieldModel, JiraServerDescriptor.KEY_JIRA_PROJECT_NAME, jiraServerJobDetails.getProjectNameOrKey()); putField(channelFieldModel, JiraServerDescriptor.KEY_ISSUE_TYPE, jiraServerJobDetails.getIssueType()); From ececc44badb229255d75b18d4e93f0a5107e0eba Mon Sep 17 00:00:00 2001 From: Paulo Santos Date: Wed, 13 Aug 2025 14:09:06 -0400 Subject: [PATCH 03/18] IALERT-3868: Remove add_comments column. --- .../src/main/resources/liquibase/9.0.0/changelog.xml | 6 ++++++ .../9.0.0/jira-cloud-job-details-remove-comments.xml | 10 ++++++++++ .../9.0.0/jira-server-job-details-remove-comments.xml | 10 ++++++++++ .../resources/liquibase/changelog-postgres-master.xml | 1 + 4 files changed, 27 insertions(+) create mode 100644 alert-database/src/main/resources/liquibase/9.0.0/changelog.xml create mode 100644 alert-database/src/main/resources/liquibase/9.0.0/jira-cloud-job-details-remove-comments.xml create mode 100644 alert-database/src/main/resources/liquibase/9.0.0/jira-server-job-details-remove-comments.xml diff --git a/alert-database/src/main/resources/liquibase/9.0.0/changelog.xml b/alert-database/src/main/resources/liquibase/9.0.0/changelog.xml new file mode 100644 index 0000000000..fcb1e9ee01 --- /dev/null +++ b/alert-database/src/main/resources/liquibase/9.0.0/changelog.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/alert-database/src/main/resources/liquibase/9.0.0/jira-cloud-job-details-remove-comments.xml b/alert-database/src/main/resources/liquibase/9.0.0/jira-cloud-job-details-remove-comments.xml new file mode 100644 index 0000000000..9dd1efa26f --- /dev/null +++ b/alert-database/src/main/resources/liquibase/9.0.0/jira-cloud-job-details-remove-comments.xml @@ -0,0 +1,10 @@ + + + + + + + + + \ No newline at end of file diff --git a/alert-database/src/main/resources/liquibase/9.0.0/jira-server-job-details-remove-comments.xml b/alert-database/src/main/resources/liquibase/9.0.0/jira-server-job-details-remove-comments.xml new file mode 100644 index 0000000000..13d860a1fb --- /dev/null +++ b/alert-database/src/main/resources/liquibase/9.0.0/jira-server-job-details-remove-comments.xml @@ -0,0 +1,10 @@ + + + + + + + + + \ No newline at end of file diff --git a/alert-database/src/main/resources/liquibase/changelog-postgres-master.xml b/alert-database/src/main/resources/liquibase/changelog-postgres-master.xml index d976618db4..53784e6f70 100644 --- a/alert-database/src/main/resources/liquibase/changelog-postgres-master.xml +++ b/alert-database/src/main/resources/liquibase/changelog-postgres-master.xml @@ -31,4 +31,5 @@ + From b43bca8bbdb4b29c7fc4dddfcd0095841073788a Mon Sep 17 00:00:00 2001 From: Paulo Santos Date: Thu, 14 Aug 2025 08:32:34 -0400 Subject: [PATCH 04/18] IALERT-3868: Make disable plugin check the default behavior. --- ui/src/main/js/common/util/fieldModelUtilities.js | 7 +++++++ .../jira/cloud/JiraCloudGlobalConfiguration.js | 14 ++++++++++++-- .../js/page/channel/jira/server/JiraServerModal.js | 5 +++-- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/ui/src/main/js/common/util/fieldModelUtilities.js b/ui/src/main/js/common/util/fieldModelUtilities.js index fead8b2bd4..612c800710 100644 --- a/ui/src/main/js/common/util/fieldModelUtilities.js +++ b/ui/src/main/js/common/util/fieldModelUtilities.js @@ -278,6 +278,13 @@ export const handleTestChange = (testData, setTestData) => ({ target }) => { setTestData(newState); }; +export const createBooleanInputChangeHandler = (testData, setTestData) => ({ target }) => { + const { type, name, value } = target; + const updatedValue = type === 'checkbox' ? target.checked : value; + const newState = { ...testData, [name]: updatedValue }; + setTestData(newState); +}; + export const handleConcreteModelChange = (data, setData) => ({ target }) => { const { type, name, value } = target; let updatedValue = type === 'checkbox' ? target.checked : value; diff --git a/ui/src/main/js/page/channel/jira/cloud/JiraCloudGlobalConfiguration.js b/ui/src/main/js/page/channel/jira/cloud/JiraCloudGlobalConfiguration.js index a90cb5488e..bbbca83764 100644 --- a/ui/src/main/js/page/channel/jira/cloud/JiraCloudGlobalConfiguration.js +++ b/ui/src/main/js/page/channel/jira/cloud/JiraCloudGlobalConfiguration.js @@ -15,13 +15,23 @@ import * as GlobalRequestHelper from 'common/configuration/global/GlobalRequestH const JiraCloudGlobalConfiguration = ({ csrfToken, errorHandler, readonly, displayTest, displaySave, displayDelete }) => { - const [formData, setFormData] = useState(FieldModelUtilities.createEmptyFieldModel([], CONTEXT_TYPE.GLOBAL, JIRA_CLOUD_INFO.key)); + const initModelFunction = () => { + let initModel = FieldModelUtilities.createEmptyFieldModel([], CONTEXT_TYPE.GLOBAL, JIRA_CLOUD_INFO.key); + initModel = FieldModelUtilities.updateFieldModelSingleValue(initModel, JIRA_CLOUD_GLOBAL_FIELD_KEYS.disablePluginCheck, 'true'); + return initModel; + }; + const [formData, setFormData] = useState(initModelFunction()); const [errors, setErrors] = useState(HttpErrorUtilities.createEmptyErrorObject()); const retrieveData = async () => { const data = await GlobalRequestHelper.getDataFindFirst(JIRA_CLOUD_INFO.key, csrfToken); if (data) { - setFormData(data); + let updateData = { ...data }; + // if the Jira cloud configuration isn't set then keyToValues will be empty and have no keys. Add the default value in this case. + if (data.keyToValues && Object.keys(data.keyToValues).length <= 0) { + updateData = FieldModelUtilities.updateFieldModelSingleValue(data, JIRA_CLOUD_GLOBAL_FIELD_KEYS.disablePluginCheck, 'true'); + } + setFormData(updateData); } }; diff --git a/ui/src/main/js/page/channel/jira/server/JiraServerModal.js b/ui/src/main/js/page/channel/jira/server/JiraServerModal.js index 46be8d6683..3f6b808d97 100644 --- a/ui/src/main/js/page/channel/jira/server/JiraServerModal.js +++ b/ui/src/main/js/page/channel/jira/server/JiraServerModal.js @@ -56,7 +56,8 @@ const JiraServerModal = ({ data, isOpen, toggleModal, modalOptions, setStatusMes const classes = useStyles(); const dispatch = useDispatch(); const { copyDescription, submitText, title, type } = modalOptions; - const [jiraServerModel, setJiraServerModel] = useState(type === 'CREATE' ? { authorizationMethod: 'BASIC' } : getInitialData(type, data)); + const [jiraServerModel, setJiraServerModel] = useState(type === 'CREATE' ? { authorizationMethod: 'BASIC', + disablePluginCheck: true } : getInitialData(type, data)); const [showLoader, setShowLoader] = useState(false); const [requestType, setRequestType] = useState(); const [notificationConfig, setNotificationConfig] = useState(); @@ -285,7 +286,7 @@ const JiraServerModal = ({ data, isOpen, toggleModal, modalOptions, setStatusMes label="Disable Plugin Check" customDescription="This will disable checking whether the 'Alert Issue Property Indexer' plugin is installed on the specified Jira instance. Please ensure that the plugin is manually installed before using Alert with Jira. If not, issues created by Alert will not be updated properly, and duplicate issues may be created." readOnly={readonly} - onChange={FieldModelUtilities.handleTestChange(jiraServerModel, setJiraServerModel)} + onChange={FieldModelUtilities.createBooleanInputChangeHandler(jiraServerModel, setJiraServerModel)} isChecked={jiraServerModel.disablePluginCheck} errorName={JIRA_SERVER_GLOBAL_FIELD_KEYS.disablePluginCheck} errorValue={error.fieldErrors.disablePluginCheck} From d5a32833cfb7a3ea650b2a44ed5af0c22b166189 Mon Sep 17 00:00:00 2001 From: Paulo Santos Date: Wed, 20 Aug 2025 11:18:24 -0400 Subject: [PATCH 05/18] IALERT-3873: Initial implementation of tasks. --- .../task/JiraCloudSchedulingManager.java | 5 +- .../task/JiraSearchCommentUpdateTask.java | 35 ++++++++++++++ .../task/JiraSearchCommentUpdateTask.java | 46 +++++++++++++++++++ .../task/JiraServerSchedulingManager.java | 5 +- 4 files changed, 87 insertions(+), 4 deletions(-) create mode 100644 channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraSearchCommentUpdateTask.java create mode 100644 channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraSearchCommentUpdateTask.java diff --git a/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraCloudSchedulingManager.java b/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraCloudSchedulingManager.java index 29f1bc896c..1abf8033e3 100644 --- a/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraCloudSchedulingManager.java +++ b/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraCloudSchedulingManager.java @@ -46,7 +46,8 @@ public void unscheduleTasks(String configId) { private List createTasks(FieldModel fieldModel, Set projectNameOrKeys) { String configId = fieldModel.getId(); String configName = fieldModel.getFieldValue(ChannelDescriptor.KEY_NAME).orElse(""); - JiraPropertyUpdateTask task = new JiraPropertyUpdateTask(taskScheduler, taskManager, jiraPropertiesFactory, gson, configId, configName, "JiraCloud", projectNameOrKeys); - return List.of(task); + JiraPropertyUpdateTask propertyTask = new JiraPropertyUpdateTask(taskScheduler, taskManager, jiraPropertiesFactory, gson, configId, configName, "JiraCloud", projectNameOrKeys); + JiraSearchCommentUpdateTask searchCommentTask = new JiraSearchCommentUpdateTask(taskScheduler, taskManager, jiraPropertiesFactory, gson, configId, configName, "JiraCloud", projectNameOrKeys); + return List.of(propertyTask, searchCommentTask); } } diff --git a/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraSearchCommentUpdateTask.java b/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraSearchCommentUpdateTask.java new file mode 100644 index 0000000000..9160c20b05 --- /dev/null +++ b/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraSearchCommentUpdateTask.java @@ -0,0 +1,35 @@ +package com.blackduck.integration.alert.channel.jira.cloud.task; + +import com.blackduck.integration.alert.api.channel.jira.lifecycle.JiraTask; +import com.blackduck.integration.alert.api.task.ScheduledTask; +import com.blackduck.integration.alert.api.task.TaskManager; +import com.blackduck.integration.alert.channel.jira.cloud.JiraCloudPropertiesFactory; +import com.google.gson.Gson; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.scheduling.TaskScheduler; + +import java.util.Set; + +public class JiraSearchCommentUpdateTask extends JiraTask { + private Logger logger = LoggerFactory.getLogger(getClass()); + private final JiraCloudPropertiesFactory jiraPropertiesFactory; + private final Set projectNamesOrKeys; + + public JiraSearchCommentUpdateTask(TaskScheduler taskScheduler, TaskManager taskManager, JiraCloudPropertiesFactory jiraPropertiesFactory, Gson gson, String configId, String configName, String taskNameSuffix, Set projectNamesOrKeys) { + super(taskScheduler, taskManager, configId, configName, taskNameSuffix, gson); + this.jiraPropertiesFactory = jiraPropertiesFactory; + this.projectNamesOrKeys = projectNamesOrKeys; + } + + @Override + protected void executeTaskImplementation() { + logger.info("Executing Jira Search Comment Update Task"); + + } + + @Override + public String scheduleCronExpression() { + return ScheduledTask.EVERY_30_SECONDS_CRON_EXPRESSION; + } +} diff --git a/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraSearchCommentUpdateTask.java b/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraSearchCommentUpdateTask.java new file mode 100644 index 0000000000..053a3dc95d --- /dev/null +++ b/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraSearchCommentUpdateTask.java @@ -0,0 +1,46 @@ +package com.blackduck.integration.alert.channel.jira.server.task; + +import com.blackduck.integration.alert.api.channel.jira.lifecycle.JiraTask; +import com.blackduck.integration.alert.api.task.ScheduledTask; +import com.blackduck.integration.alert.api.task.TaskManager; +import com.blackduck.integration.alert.channel.jira.server.JiraServerPropertiesFactory; +import com.blackduck.integration.exception.IntegrationException; +import com.google.gson.Gson; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.scheduling.TaskScheduler; + +import java.util.Set; +import java.util.UUID; + +public class JiraSearchCommentUpdateTask extends JiraTask { + private Logger logger = LoggerFactory.getLogger(getClass()); + private final JiraServerPropertiesFactory jiraPropertiesFactory; + private final Set projectNamesOrKeys; + + public JiraSearchCommentUpdateTask(TaskScheduler taskScheduler, TaskManager taskManager, JiraServerPropertiesFactory jiraPropertiesFactory, Gson gson, String configId, String configName, String taskNameSuffix, Set projectNamesOrKeys) { + super(taskScheduler, taskManager, configId, configName, taskNameSuffix, gson); + this.jiraPropertiesFactory = jiraPropertiesFactory; + this.projectNamesOrKeys = projectNamesOrKeys; + } + + @Override + protected void executeTaskImplementation() { + logger.info("Jira Server search comment task started."); + UUID configId = UUID.fromString(getConfigId()); + try { + } catch (IntegrationException e) { + logger.error("Error getting Jira Server Configuration.", e); + } catch (InterruptedException e) { + logger.error("Error updating Jira Server issues with new search key comment.", e); + Thread.currentThread().interrupt(); + } + + logger.info("Jira Server property migrator task ended."); + } + + @Override + public String scheduleCronExpression() { + return ScheduledTask.EVERY_30_SECONDS_CRON_EXPRESSION; + } +} diff --git a/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraServerSchedulingManager.java b/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraServerSchedulingManager.java index 6d444bf372..d8411ecbbc 100644 --- a/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraServerSchedulingManager.java +++ b/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraServerSchedulingManager.java @@ -44,7 +44,8 @@ public void unscheduleTasks(UUID configId) { } private List createTasks(JiraServerGlobalConfigModel configModel, Set projectNameOrKeys) { - JiraPropertyUpdateTask task = new JiraPropertyUpdateTask(taskScheduler, taskManager, jiraPropertiesFactory, gson, configModel.getId(), configModel.getName(), "JiraServer", projectNameOrKeys); - return List.of(task); + JiraPropertyUpdateTask propertyTask = new JiraPropertyUpdateTask(taskScheduler, taskManager, jiraPropertiesFactory, gson, configModel.getId(), configModel.getName(), "JiraServer", projectNameOrKeys); + JiraSearchCommentUpdateTask searchCommentTask = new JiraSearchCommentUpdateTask(taskScheduler, taskManager, jiraPropertiesFactory, gson, configModel.getId(), configModel.getName(), "JiraServer", projectNameOrKeys); + return List.of(propertyTask, searchCommentTask); } } From 8d55ecb9cd0c26d64191adb2f01134087951c13a Mon Sep 17 00:00:00 2001 From: Paulo Santos Date: Thu, 21 Aug 2025 09:39:13 -0400 Subject: [PATCH 06/18] IALERT-3873: Rename JiraTask to JiraPropertyTask. --- .../{JiraTask.java => JiraPropertyTask.java} | 14 ++++++++------ .../jira/lifecycle/JiraSchedulingManager.java | 14 +++++++------- .../cloud/task/JiraCloudSchedulingManager.java | 8 ++++---- .../jira/cloud/task/JiraPropertyUpdateTask.java | 11 ++++++++--- .../jira/server/task/JiraPropertyUpdateTask.java | 11 ++++++++--- .../server/task/JiraServerSchedulingManager.java | 8 ++++---- 6 files changed, 39 insertions(+), 27 deletions(-) rename api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/lifecycle/{JiraTask.java => JiraPropertyTask.java} (89%) diff --git a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/lifecycle/JiraTask.java b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/lifecycle/JiraPropertyTask.java similarity index 89% rename from api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/lifecycle/JiraTask.java rename to api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/lifecycle/JiraPropertyTask.java index d07d81ea2d..74285144bf 100644 --- a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/lifecycle/JiraTask.java +++ b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/lifecycle/JiraPropertyTask.java @@ -20,7 +20,7 @@ import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; -public abstract class JiraTask extends ScheduledTask { +public abstract class JiraPropertyTask extends ScheduledTask { private final Logger logger = LoggerFactory.getLogger(this.getClass()); // find tickets created by alert first: // 1. A summary that starts with "Alert - Black Duck" @@ -44,7 +44,7 @@ public static String createProjectSpecificQuery(String projectName) { private final String configName; private final Gson gson; - protected JiraTask(TaskScheduler taskScheduler, TaskManager taskManager, String configId, String configName, String taskNameSuffix, Gson gson) { + protected JiraPropertyTask(TaskScheduler taskScheduler, TaskManager taskManager, String configId, String configName, String taskNameSuffix, Gson gson) { super(taskScheduler); this.taskManager = taskManager; this.configId = configId; @@ -60,20 +60,22 @@ public final void runTask() { protected abstract void executeTaskImplementation(); - protected void updateIssues(List issueKeys,Integer totalIssues, IssuePropertyService issuePropertyService) throws InterruptedException { + protected void updateIssues(List issueKeys,Integer totalIssues, IssuePropertyService issuePropertyService, String loggingTaskName) throws InterruptedException { ExecutorService executorService = getExecutorService(); for (String issueKey : issueKeys) { - executorService.submit(() -> setIssueProperty(issueKey, issuePropertyService)); + executorService.submit(createUpdateRunnable(issueKey, issuePropertyService)); } executorService.shutdown(); boolean success = executorService.awaitTermination(1, TimeUnit.MINUTES); if (success) { - logger.info("Jira property migrator task remaining issues {} ", totalIssues); + logger.info("Jira {} task remaining issues {} ", loggingTaskName, totalIssues); } else { - logger.info("Jira property migrator task timed out updating issues; will resume with the next iteration."); + logger.info("Jira {} task timed out updating issues; will resume with the next iteration.", loggingTaskName); } } + protected abstract Runnable createUpdateRunnable(String issueKey, IssuePropertyService issuePropertyService); + protected void setIssueProperty(String issueKey, IssuePropertyService issuePropertyService) { try { String propertyValue = getCurrentPropertyValue(issueKey, issuePropertyService); diff --git a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/lifecycle/JiraSchedulingManager.java b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/lifecycle/JiraSchedulingManager.java index 10f54be36b..c1191584e8 100644 --- a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/lifecycle/JiraSchedulingManager.java +++ b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/lifecycle/JiraSchedulingManager.java @@ -19,9 +19,9 @@ public JiraSchedulingManager(TaskManager taskManager) { this.taskManager = taskManager; } - public List scheduleTasks(List tasks) { - List acceptedTasks = new ArrayList<>(); - for (JiraTask task : tasks) { + public List scheduleTasks(List tasks) { + List acceptedTasks = new ArrayList<>(); + for (JiraPropertyTask task : tasks) { unscheduleTasks(task.getConfigId()); logger.debug("Perform scheduling jira tasks for config with id {} and name {}", task.getConfigId(), task.getConfigName()); if (taskManager.getNextRunTime(task.getTaskName()).isEmpty()) { @@ -37,23 +37,23 @@ public List scheduleTasks(List tasks) { public void unscheduleTasks(String configId) { logger.debug("Performing unscheduling jira tasks for config: id={}", configId); - List tasks = taskManager.getTasksByClass(JiraTask.class) + List tasks = taskManager.getTasksByClass(JiraPropertyTask.class) .stream() .filter(task -> task.getConfigId().equals(configId)) .toList(); - for (JiraTask task : tasks) { + for (JiraPropertyTask task : tasks) { unscheduleTask(task); } logger.debug("Finished unscheduling jira tasks for config: id={}", configId); } - private void scheduleTask(JiraTask task) { + private void scheduleTask(JiraPropertyTask task) { taskManager.registerTask(task); taskManager.scheduleCronTask(task.scheduleCronExpression(), task.getTaskName()); } - private void unscheduleTask(JiraTask task) { + private void unscheduleTask(JiraPropertyTask task) { taskManager.unregisterTask(task.getTaskName()); } } diff --git a/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraCloudSchedulingManager.java b/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraCloudSchedulingManager.java index 1abf8033e3..f4fc006380 100644 --- a/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraCloudSchedulingManager.java +++ b/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraCloudSchedulingManager.java @@ -1,7 +1,7 @@ package com.blackduck.integration.alert.channel.jira.cloud.task; import com.blackduck.integration.alert.api.channel.jira.lifecycle.JiraSchedulingManager; -import com.blackduck.integration.alert.api.channel.jira.lifecycle.JiraTask; +import com.blackduck.integration.alert.api.channel.jira.lifecycle.JiraPropertyTask; import com.blackduck.integration.alert.api.task.TaskManager; import com.blackduck.integration.alert.channel.jira.cloud.JiraCloudPropertiesFactory; import com.blackduck.integration.alert.common.descriptor.ChannelDescriptor; @@ -31,11 +31,11 @@ public JiraCloudSchedulingManager(Gson gson, JiraSchedulingManager jiraSchedulin this.jiraPropertiesFactory = jiraPropertiesFactory; } - public List scheduleTasks(FieldModel fieldModel) { + public List scheduleTasks(FieldModel fieldModel) { return scheduleTasks(fieldModel, Set.of()); } - public List scheduleTasks(FieldModel fieldModel, Set projectNameOrKeys) { + public List scheduleTasks(FieldModel fieldModel, Set projectNameOrKeys) { return jiraSchedulingManager.scheduleTasks(createTasks(fieldModel, projectNameOrKeys)); } @@ -43,7 +43,7 @@ public void unscheduleTasks(String configId) { jiraSchedulingManager.unscheduleTasks(configId); } - private List createTasks(FieldModel fieldModel, Set projectNameOrKeys) { + private List createTasks(FieldModel fieldModel, Set projectNameOrKeys) { String configId = fieldModel.getId(); String configName = fieldModel.getFieldValue(ChannelDescriptor.KEY_NAME).orElse(""); JiraPropertyUpdateTask propertyTask = new JiraPropertyUpdateTask(taskScheduler, taskManager, jiraPropertiesFactory, gson, configId, configName, "JiraCloud", projectNameOrKeys); diff --git a/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraPropertyUpdateTask.java b/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraPropertyUpdateTask.java index cc119854af..c910ed0db5 100644 --- a/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraPropertyUpdateTask.java +++ b/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraPropertyUpdateTask.java @@ -1,6 +1,6 @@ package com.blackduck.integration.alert.channel.jira.cloud.task; -import com.blackduck.integration.alert.api.channel.jira.lifecycle.JiraTask; +import com.blackduck.integration.alert.api.channel.jira.lifecycle.JiraPropertyTask; import com.blackduck.integration.alert.api.task.ScheduledTask; import com.blackduck.integration.alert.api.task.TaskManager; import com.blackduck.integration.alert.channel.jira.cloud.JiraCloudProperties; @@ -20,7 +20,7 @@ import java.util.List; import java.util.Set; -public class JiraPropertyUpdateTask extends JiraTask { +public class JiraPropertyUpdateTask extends JiraPropertyTask { private final Logger logger = LoggerFactory.getLogger(this.getClass()); private final JiraCloudPropertiesFactory jiraPropertiesFactory; private final Set projectNamesOrKeys; @@ -71,6 +71,11 @@ protected void executeTaskImplementation() { } } + @Override + protected Runnable createUpdateRunnable(String issueKey, IssuePropertyService issuePropertyService) { + return () -> setIssueProperty(issueKey, issuePropertyService); + } + private boolean updateIssues(IssueSearchResponseModel responseModel, IssuePropertyService issuePropertyService) throws InterruptedException { int totalIssues = responseModel.getTotal(); boolean foundIssues = totalIssues > 0; @@ -79,7 +84,7 @@ private boolean updateIssues(IssueSearchResponseModel responseModel, IssueProper List issueKeys = responseModel.getIssues().stream() .map(IssueResponseModel::getKey) .toList(); - updateIssues(issueKeys, totalIssues, issuePropertyService); + updateIssues(issueKeys, totalIssues, issuePropertyService, "property migrator"); } return foundIssues; } diff --git a/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraPropertyUpdateTask.java b/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraPropertyUpdateTask.java index 2c033eea69..0897ec7cd1 100644 --- a/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraPropertyUpdateTask.java +++ b/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraPropertyUpdateTask.java @@ -1,6 +1,6 @@ package com.blackduck.integration.alert.channel.jira.server.task; -import com.blackduck.integration.alert.api.channel.jira.lifecycle.JiraTask; +import com.blackduck.integration.alert.api.channel.jira.lifecycle.JiraPropertyTask; import com.blackduck.integration.alert.api.task.ScheduledTask; import com.blackduck.integration.alert.api.task.TaskManager; import com.blackduck.integration.alert.channel.jira.server.JiraServerProperties; @@ -21,7 +21,7 @@ import java.util.Set; import java.util.UUID; -public class JiraPropertyUpdateTask extends JiraTask { +public class JiraPropertyUpdateTask extends JiraPropertyTask { private final Logger logger = LoggerFactory.getLogger(this.getClass()); private final JiraServerPropertiesFactory jiraPropertiesFactory; private final Set projectNamesOrKeys; @@ -73,6 +73,11 @@ protected void executeTaskImplementation() { logger.info("Jira Server property migrator task ended."); } + @Override + protected Runnable createUpdateRunnable(String issueKey, IssuePropertyService issuePropertyService) { + return () -> setIssueProperty(issueKey, issuePropertyService); + } + private boolean updateIssues(IssueSearchResponseModel responseModel, IssuePropertyService issuePropertyService) throws InterruptedException { int totalIssues = responseModel.getTotal(); boolean foundIssues = totalIssues > 0; @@ -81,7 +86,7 @@ private boolean updateIssues(IssueSearchResponseModel responseModel, IssueProper List issueKeys = responseModel.getIssues().stream() .map(IssueSearchIssueComponent::getKey) .toList(); - updateIssues(issueKeys, totalIssues, issuePropertyService); + updateIssues(issueKeys, totalIssues, issuePropertyService, "property migrator"); } return foundIssues; } diff --git a/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraServerSchedulingManager.java b/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraServerSchedulingManager.java index d8411ecbbc..cf35689897 100644 --- a/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraServerSchedulingManager.java +++ b/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraServerSchedulingManager.java @@ -1,7 +1,7 @@ package com.blackduck.integration.alert.channel.jira.server.task; import com.blackduck.integration.alert.api.channel.jira.lifecycle.JiraSchedulingManager; -import com.blackduck.integration.alert.api.channel.jira.lifecycle.JiraTask; +import com.blackduck.integration.alert.api.channel.jira.lifecycle.JiraPropertyTask; import com.blackduck.integration.alert.api.task.TaskManager; import com.blackduck.integration.alert.channel.jira.server.JiraServerPropertiesFactory; import com.blackduck.integration.alert.channel.jira.server.model.JiraServerGlobalConfigModel; @@ -31,11 +31,11 @@ public JiraServerSchedulingManager(Gson gson, JiraSchedulingManager jiraScheduli this.jiraPropertiesFactory = jiraPropertiesFactory; } - public List scheduleTasks(JiraServerGlobalConfigModel configModel) { + public List scheduleTasks(JiraServerGlobalConfigModel configModel) { return scheduleTasks(configModel, Set.of()); } - public List scheduleTasks(JiraServerGlobalConfigModel configModel, Set projectNameOrKeys) { + public List scheduleTasks(JiraServerGlobalConfigModel configModel, Set projectNameOrKeys) { return jiraSchedulingManager.scheduleTasks(createTasks(configModel, projectNameOrKeys)); } @@ -43,7 +43,7 @@ public void unscheduleTasks(UUID configId) { jiraSchedulingManager.unscheduleTasks(configId.toString()); } - private List createTasks(JiraServerGlobalConfigModel configModel, Set projectNameOrKeys) { + private List createTasks(JiraServerGlobalConfigModel configModel, Set projectNameOrKeys) { JiraPropertyUpdateTask propertyTask = new JiraPropertyUpdateTask(taskScheduler, taskManager, jiraPropertiesFactory, gson, configModel.getId(), configModel.getName(), "JiraServer", projectNameOrKeys); JiraSearchCommentUpdateTask searchCommentTask = new JiraSearchCommentUpdateTask(taskScheduler, taskManager, jiraPropertiesFactory, gson, configModel.getId(), configModel.getName(), "JiraServer", projectNameOrKeys); return List.of(propertyTask, searchCommentTask); From 3036b2c9377d4ad834b13626c557aeec57f9391f Mon Sep 17 00:00:00 2001 From: Paulo Santos Date: Thu, 21 Aug 2025 13:12:55 -0400 Subject: [PATCH 07/18] Create the skeleton to update tickets with comments --- .../alert/api/channel/jira/JiraConstants.java | 8 +++ .../jira/lifecycle/JiraPropertyTask.java | 72 +++---------------- .../jira/lifecycle/JiraSchedulingManager.java | 10 +-- .../api/channel/jira/lifecycle/JiraTask.java | 70 ++++++++++++++++++ .../task/JiraCloudSchedulingManager.java | 10 +-- .../cloud/task/JiraPropertyUpdateTask.java | 7 +- .../task/JiraSearchCommentUpdateTask.java | 60 ++++++++++++++-- .../server/task/JiraPropertyUpdateTask.java | 7 +- .../task/JiraSearchCommentUpdateTask.java | 52 ++++++++++++-- .../task/JiraServerSchedulingManager.java | 10 +-- 10 files changed, 203 insertions(+), 103 deletions(-) create mode 100644 api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/lifecycle/JiraTask.java diff --git a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/JiraConstants.java b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/JiraConstants.java index b814e63a32..740af2a3bf 100644 --- a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/JiraConstants.java +++ b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/JiraConstants.java @@ -7,6 +7,8 @@ */ package com.blackduck.integration.alert.api.channel.jira; +import com.blackduck.integration.alert.api.channel.jira.distribution.search.JiraIssuePropertyKeys; + public final class JiraConstants { public static final String DEFAULT_ISSUE_TYPE = "Task"; // This String must always match the String found in the atlassian-connect.json file under key. @@ -19,6 +21,12 @@ public final class JiraConstants { public static final String JIRA_SEARCH_KEY_JIRA_PROJECT = "project"; + // find tickets created by alert first: + // 1. A summary that starts with "Alert - Black Duck" + // 2. A summary that isn't an Alert test message and does not have a comment "=== BEGIN JIRA ISSUE KEYS ===" + // 3. Then check if the new property key exists on that issue or if the old property key is on the issue. + public static final String JQL_QUERY_FOR_ISSUE_SEARCH_COMMENT_MIGRATION = String.format("(summary ~ \"Alert - Black Duck\" OR (summary !~ \"Alert Test Message\" AND NOT comment ~\"%s\")) AND (issue.property[%s].topicName IS NOT EMPTY OR issue.property[%s].topicName IS NOT EMPTY) ORDER BY created DESC", JiraIssuePropertyKeys.JIRA_ISSUE_KEY_START_HEADER, JiraConstants.JIRA_ISSUE_PROPERTY_KEY, JiraConstants.JIRA_ISSUE_PROPERTY_OLD_KEY); + // These Strings must always match the Strings found in the atlassian-connect.json file under modules.jiraEntityProperties.keyConfigurations.propertyKey["com-blackduck-integration-alert"].extractions.objectName. public static final String JIRA_ISSUE_PROPERTY_OBJECT_KEY_PROVIDER = "provider"; public static final String JIRA_ISSUE_PROPERTY_OBJECT_KEY_PROVIDER_URL = "providerUrl"; diff --git a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/lifecycle/JiraPropertyTask.java b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/lifecycle/JiraPropertyTask.java index 74285144bf..a5c9eb8a6c 100644 --- a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/lifecycle/JiraPropertyTask.java +++ b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/lifecycle/JiraPropertyTask.java @@ -17,17 +17,15 @@ import java.util.List; import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; -public abstract class JiraPropertyTask extends ScheduledTask { +public abstract class JiraPropertyTask extends JiraTask { private final Logger logger = LoggerFactory.getLogger(this.getClass()); // find tickets created by alert first: // 1. A summary that starts with "Alert - Black Duck" // 2. A summary that isn't an Alert test message and have a comment "This issue was automatically created by Alert." // 3. Then check if the new property key exists on that issue. Only works because the new property key is indexed with the new plugin. protected static final String JQL_QUERY_FOR_ISSUE_PROPERTY_MIGRATION = String.format("(summary ~ \"Alert - Black Duck\" OR (summary !~ \"Alert Test Message\" AND comment ~ \"This issue was automatically created by Alert.\")) AND issue.property[%s].topicName IS EMPTY ORDER BY created DESC", JiraConstants.JIRA_ISSUE_PROPERTY_KEY); - protected static final int JQL_QUERY_MAX_RESULTS = 100; protected static final JiraIssueSearchProperties EMPTY_SEARCH_PROPERTIES = new JiraIssueSearchProperties(StringUtils.EMPTY, StringUtils.EMPTY, StringUtils.EMPTY, StringUtils.EMPTY, StringUtils.EMPTY, StringUtils.EMPTY, StringUtils.EMPTY, StringUtils.EMPTY, StringUtils.EMPTY, StringUtils.EMPTY, StringUtils.EMPTY, StringUtils.EMPTY); @@ -37,20 +35,8 @@ public static String createProjectSpecificQuery(String projectName) { return String.format("project = %s AND issue.property[%s].topicName IS EMPTY ORDER BY created DESC", projectQueryValue, JiraConstants.JIRA_ISSUE_PROPERTY_KEY); } - - private final TaskManager taskManager; - private final String taskName; - private final String configId; - private final String configName; - private final Gson gson; - protected JiraPropertyTask(TaskScheduler taskScheduler, TaskManager taskManager, String configId, String configName, String taskNameSuffix, Gson gson) { - super(taskScheduler); - this.taskManager = taskManager; - this.configId = configId; - this.configName = configName; - this.taskName = computeTaskName(taskNameSuffix); - this.gson = gson; + super(taskScheduler, taskManager, configId, configName, taskNameSuffix, gson); } @Override @@ -60,22 +46,20 @@ public final void runTask() { protected abstract void executeTaskImplementation(); - protected void updateIssues(List issueKeys,Integer totalIssues, IssuePropertyService issuePropertyService, String loggingTaskName) throws InterruptedException { + protected void updateIssues(List issueKeys,Integer totalIssues, IssuePropertyService issuePropertyService) throws InterruptedException { ExecutorService executorService = getExecutorService(); for (String issueKey : issueKeys) { - executorService.submit(createUpdateRunnable(issueKey, issuePropertyService)); + executorService.submit(() -> setIssueProperty(issueKey, issuePropertyService)); } executorService.shutdown(); boolean success = executorService.awaitTermination(1, TimeUnit.MINUTES); if (success) { - logger.info("Jira {} task remaining issues {} ", loggingTaskName, totalIssues); + logger.info("Jira property migrator task remaining issues {} ", totalIssues); } else { - logger.info("Jira {} task timed out updating issues; will resume with the next iteration.", loggingTaskName); + logger.info("Jira property migrator task timed out updating issues; will resume with the next iteration."); } } - protected abstract Runnable createUpdateRunnable(String issueKey, IssuePropertyService issuePropertyService); - protected void setIssueProperty(String issueKey, IssuePropertyService issuePropertyService) { try { String propertyValue = getCurrentPropertyValue(issueKey, issuePropertyService); @@ -88,54 +72,14 @@ protected void setIssueProperty(String issueKey, IssuePropertyService issuePrope protected String getCurrentPropertyValue(String issueKey, IssuePropertyService issuePropertyService) { // empty property value - String jsonPropertyValue = gson.toJson(EMPTY_SEARCH_PROPERTIES); + String jsonPropertyValue = getGson().toJson(EMPTY_SEARCH_PROPERTIES); try { IssuePropertyResponseModel issuePropertyResponse = issuePropertyService.getProperty(issueKey, JiraConstants.JIRA_ISSUE_PROPERTY_OLD_KEY); - jsonPropertyValue = gson.toJson(issuePropertyResponse.getValue()); + jsonPropertyValue = getGson().toJson(issuePropertyResponse.getValue()); } catch (IntegrationException ex) { logger.debug("Error old issue property for issue: {} cause: {}", issueKey, ex.getMessage()); logger.debug("Caused by: ", ex); } return jsonPropertyValue; } - - @Override - public String getTaskName() { - return taskName; - } - - @Override - public TaskMetaData createTaskMetaData() { - String fullyQualifiedName = ScheduledTask.computeFullyQualifiedName(getClass()); - String nextRunTime = getFormatedNextRunTime().orElse(""); - TaskMetaDataProperty configNameProperty = new TaskMetaDataProperty("configurationName", "Configuration Name", getConfigName()); - List properties = List.of(configNameProperty); - return new TaskMetaData(getTaskName(), getClass().getSimpleName(), fullyQualifiedName, nextRunTime, properties); - } - - public String getConfigId() { - return configId; - } - - public String getConfigName() { - return configName; - } - - protected Gson getGson() { - return gson; - } - - protected ExecutorService getExecutorService() { - return Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); - } - - public void unScheduleTask() { - taskManager.unScheduleTask(taskName); - taskManager.unregisterTask(taskName); - } - - private String computeTaskName(String taskNameSuffix) { - String superTaskName = ScheduledTask.computeTaskName(getClass()); - return String.format("%s::%s[id:%s]", superTaskName, taskNameSuffix,getConfigId()); - } } diff --git a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/lifecycle/JiraSchedulingManager.java b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/lifecycle/JiraSchedulingManager.java index c1191584e8..f1c075676e 100644 --- a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/lifecycle/JiraSchedulingManager.java +++ b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/lifecycle/JiraSchedulingManager.java @@ -19,9 +19,9 @@ public JiraSchedulingManager(TaskManager taskManager) { this.taskManager = taskManager; } - public List scheduleTasks(List tasks) { - List acceptedTasks = new ArrayList<>(); - for (JiraPropertyTask task : tasks) { + public List scheduleTasks(List tasks) { + List acceptedTasks = new ArrayList<>(); + for (JiraTask task : tasks) { unscheduleTasks(task.getConfigId()); logger.debug("Perform scheduling jira tasks for config with id {} and name {}", task.getConfigId(), task.getConfigName()); if (taskManager.getNextRunTime(task.getTaskName()).isEmpty()) { @@ -48,12 +48,12 @@ public void unscheduleTasks(String configId) { logger.debug("Finished unscheduling jira tasks for config: id={}", configId); } - private void scheduleTask(JiraPropertyTask task) { + private void scheduleTask(JiraTask task) { taskManager.registerTask(task); taskManager.scheduleCronTask(task.scheduleCronExpression(), task.getTaskName()); } - private void unscheduleTask(JiraPropertyTask task) { + private void unscheduleTask(JiraTask task) { taskManager.unregisterTask(task.getTaskName()); } } diff --git a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/lifecycle/JiraTask.java b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/lifecycle/JiraTask.java new file mode 100644 index 0000000000..c76dfe47c4 --- /dev/null +++ b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/lifecycle/JiraTask.java @@ -0,0 +1,70 @@ +package com.blackduck.integration.alert.api.channel.jira.lifecycle; + +import com.blackduck.integration.alert.api.task.ScheduledTask; +import com.blackduck.integration.alert.api.task.TaskManager; +import com.blackduck.integration.alert.api.task.TaskMetaData; +import com.blackduck.integration.alert.api.task.TaskMetaDataProperty; +import com.google.gson.Gson; +import org.springframework.scheduling.TaskScheduler; + +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public abstract class JiraTask extends ScheduledTask { + protected static final int JQL_QUERY_MAX_RESULTS = 100; + private final TaskManager taskManager; + private final String taskName; + private final String configId; + private final String configName; + private final Gson gson; + + public JiraTask(TaskScheduler taskScheduler, TaskManager taskManager, String taskName, String configId, String configName, Gson gson) { + super(taskScheduler); + this.taskManager = taskManager; + this.taskName = taskName; + this.configId = configId; + this.configName = configName; + this.gson = gson; + } + + @Override + public String getTaskName() { + return taskName; + } + + @Override + public TaskMetaData createTaskMetaData() { + String fullyQualifiedName = ScheduledTask.computeFullyQualifiedName(getClass()); + String nextRunTime = getFormatedNextRunTime().orElse(""); + TaskMetaDataProperty configNameProperty = new TaskMetaDataProperty("configurationName", "Configuration Name", getConfigName()); + List properties = List.of(configNameProperty); + return new TaskMetaData(getTaskName(), getClass().getSimpleName(), fullyQualifiedName, nextRunTime, properties); + } + + public String getConfigId() { + return configId; + } + + public String getConfigName() { + return configName; + } + + protected Gson getGson() { + return gson; + } + + protected ExecutorService getExecutorService() { + return Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); + } + + public void unScheduleTask() { + taskManager.unScheduleTask(taskName); + taskManager.unregisterTask(taskName); + } + + private String computeTaskName(String taskNameSuffix) { + String superTaskName = ScheduledTask.computeTaskName(getClass()); + return String.format("%s::%s[id:%s]", superTaskName, taskNameSuffix,getConfigId()); + } +} diff --git a/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraCloudSchedulingManager.java b/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraCloudSchedulingManager.java index f4fc006380..65f24cd9d2 100644 --- a/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraCloudSchedulingManager.java +++ b/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraCloudSchedulingManager.java @@ -1,7 +1,7 @@ package com.blackduck.integration.alert.channel.jira.cloud.task; import com.blackduck.integration.alert.api.channel.jira.lifecycle.JiraSchedulingManager; -import com.blackduck.integration.alert.api.channel.jira.lifecycle.JiraPropertyTask; +import com.blackduck.integration.alert.api.channel.jira.lifecycle.JiraTask; import com.blackduck.integration.alert.api.task.TaskManager; import com.blackduck.integration.alert.channel.jira.cloud.JiraCloudPropertiesFactory; import com.blackduck.integration.alert.common.descriptor.ChannelDescriptor; @@ -31,11 +31,11 @@ public JiraCloudSchedulingManager(Gson gson, JiraSchedulingManager jiraSchedulin this.jiraPropertiesFactory = jiraPropertiesFactory; } - public List scheduleTasks(FieldModel fieldModel) { + public List scheduleTasks(FieldModel fieldModel) { return scheduleTasks(fieldModel, Set.of()); } - public List scheduleTasks(FieldModel fieldModel, Set projectNameOrKeys) { + public List scheduleTasks(FieldModel fieldModel, Set projectNameOrKeys) { return jiraSchedulingManager.scheduleTasks(createTasks(fieldModel, projectNameOrKeys)); } @@ -43,11 +43,11 @@ public void unscheduleTasks(String configId) { jiraSchedulingManager.unscheduleTasks(configId); } - private List createTasks(FieldModel fieldModel, Set projectNameOrKeys) { + private List createTasks(FieldModel fieldModel, Set projectNameOrKeys) { String configId = fieldModel.getId(); String configName = fieldModel.getFieldValue(ChannelDescriptor.KEY_NAME).orElse(""); JiraPropertyUpdateTask propertyTask = new JiraPropertyUpdateTask(taskScheduler, taskManager, jiraPropertiesFactory, gson, configId, configName, "JiraCloud", projectNameOrKeys); - JiraSearchCommentUpdateTask searchCommentTask = new JiraSearchCommentUpdateTask(taskScheduler, taskManager, jiraPropertiesFactory, gson, configId, configName, "JiraCloud", projectNameOrKeys); + JiraSearchCommentUpdateTask searchCommentTask = new JiraSearchCommentUpdateTask(taskScheduler, taskManager, jiraPropertiesFactory, gson, configId, configName, "JiraCloud"); return List.of(propertyTask, searchCommentTask); } } diff --git a/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraPropertyUpdateTask.java b/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraPropertyUpdateTask.java index c910ed0db5..922da14a6c 100644 --- a/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraPropertyUpdateTask.java +++ b/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraPropertyUpdateTask.java @@ -71,11 +71,6 @@ protected void executeTaskImplementation() { } } - @Override - protected Runnable createUpdateRunnable(String issueKey, IssuePropertyService issuePropertyService) { - return () -> setIssueProperty(issueKey, issuePropertyService); - } - private boolean updateIssues(IssueSearchResponseModel responseModel, IssuePropertyService issuePropertyService) throws InterruptedException { int totalIssues = responseModel.getTotal(); boolean foundIssues = totalIssues > 0; @@ -84,7 +79,7 @@ private boolean updateIssues(IssueSearchResponseModel responseModel, IssueProper List issueKeys = responseModel.getIssues().stream() .map(IssueResponseModel::getKey) .toList(); - updateIssues(issueKeys, totalIssues, issuePropertyService, "property migrator"); + updateIssues(issueKeys, totalIssues, issuePropertyService); } return foundIssues; } diff --git a/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraSearchCommentUpdateTask.java b/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraSearchCommentUpdateTask.java index 9160c20b05..e42e9d9d11 100644 --- a/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraSearchCommentUpdateTask.java +++ b/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraSearchCommentUpdateTask.java @@ -1,31 +1,79 @@ package com.blackduck.integration.alert.channel.jira.cloud.task; +import com.blackduck.integration.alert.api.channel.jira.JiraConstants; import com.blackduck.integration.alert.api.channel.jira.lifecycle.JiraTask; import com.blackduck.integration.alert.api.task.ScheduledTask; import com.blackduck.integration.alert.api.task.TaskManager; +import com.blackduck.integration.alert.channel.jira.cloud.JiraCloudProperties; import com.blackduck.integration.alert.channel.jira.cloud.JiraCloudPropertiesFactory; +import com.blackduck.integration.exception.IntegrationException; +import com.blackduck.integration.jira.common.cloud.model.IssueSearchResponseModel; +import com.blackduck.integration.jira.common.cloud.service.IssueSearchService; +import com.blackduck.integration.jira.common.cloud.service.JiraCloudServiceFactory; +import com.blackduck.integration.jira.common.model.response.IssueResponseModel; +import com.blackduck.integration.jira.common.rest.service.IssuePropertyService; import com.google.gson.Gson; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.scheduling.TaskScheduler; -import java.util.Set; +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.TimeUnit; public class JiraSearchCommentUpdateTask extends JiraTask { private Logger logger = LoggerFactory.getLogger(getClass()); private final JiraCloudPropertiesFactory jiraPropertiesFactory; - private final Set projectNamesOrKeys; - public JiraSearchCommentUpdateTask(TaskScheduler taskScheduler, TaskManager taskManager, JiraCloudPropertiesFactory jiraPropertiesFactory, Gson gson, String configId, String configName, String taskNameSuffix, Set projectNamesOrKeys) { + public JiraSearchCommentUpdateTask(TaskScheduler taskScheduler, TaskManager taskManager, JiraCloudPropertiesFactory jiraPropertiesFactory, Gson gson, String configId, String configName, String taskNameSuffix) { super(taskScheduler, taskManager, configId, configName, taskNameSuffix, gson); this.jiraPropertiesFactory = jiraPropertiesFactory; - this.projectNamesOrKeys = projectNamesOrKeys; } @Override - protected void executeTaskImplementation() { - logger.info("Executing Jira Search Comment Update Task"); + public void runTask() { + logger.info("Jira Cloud search comment task started."); + try { + JiraCloudProperties jiraProperties = jiraPropertiesFactory.createJiraProperties(); + JiraCloudServiceFactory serviceFactory = jiraProperties.createJiraServicesCloudFactory(logger, getGson()); + IssueSearchService issueSearchService = serviceFactory.createIssueSearchService(); + IssuePropertyService issuePropertyService = serviceFactory.createIssuePropertyService(); + IssueSearchResponseModel responseModel = issueSearchService.queryForIssuePage(JiraConstants.JQL_QUERY_FOR_ISSUE_SEARCH_COMMENT_MIGRATION, 0, JQL_QUERY_MAX_RESULTS); + + int totalIssues = responseModel.getTotal(); + boolean foundIssues = totalIssues > 0; + + if(foundIssues) { + List issueKeys = responseModel.getIssues().stream() + .map(IssueResponseModel::getKey) + .toList(); + ExecutorService executorService = getExecutorService(); + for (String issueKey : issueKeys) { + executorService.submit(createUpdateRunnable(issueKey, issuePropertyService)); + } + executorService.shutdown(); + boolean success = executorService.awaitTermination(1, TimeUnit.MINUTES); + if (success) { + logger.info("Jira search key comment update task remaining issues {} ", totalIssues); + } else { + logger.info("Jira search key comment update task timed out updating issues; will resume with the next iteration."); + } + } else { + // unschedule the task because the query returned no results + unScheduleTask(); + } + logger.info("Jira Cloud search comment task ended."); + } catch (IntegrationException e) { + logger.error("Error getting Jira Cloud Configuration.", e); + } catch (InterruptedException e) { + logger.error("Error updating Jira Cloud issues with new search key comment.", e); + Thread.currentThread().interrupt(); + } + } + + private Runnable createUpdateRunnable(String issueKey, IssuePropertyService issuePropertyService) { + return () -> {}; } @Override diff --git a/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraPropertyUpdateTask.java b/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraPropertyUpdateTask.java index 0897ec7cd1..6f242ae440 100644 --- a/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraPropertyUpdateTask.java +++ b/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraPropertyUpdateTask.java @@ -73,11 +73,6 @@ protected void executeTaskImplementation() { logger.info("Jira Server property migrator task ended."); } - @Override - protected Runnable createUpdateRunnable(String issueKey, IssuePropertyService issuePropertyService) { - return () -> setIssueProperty(issueKey, issuePropertyService); - } - private boolean updateIssues(IssueSearchResponseModel responseModel, IssuePropertyService issuePropertyService) throws InterruptedException { int totalIssues = responseModel.getTotal(); boolean foundIssues = totalIssues > 0; @@ -86,7 +81,7 @@ private boolean updateIssues(IssueSearchResponseModel responseModel, IssueProper List issueKeys = responseModel.getIssues().stream() .map(IssueSearchIssueComponent::getKey) .toList(); - updateIssues(issueKeys, totalIssues, issuePropertyService, "property migrator"); + updateIssues(issueKeys, totalIssues, issuePropertyService); } return foundIssues; } diff --git a/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraSearchCommentUpdateTask.java b/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraSearchCommentUpdateTask.java index 053a3dc95d..1c8715c4af 100644 --- a/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraSearchCommentUpdateTask.java +++ b/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraSearchCommentUpdateTask.java @@ -1,34 +1,70 @@ package com.blackduck.integration.alert.channel.jira.server.task; +import com.blackduck.integration.alert.api.channel.jira.JiraConstants; import com.blackduck.integration.alert.api.channel.jira.lifecycle.JiraTask; import com.blackduck.integration.alert.api.task.ScheduledTask; import com.blackduck.integration.alert.api.task.TaskManager; +import com.blackduck.integration.alert.channel.jira.server.JiraServerProperties; import com.blackduck.integration.alert.channel.jira.server.JiraServerPropertiesFactory; import com.blackduck.integration.exception.IntegrationException; +import com.blackduck.integration.jira.common.rest.service.IssuePropertyService; +import com.blackduck.integration.jira.common.server.model.IssueSearchIssueComponent; +import com.blackduck.integration.jira.common.server.model.IssueSearchResponseModel; +import com.blackduck.integration.jira.common.server.service.IssueSearchService; +import com.blackduck.integration.jira.common.server.service.JiraServerServiceFactory; import com.google.gson.Gson; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.scheduling.TaskScheduler; -import java.util.Set; +import java.util.List; import java.util.UUID; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.TimeUnit; public class JiraSearchCommentUpdateTask extends JiraTask { private Logger logger = LoggerFactory.getLogger(getClass()); private final JiraServerPropertiesFactory jiraPropertiesFactory; - private final Set projectNamesOrKeys; - public JiraSearchCommentUpdateTask(TaskScheduler taskScheduler, TaskManager taskManager, JiraServerPropertiesFactory jiraPropertiesFactory, Gson gson, String configId, String configName, String taskNameSuffix, Set projectNamesOrKeys) { + public JiraSearchCommentUpdateTask(TaskScheduler taskScheduler, TaskManager taskManager, JiraServerPropertiesFactory jiraPropertiesFactory, Gson gson, String configId, String configName, String taskNameSuffix) { super(taskScheduler, taskManager, configId, configName, taskNameSuffix, gson); this.jiraPropertiesFactory = jiraPropertiesFactory; - this.projectNamesOrKeys = projectNamesOrKeys; } @Override - protected void executeTaskImplementation() { + public void runTask() { logger.info("Jira Server search comment task started."); UUID configId = UUID.fromString(getConfigId()); try { + JiraServerProperties jiraProperties = jiraPropertiesFactory.createJiraProperties(configId); + JiraServerServiceFactory serviceFactory = jiraProperties.createJiraServicesServerFactory(logger,getGson()); + IssueSearchService issueSearchService = serviceFactory.createIssueSearchService(); + IssuePropertyService issuePropertyService = serviceFactory.createIssuePropertyService(); + IssueSearchResponseModel responseModel = issueSearchService.queryForIssuePage(JiraConstants.JQL_QUERY_FOR_ISSUE_SEARCH_COMMENT_MIGRATION, 0, JQL_QUERY_MAX_RESULTS); + + int totalIssues = responseModel.getTotal(); + boolean foundIssues = totalIssues > 0; + + if(foundIssues) { + List issueKeys = responseModel.getIssues().stream() + .map(IssueSearchIssueComponent::getKey) + .toList(); + ExecutorService executorService = getExecutorService(); + for (String issueKey : issueKeys) { + executorService.submit(createUpdateRunnable(issueKey, issuePropertyService)); + } + executorService.shutdown(); + boolean success = executorService.awaitTermination(1, TimeUnit.MINUTES); + if (success) { + logger.info("Jira search key comment update task remaining issues {} ", totalIssues); + } else { + logger.info("Jira search key comment update task timed out updating issues; will resume with the next iteration."); + } + } else { + + // unschedule the task because the query returned no results + unScheduleTask(); + } } catch (IntegrationException e) { logger.error("Error getting Jira Server Configuration.", e); } catch (InterruptedException e) { @@ -36,7 +72,11 @@ protected void executeTaskImplementation() { Thread.currentThread().interrupt(); } - logger.info("Jira Server property migrator task ended."); + logger.info("Jira Server search comment task ended."); + } + + private Runnable createUpdateRunnable(String issueKey, IssuePropertyService issuePropertyService) { + return () -> {}; } @Override diff --git a/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraServerSchedulingManager.java b/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraServerSchedulingManager.java index cf35689897..41a4254762 100644 --- a/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraServerSchedulingManager.java +++ b/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraServerSchedulingManager.java @@ -1,7 +1,7 @@ package com.blackduck.integration.alert.channel.jira.server.task; import com.blackduck.integration.alert.api.channel.jira.lifecycle.JiraSchedulingManager; -import com.blackduck.integration.alert.api.channel.jira.lifecycle.JiraPropertyTask; +import com.blackduck.integration.alert.api.channel.jira.lifecycle.JiraTask; import com.blackduck.integration.alert.api.task.TaskManager; import com.blackduck.integration.alert.channel.jira.server.JiraServerPropertiesFactory; import com.blackduck.integration.alert.channel.jira.server.model.JiraServerGlobalConfigModel; @@ -31,11 +31,11 @@ public JiraServerSchedulingManager(Gson gson, JiraSchedulingManager jiraScheduli this.jiraPropertiesFactory = jiraPropertiesFactory; } - public List scheduleTasks(JiraServerGlobalConfigModel configModel) { + public List scheduleTasks(JiraServerGlobalConfigModel configModel) { return scheduleTasks(configModel, Set.of()); } - public List scheduleTasks(JiraServerGlobalConfigModel configModel, Set projectNameOrKeys) { + public List scheduleTasks(JiraServerGlobalConfigModel configModel, Set projectNameOrKeys) { return jiraSchedulingManager.scheduleTasks(createTasks(configModel, projectNameOrKeys)); } @@ -43,9 +43,9 @@ public void unscheduleTasks(UUID configId) { jiraSchedulingManager.unscheduleTasks(configId.toString()); } - private List createTasks(JiraServerGlobalConfigModel configModel, Set projectNameOrKeys) { + private List createTasks(JiraServerGlobalConfigModel configModel, Set projectNameOrKeys) { JiraPropertyUpdateTask propertyTask = new JiraPropertyUpdateTask(taskScheduler, taskManager, jiraPropertiesFactory, gson, configModel.getId(), configModel.getName(), "JiraServer", projectNameOrKeys); - JiraSearchCommentUpdateTask searchCommentTask = new JiraSearchCommentUpdateTask(taskScheduler, taskManager, jiraPropertiesFactory, gson, configModel.getId(), configModel.getName(), "JiraServer", projectNameOrKeys); + JiraSearchCommentUpdateTask searchCommentTask = new JiraSearchCommentUpdateTask(taskScheduler, taskManager, jiraPropertiesFactory, gson, configModel.getId(), configModel.getName(), "JiraServer"); return List.of(propertyTask, searchCommentTask); } } From d1b863f09c0dd1f187113b4f41b3eb8770ce88da Mon Sep 17 00:00:00 2001 From: Paulo Santos Date: Wed, 27 Aug 2025 15:03:53 -0400 Subject: [PATCH 08/18] IALERT-3873: Implement the changes to get the property value. --- .../delegate/JiraIssueCreator.java | 62 ++-------------- .../distribution/search/JqlStringCreator.java | 21 +++++- .../search/SearchCommentCreator.java | 73 +++++++++++++++++++ .../jira/lifecycle/JiraPropertyTask.java | 5 +- .../api/channel/jira/lifecycle/JiraTask.java | 5 ++ .../search/JqlStringCreatorTest.java | 12 +-- .../task/JiraSearchCommentUpdateTask.java | 42 ++++++++++- .../task/JiraSearchCommentUpdateTask.java | 42 ++++++++++- 8 files changed, 190 insertions(+), 72 deletions(-) create mode 100644 api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/SearchCommentCreator.java diff --git a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/delegate/JiraIssueCreator.java b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/delegate/JiraIssueCreator.java index 58f85ab7b3..58069f7e50 100644 --- a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/delegate/JiraIssueCreator.java +++ b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/delegate/JiraIssueCreator.java @@ -7,13 +7,10 @@ */ package com.blackduck.integration.alert.api.channel.jira.distribution.delegate; -import java.nio.charset.StandardCharsets; -import java.util.Base64; import java.util.List; import java.util.Optional; -import com.blackduck.integration.alert.api.channel.jira.distribution.search.JiraIssuePropertyKeys; -import io.opencensus.trace.Link; +import com.blackduck.integration.alert.api.channel.jira.distribution.search.SearchCommentCreator; import org.apache.commons.lang3.StringUtils; import com.blackduck.integration.alert.api.channel.issue.tracker.callback.IssueTrackerCallbackInfoCreator; @@ -239,7 +236,6 @@ private JiraIssueSearchProperties createSearchProperties(ProjectIssueModel alert @Override protected Optional getAlertSearchKeys(ExistingIssueDetails existingIssueDetails, @Nullable ProjectIssueModel alertIssueSource) { - StringBuilder keyBuilder = new StringBuilder(); if(alertIssueSource == null) { return Optional.empty(); @@ -255,59 +251,17 @@ protected Optional getAlertSearchKeys(ExistingIssueDetails exist IssueBomComponentDetails bomComponent = alertIssueSource.getBomComponentDetails(); - String projectId = StringUtils.substringAfterLast(project.getUrl().orElse(""), "/"); - int versionUUIDStart = StringUtils.lastIndexOf(projectVersion.getUrl().orElse(""), "versions/") +"versions/".length(); - int versionUUIDEnd = StringUtils.indexOf(projectVersion.getUrl().orElse(""), "/", versionUUIDStart); - String projectVersionId = StringUtils.substring(projectVersion.getUrl().orElse(""), versionUUIDStart, versionUUIDEnd); - String componentName = bomComponent.getComponent().getValue(); - Optional componentVersionName = bomComponent.getComponentVersion(); - keyBuilder.append("This comment was automatically created by Alert. DO NOT REMOVE."); - keyBuilder.append(JiraIssuePropertyKeys.JIRA_ISSUE_KEY_START_HEADER); - keyBuilder.append(StringUtils.SPACE); - keyBuilder.append(JiraIssuePropertyKeys.JIRA_ISSUE_KEY_PROJECT_ID); - keyBuilder.append(JiraIssuePropertyKeys.JIRA_ISSUE_KEY_SEPARATOR); - keyBuilder.append(projectId); - keyBuilder.append(StringUtils.SPACE); - keyBuilder.append(JiraIssuePropertyKeys.JIRA_ISSUE_KEY_PROJECT_VERSION_ID); - keyBuilder.append(JiraIssuePropertyKeys.JIRA_ISSUE_KEY_SEPARATOR); - keyBuilder.append(projectVersionId); - keyBuilder.append(StringUtils.SPACE); - keyBuilder.append(JiraIssuePropertyKeys.JIRA_ISSUE_KEY_COMPONENT_NAME); - keyBuilder.append(JiraIssuePropertyKeys.JIRA_ISSUE_KEY_SEPARATOR); - keyBuilder.append(componentName); - keyBuilder.append(StringUtils.SPACE); - if(componentVersionName.isPresent()) { - keyBuilder.append(JiraIssuePropertyKeys.JIRA_ISSUE_KEY_COMPONENT_VERSION_NAME); - keyBuilder.append(JiraIssuePropertyKeys.JIRA_ISSUE_KEY_SEPARATOR); - keyBuilder.append(componentVersionName.get().getValue()); - keyBuilder.append(StringUtils.SPACE); - } + Optional componentVersion = bomComponent.getComponentVersion(); Optional policyDetails = alertIssueSource.getPolicyDetails(); - Optional category = Optional.empty(); + String policyName = policyDetails.map(IssuePolicyDetails::getName).orElse(null); + ComponentConcernType category = null; if (alertIssueSource.getVulnerabilityDetails().isPresent()) { - category = Optional.of(ComponentConcernType.VULNERABILITY); + category = ComponentConcernType.VULNERABILITY; } else if(policyDetails.isPresent()) { - category = Optional.of(ComponentConcernType.POLICY); + category = ComponentConcernType.POLICY; } else if(alertIssueSource.getComponentUnknownVersionDetails().isPresent()) { - category = Optional.of(ComponentConcernType.UNKNOWN_VERSION); - } - if(category.isPresent()) { - keyBuilder.append(JiraIssuePropertyKeys.JIRA_ISSUE_KEY_CATEGORY); - keyBuilder.append(JiraIssuePropertyKeys.JIRA_ISSUE_KEY_SEPARATOR); - keyBuilder.append(category.get().name()); - keyBuilder.append(StringUtils.SPACE); + category = ComponentConcernType.UNKNOWN_VERSION; } - - if(policyDetails.isPresent()) { - // add policy name - keyBuilder.append(JiraIssuePropertyKeys.JIRA_ISSUE_KEY_POLICY_NAME); - keyBuilder.append(JiraIssuePropertyKeys.JIRA_ISSUE_KEY_SEPARATOR); - keyBuilder.append(JiraIssueSearchPropertyStringCompatibilityUtils.createPolicyAdditionalKey(policyDetails.get().getName())); - keyBuilder.append(StringUtils.SPACE); - } - keyBuilder.append(StringUtils.SPACE); - keyBuilder.append(JiraIssuePropertyKeys.JIRA_ISSUE_KEY_END_HEADER); - - return Optional.of(keyBuilder.toString()); + return Optional.of(SearchCommentCreator.createSearchComment(project, projectVersion, bomComponent.getComponent(), componentVersion.orElse(null),category, policyName)); } } diff --git a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/JqlStringCreator.java b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/JqlStringCreator.java index 7d96f114e0..664322aae8 100644 --- a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/JqlStringCreator.java +++ b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/JqlStringCreator.java @@ -119,28 +119,46 @@ private static void appendBlackDuckCommentSearchStrings( if(project != null && project.getUrl().isPresent()) { String projectId = extractUuid(project.getUrl().get(), "/api/projects/"); + jqlBuilder.append(SEARCH_CONJUNCTION); + jqlBuilder.append(" ("); appendCommentSearchString(jqlBuilder, JiraIssuePropertyKeys.JIRA_ISSUE_KEY_PROJECT_ID, projectId); + jqlBuilder.append("OR "); + appendCommentSearchString(jqlBuilder, JiraIssuePropertyKeys.JIRA_ISSUE_KEY_PROJECT_ID, project.getValue()); + jqlBuilder.append(") "); } if(projectVersion != null && projectVersion.getUrl().isPresent()) { String projectVersionId = extractUuid(projectVersion.getUrl().get(), "/versions/"); + jqlBuilder.append(SEARCH_CONJUNCTION); + jqlBuilder.append(" ("); appendCommentSearchString(jqlBuilder, JiraIssuePropertyKeys.JIRA_ISSUE_KEY_PROJECT_VERSION_ID, projectVersionId); + jqlBuilder.append("OR "); + appendCommentSearchString(jqlBuilder, JiraIssuePropertyKeys.JIRA_ISSUE_KEY_PROJECT_VERSION_ID, projectVersion.getValue()); + jqlBuilder.append(") "); } if(component != null) { + jqlBuilder.append(SEARCH_CONJUNCTION); + jqlBuilder.append(StringUtils.SPACE); appendCommentSearchString(jqlBuilder, JiraIssuePropertyKeys.JIRA_ISSUE_KEY_COMPONENT_NAME, component.getValue()); } if(componentVersion != null) { + jqlBuilder.append(SEARCH_CONJUNCTION); + jqlBuilder.append(StringUtils.SPACE); appendCommentSearchString(jqlBuilder, JiraIssuePropertyKeys.JIRA_ISSUE_KEY_COMPONENT_VERSION_NAME, componentVersion.getValue()); } if(concernType != null) { + jqlBuilder.append(SEARCH_CONJUNCTION); + jqlBuilder.append(StringUtils.SPACE); appendCommentSearchString(jqlBuilder, JiraIssuePropertyKeys.JIRA_ISSUE_KEY_CATEGORY, concernType.name()); } if(StringUtils.isNotBlank(policyName)) { String escapedPolicyName = JiraIssueSearchPropertyStringCompatibilityUtils.createPolicyAdditionalKey(policyName); + jqlBuilder.append(SEARCH_CONJUNCTION); + jqlBuilder.append(StringUtils.SPACE); appendCommentSearchString(jqlBuilder, JiraIssuePropertyKeys.JIRA_ISSUE_KEY_POLICY_NAME, escapedPolicyName); } jqlBuilder.append(")"); @@ -212,8 +230,7 @@ private static void appendProjectKey(StringBuilder jqlBuilder, String jiraProjec } private static void appendCommentSearchString(StringBuilder jqlBuilder, String key, String value) { - jqlBuilder.append(SEARCH_CONJUNCTION); - jqlBuilder.append(" comment ~ \""); + jqlBuilder.append("comment ~ \""); jqlBuilder.append(String.format("%s%s%s", key,JiraIssuePropertyKeys.JIRA_ISSUE_KEY_SEPARATOR, escapeSearchString(value))); jqlBuilder.append("\""); jqlBuilder.append(StringUtils.SPACE); diff --git a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/SearchCommentCreator.java b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/SearchCommentCreator.java new file mode 100644 index 0000000000..8baa03e44f --- /dev/null +++ b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/SearchCommentCreator.java @@ -0,0 +1,73 @@ +package com.blackduck.integration.alert.api.channel.jira.distribution.search; + +import com.blackduck.integration.alert.api.processor.extract.model.project.ComponentConcernType; +import com.blackduck.integration.alert.common.message.model.LinkableItem; +import org.apache.commons.lang3.StringUtils; + +import javax.annotation.Nullable; + +public final class SearchCommentCreator { + + public static String createSearchComment(LinkableItem project, LinkableItem projectVersion, LinkableItem component, @Nullable LinkableItem componentVersion, @Nullable ComponentConcernType componentConcernType, @Nullable String policyName) { + String projectId = StringUtils.substringAfterLast(project.getUrl().orElse(""), "/"); + int versionUUIDStart = StringUtils.lastIndexOf(projectVersion.getUrl().orElse(""), "versions/") + "versions/".length(); + int versionUUIDEnd = StringUtils.indexOf(projectVersion.getUrl().orElse(""), "/", versionUUIDStart); + String projectVersionId = StringUtils.substring(projectVersion.getUrl().orElse(""), versionUUIDStart, versionUUIDEnd); + String componentName = component.getValue(); + String componentVersionName = null; + if(null != componentVersion) { + componentVersionName = componentVersion.getValue(); + } + return createSearchComment(projectId, projectVersionId, componentName, componentVersionName, componentConcernType, policyName); + } + + public static String createSearchComment(String projectId, String projectVersionId, String componentName, @Nullable String componentVersion, @Nullable ComponentConcernType componentConcernType, @Nullable String policyName) { + StringBuilder keyBuilder = new StringBuilder(); + + keyBuilder.append("This comment was automatically created by Alert. DO NOT REMOVE."); + keyBuilder.append(JiraIssuePropertyKeys.JIRA_ISSUE_KEY_START_HEADER); + keyBuilder.append(StringUtils.SPACE); + keyBuilder.append(JiraIssuePropertyKeys.JIRA_ISSUE_KEY_PROJECT_ID); + keyBuilder.append(JiraIssuePropertyKeys.JIRA_ISSUE_KEY_SEPARATOR); + keyBuilder.append(projectId); + keyBuilder.append(StringUtils.SPACE); + keyBuilder.append(JiraIssuePropertyKeys.JIRA_ISSUE_KEY_PROJECT_VERSION_ID); + keyBuilder.append(JiraIssuePropertyKeys.JIRA_ISSUE_KEY_SEPARATOR); + keyBuilder.append(projectVersionId); + keyBuilder.append(StringUtils.SPACE); + keyBuilder.append(JiraIssuePropertyKeys.JIRA_ISSUE_KEY_COMPONENT_NAME); + keyBuilder.append(JiraIssuePropertyKeys.JIRA_ISSUE_KEY_SEPARATOR); + keyBuilder.append(componentName); + keyBuilder.append(StringUtils.SPACE); + if(StringUtils.isNotBlank(componentVersion)) { + keyBuilder.append(JiraIssuePropertyKeys.JIRA_ISSUE_KEY_COMPONENT_VERSION_NAME); + keyBuilder.append(JiraIssuePropertyKeys.JIRA_ISSUE_KEY_SEPARATOR); + keyBuilder.append(componentVersion); + keyBuilder.append(StringUtils.SPACE); + } + + if(null != componentConcernType) { + keyBuilder.append(JiraIssuePropertyKeys.JIRA_ISSUE_KEY_CATEGORY); + keyBuilder.append(JiraIssuePropertyKeys.JIRA_ISSUE_KEY_SEPARATOR); + keyBuilder.append(componentConcernType.name()); + keyBuilder.append(StringUtils.SPACE); + } + + if(StringUtils.isNotBlank(policyName)) { + // add policy name + keyBuilder.append(JiraIssuePropertyKeys.JIRA_ISSUE_KEY_POLICY_NAME); + keyBuilder.append(JiraIssuePropertyKeys.JIRA_ISSUE_KEY_SEPARATOR); + keyBuilder.append(JiraIssueSearchPropertyStringCompatibilityUtils.createPolicyAdditionalKey(policyName)); + keyBuilder.append(StringUtils.SPACE); + } + keyBuilder.append(StringUtils.SPACE); + keyBuilder.append(JiraIssuePropertyKeys.JIRA_ISSUE_KEY_END_HEADER); + + return keyBuilder.toString(); + } + + private SearchCommentCreator() { + // cannot instantiate this class. + } + +} diff --git a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/lifecycle/JiraPropertyTask.java b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/lifecycle/JiraPropertyTask.java index a5c9eb8a6c..c0d959336c 100644 --- a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/lifecycle/JiraPropertyTask.java +++ b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/lifecycle/JiraPropertyTask.java @@ -26,9 +26,6 @@ public abstract class JiraPropertyTask extends JiraTask { // 2. A summary that isn't an Alert test message and have a comment "This issue was automatically created by Alert." // 3. Then check if the new property key exists on that issue. Only works because the new property key is indexed with the new plugin. protected static final String JQL_QUERY_FOR_ISSUE_PROPERTY_MIGRATION = String.format("(summary ~ \"Alert - Black Duck\" OR (summary !~ \"Alert Test Message\" AND comment ~ \"This issue was automatically created by Alert.\")) AND issue.property[%s].topicName IS EMPTY ORDER BY created DESC", JiraConstants.JIRA_ISSUE_PROPERTY_KEY); - protected static final JiraIssueSearchProperties EMPTY_SEARCH_PROPERTIES = new JiraIssueSearchProperties(StringUtils.EMPTY, - StringUtils.EMPTY, StringUtils.EMPTY, StringUtils.EMPTY, StringUtils.EMPTY, StringUtils.EMPTY, StringUtils.EMPTY, - StringUtils.EMPTY, StringUtils.EMPTY, StringUtils.EMPTY, StringUtils.EMPTY, StringUtils.EMPTY); public static String createProjectSpecificQuery(String projectName) { String projectQueryValue = String.format("\"%s\"", projectName); @@ -72,7 +69,7 @@ protected void setIssueProperty(String issueKey, IssuePropertyService issuePrope protected String getCurrentPropertyValue(String issueKey, IssuePropertyService issuePropertyService) { // empty property value - String jsonPropertyValue = getGson().toJson(EMPTY_SEARCH_PROPERTIES); + String jsonPropertyValue = getGson().toJson(JiraTask.EMPTY_SEARCH_PROPERTIES); try { IssuePropertyResponseModel issuePropertyResponse = issuePropertyService.getProperty(issueKey, JiraConstants.JIRA_ISSUE_PROPERTY_OLD_KEY); jsonPropertyValue = getGson().toJson(issuePropertyResponse.getValue()); diff --git a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/lifecycle/JiraTask.java b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/lifecycle/JiraTask.java index c76dfe47c4..e0451ba34c 100644 --- a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/lifecycle/JiraTask.java +++ b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/lifecycle/JiraTask.java @@ -1,10 +1,12 @@ package com.blackduck.integration.alert.api.channel.jira.lifecycle; +import com.blackduck.integration.alert.api.channel.jira.JiraIssueSearchProperties; import com.blackduck.integration.alert.api.task.ScheduledTask; import com.blackduck.integration.alert.api.task.TaskManager; import com.blackduck.integration.alert.api.task.TaskMetaData; import com.blackduck.integration.alert.api.task.TaskMetaDataProperty; import com.google.gson.Gson; +import org.apache.commons.lang3.StringUtils; import org.springframework.scheduling.TaskScheduler; import java.util.List; @@ -13,6 +15,9 @@ public abstract class JiraTask extends ScheduledTask { protected static final int JQL_QUERY_MAX_RESULTS = 100; + protected static final JiraIssueSearchProperties EMPTY_SEARCH_PROPERTIES = new JiraIssueSearchProperties(StringUtils.EMPTY, + StringUtils.EMPTY, StringUtils.EMPTY, StringUtils.EMPTY, StringUtils.EMPTY, StringUtils.EMPTY, StringUtils.EMPTY, + StringUtils.EMPTY, StringUtils.EMPTY, StringUtils.EMPTY, StringUtils.EMPTY, StringUtils.EMPTY); private final TaskManager taskManager; private final String taskName; private final String configId; diff --git a/api-channel-jira/src/test/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/JqlStringCreatorTest.java b/api-channel-jira/src/test/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/JqlStringCreatorTest.java index 0715bad0a8..50f362e61f 100644 --- a/api-channel-jira/src/test/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/JqlStringCreatorTest.java +++ b/api-channel-jira/src/test/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/JqlStringCreatorTest.java @@ -55,8 +55,8 @@ void policySearchStringTest() { "(" + "project = 'TEST'" + " AND comment ~\"=== BEGIN JIRA ISSUE KEYS ===\"" - + " AND comment ~ \"projectId: project-uuid\"" - + " AND comment ~ \"projectVersionId: project-version-uuid\"" + + " AND (comment ~ \"projectId: project-uuid\" OR comment ~ \"projectId: project_with_single_quote\\'\" )" + + " AND (comment ~ \"projectVersionId: project-version-uuid\" OR comment ~ \"projectVersionId: v1.0 \\\\& v2.0\" )" + " AND comment ~ \"componentName: myVulnerableComponent\"" + " AND comment ~ \"componentVersionName: 1.1.2\"" + " AND comment ~ \"category: POLICY\"" @@ -96,8 +96,8 @@ void vulnerabilitySearchStringTest() { "(" + "project = 'TEST'" + " AND comment ~\"=== BEGIN JIRA ISSUE KEYS ===\"" - + " AND comment ~ \"projectId: project-uuid\"" - + " AND comment ~ \"projectVersionId: project-version-uuid\"" + + " AND (comment ~ \"projectId: project-uuid\" OR comment ~ \"projectId: project_with_single_quote\\'\" )" + + " AND (comment ~ \"projectVersionId: project-version-uuid\" OR comment ~ \"projectVersionId: v1.0 \\\\& v2.0\" )" + " AND comment ~ \"componentName: myVulnerableComponent\"" + " AND comment ~ \"componentVersionName: 1.1.2\"" + " AND comment ~ \"category: VULNERABILITY\"" @@ -141,8 +141,8 @@ void injectionTest() { "(" + "project = 'TEST'" + " AND comment ~\"=== BEGIN JIRA ISSUE KEYS ===\"" - + " AND comment ~ \"projectId: project-uuid\"" - + " AND comment ~ \"projectVersionId: projectVersionUrl\"" + + " AND (comment ~ \"projectId: project-uuid\" OR comment ~ \"projectId: project_with_single_quote\\'\" )" + + " AND (comment ~ \"projectVersionId: projectVersionUrl\" OR comment ~ \"projectVersionId: INJECTED\\\\\\' OR project = \"SomeOtherProject\" OR summary ~ 2021-01-01\\\\\\\\\\\\\" )" + " AND comment ~ \"componentName: myVulnerableComponent\"" + " AND comment ~ \"componentVersionName: 1.1.2\"" + " AND comment ~ \"category: VULNERABILITY\"" diff --git a/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraSearchCommentUpdateTask.java b/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraSearchCommentUpdateTask.java index e42e9d9d11..26d3ce81c8 100644 --- a/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraSearchCommentUpdateTask.java +++ b/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraSearchCommentUpdateTask.java @@ -9,7 +9,10 @@ import com.blackduck.integration.exception.IntegrationException; import com.blackduck.integration.jira.common.cloud.model.IssueSearchResponseModel; import com.blackduck.integration.jira.common.cloud.service.IssueSearchService; +import com.blackduck.integration.jira.common.cloud.service.IssueService; import com.blackduck.integration.jira.common.cloud.service.JiraCloudServiceFactory; +import com.blackduck.integration.jira.common.model.request.IssueCommentRequestModel; +import com.blackduck.integration.jira.common.model.response.IssuePropertyResponseModel; import com.blackduck.integration.jira.common.model.response.IssueResponseModel; import com.blackduck.integration.jira.common.rest.service.IssuePropertyService; import com.google.gson.Gson; @@ -18,6 +21,7 @@ import org.springframework.scheduling.TaskScheduler; import java.util.List; +import java.util.Optional; import java.util.concurrent.ExecutorService; import java.util.concurrent.TimeUnit; @@ -38,6 +42,7 @@ public void runTask() { JiraCloudServiceFactory serviceFactory = jiraProperties.createJiraServicesCloudFactory(logger, getGson()); IssueSearchService issueSearchService = serviceFactory.createIssueSearchService(); IssuePropertyService issuePropertyService = serviceFactory.createIssuePropertyService(); + IssueService issueService = serviceFactory.createIssueService(); IssueSearchResponseModel responseModel = issueSearchService.queryForIssuePage(JiraConstants.JQL_QUERY_FOR_ISSUE_SEARCH_COMMENT_MIGRATION, 0, JQL_QUERY_MAX_RESULTS); @@ -50,7 +55,7 @@ public void runTask() { .toList(); ExecutorService executorService = getExecutorService(); for (String issueKey : issueKeys) { - executorService.submit(createUpdateRunnable(issueKey, issuePropertyService)); + executorService.submit(createUpdateRunnable(issueKey, issuePropertyService, issueService)); } executorService.shutdown(); boolean success = executorService.awaitTermination(1, TimeUnit.MINUTES); @@ -72,8 +77,39 @@ public void runTask() { } } - private Runnable createUpdateRunnable(String issueKey, IssuePropertyService issuePropertyService) { - return () -> {}; + private Runnable createUpdateRunnable(String issueKey, IssuePropertyService issuePropertyService, IssueService issueService) { + return () -> { + Optional propertyValue = getPropertyValue(issueKey, issuePropertyService, JiraConstants.JIRA_ISSUE_PROPERTY_KEY); + if (propertyValue.isEmpty()) { + // try the old key + propertyValue = getPropertyValue(issueKey, issuePropertyService, JiraConstants.JIRA_ISSUE_PROPERTY_OLD_KEY); + } + if(propertyValue.isPresent()) { + try { + IssueCommentRequestModel comment = createSearchKeyComment(issueKey, propertyValue.get()); + issueService.addComment(comment); + } catch (IntegrationException ex) { + logger.debug("Error updating issue {} with search key comment.", issueKey); + logger.debug("Caused by: ", ex); + } + } + }; + } + + private IssueCommentRequestModel createSearchKeyComment(String issueKey, IssuePropertyResponseModel propertyValue) { + return null; + } + + protected Optional getPropertyValue(String issueKey, IssuePropertyService issuePropertyService, String propertyKey) { + // empty property value + Optional responseModel = Optional.empty(); + try { + responseModel = Optional.ofNullable(issuePropertyService.getProperty(issueKey, propertyKey)); + } catch (IntegrationException ex) { + logger.debug("Error finding issue property {} for issue: {} cause: {}", propertyKey, issueKey, ex.getMessage()); + logger.debug("Caused by: ", ex); + } + return responseModel; } @Override diff --git a/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraSearchCommentUpdateTask.java b/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraSearchCommentUpdateTask.java index 1c8715c4af..5088b87bdc 100644 --- a/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraSearchCommentUpdateTask.java +++ b/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraSearchCommentUpdateTask.java @@ -7,10 +7,13 @@ import com.blackduck.integration.alert.channel.jira.server.JiraServerProperties; import com.blackduck.integration.alert.channel.jira.server.JiraServerPropertiesFactory; import com.blackduck.integration.exception.IntegrationException; +import com.blackduck.integration.jira.common.model.request.IssueCommentRequestModel; +import com.blackduck.integration.jira.common.model.response.IssuePropertyResponseModel; import com.blackduck.integration.jira.common.rest.service.IssuePropertyService; import com.blackduck.integration.jira.common.server.model.IssueSearchIssueComponent; import com.blackduck.integration.jira.common.server.model.IssueSearchResponseModel; import com.blackduck.integration.jira.common.server.service.IssueSearchService; +import com.blackduck.integration.jira.common.server.service.IssueService; import com.blackduck.integration.jira.common.server.service.JiraServerServiceFactory; import com.google.gson.Gson; import org.slf4j.Logger; @@ -18,6 +21,7 @@ import org.springframework.scheduling.TaskScheduler; import java.util.List; +import java.util.Optional; import java.util.UUID; import java.util.concurrent.ExecutorService; import java.util.concurrent.TimeUnit; @@ -41,6 +45,7 @@ public void runTask() { IssueSearchService issueSearchService = serviceFactory.createIssueSearchService(); IssuePropertyService issuePropertyService = serviceFactory.createIssuePropertyService(); IssueSearchResponseModel responseModel = issueSearchService.queryForIssuePage(JiraConstants.JQL_QUERY_FOR_ISSUE_SEARCH_COMMENT_MIGRATION, 0, JQL_QUERY_MAX_RESULTS); + IssueService issueService = serviceFactory.createIssueService(); int totalIssues = responseModel.getTotal(); boolean foundIssues = totalIssues > 0; @@ -51,7 +56,7 @@ public void runTask() { .toList(); ExecutorService executorService = getExecutorService(); for (String issueKey : issueKeys) { - executorService.submit(createUpdateRunnable(issueKey, issuePropertyService)); + executorService.submit(createUpdateRunnable(issueKey, issuePropertyService, issueService)); } executorService.shutdown(); boolean success = executorService.awaitTermination(1, TimeUnit.MINUTES); @@ -75,8 +80,39 @@ public void runTask() { logger.info("Jira Server search comment task ended."); } - private Runnable createUpdateRunnable(String issueKey, IssuePropertyService issuePropertyService) { - return () -> {}; + private Runnable createUpdateRunnable(String issueKey, IssuePropertyService issuePropertyService, IssueService issueService) { + return () -> { + Optional propertyValue = getPropertyValue(issueKey, issuePropertyService, JiraConstants.JIRA_ISSUE_PROPERTY_KEY); + if (propertyValue.isEmpty()) { + // try the old key + propertyValue = getPropertyValue(issueKey, issuePropertyService, JiraConstants.JIRA_ISSUE_PROPERTY_OLD_KEY); + } + if(propertyValue.isPresent()) { + try { + IssueCommentRequestModel comment = createSearchKeyComment(issueKey, propertyValue.get()); + issueService.addComment(comment); + } catch (IntegrationException ex) { + logger.debug("Error updating issue {} with search key comment.", issueKey); + logger.debug("Caused by: ", ex); + } + } + }; + } + + private IssueCommentRequestModel createSearchKeyComment(String issueKey, IssuePropertyResponseModel propertyValue) { + return null; + } + + protected Optional getPropertyValue(String issueKey, IssuePropertyService issuePropertyService, String propertyKey) { + // empty property value + Optional responseModel = Optional.empty(); + try { + responseModel = Optional.ofNullable(issuePropertyService.getProperty(issueKey, propertyKey)); + } catch (IntegrationException ex) { + logger.debug("Error finding issue property {} for issue: {} cause: {}", propertyKey, issueKey, ex.getMessage()); + logger.debug("Caused by: ", ex); + } + return responseModel; } @Override From 3bf9771262b2ccc97412c3802cdc981a132c010c Mon Sep 17 00:00:00 2001 From: Paulo Santos Date: Thu, 28 Aug 2025 10:35:05 -0400 Subject: [PATCH 09/18] IALERT-3873: Implement the code to read the properties and create the comment. --- .../search/SearchCommentCreator.java | 10 +++++--- .../task/JiraSearchCommentUpdateTask.java | 24 +++++++++++++++++- .../task/JiraSearchCommentUpdateTask.java | 25 ++++++++++++++++++- 3 files changed, 53 insertions(+), 6 deletions(-) diff --git a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/SearchCommentCreator.java b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/SearchCommentCreator.java index 8baa03e44f..efbce1bbfe 100644 --- a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/SearchCommentCreator.java +++ b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/SearchCommentCreator.java @@ -5,6 +5,7 @@ import org.apache.commons.lang3.StringUtils; import javax.annotation.Nullable; +import java.util.Optional; public final class SearchCommentCreator { @@ -15,13 +16,14 @@ public static String createSearchComment(LinkableItem project, LinkableItem proj String projectVersionId = StringUtils.substring(projectVersion.getUrl().orElse(""), versionUUIDStart, versionUUIDEnd); String componentName = component.getValue(); String componentVersionName = null; + String category = Optional.ofNullable(componentConcernType).map(ComponentConcernType::name).orElse(null); if(null != componentVersion) { componentVersionName = componentVersion.getValue(); } - return createSearchComment(projectId, projectVersionId, componentName, componentVersionName, componentConcernType, policyName); + return createSearchComment(projectId, projectVersionId, componentName, componentVersionName, category, policyName); } - public static String createSearchComment(String projectId, String projectVersionId, String componentName, @Nullable String componentVersion, @Nullable ComponentConcernType componentConcernType, @Nullable String policyName) { + public static String createSearchComment(String projectId, String projectVersionId, String componentName, @Nullable String componentVersion, @Nullable String category, @Nullable String policyName) { StringBuilder keyBuilder = new StringBuilder(); keyBuilder.append("This comment was automatically created by Alert. DO NOT REMOVE."); @@ -46,10 +48,10 @@ public static String createSearchComment(String projectId, String projectVersion keyBuilder.append(StringUtils.SPACE); } - if(null != componentConcernType) { + if(StringUtils.isNotBlank(category)) { keyBuilder.append(JiraIssuePropertyKeys.JIRA_ISSUE_KEY_CATEGORY); keyBuilder.append(JiraIssuePropertyKeys.JIRA_ISSUE_KEY_SEPARATOR); - keyBuilder.append(componentConcernType.name()); + keyBuilder.append(category); keyBuilder.append(StringUtils.SPACE); } diff --git a/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraSearchCommentUpdateTask.java b/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraSearchCommentUpdateTask.java index 26d3ce81c8..00fd3ed515 100644 --- a/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraSearchCommentUpdateTask.java +++ b/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraSearchCommentUpdateTask.java @@ -1,6 +1,8 @@ package com.blackduck.integration.alert.channel.jira.cloud.task; import com.blackduck.integration.alert.api.channel.jira.JiraConstants; +import com.blackduck.integration.alert.api.channel.jira.distribution.search.JiraIssuePropertyKeys; +import com.blackduck.integration.alert.api.channel.jira.distribution.search.SearchCommentCreator; import com.blackduck.integration.alert.api.channel.jira.lifecycle.JiraTask; import com.blackduck.integration.alert.api.task.ScheduledTask; import com.blackduck.integration.alert.api.task.TaskManager; @@ -16,6 +18,7 @@ import com.blackduck.integration.jira.common.model.response.IssueResponseModel; import com.blackduck.integration.jira.common.rest.service.IssuePropertyService; import com.google.gson.Gson; +import com.google.gson.JsonObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.scheduling.TaskScheduler; @@ -97,7 +100,26 @@ private Runnable createUpdateRunnable(String issueKey, IssuePropertyService issu } private IssueCommentRequestModel createSearchKeyComment(String issueKey, IssuePropertyResponseModel propertyValue) { - return null; + JsonObject jsonObject = propertyValue.getValue(); + // projectName, projectVersionName, and componentName should all be populated but since an optional is returned use orElse(null) + String projectName = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_PROJECT_NAME).orElse(null); + String projectVersionName = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_PROJECT_VERSION_NAME).orElse(null); + String componentName = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_COMPONENT_VALUE).orElse(null); + String componentVersionName = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_SUB_COMPONENT_VALUE).orElse(null); + String category = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_CATEGORY).orElse(null); + String policyName = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_ADDITIONAL_KEY).orElse(null); + String commentString = SearchCommentCreator.createSearchComment(projectName, projectVersionName, componentName, componentVersionName, category, policyName); + return new IssueCommentRequestModel(issueKey, commentString); + } + + public Optional getPropertyValue(JsonObject jsonObject, String propertyKey) { + Optional value = Optional.empty(); + + if(jsonObject.has(propertyKey)) { + value = Optional.of(jsonObject.get(propertyKey).getAsString()); + } + + return value; } protected Optional getPropertyValue(String issueKey, IssuePropertyService issuePropertyService, String propertyKey) { diff --git a/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraSearchCommentUpdateTask.java b/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraSearchCommentUpdateTask.java index 5088b87bdc..6acd9be547 100644 --- a/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraSearchCommentUpdateTask.java +++ b/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraSearchCommentUpdateTask.java @@ -1,6 +1,8 @@ package com.blackduck.integration.alert.channel.jira.server.task; import com.blackduck.integration.alert.api.channel.jira.JiraConstants; +import com.blackduck.integration.alert.api.channel.jira.distribution.search.JiraIssuePropertyKeys; +import com.blackduck.integration.alert.api.channel.jira.distribution.search.SearchCommentCreator; import com.blackduck.integration.alert.api.channel.jira.lifecycle.JiraTask; import com.blackduck.integration.alert.api.task.ScheduledTask; import com.blackduck.integration.alert.api.task.TaskManager; @@ -16,6 +18,7 @@ import com.blackduck.integration.jira.common.server.service.IssueService; import com.blackduck.integration.jira.common.server.service.JiraServerServiceFactory; import com.google.gson.Gson; +import com.google.gson.JsonObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.scheduling.TaskScheduler; @@ -100,9 +103,29 @@ private Runnable createUpdateRunnable(String issueKey, IssuePropertyService issu } private IssueCommentRequestModel createSearchKeyComment(String issueKey, IssuePropertyResponseModel propertyValue) { - return null; + JsonObject jsonObject = propertyValue.getValue(); + // projectName, projectVersionName, and componentName should all be populated but since an optional is returned use orElse(null) + String projectName = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_PROJECT_NAME).orElse(null); + String projectVersionName = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_PROJECT_VERSION_NAME).orElse(null); + String componentName = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_COMPONENT_VALUE).orElse(null); + String componentVersionName = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_SUB_COMPONENT_VALUE).orElse(null); + String category = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_CATEGORY).orElse(null); + String policyName = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_ADDITIONAL_KEY).orElse(null); + String commentString = SearchCommentCreator.createSearchComment(projectName, projectVersionName, componentName, componentVersionName, category, policyName); + return new IssueCommentRequestModel(issueKey, commentString); } + public Optional getPropertyValue(JsonObject jsonObject, String propertyKey) { + Optional value = Optional.empty(); + + if(jsonObject.has(propertyKey)) { + value = Optional.of(jsonObject.get(propertyKey).getAsString()); + } + + return value; + } + + protected Optional getPropertyValue(String issueKey, IssuePropertyService issuePropertyService, String propertyKey) { // empty property value Optional responseModel = Optional.empty(); From 028f7dc67c2f4daf043cd1b2688defb8e679a618 Mon Sep 17 00:00:00 2001 From: Paulo Santos Date: Fri, 29 Aug 2025 15:54:31 -0400 Subject: [PATCH 10/18] IALERT-3873: Fix the start of the property tasks. --- .../alert/api/channel/jira/lifecycle/JiraTask.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/lifecycle/JiraTask.java b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/lifecycle/JiraTask.java index e0451ba34c..9083a87f4d 100644 --- a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/lifecycle/JiraTask.java +++ b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/lifecycle/JiraTask.java @@ -24,12 +24,12 @@ public abstract class JiraTask extends ScheduledTask { private final String configName; private final Gson gson; - public JiraTask(TaskScheduler taskScheduler, TaskManager taskManager, String taskName, String configId, String configName, Gson gson) { + public JiraTask(TaskScheduler taskScheduler, TaskManager taskManager, String configId, String configName, String taskNameSuffix, Gson gson) { super(taskScheduler); this.taskManager = taskManager; - this.taskName = taskName; this.configId = configId; this.configName = configName; + this.taskName = computeTaskName(taskNameSuffix); this.gson = gson; } From 6659326f55e1766d6d669f17ef19bb9fcbabe93a Mon Sep 17 00:00:00 2001 From: Paulo Santos Date: Fri, 29 Aug 2025 17:47:48 -0400 Subject: [PATCH 11/18] IALERT-3873: Fix JQL query to migrate issues missing comments. --- .../alert/api/channel/jira/JiraConstants.java | 27 ++++++++++++ .../delegate/JiraIssueCreator.java | 5 ++- .../distribution/search/JqlStringCreator.java | 31 +++++++++++++- .../search/JqlStringCreatorTest.java | 2 +- .../task/JiraSearchCommentUpdateTask.java | 41 ++++++++++++------- .../task/JiraSearchCommentUpdateTask.java | 41 ++++++++++++------- 6 files changed, 113 insertions(+), 34 deletions(-) diff --git a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/JiraConstants.java b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/JiraConstants.java index 740af2a3bf..3110a21e16 100644 --- a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/JiraConstants.java +++ b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/JiraConstants.java @@ -27,6 +27,8 @@ public final class JiraConstants { // 3. Then check if the new property key exists on that issue or if the old property key is on the issue. public static final String JQL_QUERY_FOR_ISSUE_SEARCH_COMMENT_MIGRATION = String.format("(summary ~ \"Alert - Black Duck\" OR (summary !~ \"Alert Test Message\" AND NOT comment ~\"%s\")) AND (issue.property[%s].topicName IS NOT EMPTY OR issue.property[%s].topicName IS NOT EMPTY) ORDER BY created DESC", JiraIssuePropertyKeys.JIRA_ISSUE_KEY_START_HEADER, JiraConstants.JIRA_ISSUE_PROPERTY_KEY, JiraConstants.JIRA_ISSUE_PROPERTY_OLD_KEY); + public static final String JIRA_ISSUE_PROPERTY_SEARCH_COMMENT_MIGRATION_TOKEN = "_alert_9_migrated"; + // These Strings must always match the Strings found in the atlassian-connect.json file under modules.jiraEntityProperties.keyConfigurations.propertyKey["com-blackduck-integration-alert"].extractions.objectName. public static final String JIRA_ISSUE_PROPERTY_OBJECT_KEY_PROVIDER = "provider"; public static final String JIRA_ISSUE_PROPERTY_OBJECT_KEY_PROVIDER_URL = "providerUrl"; @@ -43,6 +45,31 @@ public final class JiraConstants { public static final String JIRA_ISSUE_VALIDATION_ERROR_MESSAGE = "There are issues with the configuration."; + + public static String createCommentMigrationJQL() { + // find tickets created by alert first: + // 1. A summary that starts with "Alert - Black Duck" + // 2. A summary that isn't an Alert test message + // 3. Then check if the new property key exists on that issue + // 4. Then check if the new property additionalKey is empty or has the text "_alert_9_migrated". + + // TODO we may be able to add a net new field to the properties and that may work better to key off of. + return "(summary ~ \"Alert - Black Duck\" OR summary !~ \"Alert Test Message\")" + + " AND " + + "(issue.property[" + + JiraConstants.JIRA_ISSUE_PROPERTY_KEY + + "].topicName IS NOT EMPTY " + + "AND " + + "(issue.property[" + + JiraConstants.JIRA_ISSUE_PROPERTY_KEY + + "].additionalKey IS EMPTY " + + "OR issue.property[" + + JiraConstants.JIRA_ISSUE_PROPERTY_KEY + + "].additionalKey !~ '" + + JiraConstants.JIRA_ISSUE_PROPERTY_SEARCH_COMMENT_MIGRATION_TOKEN + + "'))"; + } + private JiraConstants() { } diff --git a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/delegate/JiraIssueCreator.java b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/delegate/JiraIssueCreator.java index 58069f7e50..bec0dbb083 100644 --- a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/delegate/JiraIssueCreator.java +++ b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/delegate/JiraIssueCreator.java @@ -10,6 +10,7 @@ import java.util.List; import java.util.Optional; +import com.blackduck.integration.alert.api.channel.jira.JiraConstants; import com.blackduck.integration.alert.api.channel.jira.distribution.search.SearchCommentCreator; import org.apache.commons.lang3.StringUtils; @@ -204,7 +205,7 @@ private JiraIssueSearchProperties createSearchProperties(ProjectIssueModel alert String componentVersionLabel = bomComponent.getComponentVersion().map(LinkableItem::getLabel).orElse(null); String componentVersionName = bomComponent.getComponentVersion().map(LinkableItem::getValue).orElse(null); - String additionalKey = null; + String additionalKey = ""; ComponentConcernType concernType = ComponentConcernType.VULNERABILITY; Optional optionalPolicyName = alertIssueSource.getPolicyDetails().map(IssuePolicyDetails::getName); @@ -230,7 +231,7 @@ private JiraIssueSearchProperties createSearchProperties(ProjectIssueModel alert component.getValue(), componentVersionLabel, componentVersionName, - additionalKey + additionalKey + JiraConstants.JIRA_ISSUE_PROPERTY_SEARCH_COMMENT_MIGRATION_TOKEN ); } diff --git a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/JqlStringCreator.java b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/JqlStringCreator.java index 664322aae8..7804d5894d 100644 --- a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/JqlStringCreator.java +++ b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/JqlStringCreator.java @@ -91,7 +91,36 @@ public static String createBlackDuckComponentConcernIssuesSearchString( if (ComponentConcernType.POLICY.equals(concernType) && null != policyName) { String additionalKey = JiraIssueSearchPropertyStringCompatibilityUtils.createPolicyAdditionalKey(policyName); - appendPropertySearchString(jqlBuilder, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_ADDITIONAL_KEY, additionalKey); + String escapedValue = escapeSearchString(additionalKey); + + jqlBuilder.append(SEARCH_CONJUNCTION); + jqlBuilder.append(StringUtils.SPACE); + jqlBuilder.append("(issue.property[") + .append(JiraConstants.JIRA_ISSUE_PROPERTY_KEY) + .append("].") + .append(JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_ADDITIONAL_KEY) + .append(" = '") + .append(escapedValue) + .append("'"); + jqlBuilder.append(" OR "); + jqlBuilder.append("issue.property[") + .append(JiraConstants.JIRA_ISSUE_PROPERTY_OLD_KEY) + .append("].") + .append(JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_ADDITIONAL_KEY) + .append(" = '") + .append(escapedValue) + .append("'"); + jqlBuilder.append(" OR "); + jqlBuilder.append("issue.property[") + .append(JiraConstants.JIRA_ISSUE_PROPERTY_KEY) + .append("].") + .append(JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_ADDITIONAL_KEY) + .append(" = '") + .append(escapedValue) + .append(JiraConstants.JIRA_ISSUE_PROPERTY_SEARCH_COMMENT_MIGRATION_TOKEN) + .append("'"); + jqlBuilder.append(")"); + jqlBuilder.append(StringUtils.SPACE); } jqlBuilder.append(")"); diff --git a/api-channel-jira/src/test/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/JqlStringCreatorTest.java b/api-channel-jira/src/test/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/JqlStringCreatorTest.java index 50f362e61f..23e367a734 100644 --- a/api-channel-jira/src/test/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/JqlStringCreatorTest.java +++ b/api-channel-jira/src/test/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/JqlStringCreatorTest.java @@ -74,7 +74,7 @@ void policySearchStringTest() { + "AND (issue.property[com-blackduck-integration-alert].subComponentName = 'Component Version' OR issue.property[com-synopsys-integration-alert].subComponentName = 'Component Version') " + "AND (issue.property[com-blackduck-integration-alert].subComponentValue = '1.1.2' OR issue.property[com-synopsys-integration-alert].subComponentValue = '1.1.2') " + "AND (issue.property[com-blackduck-integration-alert].category = 'Policy' OR issue.property[com-synopsys-integration-alert].category = 'Policy') " - + "AND (issue.property[com-blackduck-integration-alert].additionalKey = 'Policy ViolatedMyPolicy' OR issue.property[com-synopsys-integration-alert].additionalKey = 'Policy ViolatedMyPolicy') " + + "AND (issue.property[com-blackduck-integration-alert].additionalKey = 'Policy ViolatedMyPolicy' OR issue.property[com-synopsys-integration-alert].additionalKey = 'Policy ViolatedMyPolicy' OR issue.property[com-blackduck-integration-alert].additionalKey = 'Policy ViolatedMyPolicy_alert_9_migrated') " + ")"; assertEquals(expectedSearchString, jqlString); diff --git a/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraSearchCommentUpdateTask.java b/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraSearchCommentUpdateTask.java index 00fd3ed515..1fc1a8baef 100644 --- a/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraSearchCommentUpdateTask.java +++ b/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraSearchCommentUpdateTask.java @@ -19,6 +19,7 @@ import com.blackduck.integration.jira.common.rest.service.IssuePropertyService; import com.google.gson.Gson; import com.google.gson.JsonObject; +import io.micrometer.common.util.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.scheduling.TaskScheduler; @@ -47,7 +48,7 @@ public void runTask() { IssuePropertyService issuePropertyService = serviceFactory.createIssuePropertyService(); IssueService issueService = serviceFactory.createIssueService(); - IssueSearchResponseModel responseModel = issueSearchService.queryForIssuePage(JiraConstants.JQL_QUERY_FOR_ISSUE_SEARCH_COMMENT_MIGRATION, 0, JQL_QUERY_MAX_RESULTS); + IssueSearchResponseModel responseModel = issueSearchService.queryForIssuePage(JiraConstants.createCommentMigrationJQL(), 0, JQL_QUERY_MAX_RESULTS); int totalIssues = responseModel.getTotal(); boolean foundIssues = totalIssues > 0; @@ -89,7 +90,30 @@ private Runnable createUpdateRunnable(String issueKey, IssuePropertyService issu } if(propertyValue.isPresent()) { try { - IssueCommentRequestModel comment = createSearchKeyComment(issueKey, propertyValue.get()); + JsonObject jsonObject = propertyValue.get().getValue(); + // projectName, projectVersionName, and componentName should all be populated but since an optional is returned use orElse(null) + String projectName = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_PROJECT_NAME).orElse(null); + String projectVersionName = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_PROJECT_VERSION_NAME).orElse(null); + String componentName = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_COMPONENT_VALUE).orElse(null); + String componentVersionName = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_SUB_COMPONENT_VALUE).orElse(null); + String category = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_CATEGORY).orElse(null); + String policyName = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_ADDITIONAL_KEY).orElse(null); + + String migratedAdditionalKeyValue; + if(StringUtils.isNotBlank(policyName)) { + // append jira 9 migration property + migratedAdditionalKeyValue = policyName + JiraConstants.JIRA_ISSUE_PROPERTY_SEARCH_COMMENT_MIGRATION_TOKEN; + } else { + // add jira 9 migration property + migratedAdditionalKeyValue = JiraConstants.JIRA_ISSUE_PROPERTY_SEARCH_COMMENT_MIGRATION_TOKEN; + } + + jsonObject.addProperty(JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_ADDITIONAL_KEY, migratedAdditionalKeyValue); + String migratedPropertyValue = getGson().toJson(jsonObject); + issuePropertyService.setProperty(issueKey, JiraConstants.JIRA_ISSUE_PROPERTY_KEY, migratedPropertyValue); + + String commentString = SearchCommentCreator.createSearchComment(projectName, projectVersionName, componentName, componentVersionName, category, policyName); + IssueCommentRequestModel comment = new IssueCommentRequestModel(issueKey, commentString); issueService.addComment(comment); } catch (IntegrationException ex) { logger.debug("Error updating issue {} with search key comment.", issueKey); @@ -99,19 +123,6 @@ private Runnable createUpdateRunnable(String issueKey, IssuePropertyService issu }; } - private IssueCommentRequestModel createSearchKeyComment(String issueKey, IssuePropertyResponseModel propertyValue) { - JsonObject jsonObject = propertyValue.getValue(); - // projectName, projectVersionName, and componentName should all be populated but since an optional is returned use orElse(null) - String projectName = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_PROJECT_NAME).orElse(null); - String projectVersionName = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_PROJECT_VERSION_NAME).orElse(null); - String componentName = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_COMPONENT_VALUE).orElse(null); - String componentVersionName = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_SUB_COMPONENT_VALUE).orElse(null); - String category = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_CATEGORY).orElse(null); - String policyName = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_ADDITIONAL_KEY).orElse(null); - String commentString = SearchCommentCreator.createSearchComment(projectName, projectVersionName, componentName, componentVersionName, category, policyName); - return new IssueCommentRequestModel(issueKey, commentString); - } - public Optional getPropertyValue(JsonObject jsonObject, String propertyKey) { Optional value = Optional.empty(); diff --git a/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraSearchCommentUpdateTask.java b/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraSearchCommentUpdateTask.java index 6acd9be547..43d150ba72 100644 --- a/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraSearchCommentUpdateTask.java +++ b/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraSearchCommentUpdateTask.java @@ -19,6 +19,7 @@ import com.blackduck.integration.jira.common.server.service.JiraServerServiceFactory; import com.google.gson.Gson; import com.google.gson.JsonObject; +import io.micrometer.common.util.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.scheduling.TaskScheduler; @@ -47,7 +48,7 @@ public void runTask() { JiraServerServiceFactory serviceFactory = jiraProperties.createJiraServicesServerFactory(logger,getGson()); IssueSearchService issueSearchService = serviceFactory.createIssueSearchService(); IssuePropertyService issuePropertyService = serviceFactory.createIssuePropertyService(); - IssueSearchResponseModel responseModel = issueSearchService.queryForIssuePage(JiraConstants.JQL_QUERY_FOR_ISSUE_SEARCH_COMMENT_MIGRATION, 0, JQL_QUERY_MAX_RESULTS); + IssueSearchResponseModel responseModel = issueSearchService.queryForIssuePage(JiraConstants.createCommentMigrationJQL(), 0, JQL_QUERY_MAX_RESULTS); IssueService issueService = serviceFactory.createIssueService(); int totalIssues = responseModel.getTotal(); @@ -92,7 +93,30 @@ private Runnable createUpdateRunnable(String issueKey, IssuePropertyService issu } if(propertyValue.isPresent()) { try { - IssueCommentRequestModel comment = createSearchKeyComment(issueKey, propertyValue.get()); + JsonObject jsonObject = propertyValue.get().getValue(); + // projectName, projectVersionName, and componentName should all be populated but since an optional is returned use orElse(null) + String projectName = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_PROJECT_NAME).orElse(null); + String projectVersionName = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_PROJECT_VERSION_NAME).orElse(null); + String componentName = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_COMPONENT_VALUE).orElse(null); + String componentVersionName = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_SUB_COMPONENT_VALUE).orElse(null); + String category = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_CATEGORY).orElse(null); + String policyName = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_ADDITIONAL_KEY).orElse(null); + + String migratedAdditionalKeyValue; + if(StringUtils.isNotBlank(policyName)) { + // append jira 9 migration property + migratedAdditionalKeyValue = policyName + JiraConstants.JIRA_ISSUE_PROPERTY_SEARCH_COMMENT_MIGRATION_TOKEN; + } else { + // add jira 9 migration property + migratedAdditionalKeyValue = JiraConstants.JIRA_ISSUE_PROPERTY_SEARCH_COMMENT_MIGRATION_TOKEN; + } + + jsonObject.addProperty(JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_ADDITIONAL_KEY, migratedAdditionalKeyValue); + String migratedPropertyValue = getGson().toJson(jsonObject); + issuePropertyService.setProperty(issueKey, JiraConstants.JIRA_ISSUE_PROPERTY_KEY, migratedPropertyValue); + + String commentString = SearchCommentCreator.createSearchComment(projectName, projectVersionName, componentName, componentVersionName, category, policyName); + IssueCommentRequestModel comment = new IssueCommentRequestModel(issueKey, commentString); issueService.addComment(comment); } catch (IntegrationException ex) { logger.debug("Error updating issue {} with search key comment.", issueKey); @@ -102,19 +126,6 @@ private Runnable createUpdateRunnable(String issueKey, IssuePropertyService issu }; } - private IssueCommentRequestModel createSearchKeyComment(String issueKey, IssuePropertyResponseModel propertyValue) { - JsonObject jsonObject = propertyValue.getValue(); - // projectName, projectVersionName, and componentName should all be populated but since an optional is returned use orElse(null) - String projectName = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_PROJECT_NAME).orElse(null); - String projectVersionName = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_PROJECT_VERSION_NAME).orElse(null); - String componentName = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_COMPONENT_VALUE).orElse(null); - String componentVersionName = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_SUB_COMPONENT_VALUE).orElse(null); - String category = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_CATEGORY).orElse(null); - String policyName = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_ADDITIONAL_KEY).orElse(null); - String commentString = SearchCommentCreator.createSearchComment(projectName, projectVersionName, componentName, componentVersionName, category, policyName); - return new IssueCommentRequestModel(issueKey, commentString); - } - public Optional getPropertyValue(JsonObject jsonObject, String propertyKey) { Optional value = Optional.empty(); From 5f65a57e01047d52b426a0eb622836a7c5d4b505 Mon Sep 17 00:00:00 2001 From: Paulo Santos Date: Tue, 2 Sep 2025 17:03:21 -0400 Subject: [PATCH 12/18] IALERT-3873: Update the properties with a new version of the indexer. --- .../alert/api/channel/jira/JiraConstants.java | 33 ++----------------- .../jira/JiraIssueSearchProperties.java | 4 +++ .../delegate/JiraIssueCreator.java | 4 +-- .../search/JiraIssuePropertyKeys.java | 1 + .../distribution/search/JqlStringCreator.java | 31 +---------------- .../search/JqlStringCreatorTest.java | 2 +- .../task/JiraSearchCommentUpdateTask.java | 25 +++++++------- .../task/JiraSearchCommentUpdateTask.java | 25 +++++++------- 8 files changed, 36 insertions(+), 89 deletions(-) diff --git a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/JiraConstants.java b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/JiraConstants.java index 3110a21e16..67dc1e5d79 100644 --- a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/JiraConstants.java +++ b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/JiraConstants.java @@ -21,31 +21,6 @@ public final class JiraConstants { public static final String JIRA_SEARCH_KEY_JIRA_PROJECT = "project"; - // find tickets created by alert first: - // 1. A summary that starts with "Alert - Black Duck" - // 2. A summary that isn't an Alert test message and does not have a comment "=== BEGIN JIRA ISSUE KEYS ===" - // 3. Then check if the new property key exists on that issue or if the old property key is on the issue. - public static final String JQL_QUERY_FOR_ISSUE_SEARCH_COMMENT_MIGRATION = String.format("(summary ~ \"Alert - Black Duck\" OR (summary !~ \"Alert Test Message\" AND NOT comment ~\"%s\")) AND (issue.property[%s].topicName IS NOT EMPTY OR issue.property[%s].topicName IS NOT EMPTY) ORDER BY created DESC", JiraIssuePropertyKeys.JIRA_ISSUE_KEY_START_HEADER, JiraConstants.JIRA_ISSUE_PROPERTY_KEY, JiraConstants.JIRA_ISSUE_PROPERTY_OLD_KEY); - - public static final String JIRA_ISSUE_PROPERTY_SEARCH_COMMENT_MIGRATION_TOKEN = "_alert_9_migrated"; - - // These Strings must always match the Strings found in the atlassian-connect.json file under modules.jiraEntityProperties.keyConfigurations.propertyKey["com-blackduck-integration-alert"].extractions.objectName. - public static final String JIRA_ISSUE_PROPERTY_OBJECT_KEY_PROVIDER = "provider"; - public static final String JIRA_ISSUE_PROPERTY_OBJECT_KEY_PROVIDER_URL = "providerUrl"; - public static final String JIRA_ISSUE_PROPERTY_OBJECT_KEY_TOPIC_NAME = "topicName"; - public static final String JIRA_ISSUE_PROPERTY_OBJECT_KEY_TOPIC_VALUE = "topicValue"; - public static final String JIRA_ISSUE_PROPERTY_OBJECT_KEY_SUB_TOPIC_NAME = "subTopicName"; - public static final String JIRA_ISSUE_PROPERTY_OBJECT_KEY_SUB_TOPIC_VALUE = "subTopicValue"; - public static final String JIRA_ISSUE_PROPERTY_OBJECT_KEY_CATEGORY = "category"; - public static final String JIRA_ISSUE_PROPERTY_OBJECT_KEY_COMPONENT_NAME = "componentName"; - public static final String JIRA_ISSUE_PROPERTY_OBJECT_KEY_COMPONENT_VALUE = "componentValue"; - public static final String JIRA_ISSUE_PROPERTY_OBJECT_KEY_SUB_COMPONENT_NAME = "subComponentName"; - public static final String JIRA_ISSUE_PROPERTY_OBJECT_KEY_SUB_COMPONENT_VALUE = "subComponentValue"; - public static final String JIRA_ISSUE_PROPERTY_OBJECT_KEY_ADDITIONAL_KEY = "additionalKey"; - - public static final String JIRA_ISSUE_VALIDATION_ERROR_MESSAGE = "There are issues with the configuration."; - - public static String createCommentMigrationJQL() { // find tickets created by alert first: // 1. A summary that starts with "Alert - Black Duck" @@ -53,7 +28,6 @@ public static String createCommentMigrationJQL() { // 3. Then check if the new property key exists on that issue // 4. Then check if the new property additionalKey is empty or has the text "_alert_9_migrated". - // TODO we may be able to add a net new field to the properties and that may work better to key off of. return "(summary ~ \"Alert - Black Duck\" OR summary !~ \"Alert Test Message\")" + " AND " + "(issue.property[" @@ -62,12 +36,11 @@ public static String createCommentMigrationJQL() { + "AND " + "(issue.property[" + JiraConstants.JIRA_ISSUE_PROPERTY_KEY - + "].additionalKey IS EMPTY " + + "].alert9Migrated IS EMPTY " + "OR issue.property[" + JiraConstants.JIRA_ISSUE_PROPERTY_KEY - + "].additionalKey !~ '" - + JiraConstants.JIRA_ISSUE_PROPERTY_SEARCH_COMMENT_MIGRATION_TOKEN - + "'))"; + + "].alert9Migrated != 'true'" + + "))"; } private JiraConstants() { diff --git a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/JiraIssueSearchProperties.java b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/JiraIssueSearchProperties.java index e22e9a437f..0fff0828b1 100644 --- a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/JiraIssueSearchProperties.java +++ b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/JiraIssueSearchProperties.java @@ -24,6 +24,7 @@ public class JiraIssueSearchProperties extends Stringable implements Serializabl private String subComponentName; private String subComponentValue; private String additionalKey; + private String alert9Migrated; public JiraIssueSearchProperties() { // For serialization @@ -55,6 +56,7 @@ public JiraIssueSearchProperties( this.subComponentName = subComponentName; this.subComponentValue = subComponentValue; this.additionalKey = additionalKey; + this.alert9Migrated = "true"; } public String getProvider() { @@ -105,4 +107,6 @@ public String getAdditionalKey() { return additionalKey; } + public String getAlert9Migrated() { return alert9Migrated; } + } diff --git a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/delegate/JiraIssueCreator.java b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/delegate/JiraIssueCreator.java index bec0dbb083..77ae800334 100644 --- a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/delegate/JiraIssueCreator.java +++ b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/delegate/JiraIssueCreator.java @@ -205,7 +205,7 @@ private JiraIssueSearchProperties createSearchProperties(ProjectIssueModel alert String componentVersionLabel = bomComponent.getComponentVersion().map(LinkableItem::getLabel).orElse(null); String componentVersionName = bomComponent.getComponentVersion().map(LinkableItem::getValue).orElse(null); - String additionalKey = ""; + String additionalKey = null; ComponentConcernType concernType = ComponentConcernType.VULNERABILITY; Optional optionalPolicyName = alertIssueSource.getPolicyDetails().map(IssuePolicyDetails::getName); @@ -231,7 +231,7 @@ private JiraIssueSearchProperties createSearchProperties(ProjectIssueModel alert component.getValue(), componentVersionLabel, componentVersionName, - additionalKey + JiraConstants.JIRA_ISSUE_PROPERTY_SEARCH_COMMENT_MIGRATION_TOKEN + additionalKey ); } diff --git a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/JiraIssuePropertyKeys.java b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/JiraIssuePropertyKeys.java index e69e947b8f..e3e068e1d6 100644 --- a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/JiraIssuePropertyKeys.java +++ b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/JiraIssuePropertyKeys.java @@ -23,6 +23,7 @@ public final class JiraIssuePropertyKeys { public static final String JIRA_ISSUE_PROPERTY_OBJECT_KEY_SUB_COMPONENT_NAME = "subComponentName"; public static final String JIRA_ISSUE_PROPERTY_OBJECT_KEY_SUB_COMPONENT_VALUE = "subComponentValue"; public static final String JIRA_ISSUE_PROPERTY_OBJECT_KEY_ADDITIONAL_KEY = "additionalKey"; + public static final String JIRA_ISSUE_PROPERTY_OBJECT_KEY_ALERT_9_MIGRATED = "alert9Migrated"; public static final String JIRA_ISSUE_KEY_SEPARATOR = ": "; public static final String JIRA_ISSUE_KEY_START_HEADER = "=== BEGIN JIRA ISSUE KEYS ==="; diff --git a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/JqlStringCreator.java b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/JqlStringCreator.java index 7804d5894d..664322aae8 100644 --- a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/JqlStringCreator.java +++ b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/JqlStringCreator.java @@ -91,36 +91,7 @@ public static String createBlackDuckComponentConcernIssuesSearchString( if (ComponentConcernType.POLICY.equals(concernType) && null != policyName) { String additionalKey = JiraIssueSearchPropertyStringCompatibilityUtils.createPolicyAdditionalKey(policyName); - String escapedValue = escapeSearchString(additionalKey); - - jqlBuilder.append(SEARCH_CONJUNCTION); - jqlBuilder.append(StringUtils.SPACE); - jqlBuilder.append("(issue.property[") - .append(JiraConstants.JIRA_ISSUE_PROPERTY_KEY) - .append("].") - .append(JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_ADDITIONAL_KEY) - .append(" = '") - .append(escapedValue) - .append("'"); - jqlBuilder.append(" OR "); - jqlBuilder.append("issue.property[") - .append(JiraConstants.JIRA_ISSUE_PROPERTY_OLD_KEY) - .append("].") - .append(JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_ADDITIONAL_KEY) - .append(" = '") - .append(escapedValue) - .append("'"); - jqlBuilder.append(" OR "); - jqlBuilder.append("issue.property[") - .append(JiraConstants.JIRA_ISSUE_PROPERTY_KEY) - .append("].") - .append(JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_ADDITIONAL_KEY) - .append(" = '") - .append(escapedValue) - .append(JiraConstants.JIRA_ISSUE_PROPERTY_SEARCH_COMMENT_MIGRATION_TOKEN) - .append("'"); - jqlBuilder.append(")"); - jqlBuilder.append(StringUtils.SPACE); + appendPropertySearchString(jqlBuilder, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_ADDITIONAL_KEY, additionalKey); } jqlBuilder.append(")"); diff --git a/api-channel-jira/src/test/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/JqlStringCreatorTest.java b/api-channel-jira/src/test/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/JqlStringCreatorTest.java index 23e367a734..50f362e61f 100644 --- a/api-channel-jira/src/test/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/JqlStringCreatorTest.java +++ b/api-channel-jira/src/test/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/JqlStringCreatorTest.java @@ -74,7 +74,7 @@ void policySearchStringTest() { + "AND (issue.property[com-blackduck-integration-alert].subComponentName = 'Component Version' OR issue.property[com-synopsys-integration-alert].subComponentName = 'Component Version') " + "AND (issue.property[com-blackduck-integration-alert].subComponentValue = '1.1.2' OR issue.property[com-synopsys-integration-alert].subComponentValue = '1.1.2') " + "AND (issue.property[com-blackduck-integration-alert].category = 'Policy' OR issue.property[com-synopsys-integration-alert].category = 'Policy') " - + "AND (issue.property[com-blackduck-integration-alert].additionalKey = 'Policy ViolatedMyPolicy' OR issue.property[com-synopsys-integration-alert].additionalKey = 'Policy ViolatedMyPolicy' OR issue.property[com-blackduck-integration-alert].additionalKey = 'Policy ViolatedMyPolicy_alert_9_migrated') " + + "AND (issue.property[com-blackduck-integration-alert].additionalKey = 'Policy ViolatedMyPolicy' OR issue.property[com-synopsys-integration-alert].additionalKey = 'Policy ViolatedMyPolicy') " + ")"; assertEquals(expectedSearchString, jqlString); diff --git a/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraSearchCommentUpdateTask.java b/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraSearchCommentUpdateTask.java index 1fc1a8baef..f8149d4f19 100644 --- a/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraSearchCommentUpdateTask.java +++ b/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraSearchCommentUpdateTask.java @@ -99,22 +99,21 @@ private Runnable createUpdateRunnable(String issueKey, IssuePropertyService issu String category = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_CATEGORY).orElse(null); String policyName = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_ADDITIONAL_KEY).orElse(null); - String migratedAdditionalKeyValue; - if(StringUtils.isNotBlank(policyName)) { - // append jira 9 migration property - migratedAdditionalKeyValue = policyName + JiraConstants.JIRA_ISSUE_PROPERTY_SEARCH_COMMENT_MIGRATION_TOKEN; - } else { - // add jira 9 migration property - migratedAdditionalKeyValue = JiraConstants.JIRA_ISSUE_PROPERTY_SEARCH_COMMENT_MIGRATION_TOKEN; - } - - jsonObject.addProperty(JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_ADDITIONAL_KEY, migratedAdditionalKeyValue); - String migratedPropertyValue = getGson().toJson(jsonObject); - issuePropertyService.setProperty(issueKey, JiraConstants.JIRA_ISSUE_PROPERTY_KEY, migratedPropertyValue); - String commentString = SearchCommentCreator.createSearchComment(projectName, projectVersionName, componentName, componentVersionName, category, policyName); IssueCommentRequestModel comment = new IssueCommentRequestModel(issueKey, commentString); issueService.addComment(comment); + + // mark the issue as migrated + JsonObject migratedProperty = new JsonObject(); + migratedProperty.addProperty(JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_PROJECT_NAME, projectName); + migratedProperty.addProperty(JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_PROJECT_VERSION_NAME, projectVersionName); + migratedProperty.addProperty(JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_COMPONENT_VALUE, componentName); + migratedProperty.addProperty(JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_SUB_COMPONENT_VALUE, componentVersionName); + migratedProperty.addProperty(JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_CATEGORY, category); + migratedProperty.addProperty(JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_ADDITIONAL_KEY, policyName); + migratedProperty.addProperty(JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_ALERT_9_MIGRATED, "true"); + String migratedPropertyValue = getGson().toJson(migratedProperty); + issuePropertyService.setProperty(issueKey, JiraConstants.JIRA_ISSUE_PROPERTY_KEY, migratedPropertyValue); } catch (IntegrationException ex) { logger.debug("Error updating issue {} with search key comment.", issueKey); logger.debug("Caused by: ", ex); diff --git a/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraSearchCommentUpdateTask.java b/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraSearchCommentUpdateTask.java index 43d150ba72..2cf4f2631b 100644 --- a/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraSearchCommentUpdateTask.java +++ b/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraSearchCommentUpdateTask.java @@ -102,22 +102,21 @@ private Runnable createUpdateRunnable(String issueKey, IssuePropertyService issu String category = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_CATEGORY).orElse(null); String policyName = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_ADDITIONAL_KEY).orElse(null); - String migratedAdditionalKeyValue; - if(StringUtils.isNotBlank(policyName)) { - // append jira 9 migration property - migratedAdditionalKeyValue = policyName + JiraConstants.JIRA_ISSUE_PROPERTY_SEARCH_COMMENT_MIGRATION_TOKEN; - } else { - // add jira 9 migration property - migratedAdditionalKeyValue = JiraConstants.JIRA_ISSUE_PROPERTY_SEARCH_COMMENT_MIGRATION_TOKEN; - } - - jsonObject.addProperty(JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_ADDITIONAL_KEY, migratedAdditionalKeyValue); - String migratedPropertyValue = getGson().toJson(jsonObject); - issuePropertyService.setProperty(issueKey, JiraConstants.JIRA_ISSUE_PROPERTY_KEY, migratedPropertyValue); - String commentString = SearchCommentCreator.createSearchComment(projectName, projectVersionName, componentName, componentVersionName, category, policyName); IssueCommentRequestModel comment = new IssueCommentRequestModel(issueKey, commentString); issueService.addComment(comment); + + // mark the issue as migrated + JsonObject migratedProperty = new JsonObject(); + migratedProperty.addProperty(JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_PROJECT_NAME, projectName); + migratedProperty.addProperty(JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_PROJECT_VERSION_NAME, projectVersionName); + migratedProperty.addProperty(JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_COMPONENT_VALUE, componentName); + migratedProperty.addProperty(JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_SUB_COMPONENT_VALUE, componentVersionName); + migratedProperty.addProperty(JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_CATEGORY, category); + migratedProperty.addProperty(JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_ADDITIONAL_KEY, policyName); + migratedProperty.addProperty(JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_ALERT_9_MIGRATED, "true"); + String migratedPropertyValue = getGson().toJson(migratedProperty); + issuePropertyService.setProperty(issueKey, JiraConstants.JIRA_ISSUE_PROPERTY_KEY, migratedPropertyValue); } catch (IntegrationException ex) { logger.debug("Error updating issue {} with search key comment.", issueKey); logger.debug("Caused by: ", ex); From a6895815ddf3a14f1a8cd5ec06c9929d836ac24a Mon Sep 17 00:00:00 2001 From: Paulo Santos Date: Wed, 3 Sep 2025 15:57:34 -0400 Subject: [PATCH 13/18] IALERT-3873: Change the comment to have the same values as the property. --- .../delegate/JiraIssueCreator.java | 4 +- .../search/JiraIssuePropertyKeys.java | 1 + .../distribution/search/JqlStringCreator.java | 42 ++++++------------- .../search/SearchCommentCreator.java | 17 ++++---- .../search/JqlStringCreatorTest.java | 15 ++++--- .../task/JiraSearchCommentUpdateTask.java | 15 ++++++- .../task/JiraSearchCommentUpdateTask.java | 14 ++++++- 7 files changed, 61 insertions(+), 47 deletions(-) diff --git a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/delegate/JiraIssueCreator.java b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/delegate/JiraIssueCreator.java index 77ae800334..046af4a07f 100644 --- a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/delegate/JiraIssueCreator.java +++ b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/delegate/JiraIssueCreator.java @@ -241,10 +241,10 @@ protected Optional getAlertSearchKeys(ExistingIssueDetails exist if(alertIssueSource == null) { return Optional.empty(); } + LinkableItem provider = alertIssueSource.getProvider(); // the uuid for project and project version is the last uuid // use the component and version name // category and if policy include the policy name - LinkableItem project = alertIssueSource.getProject(); LinkableItem projectVersion = alertIssueSource.getProjectVersion() @@ -263,6 +263,6 @@ protected Optional getAlertSearchKeys(ExistingIssueDetails exist } else if(alertIssueSource.getComponentUnknownVersionDetails().isPresent()) { category = ComponentConcernType.UNKNOWN_VERSION; } - return Optional.of(SearchCommentCreator.createSearchComment(project, projectVersion, bomComponent.getComponent(), componentVersion.orElse(null),category, policyName)); + return Optional.of(SearchCommentCreator.createSearchComment(provider, project, projectVersion, bomComponent.getComponent(), componentVersion.orElse(null),category, policyName)); } } diff --git a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/JiraIssuePropertyKeys.java b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/JiraIssuePropertyKeys.java index e3e068e1d6..78eb3f3f55 100644 --- a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/JiraIssuePropertyKeys.java +++ b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/JiraIssuePropertyKeys.java @@ -28,6 +28,7 @@ public final class JiraIssuePropertyKeys { public static final String JIRA_ISSUE_KEY_SEPARATOR = ": "; public static final String JIRA_ISSUE_KEY_START_HEADER = "=== BEGIN JIRA ISSUE KEYS ==="; public static final String JIRA_ISSUE_KEY_END_HEADER = "=== END JIRA ISSUE KEYS ==="; + public static final String JIRA_ISSUE_KEY_PROVIDER = "provider"; public static final String JIRA_ISSUE_KEY_PROJECT_ID = "projectId"; public static final String JIRA_ISSUE_KEY_PROJECT_VERSION_ID = "projectVersionId"; public static final String JIRA_ISSUE_KEY_COMPONENT_NAME = "componentName"; diff --git a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/JqlStringCreator.java b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/JqlStringCreator.java index 664322aae8..1d1d41bbbd 100644 --- a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/JqlStringCreator.java +++ b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/JqlStringCreator.java @@ -27,7 +27,7 @@ public static String createBlackDuckProjectIssuesSearchString( LinkableItem project ) { StringBuilder jqlBuilder = new StringBuilder(); - appendBlackDuckCommentSearchStrings(jqlBuilder, jiraProjectKey, project, null, null, null, null, null); + appendBlackDuckCommentSearchStrings(jqlBuilder, jiraProjectKey, provider, project, null, null, null, null, null); jqlBuilder.append(" OR "); jqlBuilder.append("("); appendBlackDuckProjectSearchStrings(jqlBuilder, jiraProjectKey, provider, project); @@ -43,7 +43,7 @@ public static String createBlackDuckProjectVersionIssuesSearchString( LinkableItem projectVersion ) { StringBuilder jqlBuilder = new StringBuilder(); - appendBlackDuckCommentSearchStrings(jqlBuilder, jiraProjectKey, project, projectVersion, null, null, null, null); + appendBlackDuckCommentSearchStrings(jqlBuilder, jiraProjectKey, provider, project, projectVersion, null, null, null, null); jqlBuilder.append(" OR "); jqlBuilder.append("("); appendBlackDuckProjectVersionSearchStrings(jqlBuilder, jiraProjectKey, provider, project, projectVersion); @@ -61,7 +61,7 @@ public static String createBlackDuckComponentIssuesSearchString( @Nullable LinkableItem componentVersion ) { StringBuilder jqlBuilder = new StringBuilder(); - appendBlackDuckCommentSearchStrings(jqlBuilder, jiraProjectKey, project, projectVersion, component, componentVersion, null, null); + appendBlackDuckCommentSearchStrings(jqlBuilder, jiraProjectKey, provider, project, projectVersion, component, componentVersion, null, null); jqlBuilder.append(" OR "); jqlBuilder.append("("); appendBlackDuckComponentSearchStrings(jqlBuilder, jiraProjectKey, provider, project, projectVersion, component, componentVersion); @@ -81,7 +81,7 @@ public static String createBlackDuckComponentConcernIssuesSearchString( @Nullable String policyName ) { StringBuilder jqlBuilder = new StringBuilder(); - appendBlackDuckCommentSearchStrings(jqlBuilder, jiraProjectKey, project, projectVersion, component, componentVersion, concernType, policyName); + appendBlackDuckCommentSearchStrings(jqlBuilder, jiraProjectKey,provider, project, projectVersion, component, componentVersion, concernType, policyName); jqlBuilder.append(" OR "); jqlBuilder.append("("); appendBlackDuckComponentSearchStrings(jqlBuilder, jiraProjectKey, provider, project, projectVersion, component, componentVersion); @@ -103,6 +103,7 @@ public static String createBlackDuckComponentConcernIssuesSearchString( private static void appendBlackDuckCommentSearchStrings( StringBuilder jqlBuilder, String jiraProjectKey, + LinkableItem provider, LinkableItem project, @Nullable LinkableItem projectVersion, @Nullable LinkableItem component, @@ -117,24 +118,22 @@ private static void appendBlackDuckCommentSearchStrings( jqlBuilder.append(String.format("comment ~\"%s\"", JiraIssuePropertyKeys.JIRA_ISSUE_KEY_START_HEADER)); jqlBuilder.append(StringUtils.SPACE); + if(provider != null && provider.getUrl().isPresent()) { + jqlBuilder.append(SEARCH_CONJUNCTION); + jqlBuilder.append(StringUtils.SPACE); + appendCommentSearchString(jqlBuilder, JiraIssuePropertyKeys.JIRA_ISSUE_KEY_PROVIDER, provider.getUrl().get()); + } + if(project != null && project.getUrl().isPresent()) { - String projectId = extractUuid(project.getUrl().get(), "/api/projects/"); jqlBuilder.append(SEARCH_CONJUNCTION); - jqlBuilder.append(" ("); - appendCommentSearchString(jqlBuilder, JiraIssuePropertyKeys.JIRA_ISSUE_KEY_PROJECT_ID, projectId); - jqlBuilder.append("OR "); + jqlBuilder.append(StringUtils.SPACE); appendCommentSearchString(jqlBuilder, JiraIssuePropertyKeys.JIRA_ISSUE_KEY_PROJECT_ID, project.getValue()); - jqlBuilder.append(") "); } if(projectVersion != null && projectVersion.getUrl().isPresent()) { - String projectVersionId = extractUuid(projectVersion.getUrl().get(), "/versions/"); jqlBuilder.append(SEARCH_CONJUNCTION); - jqlBuilder.append(" ("); - appendCommentSearchString(jqlBuilder, JiraIssuePropertyKeys.JIRA_ISSUE_KEY_PROJECT_VERSION_ID, projectVersionId); - jqlBuilder.append("OR "); + jqlBuilder.append(StringUtils.SPACE); appendCommentSearchString(jqlBuilder, JiraIssuePropertyKeys.JIRA_ISSUE_KEY_PROJECT_VERSION_ID, projectVersion.getValue()); - jqlBuilder.append(") "); } if(component != null) { @@ -164,21 +163,6 @@ private static void appendBlackDuckCommentSearchStrings( jqlBuilder.append(")"); } - private static @NotNull String extractUuid(String url, String pathSearchToken) { - int searchTokenStart = StringUtils.indexOf(url, pathSearchToken); - int startIndex = searchTokenStart + pathSearchToken.length(); - int endSlashIndex = StringUtils.indexOf(url, '/', startIndex); - String uuid; - if(endSlashIndex > startIndex) { - uuid = StringUtils.substring(url, startIndex, endSlashIndex); - } else { - uuid = StringUtils.substring(url, startIndex); - } - - return uuid; - } - - private static void appendBlackDuckComponentSearchStrings( StringBuilder jqlBuilder, String jiraProjectKey, diff --git a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/SearchCommentCreator.java b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/SearchCommentCreator.java index efbce1bbfe..b373e8f8bf 100644 --- a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/SearchCommentCreator.java +++ b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/SearchCommentCreator.java @@ -9,26 +9,29 @@ public final class SearchCommentCreator { - public static String createSearchComment(LinkableItem project, LinkableItem projectVersion, LinkableItem component, @Nullable LinkableItem componentVersion, @Nullable ComponentConcernType componentConcernType, @Nullable String policyName) { - String projectId = StringUtils.substringAfterLast(project.getUrl().orElse(""), "/"); - int versionUUIDStart = StringUtils.lastIndexOf(projectVersion.getUrl().orElse(""), "versions/") + "versions/".length(); - int versionUUIDEnd = StringUtils.indexOf(projectVersion.getUrl().orElse(""), "/", versionUUIDStart); - String projectVersionId = StringUtils.substring(projectVersion.getUrl().orElse(""), versionUUIDStart, versionUUIDEnd); + public static String createSearchComment(LinkableItem provider, LinkableItem project, LinkableItem projectVersion, LinkableItem component, @Nullable LinkableItem componentVersion, @Nullable ComponentConcernType componentConcernType, @Nullable String policyName) { + String providerUrl = provider.getUrl().orElse(""); + String projectId = project.getValue(); + String projectVersionId = projectVersion.getValue(); String componentName = component.getValue(); String componentVersionName = null; String category = Optional.ofNullable(componentConcernType).map(ComponentConcernType::name).orElse(null); if(null != componentVersion) { componentVersionName = componentVersion.getValue(); } - return createSearchComment(projectId, projectVersionId, componentName, componentVersionName, category, policyName); + return createSearchComment(providerUrl, projectId, projectVersionId, componentName, componentVersionName, category, policyName); } - public static String createSearchComment(String projectId, String projectVersionId, String componentName, @Nullable String componentVersion, @Nullable String category, @Nullable String policyName) { + public static String createSearchComment(String providerId, String projectId, String projectVersionId, String componentName, @Nullable String componentVersion, @Nullable String category, @Nullable String policyName) { StringBuilder keyBuilder = new StringBuilder(); keyBuilder.append("This comment was automatically created by Alert. DO NOT REMOVE."); keyBuilder.append(JiraIssuePropertyKeys.JIRA_ISSUE_KEY_START_HEADER); keyBuilder.append(StringUtils.SPACE); + keyBuilder.append(JiraIssuePropertyKeys.JIRA_ISSUE_KEY_PROVIDER); + keyBuilder.append(JiraIssuePropertyKeys.JIRA_ISSUE_KEY_SEPARATOR); + keyBuilder.append(providerId); + keyBuilder.append(StringUtils.SPACE); keyBuilder.append(JiraIssuePropertyKeys.JIRA_ISSUE_KEY_PROJECT_ID); keyBuilder.append(JiraIssuePropertyKeys.JIRA_ISSUE_KEY_SEPARATOR); keyBuilder.append(projectId); diff --git a/api-channel-jira/src/test/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/JqlStringCreatorTest.java b/api-channel-jira/src/test/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/JqlStringCreatorTest.java index 50f362e61f..1bb5d522b0 100644 --- a/api-channel-jira/src/test/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/JqlStringCreatorTest.java +++ b/api-channel-jira/src/test/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/JqlStringCreatorTest.java @@ -55,8 +55,9 @@ void policySearchStringTest() { "(" + "project = 'TEST'" + " AND comment ~\"=== BEGIN JIRA ISSUE KEYS ===\"" - + " AND (comment ~ \"projectId: project-uuid\" OR comment ~ \"projectId: project_with_single_quote\\'\" )" - + " AND (comment ~ \"projectVersionId: project-version-uuid\" OR comment ~ \"projectVersionId: v1.0 \\\\& v2.0\" )" + + " AND comment ~ \"provider: http://providerUrl\"" + + " AND comment ~ \"projectId: project_with_single_quote\\'\"" + + " AND comment ~ \"projectVersionId: v1.0 \\\\& v2.0\"" + " AND comment ~ \"componentName: myVulnerableComponent\"" + " AND comment ~ \"componentVersionName: 1.1.2\"" + " AND comment ~ \"category: POLICY\"" @@ -96,8 +97,9 @@ void vulnerabilitySearchStringTest() { "(" + "project = 'TEST'" + " AND comment ~\"=== BEGIN JIRA ISSUE KEYS ===\"" - + " AND (comment ~ \"projectId: project-uuid\" OR comment ~ \"projectId: project_with_single_quote\\'\" )" - + " AND (comment ~ \"projectVersionId: project-version-uuid\" OR comment ~ \"projectVersionId: v1.0 \\\\& v2.0\" )" + + " AND comment ~ \"provider: http://providerUrl\"" + + " AND comment ~ \"projectId: project_with_single_quote\\'\"" + + " AND comment ~ \"projectVersionId: v1.0 \\\\& v2.0\"" + " AND comment ~ \"componentName: myVulnerableComponent\"" + " AND comment ~ \"componentVersionName: 1.1.2\"" + " AND comment ~ \"category: VULNERABILITY\"" @@ -141,8 +143,9 @@ void injectionTest() { "(" + "project = 'TEST'" + " AND comment ~\"=== BEGIN JIRA ISSUE KEYS ===\"" - + " AND (comment ~ \"projectId: project-uuid\" OR comment ~ \"projectId: project_with_single_quote\\'\" )" - + " AND (comment ~ \"projectVersionId: projectVersionUrl\" OR comment ~ \"projectVersionId: INJECTED\\\\\\' OR project = \"SomeOtherProject\" OR summary ~ 2021-01-01\\\\\\\\\\\\\" )" + + " AND comment ~ \"provider: http://providerUrl\"" + + " AND comment ~ \"projectId: project_with_single_quote\\'\"" + + " AND comment ~ \"projectVersionId: INJECTED\\\\\\' OR project = \"SomeOtherProject\" OR summary ~ 2021-01-01\\\\\\\\\\\\\"" + " AND comment ~ \"componentName: myVulnerableComponent\"" + " AND comment ~ \"componentVersionName: 1.1.2\"" + " AND comment ~ \"category: VULNERABILITY\"" diff --git a/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraSearchCommentUpdateTask.java b/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraSearchCommentUpdateTask.java index f8149d4f19..88dfabb693 100644 --- a/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraSearchCommentUpdateTask.java +++ b/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraSearchCommentUpdateTask.java @@ -92,22 +92,33 @@ private Runnable createUpdateRunnable(String issueKey, IssuePropertyService issu try { JsonObject jsonObject = propertyValue.get().getValue(); // projectName, projectVersionName, and componentName should all be populated but since an optional is returned use orElse(null) + String provider = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_PROVIDER).orElse(null); + String providerUrl = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_PROVIDER_URL).orElse(null); + String projectLabel = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_PROJECT_LABEL).orElse(null); String projectName = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_PROJECT_NAME).orElse(null); + String projectVersionLabel = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_PROJECT_VERSION_LABEL).orElse(null); String projectVersionName = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_PROJECT_VERSION_NAME).orElse(null); + String componentLabel = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_COMPONENT_LABEL).orElse(null); String componentName = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_COMPONENT_VALUE).orElse(null); + String componentVersionLabel = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_SUB_COMPONENT_NAME).orElse(null); String componentVersionName = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_SUB_COMPONENT_VALUE).orElse(null); String category = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_CATEGORY).orElse(null); String policyName = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_ADDITIONAL_KEY).orElse(null); - - String commentString = SearchCommentCreator.createSearchComment(projectName, projectVersionName, componentName, componentVersionName, category, policyName); + String commentString = SearchCommentCreator.createSearchComment(provider, projectName, projectVersionName, componentName, componentVersionName, category, policyName); IssueCommentRequestModel comment = new IssueCommentRequestModel(issueKey, commentString); issueService.addComment(comment); // mark the issue as migrated JsonObject migratedProperty = new JsonObject(); + migratedProperty.addProperty(JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_PROVIDER, provider); + migratedProperty.addProperty(JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_PROVIDER_URL, providerUrl); + migratedProperty.addProperty(JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_PROJECT_LABEL, projectLabel); migratedProperty.addProperty(JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_PROJECT_NAME, projectName); + migratedProperty.addProperty(JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_PROJECT_VERSION_LABEL, projectVersionLabel); migratedProperty.addProperty(JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_PROJECT_VERSION_NAME, projectVersionName); + migratedProperty.addProperty(JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_COMPONENT_LABEL, componentLabel); migratedProperty.addProperty(JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_COMPONENT_VALUE, componentName); + migratedProperty.addProperty(JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_SUB_COMPONENT_NAME, componentVersionLabel); migratedProperty.addProperty(JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_SUB_COMPONENT_VALUE, componentVersionName); migratedProperty.addProperty(JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_CATEGORY, category); migratedProperty.addProperty(JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_ADDITIONAL_KEY, policyName); diff --git a/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraSearchCommentUpdateTask.java b/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraSearchCommentUpdateTask.java index 2cf4f2631b..3fbb10e9fe 100644 --- a/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraSearchCommentUpdateTask.java +++ b/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraSearchCommentUpdateTask.java @@ -95,22 +95,34 @@ private Runnable createUpdateRunnable(String issueKey, IssuePropertyService issu try { JsonObject jsonObject = propertyValue.get().getValue(); // projectName, projectVersionName, and componentName should all be populated but since an optional is returned use orElse(null) + String provider = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_PROVIDER).orElse(null); + String providerUrl = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_PROVIDER_URL).orElse(null); + String projectLabel = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_PROJECT_LABEL).orElse(null); String projectName = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_PROJECT_NAME).orElse(null); + String projectVersionLabel = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_PROJECT_VERSION_LABEL).orElse(null); String projectVersionName = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_PROJECT_VERSION_NAME).orElse(null); + String componentLabel = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_COMPONENT_LABEL).orElse(null); String componentName = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_COMPONENT_VALUE).orElse(null); + String componentVersionLabel = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_SUB_COMPONENT_NAME).orElse(null); String componentVersionName = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_SUB_COMPONENT_VALUE).orElse(null); String category = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_CATEGORY).orElse(null); String policyName = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_ADDITIONAL_KEY).orElse(null); - String commentString = SearchCommentCreator.createSearchComment(projectName, projectVersionName, componentName, componentVersionName, category, policyName); + String commentString = SearchCommentCreator.createSearchComment(provider, projectName, projectVersionName, componentName, componentVersionName, category, policyName); IssueCommentRequestModel comment = new IssueCommentRequestModel(issueKey, commentString); issueService.addComment(comment); // mark the issue as migrated JsonObject migratedProperty = new JsonObject(); + migratedProperty.addProperty(JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_PROVIDER, provider); + migratedProperty.addProperty(JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_PROVIDER_URL, providerUrl); + migratedProperty.addProperty(JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_PROJECT_LABEL, projectLabel); migratedProperty.addProperty(JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_PROJECT_NAME, projectName); + migratedProperty.addProperty(JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_PROJECT_VERSION_LABEL, projectVersionLabel); migratedProperty.addProperty(JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_PROJECT_VERSION_NAME, projectVersionName); + migratedProperty.addProperty(JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_COMPONENT_LABEL, componentLabel); migratedProperty.addProperty(JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_COMPONENT_VALUE, componentName); + migratedProperty.addProperty(JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_SUB_COMPONENT_NAME, componentVersionLabel); migratedProperty.addProperty(JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_SUB_COMPONENT_VALUE, componentVersionName); migratedProperty.addProperty(JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_CATEGORY, category); migratedProperty.addProperty(JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_ADDITIONAL_KEY, policyName); From e2362015959eeaedb44023c4b65964a77f5f2b5a Mon Sep 17 00:00:00 2001 From: Paulo Santos Date: Thu, 4 Sep 2025 13:52:32 -0400 Subject: [PATCH 14/18] IALERT-3873: Change the constructor visibility. --- .../integration/alert/api/channel/jira/lifecycle/JiraTask.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/lifecycle/JiraTask.java b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/lifecycle/JiraTask.java index 9083a87f4d..872621bb3b 100644 --- a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/lifecycle/JiraTask.java +++ b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/lifecycle/JiraTask.java @@ -24,7 +24,7 @@ public abstract class JiraTask extends ScheduledTask { private final String configName; private final Gson gson; - public JiraTask(TaskScheduler taskScheduler, TaskManager taskManager, String configId, String configName, String taskNameSuffix, Gson gson) { + protected JiraTask(TaskScheduler taskScheduler, TaskManager taskManager, String configId, String configName, String taskNameSuffix, Gson gson) { super(taskScheduler); this.taskManager = taskManager; this.configId = configId; From 1e401e86bcd4d0db580d36622d30cfec7202a456 Mon Sep 17 00:00:00 2001 From: Paulo Santos Date: Thu, 11 Sep 2025 07:09:55 -0400 Subject: [PATCH 15/18] IALERT-3873: Fix a comment and add whitespace. --- .../integration/alert/api/channel/jira/JiraConstants.java | 2 +- .../api/channel/jira/distribution/search/JqlStringCreator.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/JiraConstants.java b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/JiraConstants.java index 67dc1e5d79..798e39ec90 100644 --- a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/JiraConstants.java +++ b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/JiraConstants.java @@ -26,7 +26,7 @@ public static String createCommentMigrationJQL() { // 1. A summary that starts with "Alert - Black Duck" // 2. A summary that isn't an Alert test message // 3. Then check if the new property key exists on that issue - // 4. Then check if the new property additionalKey is empty or has the text "_alert_9_migrated". + // 4. Then check if the new property alert9Migrated is empty or has the text "true". return "(summary ~ \"Alert - Black Duck\" OR summary !~ \"Alert Test Message\")" + " AND " diff --git a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/JqlStringCreator.java b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/JqlStringCreator.java index 1d1d41bbbd..8c2b4d8933 100644 --- a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/JqlStringCreator.java +++ b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/JqlStringCreator.java @@ -81,7 +81,7 @@ public static String createBlackDuckComponentConcernIssuesSearchString( @Nullable String policyName ) { StringBuilder jqlBuilder = new StringBuilder(); - appendBlackDuckCommentSearchStrings(jqlBuilder, jiraProjectKey,provider, project, projectVersion, component, componentVersion, concernType, policyName); + appendBlackDuckCommentSearchStrings(jqlBuilder, jiraProjectKey, provider, project, projectVersion, component, componentVersion, concernType, policyName); jqlBuilder.append(" OR "); jqlBuilder.append("("); appendBlackDuckComponentSearchStrings(jqlBuilder, jiraProjectKey, provider, project, projectVersion, component, componentVersion); From ca10858dab2e66af78dd9be632a3b11c437dbde6 Mon Sep 17 00:00:00 2001 From: Paulo Santos Date: Thu, 11 Sep 2025 14:52:02 -0400 Subject: [PATCH 16/18] IALERT-3873: Fix a discrepancy when adding the comment to jira with the property update task. --- .../jira/distribution/search/SearchCommentCreator.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/SearchCommentCreator.java b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/SearchCommentCreator.java index b373e8f8bf..2fe4642789 100644 --- a/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/SearchCommentCreator.java +++ b/api-channel-jira/src/main/java/com/blackduck/integration/alert/api/channel/jira/distribution/search/SearchCommentCreator.java @@ -10,7 +10,7 @@ public final class SearchCommentCreator { public static String createSearchComment(LinkableItem provider, LinkableItem project, LinkableItem projectVersion, LinkableItem component, @Nullable LinkableItem componentVersion, @Nullable ComponentConcernType componentConcernType, @Nullable String policyName) { - String providerUrl = provider.getUrl().orElse(""); + String providerName = provider.getLabel(); String projectId = project.getValue(); String projectVersionId = projectVersion.getValue(); String componentName = component.getValue(); @@ -19,7 +19,7 @@ public static String createSearchComment(LinkableItem provider, LinkableItem pro if(null != componentVersion) { componentVersionName = componentVersion.getValue(); } - return createSearchComment(providerUrl, projectId, projectVersionId, componentName, componentVersionName, category, policyName); + return createSearchComment(providerName, projectId, projectVersionId, componentName, componentVersionName, category, policyName); } public static String createSearchComment(String providerId, String projectId, String projectVersionId, String componentName, @Nullable String componentVersion, @Nullable String category, @Nullable String policyName) { From 9595e594e26f446aeffb003db4524cfb855a9161 Mon Sep 17 00:00:00 2001 From: Paulo Santos Date: Thu, 30 Oct 2025 15:18:21 -0400 Subject: [PATCH 17/18] Fix: Update to use the new classes from int-jira-common. --- .../jira/cloud/task/JiraSearchCommentUpdateTask.java | 7 +++---- .../jira/server/task/JiraSearchCommentUpdateTask.java | 3 +-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraSearchCommentUpdateTask.java b/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraSearchCommentUpdateTask.java index 88dfabb693..4b44a5efee 100644 --- a/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraSearchCommentUpdateTask.java +++ b/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraSearchCommentUpdateTask.java @@ -9,17 +9,16 @@ import com.blackduck.integration.alert.channel.jira.cloud.JiraCloudProperties; import com.blackduck.integration.alert.channel.jira.cloud.JiraCloudPropertiesFactory; import com.blackduck.integration.exception.IntegrationException; +import com.blackduck.integration.jira.common.cloud.model.IssueCommentRequestModel; import com.blackduck.integration.jira.common.cloud.model.IssueSearchResponseModel; import com.blackduck.integration.jira.common.cloud.service.IssueSearchService; import com.blackduck.integration.jira.common.cloud.service.IssueService; import com.blackduck.integration.jira.common.cloud.service.JiraCloudServiceFactory; -import com.blackduck.integration.jira.common.model.request.IssueCommentRequestModel; import com.blackduck.integration.jira.common.model.response.IssuePropertyResponseModel; import com.blackduck.integration.jira.common.model.response.IssueResponseModel; import com.blackduck.integration.jira.common.rest.service.IssuePropertyService; import com.google.gson.Gson; import com.google.gson.JsonObject; -import io.micrometer.common.util.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.scheduling.TaskScheduler; @@ -48,7 +47,7 @@ public void runTask() { IssuePropertyService issuePropertyService = serviceFactory.createIssuePropertyService(); IssueService issueService = serviceFactory.createIssueService(); - IssueSearchResponseModel responseModel = issueSearchService.queryForIssuePage(JiraConstants.createCommentMigrationJQL(), 0, JQL_QUERY_MAX_RESULTS); + IssueSearchResponseModel responseModel = issueSearchService.queryForIssuePage(JiraConstants.createCommentMigrationJQL(), null, JQL_QUERY_MAX_RESULTS); int totalIssues = responseModel.getTotal(); boolean foundIssues = totalIssues > 0; @@ -105,7 +104,7 @@ private Runnable createUpdateRunnable(String issueKey, IssuePropertyService issu String category = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_CATEGORY).orElse(null); String policyName = getPropertyValue(jsonObject, JiraIssuePropertyKeys.JIRA_ISSUE_PROPERTY_OBJECT_KEY_ADDITIONAL_KEY).orElse(null); String commentString = SearchCommentCreator.createSearchComment(provider, projectName, projectVersionName, componentName, componentVersionName, category, policyName); - IssueCommentRequestModel comment = new IssueCommentRequestModel(issueKey, commentString); + IssueCommentRequestModel comment = IssueCommentRequestModel.commentForIssue(issueKey, commentString); issueService.addComment(comment); // mark the issue as migrated diff --git a/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraSearchCommentUpdateTask.java b/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraSearchCommentUpdateTask.java index 3fbb10e9fe..25a47fd962 100644 --- a/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraSearchCommentUpdateTask.java +++ b/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraSearchCommentUpdateTask.java @@ -9,9 +9,9 @@ import com.blackduck.integration.alert.channel.jira.server.JiraServerProperties; import com.blackduck.integration.alert.channel.jira.server.JiraServerPropertiesFactory; import com.blackduck.integration.exception.IntegrationException; -import com.blackduck.integration.jira.common.model.request.IssueCommentRequestModel; import com.blackduck.integration.jira.common.model.response.IssuePropertyResponseModel; import com.blackduck.integration.jira.common.rest.service.IssuePropertyService; +import com.blackduck.integration.jira.common.server.model.IssueCommentRequestModel; import com.blackduck.integration.jira.common.server.model.IssueSearchIssueComponent; import com.blackduck.integration.jira.common.server.model.IssueSearchResponseModel; import com.blackduck.integration.jira.common.server.service.IssueSearchService; @@ -19,7 +19,6 @@ import com.blackduck.integration.jira.common.server.service.JiraServerServiceFactory; import com.google.gson.Gson; import com.google.gson.JsonObject; -import io.micrometer.common.util.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.scheduling.TaskScheduler; From 6688337a3334a15193f0f67ffc6dc285be0d0b07 Mon Sep 17 00:00:00 2001 From: Paulo Santos Date: Tue, 4 Nov 2025 14:10:52 -0500 Subject: [PATCH 18/18] IALERT-3873: Fix Jira cloud task to add search comments. --- .../cloud/task/JiraCloudSchedulingManager.java | 3 ++- .../cloud/task/JiraSearchCommentUpdateTask.java | 16 ++++++++++++---- .../server/task/JiraSearchCommentUpdateTask.java | 2 +- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraCloudSchedulingManager.java b/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraCloudSchedulingManager.java index 65f24cd9d2..089c08261c 100644 --- a/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraCloudSchedulingManager.java +++ b/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraCloudSchedulingManager.java @@ -5,6 +5,7 @@ import com.blackduck.integration.alert.api.task.TaskManager; import com.blackduck.integration.alert.channel.jira.cloud.JiraCloudPropertiesFactory; import com.blackduck.integration.alert.common.descriptor.ChannelDescriptor; +import com.blackduck.integration.alert.common.rest.AlertRestConstants; import com.blackduck.integration.alert.common.rest.model.FieldModel; import com.google.gson.Gson; import org.springframework.beans.factory.annotation.Autowired; @@ -45,7 +46,7 @@ public void unscheduleTasks(String configId) { private List createTasks(FieldModel fieldModel, Set projectNameOrKeys) { String configId = fieldModel.getId(); - String configName = fieldModel.getFieldValue(ChannelDescriptor.KEY_NAME).orElse(""); + String configName = fieldModel.getFieldValue(ChannelDescriptor.KEY_NAME).orElse(AlertRestConstants.DEFAULT_CONFIGURATION_NAME); JiraPropertyUpdateTask propertyTask = new JiraPropertyUpdateTask(taskScheduler, taskManager, jiraPropertiesFactory, gson, configId, configName, "JiraCloud", projectNameOrKeys); JiraSearchCommentUpdateTask searchCommentTask = new JiraSearchCommentUpdateTask(taskScheduler, taskManager, jiraPropertiesFactory, gson, configId, configName, "JiraCloud"); return List.of(propertyTask, searchCommentTask); diff --git a/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraSearchCommentUpdateTask.java b/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraSearchCommentUpdateTask.java index 4b44a5efee..97b3e2a16c 100644 --- a/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraSearchCommentUpdateTask.java +++ b/channel-jira-cloud/src/main/java/com/blackduck/integration/alert/channel/jira/cloud/task/JiraSearchCommentUpdateTask.java @@ -49,8 +49,13 @@ public void runTask() { IssueSearchResponseModel responseModel = issueSearchService.queryForIssuePage(JiraConstants.createCommentMigrationJQL(), null, JQL_QUERY_MAX_RESULTS); - int totalIssues = responseModel.getTotal(); - boolean foundIssues = totalIssues > 0; + // Jira cloud does not return the total count of items. It just has an isLast attribute for the last page. + // use the response model api to extract the isLast to log the issue. + Gson gson = responseModel.getGson(); + JsonObject jsonObject = gson.fromJson(responseModel.getJson(),JsonObject.class); + boolean isLast = jsonObject.get("isLast").getAsBoolean(); + int totalUpdated = responseModel.getIssues().size(); + boolean foundIssues = totalUpdated > 0; if(foundIssues) { List issueKeys = responseModel.getIssues().stream() @@ -63,7 +68,7 @@ public void runTask() { executorService.shutdown(); boolean success = executorService.awaitTermination(1, TimeUnit.MINUTES); if (success) { - logger.info("Jira search key comment update task remaining issues {} ", totalIssues); + logger.info("Jira search key comment issues updated {}, more issues to update {} ", totalUpdated, !isLast); } else { logger.info("Jira search key comment update task timed out updating issues; will resume with the next iteration."); } @@ -125,7 +130,10 @@ private Runnable createUpdateRunnable(String issueKey, IssuePropertyService issu String migratedPropertyValue = getGson().toJson(migratedProperty); issuePropertyService.setProperty(issueKey, JiraConstants.JIRA_ISSUE_PROPERTY_KEY, migratedPropertyValue); } catch (IntegrationException ex) { - logger.debug("Error updating issue {} with search key comment.", issueKey); + // if there are too many comments a 413 is returned. To resolve the 413 a user with access to delete comments needs to + // remove comments. Sometimes the issue will have a zip file attached to the ticket containing all of the comments. + // If the zip file is deleted then the comment can be added. + logger.error("Error updating issue {} with search key comment. Check if there are too many comments on the issue.", issueKey); logger.debug("Caused by: ", ex); } } diff --git a/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraSearchCommentUpdateTask.java b/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraSearchCommentUpdateTask.java index 25a47fd962..c8d205f0ef 100644 --- a/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraSearchCommentUpdateTask.java +++ b/channel-jira-server/src/main/java/com/blackduck/integration/alert/channel/jira/server/task/JiraSearchCommentUpdateTask.java @@ -129,7 +129,7 @@ private Runnable createUpdateRunnable(String issueKey, IssuePropertyService issu String migratedPropertyValue = getGson().toJson(migratedProperty); issuePropertyService.setProperty(issueKey, JiraConstants.JIRA_ISSUE_PROPERTY_KEY, migratedPropertyValue); } catch (IntegrationException ex) { - logger.debug("Error updating issue {} with search key comment.", issueKey); + logger.error("Error updating issue {} with search key comment.", issueKey); logger.debug("Caused by: ", ex); } }