How can I prevent issues from being assigned to sprints not related to their assigned project?

Mark Finta May 22, 2017

Due to people assigning issues to incorrect sprints accidentally, velocity charts are getting poor data.  This is especially true for our organizations large JIRA projects which need to have their issues only in their project related sprints but have a lot of people able to edit the sprint value.  I would like to prevent this from happening by using ScriptRunner to physically limit the sprints that the issues can pick but I do not know how to implement the script for two reasons.

1. I would like to avoid the Behaviors plugin (part of ScriptRunner) because that limits where the Sprint can be changed to the Issue Edit Screen.

2. Listeners won't work because the change is fully edited before a listener is fired.

Also to note, the "Edit Issues" permission is trimmed down as much as possible for the projects of concern. 

To my current knowledge, this leaves Javascript as my only option and implement it through a script fragment.  Am I missing something or is there any other way I could implement this?  

 

4 answers

3 votes
Deleted user February 19, 2020

Somehow I was able to restrict it by using Behaviours.

It throws error as below!

sprint error.PNG
Follow the snippet! Cheers

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.util.json.JSONObject
import groovyx.net.http.HTTPBuilder
import org.apache.http.HttpRequest
import org.apache.http.protocol.HttpContext
import org.apache.http.HttpRequestInterceptor

def sprintFormField = getFieldById(fieldChanged)
def JIRA_API_URL = "https://jira.milan.com"
def HTTPBuilder jira = new HTTPBuilder(JIRA_API_URL)
//map for selecting correct board id as this behaviours run for multiple project
def projectBaordIDMap = ["TM": 427, "CTA": 343, "CTC": 338, "CTD": 341, "CTJ": 344, "CTM":345, "CTPL": 342, "CTP": 339, "CTT":340]

//correct the basic authentication here
jira.client.addRequestInterceptor(new HttpRequestInterceptor() {
void process(HttpRequest httpRequest, HttpContext httpContext) {
httpRequest.addHeader('Authorization', 'Basic ' + 'milan:milan'.bytes.encodeBase64().toString())
httpRequest.addHeader('Accept', 'application/json')
}
})

def boardID = projectBaordIDMap.get(issueContext.projectObject.key)
def resp = jira.get(path: "/rest/agile/1.0/board/"+ boardID +"/sprint")
JSONObject jsonObject = new JSONObject(resp);
def sprints = jsonObject.getString("values");
//somehow JSONArray is throwing errors, so its easy to split and get the sprint ID
def String[] str = sprints.split("id=", -1)
def boolean flag = false
for(int i = 1;i<str.length;i++) {
def sprinid= str[i].substring(0, str[i].indexOf(","))
if(sprintFormField.getFormValue().toString() == sprinid){
flag = true
break
}

}
//if flag is set true means we have sprint which belongs to the current project/board
if(!flag && sprintFormField.getValue().toString() != "") {
sprintFormField.setError("Wrong Sprint, please select the sprint which belongs to " + issueContext.projectObject.name )
} else {
sprintFormField.clearError()
Jonny Carter
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
February 19, 2020

Nicely done, @[deleted] ! Going out to the Jira Software REST API can be a good workaround when the JAVA API isn't as easy to navigate. It can create some performance & authentication issues in certain environments, but if it works for you, rock on!

I won't be in Vegas, but you should stop by the Adaptavist booth. My colleagues Joshua Yamdogo @ Adaptavist and @Aidan Derossett [Adaptavist] from the SR for Confluence team should be around, and you might just catch @Jamie Echlin if you can elbow your way through his fan base. ;)

Thanks very much for sharing.

Like Deleted user likes this
Deleted user February 19, 2020

cool ! I would love to meet Joshua Yamdogo @ Adaptavist  and @Aidan Derossett [Adaptavist] as I am looking for Atlassian partner who can help us with our Tiered Atlassian tool suites! 


2 votes
Tarun Sapra
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
May 22, 2017

You can do couple of things as well -

1) Look into "Manage sprint" permissions.

