Jelly Migration
Jelly was dropped in Jira 6.4. Everything that could be done in Jelly could also be done in ScriptRunner.
Jelly Escalation
Typically Jelly was used for transitioning issues from a JQL query. This can be done with an Escalation Service instead, which is easier and more flexible than writing your code.
A direct translation of the examples given on the old jelly documentation page follows, using both Escalation Service and code.
Making an Issue Inactive
Using an Escalation Service
In Code
If you want to do it code here’s how. It is rather long, mainly because of error handling around the transition.
You can set this up to run periodically by using a service.
When running any of these as a service, there is no authenticated user, so you cannot use ComponentAccessor.jiraAuthenticationContext
. Instead you should get a user by name, as in the first example.
import com.atlassian.jira.bc.JiraServiceContextImpl import com.atlassian.jira.bc.filter.SearchRequestService import com.atlassian.jira.bc.issue.search.SearchService import com.atlassian.jira.component.ComponentAccessor import com.atlassian.jira.issue.Issue import com.atlassian.jira.user.ApplicationUsers import com.atlassian.jira.web.bean.PagerFilter import com.atlassian.jira.workflow.JiraWorkflow import com.opensymphony.workflow.loader.ActionDescriptor import com.opensymphony.workflow.loader.StepDescriptor def searchService = ComponentAccessor.getComponent(SearchService) def searchRequestService = ComponentAccessor.getComponent(SearchRequestService) def userUtil = ComponentAccessor.getUserUtil() def issueService = ComponentAccessor.getIssueService() //////////////////////////// CONFIGURATION //////////////////////////// def workflowUser = "admin" // user to run the query and do the transition as def filterId = 10300 // filter ID def actionName = "Mark Inactive" // name of workflow action to execute def comment = """ This issue has not been updated for 5 business days. If you have an update, please use "Add Comments For Atlassian" action to let us know. If you need more time to gather information please let us know and we will 'freeze' this issue. If you have no other questions, please Close this issue. If no update is received in the next 5 business days, this issue will be automatically closed. Thank you, The Atlassian Support Team """ ///////////////////////////////////////////////////////////////////////// def user = userUtil.getUserByName(workflowUser) assert user // can't find the user specified def serviceContext = new JiraServiceContextImpl(user) def directoryUser = ApplicationUsers.toDirectoryUser(user) def searchRequest = searchRequestService.getFilter(serviceContext, filterId) assert searchRequest: "No search for ID: ${filterId} - check it exists and permissions for ${user.name}" def query = searchRequest.query def search = searchService.search(user, query, PagerFilter.getUnlimitedFilter()) def getActionIdFromName = { Issue issue, String name -> JiraWorkflow workflow = ComponentAccessor.getWorkflowManager().getWorkflow(issue) StepDescriptor step = workflow.getLinkedStep(issue.statusObject) def actions = step.getActions() actions.addAll(workflow.getDescriptor().getGlobalActions() ?: []) def action = actions.find { ActionDescriptor ad -> ad.name == name } action?.id } search.results.each { issue -> log.warn("Inactivating issue ${issue.key}") def issueInputParameters = issueService.newIssueInputParameters().setComment(comment) Integer actionId = getActionIdFromName(issue, actionName) if (actionId) { def validationResult = issueService.validateTransition(directoryUser, issue.id, actionId, issueInputParameters) if (validationResult.isValid()) { def issueResult = issueService.transition(directoryUser, validationResult) if (!issueResult.isValid()) { log.warn("Failed to transition subtask ${issue.key}, errors: ${issueResult.errorCollection}") } } else { log.warn("Could not transition subtask ${issue.key}, errors: ${validationResult.errorCollection}") } } else { log.info("No action: $actionName found for issue: ${issue.key}") } }
Attaching files
There was an undocumented tag for attaching files.
<AttachFile key="JRA-1" filepath="/attachment/file/location/on/server"/>
This can be accomplished in ScriptRunner using the following equivalent code:
import com.atlassian.jira.component.ComponentAccessor import com.atlassian.jira.issue.AttachmentManager import com.atlassian.jira.issue.attachment.CreateAttachmentParamsBean def attachmentManager = ComponentAccessor.getComponent(AttachmentManager) def user = ComponentAccessor.jiraAuthenticationContext.loggedInUser def issueManager = ComponentAccessor.issueManager //////////////////////////// CONFIGURATION //////////////////////////// def issue = issueManager.getIssueObject("JRA-333") def filepath = "C:/tmp/star.png" ///////////////////////////////////////////////////////////////////////// def file = new File(filepath) assert file.exists() && file.canRead(): "Can't read file at ${filepath}" def builder = new CreateAttachmentParamsBean.Builder(file, file.name, "application/octet-stream", user, issue) attachmentManager.createAttachment(builder.build())
Creating Issues
You could define a Jelly Service to create issues. Here is code that will do the same in groovy:
import com.atlassian.jira.component.ComponentAccessor def issueService = ComponentAccessor.issueService def projectManager = ComponentAccessor.projectManager def user = ComponentAccessor.jiraAuthenticationContext.getLoggedInUser() def issueInputParameters = issueService.newIssueInputParameters() issueInputParameters.with { projectId = projectManager.getProjectObjByKey("JRA").id summary = "Issue created from script" issueTypeId = "1" reporterId = user.name } def validationResult = issueService.validateCreate(user, issueInputParameters) assert !validationResult.errorCollection.hasAnyErrors() def issueResult = issueService.create(user, validationResult) log.info "Issue created: ${issueResult.issue}"