Listing out the groovy scripts for different scenarios below which might be useful in future requirements.
1. Script to transition sub-task to same as parent task on update or create event (Cloud)
Code Block | ||
---|---|---|
| ||
// Check if issue types are sub-tasks if (issue.fields.issuetype.subtask) { logger.info("This is a subtask") return } else if (!issue.fields.issutype.subtask) { logger.info("This is not a subtask") // Retrieve the key def parentKey = issue.key logger.info("Parent Key: " + parentKey) // Get the parent issue object def result = get('/rest/api/2/issue/' + parentKey + "?expand=transitions") .header('Content-Type', 'application/json') .asObject(Map) // Find the parent status def parentStatus = result.body.fields.status.name logger.info("Parent Status: " + parentStatus) // Find the subtask status def subTaskStatus = result.body.fields.subtasks.fields.status.name logger.info("Sub task Status: " + subTaskStatus) // Find the subtasks key String[] subTaskKeyInArray = result.body.fields.subtasks.key //def subTaskKeyString = subTaskKeyInArray.join(", ") logger.info("Length of the array is:" + subTaskKeyInArray.length) //Defining statuses def open = "Open" def qaInProg = "QA In Prog" def pendingCTS = "Pending CTS" def ctsClosed = "CTS Closed" def investigating = "Investigating" def investigatingComplete = "Investigating Complete" def fixed = "Fixed" def transition(transitionId, subTaskKey) { def transitionIssue = post("/rest/api/2/issue/" + subTaskKey + "/transitions") .header("Content-Type", "application/json") .body([transition: [id: transitionId]]) .asObject(Map) logger.info("Sub Task issue transitioned") } for(int i = 0; i < subTaskKeyInArray.length; i++) { logger.info("Value of i " + i) logger.info("Sub task:" + subTaskKeyInArray[i]) // Put conditions to set transition ids based on condition is true if (subTaskStatus.contains(qaInProg) && parentStatus.contains(investigating)) { logger.info("Transition id after entering loop: 41") transition("41", subTaskKeyInArray[i]) } if (subTaskStatus.contains(qaInProg) && parentStatus.contains(pendingCTS)) { logger.info("Transition id after entering loop: 51") transition("51", subTaskKeyInArray[i]) } if (subTaskStatus.contains(qaInProg) && parentStatus.contains(ctsClosed)) { logger.info("Transition id after entering loop: 61") transition("61", subTaskKeyInArray[i]) } if (subTaskStatus.contains(qaInProg) && parentStatus.contains(fixed)) { logger.info("Transition id after entering loop: 121") transition("121", subTaskKeyInArray[i]) } if (subTaskStatus.contains(open) && parentStatus.contains(qaInProg)) { logger.info("Transition id after entering loop: 11") transition("11", subTaskKeyInArray[i]) } if (subTaskStatus.contains(open) && parentStatus.contains(pendingCTS)) { logger.info("Transition id after entering loop: 21") transition("21", subTaskKeyInArray[i]) } if (subTaskStatus.contains(open) && parentStatus.contains(ctsClosed)) { logger.info("Transition id after entering loop: 61") transition("61", subTaskKeyInArray[i]) } if (subTaskStatus.contains(open) && parentStatus.contains(fixed)) { logger.info("Transition id after entering loop: 121") transition("121", subTaskKeyInArray[i]) } if (subTaskStatus.contains(investigating) && parentStatus.contains(investigatingComplete)) { logger.info("Transition id after entering loop: 71") transition("71", subTaskKeyInArray[i]) } if (subTaskStatus.contains(investigating) && parentStatus.contains(pendingCTS)) { logger.info("Transition id after entering loop: 81") transition("81", subTaskKeyInArray[i]) } if (subTaskStatus.contains(investigating) && parentStatus.contains(ctsClosed)) { logger.info("Transition id after entering loop: 61") transition("61", subTaskKeyInArray[i]) } if (subTaskStatus.contains(investigating) && parentStatus.contains(fixed)) { logger.info("Transition id after entering loop: 121") transition("121", subTaskKeyInArray[i]) } if (subTaskStatus.contains(investigatingComplete) && parentStatus.contains(pendingCTS)) { logger.info("Transition id after entering loop: 101") transition("101", subTaskKeyInArray[i]) } if (subTaskStatus.contains(investigatingComplete) && parentStatus.contains(ctsClosed)) { logger.info("Transition id after entering loop: 161") transition("161", subTaskKeyInArray[i]) } if (subTaskStatus.contains(investigatingComplete) && parentStatus.contains(fixed)) { logger.info("Transition id after entering loop: 121") transition("121", subTaskKeyInArray[i]) } if (subTaskStatus.contains(investigatingComplete) && parentStatus.contains(investigating)) { logger.info("Transition id after entering loop: 111") transition("111", subTaskKeyInArray[i]) } if (subTaskStatus.contains(pendingCTS) && parentStatus.contains(ctsClosed)) { logger.info("Transition id after entering loop: 141") transition("141", subTaskKeyInArray[i]) } if (subTaskStatus.contains(pendingCTS) && parentStatus.contains(fixed)) { logger.info("Transition id after entering loop: 121") transition("121", subTaskKeyInArray[i]) } if (subTaskStatus.contains(pendingCTS) && parentStatus.contains(investigating)) { logger.info("Transition id after entering loop: 131") transition("131", subTaskKeyInArray[i]) } if (subTaskStatus.contains(fixed) && parentStatus.contains(ctsClosed)) { logger.info("Transition id after entering loop: 151") transition("151", subTaskKeyInArray[i]) } if (subTaskStatus.contains(fixed) && parentStatus.contains(investigating)) { logger.info("Transition id after entering loop: 131") transition("131", subTaskKeyInArray[i]) } } } |
2. Script to prompt the user if they want to close the parent ticket when all sub-tasks under the ticket are done (Cloud)
Code Block | ||
---|---|---|
| ||
// Check if issue types are sub-tasks if (!issue.fields.issuetype.subtask) { return } // Get the parent issue as a Map def parent = (issue.fields as Map).parent as Map // Retrieve all the subtasks of this issue's parent def parentKey = parent.key logger.info("Parent Key: " + parentKey) // Specify the name of the version to extract from the issue def closedStatus = "Done" logger.info("Closed Status: " + closedStatus) // Get the parent issue object def result = get('/rest/api/2/issue/' + parentKey) .header('Content-Type', 'application/json') .asObject(Map) //Find the assignee name def assignee = result.body.fields.assignee.displayName logger.info("Assignee name is :" + assignee) // Find the subtasks status String[] subTasks = result.body.fields.subtasks logger.info("Subtasks length: " + subTasks.length) def allSubTasksResolved; for(int i = 0; i < subTasks.length; i++) { def subTasksStatus = result.body.fields.subtasks[i].fields.status.name logger.info("sub task status: " + subTasksStatus) if(subTasks.findAll{subTasksStatus.contains(closedStatus)}){ allSubTasksResolved = true } // If all subtasks have the Done status set the flag to true if(subTasks.findAll{!subTasksStatus.contains(closedStatus)}){ allSubTasksResolved = false } } if(allSubTasksResolved == true){ logger.info("All sub tasks are in Done status") def prompt = post("/rest/api/2/issue/" + parentKey + "/notify") .header("Content-Type", "application/json") .body([ subject: 'All sub-tasks transitioned to Done status', textBody: "All the sub-tasks related to " + parentKey + " are transitioned to Done status", htmlBody: "<p>Do you want to close the </p>" + parentKey + "<p> issue?</p>" , to: [ users: [[ name: assignee, active: true ]] ] ]) .asString() } else if (allSubTasksResolved == false){ logger.info("All sub tasks are not in Done status") } |
3. Script to change the fix Versions field of sub-tasks based on parent task on update event (Server)
Code Block | ||
---|---|---|
| ||
import com.atlassian.jira.component.ComponentAccessor import com.atlassian.jira.event.type.EventDispatchOption import com.atlassian.jira.issue.Issue import com.atlassian.jira.issue.IssueManager import com.atlassian.jira.issue.MutableIssue import com.atlassian.jira.project.version.Version IssueManager issueManager = ComponentAccessor.getComponent(IssueManager.class) Issue updatedIssue = event.getIssue() log.error "Issue is: " + updatedIssue Collection<Version> fixVersions = new ArrayList<Version>() fixVersions = updatedIssue.getFixVersions() log.error "Fix versions of parent are: " + fixVersions Collection<Issue> subTasks = updatedIssue.getSubTaskObjects() log.error "Sub tasks are: " + subTasks subTasks.each { log.error "Type : " + it.issueType.getName() if(it.issueType.getName() == "Migration") { if (it instanceof MutableIssue) { ((MutableIssue) it).setFixVersions(fixVersions) issueManager.updateIssue(event.getUser(), it, EventDispatchOption.ISSUE_UPDATED, false) log.error "Fix version of subbtask" } } } |
4. Script to set a default value for fix-version field (Server)
Code Block | ||
---|---|---|
| ||
def versionIdProductionMaintenance = "10214" def versionIdProductionUAT = "10306" def actionName = "Create" if (getActionName() != actionName) { return // not the initial action, so don't set default values } //get fixVersion ID def fixVersionsField = getFieldById("fixVersions") //set fixVersion value def fixVersionsNewValue = fixVersionsField.setFormValue([versionIdProductionMaintenance, versionIdProductionUAT]) |
5. Adding Custom filed value while changing the status to the particular screen: post-function (Server)
Code Block | ||
---|---|---|
| ||
import groovy.json.JsonSlurper; import groovy.json.StreamingJsonBuilder; import com.atlassian.jira.issue.util.DefaultIssueChangeHolder; import com.atlassian.jira.issue.ModifiedValue; import com.atlassian.jira.issue.CustomFieldManager; import com.atlassian.jira.issue.fields.CustomField; import com.atlassian.jira.issue.IssueManager; import com.atlassian.jira.component.ComponentAccessor; import com.atlassian.jira.issue.Issue; import com.atlassian.jira.issue.MutableIssue import org.apache.commons.codec.binary.Base64; def url = new URL("https://jsonplaceholder.typicode.com/posts").openConnection(); def message = '{"title": "foo","body": "bar", "userId": "1"}'; url.setRequestMethod("POST") url.setDoOutput(true) url.setRequestProperty("Content-Type", "application/json") url.getOutputStream().write(message.getBytes("UTF-8")); def postRC = url.getResponseCode(); IssueManager im = ComponentAccessor.getIssueManager() MutableIssue issue = im.getIssueObject("SP-5519") if(issue){ def customFieldManager = ComponentAccessor.getCustomFieldManager() def cField = customFieldManager.getCustomFieldObject("customfield_10401") def cFieldValue = issue.getCustomFieldValue(cField) def changeHolder = new DefaultIssueChangeHolder() cField.updateValue(null, issue, new ModifiedValue(cFieldValue, url.getInputStream().getText()),changeHolder) }else { return "Issue doesn't exist" } |
6. Changing the status of particular issue (Server)
Code Block | ||
---|---|---|
| ||
import com.atlassian.jira.issue.IssueManager; import com.atlassian.jira.issue.MutableIssue; import com.atlassian.jira.component.ComponentAccessor; import com.atlassian.jira.user.ApplicationUser; //Workflow imports import com.atlassian.jira.issue.IssueInputParametersImpl import com.atlassian.jira.bc.issue.IssueService import com.atlassian.jira.workflow.JiraWorkflow import com.atlassian.jira.workflow.WorkflowManager ApplicationUser currentUser = ComponentAccessor.getJiraAuthenticationContext().loggedInUser IssueManager im = ComponentAccessor.getIssueManager(); MutableIssue issue = im.getIssueObject("SP-5519"); //Workflow WorkflowManager workflowManager = ComponentAccessor.getWorkflowManager() JiraWorkflow workflow = workflowManager.getWorkflow(issue) def actionId = 41 IssueService issueService = ComponentAccessor.getIssueService() def transitionValidationResult = issueService.validateTransition(currentUser, issue.id, actionId, new IssueInputParametersImpl()) def transitionResult = issueService.transition(currentUser, transitionValidationResult) return transitionResult |
7. Getting the linked issues of particular issue (Server)
Code Block | ||
---|---|---|
| ||
import com.atlassian.jira.issue.IssueManager; import com.atlassian.jira.issue.MutableIssue; import com.atlassian.jira.component.ComponentAccessor; import com.atlassian.jira.issue.link.IssueLink; import com.atlassian.jira.issue.comments.CommentManager; import com.atlassian.jira.user.ApplicationUser; CommentManager commentMgr = ComponentAccessor.getCommentManager() ApplicationUser currentUser = ComponentAccessor.getJiraAuthenticationContext().loggedInUser IssueManager im = ComponentAccessor.getIssueManager(); MutableIssue issue = im.getIssueObject("SP-5519"); return commentMgr.getComments(issue).last().body def links = ComponentAccessor.getIssueLinkManager().getOutwardLinks(issue.getId()) def output = "" for( l in links) { //use this for Outward links output = output + l.issueLinkType.name + ": " + l.getDestinationObject() + "<br/> } return output |
8. Script to set a default value for fix-version field for a particular issue type (Server)
Code Block | ||
---|---|---|
| ||
def versionIdProductionMaintenance = "10214" def actionName = "Create" if (getActionName() != actionName) { return // not the initial action, so don't set default values } //def issueType = getFieldById("10402").getValue().toString() def issueType = issueContext.issueType.name if(issueType == "Change Request") { //get fixVersion ID def fixVersionsFieldCR = getFieldById("fixVersions") //set fixVersion value def fixVersionsNewValueCR = fixVersionsFieldCR.setFormValue([versionIdProductionMaintenance]) } else { def fixVersionsField = getFieldById("fixVersions") def fixVersionsNewValue = fixVersionsField.setFormValue("") } |
9. Adding a comment to the linked issue and the main issue (Server)
Code Block | ||
---|---|---|
| ||
import com.atlassian.jira.issue.IssueManager; import com.atlassian.jira.issue.MutableIssue; import com.atlassian.jira.component.ComponentAccessor; import com.atlassian.jira.issue.link.IssueLink; import com.atlassian.jira.issue.comments.CommentManager; import com.atlassian.jira.user.ApplicationUser; CommentManager commentMgr = ComponentAccessor.getCommentManager() ApplicationUser currentUser = ComponentAccessor.getJiraAuthenticationContext().loggedInUser IssueManager im = ComponentAccessor.getIssueManager(); MutableIssue issue = im.getIssueObject("SP-5519"); def lastComment = commentMgr.getComments(issue).last().body //def links = ComponentAccessor.getIssueLinkManager().getInwardLinks(issue.getId()) def links = ComponentAccessor.getIssueLinkManager().getOutwardLinks(issue.getId()) //return links[0].getSourceObject() def output = "" for( l in links) { //use this for Outward links output = output + l.issueLinkType.name + ": " + l.getDestinationObject() + "<br/>" //use this for Inward links //output = output + l.issueLinkType.name + ": " + l.getSourceObject() + "<br/>" // adding comment for the main issue commentMgr.create(l.getSourceObject(),currentUser, "Test------------", false) // adding comment for the linked issue commentMgr.create(l.getDestinationObject(),currentUser, "Test------------", false) } return output |
10. Getting all Sub-Tasks and Issue Key of the Sub-Task (Server)
Code Block | ||
---|---|---|
| ||
//import com.atlassian.jira.issue.IssueManager; import com.atlassian.jira.issue.MutableIssue; import com.atlassian.jira.component.ComponentAccessor; IssueManager im = ComponentAccessor.getIssueManager(); MutableIssue issue = im.getIssueObject("ANDROID-38"); def output = "" for (e in issue.getSubTaskObjects()) { output = output + e.getSummary() +"," + e.issueType.name + "<br/>" } return output // Uncomment this line for getting issue key of the subtask //MutableIssue sub_issue = im.getIssueObject(issue.getSubTaskObjects()[0].toString()); //return sub_issue |
11. Script to hide the custom fields on create screen if the user is not a project admin (behaviors - Server)
Code Block | ||
---|---|---|
| ||
/* Script to hide the "Notes" field if the current logged in user is not in "Project Owner" role and show it if the user is in "Project Owner" role. User can be in multiple roles but if he/she is not part of "Project Owner" role field should not be shown. */ import com.atlassian.jira.user.ApplicationUser import com.atlassian.jira.component.ComponentAccessor import com.atlassian.jira.security.roles.ProjectRoleManager import com.atlassian.jira.security.roles.ProjectRole import com.atlassian.jira.project.ProjectManager import com.atlassian.jira.user.util.UserManager //define the project role final String PROJECT_OWNER = "Project Owner"; //define the project name final String PROJECT_NAME = "TnT Jira Support Services"; //set flags to show and hide field final boolean NOTES_VISIBLE = true; final boolean NOTES_NOT_VISIBLE = false; //define the field to be shown/hidden final String NOTES = "Notes"; //get the current logged in user def loggedInUser = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser(); //get ProjectManager class def projectManagerClass = ComponentAccessor.projectManager; def projectRoleManager = ComponentAccessor.getComponent(ProjectRoleManager); //get the project role object of logged in user ProjectRole newRole = projectRoleManager.getProjectRole(PROJECT_OWNER); //get the project object of the project against which logged in user roles are checked def project = projectManagerClass.getProjectObjByName(PROJECT_NAME); //get the custom field def notesField = getFieldByName(NOTES); //check if the logged in user has a project role in a project, return boolean def projectRoles = projectRoleManager.isUserInProjectRole(loggedInUser, newRole, project); //condition to set the custom field hidden or shown if(projectRoles.equals(NOTES_VISIBLE)) { notesField.setHidden(NOTES_NOT_VISIBLE); } else { notesField.setHidden(NOTES_VISIBLE); } |
...
No | Date | Topics learnt | |
1 | 12-03-2020 | Introduction to Groovy, how groovy works, static and dynamic compilation, optional typed, how to use script-runner to execute scripts in script console, how to look up to java doc for methods and classes | |
2 | 13-03-2020 | Variables, rules, operators, built in scripts and scenarios in script-runner, listeners, exception handling, how to get all the details related to a specific issue (code) | |
3 | 16-03-2020 | Conditional statements (if else, switch), looping (for, for in, while), String, string functions, interpolation, multi-lines, methods / functions, closures, how to get all the sub-tasks related to issues, fetch their data and manipulate their information (code) | |
4 | 17-03-2020 | Worked on setting a default value to a fix version system field (includes reading and understanding the behaviors of script-runner, sample examples, and implementation of the code) | |
server | System JIRA | ||
---|---|---|---|
columns | key,summary,type,created,updated,due,assignee,reporter,priority,status,resolution | ||
serverId | 6f8446ac-0270-38e8-bfda-78a5daa9d08d | key | https://empyrajira.atlassian.net/browse/AP-1115|
5 | 18-03-2020 | Collections, lists, maps, ranges, types of ranges, iterations over collections, functions available for different collections, IO operations, how to set values based on system and custom fields (code) |
...