mirror of
https://github.com/odoo/runbot.git
synced 2025-03-15 15:35:46 +07:00
[IMP] runbot: simplify views and adapt to odoo13
mainly fixes datetime and bootstrap layouts
This commit is contained in:
parent
9215a23cc1
commit
93b901dcdd
@ -6,7 +6,7 @@
|
||||
'author': "Odoo SA",
|
||||
'website': "http://runbot.odoo.com",
|
||||
'category': 'Website',
|
||||
'version': '4.6',
|
||||
'version': '4.8',
|
||||
'depends': ['website', 'base'],
|
||||
'data': [
|
||||
'security/runbot_security.xml',
|
||||
@ -33,5 +33,6 @@
|
||||
'data/build_parse.xml',
|
||||
'data/runbot_error_regex_data.xml',
|
||||
'data/error_link.xml',
|
||||
'data/website_data.xml',
|
||||
],
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ class RunbotBadge(Controller):
|
||||
|
||||
build = builds[0]
|
||||
etag = request.httprequest.headers.get('If-None-Match')
|
||||
retag = hashlib.md5(build[last_update].encode()).hexdigest()
|
||||
retag = hashlib.md5(str(build[last_update]).encode()).hexdigest()
|
||||
|
||||
if etag == retag:
|
||||
return werkzeug.wrappers.Response(status=304)
|
||||
|
@ -39,6 +39,7 @@ class Runbot(Controller):
|
||||
'host_stats': [],
|
||||
'pending_total': pending[0],
|
||||
'pending_level': pending[1],
|
||||
'hosts_data': request.env['runbot.host'].search([]),
|
||||
'search': search,
|
||||
'refresh': refresh,
|
||||
}
|
||||
@ -101,15 +102,11 @@ class Runbot(Controller):
|
||||
def branch_info(branch):
|
||||
return {
|
||||
'branch': branch,
|
||||
'fqdn': fqdn(),
|
||||
'builds': [build_dict[build_id] for build_id in build_by_branch_ids.get(branch.id) or []]
|
||||
}
|
||||
|
||||
context.update({
|
||||
'branches': [branch_info(b) for b in branches],
|
||||
'testing': build_obj.search_count([('repo_id', '=', repo.id), ('local_state', '=', 'testing')]),
|
||||
'running': build_obj.search_count([('repo_id', '=', repo.id), ('local_state', '=', 'running')]),
|
||||
'pending': build_obj.search_count([('repo_id', '=', repo.id), ('local_state', '=', 'pending')]),
|
||||
'qu': QueryURL('/runbot/repo/' + slug(repo), search=search, refresh=refresh),
|
||||
'fqdn': fqdn(),
|
||||
})
|
||||
@ -117,14 +114,6 @@ class Runbot(Controller):
|
||||
# consider host gone if no build in last 100
|
||||
build_threshold = max(build_ids or [0]) - 100
|
||||
|
||||
for result in build_obj.read_group([('id', '>', build_threshold)], ['host'], ['host']):
|
||||
if result['host']:
|
||||
context['host_stats'].append({
|
||||
'host': result['host'],
|
||||
'testing': build_obj.search_count([('local_state', '=', 'testing'), ('host', '=', result['host'])]),
|
||||
'running': build_obj.search_count([('local_state', '=', 'running'), ('host', '=', result['host'])]),
|
||||
})
|
||||
|
||||
context.update({'message': request.env['ir.config_parameter'].sudo().get_param('runbot.runbot_message')})
|
||||
return request.render('runbot.repo', context)
|
||||
|
||||
@ -302,12 +291,16 @@ class Runbot(Controller):
|
||||
return request.render("runbot.glances", qctx)
|
||||
|
||||
@route('/runbot/monitoring', type='http', auth='user', website=True)
|
||||
def monitoring(self, refresh=None):
|
||||
@route('/runbot/monitoring/<int:config_id>', type='http', auth='user', website=True)
|
||||
@route('/runbot/monitoring/<int:config_id>/<int:view_id>', type='http', auth='user', website=True)
|
||||
def monitoring(self, config_id=None, view_id=None, refresh=None):
|
||||
glances_ctx = self._glances_ctx()
|
||||
pending = self._pending()
|
||||
hosts_data = request.env['runbot.host'].search([])
|
||||
|
||||
monitored_config_id = int(request.env['ir.config_parameter'].sudo().get_param('runbot.monitored_config_id', 1))
|
||||
last_monitored = None
|
||||
if config_id or config_id is None:
|
||||
monitored_config_id = config_id or int(request.env['ir.config_parameter'].sudo().get_param('runbot.monitored_config_id', 1))
|
||||
request.env.cr.execute("""SELECT DISTINCT ON (branch_id) branch_id, id FROM runbot_build
|
||||
WHERE config_id = %s
|
||||
AND global_state in ('running', 'done')
|
||||
@ -316,7 +309,9 @@ class Runbot(Controller):
|
||||
ORDER BY branch_id ASC, id DESC""", [int(monitored_config_id)])
|
||||
last_monitored = request.env['runbot.build'].browse([r[1] for r in request.env.cr.fetchall()])
|
||||
|
||||
config = request.env['runbot.build.config'].browse(monitored_config_id)
|
||||
qctx = {
|
||||
'config': config,
|
||||
'refresh': refresh,
|
||||
'pending_total': pending[0],
|
||||
'pending_level': pending[1],
|
||||
@ -326,7 +321,7 @@ class Runbot(Controller):
|
||||
'auto_tags': request.env['runbot.build.error'].disabling_tags(),
|
||||
'build_errors': request.env['runbot.build.error'].search([('random', '=', True)])
|
||||
}
|
||||
return request.render("runbot.monitoring", qctx)
|
||||
return request.render(request.env['ir.ui.view'].browse('view_id') if view_id else config.monitoring_view_id.id or "runbot.monitoring", qctx)
|
||||
|
||||
@route(['/runbot/branch/<int:branch_id>', '/runbot/branch/<int:branch_id>/page/<int:page>'], website=True, auth='public', type='http')
|
||||
def branch_builds(self, branch_id=None, search='', page=1, limit=50, refresh='', **kwargs):
|
||||
@ -337,9 +332,9 @@ class Runbot(Controller):
|
||||
url='/runbot/branch/%s' % branch_id,
|
||||
total=builds_count,
|
||||
page=page,
|
||||
step=50
|
||||
step=50,
|
||||
)
|
||||
builds = request.env['runbot.build'].search(domain, limit=limit, offset=pager.get('offset',0))
|
||||
|
||||
context = {'pager': pager, 'builds': builds}
|
||||
context = {'pager': pager, 'builds': builds, 'repo': request.env['runbot.branch'].browse(branch_id).repo_id}
|
||||
return request.render("runbot.branch", context)
|
||||
|
5
runbot/data/website_data.xml
Normal file
5
runbot/data/website_data.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<odoo>
|
||||
<record id="website.homepage_page" model="website.page">
|
||||
<field name="url">/home</field>
|
||||
</record>
|
||||
</odoo>
|
@ -365,6 +365,8 @@ class runbot_build(models.Model):
|
||||
build.job_time = int(dt2time(build.job_end) - dt2time(build.job_start))
|
||||
elif build.job_start:
|
||||
build.job_time = int(time.time() - dt2time(build.job_start))
|
||||
else:
|
||||
build.job_time = 0
|
||||
|
||||
@api.depends('build_start', 'build_end', 'duplicate_id.build_time')
|
||||
def _compute_build_time(self):
|
||||
@ -375,6 +377,8 @@ class runbot_build(models.Model):
|
||||
build.build_time = int(dt2time(build.build_end) - dt2time(build.build_start))
|
||||
elif build.build_start:
|
||||
build.build_time = int(time.time() - dt2time(build.build_start))
|
||||
else:
|
||||
build.build_time = 0
|
||||
|
||||
@api.depends('job_start', 'duplicate_id.build_age')
|
||||
def _compute_build_age(self):
|
||||
@ -384,6 +388,8 @@ class runbot_build(models.Model):
|
||||
build.build_age = build.duplicate_id.build_age
|
||||
elif build.job_start:
|
||||
build.build_age = int(time.time() - dt2time(build.build_start))
|
||||
else:
|
||||
build.build_age = 0
|
||||
|
||||
def _get_params(self):
|
||||
try:
|
||||
|
@ -31,6 +31,7 @@ class Config(models.Model):
|
||||
protected = fields.Boolean('Protected', default=False, track_visibility='onchange')
|
||||
group = fields.Many2one('runbot.build.config', 'Configuration group', help="Group of config's and config steps")
|
||||
group_name = fields.Char('Group name', related='group.name')
|
||||
monitoring_view_id = fields.Many2one('ir.ui.view', 'Monitoring view')
|
||||
|
||||
@api.model_create_single
|
||||
def create(self, values):
|
||||
|
@ -163,7 +163,7 @@ class RunbotBuildError(models.Model):
|
||||
def test_tags_list(self):
|
||||
active_errors = self.search([('test_tags', '!=', 'False'), ('random', '=', True)])
|
||||
test_tag_list = active_errors.mapped('test_tags')
|
||||
return [test_tag for error_tags in test_tag_list for test_tag in error_tags.split(',')]
|
||||
return [test_tag for error_tags in test_tag_list for test_tag in (error_tags or '').split(',')]
|
||||
|
||||
@api.model
|
||||
def disabling_tags(self):
|
||||
|
@ -58,10 +58,15 @@ class RunboHost(models.Model):
|
||||
return int(icp.get_param('runbot.runbot_running_max', default=75))
|
||||
|
||||
def set_psql_conn_count(self):
|
||||
|
||||
_logger.debug('Updating psql connection count...')
|
||||
self.ensure_one()
|
||||
with local_pgadmin_cursor() as local_cr:
|
||||
local_cr.execute("SELECT sum(numbackends) FROM pg_stat_database;")
|
||||
res = local_cr.fetchone()
|
||||
self.psql_conn_count = res and res[0] or 0
|
||||
|
||||
def _total_testing(self):
|
||||
return sum(host.nb_testing for host in self)
|
||||
|
||||
def _total_workers(self):
|
||||
return sum(host.get_nb_worker() for host in self)
|
||||
|
80
runbot/static/src/css/runbot.css
Normal file
80
runbot/static/src/css/runbot.css
Normal file
@ -0,0 +1,80 @@
|
||||
.separator {
|
||||
border-top: 2px solid #666;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
[data-toggle="collapse"] .fa:before {
|
||||
content: "\f139";
|
||||
}
|
||||
|
||||
[data-toggle="collapse"].collapsed .fa:before {
|
||||
content: "\f13a";
|
||||
}
|
||||
|
||||
body, .table{
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
color:#444;
|
||||
}
|
||||
|
||||
.btn-default {
|
||||
background-color: #fff;
|
||||
color: #444;
|
||||
border-color: #ccc;
|
||||
}
|
||||
|
||||
.btn-default:hover {
|
||||
background-color: #ccc;
|
||||
color: #444;
|
||||
border-color: #ccc;
|
||||
}
|
||||
|
||||
.btn-sm, .btn-group-sm > .btn {
|
||||
padding: 0.25rem 0.5rem;
|
||||
font-size: 0.89rem;
|
||||
line-height: 1.5;
|
||||
border-radius: 0.2rem;
|
||||
}
|
||||
.btn-ssm, .btn-group-ssm > .btn {
|
||||
padding: 0.22rem 0.4rem;
|
||||
font-size: 0.82rem;
|
||||
line-height: 1;
|
||||
border-radius: 0.2rem;
|
||||
}
|
||||
|
||||
.killed, .bg-killed, .bg-killed-light {
|
||||
background-color: #aaa;
|
||||
}
|
||||
|
||||
.dropdown-toggle:after { content: none }
|
||||
|
||||
.branch_name {
|
||||
max-width: 250px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.branch_time {
|
||||
float:right;
|
||||
margin-left:10px;
|
||||
}
|
||||
|
||||
.bg-success-light {
|
||||
background-color: #dff0d8;
|
||||
}
|
||||
.bg-danger-light {
|
||||
background-color: #f2dede;
|
||||
}
|
||||
.bg-info-light {
|
||||
background-color: #d9edf7;
|
||||
}
|
||||
|
||||
.text-info{
|
||||
color: #096b72 !important;
|
||||
}
|
||||
.build_subject_buttons {
|
||||
display: flex;
|
||||
}
|
||||
.build_buttons {
|
||||
margin-left: auto
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
.separator {
|
||||
border-top: 2px solid #666;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
[data-toggle="collapse"] .fa:before {
|
||||
content: "\f139";
|
||||
}
|
||||
|
||||
[data-toggle="collapse"].collapsed .fa:before {
|
||||
content: "\f13a";
|
||||
}
|
@ -33,7 +33,7 @@
|
||||
<t t-if="build.global_result == 'skipped'"><t t-set="rowclass">default</t></t>
|
||||
<t t-if="build.global_result in ['killed', 'manually_killed']"><t t-set="rowclass">killed</t></t>
|
||||
</t>
|
||||
<tr t-attf-class="{{rowclass}}">
|
||||
<tr t-attf-class="bg-{{rowclass}}-light">
|
||||
<td><t t-esc="build.create_date" /></td>
|
||||
<td><a t-attf-href="/runbot/build/{{build['id']}}" title="Build details" aria-label="Build details"><t t-esc="build.dest" /></a></td>
|
||||
<td>
|
||||
|
@ -40,13 +40,6 @@
|
||||
</t>
|
||||
</small>
|
||||
</t>
|
||||
<t t-set="nb_sum" t-value="bu.nb_pending+bu.nb_testing+bu.nb_running"/>
|
||||
<t t-if="nb_sum > 1"><!-- maybe only display this info if > 3 -->
|
||||
<span t-attf-title="{{bu.nb_pending}} pending, {{bu.nb_testing}} testing, {{bu.nb_running}} running">
|
||||
<t t-esc="nb_sum"/>
|
||||
<i class="fa fa-cogs"/>
|
||||
</span>
|
||||
</t>
|
||||
</template>
|
||||
<template id="runbot.build_button">
|
||||
<div t-attf-class="pull-right">
|
||||
@ -54,9 +47,9 @@
|
||||
<a t-if="bu.real_build.local_state=='running'" t-attf-href="http://{{bu['domain']}}/?db={{bu.real_build.dest}}-all" class="btn btn-primary" title="Sign in on this build" aria-label="Sign in on this build"><i class="fa fa-sign-in"/></a>
|
||||
<a t-if="bu.real_build.local_state=='done' and bu.real_build.requested_action != 'wake_up'" href="#" t-att-data-runbot-build="bu.real_build.id" class="btn btn-default runbot-wakeup" title="Wake up this build" aria-label="Wake up this build"><i class="fa fa-coffee"/></a>
|
||||
<a t-attf-href="/runbot/build/{{bu['id']}}" class="btn btn-default" title="Build details" aria-label="Build details"><i class="fa fa-file-text-o"/></a>
|
||||
<a t-attf-href="https://#{repo.base}/commit/#{bu['name']}" class="btn btn-default" title="Open commit on GitHub" aria-label="Open commit on GitHub"><i class="fa fa-github"/></a>
|
||||
<a t-if="show_commit_button" t-attf-href="https://#{repo.base}/commit/#{bu['name']}" class="btn btn-default" title="Open commit on GitHub" aria-label="Open commit on GitHub"><i class="fa fa-github"/></a>
|
||||
<button class="btn btn-default dropdown-toggle" data-toggle="dropdown" title="Build options" aria-label="Build options" aria-expanded="false"><i class="fa fa-cog"/><span class="caret"></span></button>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<ul class="dropdown-menu dropdown-menu-right" role="menu">
|
||||
<li t-if="bu.global_result=='skipped'" groups="runbot.group_runbot_admin">
|
||||
<a href="#" class="runbot-rebuild" t-att-data-runbot-build="bu['id']">Force Build <i class="fa fa-level-up"></i></a>
|
||||
</li>
|
||||
@ -89,12 +82,12 @@
|
||||
<li t-if="bu.global_state not in ('testing', 'waiting', 'pending')" class="divider"></li>
|
||||
<li><a t-attf-href="/runbot/build/{{bu['id']}}">Logs <i class="fa fa-file-text-o"/></a></li>
|
||||
<t t-set="log_url" t-value="'http://%s' % bu.real_build.host if bu.real_build.host != fqdn else ''"/>
|
||||
<t t-if="bu.real_build.host" t-foreach="bu.log_list.split(',')" t-as="log_name" >
|
||||
<t t-if="bu.real_build.host" t-foreach="(bu.log_list or '').split(',')" t-as="log_name" >
|
||||
<li><a t-attf-href="{{log_url}}/runbot/static/build/#{bu['real_build'].dest}/logs/#{log_name}.txt">Full <t t-esc="log_name"/> logs <i class="fa fa-file-text-o"/></a></li>
|
||||
</t>
|
||||
<li t-if="bu.coverage and bu.real_build.host"><a t-attf-href="http://{{bu.real_build.host}}/runbot/static/build/#{bu['real_build'].dest}/coverage/index.html">Coverage <i class="fa fa-file-text-o"/></a></li>
|
||||
<li t-if="bu.global_state!='pending'" class="divider"></li>
|
||||
<li><a t-attf-href="{{br['branch'].branch_url}}">Branch or pull <i class="fa fa-github"/></a></li>
|
||||
<li><a t-attf-href="{{br['branch'].branch_url}}"><t t-esc="'Branch ' if not br['branch'].pull_head_name else 'Pull '"/><i class="fa fa-github"/></a></li>
|
||||
<li><a t-attf-href="https://{{repo.base}}/commit/{{bu['name']}}">Commit <i class="fa fa-github"/></a></li>
|
||||
<li><a t-attf-href="https://{{repo.base}}/compare/{{br['branch'].branch_name}}">Compare <i class="fa fa-github"/></a></li>
|
||||
<!-- TODO branch.pull from -->
|
||||
@ -118,49 +111,27 @@
|
||||
</template>
|
||||
<template id="runbot.build">
|
||||
<t t-call='website.layout'>
|
||||
<div class="container" style="width: 100%;">
|
||||
<div class="row" >
|
||||
<div class='col-md-12'>
|
||||
<nav class="navbar navbar-default" role="navigation">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" t-attf-href="/runbot/repo/#{ slug(repo) }"><b><t t-esc="repo.base"/></b></a>
|
||||
<a class="navbar-brand" t-attf-href="/runbot/build/{{build['id']}}">
|
||||
<t t-esc="build['dest']"/>
|
||||
<t t-call="runbot.build_name">
|
||||
<t t-set="bu" t-value="build"/>
|
||||
</t>
|
||||
</a>
|
||||
</div>
|
||||
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
|
||||
<form class="navbar-form navbar-left form-inline">
|
||||
|
||||
<t t-set="nav_form">
|
||||
<form class="form-inline">
|
||||
<div class="btn-group">
|
||||
<t t-call="runbot.build_button">
|
||||
<t t-set="bu" t-value="build"/>
|
||||
<t t-set="klass" t-value="''"/>
|
||||
<t t-set="show_commit_button" t-value="True"/>
|
||||
</t>
|
||||
</div>
|
||||
</form>
|
||||
<p class="navbar-text">
|
||||
</p>
|
||||
|
||||
<form class="navbar-form navbar-left form-inline" t-attf-action="/runbot/build/#{build['id']}/force" method='POST' t-if="request.params.get('ask_rebuild')" groups="runbot.group_user">
|
||||
<form class="form-inline" t-attf-action="/runbot/build/#{build['id']}/force" method='POST' t-if="request.params.get('ask_rebuild')" groups="runbot.group_user">
|
||||
<a href='#' class="btn btn-danger runbot-rebuild" t-attf-data-runbot-build="#{build['id']}" > <i class='fa fa-refresh'/> Force Rebuild</a>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
</t>
|
||||
<div class="row" >
|
||||
<div class='col-md-12'>
|
||||
<table class="table table-condensed tabel-bordered">
|
||||
<tr>
|
||||
<t t-set="rowclass"><t t-call="runbot.build_class"><t t-set="build" t-value="build"/></t></t>
|
||||
<td t-attf-class="{{rowclass}}">
|
||||
<td t-attf-class="bg-{{rowclass.strip()}}-light">
|
||||
Subject: <t t-esc="build['subject']"/><br/>
|
||||
Author: <t t-esc="build['author']"/><br/>
|
||||
Committer: <t t-esc="build['committer']"/><br/>
|
||||
@ -173,6 +144,7 @@
|
||||
Branch: <span id="branchclp"><t t-esc="build.branch_id.branch_name"/></span>
|
||||
<a href="#" class="clipbtn octicon octicon-clippy" data-clipboard-target="#branchclp" title="Copy branch name to clipboard"/><br/>
|
||||
Build host: <t t-esc="build.real_build.host"/><br/>
|
||||
Build dest: <t t-esc="build['dest']"/><br/>
|
||||
</td>
|
||||
<td t-if="build.real_build.children_ids">
|
||||
Children:
|
||||
@ -182,17 +154,20 @@
|
||||
<table class="table table-condensed">
|
||||
<t t-foreach="build.real_build.children_ids.sorted('id')" t-as="child">
|
||||
<t t-set="rowclass"><t t-call="runbot.build_class"><t t-set="build" t-value="child"/></t></t>
|
||||
<tr><td t-attf-class="{{rowclass}}">
|
||||
<tr><td t-attf-class="bg-{{rowclass.strip()}}-light">
|
||||
<a t-attf-href="/runbot/build/{{child.id}}" >Build <t t-esc="child.id"/></a>
|
||||
with config <a t-attf-href="/web#id={{child.config_id.id}}&view_type=form&model=runbot.build.config"><t t-esc="child.config_id.name"/></a>
|
||||
with config <t t-esc="child.config_id.name"/>
|
||||
<a groups="runbot.group_build_config_user" t-attf-href="/web#id={{child.config_id.id}}&view_type=form&model=runbot.build.config">...</a>
|
||||
<t t-if="child.orphan_result"><i class="fa fa-chain-broken" title="Build result ignored for parent" /></t>
|
||||
<t t-if="child.job"> Running step: <t t-esc="child.job"/></t>
|
||||
<t t-if="child.global_state in ['testing', 'waiting']">
|
||||
<i class="fa fa-spinner fa-spin"/>
|
||||
<t t-esc="child.global_state"/>
|
||||
</t>
|
||||
<a t-if="child.real_build.local_state=='running'" t-attf-href="http://{{child.domain}}/?db={{child.real_build.dest}}-all" title="Sign in on this build" aria-label="Sign in on this build"><i class="fa fa-sign-in"/></a>
|
||||
<a t-if="child.real_build.local_state=='done' and child.real_build.requested_action != 'wake_up'" href="#" t-att-data-runbot-build="child.real_build.id" class="runbot-wakeup" title="Wake up this build" aria-label="Wake up this build"><i class="fa fa-coffee"/></a>
|
||||
<t t-call="runbot.build_button">
|
||||
<t t-set="bu" t-value="child"/>
|
||||
<t t-set="klass" t-value="'btn-group-ssm'"/>
|
||||
</t>
|
||||
|
||||
</td></tr>
|
||||
</t>
|
||||
@ -203,7 +178,7 @@
|
||||
<p t-if="build.parent_id">Child of <a t-attf-href="/runbot/build/#{build.parent_id.id}"><t t-esc="build.parent_id.dest"/></a>
|
||||
<t t-if="build.orphan_result">&nbsp;<i class="fa fa-chain-broken" title="Build result ignored for parent" />&nbsp;Orphaned build, the result does not affect parent build result</t></p>
|
||||
<p t-if="build.duplicate_id">Duplicate of <a t-attf-href="/runbot/build/#{build.duplicate_id.id}"><t t-esc="build.duplicate_id.dest"/></a></p>
|
||||
<table class="table table-condensed table-striped">
|
||||
<table class="table table-condensed">
|
||||
<tr>
|
||||
<th>Date</th>
|
||||
<th>Level</th>
|
||||
@ -213,13 +188,13 @@
|
||||
<t t-foreach="build.real_build.sudo().log_ids" t-as="l">
|
||||
<t t-set="subbuild" t-value="(([child for child in build.real_build.children_ids if child.id == int(l.path)] if l.type == 'subbuild' else False) or [build.browse()])[0]"/>
|
||||
<t t-set="logclass" t-value="dict(CRITICAL='danger', ERROR='danger', WARNING='warning', OK='success', SEPARATOR='separator').get(l.level)"/>
|
||||
<tr t-att-class="logclass">
|
||||
<tr t-attf-class="bg-{{logclass}}-light">
|
||||
<td style="white-space: nowrap; width:1%;"><t t-esc="l.create_date"/></td>
|
||||
<td style="white-space: nowrap; width:1%;"><b t-if="l.level != 'SEPARATOR' and l.type != 'link'" t-esc="l.level"/></td>
|
||||
<td style="white-space: nowrap; width:1%;"><t t-if="l.level != 'SEPARATOR' and l.type != 'link'" t-esc="l.type"/></td>
|
||||
<t t-set="message_class" t-value="''"/>
|
||||
<t t-set="message_class" t-value="logclass"/>
|
||||
<t t-if="subbuild" t-set="message_class"><t t-call="runbot.build_class"><t t-set="build" t-value="subbuild"/></t></t>
|
||||
<td t-att-class="message_class">
|
||||
<td t-attf-class="bg-{{message_class.strip()}}-light">
|
||||
<t t-if="l.type not in ('runbot', 'link')">
|
||||
<t t-if="l.type == 'subbuild'">
|
||||
<a t-attf-href="/runbot/build/{{l.path}}">Build #<t t-esc="l.path"/></a>
|
||||
@ -241,7 +216,7 @@
|
||||
<t t-if="l.type == 'subbuild' and subbuild.sudo().error_log_ids">
|
||||
<a data-toggle="collapse" t-attf-data-target="#subbuild-{{subbuild.id}}"><i class="fa"></i></a>
|
||||
<div t-attf-id="subbuild-{{subbuild.id}}" class="collapse in">
|
||||
<table class="table table-condensed table-striped" style="margin-bottom:0;">
|
||||
<table class="table table-condensed" style="margin-bottom:0;">
|
||||
<t t-foreach="subbuild.sudo().error_log_ids" t-as="sl">
|
||||
<tr>
|
||||
<td t-att-class="dict(CRITICAL='danger', ERROR='danger', WARNING='warning', OK='success', SEPARATOR='separator').get(sl.level)">
|
||||
@ -263,7 +238,6 @@
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</template>
|
||||
</data>
|
||||
|
@ -141,21 +141,7 @@
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div>
|
||||
<span t-attf-class="label label-{{pending_level}}">Pending: <t t-esc="pending_total"/></span>
|
||||
<t t-set="testing">0</t>
|
||||
<t t-set="workers">0</t>
|
||||
|
||||
<t t-foreach="hosts_data.sorted(key=lambda h:h.name)" t-as="host">
|
||||
<t t-set="testing" t-value="int(testing) + host.nb_testing"/>
|
||||
<t t-set="workers" t-value="int(workers) + host.sudo().get_nb_worker()"/>
|
||||
</t>
|
||||
<t t-set="klass">success</t>
|
||||
|
||||
<t t-if="int(testing)/workers > 0"><t t-set="klass">info</t></t>
|
||||
<t t-if="int(testing)/workers > 0.75"><t t-set="klass">warning</t></t>
|
||||
<t t-if="int(testing)/workers >= 1"><t t-set="klass">danger</t></t>
|
||||
|
||||
<span t-attf-class="label label-{{klass}}">Testing: <t t-esc="testing"/>/<t t-esc="workers"/></span>
|
||||
<t t-call="slots_infos"/>
|
||||
</div>
|
||||
<t t-foreach="glances_data.keys()" t-as="repo">
|
||||
<div>
|
||||
@ -178,9 +164,9 @@
|
||||
<t t-if="host.nb_testing > host.sudo().get_nb_worker()"><t t-set="klass">danger</t></t>
|
||||
<span t-attf-class="label label-{{klass}}"><span t-esc="host.nb_testing"/>/<span t-esc="host.sudo().get_nb_worker()"/></span>
|
||||
<t t-esc="host.nb_running"/>
|
||||
<t t-set="succes_time" t-value="int(datetime.datetime.now().timestamp() - datetime.datetime.strptime(host.last_success, '%Y-%m-%d %H:%M:%S').timestamp())"/>
|
||||
<t t-set="start_time" t-value="int(datetime.datetime.now().timestamp() - datetime.datetime.strptime(host.last_start_loop, '%Y-%m-%d %H:%M:%S').timestamp())"/>
|
||||
<t t-set="end_time" t-value="int(datetime.datetime.now().timestamp() - datetime.datetime.strptime(host.last_end_loop, '%Y-%m-%d %H:%M:%S').timestamp())"/>
|
||||
<t t-set="succes_time" t-value="int(datetime.datetime.now().timestamp() - host.last_success.timestamp())"/>
|
||||
<t t-set="start_time" t-value="int(datetime.datetime.now().timestamp() - host.last_start_loop.timestamp())"/>
|
||||
<t t-set="end_time" t-value="int(datetime.datetime.now().timestamp() - host.last_end_loop.timestamp())"/>
|
||||
|
||||
<t t-set="klass">success</t>
|
||||
<t t-if="succes_time > 30"><t t-set="klass">info</t></t>
|
||||
|
@ -2,13 +2,48 @@
|
||||
<odoo>
|
||||
<data>
|
||||
<!-- Replace default menu ( Home / Contactus and co...) with 5 first repos) -->
|
||||
<template id="inherits_branch_in_menu" inherit_id="website.layout" name="Inherits Show top 5 branches in menu">
|
||||
<xpath expr="//t[@t-foreach="website.menu_id.child_id"][@t-as="submenu"]" position="replace">
|
||||
<template id="inherits_branch_in_menu" inherit_id="website.layout" name="Inherits Show top 6 repo in menu and dropdown">
|
||||
<xpath expr="//footer" position="replace">
|
||||
</xpath>
|
||||
<xpath expr="//nav" position="replace">
|
||||
<nav class="navbar navbar-expand-md navbar-light bg-light">
|
||||
<a t-if="repo" t-attf-href="/runbot/repo/{{slug(repo)}}?search={{request.params.get('search', '')}}">
|
||||
<b style="color:#777;"><t t-esc="repo.short_name"/></b>
|
||||
</a>
|
||||
<button type="button" class="navbar-toggler" data-toggle="collapse" data-target="#top_menu_collapse">
|
||||
<span class="navbar-toggler-icon"/>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="top_menu_collapse">
|
||||
<ul class="nav navbar-nav ml-auto text-right" id="top_menu">
|
||||
<t t-if="repos" >
|
||||
<t t-foreach="repos[:5]" t-as="re">
|
||||
<li><a t-attf-href="/runbot/repo/{{slug(re)}}?search={{request.params.get('search', '')}}"><i class='fa fa-github' /> <t t-esc="re.short_name"/></a></li>
|
||||
<t t-foreach="repos[:6]" t-as="re">
|
||||
<li ><a t-attf-href="/runbot/repo/{{slug(re)}}?search={{request.params.get('search', '')}}"><i class='fa fa-github' /> <t t-esc="re.short_name"/></a></li>
|
||||
</t>
|
||||
<li t-if="len(repos)>6" class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" aria-expanded="false"><i class="fa fa-plus"/></a>
|
||||
<ul class="dropdown-menu">
|
||||
<t t-foreach='repos[6:]' t-as='re'>
|
||||
<li><a t-attf-href="/runbot/repo/{{slug(re)}}"><t t-esc="re.short_name"/></a></li>
|
||||
</t>
|
||||
</ul>
|
||||
</li>
|
||||
</t>
|
||||
<li class="nav-item divider" t-ignore="true" t-if="not user_id._is_public()"/>
|
||||
<li class="nav-item dropdown" t-ignore="true" t-if="not user_id._is_public()">
|
||||
<a href="#" class="nav-link dropdown-toggle" data-toggle="dropdown">
|
||||
<b>
|
||||
<span t-esc="user_id.name[:23] + '...' if user_id.name and len(user_id.name) > 25 else user_id.name"/>
|
||||
</b>
|
||||
</a>
|
||||
<div class="dropdown-menu js_usermenu" role="menu">
|
||||
<a id="o_logout" class="dropdown-item" t-attf-href="/web/session/logout?redirect=/" role="menuitem">Logout</a>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<t t-raw="nav_form or ''">
|
||||
</t>
|
||||
</div>
|
||||
</nav>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
@ -21,6 +56,18 @@
|
||||
<attribute name="t-value">'o_connected_user' if env['ir.ui.view'].user_has_groups('base.group_website_publisher') else None</attribute>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="runbot.slots_infos" name="Hosts slot nb pending/testing/slots">
|
||||
<span t-attf-class="label label-{{pending_level}}">Pending: <t t-esc="pending_total"/></span>
|
||||
<t t-set="testing" t-value="hosts_data._total_testing()"/>
|
||||
<t t-set="workers" t-value="hosts_data._total_workers()"/>
|
||||
<t t-set="klass">success</t>
|
||||
<t t-if="int(testing)/workers > 0"><t t-set="klass">info</t></t>
|
||||
<t t-if="int(testing)/workers > 0.75"><t t-set="klass">warning</t></t>
|
||||
<t t-if="int(testing)/workers >= 1"><t t-set="klass">danger</t></t>
|
||||
<span t-attf-class="label label-{{klass}}">Testing: <t t-esc="testing"/>/<t t-esc="workers"/></span>
|
||||
</template>
|
||||
|
||||
<!-- Frontend repository block -->
|
||||
<template id="runbot.repo">
|
||||
<t t-call='website.layout'>
|
||||
@ -28,58 +75,20 @@
|
||||
<t t-if="refresh">
|
||||
<meta http-equiv="refresh" t-att-content="refresh"/>
|
||||
</t>
|
||||
<style>
|
||||
.killed {
|
||||
background-color: #aaa;
|
||||
}
|
||||
</style>
|
||||
</t>
|
||||
<t t-set="nav_form">
|
||||
<form class="form-inline my-2 my-lg-0" role="search" t-att-action="qu(search='')" method="get">
|
||||
<div class="input-group md-form form-sm form-2 pl-0">
|
||||
<input class="form-control my-0 py-1 red-border" type="text" placeholder="Search" aria-label="Search" name="search" t-att-value="search"/>
|
||||
<div class="input-group-append">
|
||||
<button type='submit' class="input-group-text red lighten-3" id="basic-text1"><i class="fa fa-search text-grey"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</t>
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class='col-md-12'>
|
||||
<nav class="navbar navbar-default" role="navigation">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<t t-if="repo">
|
||||
<ul class="nav navbar-nav">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" aria-expanded="false"><b style="font-size: 18px;"><t t-esc="repo.base"/></b><b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
<t t-foreach='repos' t-as='re'>
|
||||
<li><a t-attf-href="/runbot/repo/{{slug(re)}}"><t t-esc="re.base"/></a></li>
|
||||
</t>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</t>
|
||||
</div>
|
||||
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
|
||||
<t t-if="repo">
|
||||
<form class="navbar-form navbar-right" role="search" t-att-action="qu(search='')" method="get">
|
||||
<div class="form-group">
|
||||
<input type="search" name="search" class="form-control" placeholder="Search" t-att-value="search"/>
|
||||
<button type="submit" class="btn btn-default">Search</button>
|
||||
</div>
|
||||
</form>
|
||||
</t>
|
||||
</div>
|
||||
<p class="text-center">
|
||||
<t t-foreach="host_stats" t-as="hs">
|
||||
<span class="label label-default">
|
||||
<t t-esc="hs['host']"/>: <t t-esc="hs['testing']"/> testing
|
||||
</span>&nbsp;
|
||||
</t>
|
||||
<span t-attf-class="label label-{{pending_level}}">Pending: <t t-esc="pending_total"/></span>
|
||||
</p>
|
||||
</div>
|
||||
</nav>
|
||||
<div t-if="message" class="alert alert-warning" role="alert">
|
||||
<t t-esc="message" />
|
||||
</div>
|
||||
@ -90,21 +99,16 @@
|
||||
<table t-if="repo" class="table table-condensed table-bordered" style="table-layout: initial;">
|
||||
<tr>
|
||||
<th>Branch</th>
|
||||
<td colspan="4" class="text-right">
|
||||
<t t-esc="repo.base"/>:
|
||||
<t t-esc="testing"/> testing,
|
||||
<t t-esc="running"/> running,
|
||||
<t t-esc="pending"/> pending.
|
||||
<td colspan="4">
|
||||
<span class="pull-right" t-call="runbot.slots_infos"/>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
<tr t-foreach="branches" t-as="br">
|
||||
<td>
|
||||
<i t-if="br['branch'].sticky" class="fa fa-star" style="color: #f0ad4e" />
|
||||
<a t-attf-href="/runbot/branch/#{br['branch'].id}"><b t-esc="br['branch'].branch_name"/></a>
|
||||
<small><t t-esc="br['builds'] and br['builds'][0].get_formated_build_time()"/></small><br/>
|
||||
<td style="width:12%">
|
||||
<small class="branch_time" ><t t-esc="br['builds'] and br['builds'][0].get_formated_build_time()"/></small>
|
||||
<div class="branch_name"><i t-if="br['branch'].sticky" class="fa fa-star" style="color: #f0ad4e" /><a t-attf-href="/runbot/branch/#{br['branch'].id}"><b t-esc="br['branch'].branch_name"/></a></div>
|
||||
<div class="btn-group btn-group-xs">
|
||||
<a t-attf-href="{{br['branch'].branch_url}}" class="btn btn-default btn-xs">Branch or pull <i class="fa fa-github"/></a>
|
||||
<a t-attf-href="{{br['branch'].branch_url}}" class="btn btn-default btn-xs"><t t-esc="'Branch ' if not br['branch'].pull_head_name else 'Pull '"/><i class="fa fa-github"/></a>
|
||||
<a t-attf-href="/runbot/quick_connect/#{br['branch'].id}" class="btn btn-default btn-xs" aria-label="Quick Connect"><i class="fa fa-fast-forward" title="Quick Connect"/></a>
|
||||
</div>
|
||||
<t t-if="br['branch'].sticky">
|
||||
@ -134,20 +138,21 @@
|
||||
<t t-if="bu.global_result == 'skipped'"><t t-set="klass">default</t></t>
|
||||
<t t-if="bu.global_result in ['killed', 'manually_killed']"><t t-set="klass">killed</t></t>
|
||||
</t>
|
||||
<td t-attf-class="{{klass}}">
|
||||
<td t-attf-class="bg-{{klass}}-light" style="width:22%">
|
||||
<t t-call="runbot.build_button">
|
||||
<t t-set="klass">btn-group-sm</t>
|
||||
<t t-set="show_rebuild_button" t-value="bu==br['builds'][0]"></t>
|
||||
<t t-set="show_commit_button" t-value="True"/>
|
||||
</t>
|
||||
<t t-if="bu['build_type']=='scheduled'"><i class="fa fa-moon-o" t-att-title="bu.build_type_label()" t-att-aria-label="bu.build_type_label()"/></t>
|
||||
<t t-if="bu['build_type'] in ('rebuild', 'indirect')"><i class="fa fa-recycle" t-att-title="bu.build_type_label()" t-att-aria-label="bu.build_type_label()"/></t>
|
||||
<t t-if="bu['subject']">
|
||||
<span t-if="bu['subject']" class="build_subject">
|
||||
<t t-if="bu.config_id != bu.branch_id.config_id">
|
||||
<b t-esc="bu.config_id.name"/>
|
||||
</t>
|
||||
<span t-esc="bu['subject'][:32] + ('...' if bu['subject'][32:] else '') " t-att-title="bu['subject']"/>
|
||||
<br/>
|
||||
</t>
|
||||
</span>
|
||||
<t t-id="bu['author']">
|
||||
<t t-esc="bu['author']"/>
|
||||
<t t-if="bu['committer'] and bu['author'] != bu['committer']" t-id="bu['committer']">
|
||||
|
@ -389,6 +389,7 @@ class Test_Build(RunbotCase):
|
||||
'branch_id': self.branch_10.id,
|
||||
'name': 'd0d0caca0000ffffffffffffffffffffffffffff',
|
||||
'extra_params': '0',
|
||||
'local_state': 'done'
|
||||
})
|
||||
build_parent = self.create_build({
|
||||
'branch_id': self.branch_10.id,
|
||||
@ -404,6 +405,7 @@ class Test_Build(RunbotCase):
|
||||
build_parent.local_state = 'done'
|
||||
self.assertEqual(build_child.local_state, 'duplicate')
|
||||
self.assertEqual(build_child.duplicate_id, build_old)
|
||||
self.assertEqual(build_child.global_state, 'done')
|
||||
self.assertEqual(build_parent.nb_pending, 0)
|
||||
self.assertEqual(build_parent.nb_testing, 0)
|
||||
self.assertEqual(build_parent.global_state, 'done')
|
||||
|
@ -53,9 +53,6 @@ class Test_Frontend(RunbotCase):
|
||||
self.assertEqual(self.sticky_branch, context['branches'][0]['branch'], "The sticky branch should be in first place")
|
||||
self.assertEqual(self.branch, context['branches'][1]['branch'], "The non sticky branch should be in second place")
|
||||
self.assertEqual(len(context['branches'][0]['builds']), 4, "Only the 4 last builds should appear in the context")
|
||||
self.assertEqual(context['pending'], 2, "There should be 2 pending builds")
|
||||
self.assertEqual(context['running'], 2, "There should be 2 running builds")
|
||||
self.assertEqual(context['testing'], 2, "There should be 2 testing builds")
|
||||
self.assertEqual(context['pending_total'], 2, "There should be 2 pending builds")
|
||||
self.assertEqual(context['pending_level'], 'info', "The pending level should be info")
|
||||
return Response()
|
||||
|
@ -3,7 +3,7 @@
|
||||
<data>
|
||||
<template id="assets_front_end" inherit_id="web.assets_frontend" name="runbot assets">
|
||||
<xpath expr="." position="inside">
|
||||
<link rel="stylesheet" href="/runbot/static/src/less/runbot.less"/>
|
||||
<link rel="stylesheet" href="/runbot/static/src/css/runbot.css"/>
|
||||
</xpath>
|
||||
</template>
|
||||
</data>
|
||||
|
@ -23,6 +23,7 @@
|
||||
<field name="update_github_state" groups="base.group_no_one"/>
|
||||
<field name="protected" groups="base.group_no_one"/>
|
||||
<field name="group" groups="base.group_no_one"/>
|
||||
<field name="monitoring_view_id" groups="base.group_no_one"/>
|
||||
</group>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
|
@ -2,7 +2,7 @@
|
||||
'name': 'Runbot CLA',
|
||||
'category': 'Website',
|
||||
'summary': 'Runbot CLA',
|
||||
'version': '2.0',
|
||||
'version': '2.1',
|
||||
'description': "Runbot CLA",
|
||||
'author': 'Odoo SA',
|
||||
'depends': ['runbot'],
|
||||
|
@ -5,11 +5,4 @@
|
||||
<field name="job_type">cla_check</field>
|
||||
<field name="protected" eval="True"/>
|
||||
</record>
|
||||
|
||||
<record id="runbot.runbot_build_config_default" model="runbot.build.config">
|
||||
<field name="step_order_ids" eval="[(0, 0, {'step_id': ref('runbot_build_config_step_check_cla')})]"/>
|
||||
</record>
|
||||
<record id="runbot.runbot_build_config_default_no_run" model="runbot.build.config">
|
||||
<field name="step_order_ids" eval="[(0, 0, {'step_id': ref('runbot_build_config_step_check_cla')})]"/>
|
||||
</record>
|
||||
</odoo>
|
||||
|
Loading…
Reference in New Issue
Block a user