зеркало из https://github.com/mozilla/treeherder.git
endpoints for pushes and results by platform
This commit is contained in:
Родитель
ce6617b4e8
Коммит
534b919b6c
|
@ -132,12 +132,14 @@ class JobsModel(TreeherderModelBase):
|
|||
|
||||
return id_iter.get_column_data('id')
|
||||
|
||||
def get_push_result_list(self, page, limit):
|
||||
def get_result_set_list(self, page, limit):
|
||||
"""
|
||||
Retrieve a list of pushes with associated revisions and jobs.
|
||||
Retrieve a list of ``result_sets`` (also known as ``pushes``)
|
||||
with associated revisions. No jobs
|
||||
|
||||
Mainly used by the restful api to list the pushes in the UI
|
||||
"""
|
||||
proc = "jobs.selects.get_push_result_list"
|
||||
proc = "jobs.selects.get_result_set_list"
|
||||
push_dict = self.get_jobs_dhub().execute(
|
||||
proc=proc,
|
||||
placeholders=[page, limit],
|
||||
|
@ -147,6 +149,22 @@ class JobsModel(TreeherderModelBase):
|
|||
|
||||
return push_dict
|
||||
|
||||
def get_job_list_by_result_set(self, result_set_id):
|
||||
"""
|
||||
Retrieve a list of ``jobs`` with results.
|
||||
|
||||
Mainly used by the restful api to list the job results in the UI
|
||||
"""
|
||||
proc = "jobs.selects.get_job_list_by_result_set"
|
||||
job_dict = self.get_jobs_dhub().execute(
|
||||
proc=proc,
|
||||
placeholders=[result_set_id],
|
||||
debug_show=self.DEBUG,
|
||||
return_type='iter',
|
||||
)
|
||||
|
||||
return job_dict
|
||||
|
||||
##################
|
||||
#
|
||||
# Objectstore functionality
|
||||
|
@ -428,12 +446,19 @@ class JobsModel(TreeherderModelBase):
|
|||
)
|
||||
return self.get_revision_id(src["revision"])
|
||||
|
||||
def _insert_revision_map(self, revision_id, result_set_id):
|
||||
def _get_or_create_revision_map(self, revision_id, result_set_id):
|
||||
"""
|
||||
Create a mapping between revision and result_set.
|
||||
|
||||
Return: nothing
|
||||
"""
|
||||
self._insert_data(
|
||||
'set_revision_map',
|
||||
[
|
||||
revision_id,
|
||||
result_set_id
|
||||
result_set_id,
|
||||
revision_id,
|
||||
result_set_id,
|
||||
]
|
||||
)
|
||||
|
||||
|
|
|
@ -66,7 +66,13 @@
|
|||
"sql":"INSERT INTO `revision_map` (
|
||||
`revision_id`,
|
||||
`result_set_id`)
|
||||
VALUES (?,?)",
|
||||
SELECT ?,?
|
||||
FROM DUAL
|
||||
WHERE NOT EXISTS (
|
||||
SELECT `revision_id`, `result_set_id`
|
||||
FROM `revision`
|
||||
WHERE `revision` = ? AND `result_set_id` = ?
|
||||
)",
|
||||
|
||||
"host":"master_host"
|
||||
},
|
||||
|
@ -156,19 +162,47 @@
|
|||
WHERE `revision` = ?",
|
||||
"host": "read_host"
|
||||
},
|
||||
"get_push_result_list":{
|
||||
"sql":"SELECT rs.revision_hash,
|
||||
rev.revision, rev.author, rev.push_timestamp, rev.repository_id, rev.comments,
|
||||
job.job_guid, job.build_platform_id, job.machine_platform_id, job.machine_id, job.job_type_id, job.who, job.result, job.state
|
||||
FROM result_set as rs
|
||||
"get_result_set_list":{
|
||||
"sql":"SELECT
|
||||
`rs`.`id`,
|
||||
`rs`.`revision_hash`,
|
||||
`rs`.`push_timestamp`,
|
||||
`rev`.`revision`,
|
||||
`rev`.`author`,
|
||||
`rev`.`repository_id`,
|
||||
`rev`.`comments`
|
||||
FROM result_set as rs
|
||||
LEFT JOIN revision_map as rm
|
||||
ON rs.id = rm.result_set_id
|
||||
LEFT JOIN revision as rev
|
||||
ON rm.revision_id = rev.id
|
||||
LEFT JOIN job
|
||||
ON rs.id = job.result_set_id
|
||||
LIMIT ?,?",
|
||||
"host": "read_host"
|
||||
},
|
||||
"get_job_list_by_result_set":{
|
||||
"sql":"SELECT
|
||||
j.`job_guid`,
|
||||
j.`build_platform_id`,
|
||||
mp.`platform`,
|
||||
m.`name`,
|
||||
jt.`name`,
|
||||
jt.`symbol`,
|
||||
jt.`description`,
|
||||
j.`who`,
|
||||
j.`result_set_id`,
|
||||
j.`result`,
|
||||
j.`state`
|
||||
FROM `job` as j
|
||||
LEFT JOIN `treeherder`.`machine` as m
|
||||
ON j.`machine_id` = m.id
|
||||
LEFT JOIN `treeherder`.`machine_platform` as mp
|
||||
ON j.`machine_platform_id` = mp.id
|
||||
LEFT JOIN `treeherder`.`build_platform` as bp
|
||||
ON j.`build_platform_id` = bp.id
|
||||
LEFT JOIN `treeherder`.`job_type` as jt
|
||||
ON j.`job_type_id` = jt.id
|
||||
WHERE `result_set_id` = ?",
|
||||
"host": "read_host"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,9 +17,9 @@ project_bound_router.register(
|
|||
base_name='jobs',
|
||||
)
|
||||
project_bound_router.register(
|
||||
r'pushes',
|
||||
views.PushViewSet,
|
||||
base_name='pushes',
|
||||
r'resultset',
|
||||
views.ResultSetViewSet,
|
||||
base_name='resultset',
|
||||
)
|
||||
|
||||
# this is the default router for plain restful endpoints
|
||||
|
|
|
@ -83,19 +83,56 @@ class JobsViewSet(viewsets.ViewSet):
|
|||
|
||||
return Response(obj)
|
||||
|
||||
def get_warning_level(self, jobs):
|
||||
job_states = set([x["result"] for x in jobs])
|
||||
if "busted" in job_states:
|
||||
return "red"
|
||||
elif "orange" in job_states:
|
||||
return "orange"
|
||||
elif "pending" in job_states:
|
||||
return "grey"
|
||||
elif "running" in job_states:
|
||||
return "grey"
|
||||
else:
|
||||
return "green"
|
||||
|
||||
def list(self, request, project):
|
||||
"""
|
||||
GET method implementation for list view
|
||||
"""
|
||||
try:
|
||||
page = request.QUERY_PARAMS.get('page', 0)
|
||||
jm = JobsModel(project)
|
||||
objs = jm.get_job_list(page, 10)
|
||||
return Response(objs)
|
||||
|
||||
if "result_set_id" in request.QUERY_PARAMS:
|
||||
# @@@ todo: I'm thinking this should be a separate view entirely. it has a totally different return shape
|
||||
# or should this just supplant the other list return shape? I don't know when we'd use the other one.
|
||||
# this is all for the UI, after all.
|
||||
|
||||
# if result_set_id is passed, we don't use pagination
|
||||
rsid = request.QUERY_PARAMS.get('result_set_id')
|
||||
objs_ungrouped = jm.get_job_list_by_result_set(rsid)
|
||||
# group these by their platforms for return
|
||||
objs_sorted = sorted(objs_ungrouped, key=lambda x: x["platform"])
|
||||
import itertools
|
||||
objs = []
|
||||
for k, g in itertools.groupby(objs_sorted, key=lambda x: x["platform"]):
|
||||
jobs = list(g)
|
||||
objs.append({
|
||||
"platform": k,
|
||||
"warning_level": self.get_warning_level(jobs),
|
||||
"jobs": jobs
|
||||
})
|
||||
else:
|
||||
page = request.QUERY_PARAMS.get('page', 0)
|
||||
objs = jm.get_job_list(page, 10)
|
||||
|
||||
return Response(objs, headers={"Access-Control-Allow-Origin": "*"})
|
||||
except DatasetNotFoundError as e:
|
||||
return Response({"message": unicode(e)}, status=404)
|
||||
except Exception as e: # pragma nocover
|
||||
return Response({"message": unicode(e)}, status=500)
|
||||
finally:
|
||||
jm.disconnect()
|
||||
|
||||
@action()
|
||||
def update_state(self, request, project, pk=None):
|
||||
|
@ -131,96 +168,28 @@ class JobsViewSet(viewsets.ViewSet):
|
|||
return Response({"message": "state updated to '{0}'".format(state)})
|
||||
|
||||
|
||||
class PushViewSet(viewsets.ViewSet):
|
||||
"""GET a list of pushes with revisions and job results
|
||||
|
||||
Result sets are synonymous with Pushes in the Jobs Schema
|
||||
|
||||
returns something sort of like:
|
||||
|
||||
pushes: [
|
||||
{
|
||||
revisions: [
|
||||
...
|
||||
],
|
||||
platforms: [
|
||||
results...
|
||||
]
|
||||
},
|
||||
{...}
|
||||
]
|
||||
class ResultSetViewSet(viewsets.ViewSet):
|
||||
"""GET a list of ``result sets`` with revisions
|
||||
|
||||
``result sets`` are synonymous with ``pushes`` in the ui
|
||||
"""
|
||||
|
||||
def get_push_warning_level(self, jobs):
|
||||
job_states = set([x["state"] for x in jobs])
|
||||
if "fail" in job_states:
|
||||
return "red"
|
||||
elif "orange" in job_states:
|
||||
return "orange"
|
||||
elif "pending" or "running" in job_states:
|
||||
return "grey"
|
||||
else:
|
||||
return "green"
|
||||
|
||||
def list(self, request, project):
|
||||
"""
|
||||
GET method for list of pushes with results
|
||||
GET method for list of result_sets with revisions
|
||||
"""
|
||||
try:
|
||||
page = request.QUERY_PARAMS.get('page', 0)
|
||||
jm = JobsModel(project)
|
||||
# objs = jm.get_push_result_list(page, 1000)
|
||||
|
||||
objs = sorted(
|
||||
jm.get_push_result_list(page, 1000),
|
||||
key=lambda x: x["revision_hash"]
|
||||
)
|
||||
|
||||
import itertools
|
||||
pushes = []
|
||||
for k, g in itertools.groupby(objs,
|
||||
key=lambda x: x["revision_hash"]):
|
||||
jobs = list(g)
|
||||
# extract data for the push
|
||||
email = jobs[0]["who"]
|
||||
timestamp = jobs[0]["push_timestamp"]
|
||||
|
||||
revisions = []
|
||||
for rk, rg in itertools.groupby(jobs,
|
||||
key=lambda y: y["revision"]):
|
||||
revs = list(rg)
|
||||
revisions.append({
|
||||
"name": revs[0]["author"],
|
||||
"revision": revs[0]["revision"],
|
||||
"repository": revs[0]["repository_id"],
|
||||
"message": revs[0]["comments"]
|
||||
})
|
||||
|
||||
# remove unwanted fields from the jobs
|
||||
for job in jobs:
|
||||
del(job["revision_hash"])
|
||||
del(job["who"])
|
||||
del(job["revision"])
|
||||
del(job["repository_id"])
|
||||
|
||||
pushes.append({
|
||||
"revision_hash": k,
|
||||
"email": email,
|
||||
"timestamp": timestamp,
|
||||
"warning_level": self.get_push_warning_level(list(g)),
|
||||
"revisions": revisions,
|
||||
"jobs": jobs
|
||||
})
|
||||
|
||||
|
||||
|
||||
return Response(pushes)
|
||||
objs = jm.get_result_set_list(page, 1000)
|
||||
return Response(objs, headers={"Access-Control-Allow-Origin": "*"})
|
||||
except DatasetNotFoundError as e:
|
||||
return Response({"message": unicode(e)}, status=404)
|
||||
except Exception as e: # pragma nocover
|
||||
return Response({"message": unicode(e)}, status=500)
|
||||
|
||||
finally:
|
||||
jm.disconnect()
|
||||
|
||||
|
||||
#####################
|
||||
|
|
Загрузка…
Ссылка в новой задаче