gecko-dev/tools/tryselect/selectors/chooser/app.py

182 строки
4.5 KiB
Python

# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from __future__ import absolute_import, print_function
from abc import ABCMeta, abstractproperty
from collections import defaultdict
from flask import (
Flask,
render_template,
request,
)
SECTIONS = []
SUPPORTED_KINDS = set()
def register_section(cls):
assert issubclass(cls, Section)
instance = cls()
SECTIONS.append(instance)
SUPPORTED_KINDS.update(instance.kind.split(','))
class Section(object):
__metaclass__ = ABCMeta
@abstractproperty
def name(self):
pass
@abstractproperty
def kind(self):
pass
@abstractproperty
def title(self):
pass
@abstractproperty
def attrs(self):
pass
def contains(self, task):
return task.kind in self.kind.split(',')
def get_context(self, tasks):
labels = defaultdict(lambda: {'max_chunk': 0, 'attrs': defaultdict(list)})
for task in tasks.values():
if not self.contains(task):
continue
task = task.attributes
label = labels[self.labelfn(task)]
for attr in self.attrs:
if attr in task and task[attr] not in label['attrs'][attr]:
label['attrs'][attr].append(task[attr])
if 'test_chunk' in task:
label['max_chunk'] = max(label['max_chunk'], int(task['test_chunk']))
return {
'name': self.name,
'kind': self.kind,
'title': self.title,
'labels': labels,
}
@register_section
class Platform(Section):
name = 'platform'
kind = 'build'
title = 'Platforms'
attrs = ['build_platform']
def labelfn(self, task):
return task['build_platform']
def contains(self, task):
if not Section.contains(self, task):
return False
# android-stuff tasks aren't actual platforms
return task.task['tags'].get('android-stuff', False) != "true"
@register_section
class Test(Section):
name = 'test'
kind = 'test'
title = 'Test Suites'
attrs = ['unittest_suite']
def labelfn(self, task):
suite = task['unittest_suite'].replace(' ', '-')
if suite.endswith('-chunked'):
suite = suite[:-len('-chunked')]
return suite
def contains(self, task):
if not Section.contains(self, task):
return False
return task.attributes['unittest_suite'] not in ('raptor', 'talos')
@register_section
class Perf(Section):
name = 'perf'
kind = 'test'
title = 'Performance'
attrs = ['unittest_suite', 'raptor_try_name', 'talos_try_name']
def labelfn(self, task):
suite = task['unittest_suite']
label = task['{}_try_name'.format(suite)]
if not label.startswith(suite):
label = '{}-{}'.format(suite, label)
if label.endswith('-e10s'):
label = label[:-len('-e10s')]
return label
def contains(self, task):
if not Section.contains(self, task):
return False
return task.attributes['unittest_suite'] in ('raptor', 'talos')
@register_section
class Analysis(Section):
name = 'analysis'
kind = 'build,static-analysis-autotest'
title = 'Analysis'
attrs = ['build_platform']
def labelfn(self, task):
return task['build_platform']
def contains(self, task):
if not Section.contains(self, task):
return False
if task.kind == 'build':
return task.task['tags'].get('android-stuff', False) == "true"
return True
def create_application(tg):
tasks = {l: t for l, t in tg.tasks.items() if t.kind in SUPPORTED_KINDS}
sections = [s.get_context(tasks) for s in SECTIONS]
context = {
'tasks': {l: t.attributes for l, t in tasks.items()},
'sections': sections,
}
app = Flask(__name__)
app.env = 'development'
app.tasks = []
@app.route('/', methods=['GET', 'POST'])
def chooser():
if request.method == 'GET':
return render_template('chooser.html', **context)
if request.form['action'] == 'Push':
labels = request.form['selected-tasks'].splitlines()
app.tasks.extend(labels)
shutdown = request.environ.get('werkzeug.server.shutdown')
if shutdown:
shutdown()
return render_template('close.html')
return app