Associate issues using the references header

Scenario

Matching issues on the ‘References’ header is currently not supported in Jira, or JEMH out of the box. historically, Jira stored this but it was removed some years ago due to the quantity of data stored.

Using the following script it is possible to extract the References header values and store them (hashed, to ensure a JQL query will work). Using Jira Query Language we can locate issues with the same ‘references’ header, in order to associate the current email with, avoiding a duplicated issue.This script will only associate on issue creation and when no issue is resolved by other means.

Since JEMH 3.3.21 we lock down access to arbitrary classes in the script context, they cannot be accessed using historic methods:

var pageFilter = PagerFilter.static.getUnlimitedFilter(); var jqlQueryBuilder = JqlQueryBuilder.static.newBuilder();

but need to be gained through fully specified class names:

var filter = Java.type("com.atlassian.jira.web.bean.PagerFilter").getUnlimitedFilter(); var builder = Java.type("com.atlassian.jira.jql.builder.JqlQueryBuilder").newBuilder();

These specific classes were not initially added, are available since JEMH 3.3.38

/* This method is used to store the hashes of Reference header values in a custom field This allows association of issues (to drive commenting) based on the reference header only. cfID - The ID of the custom field used (i.e. "customfield_12345") cfName - The name of the Custom field (i.e. "Reference Hash") timeFrame - Only issues updated in the timeframe will be associated to. e.g. ("-24h") (h- hours, d- days, w- weeks, etc..) */ if(relatedIssue === null) { var pattern = Java.type("java.util.regex.Pattern").compile("(\\<[^>]+\\>)"); var references = message.getHeader("References"); var cfValue = ""; var issueMatched = false; //These variables should be customized to fit the instance var cfID = "customfield_10200"; var cfName = "Reference Hash"; var timeFrame = "-24h"; //This loop Identifies individual references for(var i in references) { //this retrives a single line from the var referenceLine = references[i]; var splitReference = referenceLine.split(" "); for(var ii in splitReference) { var singleReference = splitReference[ii]; //identify a valid refernece var matcher = pattern.matcher(singleReference); if (matcher.find()) { //Hash the value to store in the customField var hashedReference = jemhUtils.hash(matcher.group(0)); if(cfValue !== "") { cfValue += ", " + hashedReference; } else { cfValue += hashedReference; } } } } //End of search for headers //Beginning of issue search var allHashed = cfValue.split(", "); //get the user to run the JQL query as var user = userManager.getUserByName("admin"); var filter = Java.type("com.atlassian.jira.web.bean.PagerFilter").getUnlimitedFilter(); var builder = Java.type("com.atlassian.jira.jql.builder.JqlQueryBuilder").newBuilder(); //create a loop to iterate through the hashed values for(var i in allHashed) { var searchValue = allHashed[i]; //construct the JQL query var query = builder.where().defaultAnd().field(cfName).like(searchValue).field("updated").gtEq(timeFrame); query=query.buildQuery(); var results = searchService.search(user, query, filter).getResults(); //cycle through the results for(var ii in results) { var matchedIssue = results[ii]; print("Matched Issue " + matchedIssue.getKey() + " using search hash: "+ searchValue); resultMap.put("issueKey",matchedIssue.getKey()); issueMatched= true; } if(issueMatched) { break; } } //Storing the value of the hashes if(!issueMatched) { if(cfValue !=="") { resultMap.put(cfID,cfValue); } } else { var cfOrigin = matchedIssue.getCustomFieldValue(customFieldManager. getCustomFieldObject(cfID)); var cfMixed = cfOrigin + ", " + cfValue; var cfSplit = cfMixed.split(", "); var cfFinal = ""; for(var i in cfSplit) { var cfRef = cfSplit[i]; if(cfFinal === "") { cfFinal += cfRef; } else { var index = cfFinal.indexOf(cfRef); if(index === -1) { cfFinal += ", " + cfRef; } } } if(cfFinal !== "") { resultMap.put(cfID,cfFinal); } } }