Merge pull request #10 from mozilla/pushlog-features

Pushlog features
This commit is contained in:
Mauro Doglio 2013-08-29 09:01:25 -07:00
Родитель ed959a6b88 b23f62ffb8
Коммит d8ffa1b6b2
6 изменённых файлов: 120 добавлений и 45 удалений

Просмотреть файл

@ -67,19 +67,26 @@
ng-show="selectedJob">
<div class="navbar-inner">
<div class="container-fluid">
<div class="span5">
<div>Reason: {{ selectedJob.reason }}</div>
<div>Machine: {{ selectedJob.machine_name }}</div>
<div>Result: {{ selectedJob.result }}</div>
<div ng-show="lvArtifact">
<a target="_blank" href="/app/logviewer.html#?id={{ lvArtifact.id }}&repo={{ repo }}">View Structured Log</a>
<div class="span7">
<dl class="dl-horizontal">
<span ng-repeat="(label, value) in selectedJob.visibleFields">
<dt class="label label-info">{{label}}</dt>
<dd class="">{{value}}</dd>
</span>
</dl>
<div ng-show="selectedJob.lvArtifact"
class="btn">
<a target="_blank" href="{{ selectedJob.lvUrl }}">View Structured Log</a>
</div>
<div ng-hide="selectedJob.lvArtifact">
<em>Processing Structured Log</em>
</div>
<div ng-repeat="joblog in selectedJob.logs">
<a target="_blank" href="{{ joblog.url }}">Raw Log</a>
<a target="_blank" href="{{ joblog.url }}">Raw Log: {{ joblog.url }}</a>
</div>
</div>
<ul class="span7" >
<li ng-repeat="line in jobPrintlines">
<li ng-repeat="line in selectedJob.jobArtifact.blob.tinderbox_printlines">
<div ng-bind-html-unsafe="line"></div>
</li>
</ul>
@ -115,6 +122,7 @@
<script src="js/app.js"></script>
<script src="js/services.js"></script>
<script src="js/providers.js"></script>
<script src="js/directives.js"></script>
<script src="js/controllers/main.js"></script>
<script src="js/controllers/jobs.js"></script>
<script src="js/controllers/machines.js"></script>

Просмотреть файл

