Introduction

I love friendly competition, because competition when done right is a great motivator.  In this blog post you’ll see how it’s motivated me (smile).  I’m still pretty new at Isos, but I’ve been told that there have been several competitions revolving around generating content and blog posts.

This spring we had a blogging competition where the company was divided into teams and each week of the competition the completed blog posts were tallied for each team using Jira issues and some points awarded.  The only problem was competitive intelligence, because the teams were documented in a Confluence page but there were no groups in Jira for the teams.  So the only way to get a list of user names for each team was to manually look them up one-by-one from the Confluence page.

…or write a little code that uses the REST API to pull those user names from the table.  If you know me, you’ll know I opted for the latter option.  The next piece needed for this intelligence was all the issues sorted by team that were unresolved belonging to the BLOG project.

The example below shows how I was able to get this information from Confluence and Jira and the output I generated.  This code works, but there are some improvements that could be made I’ll leave you to sort out.

Example

rest.py

import jira, base64, bs4
from confluence.client import Confluence as cnfl
 
 
# protocol and baseurl
proto = 'https://'
baseurl = 'isostech.com'
 
# get credentials from files
with open('/Users/sky/Dev/rest_blog/resource1', mode='br') as file_object:
    password = base64.b64decode(file_object.read()).decode()
 
with open('/Users/sky/Dev/rest_blog/resource2', mode='r') as file_object:
    username = file_object.read()
 
# create jira object and authenticate to server
jira_auth = jira.JIRA(f'{proto}issues.{baseurl}', auth=(username, password))
 
# create confluence object and authenticate to server
cnfl_auth = cnfl(f'{proto}wiki.{baseurl}', (username, password))
 
# download the page with our blog teams table on it
blog_teams = cnfl_auth.get_content(space_key='BS', title='2019 Spring Blog Draft')
for page in blog_teams:
    page_content = cnfl_auth.get_content_by_id(page.id, expand=['body.view'])
 
# parse the content of the page
parsed_page = bs4.BeautifulSoup(page_content.body.view,'html.parser')
teamsHeader = parsed_page.find_all('h1')[1]
teamsTable = teamsHeader.next_sibling.contents[0].contents[1].contents
 
# build the team lists
teams = {0: [], 1: [], 2: []}
 
for row in teamsTable:
    for i, td in enumerate(row.contents):
        try:
            teams[i].append(td.contents[0].attrs['data-username'])
        except KeyError:
            try:
                teams[i].append(td.contents[0].contents[0].contents[0].attrs['data-username'])
            except IndexError:
                break
 
# name the teams
namedTeams = {'Mary': teams[0],
              'Amanda': teams[1],
              'Bob': teams[2]}
 
# get the issues in BLOG project by team
for team in namedTeams:
    # search for issues in jira using jql
    teamIssues = jira_auth.search_issues(jql_str=f'project = BLOG AND resolution = Unresolved AND \
                                        assignee in ({",".join(namedTeams[team])})',json_result=True)
    # generate output
    print('\n\nTeam',team,'has',len(teamIssues['issues']),'open blog issues:\n')
    for issue in teamIssues['issues']:
        print(issue['key'], ':\t', issue['fields']['assignee']['displayName'],'\n\t',issue['fields']['summary'])

Example Output

$ python rest.py
 
 
Team Mary has 6 open blog issues:
 
BLOG-332 :       Sky Moore
         Rest API blog post
BLOG-329 :       Trevan Householder
         Disable the Jira Create button for a Jira Service Desk project
BLOG-327 :       Trevan Householder
         Jira Service Desk Approvals in Cloud vs. Server
BLOG-211 :       Mary Ramirez
         Service Delivery - Team Mary - 2019 Q2 blogging
BLOG-176 :       Mary Ramirez
         Q1 2019 Blog Post-Mary Ramirez
BLOG-100 :       Tracy Walton
         Q3 2018 Post - Tracy Walton
 
 
Team Amanda has 7 open blog issues:
 
BLOG-340 :       Andrew Yarrow
         Week 8 - Andrew - Blog Post 2
BLOG-339 :       Andrew Yarrow
         Week 8 - Andrew - Blog Post 1
BLOG-334 :       Amanda Kirk
         Q2 2019 Post #13 - Amanda Kirk
BLOG-328 :       Amanda Kirk
         Q2 2019 Post #12 - Amanda Kirk
BLOG-302 :       Amanda Kirk
         Q2 2019 Post #11 - Amanda Kirk
BLOG-275 :       Amanda Kirk
         Q2 2019 Post #10 - Amanda Kirk
BLOG-212 :       Amanda Kirk
         Service Delivery - Team Amanda - 2019 Q2 blogging
 
 
Team Bob has 5 open blog issues:
 
BLOG-337 :       Peggy Trammell
         Q2 2019 Post #4 - Peggy Trammell
BLOG-266 :       Isaiah 
         Q2 2019 Isaiah #2
BLOG-210 :       Bob Wen
         Service Delivery - Team Bob - 2019 Q2 blogging
BLOG-152 :       Adam Martin
         Q4 2018 Post #1 - Adam Martin
BLOG-148 :       Jojo Salazar
         Morale blog post

Conclusion

This is just one example of the power of Atlassian’s REST APIs.  These APIs are not limited to just pulling down information either.  One could easily write integrations using these interfaces that take information from any source and create Confluence pages, Jira issues, Bitbucket branches, or Jira Service Desk tickets.  It’s pretty easy to see the value the use of these APIs can deliver to your organization, especially when integrating with tools outside of Atlassian’s suite.  These APIs can be leveraged in numerous ways to make life easier for contributors and drive up efficiency.  Feel free to reach out to our team here at Isos if you’re interested in building integrations using Atlassian tools or for anything Atlassian related; we’d love to help you out!