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