Bug 1017834 - Add support for specifying a branch for dashboard testruns;r=davehunt

This commit is contained in:
William Lachance 2014-07-15 20:38:50 -04:00
Родитель e264a341f0
Коммит f64f3d4899
5 изменённых файлов: 152 добавлений и 68 удалений

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

@ -134,37 +134,40 @@ r = requests.get(baseurl + 'devices.json')
if not validate_json_response(r):
print "Can't download device list, exiting"
sys.exit(1)
devicedict = r.json()
save_file(os.path.join(outputdir, 'devices.json'), r.content)
if options.device_id:
if options.device_id in r.json()['devices'].keys():
device_names = [ options.device_id ]
deviceids = [ options.device_id ]
else:
print "WARNING: Device id '%s' specified but unavailable. Skipping." % \
options.device_id
device_names = []
deviceids = []
else:
device_names = r.json()['devices'].keys()
deviceids = devicedict['devices'].keys()
with concurrent.futures.ThreadPoolExecutor(MAX_WORKERS) as executor:
for device_name in device_names:
r = requests.get(baseurl + '%s/tests.json' % device_name)
if not validate_json_response(r):
print "Skipping tests for %s" % device_name
continue
for deviceid in deviceids:
for branchid in devicedict['devices'][deviceid]['branches']:
r = requests.get(baseurl + '%s/%s/tests.json' % (deviceid, branchid))
if not validate_json_response(r):
print "Skipping tests for device: %s, branch: %s" % (
deviceid, branchid)
continue
devicedir = os.path.join(outputdir, device_name)
create_dir(devicedir)
save_file(os.path.join(devicedir, 'tests.json'), r.content)
testnames = r.json()['tests'].keys()
for testname in testnames:
executor.submit(download_testdata,
baseurl + '%s/%s.json' % (device_name, testname),
baseurl,
os.path.join(outputdir, device_name,
'%s.json' % testname),
options,
metadatadir, videodir, profiledir)
testdir = os.path.join(outputdir, deviceid, branchid)
create_dir(testdir)
save_file(os.path.join(testdir, 'tests.json'), r.content)
testnames = r.json()['tests'].keys()
for testname in testnames:
executor.submit(download_testdata,
baseurl + '%s/%s/%s.json' % (deviceid, branchid, testname),
baseurl,
os.path.join(outputdir, deviceid, branchid,
'%s.json' % testname),
options,
metadatadir, videodir, profiledir)
sys.exit(exit_status)

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

@ -117,8 +117,10 @@ def runtest(dm, device_prefs, options, product, appinfo, testinfo,
log_actions=(testtype == 'web' or testtype == 'b2g')))
# Write testdata
eideticker.update_dashboard_testdata(options.dashboard_dir, options.device_id,
testinfo, productname, appdate,
eideticker.update_dashboard_testdata(options.dashboard_dir,
options.device_id,
options.branch_id, testinfo,
productname, appdate,
datapoint, metadata)
def main(args=sys.argv[1:]):
@ -132,6 +134,9 @@ def main(args=sys.argv[1:]):
parser.add_option("--device-id", action="store", dest="device_id",
help="id of device (used in output json)",
default=os.environ.get('DEVICE_ID'))
parser.add_option("--branch", action="store", dest="branch_id",
help="branch under test (used in output json)",
default=os.environ.get('BRANCH'))
parser.add_option("--device-name", action="store", dest="device_name",
help="name of device to display in dashboard (if not "
"specified, display model name)",
@ -155,17 +160,19 @@ def main(args=sys.argv[1:]):
default="nightly",
help="product name (android-specific, default: "
"%default)")
options, args = parser.parse_args()
if not args: # need to specify at least one test to run!
parser.print_usage()
sys.exit(1)
device_id = options.device_id
if not device_id:
print "ERROR: Must specify device id (either with --device-id or with "
"DEVICE_ID environment variable)"
if not options.device_id:
print "ERROR: Must specify device id (either with --device-id or with " \
"DEVICE_ID environment variable)"
sys.exit(1)
if not options.branch_id:
print "ERROR: Must specify branch (either with --branch or with " \
"BRANCH environment variable)"
sys.exit(1)
# get device info
@ -189,8 +196,8 @@ def main(args=sys.argv[1:]):
print "ERROR: Unknown device type '%s'" % options.devicetype
# update device index
eideticker.update_dashboard_device_list(options.dashboard_dir, device_id,
device_info)
eideticker.update_dashboard_device_list(options.dashboard_dir, options.device_id,
options.branch_id, device_info)
# get application/build info
if options.devicetype == "android":
@ -229,7 +236,8 @@ def main(args=sys.argv[1:]):
for testkey in args:
testinfo = eideticker.get_testinfo(testkey)
eideticker.update_dashboard_test_list(options.dashboard_dir, device_id,
eideticker.update_dashboard_test_list(options.dashboard_dir, options.device_id,
options.branch_id,
testinfo)
current_date = time.strftime("%Y-%m-%d")

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

@ -25,6 +25,9 @@
#device-chooser::before {
content: "Device";
}
#branch-chooser::before {
content: "Branch";
}
#test-chooser::before {
content: "Test";
}
@ -93,6 +96,7 @@
<div id="chooser">
<div class="list-group" id="device-chooser"></div>
<div class="list-group" id="branch-chooser"></div>
<div class="list-group" id="test-chooser"></div>
</div>

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

