Bug 1301729 - Store buildbot request id as a job detail

This commit is contained in:
William Lachance 2016-09-12 13:07:29 -04:00
Родитель d29527e96a
Коммит 7e4ec3423e
7 изменённых файлов: 84 добавлений и 57 удалений

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

@ -418,3 +418,35 @@ def test_post_job_with_default_tier(test_project, result_set_stored,
job = [x for x in jobs_model.get_job_list(0, 20)
if x['job_guid'] == job_guid][0]
assert job['tier'] == 1
def test_post_job_with_buildapi_artifact(test_project, result_set_stored,
mock_post_json):
"""
test submitting a job with a buildapi artifact gets that stored (and
we update the job object)
"""
tjc = client.TreeherderJobCollection()
job_guid = 'd22c74d4aa6d2a1dcba96d95dccbd5fdca70cf33'
tj = client.TreeherderJob({
'project': test_project,
'revision': result_set_stored[0]['revision'],
'job': {
'artifacts': [],
'job_guid': job_guid,
'state': 'completed',
}
})
tj.add_artifact("buildapi", "json",
json.dumps({"buildername": "Windows 8 64-bit cheezburger",
"request_id": 1234}))
tjc.add(tj)
post_collection(test_project, tjc)
assert Job.objects.count() == 1
assert JobDetail.objects.count() == 1
buildbot_request_id_detail = JobDetail.objects.all()[0]
assert buildbot_request_id_detail.title == 'buildbot_request_id'
assert buildbot_request_id_detail.value == str(1234)
assert buildbot_request_id_detail.url is None

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

@ -255,6 +255,17 @@ class ArtifactsModel(TreeherderModelBase):
self._adapt_job_artifact_collection(
artifact, job_artifact_list,
job.project_specific_id)
elif artifact_name == 'buildapi':
buildbot_request_id = json.loads(artifact['blob']).get(
'request_id')
if buildbot_request_id:
JobDetail.objects.update_or_create(
job=job,
title='buildbot_request_id',
value=str(buildbot_request_id))
self._adapt_job_artifact_collection(
artifact, job_artifact_list,
job.project_specific_id)
else:
self._adapt_job_artifact_collection(
artifact, job_artifact_list,

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

@ -90,13 +90,13 @@ treeherderApp.controller('ResultSetCtrl', [
'thUrl', 'thServiceDomain', 'thResultStatusInfo', 'thDateFormat',
'ThResultSetStore', 'thEvents', 'thJobFilters', 'thNotify',
'thBuildApi', 'thPinboard', 'ThResultSetModel', 'dateFilter',
'ThModelErrors', 'ThJobModel', 'ThJobArtifactModel',
'ThModelErrors', 'ThJobModel', 'ThJobDetailModel',
function ResultSetCtrl(
$scope, $rootScope, $http, ThLog, $location,
thUrl, thServiceDomain, thResultStatusInfo, thDateFormat,
ThResultSetStore, thEvents, thJobFilters, thNotify,
thBuildApi, thPinboard, ThResultSetModel, dateFilter, ThModelErrors, ThJobModel,
ThJobArtifactModel) {
ThJobDetailModel) {
$scope.getCountClass = function(resultStatus) {
return thResultStatusInfo(resultStatus).btnClass;
@ -200,14 +200,16 @@ treeherderApp.controller('ResultSetCtrl', [
if (singleJobSelected) {
ThJobModel.cancel($scope.repoName, job.id).then(function() {
// XXX: Remove this after 1134929 is resolved.
ThJobArtifactModel.get_list(
{name: "buildapi", "type": "json", job_id: job.id}).then(
function(artifactList) {
if (artifactList.length) {
var requestId = artifactList[0].blob.request_id;
return thBuildApi.cancelJob($scope.repoName, requestId);
}
});
ThJobDetailModel.getJobDetails({
title: "buildbot_request_id",
job_id: job.id
}).then(function(data) {
// non-buildbot jobs will have no request id, and that's ok (they
// are covered above)
if (data.length) {
return thBuildApi.cancelJob($scope.repoName, data[0].value);
}
});
}).catch(function(e) {
thNotify.send(
ThModelErrors.format(e, "Unable to cancel job"),

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

@ -255,7 +255,7 @@ logViewerApp.controller('LogviewerCtrl', [
$scope.logProperties.push({label: "Revision", value: revision});
});
ThJobDetailModel.getJobDetails(job.job_guid).then(function(jobDetails) {
ThJobDetailModel.getJobDetails({job_guid: job.job_guid}).then(function(jobDetails) {
$scope.job_details = jobDetails;
});
}, function () {

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

@ -3,12 +3,12 @@
treeherder.factory('ThJobDetailModel', [
'$http', 'thUrl', function($http, thUrl) {
return {
getJobDetails: function(jobGuid, config) {
getJobDetails: function(params, config) {
config = config || {};
var timeout = config.timeout || null;
return $http.get(thUrl.getRootUrl("/jobdetail/"), {
params: { job_guid: jobGuid },
params: params,
timeout: timeout
}).then(function(response) {
return response.data.results;

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

@ -328,7 +328,8 @@ treeherder.factory('ThResultSetStore', [
// This extra search is important to avoid confusion with Action Tasks
var decision_task = _.find(platform.groups[0].jobs, {"job_type_symbol": "D"});
var job_guid = decision_task.job_guid;
tcURLPromise = ThJobDetailModel.getJobDetails(job_guid, {timeout: null});
tcURLPromise = ThJobDetailModel.getJobDetails({job_guid: job_guid},
{timeout: null});
}
if (!tcURLPromise) {
// Here we are passing false to the results instead of skipping the promise

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

@ -130,12 +130,9 @@ treeherder.controller('PluginCtrl', [
$scope.repoName, job.id,
{timeout: selectJobPromise});
var buildapiArtifactPromise = ThJobArtifactModel.get_list(
{name: "buildapi", "type": "json", job_id: job.id},
{timeout: selectJobPromise});
var jobDetailPromise = ThJobDetailModel.getJobDetails(
job.job_guid, {timeout: selectJobPromise});
{job_guid: job.job_guid},
{timeout: selectJobPromise});
var jobLogUrlPromise = ThJobLogUrlModel.get_list(
job.id,
@ -146,7 +143,6 @@ treeherder.controller('PluginCtrl', [
return $q.all([
jobPromise,
buildapiArtifactPromise,
jobDetailPromise,
jobLogUrlPromise,
phSeriesPromise
@ -165,35 +161,32 @@ treeherder.controller('PluginCtrl', [
// set the tab options and selections based on the selected job
initializeTabs($scope.job);
// 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')){
// this is needed to cancel/retrigger jobs
$scope.artifacts.buildapi = buildapi_artifact[0];
}
// filtering values for data fields and signature
$scope.jobSearchStr = $scope.job.get_title();
$scope.jobSearchSignature = $scope.job.signature;
$scope.jobSearchStrHref = getJobSearchStrHref($scope.jobSearchStr);
$scope.jobSearchSignatureHref = getJobSearchStrHref($scope.job.signature);
// 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);
// the second result comes from the job detail promise
$scope.job_details = results[1];
// incorporate the buildername into the job details if this is a buildbot job
// (i.e. it has a buildbot request id)
var buildbotRequestIdDetail = _.find($scope.job_details,
{title: 'buildbot_request_id'});
if (buildbotRequestIdDetail) {
$scope.job_details = $scope.job_details.concat({
title: "Buildername",
value: $scope.job.ref_data_name
});
$scope.buildernameIndex = _.findIndex($scope.job_details, {title: "Buildername"});
$scope.job.buildbot_request_id = parseInt(buildbotRequestIdDetail.value);
}
// the fourth result comes from the jobLogUrl artifact
// the third result comes from the jobLogUrl artifact
// exclude the json log URLs
$scope.job_log_urls = _.reject(
results[3],
results[2],
function(log) {
return log.name.endsWith("_json");
});
@ -217,7 +210,7 @@ treeherder.controller('PluginCtrl', [
}
$scope.resultStatusShading = "result-status-shading-" + thResultStatus($scope.job);
var performanceData = results[4];
var performanceData = results[3];
if (performanceData) {
var seriesList = [];
$scope.perfJobDetail = [];
@ -326,16 +319,6 @@ treeherder.controller('PluginCtrl', [
($scope.job.state === "pending" || $scope.job.state === "running");
};
/**
* Get the build_id needed to cancel or retrigger from the currently
* selected job.
*/
var getBuildbotRequestId = function() {
if ($scope.artifacts.buildapi) {
return $scope.artifacts.buildapi.blob.request_id;
}
};
$scope.retriggerJob = function(jobs) {
if ($scope.user.loggedin) {
var job_id_list = _.pluck(jobs, 'id');
@ -346,14 +329,12 @@ treeherder.controller('PluginCtrl', [
// to the self serve api (which does not listen over pulse!).
ThJobModel.retrigger($scope.repoName, job_id_list).then(function() {
// XXX: Remove this after 1134929 is resolved.
return ThJobArtifactModel.get_list({"name": "buildapi",
"type": "json",
"count": job_id_list.length,
"job_id__in": job_id_list.join(',')})
return ThJobDetailModel.getJobDetails({"title": "buildbot_request_id",
"job_id__in": job_id_list.join(',')})
.then(function(data) {
var request_id_list = _.pluck(_.pluck(data, 'blob'), 'request_id');
_.each(request_id_list, function(request_id) {
thBuildApi.retriggerJob($scope.repoName, request_id);
var requestIdList = _.pluck(data, 'value');
requestIdList.forEach(function(requestId) {
thBuildApi.retriggerJob($scope.repoName, requestId);
});
});
}).then(function() {
@ -404,7 +385,7 @@ treeherder.controller('PluginCtrl', [
// See note in retrigger logic.
ThJobModel.cancel($scope.repoName, $scope.job.id).then(function() {
// XXX: Remove this after 1134929 is resolved.
var requestId = getBuildbotRequestId();
var requestId = $scope.job.buildbot_request_id;
if (requestId) {
return thBuildApi.cancelJob($scope.repoName, requestId);
}