-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Run `black` - Fix Dockerfile - Add `feature_request` and `interrupts` strategies - Start `datadog` + `trello` plugins (missing tests)
- Loading branch information
Corentin Chary
committed
Oct 28, 2018
1 parent
69d77d5
commit e47f962
Showing
20 changed files
with
623 additions
and
38 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
"""my-little-ticket Datadog plugin.""" | ||
import logging | ||
import time | ||
|
||
import datadog | ||
|
||
from my_little_ticket.plugins import base | ||
|
||
from django.conf import settings | ||
|
||
|
||
DEFAULT_DATADOG_API_HOST = getattr(settings, "DATADOG_API_HOST", None) | ||
DEFAULT_DATADOG_APP_KEY = getattr(settings, "DATADOG_APP_KEY", None) | ||
DEFAULT_DATADOG_API_KEY = getattr(settings, "DATADOG_API_KEY", None) | ||
|
||
# TODO: There could also be one for events (as monitors create events). | ||
|
||
class MonitorPlugin(base.Plugin): | ||
"""my-little-ticket Datadog plugin. | ||
This is not super useful yet, it's probably a better idea to plugin datadog monitors | ||
to jira or trello and fetch status from there. | ||
params: | ||
```python | ||
{ | ||
'api_host': 'https://api.datadoghq.com', // Url to root API. | ||
'api_key': '', // API Key | ||
'app_key': '', // API Key | ||
'params': {}, // Get tickets matching these params (see Datadog API). | ||
} | ||
``` | ||
""" | ||
|
||
def __init__(self, params=None): | ||
"""Create an instance of the plugin.""" | ||
super(MonitorPlugin, self).__init__(params) | ||
if params is None: | ||
params = {} | ||
|
||
self._api = None | ||
|
||
self.api_host = params.get("api_host", DEFAULT_DATADOG_API_HOST) | ||
self.api_key = params.get("api_key", DEFAULT_DATADOG_API_KEY) | ||
self.app_key = params.get("app_key", DEFAULT_DATADOG_APP_KEY) | ||
if "params" in params: | ||
self.params = params["params"] | ||
else: | ||
self.params = {} | ||
|
||
@property | ||
def short_name(self): | ||
"""Return the short name.""" | ||
return "datadog" | ||
|
||
@property | ||
def name(self): | ||
"""Return the name.""" | ||
return "Datadog" | ||
|
||
@property | ||
def description(self): | ||
"""Return the description.""" | ||
return "Returns monitors from Datadog." | ||
|
||
@property | ||
def link(self): | ||
"""Return the link.""" | ||
# TODO: Fill ?q= from self.params | ||
return "%s/monitors/manage" % self.api_host | ||
|
||
@property | ||
def api(self): | ||
"""Get a Datadog api.""" | ||
if not self._api: | ||
# This isn't super nice if somebody else in the same | ||
# process is uinsg it... | ||
datadog.initialize( | ||
api_key=self.api_key, app_key=self.app_key, api_host=self.api_host | ||
) | ||
self._api = datadog.api | ||
|
||
return self._api | ||
|
||
def tickets(self): | ||
"""Return the tickets.""" | ||
ret = {} | ||
|
||
if not self.api: | ||
return ret | ||
|
||
monitors = self.api.Monitor.get_all(**self.params) | ||
for monitor in monitors: | ||
ticket = self._to_ticket(monitor) | ||
if ticket is not None: | ||
ret[ticket["uuid"]] = ticket | ||
return ret | ||
|
||
def _to_ticket(self, monitor): | ||
"""Return a status or None.""" | ||
logging.debug("Handling %s" % (monitor)) | ||
|
||
tags = list(monitor['tags']) | ||
assignee = None | ||
priority = None | ||
summary = monitor['name'] | ||
text = monitor['message'] | ||
status = monitor['overall_state'] | ||
created_on = monitor['created'] | ||
updated_on = monitor['modified'] | ||
|
||
ticket = base.Ticket( | ||
ext_id=monitor['id'], | ||
summary=summary, | ||
text=text, | ||
link="https://%s/monitors/%d" % (self.api_host, monitor['id']), | ||
project=str(monitor['org_id']), | ||
type=monitor['type'], | ||
assignee=assignee, | ||
status=status, | ||
priority=priority, | ||
tags=tags, | ||
created_on=created_on, | ||
modified_on=updated_on, | ||
raw=monitor, | ||
) | ||
return ticket | ||
|
||
def info(self, ticket): | ||
"""Return info that might be interesting for this ticket.""" | ||
data = {} | ||
return data |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
"""Feature request strategy.""" | ||
|
||
from my_little_ticket.plugins import base | ||
|
||
|
||
class FeatureRequestStrategy(base.Strategy): | ||
"""FeatureRequestStrategy strategy. | ||
Uses votes to sort. | ||
""" | ||
|
||
def __init__(self, params): | ||
"""Constructor.""" | ||
super(FeatureRequestStrategy, self).__init__(params) | ||
self.params = params | ||
|
||
def short_name(self): | ||
"""See base.Strategy.""" | ||
return "feature-request" | ||
|
||
def name(self): | ||
"""See base.Strategy.""" | ||
return "Feature request" | ||
|
||
def description(self): | ||
"""Score based on votes.""" | ||
return """ | ||
Feature request strategy. Uses the number of votes to determine a score. | ||
The more voters, the higher the feature request will go. | ||
""" | ||
|
||
def group(self, ticket): | ||
"""See base.Strategy.""" | ||
status = ticket.status or "unknown" | ||
|
||
if status.lower() in ["block", "blocked", "idle"]: | ||
return "Waiting" | ||
elif status.lower() in ["in progress"]: | ||
return "In Progress" | ||
elif status.lower() in ["closed", "fixed", "resolved"]: | ||
return "X Implemented" | ||
else: | ||
return "Feature Requests" | ||
|
||
def _get_votes(self, ticket): | ||
raw = ticket.raw or {} | ||
return raw.get("fields", {}).get("votes", {}).get("votes", 0) | ||
|
||
def status(self, ticket): | ||
"""See base.Strategy.""" | ||
score = self._get_votes(ticket) | ||
if score == 0: # Nobody cares | ||
return self.STATUS_DANGER | ||
elif score <= 3: # Some people | ||
return self.STATUS_WARNING | ||
elif score <= 6: # At least a team | ||
return self.STATUS_INFO | ||
else: # More than a team | ||
return self.STATUS_SUCCESS | ||
|
||
def score(self, ticket): | ||
"""See base.Strategy.""" | ||
score = self._get_votes(ticket) | ||
# Multiply by itself to make more differences between scores. | ||
return score * score |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
"""Test for the default strategy plugin.""" | ||
|
||
import unittest | ||
import uuid | ||
from django import test | ||
|
||
from my_little_ticket.tickets.models import Ticket | ||
from my_little_ticket_criteo.plugins import feature_request | ||
|
||
|
||
class FeatureRequestStrategyTestCase(test.TestCase): | ||
"""Tests for DefaultStrategy.""" | ||
|
||
def test_basic(self): | ||
"""Check if the default strategy works.""" | ||
tickets = ( | ||
Ticket( | ||
id=1, | ||
uuid=uuid.uuid4(), | ||
summary="Foo", | ||
text="Foo foo", | ||
link="http://bug/foo", | ||
), | ||
Ticket( | ||
id=2, | ||
uuid=uuid.uuid4(), | ||
summary="bar", | ||
text="bar bar", | ||
link="http://bug/bar", | ||
), | ||
) | ||
strategy = feature_request.FeatureRequestStrategy(params={}) | ||
result = strategy.scores(tickets) | ||
self.assertEqual(len(result), len(tickets)) | ||
strategy.group(tickets[0]) | ||
strategy.status(tickets[0]) | ||
|
||
|
||
# FIXME: More tests here. | ||
|
||
|
||
if __name__ == "__main__": | ||
unittest.main() |
Oops, something went wrong.