@ -8,8 +8,8 @@ function getResourceURL(path) {
return serverPrefix + path;
}
function updateContent(testInfo, deviceId, testId, measureId) {
$.getJSON(getResourceURL(deviceId + '/' + testId + '.json'), function(dict) {
function updateContent(testInfo, deviceId, branchId, testId, measureId) {
$.getJSON(getResourceURL([deviceId, branchId, testId].join('/') + '.json'), function(dict) {
if (!dict || !dict['testdata']) {
$('#data-view').html("<p><b>No data for that device/test combination. :(</b></p>");
return;
@ -43,7 +43,7 @@ function updateContent(testInfo, deviceId, testId, measureId) {
$('#measure-'+measureId).attr("selected", "true");
$('#measure').change(function() {
var newMeasureId = $(this).val();
window.location.hash = '/' + [ deviceId, testId, newMeasureId ].join('/');
window.location.hash = '/' + [ deviceId, branchId, testId, newMeasureId ].join('/');
});
});
@ -286,75 +286,135 @@ $(function() {
var devices = deviceData['devices'];
var deviceIds = Object.keys(devices).sort();
$.when.apply($, deviceIds.map(function(deviceId) {
return $.getJSON(getResourceURL([deviceId, 'tests.json'].join('/')),
var deviceBranchPairs = [];
deviceIds.forEach(function(deviceId) {
devices[deviceId].branches.forEach(function(branchId) {
deviceBranchPairs.push([deviceId, branchId]);
});
});
$.when.apply($, deviceBranchPairs.map(function(pair) {
var deviceId = pair[0];
var branchId = pair[1];
return $.getJSON(getResourceURL([deviceId, branchId, 'tests.json'].join('/')),
function(testData) {
var tests = testData['tests'];
devices[deviceId]['tests'] = tests;
if (!devices[deviceId][branchId]) {
devices[deviceId][branchId] = {};
}
devices[deviceId][branchId]['tests'] = tests;
});
})).done(function() {
var defaultDeviceId = deviceIds[0];
// initialize device chooser
deviceIds.forEach(function(deviceId) {
var tests = devices[deviceId].tests;
var firstTestKey = Object.keys(tests).sort()[0];
var defaultMeasureId = tests[firstTestKey].defaultMeasureId;
function getTestIdForDeviceAndBranch(deviceId, branchId, preferredTest) {
var device = devices[deviceId];
var tests = device[branchId].tests;
var testIds = Object.keys(tests).sort();
var testId;
if (preferredTest && testIds.indexOf(preferredTest) >= 0) {
// this deviceid/branch combo has our preferred test, return it
return preferredTest;
} else {
// this deviceid/branch combo *doesn't* have our preferred test,
// fall back to the first one
return testIds[0];
}
}
var deviceURL = "#/" + [ deviceId, firstTestKey, defaultMeasureId ].join('/');
$('<a href="' + deviceURL + '" id="device-' + deviceId + '" deviceid= ' + deviceId + ' class="list-group-item">' + devices[deviceId].name+'</a></li>').appendTo(
function updateDeviceChooser(preferredBranchId, preferredTest) {
$('#device-chooser').empty();
deviceIds.forEach(function(deviceId) {
var device = devices[deviceId];
var branchId;
if (preferredBranchId && device.branches.indexOf(preferredBranchId) >= 0) {
branchId = preferredBranchId;
} else {
branchId = device.branches.sort()[0];
}
var testId = getTestIdForDeviceAndBranch(deviceId, branchId, preferredTest);
var defaultMeasureId = device[branchId].tests[testId].defaultMeasureId;
var deviceURL = "#/" + [ deviceId, branchId, testId, defaultMeasureId ].join('/');
$('<a href="' + deviceURL + '" id="device-' + deviceId + '" deviceid= ' + deviceId + ' class="list-group-item">' + devices[deviceId].name+'</a></li>').appendTo(
$('#device-chooser'));
});
});
}
function updateBranchChooser(deviceId, preferredTest) {
$('#branch-chooser').empty();
var device = devices[deviceId];
device.branches.forEach(function(branchId) {
var testId = getTestIdForDeviceAndBranch(deviceId, branchId, preferredTest);
var defaultMeasureId = device[branchId].tests[testId].defaultMeasureId;
var url = "#/" + [ deviceId, branchId, testId, defaultMeasureId ].join('/');
$('<a href="' + url + '" id="branch-' + branchId + '" class="list-group-item">' + branchId +'</a></li>').appendTo(
$('#branch-chooser'));
});
}
var currentBranchId = null;
var currentDeviceId = null;
var currentTestId = null;
var routes = {
'/:deviceId/:testId/:measureId': {
on: function(deviceId, testId, measureId) {
if (!devices[deviceId] || !devices[deviceId]['tests'][testId]) {
$('#data-view').html("<p><b>That device/test/measure combination does not seem to exist. Maybe you're using an expired link? <a href=''>Reload page</a>?</b></p>");
'/:deviceId/:branchId/:testId/:measureId': {
on: function(deviceId, branchId, testId, measureId) {
if (!devices[deviceId] || !devices[deviceId][branchId] || !devices[deviceId][branchId]['tests'][testId]) {
$('#data-view').html("<p><b>That device/branch/test/measure combination does not seem to exist. Maybe you're using an expired link? <a href=''>Reload page</a>?</b></p>");
return;
}
// update device chooser
$('#device-chooser').children('a').removeClass("active");
$('#device-chooser').children('#device-'+deviceId).addClass("active");
updateDeviceChooser(branchId, testId);
updateBranchChooser(deviceId, testId);
// update list of tests to be consistent with those of this
// particular device (in case it changed)
$('#test-chooser').empty();
var tests = devices[deviceId].tests;
var tests = devices[deviceId][branchId].tests;
var testKeys = Object.keys(tests).sort();
testKeys.forEach(function(testKey) {
$('<a id="' + testKey + '" class="list-group-item">' + testKey + '</a>').appendTo($('#test-chooser'));
});
// update all test links to be relative to the new test or device
$('#test-chooser').children('a').removeClass("active");
$('#test-chooser').children('#'+testId).addClass("active");
$('#test-chooser').children('a').each(function() {
var testIdAttr = $(this).attr('id');
if (testIdAttr) {
var defaultMeasureId = tests[testIdAttr].defaultMeasureId;
$(this).attr('href', '#/' +
[ deviceId, testIdAttr,
[ deviceId, branchId, testIdAttr,
defaultMeasureId ].join('/'));
}
});
// highlight chosen selections in choosers
$('#device-chooser').children('#device-'+deviceId).addClass("active");
$('#branch-chooser').children('#branch-'+branchId.replace('.', '\\.')).addClass("active");
$('#test-chooser').children('#'+testId).addClass("active");
var testInfo = tests[testId];
updateFooter();
updateContent(testInfo, deviceId, testId, measureId);
updateContent(testInfo, deviceId, branchId, testId, measureId);
}
}
};
var defaultDeviceId = deviceIds[0];
var initialTestKey = Object.keys(devices[defaultDeviceId]['tests'])[0];
var initialTest = devices[defaultDeviceId]['tests'][initialTestKey]
var defaultBranchId = devices[defaultDeviceId].branches[0];
var defaultTestId = Object.keys(devices[defaultDeviceId][defaultBranchId].tests)[0];
var defaultMeasureId = devices[defaultDeviceId][defaultBranchId].tests[defaultTestId].defaultMeasureId;
var router = Router(routes).init('/' + [ defaultDeviceId,
initialTestKey,
initialTest.defaultMeasureId ].join('/'));
defaultBranchId,
defaultTestId,
defaultMeasureId ].join('/'));
});
});
});

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

@ -66,19 +66,27 @@ def copy_dashboard_files(dashboard_dir, indexfile='index.html'):
os.remove(dest)
shutil.copyfile(source, dest)
def update_dashboard_device_list(dashboard_dir, device_id, device_info):
def update_dashboard_device_list(dashboard_dir, device_id, branch_id, device_info):
devices = {}
device_filename = os.path.join(dashboard_dir, 'devices.json')
if os.path.isfile(device_filename):
devices = json.loads(open(device_filename).read())['devices']
branches = []
if devices.get(device_id):
branches = devices[device_id].get('branches', [])
if branch_id not in branches:
branches.append(branch_id)
devices[device_id] = device_info
devices[device_id]['branches'] = branches
with open(device_filename, 'w') as f:
f.write(json.dumps({'devices': devices}))
def update_dashboard_test_list(dashboard_dir, device_id, testinfo):
testsdirname = os.path.join(dashboard_dir, device_id)
def update_dashboard_test_list(dashboard_dir, device_id, branch_id, testinfo):
testsdirname = os.path.join(dashboard_dir, device_id, branch_id)
if not os.path.exists(testsdirname):
os.mkdir(testsdirname)
os.makedirs(testsdirname)
tests = {}
testsfilename = os.path.join(testsdirname, 'tests.json')
@ -91,10 +99,11 @@ def update_dashboard_test_list(dashboard_dir, device_id, testinfo):
with open(testsfilename, 'w') as f:
f.write(json.dumps({'tests': tests}))
def update_dashboard_testdata(dashboard_dir, device_id, testinfo, productname,
productdate, datapoint, metadata):
def update_dashboard_testdata(dashboard_dir, device_id, branch_id, testinfo,
productname, productdate, datapoint, metadata):
# get existing data
fname = os.path.join(dashboard_dir, device_id, '%s.json' % testinfo['key'])
fname = os.path.join(dashboard_dir, device_id, branch_id,
'%s.json' % testinfo['key'])
testdata = NestedDict()
if os.path.isfile(fname):
testdata.update(json.loads(open(fname).read()))