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?
Somehow I was able to restrict it by using Behaviours.
It throws error as below!
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()
}
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.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
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!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
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.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
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.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Check other answer dude!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
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.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Yeah atlassian won’t do it, that’s why we have script runner.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
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.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
@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
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Unfortunately not. Been a bit short on round tuits as of late. :)
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
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,
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
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()
}
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
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.
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.
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.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
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.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
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
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Online forums and learning are now in one easy-to-use experience.
By continuing, you accept the updated Community Terms of Use and acknowledge the Privacy Policy. Your public name, photo, and achievements may be publicly visible and available in search engines.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.