So I have this code in a Scripted Field:
import com.atlassian.jira.component.ComponentAccessor
import com.onresolve.scriptrunner.runner.customisers.WithPlugin
import com.okapya.jira.customfields.ChecklistItem
@WithPlugin("com.okapya.jira.checklist")
def isReady(checklist) {
def uncheckedExists = false
def uncheckedRequiredExists = false
for (checklistCondition in checklist) {
def checklistItem = ((ChecklistItem) checklistCondition)
if (!checklistItem.isChecked()) {
uncheckedExists = true
if (checklistItem.isMandatory()) {
uncheckedRequiredExists = true
break
}
}
}
if (uncheckedRequiredExists) {
return "Not-Ready"
} else if (uncheckedExists) {
return "Required-Ready"
} else {
return "Fully-Ready"
}
}
def customFieldManager = ComponentAccessor.getCustomFieldManager()
def fieldDoR = customFieldManager.getCustomFieldObject("customfield_14004")
def checklistDoR = fieldDoR.getValue(issue)
return isReady(checklistDoR)
Sometimes it works and sometimes it doesn't.
JIRA (Data Center - 2 nodes) version: v7.3.3#73014
ScriptRunner version: 5.2.2
Please help :)
I guess this more or less dismisses my concerns. As stated in the documentation: "These annotations only work when running a script that is under a script root… not a script outside a script root, nor code pasted into the console."
I made a workaround using reflection:
import com.atlassian.jira.component.ComponentAccessor;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
///////////////////
// Main programm //
///////////////////
def customFieldManager = ComponentAccessor.getCustomFieldManager()
def fieldDoR = customFieldManager.getCustomFieldObject("customfield_14004")
def checklistDoR = fieldDoR.getValue(issue)
return isReady(checklistDoR)
///////////////
// Functions //
///////////////
Object invokeMethodByReflection(Object object, String methodName) {
Method method;
try {
method = object.getClass().getMethod(methodName);
} catch (SecurityException e) {
// doSomething
} catch (NoSuchMethodException e) {
// doSomething
}
try {
return method.invoke(object);
} catch (IllegalArgumentException e) {
// doSomething
} catch (IllegalAccessException e) {
// doSomething
} catch (InvocationTargetException e) {
// doSomething
}
}
String isReady(checklist) {
Boolean uncheckedExists = false
Boolean uncheckedRequiredExists = false
for (checklistItem in checklist) {
Boolean isChecked = invokeMethodByReflection(checklistItem, "isChecked")
Boolean isMandatory = invokeMethodByReflection(checklistItem, "isMandatory")
if (!isChecked) {
uncheckedExists = true
if (isMandatory) {
uncheckedRequiredExists = true
break
}
}
}
if (uncheckedRequiredExists) {
return "Not-Ready"
} else if (uncheckedExists) {
return "Required-Ready"
} else {
return "Fully-Ready"
}
}
Hi Dawid,
Must admit that I'm little bit confused. The resolution field has values such as "Fixed", "Won't Fixed" etc. It's the status that changes to "Resolved" or "Closed". Also, the problem is that I cannot know which workflow is associated to which Customfield thus the "RegEx" approach.
As for the Agile Card, thanks for the extra info. I will definitely take that into account when we're going to develop the feature.
Finally, we're thinking about allowing custom statuses. It's in our backlog but I can't see if/when we're going to do it.
Yves
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hello Yves,
Regarding the confusion. The Resolution field is by default, when you create an issue, set to a NULL value, which is displayed as "Unresolved". However, when you look at the list of Resolutions in the system, you will never find that "Unresolved" value, because it is only how JIRA displays that value in various issue screens and how it's translated from NULL in the index. Therefor a JQL with "Resolution = Unresolved" will yield the same results as "Resolution is EMPTY". As for the Resolution values, you can manipulate the list in the settings and it's shared system wide, so every project shares the same list. The Resolution field is always there in all the projects, even if it's not shown in any screen.
Now, another thing. If you look at the Created vs Resolved chart in JIRA (https://confluence.atlassian.com/jira064/created-vs-resolved-issues-report-720416052.html) it decides if an issue is resolved in a very simple, generic way:
- the issue is not considered Resolved if the Resolution field is EMPTY a.k.a. NULL a.k.a. Unresolved
- the issue is considered Resolved if the Resolution has any Resolution set at all, meaning, the value of the Resolution field is set to any one of the values of the possible Resolutions (shared system wide).
Now, what I was suggesting was a mechanism, that is pretty generic, and validates whether updating the Checklist for an existing issue is possible in the same way, as described above:
- if the Resolution field is EMPTY a.k.a. NULL a.k.a. Unresolved, then the checklist is updated
- if the Resolution field is set to one of the possible values from the system wide shared list, it is considered Resolved (no matter on the particular Resolution value) and the checklist is updated.
Of course, regexing is good enough too, however for my taste, utilizing the Resolution field is much more convenient, as it is independent from the statuses in particular workflows. It just checks if the Resolution field is empty or not.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Ok, got it now. You do know your Jira :-)
I will add this to my backlog as well.
Thanks!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi Dawid,
Sorry, but from my side of things (Checklist), I have no experience with Scriptunner or Groovy. Hopefully someone else can chip in.
Yves
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hello Whyves,
Not really that helpful, but thanks for the reply anyway.
However, as you are here, maybe I'll explain, why I actually needed to use Script Runner when using you add-on :) So please bear with me for a moment. This is the way the story goes...
We were looking for a JIRA add-on to implement DoR, DoD and AC. As far as AC go, this is (in JIRA language) issue specific, so we can actually use (in Checklist language) the local items. Of course, an empty custom field will not display in a Issue View Screen, so we use AC with a single global item (Option - in JIRA language) saying "Accceptance Criteria have been provided" and we enable our users to provide the actual ACs as the local items (in Checklist language of course).
However for DoR and DoD, as they are project / team / whatever specific, so much more general, we have encountered a serious limitation. And that limitation is that the DoR and DoD may change overtime. What does this imply in the case of your add-on? I'll try to explain.
(1) If we put our DoD and DoR as global items, then every time we update it, it will not only get updated for new issues, but it will get updated for all existing issues in the targeted scope (context - in JIRA language), for example: all the DoR and DoD compliant issues already closed in a certain project). This is not acceptable for us, as we are tied to a lot of internal and external audits, some of them serious and thorough in nature.
(2) So we have decided to put all our DoRs and DoDs as local items. The way we do this is that we use your add-on's post-function (Modify Checklist) to put the conditions inside the issue as local items during the Create transition. When the DoR or DoD change, then we modify the conditions in the post-function in the appropriate Workflow, so all the new issues are effected by the new DoR and DoD versions, but the existing ones are not. Of course we also have a mechanism, that allows us to update the DoR and DoD for already existing issues that have not yet been closed, so they should adhere to the new / updated DoR / DoD. The way we do this is that we have two additional self-looping transitions per Workflow (updateDoR and updateDoD) that purge the contents of DoR and DoD and replace it with the most current version. The downside is that whenever we need to update DoR or DoD for a certain scope (context - in JIRA langueage), we need to modify it for all applicable Workflows for a team / project and twice per Worflow. But this solution can actually meet our audit criteria. And we have also added some screens that explain the consequences of updating the DoR or DoD for an issue, with the additional need for a confirmation. This should work 99% of the time, for the 1% we have the issue change log.
Now, this being said,the first question would be, if you have an idea for any better implementation that would suit our needs, as we believe we have exploited all the possibilities. I would make a wild bet you never thought someone would actually use your add-on this way. You are free to quote me as long as you put me as the sharing author ;)
And for the main dish - why we use Script Runner together with your add-on. The predefined JQL functions in your add-on are cool, as long as you want to search issues by JQL in the general search, a predefined filter or a quick filter in a board. However, it is not usable if you want to display it in an agile card for an issue. Therefore we decided to get some calculated custom fields, Ready and Done, that more or less just calculate what's in the checklist ans say something like NotReady/Done, RequiredReady/Done, FullyReady/Done. And the script is simple, cause we just check, in a loop, the isChecked and ismandatory conditions, but somehow the script sometimes fails on loading the libraries for your add-on. So, of course, if you have any idea for obtaining similar information in fields, that can be displayed on an agile card, please share.
Edit: I have updated the question to contain the full script for a single field. Not that it matters that much (in terms of the error), but might be a good example for others. Still, I had to go through all the trouble with reflection (getClass(), getmethods() and that kind of things), to actually know what to call to do what I need. You might consider putting this knowledge out in your doc as it is accessible anyway, but for now in a much less convenient form :)
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi Dawid,
I could not answer last night, the question was marked as spam :( Probably because of the script which seems to have been stripped off. If you want to send me the script, you can do so by sending it at our email (info 'at' okapya '.' com)
I have built Checklist because I wanted to support similar cases as what you're doing so I can't say that I'm surprised by the use case :-) I wondered many time about Checklist updating global items for closed issues. Now, you provided me with a valid and real use case. Would preventing the global updated based on status be a good solution? Since it's difficult to know in which workflow the Checklist will be used, it could be some type of regular expression that could match the status.
Beside the solution that I proposed, I think that you actually implemented the solution to the best of its current capabilities. It would require development to improve it.
Now, regarding the agile card field. We will be looking into that soon so it's the perfect time to learn more about your use case. What I wanted to do was to create a field that would output something like "2/5", "3/5 All Mandatory" or "5/5 Completed". Would that be helpful? Maybe you would need to put your own text on top? This way, you wouldn't need Groovy anymore.
Yves
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hello again Yves,
I know about the SPAM thing. I actually raised a ticket with Atlassian for that :) Still, it's weird as I see the full script in this page. Hmmm... I can see it in Chrome in incognito mode, so I guess it should be visible...
Anyway, I'd like to address your reply.
"Would preventing the global updated based on status be a good solution?" - umm, yes. Although, as we have project with multiple Workflows, I guess I'd rather make it more Workflow independent and use the Resolution field:
- issue unresolved -> update the definition
- issue resolved -> do not update the definition (whatever the Resolution is)
Of course this implies that I'm using some Workflows that either use a Resolve Issue Screen or set the Resolution via a post-function (and clear that field as well in certain transitions). So probably it would be best, if there was an option to choose between Workflow / Resolution validation. Of course there is also an option of a custom field with a 1/0 value saying, if the checklist should be updated to the newest version (when that version appears) and leaving it to the user to set this value either manually or via workflow post-functions (per issue).
As for the agile card - what we basically need to display is the same text that you display in a colorful label anyway. We need to know when all conditions are checked, all mandatory conditions are checked or none of the two. This is the granularity level that would suffice. No need for us for actually displaying a custom text, but we would probably use if it was there. As for numbers N/M, we would probably use that if both N and M were is separate fields. It would then be best to actually have more than two values there:
- number of all conditions
- number of all mandatory conditions
- number of conditions met
- number of mandatory conditions met
This way we could somewhat track the "adoption rate" for our DoR / DoD.
A complicated string like "3/5 All Mandatory" would be more difficult to handle.
As for further development of the add-on, what we miss is the possibility to set our own statuses (and setting whether it's a checked status or not). Of course it would be best to get it "per Checlikst", but even a single, customizable set to use for all the checklists would be a nice addition.
Thanks for all the replies,
Dawid
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.