Scriptrunner Fragment to execute custom script

ChristopherChilds March 4, 2024

Hi All,

I am a little lost with this.  I am open to alternative solutions.

I have a problem: We periodically archive  issues which have been closed and not updated for one year. 

Teams are asking that we enable a solution to allow them to retrieve old issues so that they can search them. The solution is to allow the individual teams to Unarchive all of these issues, until the next archive process will archive them again.

We were thinking of using Fragments for this. But as far as I can tell Fragments can not execute some groovy script? they can only call an end point?

Is this correct?

This is a sample of a script we would want to execute.

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.archiving.ArchivedIssueService

def projectManager = ComponentAccessor.getProjectManager()
def issueManager = ComponentAccessor.getIssueManager()

def project = projectManager.getProjectByCurrentKey('TEST')

def issueIds = issueManager.getIssueIdsForProject(project.id)
def issues = issueManager.getIssueObjects(issueIds)

def archivedIssues = issues.findAll { it.isArchived() }

def um = ComponentAccessor.userManager
def archivedIssueService = ComponentAccessor.getComponent(ArchivedIssueService)

def techUser = um.getUserByName("Automation User")

for (item in issues) {

def validationArchive = archivedIssueService.validateRestoreIssue(techUser, item, false)

if (validationArchive.valid) {
archivedIssueService.restoreIssue(validationArchive)
}
}

What is the best way to implement this?

Also, I need to know how I can get the project key.


This is what I thought I could do:
Create Web Panel

capture_240304_125802.pngcapture_240304_125815.png

This will give me something like a panel below:

capture_240304_125841.png

1 answer

1 vote
Peter-Dave Sheehan
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
March 8, 2024

Put your script in a Custom Rest Endpoint.

Then add a "Custom Web Item" fragment with "Run Code and DIspaly a flag" option and point the web item to your new endpoint.

Make sure the endpoint returns a flag with something like "Your request to unarchive this project has been received. This may take a while. You will receive an email when it's finished".

Then, of course, add some logic to your script to send that email to the current user.

Here is a sample rest API script (untested) to get you started:

 

import com.adaptavist.hapi.jira.mail.Mail
import com.adaptavist.hapi.jira.users.Users
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.archiving.ArchivedIssueService
import com.atlassian.jira.util.JiraDurationUtils
import com.atlassian.jira.util.thread.JiraThreadLocalUtil
import com.onresolve.scriptrunner.runner.rest.common.CustomEndpointDelegate
import groovy.json.JsonBuilder
import groovy.transform.BaseScript

import javax.ws.rs.core.MultivaluedMap
import javax.ws.rs.core.Response

def projectManager = ComponentAccessor.getProjectManager()
def issueManager = ComponentAccessor.getIssueManager()
def archivedIssueService = ComponentAccessor.getComponent(ArchivedIssueService)
def jiraThreadLocalUtil = ComponentAccessor.getComponent(JiraThreadLocalUtil)
def jiraDurationUtils = ComponentAccessor.getComponentOfType(JiraDurationUtils)

@BaseScript CustomEndpointDelegate delegate

def authorizedGroups = []/*put groups here for who is allowed to trigger this*/
unarchiveProject(httpMethod: "POST", groups: authorizedGroups) { MultivaluedMap queryParams->
String projectKey = queryParams.getFirst('pkey')
if(!projectKey){
return Response.status(400).entity(new JsonBuilder([errors: "missing pkey parameter"]).toString()).build()
}

def project = projectManager.getProjectByCurrentKey(projectKey)
if(!project){
return Response.status(400).entity(new JsonBuilder([errors: "$projectKey is not a valid project"]).toString()).build()
}

def issueIds = issueManager.getIssueIdsForProject(project.id)

def currentUser = Users.loggedInUser
def techUser = Users.getByName("Automation User")

//Start a separate thread where the work will get executed. This willallow the flag to be returned immediated back to the user while the task continues in the background.
Thread.start {
jiraThreadLocalUtil.preCall()
def count = 0
def start = System.currentTimeMillis()
try {
ComponentAccessor.jiraAuthenticationContext.loggedInUser = techUser
issueIds.each { issueId ->
def issue = issueManager.getIssueObject(issueId)
count++
def validationArchive = archivedIssueService.validateRestoreIssue(techUser, issue.key, false)
if (validationArchive.valid) {
archivedIssueService.restoreIssue(validationArchive)
}
}
} finally {
jiraThreadLocalUtil.postCall(log)
}
def end = System.currentTimeMillis()
def duration = jiraDurationUtils.getFormattedDuration((end - start) / 1000 as Long)
Mail.send {
setTo(currentUser)
setSubject("Unarchive of $projectKey complete")
setBody("$count issues have been unarchived. This took $duration")
}
}

def flag = [:]
flag.type = 'success'
flag.title = "Unarchive initiated"
flag.close = 'manual'
flag.body = """Your request to unarchive $projectKey been received. <br>This may take a while.<br>You will receive an email when it's finished"""

return Response.ok(new JsonBuilder(flag).toString()).build()
}

Notice how I removed issueManager.getIssueObjects(objectIds) ... this would convert all your issues into issue objects. If you have many issue objects, that might use too much memory on your system. Instead, we iterate over the collection of long issue ids. And only create 1 issue object instance at a time.

Suggest an answer

Log in or Sign up to answer
DEPLOYMENT TYPE
SERVER
VERSION
9.4.15
TAGS
AUG Leaders

Atlassian Community Events