Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
9aae880
IALERT-3868: Disable adding comments in the backend and remove from UI.
psantos1113 Aug 13, 2025
df7d448
IALERT-3868: remove the comments field from the models and UI.
psantos1113 Aug 13, 2025
ececc44
IALERT-3868: Remove add_comments column.
psantos1113 Aug 13, 2025
b43bca8
IALERT-3868: Make disable plugin check the default behavior.
psantos1113 Aug 14, 2025
0c20929
Merge remote-tracking branch 'origin/master' into dev/ps/IALERT-3868-…
psantos1113 Aug 18, 2025
d5a3283
IALERT-3873: Initial implementation of tasks.
psantos1113 Aug 20, 2025
546a20c
Merge remote-tracking branch 'origin/master' into dev/ps/IALERT-3873-…
psantos1113 Aug 21, 2025
8d55ecb
IALERT-3873: Rename JiraTask to JiraPropertyTask.
psantos1113 Aug 21, 2025
3036b2c
Create the skeleton to update tickets with comments
psantos1113 Aug 21, 2025
d1b863f
IALERT-3873: Implement the changes to get the property value.
psantos1113 Aug 27, 2025
3bf9771
IALERT-3873: Implement the code to read the properties and create the…
psantos1113 Aug 28, 2025
028f7dc
IALERT-3873: Fix the start of the property tasks.
psantos1113 Aug 29, 2025
6659326
IALERT-3873: Fix JQL query to migrate issues missing comments.
psantos1113 Aug 29, 2025
5f65a57
IALERT-3873: Update the properties with a new version of the indexer.
psantos1113 Sep 2, 2025
a689581
IALERT-3873: Change the comment to have the same values as the property.
psantos1113 Sep 3, 2025
e236201
IALERT-3873: Change the constructor visibility.
psantos1113 Sep 4, 2025
1e401e8
IALERT-3873: Fix a comment and add whitespace.
psantos1113 Sep 11, 2025
ca10858
IALERT-3873: Fix a discrepancy when adding the comment to jira with t…
psantos1113 Sep 11, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -19,21 +21,27 @@ public final class JiraConstants {

public static final String JIRA_SEARCH_KEY_JIRA_PROJECT = "project";

// 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 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 alert9Migrated is empty or has the text "true".

public static final String JIRA_ISSUE_VALIDATION_ERROR_MESSAGE = "There are issues with the configuration.";
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
+ "].alert9Migrated IS EMPTY "
+ "OR issue.property["
+ JiraConstants.JIRA_ISSUE_PROPERTY_KEY
+ "].alert9Migrated != 'true'"
+ "))";
}

private JiraConstants() {
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -55,6 +56,7 @@ public JiraIssueSearchProperties(
this.subComponentName = subComponentName;
this.subComponentValue = subComponentValue;
this.additionalKey = additionalKey;
this.alert9Migrated = "true";
}

public String getProvider() {
Expand Down Expand Up @@ -105,4 +107,6 @@ public String getAdditionalKey() {
return additionalKey;
}

public String getAlert9Migrated() { return alert9Migrated; }

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,11 @@
*/
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.JiraConstants;
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;
Expand Down Expand Up @@ -239,75 +237,32 @@ private JiraIssueSearchProperties createSearchProperties(ProjectIssueModel alert

@Override
protected Optional<String> getAlertSearchKeys(ExistingIssueDetails<String> existingIssueDetails, @Nullable ProjectIssueModel alertIssueSource) {
StringBuilder keyBuilder = new StringBuilder();

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()
.orElseThrow(() -> new AlertRuntimeException("Missing project version"));

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<LinkableItem> 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<LinkableItem> componentVersion = bomComponent.getComponentVersion();
Optional<IssuePolicyDetails> policyDetails = alertIssueSource.getPolicyDetails();
Optional<ComponentConcernType> 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(provider, project, projectVersion, bomComponent.getComponent(), componentVersion.orElse(null),category, policyName));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,12 @@ 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 ===";
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";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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,
Expand All @@ -117,50 +118,51 @@ 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/");
appendCommentSearchString(jqlBuilder, JiraIssuePropertyKeys.JIRA_ISSUE_KEY_PROJECT_ID, projectId);
jqlBuilder.append(SEARCH_CONJUNCTION);
jqlBuilder.append(StringUtils.SPACE);
appendCommentSearchString(jqlBuilder, JiraIssuePropertyKeys.JIRA_ISSUE_KEY_PROJECT_ID, project.getValue());
}

if(projectVersion != null && projectVersion.getUrl().isPresent()) {
String projectVersionId = extractUuid(projectVersion.getUrl().get(), "/versions/");
appendCommentSearchString(jqlBuilder, JiraIssuePropertyKeys.JIRA_ISSUE_KEY_PROJECT_VERSION_ID, projectVersionId);
jqlBuilder.append(SEARCH_CONJUNCTION);
jqlBuilder.append(StringUtils.SPACE);
appendCommentSearchString(jqlBuilder, JiraIssuePropertyKeys.JIRA_ISSUE_KEY_PROJECT_VERSION_ID, projectVersion.getValue());
}

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(")");
}

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,
Expand Down Expand Up @@ -212,8 +214,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);
Expand Down
Loading