Introduction
Jira Scripting Suite allows you to execute custom Jython script to evaluate workflow conditions, perform validations and post functions. Script is evaluated in the context, which differs for each type of script (see sections below for details).
Jython is a Python port to Java, visit http://www.python.org/doc/2.5/ for general info.
Be Careful
Be careful when using single script file in many workflow actions - when you change this script in one action, all other will also be affected!
Conditions
Context:
Variable |
Description |
---|---|
result |
Result of condition evaluation; boolean value, default is True |
issue |
Issue object |
log |
|
transientVars |
A map containing all context data passed to validator |
The main context variable here is result. Validator expects it to contain boolean value - True or False.
result = True # this workflow action is enabled result = False # and now it's disabled for everyone
You can get any attribute of the Issue object using its Java methods. For example, let's deny the action for all issues having word TEST in Summary:
summary = issue.getSummary() # note that summary is a python string, not Java String result = summary.find('TEST') < 0 # find() returns -1 if string not found # or simply in one string result = issue.getSummary().find('TEST') < 0
Be Careful
Although issue is actually a MutableIssue object, you can not change any issue data in condition script.
Validation
Context:
Variable |
Description |
---|---|
result |
Result of validation; boolean value, default is True |
invalid_fields |
PyDictionary(), empty map by default |
description |
PyUnicode(), empty unicode string by default |
originalIssue |
Original (unmodified) Issueobject |
issue |
Modified Issueobject |
log |
|
transientVars |
A map containing all context data passed to validator |
In validation script we use another two valiables along with result to reports an error to the user: invalid_fields and _description _. See example:
result = False description = 'General error description' invalid_fields['summary'] = u'Error description for the Summary field'
This script produces such a message for every issue with that workflow:
invalid_fields is initially an empty map. You can attach error messages both to standard and custom fields. In case of custom field you should use its ID like this:
result = False invalid_fields['customfield_10010'] = u'This custom field is invalid!'
Post Functions
<TODO>
Code Snippets
Sending a Custom E-mail Notifier
sender = 'sender@somedomain.com' to = 'recipient@somedomain.com' subj = "SUBJECT" body = "MESSAGE BODY" server = 'smtp.somedomain.com' from email.MIMEText import MIMEText msg = MIMEText(body, 'plain', 'utf-8') msg['Subject'] = subj msg['To'] = to msg['Importance'] = 'high' import smtplib s = smtplib.SMTP(server) s.sendmail(sender, [to], msg.as_string()) s.quit()
More Complicated E-mail Notifier
Thanks to Jared Meeker for this code
# -*- coding: UTF-8 -*- #import inspect # Issue Details key = issue.getKey() status = issue.getStatusObject().name summary = issue.getSummary() project = issue.getProjectObject().name resolution = issue.getResolutionObject().name description = issue.getString("description") # Get Requestor custom field (text, not user picker) import com.atlassian.jira.ComponentManager import com.atlassian.jira.issue.CustomFieldManager import com.atlassian.jira.issue.fields.CustomField customFieldManager = ComponentManager.getInstance().getCustomFieldManager() customField = customFieldManager.getCustomFieldObjectByName("Requestor") requestor = issue.getCustomFieldValue(customField) # Verify that we have an email address in the text field import re if (re.match('[A-Za-z0-9._%+-]+@(?:[A-Za-z0-9-]+\.)+[A-Za-z]{2,4}',requestor)): # Get posted comment if it exists try: comment = dict(transientVars)['comment'] except: trash = '' # Email Details sender = '*******@*************.***' to = requestor subject = '[JIRA] ' + status + ': (' + key + ') ' + summary # Build the body of the email body = '' if (status == "Closed"): body = body + "\r\nAccording to our records, your issue (" + key + ") has been resolved.\r\n\r\n" if (resolution == "Won't Fix"): body = body + "\r\nThis issue will not be fixed. A description of why should be below.\r\n" elif (resolution == "Duplicate"): body = body + "\r\nThis issue is a duplicate of another issue.\r\n" elif (resolution == "Incomplete"): body = body + "\r\nThis issue has been marked as incomplete. A description of why should be below.\r\n" elif (resolution == "Cannot Reproduce"): body = body + "\r\nThe developers have been unable to reproduce the error you describe.\r\n" elif (resolution == "Rejected"): body = body + "\r\nThis issue has been rejected. A description of why should be below.\r\n" body = body + "\r\n" try: body = body + "Comment:\r\n" + comment + "\r\n" except: body = body + "Comment:\r\nNo comment was entered\r\n" body = body + "\r\n" body = body + "> " + summary + "\r\n" barline = '>' while (len(barline) <= len(summary)+2): barline = barline + "-" body = body + barline + """ > > > Key: """ + key + """ > Project: """ + project + """ > """ + description + """ -- This message is automatically generated by JIRA. - If you think it was sent incorrectly contact one of the administrators: https://jira.somedomain.com:8443/secure/Administrators.jspa - For more information on JIRA, see: http://www.atlassian.com/software/jira""" # Build mail message from email.MIMEText import MIMEText msg = MIMEText(body, 'plain', 'utf-8') msg['Subject'] = subject msg['To'] = to #msg['Importance'] = 'high' # Send the email import smtplib s = smtplib.SMTP('*****.*******.***') # ip or domain name of smtp server s.sendmail(sender, [to], msg.as_string()) s.quit()
230 Comments
Unknown User (tkrug0210)
What I currently need is a validator to check if the user contained in a userpicker-field is member of a specific group.
Is it possible to achieve this via the plugin?
Cheers
Thomas
Alexander Shchagin
Thomas, sure you can.
Of course, this is not a completely production code, you should add validation for None values and general error handling.
BR, Alex
Unknown User (tkrug0210)
Hi Alex,
works just fine, thanx.
Cheers
Thomas
Unknown User (tkrug0210)
Hi Alex,
I am struggling with Python concerning the None values. I thought this might work
which does not. Can you help me with the correct code?
The error thrown is
root cause: Traceback (most recent call last): File "d:\jira\data\jss\jython\workflow\zeitkorr_weiterleiten_fk.py", line 11, in <module> elif not user.inGroup('1_zeitkorrektur'): AttributeError: 'NoneType' object has no attribute 'inGroup'
Cheers
Thomas
Alexander Shchagin
Hi Thomas,
You should check for None first and after that you can safely access User object:
or shorter:
because None is equivalent to False in boolean expression
Unknown User (tkrug0210)
Hi Alex,
thanx, my script is running fine now. I have to userpickers ('fk' and 'fkvertretung'). Both users have to be in the '1_zeitkorrektur' group whereas the second userpicker is not mandatory:
Unknown User (darkoc)
Hi to all,
I just installed Jira Scripting Suite(following the instructions from the official page ) and added some Jython script as post function:
so I can inherit the Priority, Versions and Components from the parent issue when I create a subtask
works great!...
Still, when I try to edit an existing issue I get the following error: Cannot create PyString from null!...
This happens even when I try to edit some issue which doesn't have the Jython script attached as a post function... Any help???
Thanks in advance
Unknown User (tkrug0210)
Hi Darko,
I can't really help you on this one but Alex answered my questions very quickly.
You maybe solved a long open problem I have. I am using a plugin to generate subtasks in a postfunction. This plugin does not copy FixVersion and AffectedVersion from the parent to the Subtask.
Do you add the subtask in your postfunction and can supply me with the code snippet?
Cheers
Thomas
Unknown User (darkoc)
Hi Thomas,
The thing that I do is adding the code I wrote in the previous post as a POST FUNCTION. So basically, when you open a task and u set Fix Version, Affected Version, Components and Priority, they will be applied to every subtask you create from that task. I tried that and it is working. Just add the code...
Still, after I installed Jira Scripting Suite I get the error: Cannot create PyString from null! every time I try to edit ANY ISSUE... I really like the JSS but If I don't solve this issue I will have to disable it
.
Anyone knows something about this?
Cheers,
Darko
Alexander Shchagin
Hi Darko,
Did you add the code from above as a global post-function?
Alex
Unknown User (tkrug0210)
Hi Darko,
this works for me only if I EDIT a subtask, not while creating one.
Did you change the "CreateSubTaskIssue" alias in the actions.xml? If yes maybe that's the problem you have.
Cheers,
Thomas
Unknown User (darkoc)
Hi guys,
I was in a hurry these days so I didn't answer the questions. The problem was in the actions.xml... As it was described in the manual, I needed to:
change "issue.EditSubTaskIssue" to "com.quisapps.jira.plugin.action.EditSubTaskIssue" and "issue.EditIssue" to "com.quisapps.jira.plugin.action.EditIssue"
so that was the problem. I changed back to issue.EditSubTaskIssue and issue.EditIssue
and the problem was fixed. Anyway, I was wondering if there is any way to use the Jython scripts on creating issues and not just as Post functions and Validators in workflows
Regards,
Darko
Alexander Shchagin
Hi Darko,
By doing that you disabled global jython on-edit validator and post-functions. I think your problem was in incorrect on-edit post-function script.
And if you want to set a post-function on creating, you should add a jython postfunction to the "Create Issue" action of the corresponding workflow, just before the "Creates the issue originally." and place your code there.
BR, Alex
Unknown User (wufei)
Hi Alexander,
Hi have installed JSS 0.3.1 on JIRA 4.1.1.
I found answers to my questions. It may help other people.
I don't really understand how you can set a post-function on issue creation. Can you please give some more details on how you're doing this? Actually, how can you access to the "Create Issue" action of a workflow?
Top menu "Administration", Left pane menu "Events" and then, select an inactive copy of your target workflow by selecting its "Create" link.
How about validators? And would it be possible to apply these scripts to a certain type of issue only?
Make sure your workflow is working on your specific type of issue if you just want to avoid applying the script globally. This works for Validators and Post-functions. To access to the custom field of the issue, I'm using "customFieldValue = issue.getCustomFieldValue(myCustomField)".
Thanks in advance,
Wufei
Unknown User (brian)
Go to the workflow, create a draft, click the initial step (Submitted/Open/etc), in the Workflow Browser click on the "Create" transition. From there you can add post functions.
Unknown User (keith.lee)
Thanks Alex,
Your comment give me the answer for Cannot create PyString from null! issue on issue editing.
The reason was the global post function (Admin -> JSS -> Edit Postfunction) was set to 'Inline script' without any code in it.
By changing it to default file 'File (......./edit_postfunction.py)' the problem has gone.
I hope this will help others as well.
BR, Keith
Unknown User (darkoc)
Hi guys,
Can someone tell me how to check if a user belongs to a specific Project Role in specific project? Let's say in the project "Test Project" i want to check if a user belongs to the project role "Test Project Developers" and if he doesn't to restrict him to crate Developement issues.
Regards,
Darko
Unknown User (chrome@stupendous.net)
That really sounds like something Jira can do out of the box without messing with workflows?
Alexander Shchagin
Hi Darko,
I think it would be smth like this:
Anyway, a good point to start is ComponentManager javadoc - there are a lot of useful 'Managers' in JIRA
Alex
Unknown User (chrome@stupendous.net)
This plugin is awesome. I can now implement all the weird functions I wanted, that I couldn't do with any other plugin.
Here is a Post Function I am using to update a custom field with a string generated from the User's name. I needed to do this because I wanted it recorded in an easily accessible way, who performed a particular transition last.
Unknown User (jira.support@ubisoft.com)
I added the plugin but we keep getting this error : Error creating issue: root cause: IOError: (2, 'File not found - /mnt/jira/jira/jira58/jss/jython/_init_interpreter_.py (No such file or directory)') whereever I put scripts (Create post function etc)
Do we miss something ? I have the jss-0.2.jar in the installed-plugins and all the .py jython.jar (from the version 2.5.0 etc in the dir of homejira /jss/jython/
But from this error he seem to dont find the .py from the bin dir of jss jython even to the path is there.
Thanks!
Alexander Shchagin
Hi! Look into jss-0.2.jar, and you will find the 'jython' folder - it contains some jython placeholders and sample files. Just copy this folder to /mnt/jira/jira/jira58/jss.
BR, Alex
Unknown User (stenech)
Hi! How is it possible to set a specific component? I think I have to use "issue.setComponents()" but I have no clue how to setup the required list?!?
Markus
Alexander Shchagin
Hi Markus,
This should be a Collection of GenericValue objects. You can use a getGenericValue() method of ProjectComponent to obtain a GenericValue needed.
BR, Alex
Unknown User (stenech)
Yes, it works:
Markus
Unknown User (kubo@solvere.sk)
Hi, I installed the JSS plugin and when testing I get this error:
ERROR
It seems that you have tried to perform an illegal workflow operation.
If you think this message is wrong, please consult your administrators about getting the necessary permissions.
Form Errors:
General error description
Maybe I don't understand exactly the last step form the installation: Add listener with any name (e.g. Jython) and class com.quisapps.jira.plugin.listener.JythonListener .
Also what I did on previous step : Copy Jython file placeholders from plug-in jar file /jython to JIRA_HOME/jss/jython. Was that I just unzipped the jar and placed flder Jython from that jar to the path jss/jython in my Jira instance.
My test script looks like this:
Thanks for help.
Unknown User (kubo@solvere.sk)
I found out where was my problem.
The error was shown because I haven't setup any screen on transition. So if you want to have this thing showing errors correctly you have to have screen with fields that you want to check assigned to transition in Transition View field when editing transition.
Also installation step Add listener with . . . means that you have to create a listener in Administration -> Listeners.
Unknown User (matt.bates)
If you want to clear out your Fix Version (say when you Close - Won't Fix something) you need to pass an empty list.
Unknown User (hmenzi)
I am trying to create a sub-task on a workflow transition the sub-task should have all basic properties of the issue. I can not seem to find any example other than java examples that do not seem to work.
This is what I have (which is wrong) can someone please point me in the right direction?
Alexander Shchagin
Hi Hans,
In JIRA sub-task is just an issue with corresponding issue type and a link of special type between itself and its parent.
BR, Alex
Unknown User (tkrug0210)
Hi Alex,
is it somehow possible to create multiple subtasks in on script?
When duplicating the lines
Jira throws a NullpointerException
root cause: Traceback (most recent call last): File "d:\jira\data\jss\jython\workflow\kundenmanagement_subtasks.py", line 26, in <module> subTask2 = issueManager.createIssue(authenticationContext.getUser(), issueObject) at com.atlassian.jira.issue.managers.DefaultIssueManager.notifyTrackbacks(DefaultIssueManager.java:413) at com.atlassian.jira.issue.managers.DefaultIssueManager.createIssue(DefaultIssueManager.java:356) at sun.reflect.GeneratedMethodAccessor721.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at com.atlassian.util.profiling.object.ObjectProfiler.profiledInvoke(ObjectProfiler.java:70) at com.atlassian.jira.config.component.SwitchingInvocationHandler.invoke(SwitchingInvocationHandler.java:28) at $Proxy30.createIssue(Unknown Source) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) java.lang.NullPointerException: java.lang.NullPointerException
Alexander Shchagin
Possibly you can't create an issue using the same issueObject again. You should create another issueObject, set its attributes and then call issueManager.createIssue() and subTaskManager.createSubTaskIssueLink(). Of course, you can do this, for instance, in a 'for' loop.
Unknown User (tkrug0210)
I tried that without success. The exception is no longer thrown, but jira only creates the first subtask.
If I separate the code in two files and add two postfunctions to the workflow it works.
Alexander Shchagin
Thomas, in your script after the line
there is 'subTask' everywhere when it should be 'subTask2'.
Unknown User (tkrug0210)
Another copy-and-paste bug :-)
Thanks, it works now.
Unknown User (hmenzi)
Alex, worked like a charm. Thank you for your quick reply!
Unknown User (muhammad_rahman@cable.comcast.com)
Hi Alex,
I am trying to write the script in post function to create a new ticket and link back to current ticket instead of sub-task. I have created a issue link manager as
issueLinkManager = ComponentManager.getInstance().getIssueLinkManager()
then I wrote :
linkedIssue = issueManager.createIssue(authenticationContext.getUser(), issueObject)
//The above line creates a new ticket, but return a org.ofbiz.core.entity.GenericValue
The following createIssueLink() method requres the destination ticket id as a type "Long".
issueLinkManager.createIssueLink(issue.getId(),linkedIssue.getId(),10032,1,authenticationContext.getUser())
Can any one tell me me how to get the ID of "linkedIssue" to pass to createIssueLink() as destination ticket ID?
Code snippet:
from com.atlassian.jira import ManagerFactory
from com.atlassian.jira.issue.link import DefaultIssueLinkManager
from org.ofbiz.core.entity import GenericValue;
issueManager = ComponentManager.getInstance().getIssueManager()
issueFactory = ComponentManager.getInstance().getIssueFactory()
projectManager = ComponentManager.getInstance().getProjectManager()
issueLinkManager = ComponentManager.getInstance().getIssueLinkManager()
authenticationContext = ComponentManager.getInstance().getJiraAuthenticationContext()
issueObject = issueFactory.getIssue()
#issueObject.setProject(issue.getProject())
issueObject.setProject(projectManager.getProject(10358))
issueObject.setIssueTypeId("1")
issueObject.setSummary(issue.getSummary())
linkedIssue = issueManager.createIssue(authenticationContext.getUser(), issueObject)
issueLinkManager.createIssueLink(issue.getId(),linkedIssue,10032,1,authenticationContext.getUser())
ImportUtils.setIndexIssues(True)
ComponentManager.getInstance().getIndexManager().reIndex(linkedIssue)
ImportUtils.setIndexIssues(False)
Thank
Unknown User (brian)
Though this isn't an example of how to do it with the JIRA Scripting Suite, you may want to check out the JIRA Link New Issue Operation plug-in. They offer a very well supported plug-in that allows creation of a linked issue as a post-function.
Unknown User (muhammad_rahman@cable.comcast.com)
I was been able to create and link by modifying the line: issueLinkManager.createIssueLink(issue.getId(),linkedIssue.getId(),10032,1,authenticationContext.getUser())
to : issueLinkManager.createIssueLink(issue.getId(),issueObject.getId(),10032,1,authenticationContext.getUser())
Thanks
Unknown User (lhawkes)
As an FYI, the behavior is slightly different when using Jira 4.2.2. Since there's no explicit call to get the CacheManager, this line:
has to be replaced with
Unknown User (mahku)
Hi,
By following the installation guide, i have added the plugin. But getting this error : "Error creating issue: root cause: LookupError: no codec search functions registered: can't find encoding"
Don't know whether i have made any mistake. However, this is the way that i followed:
1) I have set the 'JAVA_OPTS' Environment Variable with "-Dpython.home=C:\jython2.5.0;".
2) Then, i have downloaded and kept the 'jss-0.2.jar' plugin jar in the 'homejira/plugins/installed-plugins' and also i have copied the whole 'jython' folder from 'jss-0.2.jar' plugin jar to 'homejira/jss' folder.
3) And modified "/WEB-INF/classes/actions.xml": i.e, changed "issue.EditSubTaskIssue" to "com.quisapps.jira.plugin.action.EditSubTaskIssue" and "issue.EditIssue" to "com.quisapps.jira.plugin.action.EditIssue".
4) Then restarted Jira and added listener by giving the name as 'Jython' with class "com.quisapps.jira.plugin.listener.JythonListener".
Then, i have created a sample project. And created a 'copy of default jira workflow' by giving a name to that workflow. Also created a sample screen with few fields.
Finally added 'JythonValidator' with the following script(a sample for testing) to 'CreateIssue' transition in that particular workflow and made the workflow active.
============================================================
# -- coding: UTF-8 --
summary = issue.getSummary()
project = issue.getProjectObject().name
print 'summary is '+summary
print 'project is '+project
if summary == 'hi':
result = False
description = 'Hi : Error'
invalid_fields['summary'] = u'Error description for Summary in 'project' project.'
============================================================
Thanks in advance!
Alexander Shchagin
Hi mahku,
Instead of setting an environment variable on step 1, you should modify bin\setenv.bat file in JIRA installation folder (on Windows). All other steps look good.
Alex
Unknown User (mahku)
Hi Alex,
Thanks for reply.
Still getting the same error: "Error creating issue: root cause: LookupError: no codec search functions registered: can't find encoding"
-mahku.
Alexander Shchagin
It still seems to me that the plugin can not find Jython installation. Do you have Jython installed in C:\jython2.5.0? And is there a line in your setenv.bat that reads like this? (just to be sure)
(please note backslash changed to forward slash in path)
BR, Alex
Unknown User (mahku)
Hi Alex,
I have changed backslash to forward slash in path. But still getting the same error on the screen: "Error creating issue: root cause: LookupError: no codec search functions registered: can't find encoding".
This is all for 'Create Issue' operation.
A few lines from the Log file:
http://LENOVO:8080/secure/CreateIssueDetails.jspa [jira.plugin.workflow.JythonValidator] Unrecognized exception while executing Jyphon script: null
LookupError: no codec search functions registered: can't find encoding
at org.python.core.PyException.fillInStackTrace(PyException.java:70)
at java.lang.Throwable.<init>(Throwable.java:181)
at java.lang.Exception.<init>(Exception.java:29)
at java.lang.RuntimeException.<init>(RuntimeException.java:32)
at org.python.core.PyException.<init>(PyException.java:46)
at org.python.core.PyException.<init>(PyException.java:43)
at org.python.core.PyException.<init>(PyException.java:61)
at org.python.core.codecs.lookup(codecs.java:80)
at org.python.core.codecs.getEncoder(codecs.java:209)
at org.python.core.codecs.encode(codecs.java:187)
at org.python.core.PyString.str_encode(PyString.java:2429)
at org.python.core.PyString.encode(PyString.java:2420)
.........
.........
so on.
-mahku.
Alexander Shchagin
Hi mahku,
Please open a Support Request at https://studio.plugins.atlassian.com/browse/JSS.
Enclose your script into the following code:
and attach it to the issue along with the JIRA log file after script execution.
Alex
Unknown User (mahku)
Hi Alex,
Thanks for your support in resolving the previous issue.
Now i am facing a new problem while creating a subtask. Actually, i have to validate few fields. And later, depending on a particular field, i have to create a subtask. So, at first, i have come across how to validate fields. And now, i am trying to create a sample subtask.
Displaying the following error:
Error creating issue: root cause: Traceback (most recent call last): File "C:\Program Files\Atlassian\Application Data\JIRA\jss\jython\workflow\smpValid2.py", line 26, in <module> subTask = issueManager.createIssue(authenticationContext.getUser(), issueObject) at com.atlassian.jira.workflow.SimpleWorkflowManager.createIssue(SimpleWorkflowManager.java:197) at com.atlassian.jira.issue.managers.DefaultIssueManager.createIssue(DefaultIssueManager.java:355) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at com.atlassian.util.profiling.object.ObjectProfiler.profiledInvoke(ObjectProfiler.java:70) at com.atlassian.jira.config.component.SwitchingInvocationHandler.invoke(SwitchingInvocationHandler.java:28) at $Proxy33.createIssue(Unknown Source) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) java.lang.NullPointerException: java.lang.NullPointerException
And following is the sample code that i followed (i went through the scripting samples of this page):
======================================
# -- coding: UTF-8 --
from com.atlassian.jira import ComponentManager
from com.atlassian.jira import ManagerFactory
from com.atlassian.jira.util import ImportUtils
cfm = ComponentManager.getInstance().getCustomFieldManager()
custIssueField = issue.getCustomFieldValue(cfm.getCustomFieldObject("customfield_10000"))
if custIssueField != None:
result = True
issueManager = ComponentManager.getInstance().getIssueManager()
issueFactory = ComponentManager.getInstance().getIssueFactory()
authenticationContext = ComponentManager.getInstance().getJiraAuthenticationContext()
subTaskManager = ComponentManager.getInstance().getSubTaskManager()
issueObject = issueFactory.getIssue()
issueObject.setProject(issue.getProject())
issueObject.setIssueTypeId("5") # default sub-task issue type
issueObject.setParentId(issue.getId())
#setting general issue attributes such as summary, assignee etc
issueObject.setSummary("Test a sample")
subTask = issueManager.createIssue(authenticationContext.getUser(), issueObject)
subTaskManager.createSubTaskIssueLink(issue.getGenericValue(), subTask, authenticationContext.getUser())
# Update search indexes
ImportUtils.setIndexIssues(True)
ManagerFactory.getCacheManager().flush(CacheManager.ISSUE_CACHE, subTask)
ComponentManager.getInstance().getIndexManager().reIndex(subTask)
ImportUtils.setIndexIssues(False)
=========================================
-mahku.
Unknown User (mahku)
Hi Alex,
I have resolved the above problem by enabling the subtasks and making few modifications in the code by going through the Jira API. However, Thanks for your support.
-mahku.
Alexander Shchagin
Hi mahku, thanks for the hint. I've spent some time trying to reproduce that, but with no luck - I had subtasks enabled in my Jira.
Alex
Unknown User (sunderhill)
If I can ask, how was the previous issue resolved? I am experiencing the same error message while trying to run a jython post-function.
Unknown User (gopherr)
Alex,
I am getting the same "no codec" error message as mahku, but the only relevant bug report I could find (JSS-5 ) is closed and marked invalid with no comments.
I see that mahku was able to resolve the issue by enabling sub-tasks, but I already have sub-tasks enabled and I am getting this error message on the Create Issue transition for a standard issue, not a sub-task.
I also now see that you have not been able to reproduce the problem on your side, so please let me know if there is any information I can provide that may help.
Thanks!
Geoffrey
Unknown User (ohingardail)
Brilliant plugin! Helps me fix all the niggly bits that other plugins leave behind.
For instance, the workflow 'Copy Issue Function' which is part of the 'CustomWare JIRA Utilities' plugin does exactly what it says it does; this includes copying reporter fields from the old records to the new, even if that reporter is not the person doing the copying. JSS easily fixes this by including this JSS script in the 'create' transition of the new record :
However, one thing I've not worked out yet is how to work around other (non-JSS) plugins' problems with copying fixVersion, affectedVersion and component values where the version or component doesn't already exist in the target record's project.
So, what I need to write is some JSS in the source record's workflow that, before cloning itself to a target record :
1. works out what the source version and components are (which is easy)
2. 'knows' what the target project is (in my case this will always be the same)
[ I assume the com.atlassian.jira.bc.project package is used for this, but I don't know how ]
3. works out if the source versions and components already exist in the target project
[ some kind of looping is clearly required here; I know the looping syntax but not the JIRA functions required ]
4. adds new versions and components to the target project
[ I don't know how to do this either ]
This will allow the workflow 'Copy Issue Function' (or JSS, if I give up using 'CustomWare JIRA Utilities') to directly clone a record from a source project to a target record in a different project, including source version and component fields.
Without this fix, if you attempt to clone version and component fields from one project into another that doesn't know what these versions or components are, the target fields just say 'unknown'. This isn't a JSS problem; I think it's expected JIRA functionality (on my system, at least); you're supposed to set up versions and components at a project level before assigning records to them - but I'm sure JSS could add these version and component values to the project automatically it if only I could work out how.
I think the problem, for me, is that most JSS scripting examples are at the issue rather than the project level, so I have little precedent I can use.
Any and all help would be absurdly gratefully received.
Alexander Shchagin
Hi Adam, I'll try to give you some clues.
Just look into JIRA javadocs for more details:
VersionManager.createVersion()
ProjectComponentManager.create()
BR, Alex
Unknown User (ohingardail)
Thanks, Alex.
For what its worth, here is an example of a post-function script designed to ensure that the fixVersion, affectedVersion and component values in the source record (in project 'A') are in the target project (project 'B'), thus allowing the subsequent copying of version values from record in project 'A' to a record in project 'B'. The script is put in the post-functions workflow for a transition that subsequently creates the new (project 'B') record.
If you want to work out what the key names to use for GenericValues (in the example above, the 'component' value was a GenericValue, so I needed to use "component.getString('description')" rather than "component.getDescription()") then you can use the "print str(component.getAllFields)" construct to dump the key-value pairs out to {JIRA_HOME}/logs/catalina.out; in this example they looked like "[GenericEntity:Component][id,10003][project,10020][description,null][name,CNS][lead,null][assigneetype,0][url,null]" which was enough for me to work out how to extract component names etc.
Hope this helps someone.
Unknown User (brian)
Extremely nice work! Thanks for sharing!
Unknown User (hmenzi)
I want to set the assignee of an issue to the value of a user picker custom field. Below is the code I have so far. The script fails on issueObject.getCustomFieldValue(manager) with a null pointer exception. Can someone point me in the right direction?
Alexander Shchagin
Hi Hans,
If you are trying to write a postfunction script, instead of
you should use this
JSS passes some context to the script, and issue variable is set the current issue for which the postfunction is being executed.
BR, Alex
Unknown User (mahku)
Hi Hans,
In this line of code, that is, 'issueObject = issueFactory.getIssue()', we will get a blank issue object of type 'com.atlassian.jira.issue.MutableIssue'(an interface) which extends 'com.atlassian.jira.issue.Issue'(an interface). As it gives us a blank issue object, we can't get any data/info.
If you want any data/info from current issue, then you can directly use the context variable 'issue' in your code. For example, replace 'assigneeManager = issueObject.getCustomFieldValue(manager)' line with 'assigneeManager = issue.getCustomFieldValue(manager)' line. Also replace 'issueObject.setAssignee(assigneeManager)' line with 'issue.setAssignee(assigneeManager)' line. Please observe that i have just replaced 'issueObject' with context variable 'issue'. Finally you can remove 'issueObject = issueFactory.getIssue()' line, as there is no use of this line so far.
This solution works fine only with current issue. But if you want to change the existing issues or create new issues, then you have to follow some other steps/ways.
I hope it helps you.
BR, mahku.
Unknown User (hmenzi)
Thanks to both Alex and mahku. I now have it working properly and have a better understanding.
Unknown User (kewwordtest)
Hi Alex,
jss is perfect. Now, I have a problem that I don't know how to debug. I worte a script but it didn't work. And nothing could be found at catalina.out.
Best Regrads.
Alexander Shchagin
Hi,
Actually the only way to debug is to print out some intermediate values and watch console output (particularly catalina.out in JIRA Standalone; I use
tail -f catalina.out
under Linux). Also you can use injectedlog
variable, but unless you have some special log configuration it's all the same.I suggest putting one of these in the beginning of your script just to be sure the script is executed:
The next step is using
try
andcatch
to get more info if smth goes wrong:Hope this helps.
BR, Alex
Unknown User (kewwordtest)
Thank you.
Unknown User (daregazi)
Hi Alex,
I would like to thank you for JSS. It's great!
Now imagin that I have 4 steps in my workflow. From step 1 and 2 and 3 there is a transition to step 4 say 'Goto4'. From step 4 also there are transitions to go back to those steps e.g. Goto1, Goto2, Goto3 however from step 4 I want to be able to go exactly to the original step that it came from. For example if the transition was from step 1 to step4, in return in step 4 and on transition Goto1 I want to be able to check if the original step was step 1 then to show only Goto1. Without such control, all Goto1, Goto2, Goto3 would get displayed to the user which is not what I want!
What is the best practice to do it?
thanks
Alexander Shchagin
Hi Beheshteh,
I use JIRA Misc Workflow Extensions plugin, it contains Previous Status condition - that's exactly what you need.
BR, Alex
Unknown User (daregazi)
Great!
Helped me a lot! Exactly what we needed. Thanks.
Unknown User (xerocube)
Hi Alex,
I am new to JSS, but it appears that it can solve my problem. In our workflow, we want to be able to check an issue on creation for it's Fix version. If the Fix Version is "unknown", we want to automatically set that field to the next project version set for release.
My psuedocode is as follows:
I am not certain how to iterate through the versions collection to find the next slated release, or if that is even possible.
Could you please provide some assistance/advise?
Thanks!
Unknown User (hmenzi)
Taking a look at this for reference, I would try something like this:
Hope that points you in the right direction.
Hans
Unknown User (hmenzi)
Taking a look at this for reference, I would try something like this:
Hope that points you in the right direction.
Hans
Unknown User (brian)
We are currently using JIRA 4.0.2 and used JSS version 0.2. Mentioned here was that you could use JSS to copy a parent's components and fix version/s. This is all the Jython code I have in the sub-task workflow's create transition's post function, is this correct? I've tested one of the validations mentioned in the JSS validation code snippits so I know that I have installed Jython and the JSS plug-in correctly, but this snippet doesn't appear to be doing anything.
Any help to be had out there?
Unknown User (dariam)
Hi all!!
I'm trying to make a postfunction which fills a custom field (Department) depending on one of the user's groups (starting with GD_). The custom field is a "Select List".
Something is wrong because the custom field is not updated.
Any help??
Thx!!!
Unknown User (e.kubascikova@corag.sk)
Hi,
try this
Alexander Shchagin
Adam, Brian, David,
May I give you a little debugging hint: use simple
print
command in any case when you are not sure. Python is a scripting language and thus doesn't have any compile-time type checking. That's why sometimes it is very hard to know what is the actual type and value the method returns. So my advise is: useprint
often and look to JIRA log for its output. It will save you a lot of time.BR, Alex
Unknown User (brian)
Will do, thanks Alex!
Unknown User (hmenzi)
I am trying to automatically perform a workflow action if a released version is affected or not. I think the problem I am having is with the workflow transition utility. I get no errors or warnings in the logs. Can someone point me in the right direction? Thanks in advance.
Unknown User (wufei)
Hi,
I've installed the Jira 4.1 and the Scripting Suite plugin recently and I'm trying to script something to update a custom field value, but I'm encountering some problems.
I was initially using the issue.setCustomFieldValue(customFieldObject1, 'None') to update the custom field value. It seems to work since I see the change in the History and the EAR page is refreshed with the new value.
The problem is that I read from this link (http://confluence.atlassian.com/pages/viewpage.action?pageId=160835) that setCustomFieldValue does not actually set the custom field value of an issue. The doesn't apply the change to the database. To update a custom field value on an issue, I need to use the method updateValue on the CustomField object itself.
Writing this in Java would be simple since there is a sample code on that page, but in Jython, it doesn't seem to recognize the ModifiedValue constructor method. The weird thing is that on this page, they are only using setCustomFieldValue and there are no example using the ModifiedValue class constructor.
I would appreciate to have a sample code that would show me how to call the updateValue method with the ModifiedValue constructor in the context of Jira Scripting Suite.
Thanks in advance,
Wufei
Alexander Shchagin
Hi Wufei,
This is a bit tricky, but in Jython postfunction you should really use setCustomFieldValue. This works because you modify the issue object before it is actually committed to the database. It's just like setting the field's value in the "Create Issue" or "Edit Issue" page. And this won't work if you, for instance, try to move the postfunction beyond "Creates the issue originally." in the Create Issue action, because issue.setCustomFieldValue() really does not modify the database; if you are out of Jython context - you should use the method from that article.
BR. Alex
Unknown User (wufei)
Thanks Alexander for your fast reply. I really appreciate it.
I have some other issues. I've installed JSS 0.3.1 and Jira Standalone 4.1.1.
1- I'm wondering if there is a way to add JSS script to validate some fields when the user is Editing or Creating a specific type of issue before updating the changes?
2- I'm wondering if there is a way to add JSS post-function script when the user is Editing or Creating a specific type of issue?
I've read the thread (http://forums.atlassian.com/thread.jspa?messageID=257343226) related to this issue, but since I want my script to be specific to a particular type of issue instead of applying it globally and because I want to add this on creation also, I thought I may get a different answer.
Thanks in advance
Wufei
Alexander Shchagin
Hi Wufei,
Both on-edit validator and on-edit post-function are global, that is, you should check issue type, project and other attributes inside your script.
On-create validators and postfunctions are defined in the workflow. If you use a single workflow for many issue types, you should also check issue attributes inside your script.
BR, Alex
Unknown User (wufei)
Hi,
With the JSS "Edit Postfunction", how can I know if a specific field has been modified?
The context is that I need to know if the "Description" field value has been modified during the any issue editing to automatically add a new Comment on its parent issue. If the Description didn't change during the Edit step, then no Comment should be added to the parent issue.
How can you do this?
Thanks in advance,
Alexander Shchagin
I suppose you can get the original unmodified issue object by calling
and then compare descriptions.
BR, Alex
Unknown User (wufei)
I finally did this in my post-function, hoping that it may help someone else one day:
modifiedValues = issue.getModifiedFields()
if modifiedValues.containsKey("description"):
modifiedDescrption = modifiedValues.get("description")
if modifiedDescrption.getOldValue() != modifiedDescription.getNewValue():
parentIssue = issue.getParentObject()
commentManager = ComponentManager.getInstance().getCommentManager()
comment = "Sub-issue's Description from \"" + issue.getSummary() + "\" has been updated to \"" + modifiedDescription.getNewValue() + "\""
authenticationContext = ComponentManager.getInstance().getJiraAuthenticationContext()
commentManager.create(parentIssue, authenticationContext.getUser().toString(), comment, True)
Thanks again for your reply! :)
Unknown User (tkrug0210)
Would it be possible to contact a database and update custom fields based on sql resultsets and vice versa?
Alexander Shchagin
Hi Thomas,
I think this can be done with JDBC, but I can't provide any example right away.
Alex
Unknown User (tkrug0210)
Hi Alex,
i found a small example:
Executing this gives me a ClassNotFound Exception for com.mysql.jdbc.Driver. Do you know where I have to place the jar for Jython to find it?
Simply copying it to the lib folder does not resolve this issue.
Thomas
Alexander Shchagin
Hi Thomas,
Try to put it into tomcat's
lib
orcommon/lib
folder. Furthermore, JIRA 4.1 seems to have mysql driver bundled into distribution. Which version of JIRA do you use?Alex
Unknown User (tkrug0210)
Hi Alex,
I am using Jira 4.0.1.
Jira itself uses a MySQL Database and thus the driver is already in tomcats lib.
I extracted the JAR on put it the foldes directly into the /python/lib folder, without effect.
The following exception is thrown:
root cause: Traceback (most recent call last): File "d:\jira\data\jss\jython\workflow\mysql_test.py", line 12, in <module> Class.forName(driverName) at org.apache.felix.framework.searchpolicy.R4SearchPolicyCore.findClass(R4SearchPolicyCore.java:198) at org.apache.felix.framework.searchpolicy.R4SearchPolicy.findClass(R4SearchPolicy.java:45) at org.apache.felix.framework.searchpolicy.ContentClassLoader.loadClass(ContentClassLoader.java:109) at java.lang.ClassLoader.loadClass(ClassLoader.java:248) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:169) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) java.lang.ClassNotFoundException: java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
root cause: Traceback (most recent call last): File "d:\jira\data\jss\jython\workflow\mysql_test.py", line 12, in <module> Class.forName(driverName) at org.apache.felix.framework.searchpolicy.R4SearchPolicyCore.findClass(R4SearchPolicyCore.java:198) at org.apache.felix.framework.searchpolicy.R4SearchPolicy.findClass(R4SearchPolicy.java:45) at org.apache.felix.framework.searchpolicy.ContentClassLoader.loadClass(ContentClassLoader.java:109) at java.lang.ClassLoader.loadClass(ClassLoader.java:248) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:169) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) java.lang.ClassNotFoundException: java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
Unknown User (tkrug0210)
Classpath Problem is solved. The JAR has to be placed within your JSS Jar (WEB-INF/Lib) in order for Apache Felix to find it.
Alexander Shchagin
Thomas, thanks for the info!
Unknown User (justforthee)
Hi Thomas,
I'm still stuck with the mysql jar classpath problem in JSS. I have tried putting the jdbc jar in everywhere, but no luck. By the way, I can call jdbc in jython's console because the jar was defined in classpath before executed. And surely jdbc driver has been in tomcat's lib since I can call jdbc in a JSP page within JIRA.
Can you please explain exactly which folder the jar should be put in? I'm using JIRA4.0.0 and jython2.5.0 in Windows2003, and trying to get JSS working in post function where I want to connect MYSQL database... Thanks in advance!
Unknown User (gturner)
I have a workflow where a required field can start out at an initial value if submitted thru an external interface, but I want to make sure it never has that value from here on out. I can place checks in each of the subsequent transitions, but I'd also like to validate it in the edit screen as well. My experience with this plugin is showing that the issue object in the global 'edit_validator.py' file doesn't contain the changes made in the edit screen itself. I'm using Jira v4.0. The same code works great in individual workflow tasks. Anyone else have any luck using this file?
Alexander Shchagin
Hi Greg,
There is a difference between the context of the workflow validator and the one of edit validator. In the edit validation script you should check
parameters
map to get values from the screen. You can compare withissue
object which is a original one to find changed values.BR, Alex
Unknown User (niki89g)
Hi,
I've only just started getting my hands dirty with JSS. I've tried Thomas's code to generate sub-tasks on the inititation of a workflow..but it doesn't seem to be doing anything at all? Will this be because i've just included this in inline script instead of a .py file?
Also, How will Jira know that this post function needs to be fired off only when a particular workflow is initiated and not for every workflow transition? Pardon my possible ignorance. I've only installed JSS yesterday, and have been trying to achieve the automatic generation of sub-tasks when a workflow is initiated.
Any help will be much appreciated.
Alexander Shchagin
Hi Nikhita,
If you want some script to be executed on issue creation, then you should add it to Create Issue action in you workflow. You can find it by navigating to the first status (usually Open) and looking to the incoming actions.
BR, Alex
Unknown User (hitthedrum)
Hi there!
I am all new to this plugin and wanted to ask, if it is possible to validate worklog entries (any fields)?
Examples:
1. if anyone enters 3h 55m to the "Time Spent" field I want to change the value to 4h or
2. if anyone enters more than 8h I want to show up an error message like "Just 8 hours per entry allowed".
3. if anyone enters values into "Set estimated time remaining" or "Reduce estimated time remainin" I want to check, if modulo 4h = 0
Thx and regards!
Marc
Alexander Shchagin
Hi Marc,
I think the only thing possible with JSS now is to add a listener for Issue Work Logged event (you can do some updates in that listener script), but there is no way for validating worklog values being entered.
Alex
Unknown User (toini)
Hi!
I would need perform some custom operations after a person has logged work on an issue. How can I add a listener for an Issue Work Logged event?
Toni
Unknown User (gisela.sn)
Hi Alexander,
could you help to create a code to post a work log?
I find this code but I don´t know how to make in phyton...
jiraServiceContext = new JiraServiceContextImpl(user)
worklogService = (WorklogService) ComponentManager.getComponentInstanceOfType(WorklogService.class)
worklogService.hasPermissionToCreate(jiraServiceContext, issue)
worklog = worklogService.validateCreate(jiraServiceContext, issue, tsValue, new Date(), "Work logged while resolving issue", null, null)
worklogWithRemainingEstimate = new WorklogService.WorklogNewEstimateResult(worklog, 0)
worklogService.createWithNewRemainingEstimate(jiraServiceContext, worklogWithRemainingEstimate, true)
Unknown User (dan.sexton)
How can you use today's date and store it into a customfield of date data type?
This is what I have:
from com.atlassian.jira import ManagerFactory
import com.atlassian.jira.issue.CustomFieldManager
import datetime
from datetime import date
today = date.today()
if date.weekday(today) < 3:
nextSaturday = today + datetime.timedelta(days=(5-today.weekday()))
elif date.weekday(today) < 6:
nextSaturday = today + datetime.timedelta(days=(5-today.weekday()), weeks=1)
else:
nextSaturday = today + datetime.timedelta(days=-1, weeks=1)
toTime = time.mktime(nextSaturday.timetuple())
final = time.strftime("%Y-%m-%d %H:%M:%S.000000000", time.localtime(toTime))
customFieldManager = ComponentManager.getInstance().getCustomFieldManager()
sprintDateField = customFieldManager.getCustomFieldObjectByName("Sprint Date")
issue.setCustomFieldValue(sprintDateField,final)
Alexander Shchagin
Hi Dan,
This may be a little bit late, but nevertheless - I think you should convert your
final
date to java.util.Date before setting the value to custom field.Alex
Unknown User (robert)
Hi Alex,
How to convert
final
date to java.util.Date?thanks
Unknown User (cdnexus)
Any idea why this attempt to copy two custom fields from the parent issue in a post function fails? It runs but apparently has no effect.
Thanks for your time.
Alexander Shchagin
Hi Chris,
Try a simple
issue.setCustomFieldValue(customField,newValue)
call to set a value of custom field in a postfunction. Note that your postfunction should be called before "Update change history for an issue and store the issue in the database.".Alex
Unknown User (cdnexus)
Posting for future searchers: This is performed on the Subtask's create event post-events:Updates custom fields from the parent successfully:Thanks for your help Alex.
Unknown User (cdnexus)
Unknown User (gisela.sn)
Hi, I´m trying to use the setComponents to copy the subtasks components to the parent issue, but don´t work, I found some samples but no one work, anyone know how to update this field? Other updates works, like setAssignee.
import com.atlassian.jira.ComponentManager
compManager = ComponentManager.getInstance()
IssueManager = compManager.getIssueManager()
commentManager = compManager.getCommentManager()
IssueManager = compManager.getIssueManager()
issuepai = issue.getParentObject()
issuepai = IssueManager.getIssueObject(issuepai.getKey())
subtasks = issuepai.getSubTaskObjects()
componentes = issue.getComponents()
issuepai.setAssignee(issue.getAssignee())
issuepai.store()
issuepai.setComponents(componentes)
issuepai.store()
Alexander Shchagin
Hi Gisela,
This is actually not a good way of updating issues that are not in context. You can use setters on
issue
(and you don't even need to callstore()
) in a post-function, but you should find some other proper way of updatingissuepai
. In this case you've lost change history and search index becomes out of sync.Alex
Unknown User (speimann@curtisswright.com)
Folks,
I am trying to build a transition that selects between one of two states depending on a logic tree based on various field values (both old and new).
My understanding is that JIRA Scripting Suite is a very good way to accomplish this goal.
The only example I see is the one that Hans posted on Jun 02. I assume that this is being placed into a transition "post function".
Is that the best way to go about implementing a computed transition?
Thank You All,
Scott
Unknown User (gongqifang)
Hi,Alex
I have add a validator use Jython Validator,"size" is a customfield of type Text Field(<255 characters) .I thought this might work
which does not. Can you help me with the correct code?
The error thrown is
root cause: SyntaxError: ("mismatched input 'result' expecting INDENT", ('<string>', 5, 0, 'result = False\n'))
Unknown User (speimann@curtisswright.com)
gonggifang,
You need to indent the consequent and alternate of the conditional statement (line 4)
Good Luck!
Scott
Unknown User (gongqifang)
Yes! It works,
Thanks a lot, Scott.
Unknown User (speimann@curtisswright.com)
Folks,
I thought my IT people had JYthon installed, but apparently not. Still, I need to use JYthon to do some conditional updates in a post-function, based on issue attributes.
What I want to do is clear pairs of fields, based upon one of the values being 'Reject'.
In my sample, the ss1 through ss5 fields are select-lists, and the su1 through su5 fields are user-pickers.
Will this work, especially the string comparisons and the "null" assignments?
Alexander Shchagin
Hi Scott,
That should work, but in python (and jython as well) you should use
None
instead ofnull
.BR, Alex
Unknown User (speimann@curtisswright.com)
Good Morning Alex,
Thanks for looking through that for me. I appreciate the second set of eyes, as I'm still working with my I.T. folks to get the server configured.
Cheers!
Scott
Unknown User (gongqifang)
hi, Alex
I have wrote a postfunction to change the linked status during an transition,
from com.atlassian.jira import ComponentManager
from com.atlassian.jira.util import JiraUtils
from com.atlassian.jira.workflow import WorkflowTransitionUtilImpl
cfm=ComponentManager.getInstance().getCustomFieldManager()
curuser=ComponentManager.getInstance().getJiraAuthenticationContext().getUser()
reviewer1=issue.getCustomFieldValue(cfm.getCustomFieldObject("customfield_10049"))
reviewer1_output=issue.getCustomFieldValue(cfm.getCustomFieldObject("customfield_10055"))
reviewer2=issue.getCustomFieldValue(cfm.getCustomFieldObject("customfield_10153"))
reviewer2_output=issue.getCustomFieldValue(cfm.getCustomFieldObject("customfield_10152"))
if curuser==reviewer1:
if reviewer1_output=="pass":
if reviewer2 and reviewer2_output!="pass":
workflowTransitionUtil = JiraUtils.loadComponent(WorkflowTransitionUtilImpl)
workflowTransitionUtil.setAction(211) ====>go to another status "fixed"
workflowTransitionUtil.setIssue(issue)
workflowTransitionUtil.setUsername(curuser.getName())
workflowTransitionUtil.progress()
else:
workflowTransitionUtil = JiraUtils.loadComponent(WorkflowTransitionUtilImpl)
workflowTransitionUtil.setAction(151) =====>go to another status "analysis"
workflowTransitionUtil.setIssue(issue)
workflowTransitionUtil.setUsername(curuser.getName())
workflowTransitionUtil.progress()
elif curuser==reviewer2:
if reviewer2_output=="pass":
if reviewer1 and reviewer1_output!="pass":
workflowTransitionUtil = JiraUtils.loadComponent(WorkflowTransitionUtilImpl)
workflowTransitionUtil.setAction(211)
workflowTransitionUtil.setIssue(issue)
workflowTransitionUtil.setUsername(curuser.getName())
workflowTransitionUtil.progress()
else:
workflowTransitionUtil = JiraUtils.loadComponent(WorkflowTransitionUtilImpl)
workflowTransitionUtil.setAction(151)
workflowTransitionUtil.setIssue(issue)
workflowTransitionUtil.setUsername(curuser.getName())
workflowTransitionUtil.progress()
It does not work. Can you help me with the correct code?
The error thrown is
root cause: Traceback (most recent call last): File "<string>", line 20, in <module> at com.atlassian.jira.workflow.OSWorkflowManager.getWorkflow(OSWorkflowManager.java:308) at com.atlassian.jira.permission.PermissionContextImpl.getRelevantStepDescriptor(PermissionContextImpl.java:69) at com.atlassian.jira.permission.WorkflowPermissionFactory.getWorkflowPermissions(WorkflowPermissionFactory.java:30) at com.atlassian.jira.security.WorkflowBasedPermissionManager.hasPermission(WorkflowBasedPermissionManager.java:75) at sun.reflect.GeneratedMethodAccessor368.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at com.atlassian.util.profiling.object.ObjectProfiler.profiledInvoke(ObjectProfiler.java:70) at com.atlassian.jira.config.component.SwitchingInvocationHandler.invoke(SwitchingInvocationHandler.java:28) at $Proxy32.hasPermission(Unknown Source) at com.atlassian.jira.issue.fields.AttachmentSystemField.isShown(AttachmentSystemField.java:104) at com.atlassian.jira.issue.fields.screen.AbstractFieldScreenLayoutItem.isShown(AbstractFieldScreenLayoutItem.java:82) at com.atlassian.jira.issue.fields.screen.FieldScreenRenderLayoutItemImpl.isShow(FieldScreenRenderLayoutItemImpl.java:68) at com.atlassian.jira.workflow.WorkflowTransitionUtilImpl.progress(WorkflowTransitionUtilImpl.java:262) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) java.lang.IllegalArgumentException: java.lang.IllegalArgumentException: Issue Type for issue with id '10150' is null.
It seems that Issue Type is NULL,but actual the Issue Type is not null, the valuse is "Bug"
Unknown User (tkrug0210)
Hi,
I am currently trying to modify the watcher list via jython script. The script looks like this:
This code throws a NullPointerException
com.atlassian.core.ofbiz.association.DefaultAssociationManager.createAssociation(DefaultAssociationManager.java:84) at com.atlassian.jira.issue.watchers.DefaultWatcherManager.startWatching(DefaultWatcherManager.java:111) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) java.lang.NullPointerException: java.lang.NullPointerException
Can anybody help me on this?
Alexander Shchagin
Possibly there is no user with login
testuser
.Alex
Unknown User (tkrug0210)
OMG. Typo in Username........
At least we now have an example how to add watchers via JSS Plugin :-)
Thomas
Unknown User (speimann@curtisswright.com)
So the question then becomes one of how to properly interrupt the processing sequence and roll back work, when there is an error like Thomas'.
Is the best answer to just let JIRA dump, or is there a more graceful recovery?
Unknown User (tkrug0210)
Letting Jira dump is definitely be no solution for me since I don't want my customers to see any stack traces. Jira does implement quite a lot checking methods returning boolean values (isInGroup() etc.). I just neglegted using them in my code.
A message "User does not exist" is more helpfull than a NullPointerException.
Unknown User (zoom.license@zoomint.com)
HI,
in JSS 1.0 this is not working:
invalid_fields['Component/s'] = 'You do not have permission to select component!'
i haven't got any error message, but "my error message" is not displayed on page.
Thanks
Alexander Shchagin
Hi Tibor,
You should use fields' id, not their names:
Unknown User (mbeaudoin)
Everyone, wondering why I cannot get any value out of my nb_comments variable, yes there are comment on the issue, any help more than welcome
Wondering if I use proiperly the getComments(issue) method...
TIA, MB
commentManager = ComponentManager.getInstance().getCommentManager()
customFieldManager = ComponentManager.getInstance().getCustomFieldManager()
nb_comments = commentManager.getComments(issue)
customField = customFieldManager.getCustomFieldObjectByName("Quality index")
issue.setCustomFieldValue(customField,"test:" + nb_comments.size.toString())
Unknown User (speimann@curtisswright.com)
Marc,
It looks like you left out a pair of parentheses in the fifth line after "size". Try:
but I'm not all that good with Jython, yet.
Cheers,
Scott
Unknown User (mbeaudoin)
Thanks for your quick reply Scott,
Those parentheses were definately missing but there is no such method as toString for int type here is what works for me now, hope this might help someone else ;)
commentManager = ComponentManager.getInstance().getCommentManager()
customFieldManager = ComponentManager.getInstance().getCustomFieldManager()
nb_comments = commentManager.getComments(issue)
customField = customFieldManager.getCustomFieldObjectByName("Quality index")
issue.setCustomFieldValue(customField,"test:" + str(nb_comments.size()))
Unknown User (speimann@curtisswright.com)
Marc,
Good observation on the int type. For some reason, even though I checked the documentation, I was thinking Integer return type.
I'm glad it's working.
Unknown User (lucb)
Hi,
I have added custom fields to have some emails of person that are not jira user and send them email, I can have the events when the issue status change (workflow) or when the description change but I'm unable to have an event when a comment is added. Is there a possibility to have a script firing when a comment is added ?
Thanks
Unknown User (speimann@curtisswright.com)
Luc,
This capability exists in standard notifications. There is no real need to use JSS for this capability.
Cheers,
Scott
Unknown User (lucb)
Thanks Scott but it's not helpfull in this case. Some peoples haven't a Jira Account, they can add a bug request in another system, an old system. In this system they can add a bug (for exemple) in a particular application and they will receive the statuses (fixed, on test, etc). I want to perform the work in Jira (time sheet, backlog, priorities, better events, worflow...) but have to send the comments the programmer do to the responsible of this entry. I can't use the notification because I must have one system per person... I can't use observer because the user must have a Jira login...So the idea is to send an email with this new comment to this person (Jira will receive all reply and add it to the comment issue).
Unknown User (speimann@curtisswright.com)
Luc, I see what you mean. My fault in that I misunderstood what I was reading.
Sounds like you want to implement a scripted post-function that reads the appropriate field, and then uses the JIRA e-mail API to send the message you want.
Kind of a pain in the tail, because you have to drop a copy of your function on workflow transitions to deal with the obvious cases.
As far as adding a notification handler, I don't think that Atlassian has gotten to the point where they allow developers to add new options through the plug-in system. Perhaps you will want to file an upgrade suggestion? Also, ask on the forums - there may be some one who can help.
Of course, under Linux, you could send a message to a handler address. You could then hang an e-Mail handler script, which broke down the message and forwarded it to the appropriate individuals. It'll be a bit of a difficult undertaking, but as a stop-gap, it might work.
Luck!
Unknown User (lucb)
Yes, I have started the application with a link of email...not so nice but working well. Thanks for your help Scott !
Unknown User (cdnexus)
Attempting to create a post function to modify the status of an issue after it is transitioned to the target state:
Have tried a number of different ways, the JIRA API is a little light on details in many areas.
I tried issue.setStatusId('1') for instance will corrupt an issue.
The end goal of this is to create an admin transition for a workflow with ~40 states.
Creating an individual transition from each state to every other state would be both a burden to me and the user.
http://www.customware.net/repository/pages/viewpage.action?pageId=8093744
Also seemed to be of interest. But once again tha API on these classes was a bit light on for my level of experience with JIRA.
Unknown User (speimann@curtisswright.com)
Chris,
I apprecitate what you want to do, as I have a similar scaling problem with a workflow that requires five approvals in any order.
I think you may need to open the cast the issue into a MutableIssue.
Lastly, and I don't know if this is the correct approach or not, try using something like:
issue.setStatus(stateNumber.toString())
Looking at the documentation (http://docs.atlassian.com/software/jira/docs/api/latest/com/atlassian/jira/issue/MutableIssue.html ) shows that MutableIssue.setStatus() wants a String, not an integer type
Good Luck!
Scott
Unknown User (cdnexus)
setStatus
void setStatus(org.ofbiz.core.entity.GenericValue status)
setStatusId
void setStatusId(String statusId)
Set issue's status by status id ("1", "2" etc).
Parameters:statusId- the new StatusId.
I think you meant statusId, and I did try that. After modifying this value using the SetStatusId value, I could no longer get the status for the issue (which caused all sorts of problems) and had to delete the record directly from the database. I will give it another shot.
Unknown User (speimann@curtisswright.com)
Chris,
You're right. The correct method is setStatusId.
Did you try using strings in your Jython code, instead of small integer values.
Looking back, on Dec 22, Mark used the str function to change an integer value to a string, so your code might be
The other issue may be that your stateNumber values may not all be correct. You may have to look them up by "name".
When I look through a XML dump of my development database, I see that "Status" values that I create (beyond the original five from Atlassian) are numbered sequentially from 10000. That may be part of your problem.
Cheers!
Scott
Unknown User (speimann@curtisswright.com)
Chris,
I just noticed that the status values are shown in the "History" at the bottom of the Issue View screen.
So, if you run an issue through all states, you should have your mapping right there.
I still think it would be much smarter to look up the statuses by name, though. They are of class "IssueConstant", now all we have to do is find the manager that looks them up, or provides the whole set of them.
Luck!
Scott
Unknown User (cdnexus)
Progress! That was the issue. Was using the Workflow ID for the state rather than the Globally unique issue id.
Has worked, however although the issue status changes, the options that are available and transitions suggest JIRA still thinks the issue is in the previous state.
If I transition away from the initial state,
no transition is recorded, as it still assumes the end state was the one set at the end of the transition.
Questions:
Why does JIRA still think the issue is in the previous state despite the issue field displaying the correct indended state, how can I change that?
How can I get the transition history to be correct.
Edit: It appears workflow state and issue state aren't directly linked. I assume this is handled by OSWorkflow in the background.
The question becomes is it possilble to use the conditional results in OSWorkflow to achieve my goal in combination with JSS. Seaching the forums has given me around 5 people who have attempted to make this kind of transmission, none have a posted solution.
Is it possible to direct an issue to a state in OS workflow without having seperate transitions to call in each case....?
If not, it is going to make JIRA a PITA to use for workflows with a large number of states.
Another possiblility that just occurred to me is to use a dummy state, containing all my transactions. An "admin transition" state if you will.
All states use a common transition to this state, and automatically transition out again. The user won't even need to see this state as the post function on the common transition to this state could take care of this second transaction.
Unknown User (speimann@curtisswright.com)
Chris,
This probably isn't the forum for this discussion, if we're considering workflow architecture. As I understand it, this is a discussion forum for use of the JIRA Scripting Suite plug-in.
Still, let me ask a question - what is the value in giving the ability to violate the workflow of your application?
Honestly, it sounds like you have a design problem, if you're providing an easy means of simply and arbitrarily coercing issue status. The reason I mention this is that when such an ability exists, managers tend to ignore the application structure and data flows that they are asking every-one else to follow. It starts out as an administrative feature, and one-by-one, management will have themselves added to the administrators list. At some point, some one violates something, and data are lost, or worse. At best, you have an internal audit failure, and your managers are held accountable. At worst, you have a major problem, leaving you holding the stinky end of the stick.
Please forgive my preaching, but a much better approach is to make sure that there is an appropriate permission structure, and all (including administrative) personel are required to follow the business rules. [In my case, this means that no data are ever erased, meaning that all updates are audit-trailed, etc...]
Needless to say, if there is a bug in the workflow, that can be rectified fairly quickly. If there is a bug in a validation rule, its pretty easy to fix, too (except for ones that are hard-coded as part of plug-ins). Data errors should be corrected by editing the data and supplying comments explaining the change, not by hacking the database.
One thing that I do in my workflows is give a special role "Administrator" permission to execute all transitions. I do this, as sometimes it is strictly necessary to administratively force a transition or data edit. However, this override does not void any of the data validation or other business rules that I have implemented in my applications. The beauty here is that when an "Administrator" does force something, the audit trail records the activity. Since "Administrator" is a separate role, and not an account, I can actually control who has override on any particular project. This means that I do not have managers using a "jira-administrator" account to anonymously manipulate data.
All that said, this is what my management asked me to do. They chafe about it sometimes, however we do not have the types of quality audit problems that we had in the past.
Ok, I'm sorry for descending into a lecture like that, it's just that I've seen this happen enough times to make me reluctant to build the capability to violate application structure. If you have a architecture problem, fix it, instead.
Cheers!
Scott
Unknown User (zoom.license@zoomint.com)
Hi,
statement invalid_fields doesn't work on affects version/s field for me. I tried a lot of combinations of field name but no success. If I tried it for summary field it worked fine/
What I have to write inside?
invalid_fields['XXXXXXXXXXX']
thx
Unknown User (speimann@curtisswright.com)
Tibor,
Try using invalid_fields['versions'], and see if that cures what ails you.
Cheers,
Scott
Unknown User (mhuerta)
Hi Alexander,
I am hoping to use this plugin to create a post function that will let me dynamically set the Greenhopper Rank field to the "lowest" rank for the project upon closing the issue. The Greenhopper API is not documented anywhere, but I am thinking this might be possible by retriveing all of ranks for the current project, and then finding the lowest rank and setting the current issue to this value. Would this be possible?
Cheers,
Micah
Unknown User (skloehr)
I am new with python and trying to build a post script function based on the example. I have a custom field called Approver that is not initially required but will eventually be emailed at the Ready for Approval Step in the workflow so it needs to be populated when the transition occurs . I am getting this error:
ERRORIt seems that you have tried to perform an illegal workflow operation. If you think this message is wrong, please consult your administrators about getting the necessary permissions.
Form Errorroot cause: Traceback (most recent call last): File "/opt/jira/jss/jython/workflow/send_approval_notification_post.py", line 15, in <module> invalid_fields['customfield_10010'] = u'Issue does not contain a valid approver.' NameError: name 'invalid_fields' is not defined
This is the code I have at the ready for approval transition as a post function.
import com.atlassian.jira.ComponentManager
import com.atlassian.jira.issue.CustomFieldManager
import com.atlassian.jira.issue.fields.CustomField
from urlparse import urlparse
cfm = ComponentManager.getInstance().getCustomFieldManager()
cf = cfm.getCustomFieldObjectByName("Approver")
approver = issue.getCustomFieldValue(cf)
assignee = issue.getAssignee()
issuekey = str(issue.getKey())
if not approver :
result = False
invalid_fields'customfield_10010' = u"Issue does not contain a valid approver."
description = "Edit the issue and specify an Approver."
o = urlparse('http://JiraServer01:8090/browse/' + issuekey)
sender = assignee.getEmail()
to = approver.getEmail()
subj = "Issue %s is ready for approval" % issuekey
body = """<b>Action is required to put this issue in production.</b><p>
<b>Issue Key:</b> %s<p><b>Issue Description:</b> %s<p>
Please click on the link below and after logging in with your network credentials, you will be
able to get more details about the issue.<p>
If you approve of the implementation, click on the
Approve button near the top of the issue:<p>
<a href=\"%s\">%s</a>""" % (issuekey, issue.getSummary(), o.geturl(), o.geturl())
server = 'smtp.mmplp.net'
from email.MIMEText import MIMEText
msg = MIMEText(body, 'html', 'utf-8')
msg'Subject' = subj
msg'To' = to
msg'Importance' = 'high'
import smtplib
s = smtplib.SMTP(server)
s.sendmail(sender, to, msg.as_string())
s.quit()
I have tried several different ways to gracefully notify when there is no approver but I am stuck. Any ideas?
Thanks,
Steve
Alexander Shchagin
Hi Steve,
You can't use
invalid_fields
in post-function. You should divide your script into two parts: a validator to check the fields, and a post-function to do actual work.BR, Alex
Unknown User (rfrizzel)
I'm sure I just am not seeing this, but I'm trying to write a global validator and I cannot seem to get the original value of a custom field back to me in the script through the issue object. In fact, the issue object returns the new value of the custom field.
I want to make sure that the user comments if they change this particular date.
It is a date custom field, so you know the gyrations you have to do to dates in Java to get it to a string. Here's the code:
See anything obviously wrong?
Unknown User (brian)
Change an issue's issue type as a post-function during a transition:
I am fairly new to the JSS and my python is pretty basic, but I am trying to convert an issue to a bug during a transition and used the code below as my implementation.
issue.setIssueTypeId("1") #Convert issue from ... to bug
A question: is there anything wrong with this? For instance, will the issue be indexed properly, or was there any obvious things I forgot to do when changing this issue type like this?
Unknown User (speimann@curtisswright.com)
Brian,
Two things to consider - the issue type (bug) must be in the project and the goal state must be valid for the issue. I'm not sure if JIRA will correctly transition it between workflows or not, although I suspect it does.
Cheers,
Scott
Unknown User (brian)
Scott,
Thank you for your assistance! I have verified that the issue type is valid for the project, and that the work flows between any potential issue types using this transition and the bug issue type are compatible. We had to create a transition like this since JIRA does not really contain the concept of an "initial issue type". Some day the grief may vanish, but for now JSS to the rescue! Any other obvious errors for the trained eye?
Brian
Unknown User (speimann@curtisswright.com)
Brian,
In general it's awfully difficult to foul up one line of code, although I've done it on more than a few occasions.
This link points to an example of an issue type change made by Alex.
Hopefully it helps.
Alexander Shchagin
Actually never tried this, but my experience says this won't work. This method definitely won't change the associated workflow, and there may other problems.
You may try though, but not on the production JIRA instance.
Alex
Unknown User (mmccracken)
Can anyone tell me the proper way to get the IssueSecurityLevelManager?
In 4.2.4 is looks like it should be a simple islm = ManagerFactory.getIssueSecurityLevelManager() call but that does not seem to work.
Also, it appears to be depricated in 4.3.
What is the proper way to get at issue security levels?
Thanks
Mike
Unknown User (sylvainstg)
I am trying to run this simple script in the global post edit. It all works except the setting of the custom field value (the commented out line) I know the custom field object works as I am getting its description in the summary field.
if issue.getIssueTypeObject().isSubTask():
customFieldManager = ComponentManager.getInstance().getCustomFieldManager()
customField = customFieldManager.getCustomFieldObjectByName("Effort")
issue.setComponents(issue.getParentObject().getComponents())
issue.setDescription(customField.getDescription())
#issue.setCustomFieldValue(customField, new java.lang.Integer("10"))
----
Any hints would be greatly appreciated.
Thanks!
Sylvain
Unknown User (sylvainstg)
I have experimented further along the lines of what I trying to achieve and found another blocker.
In essence, I am trying to use this mechanism to update a numerical custom field that I will use as the data source of GreenHooper statistical marker.
Once understand how to set the custom field (ref: post above) I will need to calculate the number of hours in the "remaining effort" field. However, what should work according to the documentation simply does not.
I tried:
issue.getEstimate().toString()
issue.getOriginalEstimate().toString()
They both return an empty string... Any one know how I can get to the value of the remaining effort in the task?
Thanks,
Unknown User (brian)
Hello all. I had a question about retrieving members of a JIRA group, and creating a JIRA sub-task for each member of that group. There is a bit above about dynamically creating sub-tasks, but could anyone provide assistance/direction to get me started with respect to the groups part? Specifically, I would be getting the group from a group selector custom field. Thanks!
Unknown User (brian)
Heres the code to extract each of the members of a set of groups defined by a multi group selector custom field. Should provide a basic structure for anyone attempting to extract users from groups.
Unknown User (brian)
Does anyone know how to create an issue/sub-task that is already resolved? Apparently this is not sufficient to do this during the creation of the issue:
(Using most of the code in an earlier comment in this topic) I have been able to create subtasks, but not create resolved tasks. During certain conditions, we want to have queryable sub-tasks, but have them created and closed during a workflow transition. Any guidance to be had? I am still quite new at creating these scripts around JIRA, so any help would be greatly appreciated. Thanks very much.
Unknown User (matt.bates)
I think you'll have to transition the issue:
Unknown User (jbrinkley)
I'm having an problem trying to query issues using JSS in the Jython runner. First, when I would try to import JqlQueryBuilder from com.atlassian.jira.jql.builder it would not find it. I appended WEB-INF/classes to sys.path and it now finds the name to import, but the resulting JqlQueryBuilder type does not have the newBuilder() or other JqlQueryBuilder methods.
Does anyone have an example of querying for issues (preferably with JQL) from Jython?
Unknown User (matt.bates)
I use SearchProvider and DefaultJqlQueryParser, and it works really well:
Unknown User (jbrinkley)
Thanks for the reply!
When I try this example in the Jython runner, I get:
(I added the following lines for the ComponentManager and SearchProvider types):
This is a really helpful reply, maybe you could show a short complete script that runs in the Jython runner?
Thanks again!
Unknown User (matt.bates)
I've edited my reply above.
Unfortunately uou need to do something different to get a user in different contexts.
Unknown User (luca.andreatta)
I tried your script in Jython Runner in Jira 4.4.3, but I get this error message:
cannot import name DefaultJqlQueryParser
Can you help me?
Unknown User (thomas.krug)
I have the same problem as Luca. The DefaultUserManager did not work as well.
I kicked the Parser and used the JQLQueryBuilder instead. Workes like a charm:
Unknown User (zoom.license@zoomint.com)
Hi,
Please could someone tell me how Can I get information if user exists in custom filed of type "Participants of an issue". This field type comes from plugin JIRA Toolkit https://plugins.atlassian.com/plugin/details/5142?versionId=39062
I need to return false in validation if users exists.
I tried
but I received
root cause: Traceback (most recent call last): File "<string>", line 13, in <module> AttributeError: 'NoneType' object has no attribute 'toString'
thanks
Unknown User (speimann@curtisswright.com)
Tibor,
Probably your custom field returned a NULL value. Since null doesn't have a toString() method, you'll probably have to assign the result to a variable and test for null before you can test for the username.
Luck!
Scott
Unknown User (chintu)
Hi Alex,
I'm able to find whether the user selects "Automatic" in edit validator using parameters map. I got '-1' for parameters.get('assignee')[0].
We do not have parameters map in edit postfunction. How can I find whether user selected "Automatic" option in edit postfunction?
I tried to find whether the assignee field got changed using issue.getModifiedFields, even I did not touch assignee field, it got placed in ModifiedFields list.
I tried to go with action object, I have command like print action.assigneeChanged(), it has got error as follows:
print action.assigneeChanged()
AttributeError: 'com.quisapps.jira.plugin.action.EditIssue' object has no attribute 'assigneeChanged'
Could you please let me know how can I get to know whether the assignee got changed in issue edit post function, and if possible let me know how can I get whether user selects "Automatic" option.
Thanks in advance!
Chintu
Unknown User (matt.bates)
In the Global Edit Postfunction you need to use:
instead of just referencing the parameters variable
Unknown User (matt.bates)
Does anyone have an example of a working REST script they could share?
I have encountered two problems so far:
Unknown User (zoom.license@zoomint.com)
Hi all,
I don't know if this is bug, or I badly wrote it, but my code returning me strange numbers.
Script is VALIDATOR and should get username and look on comments for got username of current issue and check if size of array is bigger than 0. If yes it should not allow users to return issue with other then these resolutions.
Problem is that script didn't return comments for given username but for my account and I don't understand why. So if I commented issue it will not allow me to return and it doesn't matter if given user did or not comments.
Could somebody help me?
Thanks
Unknown User (zoom.license@zoomint.com)
sorry my mistake, i badly read description of getCommnetsForUser method
Unknown User (glewe)
Hi there,
not sure if this script can help us.
We use the Create & Link plugin to create issues in a different project. Both issues are then linked. Now we want a transition or field change in the linked issue to cause an automatic transition or field change in the parent issue. We are looking for a plugin to perform cross-project activities like that. Is this possible with this script?
Regards,
George
Unknown User (gopherr)
Great plugin! I'm learning a lot of this, including python/jython, as I go, but I thought I would post a short validation script that I have in place that will conditionally make one field required based on the value of another select list field. I apologize if a similar example is already included on this page, but I was not able to find it easily. If my code is not atrocious, maybe it could be added as a Code Snippet instead of here in the comments.
To include this validation in a particular workflow, simply create a draft of the workflow, find the appropriate Transition, click the Validators tab, click Add and select Jython Validator, and then place this code in the editor window.
Feedback on how to improve this simple logic is welcome.
Unknown User (muhammad_rahman@cable.comcast.com)
Hi,
What is "invalid_fields'customfield_10191'" representing here? Seems like the following code is not working for me
# This ensure that if resolution field value is Duplicate, Dup Ticket Id is required
from com.atlassian.jira import ComponentManager
customFieldManager = ComponentManager.getInstance().getCustomFieldManager()
# get resolution field value selected by user
Resolution_Field =issue.getResolution()
# get a custom field by its name
Cf_DupTicket = customFieldManager.getCustomFieldObjectByName("Dup Ticket ID")
DupTicket = issue.getCustomFieldValue(Cf_DupTicket)
if Resolution_Field=='Duplicate':
if not DupTicket:
result = False
invalid_fields['customfield_ 10630'] = u'Duplicating ticket id is required when Duplicate is selected'
description = 'Please review the custom validation error message/s below'
-MR
Unknown User (csit.jira.support@list.db.com)
Hi,
We want to add a validation while a user creates a ticket. If Reporter and Assignee is same, jira should throw an error !!
Anybody can help me with this ??
Thanks !!
Arpit
Unknown User (matt.bates)
I stand to be corrected but I think its the one case you can't do.
You can do Post Functions on Create with a Listener, but I don't think there is any way to do validation.
Unknown User (muhammad_rahman@cable.comcast.com)
It seem like the plug-in is still not compatible with JIRA-4.4 ( By looking into compatibility list ).
We are using plug-in version -1.0 with JIRA-4.3.4 and in a process of upgrading JIRA to latest (JIRA-4.4). This is blocking us in doing so. So, will it be possible to test this against JIRA-4.4 and release newer version compatible withJIRA-4.4?
We will appreciated if this can be done ( sooner ) so that the user community (like us) can continue using this great plug-in with latest JIRA..
Thank you.
Unknown User (eugenet)
just tried: both 1.0 and 1.1 are not compatible with JIRA 4.4 :(
Unknown User (korolkov)
Hi! I'm new to Jira and the Jython.
Could you please help me with the following:
I'm trying to create a post-function that puts the Reporter's Email into a custom field named "E-Mail".
I've installed your plugin but even without doing a thing I keep getting stuck at the "Edit" screen. I don't even get the name of the error, it just pops out an empty error.
What did I do wrong?
Also I wrote a script that is supposed to do the thing:
Is there smth wrong with the script?
Big thanks for your future assistance.
Unknown User (korolkov)
Hi again!
I solved the problem by editing the Jython Home Dir. It turned out just like this issue https://studio.plugins.atlassian.com/browse/JSS-1.
Unknown User (korolkov)
Hi again!
Could you help me with this script:
All I want to do is to change the project of the issue depending on a value from the custom field.
But it does nothing, just changes the value of the field.
Could you please tell me where is my mistake?
Unknown User (jrubial)
Hello,
I'm new with JSS I´m trying to create a sub-task in a post-function in JIRA 4.3.4 and jython 2.5.0, I based the following example:
from com.atlassian.jira.util import ImportUtils
from com.atlassian.jira import ManagerFactory
from org.ofbiz.core.entity import GenericValue
from com.atlassian.jira import ComponentManager
from com.atlassian.jira.issue import Issue
issueManager = ComponentManager.getInstance().getIssueManager()
issueFactory = ComponentManager.getInstance().getIssueFactory()
authenticationContext = ComponentManager.getInstance().getJiraAuthenticationContext()
subTaskManager = ComponentManager.getInstance().getSubTaskManager();
issueObject = issueFactory.getIssue()
issueObject.setProject(issue.getProjectObject()) --------------------> Have I missed something here??
issueObject.setIssueTypeId("5") # default sub-task issue type
issueObject.setParentId(issue.getId())
issueObject.setFixVersions(issue.getFixVersions())
issueObject.setAffectedVersions(issue.getAffectedVersions())
issueObject.setPriority(issue.getPriority())
issueObject.setSummary("Realisierung")
issueObject.setAssignee(issue.getAssignee())
subTask = issueManager.createIssue(authenticationContext.getUser(), issueObject)
subTaskManager.createSubTaskIssueLink(issue.getGenericValue(), subTask, authenticationContext.getUser())
The problem is that when I run the workflow transaction I get this error:
ERROR
root cause: Traceback (most recent call last): File "<string>", line 13, in <module> TypeError: setproject (): 1st arg can not be Coerced to org.ofbiz.core.entity.GenericValue
Help please
Unknown User (hmenzi)
Jamie,
I have the following JSS script that creates a sub-task in a post function working well in my jira (4.2.2). I hope this helps you out.
Unknown User (felix.martineau)
Since JIRA 4.3, you don't need to flush the CacheManager anymore, so the following will do the trick:
If you do not reindex the subtask, it will be created and will appear as a subtask when you view the parent issue, but it will not show up in searches until you do a full reindex
Unknown User (jrubial)
Is there any way to get data from a custom field that is a link issue from the parent issue?
Data are available on a issue from other issues?
Thanks
Unknown User (maciek)
Hello.
i would to update worklog in post function with jss script. This is for absence in work, e.g. vacation.
i must logwork absence on first day of absence and, if needed, on first day all next month where i'm out of work. (eg. if i have vacation beetween 20 September and 10 October, i have to logwork hours on 20/Sep/11 to end month, and 01/Oct/2011 to 10/Oct/11).
i have this:
The problem is: time tracking (in the view issue) showing only the last worklog, however Worklog in activity show all worklogs. I'll try to update issue always after create worklog, but with no result.
Somebody help?
Unknown User (maciek)
something news:
when i try to execute
i get error:
TimeTrackingIssueUpdater.updateIssueOnWorklogCreate(CurrentUser,wl, 0,False) TypeError: updateIssueOnWorklogCreate(): expected 5 args; got 4
but:
Unknown User (rpugal)
Hi Alex,
I have created one project role . I need to assign issue to that particular role while creating issue.
First of all i need to get User from particular role.
Is it possible in Jython script to get user of particular role and assign issue to that user.
I tried using Jira soap call in JSS
Exception i got is
login(): expected 3 args; got 2
Thanks
Pugal.
Unknown User (olivier.vandevoorde@securex.be)
Hi,
How to set a customfieldvalue of type com.atlassian.jira.issue.customfields.impl.NumberCFType
Thanks
Unknown User (sundale)
Greetings,
reading through the documentation I'm slightly confused as to when the object is committed and at what transition we place the code.
As a proof of concept and to understand the syntax and objects we are wishing to set the Summary and Add a Watcher based upon on the Project Role. We are wishing to do this on the initial user submission ie. initial create
Gluing together a code skeleton based upon other people's invaluable contributions
The above does not give us the desired result ie. it still has the user entered text, we thought we would end up with an issue with the Summary and Description set as per above. Any insight would be greatly appreciated.
Unknown User (hazbut)
I was of the assumption that the Global Postfunction would work out of the box. I can initiate a simple script in the Jython runner, yet the same code fails to fire the Global Postfunction inline or file script when transitioning an issue.
Is there a configuration I am missing here?
Unknown User (tkrug0210)
Hi,
I started experimenting with the transientVars map. My problem is that the Map is always empty thus the above example (appending the comment to a mail) returns a key error.
The same happens when iterating over the HashMap like
Anything I missed here?
Unknown User (srividhya)
Hi Alex,
I have been trying with the Global Edit function for the past 2 days .I am not even getting a sing log in the catalina.out even if I give , print some text.
We are using jira4.2.4 with jss1.1 and and the add -on as jss42 _1.0.jar .I changed the actions.xml also.
What else we can do ..Please help ..
Thanks
Srividhya
Unknown User (awilson)
Hi Alex,
I wrote a post-function for a custom workflow that I implemented. I'm trying to update all the sub-tickets so they transition through the workflow when the parent ticket transitions, but when I call issue.getStatus() I get the starting state for the transition, and not the destination state. How do I get access to the destination state so that I can update all the sub-tickets?
Andrew
Unknown User (nakilon)
My solution was: when editing Post Functions move your postfunction down after the 'Re-index an issue to keep indexes in sync with the database.' and .getStatusObject().getId() (and must be .getStatus() also) would give you what you want.
Unknown User (manik)
Hello,
I try to edit a customfield so I do that :
But I have an error cause by the ComponentManager, he's not defined (name 'ComponentManager' is not defined), I don't understand this error :s
Unknown User (luca.andreatta)
Hi,
try to modify the import like this:
Unknown User (manik)
It works, thank you. :D
Unknown User (manik)
I can edit a customfield in format text but not for a date, I push string like this "15/02/2012 10:02"and"2012-02-17 12:30:00.0" but I have this error :
Maybe I need to use a datetime format...
Jira date settings :

Unknown User (luca.andreatta)
You can start from this script that I used some time ago:
And search in Python documentation, you could find some examples.
Unknown User (manik)
Thank's you!
correction > datetime.datetime.today()
Everything is ok, I can start to develop my function
Good afternoon
Unknown User (manik)
Hello,
I write a script using JSS plugin, I get back a date from a customfield and I need to extract data like day, month, year, hour and minute to use my own function and then to update the customfield.
But I have a problem to split the date in day, month, etc. I don't know how to use the object returned by "customField.getValue(issue)", I think it's a java.sql.Timestamp, I'm not sure and I'm getting nowhere :s
Unknown User (manik)
I resolved my problem, the type return is 'java.sql.Timestamp' so I use this doc : http://docs.oracle.com/javase/6/docs/api/java/util/Date.html
Unknown User (tsol)
Hi everybody,
i'm new to the plugin.
I'm trying to create a subtask from a workflow post function but i want to set the sub task assignee another jira user.
Could you please help me with the syntax?
thanx
Unknown User (thomas.krug)
Hi Kostas,
Unknown User (tsol)
Hi Thomas,
Thanks a lot for the help
Unknown User (bcohen)
Trying to set the Assignee based on the value of a custom field. Th script is never hitting the if block, so my guess is the way I have set the variable "feature" is wrong. Could someone give me a hand with getting the "feature" variable set to the correct method?
-Brian
Unknown User (eugenet)
if (str(feature)== "Feature 1")
Unknown User (bcohen)
Ugh, that's all I did wrong
That's good of course.
I forget I have to convert the objects to strings before
I compare. Thanks Eugene!
Unknown User (tkrug0210)
Can I show nice error messages when using post functions just like for validation?
If a NullPointerException is thrown the whole stack trace is shown as error message. I would like to catch the exeption and show a custom error message to the user.
Unknown User (jrubial)
If you figure out, let me know, please
Unknown User (bcohen)
Alex,
Phenomenal plugin! I would really like to start using this for all kinda of customizations, but I would like to know if you are working on Jira 5 support. I would hate to invest in all this scripting if I can't move to Jira 5 at some point in the future
Unknown User (sundalejesse)
Hi everybody,
Could I please have some advice on my auto assign post function script which I am having issues with.
I receive a notification via email saying that the issue has been correctly assigned according to the script although the assignee value within Jira and the database appears as "Unassigned". The person which the issue is meant to be assigned to also receives an email saying the issue has been assigned to them... I have placed the Jython script within the create issue step within the workflow as a post-function.
Edit: I should note my version of Jira is 4.4.4
Unknown User (bcohen)
When run as a post-function, why do I get the following error in the log:
AttributeError: 'com.atlassian.crowd.embedded.ofbiz.OfBizUser' object has no attribute 'getFullName'
I am simply trying to get some real "string" value from the issue.getAssignee() to act on it. If I print it out, I get "com.atlassian.crowd.embedded.ofbiz.OfBizUser@8b46cfe0".
So I am trying to get the actual userid or full name from issue.Assignee(). Help!
-Brian
Unknown User (bcohen)
Actually, looks like I want issue.getAssigneeId()
Still wondering why the getFullName() didn't work. I've seen it in others' sample code above in this thread.....
-Brian
Unknown User (yaron)
Hi there,
I'm, trying to write a script that will fetch a page from Confluence, the script works fine when i run it manually on the Linux server, but fails to run as a post script. The script:
the error messages:
Thanks!
-Yaron
Unknown User (robert.wolf@abacus.ch)
Hallo,
could someone please provide simple example for jython script getting StartDate and EndDate from Version/Sprint of Greenhopper for Jython Runner. To get simple Jira Version information I can use following code:
I have found the Greenhopper API and there is GHVersion but I am not sure how to use it.
I would like to do something like:
But "ver" is simple Jira Version object. I think I need somehow access the GHVersion but I don't know how.
I have tried to import com.atlassian.greenhopper, but it fails with "No module named greenhopper" and import com.pyxis.greenhopper fails with "No module named pyxis".
Can someone give me some hint?
Thank you.
Regards,
Robert Wolf.
Unknown User (rpugal)
Hi all,
We tried Global Edit validation using this plugin .WE got our functionality correctly but the error thrown ,which is given by the "description" that highlights the error thrown on top of the screen does not show the error message at the top of the edit screen.It simply shows an error box without any error message set in the description.
Thanks
Pugal.
Unknown User (bcohen)
What's the plan for 5.1 support? I was going to try it on my non-production server today, wondering if it's supported or forthcoming
Unknown User (maciek)
Hi all :)
is here anyone who has problems with reindex in jira 5.1?
In version 4 ewerything works fine, but now i can't find resolution for my problem (scenario):
Issue in "Awainting for acceptance" status, and there is transition "Accept" to status "Closed". In JSS I try create subTask (code attached below). subTask was created succesfully, and i can see new subTask in Issue Navigator.
After this (in the same transition in "post functions") issue resolution is updated to "Close", and when i view Issue i see correct status and resolution. But in Issue Navigator the issue is still in "Awaiting for acceptance" status. Now i have workaround with loop transition which do nothing but (i think) reindex issue.
Where i have error in the code?
Unknown User (luca.andreatta)
I have the same problem with a Java postfunction, did you find a solution?
Unknown User (maciek)
Yes, i found solution, but last week i've found a second solution. here is it:
1. (not sure it works correct in any time)
put the code (attached in my post below) in post functions just after Reindex
It wasn't works at different project. So i had to find other solution.
2. use release() function and put... before Re-index.
And now it works perfectly.
Nevertheless the second solution is clearly for me, I don't understand how works the first solution exatly. But works. :)
Unknown User (zoom.license@zoomint.com)
Hi all,
we are planning to upgrade to Jira 5.0.7 where the scripting suite is compatible. I tried it in sandbox but my old scripts didn't work.
We have simple scripot which get user groups, but after removal classes we do not know how to rewrite it. Could I ask somebody with better development skills for help?
I found that issue has new method '.getReporter()' but I cant find how to get reporter groups.
Thanks a lot
Unknown User (robert.wolf@abacus.ch)
Hallo,
you habe to get CrowdService ComponentManager.getInstance().getCrowdService() and then see Crowd API
http://docs.atlassian.com/crowd/current/com/atlassian/crowd/embedded/api/CrowdService.html
Regards,
Robert Wolf.
Unknown User (zoom.license@zoomint.com)
thanks a lot.. it works..
question: i have currently in sandbox also 5.1.4 jira. JSS works well but when I click on "EDIT" link on jython post-function I can see only 2 buttons but can't change file or content of file. I have uploaded plugin quick-edit for 5.0.4.. is it because it is not compatible?
Unknown User (robert.wolf@abacus.ch)
I am not sure, what do you exactly mean, but I found now, that I am not able to edit "Global Edit Validation" and "Global Edit Postfunction" (Jira shows 404 Not Found com.quisapps.jira.plugin.action.admin.JSSSysScriptEditor.getRemoteUser()Lcom/opensymphony/user/User
and we cannot edit currently assined jython validator and jython postfunctions in workflow transition (it shows only
- I habe to check log files for errors) and if I want to add new validator/postfunction, then the jython validator/postfunction shows only button "Add" and link "Cancel". I am going to check log files.
Regards,
Wolf.
Unknown User (zoom.license@zoomint.com)
my misstake, i found that JSS didn't update though UPM to version 2.0. I have to did it manually (i was running on 1.2)
But on 1.2 when I had an error in post-function (not global) script I saw error. Now I'm 100% sure that I have error in script but no error message is displayed.
I have only this in log
Unknown User (robert.wolf@abacus.ch)
OK, my problem solved by updating to version 2.0.0 (Jira does not update this plugin automatically).
You are right, there is some problem with quickedit plugin in jira 5.1.X, but you can still select files (we use files checked in subversion repo so no problem for us).
I have enabled the quick edit actions, but then it is impossible to edit issue because of error
Problem is that the global edit postfunction/validator do not run, because they are disabled, because of installation error.
Summary:
using old JSS version 1.2 - the jira shows error "404 not found - com.quisapps.jira.plugin.action.admin.JSSSysScriptEditor.getRemoteUser()Lcom/opensymphony/user/User; ) on JSS script editing AND the global postfunction/validator does not work
using new JSS version 2.0.0 - the jira show error "Global Edit Validation & Postfunction scripts are disabled due to installation problem: incompatible Quick Edit plugin." on JSS script editing AND the global postfunction/validator does not work
JSS developers, do you think there will be some update for Jira 5.1.X soon?
Regards,
Wolf.
Unknown User (rfrizzel)
I'm planning an update to Jira 5.1.x soon and this is a wonderful plug-in that is an integral part of our JIRA instance.
Just wanted to echo the reply of Mr. Wolf above and say that, at least for me and him, that the inline editing part of JSS is less important rather than just the base functionality. In fact, if JSS was written in a way where the quick edit plugin is an optional feature of the plug-in and if a user chose not to install it, then they would just be given a file selection dropdown and just a plain old read-only text area showing the script. For me, I would be perfectly fine with editing the file behind the scenes and just having a basic read-only view of the script if it meant getting a version of JSS that is 5.1.x compatible. Like Mr. Wolf above, we control our scripts with source control anyway, so this would not be any trouble for us at all.
In fact, you could even make the argument that some companies may not feel comfortable having the ease of use of editing the scripts inside of JIRA due to strictly controlling their JIRA instance for audit purposes.
Finally, and this is only a guess so correct me if I am wrong, it seems that the quick edit plug-in is a major source of heartburn for JSS. Having the editing feature as an optional feature may allow others who are less interested in that feature to continue to use JSS without having to wait on the edit plug-in getting in the way of the basic functionality of JSS.
I am not discounting the edit feature within JSS and I realize that it is important to many others, but maybe either simplifying the edit feature or truly making it an optional feature in JSS for those not as interested in it may help with keeping JSS up-to-date with the latest JIRA releases now and in the future.
Thanks for hearing me out and again, thanks for a well-crafted, well-written JIRA plug-in!
Unknown User (zoom.license@zoomint.com)
Hi again,
have another issue with JSS 2.0 on Jira 5.x and 5.1
We had a code:
I have problem on last line isue.setCustomFieldValue
I found in API that better is use http://docs.atlassian.com/jira/latest/index.html?com/atlassian/jira/issue/MutableIssue.html
I do not understand how to use OrderableField.updateIssue
Thanks a lot for any advice
Unknown User (dariam)
Hi,
You can use customField.getCustomFieldType().updateValue() instead.
In your case:
Unknown User (maciek)
Hi all,
how i can set assignee user in other exists issue?
do nothing (also after reindex issueObject). All i can do is read fields from the issueObject.
Unknown User (bcohen)
Can you have more then one listener script? Currently, I have the com.quisapps.jira.plugin.listener.JythonListener with name "Jython" defined in my Listeners configuration, and I use the default workflow_event.py script for my code.
If I want a different listener script, what would I do?
-Brian