I want to transit all non-resolved issues in a Sprint to a specific workflow status, whenever a Sprint is closed. In order to do so, I need to latch onto the Sprint end event.
So, I have found out that the only place to latch onto this event, is at JIRA Webhooks. My idea was to add ScriptRunner REST Endpoints to reroute the Webhook back to ScriptRunner through the Webhook and go on from there.
Now as you can see, this is a cumbersome way to accomplish this. My questions are:
JIRA Software 7.1+ seems to have a com.atlassian.greenhopper.api.events.sprint.SprintClosedEvent. Unfortunately ScriptRunner only handles JIRA events for scripted event handlers (ones that extend JiraEvent or IssueEvent). The sprint closed event only extends AbstactSprintEvent so you can't write a scripted event handler at present.
Please track and vote on this issue SRJIRA-1910 which would let you do that.
Its true that you can programatically register an event handler using the event publisher but then you have to handle registering and unregistering on startup and you could get into a bit of a mess so we will avoid it for this solution.
You should setup a web hook for the sprint closed event and your url should look something like:
<jira-base-url>/rest/scriptrunner/latest/custom/sprintClosed/${sprint.id}
You'll also need to add the following script REST endpoint script:
import com.atlassian.greenhopper.service.rapid.view.RapidViewService import com.atlassian.greenhopper.service.sprint.SprintManager import com.atlassian.greenhopper.web.rapid.chart.HistoricSprintDataFactory import com.atlassian.jira.component.ComponentAccessor import com.onresolve.scriptrunner.runner.customisers.PluginModuleCompilationCustomiser import com.onresolve.scriptrunner.runner.customisers.WithPlugin import com.onresolve.scriptrunner.runner.rest.common.CustomEndpointDelegate import groovy.transform.BaseScript import javax.ws.rs.core.MultivaluedMap import javax.ws.rs.core.Response @WithPlugin("com.pyxis.greenhopper.jira") @BaseScript CustomEndpointDelegate customEndpointDelegate sprintClosed(httpMethod: "POST") { MultivaluedMap queryParams, String body -> def extraPath = extraPath as String def sprintId = extraPath.replace("/", "") def userKey = queryParams.getFirst("user_key") def sprintManager = PluginModuleCompilationCustomiser.getGreenHopperBean(SprintManager) def historicSprintDataFactory = PluginModuleCompilationCustomiser.getGreenHopperBean(HistoricSprintDataFactory) def rapidViewService = PluginModuleCompilationCustomiser.getGreenHopperBean(RapidViewService) def issueService = ComponentAccessor.getIssueService() def userManager = ComponentAccessor.getUserManager() def user = userManager.getUserByKey(userKey) def closedSprint = sprintManager.getSprint(sprintId.toLong()).value def view = rapidViewService.getRapidView(user, closedSprint.rapidViewId).value def sprintContents = historicSprintDataFactory.getSprintOriginalContents(user, view, closedSprint) def sprintData = sprintContents.value if (sprintData) { def incompleteIssues = sprintData.contents.issuesNotCompletedInCurrentSprint*.issueId incompleteIssues.each { issueId -> // This is the id of the transition you want to make def actionId = 21 def transitionValidationResult = issueService.validateTransition(user, issueId, actionId, issueService.newIssueInputParameters()) if (transitionValidationResult.isValid()) { issueService.transition(user, transitionValidationResult) } else { log.warn transitionValidationResult.errorCollection.errorMessages } } } return Response.noContent().build() }
That will transition all the incomplete issues to a specified status. You will need to replace actionId in the script with the id you want to transition to which you can find in the workflow.
The user that has closed the sprint will need to have permissions to transition the issue as well.
When you close the sprint the page it shows the incomplete issues on doesn't seem to have the status updated to reflect the transition we did, there doesn't seem like a way I can fix this small bug. But if you click into the issue it will have the correct status.
Note that the body in the script contains data like:
{ "timestamp": 1474627199320, "webhookEvent": "sprint_closed", "sprint": { "id": 8, "self": "http://localhost:8080/jira/rest/agile/1.0/sprint/8", "state": "closed", "name": "Sample Sprint 7", "startDate": "2016-09-23T11:39:43.555+01:00", "endDate": "2016-10-07T11:39:00.000+01:00", "completeDate": "2016-09-23T11:39:59.318+01:00", "originBoardId": 1 } }
In case you wanted to extract anymore data out but you should be able to get most of that from the closedSprint object in the script.
Hope this helps.
Adam
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Yup, that did it. So, I am trying to understand your code, and I am already stumbling in your first line in the closure:
def extrapath = extrapath as String
This is also related to something else I do not understand, the REST Endpoint URL. So, in your documentation, <jira-base-url>/rest/scriptrunner/latest/custom/sprintClosed should be matched with the sprintClosed Method. But, we append /${sprint.id} to the Webhook-URL. Does this mean that is <jira-base-url>/rest/scriptrunner/latest/custom/sprintClosed/<whatever> always matched with the sprintClosed Endpoint, and /<whatever> is put into the extrapath variable? I have never written a groovy code ever, so perhaps I am missing some syntax magic.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Yes thats correct. The extraPath is not really documented in ScriptRunner but it will give you anything in the path after "sprintClosed".
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
HI @adammarkham
I have the same requirement as..while sprint closing/completing..the incomplete issues will be moved either future sprint or backlog...so whenever we moved the incomplete issues to backlog then the sprint field should be reset to null...i mean sprint value should be removed.
Normally when we add the incomplete issues to backlog the sprint field contains the sprint name to which the ticket has belonged.
Could you please help me on this...i tried to update the sprint field but getting below error.
2019-04-30 20:23:03,055 http-nio-8712-exec-2 ERROR admin 1222x1118x1 1lhqugt 0:0:0:0:0:0:0:1 /rest/greenhopper/1.0/sprint/106/complete [c.o.scriptrunner.runner.AbstractScriptListener] Script function failed on event: com.atlassian.greenhopper.api.events.sprint.SprintClosedEvent, file: <inline script>
org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object '[10201, 10601]' with class 'java.util.ArrayList' to class 'com.atlassian.jira.issue.MutableIssue' due to: groovy.lang.GroovyRuntimeException: Could not find matching constructor for: com.atlassian.jira.issue.MutableIssue(java.lang.Long, java.lang.Long)
at Script9.run(Script9.groovy:62)
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi, Somebody know how can I do in Cloud?
Serach in event the number Sprint or boardId
thank's
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Also, there is an entry in the Atlasssian Issue DB regarding Sprint events:
https://jira.atlassian.com/browse/JSW-6395
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Thanks for you time! We are using JIRA Software 7.1.1 (JIRA Agile does not exist anymore) and JIRA Core 7.1.0.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
It took me a while to investigate the best approach for this.
What version of JIRA Agile are you using? This may be possible using a script that registers an event listener rather than using a webhook but it depends if you have JIRA Agile 7.1+ or not as the SprintClosedEvent is only available in that version onwards.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.