Skip to content
This repository was archived by the owner on Nov 26, 2018. It is now read-only.

Add support for JIRA #26

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions botbot_plugins/plugins/jira.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import requests
import json
import re
from urlparse import urljoin
from .. import config
from ..base import BasePlugin, DummyLine
from ..decorators import listens_to_all, listens_to_mentions



class Config(config.BaseConfig):
jira_url = config.Field(help_text="JIRA Link, eg: 'https://tickets.metabrainz.org'")
rest_api_suffix = config.Field(help_text="Suffix for the JIRA REST API, eg: 'rest/api/2/project'", default="rest/api/2/project")
bot_name = config.Field(help_text="Name of your bot, eg: BrainzBot")

class Plugin(BasePlugin):
"""
JIRA issue lookup

Returns the description of a JIRA Issue

jira:{{projectname}}-{{issuenumber}}
"""
config_class = Config

@listens_to_all(ur'(?:.*)\b(\w+-\d+)\b(?:.*)')
def issue_lookup(self, line):
"""
Lookup a specified JIRA issue

Usage:
Just mention the issue by its {{ISSUENAME}}
Eg:
Can you please checkup on PROJECT-123
"""

if line.user not in (self.config['bot_name'],'github'):
api_url = urljoin(self.config['jira_url'], self.config['rest_api_suffix'])
projects = json.loads(self.retrieve('projects'))

queries = re.findall(r"\w+-\d+", line.text)
queries = [query.split("-") for query in queries]
reply = []

for query in queries:
if query[0] in projects:
issue_url = urljoin(api_url,"issue/{}-{}".format(query[0],query[1]))
response = requests.get(issue_url)

if response.status_code == 200:
response_text = json.loads(response.text)
name = response_text['key']
desc = response_text['fields']['summary']

# Only post URL if issue isn't already mentioned as part of one
if re.search(ur'(http)(\S*)/({})\b'.format(name), line.text):
reply.append("{}: {}".format(name, desc))

else:
return_url = urljoin(self.config['jira_url'], "browse/{}".format(name))
reply.append("{}: {} {}".format(name, desc, return_url))

# if Off topic then bot also replies with off topic
if re.search(r'^\[off\]', line.text):
return "[off] {}".format("\n[off] ".join(reply))
else:
return "\n".join(reply)

@listens_to_mentions(ur'(.*)\bUPDATE:JIRA')
def update_projects(self, line):
"""
Updates projects list on mentioning the bot with the command

Usage:
Ping the bot with the command:
UPDATE:JIRA
"""
api_url = urljoin(self.config['jira_url'], self.config['rest_api_suffix'])
project_url = urljoin(api_url, 'project')
response = requests.get(project_url)

if response.status_code == 200:
projects = [project['key'] for project in json.loads(response.text)]
self.store('projects', json.dumps(projects))
return "Successfully updated projects list"

return "Could not update projects list"
57 changes: 57 additions & 0 deletions botbot_plugins/tests/test_jira.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import pytest
import json
from mock import patch, call
import requests
from botbot_plugins.base import DummyApp
from botbot_plugins.plugins import jira

class FakeProjectResponse(object):
"""Dummy response from JIRA"""
status_code = 200
text = json.dumps([{'key': 'TEST'}])

class FakeUserResponse1(object):
"""Dummy response from JIRA"""
status_code = 200
text = json.dumps({'key': 'TEST-123', 'fields': {'summary': "Testing JIRA plugin"}})

class FakeUserResponse2(object):
"""Dummy response from JIRA"""
status_code = 200
text = json.dumps({'key': 'TEST-234', 'fields': {'summary': "Testing JIRA plugin"}})

@pytest.fixture
def app():
dummy_app = DummyApp(test_plugin=jira.Plugin())
dummy_app.set_config('jira', {'jira_url': 'https://tickets.test.org', 'bot_name': 'testbot'})
return dummy_app


def test_jira(app):
# patch requests.get so we don't need to make a real call to Jira

# Test project retrival
with patch.object(requests, 'get') as mock_get:
mock_get.return_value = FakeProjectResponse()
responses = app.respond("@UPDATE:JIRA")
mock_get.assert_called_with(
'https://tickets.test.org/rest/api/2/project')
assert responses == ["Successfully updated projects list"]

# Test appropriate response
with patch.object(requests, 'get') as mock_get:
mock_get.return_value = FakeUserResponse1()
responses = app.respond("I just assigned TEST-123 to testuser")
mock_get.assert_called_with(
'https://tickets.test.org/rest/api/2/issue/TEST-123')
assert responses == ["TEST-123: Testing JIRA plugin https://tickets.test.org/browse/TEST-123"]

# Test response when issue is mentioned as part of url
with patch.object(requests, 'get') as mock_get:
mock_get.return_value = FakeUserResponse1()
responses = app.respond("Check out https://tickets.test.org/browse/TEST-123")
mock_get.assert_called_with(
'https://tickets.test.org/rest/api/2/issue/TEST-123')
assert responses == ["TEST-123: Testing JIRA plugin"]