2) Since you mention "project related sprints" , - Since Scrum boards are visible only to people having access to the underlying Filters, thus you can have groups specific to filters , i.e. share the filters only with the groups and once you do that then the board will also be visible to the speific group and in this way you can make sure that using these 3 combinations - Edit issue, manage sprints and filter share permissions you can restrict unneccesary access to the sprint value.

Also, please remove the "sprint" field from the"Edit" screen just to make sure that this field is only visible on the "view screen" and is getting updated only via backlog management of the scrum boards i.e. through drag and drop and not manually editing the field.

Vijay Byndoor June 26, 2020

There is one issue with removing the "sprint" field from the "Edit" screen. If there are integrations and API's that use this data, they will fail. 

for example, if you are integrating Jira with QTest, then integration of the sprints won't work because now we don't have that field exposed.  

Deleted user June 26, 2020

Check other answer dude!

Vijay Byndoor June 26, 2020

You mean using the Script Runner Behaviors? 

but that is a hack/customization, what i am driving towards is that Jira should have this behavior out of the box, maybe configurable if required. I don't think there is a valid scenario where this should even happen in the first place.

as of now, Atlassian has a new feature being implemented to make this opt-in. 

Deleted user June 26, 2020

Yeah atlassian won’t do it, that’s why we have script runner. 

0 votes
Jonny Carter
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
June 9, 2017

If you're going to avoid Behaviours, and using a Listener to retroactively fix the issue isn't an option, then I would agree that rolling your own javascript through a Custom Web Resource is probably the main way you could approach the issue in ScriptRunner.

Behaviours is designed to do exactly this sort of thing (provide client-side guidance and validation), but if disabling inline edit on the view screen isn't an option, then unfortunately it won't work for this case. 

Deleted user February 6, 2020

@Jonny Carter any chance were you able to develop such custom web resource which can filter the values of sprints suggested in sprint value to suggest only items which are from current project?

Any hints/sourcecode/repo/links are appreciated.

Thanks,
Milan

Jonny Carter
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
February 13, 2020

Unfortunately not. Been a bit short on round tuits as of late. :)

Deleted user February 18, 2020

Hello Jonny!

I am captivated with behaviour script and I am attempting to fly off into wild yonder as you can see!

Here is the following code that previously written which is working fine for one sprint.


import com.atlassian.jira.component.ComponentAccessor

 

def sprintFormField = getFieldById(fieldChanged)

 

log.warn "====>>>>> ${sprintFormField.getFormValue().toString()} <<<<======"

 

if(sprintFormField.getFormValue().toString() != "816" && sprintFormField.getValue().toString() != "") {

    sprintFormField.setError("Wrong Sprint")

} else {

    sprintFormField.clearError()

}


Now this solution need to horizontally scale dynamically as sprint gets created within project backlog view. I can see there is API which can help find list of sprints.

 https://jira.milan.com/rest/agile/1.0/board/427/sprint

{"maxResults":50,"startAt":0,"isLast":true,"values":[{"id":816,"self":"https://jira.milan.com/rest/agile/1.0/sprint/816","state":"active","name":"TM Sprint 1","startDate":"2020-02-18T22:54:16.808Z","endDate":"2020-03-03T22:54:00.000Z","originBoardId":427,"goal":""},{"id":817,"self":"https://jira.milan.com/rest/agile/1.0/sprint/817","state":"future","name":"TM Sprint 2","originBoardId":427},{"id":818,"self":"https://jira.milan.com/rest/agile/1.0/sprint/818","state":"future","name":"TM Sprint 3","originBoardId":427}]}


how can I programmatically invoke REST api in behaviour with right approach and parse the id of each sprint and get in list?

Thanks,

Deleted user February 19, 2020

Jonny This make my life easy!! Hope we can meet in vegas and grab a beer! 

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.util.json.JSONObject
import groovyx.net.http.HTTPBuilder
import org.apache.http.HttpRequest
import org.apache.http.protocol.HttpContext
import org.apache.http.HttpRequestInterceptor

