0% found this document useful (0 votes)
29 views

Jira Script Runner Groovy Examples

Uploaded by

vinay endla
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
29 views

Jira Script Runner Groovy Examples

Uploaded by

vinay endla
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 69

Jira ScriptRunner is a powerful tool for automating and extending Jira's capabilities

through custom scripts written in Groovy. Here are some common examples of how you
can use ScriptRunner in Jira:

### 1. Automating Issue Transitions

Automate the transition of issues based on specific conditions.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.issue.Issue

def issueManager = ComponentAccessor.getIssueManager()

def workflowManager = ComponentAccessor.getWorkflowManager()

def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

Issue issue = issueManager.getIssueObject("TEST-1")

// Check if issue meets the condition

if (issue.getStatus().getName() == "To Do") {

def workflowTransitionUtil =
ComponentAccessor.getComponent(com.atlassian.jira.workflow.WorkflowTransitionUtil
)

workflowTransitionUtil.setIssue(issue)

workflowTransitionUtil.setUserkey(user.key)

workflowTransitionUtil.setAction(11) // ID of the transition action

workflowTransitionUtil.validate()

workflowTransitionUtil.progress()

}
```

### 2. Automatically Assign Issues

Automatically assign issues to a user based on certain criteria.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.issue.MutableIssue

def issueManager = ComponentAccessor.getIssueManager()

def userManager = ComponentAccessor.getUserManager()

MutableIssue issue = issueManager.getIssueObject("TEST-1")

def user = userManager.getUserByKey("jdoe")

if (issue.getPriority().getName() == "High") {

issue.setAssignee(user)

issue.store()

```

### 3. Creating Sub-Tasks Automatically

Create sub-tasks when an issue is created.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.IssueFactory

def issueManager = ComponentAccessor.getIssueManager()

def subTaskManager = ComponentAccessor.getSubTaskManager()

def issueFactory = ComponentAccessor.getComponent(IssueFactory)

def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

MutableIssue parentIssue = issueManager.getIssueObject("TEST-1")

