зеркало из https://github.com/mozilla/treeherder.git
Bug 1117583 - Add an API endpoint that creates a new bug in Bugzilla.
This endpoint receives a http POST request from the UI containing information about the bug to be filed (product, component, summary, version, description), then formats it properly as a submission to Bugzilla's REST API, using a server-side Bugzilla API key, and adding a "treeherder" comment tag. The API then passes back either the bug ID (if the submission was successful) or Bugzilla's failure response if something went wrong.
This commit is contained in:
Родитель
3b5f39b787
Коммит
371ec172de
|
@ -10,3 +10,7 @@ CELERY_EAGER_PROPAGATES_EXCEPTIONS = True
|
|||
# Reconfigure pulse to operate on default vhost of rabbitmq
|
||||
PULSE_URI = BROKER_URL
|
||||
PULSE_EXCHANGE_NAMESPACE = 'test'
|
||||
|
||||
# Set a fake api key for testing bug filing
|
||||
BZ_API_KEY = "12345helloworld"
|
||||
BZ_API_URL = "https://thisisnotbugzilla.org"
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
import json
|
||||
|
||||
import responses
|
||||
from django.contrib.auth.models import User
|
||||
from django.core.urlresolvers import reverse
|
||||
from rest_framework.test import APIClient
|
||||
|
||||
|
||||
def test_create_bug(webapp, eleven_jobs_stored, activate_responses):
|
||||
"""
|
||||
test successfully creating a bug in bugzilla
|
||||
"""
|
||||
|
||||
def request_callback(request):
|
||||
headers = {}
|
||||
requestdata = json.loads(request.body)
|
||||
requestheaders = request.headers
|
||||
print requestdata
|
||||
print requestheaders
|
||||
assert requestheaders['x-bugzilla-api-key'] == "12345helloworld"
|
||||
assert requestdata['product'] == "Bugzilla"
|
||||
assert requestdata['description'] == "Filed by: MyName\n\nIntermittent Description"
|
||||
assert requestdata['component'] == "Administration"
|
||||
assert requestdata['summary'] == "Intermittent summary"
|
||||
assert requestdata['comment_tags'] == "treeherder"
|
||||
assert requestdata['version'] == "4.0.17"
|
||||
assert requestdata['keywords'] == "intermittent-failure"
|
||||
resp_body = {"id": 323}
|
||||
return(200, headers, json.dumps(resp_body))
|
||||
|
||||
responses.add_callback(
|
||||
responses.POST, "https://thisisnotbugzilla.org/rest/bug",
|
||||
callback=request_callback, match_querystring=False,
|
||||
content_type="application/json",
|
||||
)
|
||||
|
||||
client = APIClient()
|
||||
user = User.objects.create(username="MyName", email="foo@bar.com")
|
||||
client.force_authenticate(user=user)
|
||||
|
||||
resp = client.post(
|
||||
reverse("bugzilla-create-bug"),
|
||||
{
|
||||
"product": "Bugzilla",
|
||||
"component": "Administration",
|
||||
"summary": "Intermittent summary",
|
||||
"version": "4.0.17",
|
||||
"description": "Intermittent Description",
|
||||
"comment_tags": "treeherder",
|
||||
"keywords": "intermittent-failure",
|
||||
}
|
||||
)
|
||||
|
||||
user.delete()
|
||||
|
||||
content = json.loads(resp.content)
|
||||
|
||||
print content
|
||||
assert content['success'] == 323
|
||||
|
||||
|
||||
def test_create_unauthenticated_bug(webapp, eleven_jobs_stored, activate_responses):
|
||||
"""
|
||||
test successfully creating a bug in bugzilla
|
||||
"""
|
||||
|
||||
def request_callback(request):
|
||||
headers = {}
|
||||
requestdata = json.loads(request.body)
|
||||
requestheaders = request.headers
|
||||
print requestdata
|
||||
print requestheaders
|
||||
assert requestheaders['x-bugzilla-api-key'] == "12345helloworld"
|
||||
assert requestdata['product'] == "Bugzilla"
|
||||
assert requestdata['description'] == "Filed by: MyName\n\nIntermittent Description"
|
||||
assert requestdata['component'] == "Administration"
|
||||
assert requestdata['summary'] == "Intermittent summary"
|
||||
assert requestdata['comment_tags'] == "treeherder"
|
||||
assert requestdata['version'] == "4.0.17"
|
||||
assert requestdata['keywords'] == "intermittent-failure"
|
||||
resp_body = {"id": 323}
|
||||
return(200, headers, json.dumps(resp_body))
|
||||
|
||||
responses.add_callback(
|
||||
responses.POST, "https://thisisnotbugzilla.org/rest/bug",
|
||||
callback=request_callback, match_querystring=False,
|
||||
content_type="application/json",
|
||||
)
|
||||
|
||||
client = APIClient()
|
||||
|
||||
resp = client.post(
|
||||
reverse("bugzilla-create-bug"),
|
||||
{
|
||||
"product": "Bugzilla",
|
||||
"component": "Administration",
|
||||
"summary": "Intermittent summary",
|
||||
"version": "4.0.17",
|
||||
"description": "Intermittent Description",
|
||||
"comment_tags": "treeherder",
|
||||
"keywords": "intermittent-failure",
|
||||
}
|
||||
)
|
||||
|
||||
content = json.loads(resp.content)
|
||||
|
||||
print content
|
||||
assert content['detail'] == "Authentication credentials were not provided."
|
|
@ -327,6 +327,7 @@ PARSER_MAX_SUMMARY_LINES = 200
|
|||
FAILURE_LINES_CUTOFF = 35
|
||||
|
||||
BZ_API_URL = "https://bugzilla.mozilla.org"
|
||||
BZ_API_KEY = env("BUGZILLA_API_KEY", default=None)
|
||||
|
||||
ORANGEFACTOR_SUBMISSION_URL = "https://brasstacks.mozilla.com/orangefactor/api/saveclassification"
|
||||
ORANGEFACTOR_HAWK_ID = "treeherder"
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
# Switch to using a different bugzilla instance
|
||||
BZ_API_URL = "http://bugzilla-dev.allizom.org/"
|
||||
|
||||
# Applications useful for development, e.g. debug_toolbar, django_extensions.
|
||||
# Always empty in production
|
||||
LOCAL_APPS = []
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
import requests
|
||||
from django.conf import settings
|
||||
from rest_framework import (status,
|
||||
viewsets)
|
||||
from rest_framework.decorators import list_route
|
||||
from rest_framework.permissions import IsAuthenticatedOrReadOnly
|
||||
from rest_framework.response import Response
|
||||
|
||||
from treeherder.etl.common import make_request
|
||||
|
||||
|
||||
class BugzillaViewSet(viewsets.ViewSet):
|
||||
permission_classes = (IsAuthenticatedOrReadOnly,)
|
||||
|
||||
@list_route(methods=['post'])
|
||||
def create_bug(self, request):
|
||||
"""
|
||||
Create a bugzilla bug with passed params
|
||||
"""
|
||||
|
||||
if settings.BZ_API_KEY is None:
|
||||
return Response({"failure": "Bugzilla API key not defined. This shouldn't happen."}, status=status.HTTP_400_BAD_REQUEST)
|
||||
else:
|
||||
params = request.data
|
||||
url = settings.BZ_API_URL + "/rest/bug"
|
||||
headers = {
|
||||
'x-bugzilla-api-key': settings.BZ_API_KEY
|
||||
}
|
||||
data = {
|
||||
'product': params["product"],
|
||||
'component': params["component"],
|
||||
'summary': params["summary"],
|
||||
'keywords': params["keywords"],
|
||||
'version': params["version"],
|
||||
'description': "Filed by: " + request.user.username + "\n\n" + params["description"],
|
||||
'comment_tags': "treeherder",
|
||||
}
|
||||
|
||||
try:
|
||||
response = make_request(url, method='POST', headers=headers, json=data)
|
||||
except requests.exceptions.HTTPError as e:
|
||||
response = e.response
|
||||
try:
|
||||
rsperror = response.json()['message']
|
||||
except:
|
||||
rsperror = response
|
||||
return Response({"failure": rsperror}, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
return Response({"success": response.json()["id"]})
|
|
@ -4,6 +4,7 @@ from rest_framework import routers
|
|||
|
||||
from treeherder.webapp.api import (artifact,
|
||||
bug,
|
||||
bugzilla,
|
||||
job_log_url,
|
||||
jobs,
|
||||
logslice,
|
||||
|
@ -108,6 +109,8 @@ default_router.register(r'performance/alert',
|
|||
default_router.register(r'performance/framework',
|
||||
performance_data.PerformanceFrameworkViewSet,
|
||||
base_name='performance-frameworks')
|
||||
default_router.register(r'bugzilla', bugzilla.BugzillaViewSet,
|
||||
base_name='bugzilla')
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^project/(?P<project>[\w-]{0,50})/',
|
||||
|
|
Загрузка…
Ссылка в новой задаче