Page History
...
| Code Block | ||||||
|---|---|---|---|---|---|---|
| ||||||
import com.onresolve.scriptrunner.runner.rest.common.CustomEndpointDelegate
import groovy.json.JsonOutput
import groovy.transform.BaseScript
import groovy.json.JsonSlurper;
import groovy.json.StreamingJsonBuilder;
import javax.ws.rs.core.MultivaluedMap
import javax.ws.rs.core.Response
import java.nio.charset.StandardCharsets
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.link.IssueLinkManager
import com.atlassian.jira.issue.link.IssueLinkType
import com.atlassian.jira.issue.link.IssueLinkTypeManager
import com.atlassian.jira.ComponentManager
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.jql.builder.JqlQueryBuilder
import com.atlassian.jira.user.util.UserUtil
import com.atlassian.jira.user.util.UserManager;
import com.atlassian.jira.bc.issue.IssueService
import com.atlassian.jira.bc.issue.search.SearchService;
import com.atlassian.jira.issue.search.SearchProvider
import com.atlassian.jira.issue.search.SearchResults
import com.atlassian.jira.web.bean.PagerFilter;
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.user.UserPropertyManager
import com.atlassian.jira.propertyset.JiraPropertySetFactory;
import com.google.common.collect.ImmutableMap;
import com.opensymphony.module.propertyset.PropertySet;
import com.opensymphony.module.propertyset.PropertySetManager;
import com.atlassian.jira.util.BuildUtils
import com.atlassian.jira.util.BuildUtilsInfo
import com.atlassian.jira.util.BuildUtilsInfoImpl
import com.atlassian.plugin.PluginAccessor
import com.atlassian.plugin.PluginManager
import com.atlassian.jira.bc.license.JiraLicenseService
import com.atlassian.jira.bc.license.JiraLicenseServiceImpl
import org.apache.log4j.Level
import org.apache.log4j.Logger
import com.atlassian.jira.issue.IssueManager
import groovy.json.StreamingJsonBuilder
@BaseScript CustomEndpointDelegate delegate
boolean associateTestsToXrayIssue(endpoint, issueKey,listOfTestKeys){
def jiraBaseUrl = com.atlassian.jira.component.ComponentAccessor.getApplicationProperties().getString("jira.baseurl")
def endpointUrl = "${jiraBaseUrl}/rest/raven/1.0/api/${endpoint}/${issueKey}/test"
log.debug("issueKey: "+issueKey)
log.debug("listOfTestKeys: "+listOfTestKeys)
log.debug("jirabaseurl: "+jiraBaseUrl)
log.debug("endpoint: "+endpointUrl)
url = new URL(endpointUrl);
def body_req = [ "add": listOfTestKeys ]
// you should use a specific user for this purpose
username = "admin"
password = "admin"
def authString = "${username}:${password}".bytes.encodeBase64().toString()
URLConnection connection = url.openConnection();
connection.requestMethod = "POST"
connection.doOutput = true
connection.addRequestProperty("Authorization", "Basic ${authString}")
connection.setRequestProperty("Content-Type", "application/json;charset=UTF-8")
connection.outputStream.withWriter("UTF-8") { new StreamingJsonBuilder(it, body_req) }
connection.connect();
log.debug(connection.getResponseCode())
log.debug(connection.getResponseMessage())
if (connection.getResponseCode() == 200) {
// OK
return true;
} else {
// error
return false;
}
}
boolean associateTestsToTestPlan(testPlanKey, listOfTestKeys){
return associateTestsToXrayIssue("testplan", testPlanKey, listOfTestKeys)
}
boolean associateTestsToTestExecution(testExecutionKey, listOfTestKeys){
return associateTestsToXrayIssue("testexec", testExecutionKey, listOfTestKeys)
}
Object getIssues(jqlQuery){
// A list of GenericValues representing issues
List<Issue> searchResults = null;
SearchService.ParseResult parseResult = searchService.parseQuery(serviceAccount, jqlQuery);
if (parseResult.isValid()) {
// throws SearchException
SearchResults results = searchService.search(serviceAccount, parseResult.getQuery(), PagerFilter.getUnlimitedFilter());
searchResults = results.getIssues();
return searchResults;
}
return []
}
synchTestsFromRelatedTestSets(httpMethod: "GET") { MultivaluedMap queryParams ->
// issue_key may refer to a Test Plan or to a Test Execution
def issue_key = queryParams.getFirst("issueId") as String // use the issueId to retrieve this issue
projectManager = ComponentAccessor.getProjectManager()
componentManager = ComponentManager.getInstance();
searchService = ComponentAccessor.getComponent(SearchService.class);
issueManager = ComponentAccessor.getIssueManager()
customFieldManager = ComponentAccessor.getCustomFieldManager()
userUtil = ComponentAccessor.getUserUtil();
serviceAccount = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()
pluginAccessor = componentManager.getPluginAccessor();
MutableIssue issue = issueManager.getIssueObject(issue_key)
Logger.getLogger("com.onresolve").setLevel(Level.DEBUG)
// assume that Test Plan/Execution is linked to Test Sets using the issue link "relates to"; customize if needed
jql = "issue in linkedIssues('${issue_key}', 'relates to')"
testset_issues = getIssues(jql)
def had_errors = false
def success = false
testset_issues.each {
// process only "Test Set" issues
if (it.issueType.name == "Test Set") {
jql = "issue in testSetTests('${it.key}')"
issues = getIssues(jql)
test_keys = issues.collect{ it.key }
//log.debug(test_keys)
if (issue.issueType.name == "Test Plan") {
success = associateTestsToTestPlan(issue_key, test_keys)
} else if ((issue.issueType.name == "Sub Test Execution") || (issue.issueType.name == "Test Execution")) {
success = associateTestsToTestExecution(issue_key, test_keys)
}
if (!success) {
had_errors = true
}
}
}
def flag = []
if (success) {
flag = [
type : 'success',
title: "Test Sets Synchronization",
close: 'auto',
body : "Tests have been synchronized for " + issue_key
]
Response.ok(JsonOutput.toJson(flag)).build()
} else {
flag = [
type : 'success',
title: "Test Sets Synchronization",
close: 'auto',
body : "Tests have been synchronized for " + issue_key
]
Response.serverError().entity([error: "some Tests were no synchronized"]).build()
}
} |
Example
Add a custom link to the Tests top menu
Sometimes it may be useful to add a custom link to the Tests top menu.
As an example, you may have an internal documentation/Confluence space with some valuable information concerning Xray usage in your organization.
ScripRunner configuration
Adding an entry to the top menu is easy.
Just go the Add-ons section in your Jira administration and then "Script Fragments".
Add a new "Raw xml module".
And add the configuration for the link; this configuration is exactly the same as if you were going to develop your own app, so it follows Atlassian developer documentation guidelines for the "web-item" element.
Make sure the "web-item" as a "weight" value higher than 120, to append your link to the end of the options available from the dropdown menu.
Example
Let's say that we want to add a link to "https://getxray.app" in the top Test menu, having the name "My Custom Link".
The "raw xml module" configuration would be something similar to the following snippet.
| Code Block |
|---|
<web-item key="xray-topnav-tests-meta-customlink" name="Custom link" section="raven-menu/xray.topnav.meta.section" weight="130">
<label>My Custom Link</label>
<link linkId="raven-topnav-test-item-meta.customlink">https://getxray.app</link>
</web-item> |






