
This might be a very esoteric topic for most people, but since I could
not find information about this anywhere, I decided to document this
in a post.
Here is the problem. I use Jira at work, and today, I needed
to close a bunch of tickets based on a search result. Now, searching
or doing batch operations is simple enough from the browser, but a
small detail made the exercise impossible via the web UI.
Our Jira project requires a field to be filled while closing the
ticket – the time spent in the ticket. This breaks Jira in all sorts
of ways – the batch operation doesn’t work, some of the email-to-jira
interface at work breaks as well.
So I looked at doing this via the Jira Python library. But
it didn’t work as expected.
>>> from jira import JIRA
>>>
>>> jira = JIRA("https://JIRA_URL", basic_auth=('USER_NAME', 'Password'))
>>>
>>> issue = jira.issue("ISSUE-123")
>>>
>>> [(t['id'], t['name']) for t in jira.transitions(issue)] # What are the workflows available?
[(u'4', u'Start Progress'), (u'5', u'Resolve Issue'), (u'2', u'Close Issue'), (u'711', u'Planning'), (u'751', u'Blocked'), (u'801', u'To Monitor')
>>>
>>> jira.transition_issue(issue, '2')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
...
jira.exceptions.JIRAError: JiraError HTTP 400
text: Time Spent is required
url: ...
response headers = {...}
response text = {"errorMessages":["Time Spent is required"],"errors":{}}
The documentation on transitions mentioned that
we could add fields in the call to jira.transitions(). That didn’t
work as well.
>>> jira.transition_issue(issue, '2', timespent="1h")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
...
jira.exceptions.JIRAError: JiraError HTTP 400
text: Field 'timespent' cannot be set. It is not on the appropriate screen, or unknown.
url: ...
response headers = ...
response text = {"errorMessages":[],"errors":{"timespent":"Field 'timespent' cannot be set. It is not on the appropriate screen, or unknown."}}
So I scoured the Internet for a long time, till I found this post
about how to do it via the REST API – the only official
interface to Jira. Here is what needs to be sent as the body to the
POST request.
{
"transition": {
"id": "2"
},
"update": {
"worklog": [
{
"add": {
"timeSpent": "2m"
}
}
]
}
}
I felt that to be odd, till I looked at both the api documentation
for transition and the doc for transition using the
python library and I found out why I have not been
successful till now.
The REST api supports two ways to update the issue while doing a
transition – you can set certain fields using the fields option, or
you can use the update option to do more complex changes.
The comment in the Python code revealed that the update method has
not yet been implemented.
def transition_issue(self, issue, transition, fields=None, comment=None, **fieldargs):
# TODO: Support update verbs (same as issue.update())
That put me in a bind. I had only one way to hack around this problem
now – using the REST api for the specific operation I wanted, and the
Python library for the rest of the work – ugly, but works for now,
till the Python library is complete.
So here was the final solution that did what I wanted.
from jira import JIRA
import requests
jira = JIRA("https://JIRA_URL", basic_auth=('USER_NAME', 'PASSWORD'))
d = {}
d["transition"]={"id": "2"}
d["update"]={"worklog": [{"add": {"timeSpent": "1h"}}]}
s = requests.Session()
s.auth = ("USER", "PASSWORD")
s.headers.update({"Content-Type": "application/json"})
j="https://JIRA_URL"
issue_list = jira.search_issues("assignee = currentUser() AND resolution = Unresolved and status != Closed and updatedDate < '2015-10-01' and project='PROJECT' ORDER BY updatedDate DESC")
for i in issue_list:
print i
s.post(j+"/rest/api/2/issue/"+i.key+"/transitions", data=json.dumps(d))