if (parentIssue.getIssueType().getName() == "Task") {

def subTask = issueFactory.getIssue()

subTask.setSummary("Sub-task for " + parentIssue.getSummary())

subTask.setParentObject(parentIssue)

subTask.setIssueTypeId("5") // Sub-task issue type ID

subTask.setAssignee(parentIssue.getAssignee())

subTaskManager.createIssue(user, subTask)

```

### 4. Sending Custom Notifications

Send custom email notifications based on issue events.

```groovy

import com.atlassian.mail.server.SMTPMailServer

import com.atlassian.mail.Email

import com.atlassian.jira.component.ComponentAccessor
def mailServer =
ComponentAccessor.getMailServerManager().getDefaultSMTPMailServer()

def issueManager = ComponentAccessor.getIssueManager()

if (mailServer) {

def issue = issueManager.getIssueObject("TEST-1")

def emailAddr = issue.getAssignee().getEmailAddress()

def email = new Email(emailAddr)

email.setSubject("Issue Updated: ${issue.getKey()}")

email.setBody("The issue ${issue.getKey()} has been updated. Please review the


changes.")

mailServer.send(email)

} else {

log.error("No SMTP mail server configured")

```

### 5. Adding Comments Programmatically

Add a comment to an issue based on a condition.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.issue.comments.CommentManager
def issueManager = ComponentAccessor.getIssueManager()

def commentManager = ComponentAccessor.getCommentManager()

def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

def issue = issueManager.getIssueObject("TEST-1")

if (issue.getPriority().getName() == "Critical") {

commentManager.create(issue, user, "This is a critical issue that requires immediate


attention.", true)

```

These examples showcase various ways you can utilize Jira ScriptRunner to enhance
your Jira workflows. Always ensure you test scripts in a staging environment before
applying them to production to prevent any disruptions.

Sure, here are some more advanced examples of how you can use Jira ScriptRunner to
automate and extend Jira functionalities.

### 6. Bulk Update Custom Fields

Update a custom field for all issues in a particular project.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.issue.CustomFieldManager

import com.atlassian.jira.issue.search.SearchProvider

import com.atlassian.jira.web.bean.PagerFilter

def issueManager = ComponentAccessor.getIssueManager()


def customFieldManager = ComponentAccessor.getCustomFieldManager()

def searchService = ComponentAccessor.getComponent(SearchProvider)

def query = "project = TEST" // JQL query

def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

def parseResult = searchService.parseQuery(user, query)

def results = searchService.search(parseResult.query, user,


PagerFilter.getUnlimitedFilter())

def customField =
customFieldManager.getCustomFieldObjectByName("CustomFieldName")

results.getIssues().each { issue ->

def mutableIssue = issueManager.getIssueObject(issue.id)

mutableIssue.setCustomFieldValue(customField, "New Value")

issueManager.updateIssue(user, mutableIssue,
EventDispatchOption.DO_NOT_DISPATCH, false)

```

### 7. Cloning Issues with Links

Clone an issue and create a link between the original and the clone.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.issue.Issue

import com.atlassian.jira.issue.IssueFactory

import com.atlassian.jira.issue.link.IssueLinkManager
def issueManager = ComponentAccessor.getIssueManager()

def issueFactory = ComponentAccessor.getIssueFactory()

def issueLinkManager = ComponentAccessor.getIssueLinkManager()

def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

Issue issue = issueManager.getIssueObject("TEST-1")

def clone = issueFactory.cloneIssue(issue)

clone.setSummary("Clone of " + issue.getSummary())

issueManager.createIssue(user, clone)

issueLinkManager.createIssueLink(issue.id, clone.id, 10000, 1, user) // 10000 is the link


type ID for "Cloners"

```

### 8. Escalating Issues Based on SLA

Escalate issues by changing their priority if SLA is breached.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.issue.MutableIssue

import com.atlassian.jira.issue.search.SearchProvider

import com.atlassian.jira.web.bean.PagerFilter

import com.atlassian.jira.bc.issue.search.SearchService

def searchService = ComponentAccessor.getComponent(SearchProvider)

def issueManager = ComponentAccessor.getIssueManager()


def constantsManager = ComponentAccessor.getConstantsManager()

def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

def query = "project = TEST AND \"Time to resolution\" <= remaining(\"1d\") AND
status != Resolved"

def parseResult = searchService.parseQuery(user, query)

def results = searchService.search(parseResult.query, user,


PagerFilter.getUnlimitedFilter())

def highPriority = constantsManager.getPriorityObject("2") // "2" is typically the ID for


High priority

results.getIssues().each { issue ->

MutableIssue mutableIssue = issueManager.getIssueObject(issue.id)

mutableIssue.setPriority(highPriority)

issueManager.updateIssue(user, mutableIssue, EventDispatchOption.ISSUE_UPDATED,


false)

```

### 9. Transition Issues in Bulk

Transition multiple issues to a different status based on a condition.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.issue.Issue

import com.atlassian.jira.issue.search.SearchProvider

import com.atlassian.jira.web.bean.PagerFilter
import com.atlassian.jira.workflow.TransitionOptions

def searchService = ComponentAccessor.getComponent(SearchProvider)

def issueService = ComponentAccessor.getIssueService()

def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

def query = "project = TEST AND status = 'Open'"

def parseResult = searchService.parseQuery(user, query)

def results = searchService.search(parseResult.query, user,


PagerFilter.getUnlimitedFilter())

results.getIssues().each { issue ->

def transitionInput = new IssueService.TransitionValidationResult(issue.getKey(), 31,


user) // 31 is the ID for the transition action

def transitionResult = issueService.transition(user, transitionInput, new


TransitionOptions.Builder().skipPermissions().build())

if (transitionResult.isValid()) {

issueService.transition(user, transitionResult)

```

### 10. Setting Security Levels on Issues

Automatically set security levels on issues based on certain conditions.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.security.IssueSecurityLevelManager

def issueManager = ComponentAccessor.getIssueManager()

def securityLevelManager = ComponentAccessor.getIssueSecurityLevelManager()

def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

def issue = issueManager.getIssueObject("TEST-1")

def securityLevel = securityLevelManager.getSecurityLevel(10000) // ID of the security


level

if (issue.getPriority().getName() == "High") {

MutableIssue mutableIssue = issueManager.getIssueObject(issue.id)

mutableIssue.setSecurityLevelId(securityLevel.id)

issueManager.updateIssue(user, mutableIssue, EventDispatchOption.ISSUE_UPDATED,


false)

```

These examples demonstrate the versatility of ScriptRunner in Jira, allowing you to


automate complex workflows and customize your Jira instance to fit your organization's
needs. As always, ensure thorough testing in a staging environment before applying
these scripts in production.

Certainly! Here are more advanced ScriptRunner examples to help you further automate
and extend your Jira workflows:

### 11. Enforcing Field Validation

Ensure a custom field is filled out before transitioning an issue.


```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.opensymphony.workflow.InvalidInputException

def customFieldManager = ComponentAccessor.getCustomFieldManager()

def issueManager = ComponentAccessor.getIssueManager()

def customField =
customFieldManager.getCustomFieldObjectByName("CustomFieldName")

def issue = issueManager.getIssueObject("TEST-1")

def fieldValue = issue.getCustomFieldValue(customField)

if (!fieldValue) {

throw new InvalidInputException("Custom field must be filled before transitioning.")

```

### 12. Auto-Close Issues After a Period

Automatically close issues that have been in a specific status for more than a certain
number of days.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.issue.search.SearchProvider

import com.atlassian.jira.web.bean.PagerFilter

import com.atlassian.jira.bc.issue.IssueService

import com.atlassian.jira.bc.issue.search.SearchService
import com.atlassian.jira.datetime.JiraDateUtils

def searchService = ComponentAccessor.getComponent(SearchProvider)

def issueService = ComponentAccessor.getIssueService()

def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

def query = "project = TEST AND status = 'Resolved' AND resolved <= -7d" // JQL for
issues resolved more than 7 days ago

def parseResult = searchService.parseQuery(user, query)

def results = searchService.search(parseResult.query, user,


PagerFilter.getUnlimitedFilter())

results.getIssues().each { issue ->

def transitionInput = new IssueService.TransitionValidationResult(issue.getKey(), 31,


user) // 31 is the ID for the transition action to close

def transitionResult = issueService.transition(user, transitionInput)

if (transitionResult.isValid()) {

issueService.transition(user, transitionResult)

```

### 13. Linking Related Issues

Link issues together based on custom field values.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.issue.link.IssueLinkManager

import com.atlassian.jira.issue.CustomFieldManager
def issueManager = ComponentAccessor.getIssueManager()

def customFieldManager = ComponentAccessor.getCustomFieldManager()

def issueLinkManager = ComponentAccessor.getIssueLinkManager()

def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

def customField =
customFieldManager.getCustomFieldObjectByName("RelatedIssueKey")

def issue = issueManager.getIssueObject("TEST-1")

def relatedIssueKey = issue.getCustomFieldValue(customField)

if (relatedIssueKey) {

def relatedIssue = issueManager.getIssueObject(relatedIssueKey.toString())

if (relatedIssue) {

issueLinkManager.createIssueLink(issue.id, relatedIssue.id, 10000, 1, user) //


10000 is the link type ID for "Relates"

```

### 14. Setting Due Dates Based on Priority

Automatically set due dates for issues based on their priority.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.issue.MutableIssue

import java.time.LocalDate
def issueManager = ComponentAccessor.getIssueManager()

def issue = issueManager.getIssueObject("TEST-1")

def today = LocalDate.now()

MutableIssue mutableIssue = issueManager.getIssueObject(issue.id)

switch (issue.getPriority().getName()) {

case "Highest":

mutableIssue.setDueDate(Date.from(today.plusDays(1).atStartOfDay(ZoneId.systemDef
ault()).toInstant()))

break

case "High":

mutableIssue.setDueDate(Date.from(today.plusDays(3).atStartOfDay(ZoneId.systemDef
ault()).toInstant()))

break

case "Medium":

mutableIssue.setDueDate(Date.from(today.plusDays(7).atStartOfDay(ZoneId.systemDef
ault()).toInstant()))

break

case "Low":

mutableIssue.setDueDate(Date.from(today.plusDays(14).atStartOfDay(ZoneId.systemDe
fault()).toInstant()))

break

case "Lowest":
mutableIssue.setDueDate(Date.from(today.plusDays(30).atStartOfDay(ZoneId.systemDe
fault()).toInstant()))

break

issueManager.updateIssue(ComponentAccessor.getJiraAuthenticationContext().getLogg
edInUser(), mutableIssue, EventDispatchOption.ISSUE_UPDATED, false)

```

### 15. Escalate to Different Project

Automatically clone and escalate issues to another project if they meet certain criteria.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.issue.IssueFactory

import com.atlassian.jira.issue.MutableIssue

import com.atlassian.jira.issue.link.IssueLinkManager

def issueManager = ComponentAccessor.getIssueManager()

def issueFactory = ComponentAccessor.getIssueFactory()

def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

def issueLinkManager = ComponentAccessor.getIssueLinkManager()

def issue = issueManager.getIssueObject("TEST-1")

if (issue.getPriority().getName() == "Critical") {

MutableIssue clone = issueFactory.cloneIssue(issue)

clone.setProjectId(10200) // Target project ID


clone.setIssueTypeId("10001") // Target issue type ID

clone.setSummary("Escalated: " + issue.getSummary())

clone.setReporter(user)

clone.store()

issueManager.createIssue(user, clone)

issueLinkManager.createIssueLink(issue.id, clone.id, 10001, 1, user) // 10001 is the


link type ID for "Escalates"

```

### 16. Custom Workflow Validators

Add custom validators to workflows to enforce business rules.

```groovy

import com.opensymphony.workflow.InvalidInputException

import com.atlassian.jira.component.ComponentAccessor

def customFieldManager = ComponentAccessor.getCustomFieldManager()

def issueManager = ComponentAccessor.getIssueManager()

def customField = customFieldManager.getCustomFieldObjectByName("Approval")

def issue = issueManager.getIssueObject("TEST-1")

def approvalValue = issue.getCustomFieldValue(customField)

if (!approvalValue || approvalValue.toString() != "Approved") {

throw new InvalidInputException("Issue must be approved before transitioning.")


}

```

### 17. Generate and Attach PDF Report

Generate a PDF report for an issue and attach it to the issue.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.issue.AttachmentManager

import com.atlassian.jira.issue.MutableIssue

import org.apache.pdfbox.pdmodel.PDDocument

import org.apache.pdfbox.pdmodel.PDPage

import org.apache.pdfbox.pdmodel.PDPageContentStream

import org.apache.pdfbox.pdmodel.font.PDType1Font

def issueManager = ComponentAccessor.getIssueManager()

def attachmentManager = ComponentAccessor.getAttachmentManager()

def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

MutableIssue issue = issueManager.getIssueObject("TEST-1")

PDDocument document = new PDDocument()

PDPage page = new PDPage()

document.addPage(page)

PDPageContentStream contentStream = new PDPageContentStream(document, page)

contentStream.setFont(PDType1Font.HELVETICA, 12)
contentStream.beginText()

contentStream.newLineAtOffset(100, 700)

contentStream.showText("Issue Key: " + issue.getKey())

contentStream.newLineAtOffset(0, -20)

contentStream.showText("Summary: " + issue.getSummary())

contentStream.endText()

contentStream.close()

def tempFile = File.createTempFile("issue-report", ".pdf")

document.save(tempFile)

document.close()

attachmentManager.createAttachment(tempFile, "issue-report.pdf", "application/pdf",


user, issue, null, new Date())

tempFile.delete()

```

### 18. Dynamic Priority Adjustment

Adjust issue priority based on custom logic involving multiple fields.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.issue.MutableIssue

def issueManager = ComponentAccessor.getIssueManager()

def constantsManager = ComponentAccessor.getConstantsManager()


def issue = issueManager.getIssueObject("TEST-1")

def priority = constantsManager.getPriorityObject(issue.priority.id)

def urgency =
issue.getCustomFieldValue(ComponentAccessor.getCustomFieldManager().getCustomFi
eldObjectByName("Urgency"))

def impact =
issue.getCustomFieldValue(ComponentAccessor.getCustomFieldManager().getCustomFi
eldObjectByName("Impact"))

if (urgency == "High" && impact == "High") {

priority = constantsManager.getPriorityObject("1") // Highest

} else if (urgency == "High" || impact == "High") {

priority = constantsManager.getPriorityObject("2") // High

} else {

priority = constantsManager.getPriorityObject("3") // Medium

MutableIssue mutableIssue = issueManager.getIssueObject(issue.id)

mutableIssue.setPriority(priority)

issueManager.updateIssue(ComponentAccessor.getJiraAuthenticationContext().getLogg
edInUser(), mutableIssue, EventDispatchOption.ISSUE_UPDATED, false)

```

### 19. Automatically Watch Issues

Automatically add watchers to an issue based on custom field values.

```groovy

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.watchers.WatcherManager

def issue

Sure, here are additional advanced ScriptRunner examples for Jira:

### 19. Automatically Watch Issues (Continued)

Automatically add watchers to an issue based on custom field values.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.issue.watchers.WatcherManager

def issueManager = ComponentAccessor.getIssueManager()

def customFieldManager = ComponentAccessor.getCustomFieldManager()

def watcherManager = ComponentAccessor.getWatcherManager()

def userManager = ComponentAccessor.getUserManager()

def issue = issueManager.getIssueObject("TEST-1")

def customField = customFieldManager.getCustomFieldObjectByName("Watchers")

def watcherUsernames = issue.getCustomFieldValue(customField) as List<String>

watcherUsernames?.each { username ->

def user = userManager.getUserByName(username)

if (user) {

watcherManager.startWatching(user, issue)

}
```

### 20. Custom Scripted Conditions

Condition to check if a user belongs to a specific group before allowing a transition.

```groovy

import com.atlassian.jira.component.ComponentAccessor

def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

def groupManager = ComponentAccessor.getGroupManager()

def groupName = "jira-administrators"

def group = groupManager.getGroup(groupName)

if (groupManager.isUserInGroup(user, group)) {

return true

} else {

return false

```

### 21. Sending Slack Notifications

Send a notification to a Slack channel when an issue is updated.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import groovy.json.JsonBuilder
import groovyx.net.http.RESTClient

def issueManager = ComponentAccessor.getIssueManager()

def issue = issueManager.getIssueObject("TEST-1")

def slackWebhookUrl = "https://hooks.slack.com/services/your/slack/webhook/url"

def payload = [

text: "Issue ${issue.key} has been updated. Summary: ${issue.summary}",

username: "JiraBot",

icon_emoji: ":jira:"

def restClient = new RESTClient(slackWebhookUrl)

restClient.post(

body: new JsonBuilder(payload).toString(),

requestContentType: 'application/json'

```

### 22. Reopening Closed Issues

Automatically reopen issues if a comment is added after they are closed.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.event.issue.IssueEvent
def issueManager = ComponentAccessor.getIssueManager()

def issueService = ComponentAccessor.getIssueService()

def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

IssueEvent issueEvent = event as IssueEvent

def issue = issueEvent.issue

if (issue.getStatus().name == "Closed" && issueEvent.eventTypeId ==


EventType.ISSUE_COMMENTED_ID) {

def transitionValidationResult = issueService.validateTransition(user, issue.id, 3, new


IssueInputParametersImpl()) // 3 is the transition ID for reopen

if (transitionValidationResult.isValid()) {

issueService.transition(user, transitionValidationResult)

```

### 23. Assign Issues Based on Round-Robin

Automatically assign issues to a team in a round-robin fashion.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.issue.MutableIssue

def issueManager = ComponentAccessor.getIssueManager()

def userManager = ComponentAccessor.getUserManager()

def projectManager = ComponentAccessor.getProjectManager()


def customFieldManager = ComponentAccessor.getCustomFieldManager()

def issue = issueManager.getIssueObject("TEST-1")

def project = projectManager.getProjectObj(issue.getProjectId())

def assigneeUsernames = ["user1", "user2", "user3"]

def customField = customFieldManager.getCustomFieldObjectByName("Last Assignee")

def lastAssignee = project.getCustomFieldValue(customField) as String

def nextAssignee = assigneeUsernames[(assigneeUsernames.indexOf(lastAssignee) + 1)


% assigneeUsernames.size()]

def user = userManager.getUserByKey(nextAssignee)

issue.setAssignee(user)

issue.store()

project.setCustomFieldValue(customField, nextAssignee)

```

### 24. Synchronizing Issue Data with External System

Synchronize issue data with an external system via REST API.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import groovy.json.JsonBuilder

import groovyx.net.http.RESTClient
def issueManager = ComponentAccessor.getIssueManager()

def issue = issueManager.getIssueObject("TEST-1")

def externalSystemUrl = "https://external-system/api/issues"

def payload = [

issueKey: issue.key,

summary: issue.summary,

description: issue.description,

status: issue.getStatus().getName()

def restClient = new RESTClient(externalSystemUrl)

restClient.post(

body: new JsonBuilder(payload).toString(),

requestContentType: 'application/json'

```

### 25. Validating Issue Fields on Transition

Ensure specific fields meet criteria before allowing a transition.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.opensymphony.workflow.InvalidInputException

def issueManager = ComponentAccessor.getIssueManager()

def customFieldManager = ComponentAccessor.getCustomFieldManager()


def issue = issueManager.getIssueObject("TEST-1")

def customField =
customFieldManager.getCustomFieldObjectByName("CustomFieldName")

def fieldValue = issue.getCustomFieldValue(customField)

if (!fieldValue || fieldValue.size() < 5) {

throw new InvalidInputException("Custom field must be at least 5 characters long


before transitioning.")

```

### 26. Custom Email Notifications

Send custom email notifications based on issue events.

```groovy

import com.atlassian.mail.server.SMTPMailServer

import com.atlassian.mail.Email

import com.atlassian.jira.component.ComponentAccessor

def mailServer =
ComponentAccessor.getMailServerManager().getDefaultSMTPMailServer()

def issueManager = ComponentAccessor.getIssueManager()

if (mailServer) {

Absolutely, here are additional ScriptRunner examples for further automation and
customization in Jira:
### 26. Custom Email Notifications (Continued)

Send custom email notifications based on issue events.

```groovy

import com.atlassian.mail.Email

import com.atlassian.mail.server.SMTPMailServer

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.issue.Issue

def mailServer =
ComponentAccessor.getMailServerManager().getDefaultSMTPMailServer()

def issueManager = ComponentAccessor.getIssueManager()

def issue = issueManager.getIssueObject("TEST-1")

if (mailServer) {

def emailAddr = issue.getReporter().getEmailAddress()

def email = new Email(emailAddr)

email.setSubject("Issue Updated: ${issue.getKey()}")

email.setBody("The issue ${issue.getKey()} has been updated. Please review the


changes.")

mailServer.send(email)

} else {

log.error("No SMTP mail server configured")

```

### 27. Auto-Create Linked Issues in Another Project


Automatically create a linked issue in another project when an issue is created.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.issue.IssueInputParametersImpl

import com.atlassian.jira.issue.link.IssueLinkManager

def issueManager = ComponentAccessor.getIssueManager()

def issueService = ComponentAccessor.getIssueService()

def issueLinkManager = ComponentAccessor.getIssueLinkManager()

def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

def issue = issueManager.getIssueObject("TEST-1")

def projectKey = "OTHERPROJECT"

def issueTypeId = "10001" // Issue type ID for the new issue

def issueInputParameters = new IssueInputParametersImpl()

issueInputParameters.setProjectKey(projectKey)

issueInputParameters.setIssueTypeId(issueTypeId)

issueInputParameters.setSummary("Linked issue for: " + issue.getSummary())

issueInputParameters.setReporterId(user.key)

issueInputParameters.setDescription("This issue is linked to " + issue.getKey())

def validationResult = issueService.validateCreate(user, issueInputParameters)

if (validationResult.isValid()) {

def createResult = issueService.create(user, validationResult)

if (createResult.isValid()) {
issueLinkManager.createIssueLink(issue.id, createResult.issue.id, 10000, 1, user) //
10000 is the link type ID for "Relates"

```

### 28. Enforcing Sub-Task Closure Before Parent Closure

Ensure all sub-tasks are closed before allowing the parent issue to be closed.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.issue.Issue

import com.opensymphony.workflow.InvalidInputException

def issueManager = ComponentAccessor.getIssueManager()

def subTaskManager = ComponentAccessor.getSubTaskManager()

def issue = issueManager.getIssueObject("TEST-1")

if (issue.isSubTask()) {

return

def subTasks = subTaskManager.getSubTaskObjects(issue)

def openSubTasks = subTasks.findAll { it.getStatus().getName() != "Closed" }

if (openSubTasks) {
throw new InvalidInputException("All sub-tasks must be closed before closing the
parent issue.")

```

### 29. Dynamic Field Update Based on Linked Issue Status

Update a custom field based on the status of linked issues.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.issue.link.IssueLinkManager

import com.atlassian.jira.issue.CustomFieldManager

import com.atlassian.jira.issue.MutableIssue

def issueManager = ComponentAccessor.getIssueManager()

def issueLinkManager = ComponentAccessor.getIssueLinkManager()

def customFieldManager = ComponentAccessor.getCustomFieldManager()

def issue = issueManager.getIssueObject("TEST-1")

def linkedIssues = issueLinkManager.getOutwardLinks(issue.id).collect {


it.destinationObject }

def linkedIssuesStatus = linkedIssues*.getStatus().collect { it.getName() }

def customField =
customFieldManager.getCustomFieldObjectByName("LinkedIssuesStatus")

def linkedIssuesStatusStr = linkedIssuesStatus.join(", ")

MutableIssue mutableIssue = issueManager.getIssueObject(issue.id)

mutableIssue.setCustomFieldValue(customField, linkedIssuesStatusStr)
issueManager.updateIssue(ComponentAccessor.getJiraAuthenticationContext().getLogg
edInUser(), mutableIssue, EventDispatchOption.DO_NOT_DISPATCH, false)

```

### 30. Auto-Assign Based on Components

Automatically assign issues based on the components selected.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.issue.MutableIssue

import com.atlassian.jira.project.ProjectComponent

def issueManager = ComponentAccessor.getIssueManager()

def userManager = ComponentAccessor.getUserManager()

def componentManager = ComponentAccessor.getProjectComponentManager()

def issue = issueManager.getIssueObject("TEST-1")

def components = issue.getComponentObjects()

def userToAssign

components.each { ProjectComponent component ->

if (component.getName() == "Database") {

userToAssign = userManager.getUserByKey("database_user")

} else if (component.getName() == "UI") {

userToAssign = userManager.getUserByKey("ui_user")

}
if (userToAssign) {

MutableIssue mutableIssue = issueManager.getIssueObject(issue.id)

mutableIssue.setAssignee(userToAssign)

issueManager.updateIssue(ComponentAccessor.getJiraAuthenticationContext().getLogg
edInUser(), mutableIssue, EventDispatchOption.DO_NOT_DISPATCH, false)

```

### 31. Setting Issue Priority Based on Linked Bug Severity

Set issue priority based on the severity of linked bug issues.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.issue.Issue

import com.atlassian.jira.issue.link.IssueLinkManager

import com.atlassian.jira.issue.MutableIssue

def issueManager = ComponentAccessor.getIssueManager()

def issueLinkManager = ComponentAccessor.getIssueLinkManager()

def constantsManager = ComponentAccessor.getConstantsManager()

def issue = issueManager.getIssueObject("TEST-1")

def linkedIssues = issueLinkManager.getOutwardLinks(issue.id).collect {


it.destinationObject }

def highestSeverity = linkedIssues.find { it.getIssueType().getName() == "Bug"


}?.getPriority()?.getName()
def priority

if (highestSeverity == "Blocker") {

priority = constantsManager.getPriorityObject("1") // Highest

} else if (highestSeverity == "Critical") {

priority = constantsManager.getPriorityObject("2") // High

if (priority) {

MutableIssue mutableIssue = issueManager.getIssueObject(issue.id)

mutableIssue.setPriority(priority)

issueManager.updateIssue(ComponentAccessor.getJiraAuthenticationContext().getLogg
edInUser(), mutableIssue, EventDispatchOption.DO_NOT_DISPATCH, false)

```

### 32. Notifying on Issue Creation in Specific Projects

Send an email notification to a specific group when an issue is created in a specific


project.

```groovy

import com.atlassian.mail.Email

import com.atlassian.mail.server.SMTPMailServer

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.issue.Issue
def mailServer =
ComponentAccessor.getMailServerManager().getDefaultSMTPMailServer()

def issueManager = ComponentAccessor.getIssueManager()

def groupManager = ComponentAccessor.getGroupManager()

def userManager = ComponentAccessor.getUserManager()

def issue = issueManager.getIssueObject("TEST-1")

if (mailServer && issue.getProjectObject().getKey() == "SPECIALPROJECT") {

def group = groupManager.getGroup("special-group")

def emailAddresses = groupManager.getUsersInGroup(group).collect {


it.getEmailAddress() }.join(",")

def email = new Email(emailAddresses)

email.setSubject("New Issue Created: ${issue.getKey()}")

email.setBody("A new issue ${issue.getKey()} has been created in project


SPECIALPROJECT. Summary: ${issue.getSummary()}")

mailServer.send(email)

```

### 33. Triggering Builds on CI Server

Trigger a build on a CI server (e.g., Jenkins) when an issue transitions.

```groovy

import groovyx.net.http.RESTClient

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.issue.Issue
def issueManager = ComponentAccessor.getIssueManager()

def issue = issueManager.getIssueObject("TEST-1")

def ciServerUrl = "http://ci-server/job/trigger-build"

def apiToken = "your-api-token"

def restClient = new RESTClient(ciServerUrl)

def response = restClient.post(

headers: ['Authorization': "Bearer ${apiToken}"],

body: [issueKey: issue.getKey()],

requestContentType: 'application/json'

if (response.status != 200) {

log.error("Failed to trigger CI build: ${response.status}")

```

### 34. Generate and Attach CSV Report

Generate a CSV report for an issue and attach it to the issue.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.issue.AttachmentManager

import com.atlassian.jira.issue.MutableIssue

def issueManager = ComponentAccessor.getIssueManager()

def attachmentManager = ComponentAccessor.getAttachmentManager()


def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

def issue = issueManager.getIssueObject("TEST-1")

def csvContent = "Key,Summary,Status\n

Certainly! Here are even more advanced ScriptRunner examples for Jira:

### 34. Generate and Attach CSV Report (Continued)

Generate a CSV report for an issue and attach it to the issue.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.issue.AttachmentManager

import com.atlassian.jira.issue.IssueManager

import com.atlassian.jira.issue.MutableIssue

import com.atlassian.jira.user.ApplicationUser

def issueManager = ComponentAccessor.getIssueManager()

def attachmentManager = ComponentAccessor.getAttachmentManager()

def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

def issue = issueManager.getIssueObject("TEST-1")

def csvContent =
"Key,Summary,Status\n${issue.key},${issue.summary},${issue.status.name}\n"

def tempFile = File.createTempFile("issue-report", ".csv")

tempFile.write(csvContent)
attachmentManager.createAttachment(tempFile, "issue-report.csv", "text/csv", user,
issue, null, new Date())

tempFile.delete()

```

### 35. Bulk Update Issues

Bulk update the description of all issues in a project.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.issue.search.SearchProvider

import com.atlassian.jira.bc.issue.search.SearchService

import com.atlassian.jira.web.bean.PagerFilter

import com.atlassian.jira.issue.IssueManager

import com.atlassian.jira.issue.MutableIssue

def searchService = ComponentAccessor.getComponent(SearchService)

def searchProvider = ComponentAccessor.getComponent(SearchProvider)

def issueManager = ComponentAccessor.getIssueManager()

def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

def jqlQuery = "project = TEST"

def parseResult = searchService.parseQuery(user, jqlQuery)

def searchResults = searchService.search(user, parseResult.query,


PagerFilter.getUnlimitedFilter())

searchResults.issues.each { documentIssue ->


MutableIssue issue = issueManager.getIssueObject(documentIssue.id)

issue.setDescription("Updated description")

issueManager.updateIssue(user, issue, EventDispatchOption.ISSUE_UPDATED, false)

```

### 36. Automatically Close Issues Based on Comment Content

Automatically close issues if a comment contains a specific keyword.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.event.issue.IssueEvent

import com.atlassian.jira.bc.issue.IssueService

def issueService = ComponentAccessor.getIssueService()

def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

IssueEvent issueEvent = event as IssueEvent

def issue = issueEvent.issue

if (issueEvent.eventTypeId == EventType.ISSUE_COMMENTED_ID) {

def comment = issueEvent.comment

if (comment && comment.body.contains("close issue")) {

def transitionValidationResult = issueService.validateTransition(user, issue.id, 5,


new IssueInputParametersImpl()) // 5 is the transition ID for close

if (transitionValidationResult.isValid()) {

issueService.transition(user, transitionValidationResult)
}

```

### 37. Calculate and Set Due Date Based on Custom Field

Calculate and set the due date based on a custom field value.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.issue.MutableIssue

def issueManager = ComponentAccessor.getIssueManager()

def customFieldManager = ComponentAccessor.getCustomFieldManager()

def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

def issue = issueManager.getIssueObject("TEST-1")

def customField = customFieldManager.getCustomFieldObjectByName("Time to


Complete (days)")

def daysToComplete = issue.getCustomFieldValue(customField) as Integer

if (daysToComplete != null) {

def dueDate = new Date() + daysToComplete

issue.setDueDate(dueDate)

issueManager.updateIssue(user, issue, EventDispatchOption.DO_NOT_DISPATCH,


false)

}
```

### 38. Automatically Set Labels Based on Summary

Automatically set issue labels based on keywords in the summary.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.issue.MutableIssue

def issueManager = ComponentAccessor.getIssueManager()

def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

def issue = issueManager.getIssueObject("TEST-1")

def summary = issue.getSummary()

def labels = issue.getLabels()

if (summary.contains("urgent")) {

labels.add("urgent")

if (summary.contains("bug")) {

labels.add("bug")

issue.setLabels(labels)

issueManager.updateIssue(user, issue, EventDispatchOption.DO_NOT_DISPATCH, false)

```
### 39. Sync Custom Field Value with External System

Sync a custom field value with an external system via REST API.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import groovy.json.JsonBuilder

import groovyx.net.http.RESTClient

def issueManager = ComponentAccessor.getIssueManager()

def customFieldManager = ComponentAccessor.getCustomFieldManager()

def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

def issue = issueManager.getIssueObject("TEST-1")

def customField = customFieldManager.getCustomFieldObjectByName("External ID")

def externalId = issue.getCustomFieldValue(customField)

def externalSystemUrl = "https://external-system/api/update"

def payload = [

issueKey: issue.key,

externalId: externalId

def restClient = new RESTClient(externalSystemUrl)

def response = restClient.post(

body: new JsonBuilder(payload).toString(),

requestContentType: 'application/json'

)
if (response.status != 200) {

log.error("Failed to sync with external system: ${response.status}")

```

### 40. Auto-Transition Based on Linked Issues

Auto-transition an issue when all linked issues reach a certain status.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.issue.link.IssueLinkManager

import com.atlassian.jira.issue.Issue

import com.atlassian.jira.bc.issue.IssueService

def issueManager = ComponentAccessor.getIssueManager()

def issueLinkManager = ComponentAccessor.getIssueLinkManager()

def issueService = ComponentAccessor.getIssueService()

def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

def issue = issueManager.getIssueObject("TEST-1")

def linkedIssues = issueLinkManager.getInwardLinks(issue.id).collect { it.sourceObject }

def allResolved = linkedIssues.every { it.getStatus().getName() == "Resolved" }

if (allResolved) {

def transitionValidationResult = issueService.validateTransition(user, issue.id, 31, new


IssueInputParametersImpl()) // 31 is the transition ID for close
if (transitionValidationResult.isValid()) {

issueService.transition(user, transitionValidationResult)

```

### 41. Bulk Clone Issues

Bulk clone issues in a project and link them to the original issues.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.issue.IssueFactory

import com.atlassian.jira.issue.MutableIssue

import com.atlassian.jira.issue.link.IssueLinkManager

import com.atlassian.jira.bc.issue.IssueService

import com.atlassian.jira.issue.IssueInputParametersImpl

def issueManager = ComponentAccessor.getIssueManager()

def issueService = ComponentAccessor.getIssueService()

def issueFactory = ComponentAccessor.getIssueFactory()

def issueLinkManager = ComponentAccessor.getIssueLinkManager()

def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

def jqlQuery = "project = TEST"

def searchService = ComponentAccessor.getComponent(SearchService)

def parseResult = searchService.parseQuery(user, jqlQuery)


def searchResults = searchService.search(user, parseResult.query,
PagerFilter.getUnlimitedFilter())

searchResults.issues.each { issueDocument ->

def issue = issueManager.getIssueObject(issueDocument.id)

def clonedIssue = issueFactory.cloneIssue(issue)

clonedIssue.setProjectId(issue.getProjectObject().getId())

clonedIssue.setIssueTypeId(issue.getIssueTypeObject().getId())

clonedIssue.setSummary("Clone of " + issue.getSummary())

clonedIssue.setReporter(user)

def inputParams = new IssueInputParametersImpl(clonedIssue)

def createResult = issueService.create(user, inputParams)

if (createResult.isValid()) {

issueLinkManager.createIssueLink(issue.id, createResult.issue.id, 10000, 1, user) //


10000 is the link type ID for "Relates"

```

These examples should give you a broader range of automation and customization
options for your Jira environment using ScriptRunner. Feel free to adapt and combine
these scripts according to your specific requirements.

Certainly! Here are even more advanced ScriptRunner examples for Jira:

### 42. Update Issue Custom Field Based on Linked Issue Field

Update a custom field in an issue based on a field value from linked issues.
```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.issue.link.IssueLinkManager

import com.atlassian.jira.issue.CustomFieldManager

import com.atlassian.jira.issue.MutableIssue

def issueManager = ComponentAccessor.getIssueManager()

def issueLinkManager = ComponentAccessor.getIssueLinkManager()

def customFieldManager = ComponentAccessor.getCustomFieldManager()

def issue = issueManager.getIssueObject("TEST-1")

def linkedIssues = issueLinkManager.getOutwardLinks(issue.id).collect {


it.destinationObject }

def linkedPriorities = linkedIssues*.getPriority().collect { it.name }

def highestPriority = linkedPriorities.sort { it }.first()

def customField = customFieldManager.getCustomFieldObjectByName("Linked Issue


Priority")

MutableIssue mutableIssue = issueManager.getIssueObject(issue.id)

mutableIssue.setCustomFieldValue(customField, highestPriority)

issueManager.updateIssue(ComponentAccessor.getJiraAuthenticationContext().getLogg
edInUser(), mutableIssue, EventDispatchOption.DO_NOT_DISPATCH, false)

```

### 43. Restrict Issue Transition Based on Time of Day

Restrict issue transitions to business hours only.


```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.opensymphony.workflow.InvalidInputException

def currentTime = new Date().format("HH:mm", TimeZone.getTimeZone("UTC"))

def startTime = "09:00"

def endTime = "17:00"

if (currentTime < startTime || currentTime > endTime) {

throw new InvalidInputException("Issue transitions are only allowed during business


hours (09:00 - 17:00 UTC).")

```

### 44. Copy Comments from Linked Issues

Copy comments from linked issues to the current issue.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.issue.comments.CommentManager

def issueManager = ComponentAccessor.getIssueManager()

def issueLinkManager = ComponentAccessor.getIssueLinkManager()

def commentManager = ComponentAccessor.getCommentManager()

def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

def issue = issueManager.getIssueObject("TEST-1")


def linkedIssues = issueLinkManager.getInwardLinks(issue.id).collect { it.sourceObject }

linkedIssues.each { linkedIssue ->

def comments = commentManager.getComments(linkedIssue)

comments.each { comment ->

commentManager.create(issue, user, "Copied from ${linkedIssue.key}:


${comment.body}", false)

```

### 45. Automatically Assign Issue to Reporter of Linked Issue

Automatically assign an issue to the reporter of a linked issue.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.issue.link.IssueLinkManager

import com.atlassian.jira.issue.MutableIssue

def issueManager = ComponentAccessor.getIssueManager()

def issueLinkManager = ComponentAccessor.getIssueLinkManager()

def userManager = ComponentAccessor.getUserManager()

def issue = issueManager.getIssueObject("TEST-1")

def linkedIssues = issueLinkManager.getOutwardLinks(issue.id).collect {


it.destinationObject }
def reporter = linkedIssues?.first()?.getReporter()

if (reporter) {

MutableIssue mutableIssue = issueManager.getIssueObject(issue.id)

mutableIssue.setAssignee(reporter)

issueManager.updateIssue(ComponentAccessor.getJiraAuthenticationContext().getLogg
edInUser(), mutableIssue, EventDispatchOption.DO_NOT_DISPATCH, false)

```

### 46. Send Email Notification for Specific Label Addition

Send an email notification when a specific label is added to an issue.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.mail.Email

import com.atlassian.mail.server.SMTPMailServer

def mailServer =
ComponentAccessor.getMailServerManager().getDefaultSMTPMailServer()

def issueManager = ComponentAccessor.getIssueManager()

def userManager = ComponentAccessor.getUserManager()

def issue = issueManager.getIssueObject("TEST-1")

def labels = issue.getLabels()

if (labels.contains("important")) {

def emailAddr = issue.getReporter().getEmailAddress()


def email = new Email(emailAddr)

email.setSubject("Important Label Added to Issue: ${issue.key}")

email.setBody("The important label has been added to the issue ${issue.key}. Please
review it immediately.")

mailServer.send(email)

```

### 47. Calculate and Set SLA Breach Custom Field

Calculate SLA breach time and set it in a custom field.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.issue.MutableIssue

import com.atlassian.jira.issue.CustomFieldManager

import java.time.Duration

def issueManager = ComponentAccessor.getIssueManager()

def customFieldManager = ComponentAccessor.getCustomFieldManager()

def issue = issueManager.getIssueObject("TEST-1")

def slaStart = issue.getCreated()

def slaEnd = new Date() // Assuming this is the end of the SLA period

def slaDuration = Duration.between(slaStart.toInstant(), slaEnd.toInstant()).toHours()

def customField = customFieldManager.getCustomFieldObjectByName("SLA Breach


(hours)")
MutableIssue mutableIssue = issueManager.getIssueObject(issue.id)

mutableIssue.setCustomFieldValue(customField, slaDuration.toString())

issueManager.updateIssue(ComponentAccessor.getJiraAuthenticationContext().getLogg
edInUser(), mutableIssue, EventDispatchOption.DO_NOT_DISPATCH, false)

```

### 48. Create Sub-Tasks Automatically Based on Issue Type

Automatically create specific sub-tasks when an issue of a certain type is created.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.issue.IssueInputParametersImpl

import com.atlassian.jira.bc.issue.IssueService

import com.atlassian.jira.issue.MutableIssue

def issueManager = ComponentAccessor.getIssueManager()

def issueService = ComponentAccessor.getIssueService()

def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

def issue = issueManager.getIssueObject("TEST-1")

if (issue.issueType.name == "Story") {

["Design", "Development", "Testing"].each { subTaskSummary ->

def issueInputParameters = new IssueInputParametersImpl()

issueInputParameters.setProjectId(issue.getProjectObject().getId())

issueInputParameters.setIssueTypeId("5") // Assuming "5" is the issue type ID for


sub-task

issueInputParameters.setParentIssueId(issue.getId())
issueInputParameters.setSummary(subTaskSummary)

issueInput

Certainly! Here are even more advanced ScriptRunner examples for Jira:

### 48. Create Sub-Tasks Automatically Based on Issue Type (Continued)

Automatically create specific sub-tasks when an issue of a certain type is created.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.issue.IssueInputParametersImpl

import com.atlassian.jira.bc.issue.IssueService

import com.atlassian.jira.issue.MutableIssue

def issueManager = ComponentAccessor.getIssueManager()

def issueService = ComponentAccessor.getIssueService()

def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

def issue = issueManager.getIssueObject("TEST-1")

if (issue.issueType.name == "Story") {

["Design", "Development", "Testing"].each { subTaskSummary ->

def issueInputParameters = new IssueInputParametersImpl()

issueInputParameters.setProjectId(issue.getProjectObject().getId())

issueInputParameters.setIssueTypeId("5") // Assuming "5" is the issue type ID for


sub-task

issueInputParameters.setParentIssueId(issue.getId())

issueInputParameters.setSummary(subTaskSummary)

issueInputParameters.setReporterId(issue.reporterId)
def validationResult = issueService.validateSubTaskCreate(user,
issueInputParameters)

if (validationResult.isValid()) {

issueService.create(user, validationResult)

} else {

log.error("Failed to create sub-task: ${validationResult.errorCollection}")

```

### 49. Transition Linked Issues When Parent Issue Transitions

Automatically transition linked issues when the parent issue transitions.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.issue.link.IssueLinkManager

import com.atlassian.jira.bc.issue.IssueService

def issueManager = ComponentAccessor.getIssueManager()

def issueLinkManager = ComponentAccessor.getIssueLinkManager()

def issueService = ComponentAccessor.getIssueService()

def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

def issue = issueManager.getIssueObject("TEST-1")

def linkedIssues = issueLinkManager.getInwardLinks(issue.id).collect { it.sourceObject }


linkedIssues.each { linkedIssue ->

def transitionValidationResult = issueService.validateTransition(user, linkedIssue.id,


31, new IssueInputParametersImpl()) // 31 is the transition ID for close

if (transitionValidationResult.isValid()) {

issueService.transition(user, transitionValidationResult)

} else {

log.error("Failed to transition linked issue: ${linkedIssue.key}")

```

### 50. Set Issue Components Based on Custom Field

Set the issue components based on a custom field value.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.issue.MutableIssue

import com.atlassian.jira.project.ProjectComponent

def issueManager = ComponentAccessor.getIssueManager()

def customFieldManager = ComponentAccessor.getCustomFieldManager()

def componentManager = ComponentAccessor.getProjectComponentManager()

def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

def issue = issueManager.getIssueObject("TEST-1")


def customField = customFieldManager.getCustomFieldObjectByName("Component
Selector")

def selectedComponentName = issue.getCustomFieldValue(customField) as String

if (selectedComponentName) {

def projectComponents =
componentManager.getComponents(issue.getProjectObject().id)

def selectedComponent = projectComponents.find { it.name ==


selectedComponentName }

if (selectedComponent) {

issue.setComponent([selectedComponent] as Collection<ProjectComponent>)

issueManager.updateIssue(user, issue, EventDispatchOption.DO_NOT_DISPATCH,


false)

```

### 51. Sync Status Between Parent and Sub-Tasks

Automatically sync the status between a parent issue and its sub-tasks.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.issue.MutableIssue

import com.atlassian.jira.bc.issue.IssueService

import com.atlassian.jira.issue.link.IssueLinkManager

def issueManager = ComponentAccessor.getIssueManager()

def issueService = ComponentAccessor.getIssueService()


def issueLinkManager = ComponentAccessor.getIssueLinkManager()

def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

def issue = issueManager.getIssueObject("TEST-1")

if (issue.isSubTask()) {

def parentIssue = issue.getParentObject()

if (issue.status.name == "Done" && parentIssue.status.name != "Done") {

def transitionValidationResult = issueService.validateTransition(user,


parentIssue.id, 31, new IssueInputParametersImpl()) // 31 is the transition ID for Done

if (transitionValidationResult.isValid()) {

issueService.transition(user, transitionValidationResult)

} else {

def subTasks = issue.getSubTaskObjects()

if (issue.status.name == "Done") {

subTasks.each { subTask ->

if (subTask.status.name != "Done") {

def transitionValidationResult = issueService.validateTransition(user,


subTask.id, 31, new IssueInputParametersImpl()) // 31 is the transition ID for Done

if (transitionValidationResult.isValid()) {

issueService.transition(user, transitionValidationResult)

}
```

### 52. Automatically Watch Issue Based on Field Value

Automatically add a watcher to an issue based on a custom field value.

```groovy

import com.atlassian.jira.component.ComponentAccessor

def issueManager = ComponentAccessor.getIssueManager()

def customFieldManager = ComponentAccessor.getCustomFieldManager()

def watcherManager = ComponentAccessor.getWatcherManager()

def userManager = ComponentAccessor.getUserManager()

def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

def issue = issueManager.getIssueObject("TEST-1")

def customField = customFieldManager.getCustomFieldObjectByName("Watch User")

def userName = issue.getCustomFieldValue(customField) as String

if (userName) {

def userToWatch = userManager.getUserByName(userName)

if (userToWatch) {

watcherManager.startWatching(userToWatch, issue)

```

### 53. Prevent Issue Creation During Certain Times


Prevent issue creation during non-business hours.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.issue.IssueInputParameters

import com.opensymphony.workflow.InvalidInputException

def currentTime = new Date().format("HH:mm", TimeZone.getTimeZone("UTC"))

def startTime = "09:00"

def endTime = "17:00"

if (currentTime < startTime || currentTime > endTime) {

throw new InvalidInputException("Issue creation is only allowed during business


hours (09:00 - 17:00 UTC).")

def issueManager = ComponentAccessor.getIssueManager()

def issueService = ComponentAccessor.getIssueService()

def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

def issueInputParameters = issueService.getDefaultIssueInputParameters()

```

### 54. Sync Comments Between Linked Issues

Sync comments between linked issues.

```groovy

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.comments.CommentManager

def issueManager = ComponentAccessor.getIssueManager()

def issueLinkManager = ComponentAccessor.getIssueLinkManager()

def commentManager = ComponentAccessor.getCommentManager()

def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

def issue = issueManager.getIssueObject("TEST-1")

def linkedIssues = issueLinkManager.getInwardLinks(issue.id).collect { it.sourceObject }

def newCommentBody = "New comment on linked issues"

linkedIssues.each { linkedIssue ->

commentManager.create(linkedIssue, user, newCommentBody, false)

```

### 55. Automatically Create Linked Issue in Different Project

Automatically create a linked issue in a different project when an issue is created.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.issue.IssueInputParametersImpl

import com.atlassian.jira.bc.issue.IssueService

import com.atlassian.jira.issue.link.IssueLinkManager

def issueManager = ComponentAccessor.getIssueManager()

def issueService = ComponentAccessor.getIssueService()


def issueLinkManager = ComponentAccessor.getIssueLinkManager()

def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

def issue = issueManager.getIssueObject("TEST-1")

def projectKey = "OTHERPROJECT"

def issueTypeId = "10001" // Issue type ID for the new issue

def issueInputParameters = new IssueInputParametersImpl()

issueInputParameters.setProjectKey(projectKey)

issueInputParameters.setIssueTypeId(issueTypeId)

issueInputParameters.setSummary("Linked issue for: " + issue.getSummary())

issueInputParameters.setReporterId(user.key)

issueInputParameters.setDescription("This issue is linked to " + issue.getKey())

def validationResult = issueService.validateCreate(user, issueInputParameters)

if (validationResult.isValid()) {

def createResult = issueService.create(user, validationResult)

if (createResult.isValid()) {

issueLinkManager.createIssueLink(issue.id, createResult.issue.id, 10000, 1, user) //


10000 is the link type ID for "Relates"

```

### 56. Transition Issue Based on Custom Field Value

Transition an issue based on a specific custom field value.


```groovy

import com.atlassian.jira.component

Certainly! Here are more advanced ScriptRunner examples for Jira:

### 56. Transition Issue Based on Custom Field Value (Continued)

Transition an issue based on a specific custom field value.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.bc.issue.IssueService

import com.atlassian.jira.issue.IssueInputParametersImpl

def issueManager = ComponentAccessor.getIssueManager()

def customFieldManager = ComponentAccessor.getCustomFieldManager()

def issueService = ComponentAccessor.getIssueService()

def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

def issue = issueManager.getIssueObject("TEST-1")

def customField = customFieldManager.getCustomFieldObjectByName("Status Change


Trigger")

def triggerValue = issue.getCustomFieldValue(customField) as String

if (triggerValue == "Close") {

def transitionValidationResult = issueService.validateTransition(user, issue.id, 31, new


IssueInputParametersImpl()) // 31 is the transition ID for Close

if (transitionValidationResult.isValid()) {

issueService.transition(user, transitionValidationResult)
}

```

### 57. Calculate and Update Remaining Estimate

Calculate and update the remaining estimate based on work log entries.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.issue.worklog.WorklogManager

def issueManager = ComponentAccessor.getIssueManager()

def worklogManager = ComponentAccessor.getWorklogManager()

def issue = issueManager.getIssueObject("TEST-1")

def worklogs = worklogManager.getByIssue(issue)

def totalLoggedTime = worklogs.sum { it.getTimeSpent() } ?: 0

def originalEstimate = issue.getOriginalEstimate() ?: 0

def remainingEstimate = originalEstimate - totalLoggedTime

issue.setEstimate(remainingEstimate)

issueManager.updateIssue(ComponentAccessor.getJiraAuthenticationContext().getLogg
edInUser(), issue, EventDispatchOption.DO_NOT_DISPATCH, false)

```

### 58. Auto-Transition Based on Linked Issue Resolution


Automatically transition an issue when a linked issue is resolved.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.issue.link.IssueLinkManager

import com.atlassian.jira.bc.issue.IssueService

def issueManager = ComponentAccessor.getIssueManager()

def issueLinkManager = ComponentAccessor.getIssueLinkManager()

def issueService = ComponentAccessor.getIssueService()

def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

def issue = issueManager.getIssueObject("TEST-1")

def linkedIssues = issueLinkManager.getInwardLinks(issue.id).collect { it.sourceObject }

if (linkedIssues.every { it.resolution }) {

def transitionValidationResult = issueService.validateTransition(user, issue.id, 31, new


IssueInputParametersImpl()) // 31 is the transition ID for Close

if (transitionValidationResult.isValid()) {

issueService.transition(user, transitionValidationResult)

```

### 59. Send Weekly Summary Report via Email

Send a weekly summary report of issues via email.


```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.mail.Email

import com.atlassian.mail.server.SMTPMailServer

import com.atlassian.jira.issue.search.SearchProvider

import com.atlassian.jira.bc.issue.search.SearchService

import com.atlassian.jira.web.bean.PagerFilter

def mailServer =
ComponentAccessor.getMailServerManager().getDefaultSMTPMailServer()

def searchService = ComponentAccessor.getComponent(SearchService)

def searchProvider = ComponentAccessor.getComponent(SearchProvider)

def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

def jqlQuery = "project = TEST AND created >= -1w"

def parseResult = searchService.parseQuery(user, jqlQuery)

def searchResults = searchService.search(user, parseResult.query,


PagerFilter.getUnlimitedFilter())

def emailBody = "Weekly Summary Report:\n\n"

searchResults.issues.each { issue ->

emailBody += "Key: ${issue.key}, Summary: ${issue.summary}, Status:


${issue.status.name}\n"

def email = new Email("recipient@example.com")

email.setSubject("Weekly Jira Report")

email.setBody(emailBody)
mailServer.send(email)

```

### 60. Auto-Assign Issue Based on Component Lead

Automatically assign an issue to the component lead.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.issue.MutableIssue

def issueManager = ComponentAccessor.getIssueManager()

def componentManager = ComponentAccessor.getProjectComponentManager()

def userManager = ComponentAccessor.getUserManager()

def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

def issue = issueManager.getIssueObject("TEST-1")

def components = issue.getComponents()

if (components) {

def componentLead = components.first().getLead()

if (componentLead) {

issue.setAssignee(componentLead)

issueManager.updateIssue(user, issue, EventDispatchOption.DO_NOT_DISPATCH,


false)

```
### 61. Auto-Close Resolved Issues After 7 Days

Automatically close resolved issues after 7 days.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.bc.issue.IssueService

import java.time.Instant

import java.time.temporal.ChronoUnit

def issueManager = ComponentAccessor.getIssueManager()

def issueService = ComponentAccessor.getIssueService()

def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

def jqlQuery = "status = Resolved AND resolved <= -7d"

def searchService = ComponentAccessor.getComponent(SearchService)

def parseResult = searchService.parseQuery(user, jqlQuery)

def searchResults = searchService.search(user, parseResult.query,


PagerFilter.getUnlimitedFilter())

searchResults.issues.each { issue ->

def transitionValidationResult = issueService.validateTransition(user, issue.id, 31, new


IssueInputParametersImpl()) // 31 is the transition ID for Close

if (transitionValidationResult.isValid()) {

issueService.transition(user, transitionValidationResult)

}
```

### 62. Update Due Date Based on Priority

Update the due date based on the priority of the issue.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.issue.MutableIssue

def issueManager = ComponentAccessor.getIssueManager()

def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

def issue = issueManager.getIssueObject("TEST-1")

def priority = issue.getPriority().getName()

def dueDateOffset = [

"Highest": 1,

"High": 3,

"Medium": 5,

"Low": 7,

"Lowest": 10

def dueDate = new Date() + dueDateOffset[priority]

issue.setDueDate(dueDate)

issueManager.updateIssue(user, issue, EventDispatchOption.DO_NOT_DISPATCH, false)

```
### 63. Prevent Issue Deletion Based on Conditions

Prevent issue deletion if certain conditions are met.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import com.opensymphony.workflow.InvalidInputException

def issueManager = ComponentAccessor.getIssueManager()

def customFieldManager = ComponentAccessor.getCustomFieldManager()

def issue = issueManager.getIssueObject("TEST-1")

def customField = customFieldManager.getCustomFieldObjectByName("Prevent


Deletion")

def preventDeletion = issue.getCustomFieldValue(customField) as Boolean

if (preventDeletion) {

throw new InvalidInputException("Issue cannot be deleted due to custom field


setting.")

```

### 64. Set Issue Security Level Based on Issue Type

Automatically set the issue security level based on the issue type.

```groovy

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.MutableIssue

import com.atlassian.jira.security.JiraAuthenticationContext

def issueManager = ComponentAccessor.getIssueManager()

def securityLevelManager = ComponentAccessor.getIssueSecurityLevelManager()

def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

def issue = issueManager.getIssueObject("TEST-1")

def issueType = issue.getIssueType().getName()

def securityLevelName = issueType == "Bug" ? "Internal" : "Public"

def securityLevel =
securityLevelManager.getSecurityLevelByName(issue.getProjectObject().id,
securityLevelName)

issue.setSecurityLevelId(securityLevel.id)

issueManager.updateIssue(user, issue, EventDispatchOption.DO_NOT_DISPATCH, false)

```

### 65. Sync Issue Fields with External System

Sync certain issue fields with an external system using REST API.

```groovy

import com.atlassian.jira.component.ComponentAccessor

import groovy.json.JsonBuilder

import groovyx.net.http.RESTClient
def issueManager = ComponentAccessor.getIssueManager()

def customFieldManager = ComponentAccessor.getCustomFieldManager()

def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

def issue = issueManager.getIssueObject("TEST-1")

def customField = customFieldManager.getCustomFieldObjectByName("External System


ID")

def externalSystemId = issue.getCustomFieldValue(customField)

def externalSystemUrl = "https://external-system/api/update"

def payload = [

issueKey: issue.key,

externalSystemId: externalSystemId,

summary: issue.summary,

status: issue.status.name

def restClient = new RESTClient(externalSystemUrl)

def response = restClient.post(

body: new JsonBuilder(payload).

You might also like