Managing JIRA Scrum Sprints using API

Atlassian Jira is a great tool for organizing Agile processes, especially Scrum. But managing Scrum Sprints manually using Jira web GUI maybe time consuming and annoying. So, I decided to automate some routine operations using JIRA API and Python.

The API calls are described on the official page at JIRA Agile REST API Reference.

Managing JIRA Agile Sprints using API

I will use my domain account for authentication. First of all let’s see how to get Jira Scrum Board ID by it’s name and get all the Sprints related to the Board.

name = "CyberSecurity"
response = requests.get('https://jira.corporation.com/rest/agile/1.0/board?name=' + name, auth=(user, password))
print(response.text)
board_id = json.loads(response.text)['id']

Output:

{"maxResults":50,"startAt":0,"isLast":true,"values":[{"id":2334,"self":"https://jira.corporation.com/rest/agile/1.0/board/2334","name":"CyberSecurity","type":"scrum"}]}

Getting all the Sprints

Not bad, now we can list all sprints for this Scrum Board:

response = requests.get('https://jira.corporation.com/rest/agile/1.0/board/' + str(board_id)
                        + '/sprint', auth=(user, password))
print json.dumps(json.loads(response.text), indent=2, sort_keys=True)

Output:

{
  "isLast": true, 
  "maxResults": 50, 
  "startAt": 0, 
  "values": [
    ...
    {
      "endDate": "2018-12-29T12:41:00.000+03:00", 
      "goal": "", 
      "id": 9879, 
      "name": "24.12.2018-31.12.2018", 
      "originBoardId": 1886, 
      "self": "https://jira.corporation.com/rest/agile/1.0/sprint/9879", 
      "startDate": "2018-12-24T12:41:44.662+03:00", 
      "state": "active"
    }
  ]
}

If you have more than 50 Sprints, it will be necessary to make several request and increase startAt until isLast is true.

Creating a new sprint

Now we can create a new Sprint. We have to set name of the Sprint, time when it starts and ends, and the board_id we received earlier.

headers = {
    'Content-Type': 'application/json',
}

data = {
    'name': '14.01.2019-21.01.2019',
    'startDate': '2019-01-14T10:00:00.000+10:00',
    'endDate': '2019-01-21T10:00:00.000+10:00',
    'originBoardId': board_id
}

response = requests.post('https://jira.corporation.com/rest/agile/1.0/sprint', headers=headers,
                         data=json.dumps(data), auth=(user, password))
print(response.text)

Output:

{"id":10233,"self":"https://jira.corporation.com/rest/agile/1.0/sprint/10233","state":"future","name":"14.01.2019-21.01.2019","startDate":"2019-01-14T03:00:00.000+03:00","endDate":"2019-01-21T03:00:00.000+03:00","originBoardId":1886}

Starting and closing the sprint

Now let’s start this sprint. In fact it is no more than changing the state parameter:

headers = {
    'Content-Type': 'application/json',
}
data = {
    'state': 'active'
}

sprint_id = "10233"
response = requests.post('https://jira.corporation.com/rest/agile/1.0/sprint/' + str(sprint_id), headers=headers,
                         data=json.dumps(data),  auth=(user, password))
print(response.text)

Output:

{"id":10233,"self":"https://jira.corporation.com/rest/agile/1.0/sprint/10233","state":"active","name":"14.01.2019-21.01.2019","startDate":"2019-01-14T03:00:00.000+03:00","endDate":"2019-01-21T03:00:00.000+03:00","originBoardId":1886}

Closing the sprint is the same, but the state should be set to ‘closed’.

Moving Issues between the Sprints

Ok, now let’s figure out what Issues we have in the Sprint:

response = requests.get('https://jira.corporation.com/rest/agile/1.0/sprint/' + str(sprint_id)+ '/issue', auth=(user, password))
print(response.text)

It will return a pretty complex structure. However, it is easily parsable and you can iterate and choose IDs you need like this:

issues = set()
for issue in json.loads(response.text):
    assignee = ""
    if 'assignee' in issue['fields']:
        if issue['fields']['assignee']:
            assignee = issue['fields']['assignee']['name']
    if assignee == "j.smith" and "CyberSecurity" in issue['fields']['labels']:
        issues.add(issue['key'])

And then move them to another sprint:

new_sprint_id = "9879"

data = {
    'issues': list(issues)
}

response = requests.post('https://jira.corporation.com//rest/agile/1.0/sprint/' + str(new_sprint_id)+ '/issue',
                         headers=headers, data=json.dumps(data), auth=(user, password))

If everything is ok, the output will be empty and the STATUS of the request will be 204.

Using these calls, I was able to close old Sprints, create new ones and move active Issues from old sprints to new ones. Read more about Jira automation in my posts “Automated task processing with JIRA API” and “Atlassian Jira, Python and automated labeling

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.