@ -37,34 +37,78 @@ treeherder.controller('JobsCtrl',
);
treeherder.controller('PushCtrl',
function PushCtrl($scope, $rootScope, $http, thResults, thServiceDomain) {
function PushCtrl($scope, $rootScope, $http, thResults, thUrl, thServiceDomain) {
// whether or not revision list for a push is collapsed
$scope.isCollapsedRevisions = true;
$scope.isCollapsedResults = true;
// get the jobs list for the current resultset
thResults.getResults($scope.push, $scope);
$scope.viewJob = function(job_uri) {
console.log(job_uri);
$http.get(thServiceDomain + job_uri).
$scope.viewJob = function(job) {
// view the job details in the lower job-details section
$rootScope.selectedJob = job;
// fields that will show in the job detail panel
$rootScope.selectedJob.visibleFields = {
"Reason": job.reason,
"State": job.state,
"Result": job.result,
"Type Name": job.job_type_name,
"Type Desc": job.job_type_description,
"Who": job.who,
"Job GUID": job.job_guid,
"Machine Name": job.machine_name,
"Machine Platform Arch": job.machine_platform_architecture,
"Machine Platform OS": job.machine_platform_os,
"Build Platform": job.build_platform,
"Build Arch": job.build_architecture,
"Build OS": job.build_os
};
$http.get(thServiceDomain + job.resource_uri).
success(function(data) {
console.log(data);
$rootScope.selectedJob = data;
$rootScope.lvArtifact = null;
$rootScope.jobArtifact = null;
$rootScope.selectedJob.logs = data.logs;
data.artifacts.forEach(function(artifact) {
if (artifact.name.contains("Job Artifact")) {
$rootScope.jobArtifact=artifact;
// we don't return the blobs with job, just resource_uris
// to them. For the Job Artifact, we want that blob, so we
// need to fetch the detail to get the blob which has the
// tinderbox_printlines, etc.
$http.get(thServiceDomain + artifact.resource_uri).
success(function(data) {
$rootScope.jobPrintlines = data.blob.tinderbox_printlines;
$rootScope.selectedJob.jobArtifact = data;
});
} else if (artifact.name === "Structured Log") {
$rootScope.lvArtifact=artifact;
// for the structured log, we don't need the blob here, we
// have everything we need in the artifact as is, so
// just save it.
$rootScope.selectedJob.lvArtifact=artifact;
$rootScope.selectedJob.lvUrl = thUrl.getLogViewerUrl(artifact.id);
}
});
});
};
$scope.viewLog = function(job_uri) {
// open the logviewer for this job in a new window
// currently, invoked by right-clicking a job.
$http.get(thServiceDomain + job_uri).
success(function(data) {
if (data.hasOwnProperty("artifacts")) {
data.artifacts.forEach(function(artifact) {
if (artifact.name === "Structured Log") {
window.open(thUrl.getLogViewerUrl(artifact.id));
}
});
} else {
console.log("Job had no artifacts: " + job_uri);
}
});
};
}
);

Просмотреть файл

@ -1,3 +1,14 @@
'use strict';
/* Directives */
treeherder.directive('ngRightClick', function($parse) {
return function(scope, element, attrs) {
var fn = $parse(attrs.ngRightClick);
element.bind('contextmenu', function(event) {
scope.$apply(function() {
event.preventDefault();
fn(scope, {$event:event});
});
});
};
});

Просмотреть файл

@ -22,6 +22,14 @@ treeherder.filter('typeClass', function() {
};
});
treeherder.filter('jobHover', function() {
// duration of job
return function(job) {
var duration = Math.round((job.end_timestamp - job.submit_timestamp) / 60);
return job.job_type_name + " - " + job.result + " - " + duration + "mins";
};
});
treeherder.filter('resultClass', function() {
// Add color to the button for this job
return function(input) {

Просмотреть файл

@ -1,7 +1,7 @@
'use strict';
/* Services */
treeherder.factory('thService',
treeherder.factory('thUrl',
['$rootScope', 'thServiceDomain',
function($rootScope, thServiceDomain) {
return {
@ -10,42 +10,45 @@ treeherder.factory('thService',
},
getProjectUrl: function(uri) {
return thServiceDomain + "/api/project/" + $rootScope.repo + uri;
},
getLogViewerUrl: function(artifactId) {
return "/app/logviewer.html#?id=" + artifactId + "&repo=" + $rootScope.repo;
}
};
return thService;
return thUrl;
}]);
treeherder.factory('thArtifact',
['$http', 'thService',
function($http, thService) {
['$http', 'thUrl',
function($http, thUrl) {
// get the pushes for this tree
// sample: 'resources/push_sample.json'
return {
getArtifact: function(id) {
return $http.get(thService.getProjectUrl(
return $http.get(thUrl.getProjectUrl(
"/artifact/" + id + "/?format=json"));
}
}
}]);
treeherder.factory('thResultSets',
['$http', 'thService',
function($http, thService) {
['$http', 'thUrl',
function($http, thUrl) {
// get the pushes for this tree
// sample: 'resources/push_sample.json'
return {
getResultSets: function() {
return $http.get(thService.getProjectUrl("/resultset/?format=json"));
return $http.get(thUrl.getProjectUrl("/resultset/?format=json"));
}
}
}]);
treeherder.factory('thResults',
['$http', 'thService', '$rootScope',
function($http, thService, $rootScope) {
['$http', 'thUrl', '$rootScope',
function($http, thUrl, $rootScope) {
var getWarningLevel = function(results) {
var COLORS = {
@ -71,7 +74,7 @@ treeherder.factory('thResults',
getResults: function(result_set, $scope) {
// store the results in scope for this push via ajax
var jobUrl = thService.getProjectUrl("/resultset/" + result_set.id + "/?format=json");
var jobUrl = thUrl.getProjectUrl("/resultset/" + result_set.id + "/?format=json");
console.log("fetching for " + result_set.id + " from: " + jobUrl);
$scope.isLoadingResults = true;
$http.get(jobUrl).
@ -114,14 +117,14 @@ treeherder.factory('thResults',
}]);
treeherder.factory('thRepos',
['$http', 'thService', '$rootScope',
function($http, thService, $rootScope) {
['$http', 'thUrl', '$rootScope',
function($http, thUrl, $rootScope) {
// get the repositories (aka trees)
// sample: 'resources/menu.json'
return {
getRepos: function($rootScope) {
$http.get(thService.getRootUrl("/repository/?format=json")).
$http.get(thUrl.getRootUrl("/repository/?format=json")).
success(function(data) {
$rootScope.repos = data;
});

Просмотреть файл

@ -53,20 +53,21 @@
ng-class="{'btn-group': group.symbol}">
<a ng-show="group.symbol"
class="btn-mini btn-info btn"
title="{{ group.job_group_name }}">
title="{{ group.name }}">
{{ group.symbol }}
</a>
<a class="btn-mini {{ job|typeClass }} {{ job.result|resultClass }}"
title="{{ job.job_type_name }}"
ng-repeat="job in group.jobs"
ng-click="viewJob(job.resource_uri)">
<!--
We should conditionally remove the fire icon once they have
starred it, most likely.
-->
<i class="icon-fire" ng-show="job.result=='fail' || job.result=='orange'"></i>
{{ job.job_type_symbol }}
</a>
<a class="btn-mini {{ job|typeClass }} {{ job.result|resultClass }}"
title="{{ job|jobHover }}"
ng-repeat="job in group.jobs"
ng-click="viewJob(job)"
ng-right-click="viewLog(job.resource_uri)">
<!--
We should conditionally remove the fire icon once they have
starred it, most likely.
-->
<i class="icon-fire" ng-show="job.result=='testfailed' || job.result=='busted'"></i>
{{ job.job_type_symbol }}
</a>
</div>
</div>
</div>