зеркало из https://github.com/mozilla/treeherder.git
Bug 1270629 - Replace Job Info artifacts with a "jobdetail" endpoint
This is simpler and removes one more type of artifact from the per-project databases.
This commit is contained in:
Родитель
d0ea27feb8
Коммит
af9c208792
|
@ -1,6 +1,7 @@
|
|||
import json
|
||||
|
||||
import pytest
|
||||
from django.forms import model_to_dict
|
||||
from mock import MagicMock
|
||||
|
||||
from tests.test_utils import post_collection
|
||||
|
@ -9,6 +10,7 @@ from treeherder.log_parser.parsers import StepParser
|
|||
from treeherder.model import error_summary
|
||||
from treeherder.model.derived import (ArtifactsModel,
|
||||
JobsModel)
|
||||
from treeherder.model.models import JobDetail
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
@ -361,7 +363,8 @@ def test_post_job_artifacts_by_add_artifact(
|
|||
}
|
||||
})
|
||||
|
||||
ji_blob = json.dumps({"job_details": [{"foo": "fah"}]})
|
||||
ji_blob = json.dumps({"job_details": [{"title": "mytitle",
|
||||
"value": "myvalue"}]})
|
||||
bapi_blob = json.dumps({"buildername": "merd"})
|
||||
pb_blob = json.dumps({"build_url": "feh", "chunk": 1, "config_file": "mah"})
|
||||
|
||||
|
@ -374,8 +377,17 @@ def test_post_job_artifacts_by_add_artifact(
|
|||
|
||||
post_collection(test_project, tjc)
|
||||
|
||||
check_artifacts(test_project, job_guid, 'parsed', 5,
|
||||
{'Bug suggestions', 'text_log_summary', 'Job Info',
|
||||
assert JobDetail.objects.count() == 1
|
||||
assert model_to_dict(JobDetail.objects.get(job__guid=job_guid)) == {
|
||||
'id': 1,
|
||||
'job': 1,
|
||||
'title': 'mytitle',
|
||||
'value': 'myvalue',
|
||||
'url': None
|
||||
}
|
||||
|
||||
check_artifacts(test_project, job_guid, 'parsed', 4,
|
||||
{'Bug suggestions', 'text_log_summary',
|
||||
'privatebuild', 'buildapi'}, mock_error_summary)
|
||||
|
||||
# ensure the parsing didn't happen
|
||||
|
|
|
@ -4,6 +4,7 @@ import pytest
|
|||
|
||||
from treeherder.etl.job_loader import JobLoader
|
||||
from treeherder.model.derived.artifacts import ArtifactsModel
|
||||
from treeherder.model.models import JobDetail
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
@ -55,7 +56,9 @@ def test_ingest_pulse_jobs(pulse_jobs, test_project, jm, result_set_stored,
|
|||
assert len(logs) == 1
|
||||
with ArtifactsModel(test_project) as am:
|
||||
artifacts = am.get_job_artifact_list(0, 10)
|
||||
assert len(artifacts) == 4
|
||||
assert len(artifacts) == 3
|
||||
|
||||
assert JobDetail.objects.count() == 2
|
||||
|
||||
|
||||
def test_transition_pending_running_complete(first_job, jm, mock_log_parser):
|
||||
|
|
|
@ -7,6 +7,8 @@ import simplejson as json
|
|||
from django.conf import settings
|
||||
from django.utils.six import BytesIO
|
||||
|
||||
from treeherder.model.models import JobDetail
|
||||
|
||||
from ..sampledata import SampleData
|
||||
|
||||
|
||||
|
@ -60,8 +62,8 @@ def mock_mozlog_get_log_handler(monkeypatch):
|
|||
def test_parse_log(jm, jobs_with_local_log, sample_resultset,
|
||||
mock_post_json, mock_fetch_json):
|
||||
"""
|
||||
check that at least 3 job_artifacts get inserted when running
|
||||
a parse_log task for a successful job
|
||||
check that 2 job_artifacts get inserted when running a parse_log task for
|
||||
a successful job and that JobDetail objects get created
|
||||
"""
|
||||
|
||||
jm.store_result_set_data(sample_resultset)
|
||||
|
@ -84,11 +86,12 @@ def test_parse_log(jm, jobs_with_local_log, sample_resultset,
|
|||
placeholders=[job_id]
|
||||
)
|
||||
|
||||
# we must have at least 3 artifacts:
|
||||
# we should have 2 artifacts:
|
||||
# 1 for the log viewer
|
||||
# 1 for the job artifact panel
|
||||
# 1 for the bug suggestions
|
||||
assert len(job_artifacts) >= 3
|
||||
assert len(job_artifacts) == 2
|
||||
# this log generates 4 job detail objects at present
|
||||
print JobDetail.objects.count() == 4
|
||||
|
||||
|
||||
def test_bug_suggestions_artifact(jm, jobs_with_local_log,
|
||||
|
@ -118,11 +121,10 @@ def test_bug_suggestions_artifact(jm, jobs_with_local_log,
|
|||
placeholders=[job_id]
|
||||
)
|
||||
|
||||
# we must have at least 3 artifacts:
|
||||
# we must have 2 artifacts:
|
||||
# 1 for the log viewer
|
||||
# 1 for the job artifact panel
|
||||
# 1 for the bug suggestions
|
||||
assert len(job_artifacts) >= 3
|
||||
assert len(job_artifacts) == 2
|
||||
|
||||
structured_log_artifact = [artifact for artifact in job_artifacts
|
||||
if artifact["name"] == "text_log_summary"][0]
|
||||
|
|
|
@ -14,6 +14,7 @@ from treeherder.model.models import (BuildPlatform,
|
|||
FailureClassification,
|
||||
FailureLine,
|
||||
Job,
|
||||
JobDetail,
|
||||
JobDuration,
|
||||
JobGroup,
|
||||
JobType,
|
||||
|
@ -368,6 +369,7 @@ def test_cycle_all_data(jm, sample_data,
|
|||
assert len(jobs_after) == 0
|
||||
assert FailureLine.objects.count() == 0
|
||||
assert Job.objects.count() == 0
|
||||
assert JobDetail.objects.count() == 0
|
||||
|
||||
|
||||
def test_cycle_one_job(jm, sample_data,
|
||||
|
@ -383,10 +385,17 @@ def test_cycle_one_job(jm, sample_data,
|
|||
|
||||
job_not_deleted = jm.get_job(2)[0]
|
||||
|
||||
failure_lines_remaining = create_failure_lines(test_repository,
|
||||
job_not_deleted["job_guid"],
|
||||
[(test_line, {}),
|
||||
(test_line, {"subtest": "subtest2"})])
|
||||
extra_objects = {
|
||||
'failure_lines': (FailureLine,
|
||||
create_failure_lines(test_repository,
|
||||
job_not_deleted["job_guid"],
|
||||
[(test_line, {}),
|
||||
(test_line, {"subtest": "subtest2"})])),
|
||||
'job_details': (JobDetail, [JobDetail.objects.create(
|
||||
job=Job.objects.get(guid=job_not_deleted["job_guid"]),
|
||||
title='test',
|
||||
value='testvalue')])
|
||||
}
|
||||
|
||||
time_now = time.time()
|
||||
cycle_date_ts = int(time_now - 7 * 24 * 3600)
|
||||
|
@ -424,8 +433,9 @@ def test_cycle_one_job(jm, sample_data,
|
|||
assert len(jobs_after) == len(jobs_before) - len(jobs_to_be_deleted)
|
||||
assert len(jobs_after) == Job.objects.count()
|
||||
|
||||
assert (set(item.id for item in FailureLine.objects.all()) ==
|
||||
set(item.id for item in failure_lines_remaining))
|
||||
for (object_type, objects) in extra_objects.values():
|
||||
assert (set(item.id for item in object_type.objects.all()) ==
|
||||
set(item.id for item in objects))
|
||||
|
||||
|
||||
def test_cycle_all_data_in_chunks(jm, sample_data,
|
||||
|
@ -467,6 +477,7 @@ def test_cycle_all_data_in_chunks(jm, sample_data,
|
|||
assert len(jobs_after) == 0
|
||||
assert Job.objects.count() == 0
|
||||
assert FailureLine.objects.count() == 0
|
||||
assert JobDetail.objects.count() == 0
|
||||
|
||||
|
||||
def test_cycle_task_set_meta(jm):
|
||||
|
|
|
@ -8,6 +8,7 @@ from django.forms import model_to_dict
|
|||
from treeherder.etl.perf import load_perf_artifacts
|
||||
from treeherder.model import utils
|
||||
from treeherder.model.models import (Job,
|
||||
JobDetail,
|
||||
ReferenceDataSignatures)
|
||||
|
||||
from .base import TreeherderModelBase
|
||||
|
@ -91,6 +92,19 @@ class ArtifactsModel(TreeherderModelBase):
|
|||
placeholders=artifact_placeholders,
|
||||
executemany=True)
|
||||
|
||||
def store_job_details(self, job, job_info_artifact):
|
||||
"""
|
||||
Store the contents of the job info artifact
|
||||
in job details
|
||||
"""
|
||||
job_details = json.loads(job_info_artifact['blob'])['job_details']
|
||||
for job_detail in job_details:
|
||||
JobDetail.objects.get_or_create(
|
||||
job=job,
|
||||
title=job_detail.get('title'),
|
||||
value=job_detail['value'],
|
||||
url=job_detail.get('url'))
|
||||
|
||||
def store_performance_artifact(
|
||||
self, job_ids, performance_artifact_placeholders):
|
||||
"""
|
||||
|
@ -169,6 +183,8 @@ class ArtifactsModel(TreeherderModelBase):
|
|||
artifact, performance_artifact_list,
|
||||
performance_artifact_job_id_list,
|
||||
job.project_specific_id)
|
||||
elif artifact_name == 'Job Info':
|
||||
self.store_job_details(job, artifact)
|
||||
else:
|
||||
self._adapt_job_artifact_collection(
|
||||
artifact, job_artifact_list,
|
||||
|
|
|
@ -22,6 +22,7 @@ from treeherder.model.models import (BuildPlatform,
|
|||
FailureClassification,
|
||||
FailureLine,
|
||||
Job,
|
||||
JobDetail,
|
||||
JobDuration,
|
||||
JobGroup,
|
||||
JobType,
|
||||
|
@ -751,9 +752,11 @@ into chunks of chunk_size size. Returns the number of result sets deleted"""
|
|||
# remove data from specified jobs tables that is older than max_timestamp
|
||||
self._execute_table_deletes(jobs_targets, 'jobs', sleep_time)
|
||||
|
||||
# Remove FailueLine + intermediate job entries for these jobs
|
||||
# Remove ORM entries for these jobs
|
||||
orm_delete(FailureLine, FailureLine.objects.filter(job_guid__in=job_guid_list),
|
||||
chunk_size, sleep_time)
|
||||
orm_delete(JobDetail, JobDetail.objects.filter(job__guid__in=job_guid_list),
|
||||
chunk_size, sleep_time)
|
||||
orm_delete(Job, Job.objects.filter(guid__in=job_guid_list),
|
||||
chunk_size, sleep_time)
|
||||
|
||||
|
@ -1272,7 +1275,6 @@ into chunks of chunk_size size. Returns the number of result sets deleted"""
|
|||
push_timestamps = {}
|
||||
|
||||
for index, job in enumerate(job_placeholders):
|
||||
|
||||
# Replace reference data with their associated ids
|
||||
self._set_data_ids(
|
||||
index,
|
||||
|
|
|
@ -93,6 +93,7 @@
|
|||
<script src="js/models/resultset.js"></script>
|
||||
<script src="js/models/resultsets_store.js"></script>
|
||||
<script src="js/models/job_artifact.js"></script>
|
||||
<script src="js/models/job_detail.js"></script>
|
||||
<script src="js/models/repository.js"></script>
|
||||
<script src="js/models/bug_job_map.js"></script>
|
||||
<script src="js/models/classification.js"></script>
|
||||
|
|
|
@ -2,13 +2,13 @@
|
|||
|
||||
logViewerApp.controller('LogviewerCtrl', [
|
||||
'$anchorScroll', '$http', '$location', '$q', '$rootScope', '$scope',
|
||||
'$timeout', 'ThJobArtifactModel', 'ThLog', 'ThLogSliceModel', 'ThJobModel', 'thNotify',
|
||||
'dateFilter', 'ThResultSetModel', 'thDateFormat', 'thReftestStatus',
|
||||
'$timeout', 'ThJobArtifactModel', 'ThJobDetailModel', 'ThLog', 'ThLogSliceModel',
|
||||
'ThJobModel', 'thNotify', 'dateFilter', 'ThResultSetModel', 'thDateFormat',
|
||||
'thReftestStatus',
|
||||
function Logviewer(
|
||||
$anchorScroll, $http, $location, $q, $rootScope, $scope,
|
||||
$timeout, ThJobArtifactModel, ThLog, ThLogSliceModel, ThJobModel, thNotify,
|
||||
dateFilter, ThResultSetModel, thDateFormat, thReftestStatus) {
|
||||
|
||||
var $log = new ThLog('LogviewerCtrl');
|
||||
|
||||
// changes the size of chunks pulled from server
|
||||
|
@ -250,6 +250,9 @@ logViewerApp.controller('LogviewerCtrl', [
|
|||
$scope.logProperties.push({label: "Revision", value: revision});
|
||||
});
|
||||
|
||||
ThJobDetailModel.getJobDetails(job.job_guid).then(function(jobDetails) {
|
||||
$scope.job_details = jobDetails;
|
||||
});
|
||||
}, function (error) {
|
||||
$scope.loading = false;
|
||||
$scope.jobExists = false;
|
||||
|
@ -257,42 +260,37 @@ logViewerApp.controller('LogviewerCtrl', [
|
|||
});
|
||||
|
||||
// Make the log and job artifacts available
|
||||
ThJobArtifactModel.get_list({job_id: $scope.job_id, name__in: 'text_log_summary,Job Info'})
|
||||
ThJobArtifactModel.get_list({job_id: $scope.job_id, name: 'text_log_summary'})
|
||||
.then(function(artifactList) {
|
||||
artifactList.forEach(function(artifact, $event) {
|
||||
if (artifact.name === 'text_log_summary') {
|
||||
$scope.artifact = artifact.blob;
|
||||
$scope.step_data = artifact.blob.step_data;
|
||||
if (artifactList.length === 0)
|
||||
return;
|
||||
$scope.artifact = artifactList[0].blob;
|
||||
$scope.step_data = $scope.artifact.step_data;
|
||||
|
||||
// If the log contains no errors load the head otherwise
|
||||
// load the first failure step line in the artifact. We
|
||||
// also need to test for the 0th element for outlier jobs.
|
||||
if ($scope.step_data.steps[0]) {
|
||||
// If the log contains no errors load the head otherwise
|
||||
// load the first failure step line in the artifact. We
|
||||
// also need to test for the 0th element for outlier jobs.
|
||||
if ($scope.step_data.steps[0]) {
|
||||
|
||||
if ($scope.step_data.all_errors.length === 0) {
|
||||
angular.element(document).ready(function () {
|
||||
if (isNaN($scope.selectedBegin)) {
|
||||
for (var i = 0; i < $scope.step_data.steps.length; i++) {
|
||||
var step = $scope.step_data.steps[i];
|
||||
if (step.result !== "success") {
|
||||
$scope.selectedBegin = step.started_linenumber;
|
||||
$scope.selectedEnd = step.finished_linenumber;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($scope.step_data.all_errors.length === 0) {
|
||||
angular.element(document).ready(function () {
|
||||
if (isNaN($scope.selectedBegin)) {
|
||||
for (var i = 0; i < $scope.step_data.steps.length; i++) {
|
||||
var step = $scope.step_data.steps[i];
|
||||
if (step.result !== "success") {
|
||||
$scope.selectedBegin = step.started_linenumber;
|
||||
$scope.selectedEnd = step.finished_linenumber;
|
||||
break;
|
||||
}
|
||||
moveScrollToLineNumber($scope.selectedBegin, $event);
|
||||
});
|
||||
} else {
|
||||
$scope.setLineNumber($scope.step_data.all_errors[0].linenumber);
|
||||
moveScrollToLineNumber($scope.selectedBegin, $event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else if (artifact.name === 'Job Info') {
|
||||
$scope.job_details = artifact.blob.job_details;
|
||||
moveScrollToLineNumber($scope.selectedBegin, $event);
|
||||
});
|
||||
} else {
|
||||
$scope.setLineNumber($scope.step_data.all_errors[0].linenumber);
|
||||
moveScrollToLineNumber($scope.selectedBegin, $event);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
'use strict';
|
||||
|
||||
treeherder.factory('ThJobDetailModel', [
|
||||
'$http', 'thUrl', function($http, thUrl) {
|
||||
return {
|
||||
getJobDetails: function(jobGuid, config) {
|
||||
config = config || {};
|
||||
var timeout = config.timeout || null;
|
||||
|
||||
return $http.get(thUrl.getRootUrl("/jobdetail/"), {
|
||||
params: { job__guid: jobGuid },
|
||||
timeout: timeout
|
||||
}).then(function(response) {
|
||||
return response.data.results;
|
||||
});
|
||||
}
|
||||
};
|
||||
}]);
|
|
@ -96,13 +96,16 @@
|
|||
ng-cloak class="break-word">{{property.value}}</td>
|
||||
</tr>
|
||||
<tr ng-repeat="line in job_details | orderBy:'title'">
|
||||
<th ng-cloak>{{line.title}}:</th>
|
||||
<td ng-switch on="line.content_type">
|
||||
<a ng-cloak ng-switch-when="link" title="{{line.value}}"
|
||||
href="{{line.url}}" target="_blank">{{line.value}}</a>
|
||||
<span ng-switch-when="raw_html" ng-bind-html="line.value"></span>
|
||||
<span ng-switch-default>{{line.value}}</span>
|
||||
<td/>
|
||||
<th ng-cloak>
|
||||
<span ng-if="line.title">
|
||||
{{line.title}}:
|
||||
</span>
|
||||
</th>
|
||||
<td ng-cloak>
|
||||
<a ng-if="line.url" title="{{line.value}}"
|
||||
href="{{line.url}}" target="_blank">{{line.value}}</a>
|
||||
<span ng-if="!line.url" ng-bind-html="line.value"></span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
@ -147,6 +150,7 @@
|
|||
|
||||
<!-- Model services -->
|
||||
<script src="js/models/job_artifact.js"></script>
|
||||
<script src="js/models/job_detail.js"></script>
|
||||
<script src="js/models/job.js"></script>
|
||||
<script src="js/models/runnable_job.js"></script>
|
||||
<script src="js/models/resultset.js"></script>
|
||||
|
|
|
@ -5,15 +5,15 @@ treeherder.controller('PluginCtrl', [
|
|||
'thClassificationTypes', 'ThJobModel', 'thEvents', 'dateFilter', 'thDateFormat',
|
||||
'numberFilter', 'ThBugJobMapModel', 'thResultStatus', 'thJobFilters',
|
||||
'ThResultSetModel', 'ThLog', '$q', 'thPinboard', 'ThJobArtifactModel',
|
||||
'thBuildApi', 'thNotify', 'ThJobLogUrlModel', 'ThModelErrors', 'thTabs',
|
||||
'$timeout', 'thReftestStatus', 'ThResultSetStore',
|
||||
'ThJobDetailModel', 'thBuildApi', 'thNotify', 'ThJobLogUrlModel', 'ThModelErrors',
|
||||
'thTabs', '$timeout', 'thReftestStatus', 'ThResultSetStore',
|
||||
'PhSeries', 'thServiceDomain', 'ThFailureLinesModel',
|
||||
function PluginCtrl(
|
||||
$scope, $rootScope, $location, $http, thUrl, ThJobClassificationModel,
|
||||
thClassificationTypes, ThJobModel, thEvents, dateFilter, thDateFormat,
|
||||
numberFilter, ThBugJobMapModel, thResultStatus, thJobFilters,
|
||||
ThResultSetModel, ThLog, $q, thPinboard, ThJobArtifactModel,
|
||||
thBuildApi, thNotify, ThJobLogUrlModel, ThModelErrors, thTabs,
|
||||
ThJobDetailModel, thBuildApi, thNotify, ThJobLogUrlModel, ThModelErrors, thTabs,
|
||||
$timeout, thReftestStatus, ThResultSetStore, PhSeries,
|
||||
thServiceDomain, ThFailureLinesModel) {
|
||||
|
||||
|
@ -105,9 +105,9 @@ treeherder.controller('PluginCtrl', [
|
|||
var selectJobPromise = null;
|
||||
var selectJobRetryPromise = null;
|
||||
|
||||
var selectJob = function(job_id) {
|
||||
var selectJob = function(job) {
|
||||
// set the scope variables needed for the job detail panel
|
||||
if (job_id) {
|
||||
if (job.id) {
|
||||
$scope.job_detail_loading = true;
|
||||
if(selectJobPromise !== null){
|
||||
$log.debug("timing out previous job request");
|
||||
|
@ -121,34 +121,33 @@ treeherder.controller('PluginCtrl', [
|
|||
$scope.job = {};
|
||||
$scope.artifacts = {};
|
||||
$scope.job_details = [];
|
||||
var jobDetailPromise = ThJobModel.get(
|
||||
$scope.repoName, job_id,
|
||||
var jobPromise = ThJobModel.get(
|
||||
$scope.repoName, job.id,
|
||||
{timeout: selectJobPromise});
|
||||
|
||||
var buildapiArtifactPromise = ThJobArtifactModel.get_list(
|
||||
{name: "buildapi", "type": "json", job_id: job_id},
|
||||
{name: "buildapi", "type": "json", job_id: job.id},
|
||||
{timeout: selectJobPromise});
|
||||
|
||||
var jobInfoArtifactPromise = ThJobArtifactModel.get_list({
|
||||
name: "Job Info", "type": "json", job_id: job_id},
|
||||
{timeout: selectJobPromise});
|
||||
var jobDetailPromise = ThJobDetailModel.getJobDetails(
|
||||
job.job_guid, {timeout: selectJobPromise});
|
||||
|
||||
var jobLogUrlPromise = ThJobLogUrlModel.get_list(
|
||||
job_id,
|
||||
job.id,
|
||||
{timeout: selectJobPromise});
|
||||
|
||||
var phSeriesPromise = PhSeries.getSeriesData(
|
||||
$scope.repoName, { job_id: job_id });
|
||||
$scope.repoName, { job_id: job.id });
|
||||
|
||||
return $q.all([
|
||||
jobDetailPromise,
|
||||
jobPromise,
|
||||
buildapiArtifactPromise,
|
||||
jobInfoArtifactPromise,
|
||||
jobDetailPromise,
|
||||
jobLogUrlPromise,
|
||||
phSeriesPromise
|
||||
]).then(function(results){
|
||||
|
||||
//the first result comes from the job detail promise
|
||||
//the first result comes from the job promise
|
||||
$scope.job = results[0];
|
||||
if ($scope.job.state === 'running') {
|
||||
$scope.eta = $scope.job.running_time_remaining();
|
||||
|
@ -162,7 +161,6 @@ treeherder.controller('PluginCtrl', [
|
|||
|
||||
// the second result come from the buildapi artifact promise
|
||||
var buildapi_artifact = results[1];
|
||||
|
||||
// if this is a buildbot job use the buildername for searching
|
||||
if (buildapi_artifact.length > 0 &&
|
||||
_.has(buildapi_artifact[0], 'blob')){
|
||||
|
@ -175,23 +173,14 @@ treeherder.controller('PluginCtrl', [
|
|||
$scope.jobSearchSignature = $scope.job.signature;
|
||||
$scope.jobSearchStrHref = getJobSearchStrHref($scope.jobSearchStr);
|
||||
$scope.jobSearchSignatureHref = getJobSearchStrHref($scope.job.signature);
|
||||
// the third result comes from the job info artifact promise
|
||||
var jobInfoArtifact = results[2];
|
||||
if (jobInfoArtifact.length > 0) {
|
||||
// The job artifacts may have many "Job Info" blobs so
|
||||
// we merge them here to make displaying them in the UI
|
||||
// easier.
|
||||
$scope.job_details = jobInfoArtifact.reduce(function(result, artifact) {
|
||||
if (artifact.blob && Array.isArray(artifact.blob.job_details)) {
|
||||
result = result.concat(artifact.blob.job_details);
|
||||
}
|
||||
if ($scope.artifacts.buildapi) {
|
||||
$scope.artifacts.buildapi.blob.title = "Buildername";
|
||||
$scope.artifacts.buildapi.blob.value = $scope.artifacts.buildapi.blob.buildername;
|
||||
result = result.concat($scope.artifacts.buildapi.blob);
|
||||
}
|
||||
return result;
|
||||
}, []);
|
||||
|
||||
// the third result comes from the job detail promise
|
||||
$scope.job_details = results[2];
|
||||
// incorporate the buildername into the job details if it is present
|
||||
if ($scope.artifacts.buildapi) {
|
||||
$scope.artifacts.buildapi.blob.title = "Buildername";
|
||||
$scope.artifacts.buildapi.blob.value = $scope.artifacts.buildapi.blob.buildername;
|
||||
$scope.job_details = $scope.job_details.concat($scope.artifacts.buildapi.blob);
|
||||
$scope.buildernameIndex = _.findIndex($scope.job_details, {title: "Buildername"});
|
||||
}
|
||||
|
||||
|
@ -234,7 +223,7 @@ treeherder.controller('PluginCtrl', [
|
|||
)){
|
||||
selectJobRetryPromise = $timeout(function(){
|
||||
// refetch the job data details
|
||||
selectJobAndRender(job_id);
|
||||
selectJobAndRender(job);
|
||||
}, 5000);
|
||||
}
|
||||
});
|
||||
|
@ -447,15 +436,15 @@ treeherder.controller('PluginCtrl', [
|
|||
}
|
||||
};
|
||||
|
||||
var selectJobAndRender = function(job_id) {
|
||||
$scope.jobLoadedPromise = selectJob(job_id);
|
||||
var selectJobAndRender = function(job) {
|
||||
$scope.jobLoadedPromise = selectJob(job);
|
||||
$scope.jobLoadedPromise.then(function(){
|
||||
thTabs.showTab(thTabs.selectedTab, job_id);
|
||||
thTabs.showTab(thTabs.selectedTab, job.id);
|
||||
});
|
||||
};
|
||||
|
||||
$rootScope.$on(thEvents.jobClick, function(event, job) {
|
||||
selectJobAndRender(job.id);
|
||||
selectJobAndRender(job);
|
||||
$rootScope.selectedJob = job;
|
||||
});
|
||||
|
||||
|
|
|
@ -1,17 +1,14 @@
|
|||
<div class="job-tabs-content">
|
||||
<ul class="list-unstyled">
|
||||
<li ng-repeat="line in job_details | orderBy:'title'" class="small">
|
||||
<label ng-if="line.content_type != 'TalosResult'">{{line.title}}:</label>
|
||||
<span ng-if="line.content_type != 'TalosResult'" ng-switch on="line.content_type">
|
||||
<a ng-switch-when="link" title="{{line.value}}"
|
||||
href="{{line.url}}" target="_blank">{{line.value}}</a>
|
||||
<span ng-if="line.value.endsWith('raw.log')">
|
||||
- <a title="{{line.value}}" href="http://mozilla.github.io/wptview/#/?urls={{line.url | encodeURIComponent}},{{job_details[buildernameIndex].value | encodeURIComponent}}">open in test results viewer</a>
|
||||
</span>
|
||||
<span ng-switch-when="raw_html" ng-bind-html="line.value"></span>
|
||||
<span title="{{line.value}}" ng-switch-when="object">{{line.value}}</span>
|
||||
<span title="{{line.value}}" ng-switch-default>{{line.value}}</span>
|
||||
<label>{{line.title ? line.title : 'Untitled data'}}:</label>
|
||||
<!-- URL provided -->
|
||||
<a ng-if="line.url" title="{{line.value}}" href="{{line.url}}" target="_blank">{{line.value}}</a>
|
||||
<span ng-if="line.url && line.value.endsWith('raw.log')">
|
||||
- <a title="{{line.value}}" href="http://mozilla.github.io/wptview/#/?urls={{line.url | encodeURIComponent}},{{job_details[buildernameIndex].value | encodeURIComponent}}">open in test results viewer</a>
|
||||
</span>
|
||||
<!-- no URL (just informational) -->
|
||||
<span ng-if="!line.url" ng-bind-html="line.value"></span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
Загрузка…
Ссылка в новой задаче