{"id":403,"date":"2016-10-25T04:14:24","date_gmt":"2016-10-25T04:14:24","guid":{"rendered":"http:\/\/tuxlabs.com\/?p=403"},"modified":"2016-10-25T14:29:11","modified_gmt":"2016-10-25T14:29:11","slug":"python-the-jira-rest-api","status":"publish","type":"post","link":"https:\/\/tuxlabs.com\/?p=403","title":{"rendered":"Python &#038; The Jira Rest API"},"content":{"rendered":"<p>Recently, while having to work a lot more in Jira than normal I got annoyed with the Jira Web GUI. So I wrote a script to do simple management of our jira issues.<\/p>\n<h2>Here is the basic usage<\/h2>\n<pre class=\"lang:default decode:true\">(env) \u279c  jira git:(master) \u2717 .\/jira-ctl.py\r\nusage: jira-ctl.py [-h] [-lp] [-li LIST_PROJECT_ISSUES] [-ua UPDATE_ASSIGNEE]\r\n                   [-ud UPDATE_DATE] [-usts UPDATE_STATUS]\r\n                   [-usum UPDATE_SUMMARY]\r\n\r\noptional arguments:\r\n  -h, --help            show this help message and exit\r\n  -lp, --list-projects  List all projects\r\n  -li LIST_PROJECT_ISSUES, --list-issues LIST_PROJECT_ISSUES\r\n                        List Issues for a specific project\r\n  -ua UPDATE_ASSIGNEE, --update-assignee UPDATE_ASSIGNEE\r\n                        Update an issues assignee format: &lt;issue\r\n                        number&gt;,&lt;first_last&gt;\r\n  -ud UPDATE_DATE, --update-date UPDATE_DATE\r\n                        Update an issues due date format: &lt;issue number\r\n                        &gt;,&lt;yyyy-mm-dd&gt;\r\n  -usts UPDATE_STATUS, --update-status UPDATE_STATUS\r\n                        Update an issues status format: &lt;issue\r\n                        number&gt;,'&lt;Open|In Progress|Resolved&gt;'\r\n  -usum UPDATE_SUMMARY, --update-summary UPDATE_SUMMARY\r\n                        Update an issues summary format: &lt;issue\r\n                        number&gt;,'&lt;summary&gt;'\r\n(env) \u279c  jira git:(master) \u2717<\/pre>\n<h2>Here is the code&#8230;<\/h2>\n<pre class=\"lang:default decode:true  \">from jira.client import JIRA\r\nimport os, sys\r\nimport prettytable\r\nimport argparse\r\n\r\nparser = argparse.ArgumentParser()\r\nparser.add_argument('-lp', '--list-projects', action=\"store_true\", dest=\"list_projects\", required=False, help=\"List all projects\")\r\nparser.add_argument('-li', '--list-issues', action=\"store\", dest=\"list_project_issues\", required=False, help=\"List Issues for a specific project\")\r\nparser.add_argument('-ua', '--update-assignee', action=\"store\", dest=\"update_assignee\", required=False, help=\"Update an issues assignee format: &lt;issue number&gt;,&lt;first_last&gt;\")\r\nparser.add_argument('-ud', '--update-date', action=\"store\", dest=\"update_date\", required=False, help=\"Update an issues due date format: &lt;issue number&gt;,&lt;yyyy-mm-dd&gt;\")\r\nparser.add_argument('-usts', '--update-status', action=\"store\", dest=\"update_status\", required=False, help=\"Update an issues status format: &lt;issue number&gt;,'&lt;Open|In Progress|Resolved&gt;'\")\r\nparser.add_argument('-usum', '--update-summary', action=\"store\", dest=\"update_summary\", required=False, help=\"Update an issues summary format: &lt;issue number&gt;,'&lt;summary&gt;'\")\r\nargs = parser.parse_args()\r\n\r\ndef get_pass():\r\n    if os.environ.get('JIRA_PASS') == None:\r\n        print \"you must first export your JIRA_PASS in the shell by running: source getpass.sh\"\r\n        print 'or \"export JIRA_PASS=&lt;jira_password&gt;'\r\n        sys.exit()\r\n    jira_password = str(os.environ['JIRA_PASS'])\r\n\r\n    return jira_password\r\n\r\ndef connect_jira(jira_server, jira_user, jira_password):\r\n    '''\r\n    Connect to JIRA. Return None on error\r\n    '''\r\n    try:\r\n        #print \"Connecting to JIRA: %s\" % jira_server\r\n        jira_options = {'server': jira_server}\r\n        jira = JIRA(options=jira_options,\r\n                    # Note the tuple\r\n                    basic_auth=(jira_user,\r\n                                jira_password))\r\n        return jira\r\n    except Exception,e:\r\n        print \"Failed to connect to JIRA: %s\" % e\r\n        return None\r\n\r\ndef list_projects():\r\n    projects = jira.projects()\r\n    header = [\"Projects\"]\r\n    table = prettytable.PrettyTable(header)\r\n    for project in projects:\r\n        row = [str(project)]\r\n        table.add_row(row)\r\n    print table\r\n\r\ndef list_project_issues(project):\r\n    query = 'project = %s and status != Resolved order by due asc' % (project)\r\n    #query = 'project = %s and status != Resolved order by due desc' % (project)\r\n    #query = 'project = %s order by due desc' % (project)\r\n    issues = jira.search_issues(query, maxResults=100)\r\n\r\n    if issues:\r\n        header = [\"Ticket\", \"Summary\", \"Assignee\", \"Status\", \"Due Date\"]\r\n        table = prettytable.PrettyTable(header)\r\n\r\n        for issue in issues:\r\n                summary = issue.fields.summary\r\n                st = str(issue.fields.status)\r\n                dd = issue.fields.duedate\r\n                assignee = issue.fields.assignee\r\n                row = [issue, summary, assignee, st, dd]\r\n                table.add_row(row)\r\n        print table\r\n\r\ndef update_issue_assignee(issue_number, assignee):\r\n    issue = jira.issue(issue_number)\r\n    issue.update(assignee=assignee)\r\n    print \"updated %s with new Assignee: %s\" % (issue_number, assignee)\r\n\r\ndef update_issue_duedate(issue_number, dd):\r\n    issue = jira.issue(issue_number)\r\n    issue.update(duedate=dd)\r\n    print \"updated %s with new Due Date: %s\" % (issue_number, dd)\r\n\r\ndef update_issue_summary(issue_number, summary):\r\n    issue = jira.issue(issue_number)\r\n    issue.update(summary=summary)\r\n    print \"updated %s with new Summary: %s\" % (issue_number, summary)\r\n\r\ndef update_issue_status(issue_number, status):\r\n    # To figure out transitions view the following URL\r\n    # https:\/\/jira.yourcompany.com\/rest\/api\/2\/issue\/XXXXXX-22\/transitions?expand=transitions.fields\r\n\r\n    transitions = {\r\n                    'Resolved': 11,\r\n                    'Open': 41,\r\n                    'In Progress': 21,\r\n                    'Testing': 71,\r\n                    'Transition': 81,\r\n                    'Closed': 91,\r\n    }\r\n\r\n    issue = jira.issue(issue_number)\r\n    jira.transition_issue(issue, transitions[status])\r\n    print \"updated %s with new Status: %s\" % (issue_number, status)\r\n\r\nif __name__ == \"__main__\":\r\n    if not args:\r\n        parser.print_help()\r\n    else:\r\n        jira_user = '&lt;your_login&gt;'\r\n        jira_password = get_pass()\r\n        jira_server = 'https:\/\/jira.yourcompany.com'\r\n\r\n        jira = connect_jira(jira_server, jira_user, jira_password)\r\n\r\n        if args.list_projects:\r\n            list_projects()\r\n        elif args.list_project_issues:\r\n            project = args.list_project_issues\r\n            list_project_issues(project)\r\n        elif args.update_assignee:\r\n            (issue_number, assignee) = args.update_assignee.split(',')\r\n            update_issue_assignee(issue_number, assignee)\r\n        elif args.update_date:\r\n            (issue_number, dd) = args.update_date.split(',')\r\n            update_issue_duedate(issue_number, dd)\r\n        elif args.update_status:\r\n            (issue_number, status) = args.update_status.split(',')\r\n            update_issue_status(issue_number, status)\r\n        elif args.update_summary:\r\n            (issue_number, summary) = args.update_summary.split(',')\r\n            update_issue_summary(issue_number, summary)\r\n        else:\r\n            parser.print_help()<\/pre>\n<p>Later, I found out that there is a Jira command line utility, I didn&#8217;t check and see what functionality it provided, but I enjoyed writing this anyway.<\/p>\n<p>Happy coding !<\/p>\n","protected":false},"excerpt":{"rendered":"<a href=\"https:\/\/tuxlabs.com\/?p=403\" rel=\"bookmark\" title=\"Permalink to Python &#038; The Jira Rest API\"><p>Recently, while having to work a lot more in Jira than normal I got annoyed with the Jira Web GUI. So I wrote a script to do simple management of our jira issues. Here is the basic usage (env) \u279c jira git:(master) \u2717 .\/jira-ctl.py usage: jira-ctl.py [-h] [-lp] [-li LIST_PROJECT_ISSUES] [-ua UPDATE_ASSIGNEE] [-ud UPDATE_DATE] [-usts [&hellip;]<\/p>\n<\/a>","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[126,146,55,147],"class_list":{"0":"post-403","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-howtos","7":"tag-api","8":"tag-jira","9":"tag-python","10":"tag-rest","11":"h-entry","12":"hentry"},"_links":{"self":[{"href":"https:\/\/tuxlabs.com\/index.php?rest_route=\/wp\/v2\/posts\/403","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tuxlabs.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tuxlabs.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tuxlabs.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/tuxlabs.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=403"}],"version-history":[{"count":2,"href":"https:\/\/tuxlabs.com\/index.php?rest_route=\/wp\/v2\/posts\/403\/revisions"}],"predecessor-version":[{"id":423,"href":"https:\/\/tuxlabs.com\/index.php?rest_route=\/wp\/v2\/posts\/403\/revisions\/423"}],"wp:attachment":[{"href":"https:\/\/tuxlabs.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=403"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tuxlabs.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=403"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tuxlabs.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=403"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}