def sprintFormField = getFieldById(fieldChanged)
def JIRA_API_URL = "https://jira.milan.com"
def HTTPBuilder jira = new HTTPBuilder(JIRA_API_URL)
//map for selecting correct board id as this behaviours run for multiple project
def projectBaordIDMap = ["TM": 427, "CTA": 343, "CTC": 338, "CTD": 341, "CTJ": 344, "CTM":345, "CTPL": 342, "CTP": 339, "CTT":340]

//correct the basic authentication here
jira.client.addRequestInterceptor(new HttpRequestInterceptor() {
void process(HttpRequest httpRequest, HttpContext httpContext) {
httpRequest.addHeader('Authorization', 'Basic ' + 'milan:milan'.bytes.encodeBase64().toString())
httpRequest.addHeader('Accept', 'application/json')
}
})

def boardID = projectBaordIDMap.get(issueContext.projectObject.key)
def resp = jira.get(path: "/rest/agile/1.0/board/"+ boardID +"/sprint")
JSONObject jsonObject = new JSONObject(resp);
def sprints = jsonObject.getString("values");
//somehow JSONArray is throwing errors, so its easy to split and get the sprint ID
def String[] str = sprints.split("id=", -1)
def boolean flag = false
for(int i = 1;i<str.length;i++) {
def sprinid= str[i].substring(0, str[i].indexOf(","))
if(sprintFormField.getFormValue().toString() == sprinid){
flag = true
break
}

}
//if flag is set true means we have sprint which belongs to the current project/board
if(!flag && sprintFormField.getValue().toString() != "") {
sprintFormField.setError("Wrong Sprint, please select the sprint which belongs to " + issueContext.projectObject.name )
} else {
sprintFormField.clearError()
}
Like # people like this
0 votes
Mark Finta May 22, 2017

I completely forgot about about the Edit screen option, that is definitely something to look into.  So if it is removed from the Edit Screen you can still edit the sprint in the backlog view of a scrum board?

To your first and second comment though, I don't think it would work well for "my" case.  The projects I want to implement this for involves around 100 users on a project.  So even though we split people up with groups (has edit issue permission and who doesn't) it is still inevitable that people will screw up and add an issue to a 'bad' sprint.  Especially with a high profile project, I need a more surefire way to make sure bad data doesn't get generated on the project.  That is why I was looking to more of a coding method.

Mark Finta May 22, 2017

This was meant to go under "Tarun Sapra" response

Tarun Sapra May 22, 2017

You can remove the "sprint" field from the Edit Screen and also finetune- manage sprint permissions thus it will narrow down things to selected group of people, who can do things in the backlog view of things.

You have mentioned 

" it is still inevitable that people will screw up and add an issue to a 'bad' sprint. "

Why is this happening in the first place? Only Scrum Master or Product Owner should have the rights to add issues in the sprints and backlog in the scrum board.

Mark Finta May 22, 2017

For our larger projects, on average these sprints hold around 1800 story points (12,000 - 13,000 hours) worth of work.  Being able to effectively manage that kind of work requires the help of more than just a few people.  Also, even though we have developed very specific sprint naming conventions, mistakes still happens when there are hundreds of sprints in the environment that all have similar naming.  The combination of amount of work and number of sprints especially on teams that are a little bit new to JIRA is not a good combo.  I can look a little more into manage sprint permissions but from what I have seen, that isn't going to be 'our' answer because we have the Edit Issue permission as limited as possible for the larger teams.  I need something more like a validator that still allows for JIRA to not limit our users in ways to edit the field, but still guide them incase a mistake is made.

Deleted user February 6, 2020

Exactly! and now we are searching for the same solution. you will laugh at this but our SM are hijacking the sprints from other projects.. Eventually one user marked it as wrong sprint in one of the stupid story created and other project SM will rename that to be their own sprint later as it appears in their backlog view! Some times its like tom & jerry in scrum of scrum..

Anyhow @Mark Finta did you get any solution for this problem?

thanks

Suggest an answer

Log in or Sign up to answer
TAGS
AUG Leaders

Atlassian Community Events