mirror of
https://github.com/odoo/runbot.git
synced 2025-03-30 23:05:44 +07:00
[IMP] runbot: improve build log view
Co-authored-by: Xavier-Do <xdo@odoo.com>
This commit is contained in:
parent
5552c16102
commit
6c64bbb49b
@ -160,28 +160,14 @@ class Runbot(Controller):
|
|||||||
if not build.exists():
|
if not build.exists():
|
||||||
return request.not_found()
|
return request.not_found()
|
||||||
|
|
||||||
# other builds
|
show_rebuild_button = Build.search([('branch_id', '=', build.branch_id.id), ('parent_id', '=', False)], limit=1) == build
|
||||||
build_ids = Build.search([('branch_id', '=', build.branch_id.id)], limit=100)
|
|
||||||
other_builds = Build.browse(build_ids)
|
|
||||||
domain = [('build_id', '=', build.real_build.id)]
|
|
||||||
log_type = request.params.get('type', '')
|
|
||||||
if log_type:
|
|
||||||
domain.append(('type', '=', log_type))
|
|
||||||
level = request.params.get('level', '')
|
|
||||||
if level:
|
|
||||||
domain.append(('level', '=', level.upper()))
|
|
||||||
if search:
|
|
||||||
domain.append(('message', 'ilike', search))
|
|
||||||
logging_ids = Logging.sudo().search(domain, limit=10000)
|
|
||||||
|
|
||||||
context = {
|
context = {
|
||||||
'repo': build.repo_id,
|
'repo': build.repo_id,
|
||||||
'build': build,
|
'build': build,
|
||||||
'fqdn': fqdn(),
|
'fqdn': fqdn(),
|
||||||
'br': {'branch': build.branch_id},
|
'br': {'branch': build.branch_id},
|
||||||
'logs': Logging.sudo().browse(logging_ids).ids,
|
'show_rebuild_button': show_rebuild_button,
|
||||||
'other_builds': other_builds.ids,
|
|
||||||
'bu_index': 0 if build == build_ids[0] else -1
|
|
||||||
}
|
}
|
||||||
return request.render("runbot.build", context)
|
return request.render("runbot.build", context)
|
||||||
|
|
||||||
@ -357,4 +343,3 @@ class Runbot(Controller):
|
|||||||
|
|
||||||
context = {'pager': pager, 'builds': builds}
|
context = {'pager': pager, 'builds': builds}
|
||||||
return request.render("runbot.branch", context)
|
return request.render("runbot.branch", context)
|
||||||
|
|
||||||
|
@ -49,6 +49,8 @@ class runbot_build(models.Model):
|
|||||||
committer_email = fields.Char('Committer Email')
|
committer_email = fields.Char('Committer Email')
|
||||||
subject = fields.Text('Subject')
|
subject = fields.Text('Subject')
|
||||||
sequence = fields.Integer('Sequence')
|
sequence = fields.Integer('Sequence')
|
||||||
|
log_ids = fields.One2many('ir.logging', 'build_id', string='Logs')
|
||||||
|
error_log_ids = fields.One2many('ir.logging', 'build_id', domain=[('level', 'in', ['WARNING', 'ERROR', 'CRITICAL'])], string='Error Logs')
|
||||||
|
|
||||||
# state machine
|
# state machine
|
||||||
|
|
||||||
|
@ -2,3 +2,11 @@
|
|||||||
border-top: 2px solid #666;
|
border-top: 2px solid #666;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[data-toggle="collapse"] .fa:before {
|
||||||
|
content: "\f139";
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-toggle="collapse"].collapsed .fa:before {
|
||||||
|
content: "\f13a";
|
||||||
|
}
|
||||||
|
@ -66,7 +66,7 @@
|
|||||||
<li><a t-attf-href="http://{{bu['domain']}}/">Connect <i class="fa fa-sign-in"></i></a></li>
|
<li><a t-attf-href="http://{{bu['domain']}}/">Connect <i class="fa fa-sign-in"></i></a></li>
|
||||||
</t>
|
</t>
|
||||||
<li t-if="bu.global_state in ['done','running'] or requested_action == 'deathrow'" groups="base.group_user">
|
<li t-if="bu.global_state in ['done','running'] or requested_action == 'deathrow'" groups="base.group_user">
|
||||||
<t t-if="bu_index==0">
|
<t t-if="show_rebuild_button">
|
||||||
<a href="#" class="runbot-rebuild" t-att-data-runbot-build="bu['id']"
|
<a href="#" class="runbot-rebuild" t-att-data-runbot-build="bu['id']"
|
||||||
title="Create a new build keeping build commit head, but will recompute all other info (config, dependencies, extra_params)">
|
title="Create a new build keeping build commit head, but will recompute all other info (config, dependencies, extra_params)">
|
||||||
Rebuild <i class="fa fa-refresh"/>
|
Rebuild <i class="fa fa-refresh"/>
|
||||||
@ -105,6 +105,17 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<!-- Event / Logs page -->
|
<!-- Event / Logs page -->
|
||||||
|
<template id="runbot.build_class">
|
||||||
|
<t t-set="rowclass">info</t>
|
||||||
|
<t t-if="build.global_state in ['running','done']">
|
||||||
|
<t t-if="build.global_result == 'ok'"><t t-set="rowclass">success</t></t>
|
||||||
|
<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>
|
||||||
|
<t t-if="build.global_result == 'ko'"><t t-set="rowclass">danger</t></t>
|
||||||
|
<t t-if="build.global_result == 'warn'"><t t-set="rowclass">warning</t></t>
|
||||||
|
<t t-esc="rowclass"/>
|
||||||
|
</template>
|
||||||
<template id="runbot.build">
|
<template id="runbot.build">
|
||||||
<t t-call='website.layout'>
|
<t t-call='website.layout'>
|
||||||
<div class="container" style="width: 100%;">
|
<div class="container" style="width: 100%;">
|
||||||
@ -138,67 +149,17 @@
|
|||||||
</form>
|
</form>
|
||||||
<p class="navbar-text">
|
<p class="navbar-text">
|
||||||
</p>
|
</p>
|
||||||
<form class="navbar-form navbar-left form-inline">
|
|
||||||
<div class="btn-group">
|
|
||||||
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
|
|
||||||
Filter <span class="caret"></span>
|
|
||||||
</button>
|
|
||||||
<ul class="dropdown-menu" role="menu">
|
|
||||||
<li role="presentation" class="dropdown-header">Level</li>
|
|
||||||
<li><a t-att-href="'?' + keep_query('search', 'type', level='debug')"><i t-if="level == 'debug'" class="fa fa-check"/> Debug</a></li>
|
|
||||||
<li><a t-att-href="'?' + keep_query('search', 'type', level='info')"><i t-if="level == 'info'" class="fa fa-check"/> Info</a></li>
|
|
||||||
<li><a t-att-href="'?' + keep_query('search', 'type', level='warning')"><i t-if="level == 'warning'" class="fa fa-check"/> Warning</a></li>
|
|
||||||
<li><a t-att-href="'?' + keep_query('search', 'type', level='error')"><i t-if="level == 'error'" class="fa fa-check"/> Error</a></li>
|
|
||||||
<li role="presentation" class="dropdown-header">Type</li>
|
|
||||||
<li><a t-att-href="'?' + keep_query('search', 'level',type='runbot')"><i t-if="type == 'runbot'" class="fa fa-check"/> Runbot</a></li>
|
|
||||||
<li><a t-att-href="'?' + keep_query('search', 'level',type='server')"><i t-if="type == 'server'" class="fa fa-check"/> Server</a></li>
|
|
||||||
<li><a t-att-href="'?' + keep_query('search', 'level',type='client')"><i t-if="type == 'client'" class="fa fa-check"/> Client</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="btn-group">
|
|
||||||
<button type="button" class="btn btn-default">Expand</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<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="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">
|
||||||
<a href='#' class="btn btn-danger runbot-rebuild" t-attf-data-runbot-build="#{build['id']}" > <i class='fa fa-refresh'/> Force Rebuild</a>
|
<a href='#' class="btn btn-danger runbot-rebuild" t-attf-data-runbot-build="#{build['id']}" > <i class='fa fa-refresh'/> Force Rebuild</a>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<ul class="nav navbar-nav navbar-right">
|
|
||||||
<li class="dropdown">
|
|
||||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" aria-expanded="false">Other builds <b class="caret"></b></a>
|
|
||||||
<ul class="dropdown-menu">
|
|
||||||
<t t-foreach='other_builds' t-as='other_build'>
|
|
||||||
<li><a t-attf-href="/runbot/build/{{other_build.id}}">
|
|
||||||
<t t-esc='other_build.dest'/>
|
|
||||||
<t t-call="runbot.build_name">
|
|
||||||
<t t-set="bu" t-value="other_build"/>
|
|
||||||
<t t-set="hide_time" t-value="True"></t>
|
|
||||||
</t>
|
|
||||||
</a></li>
|
|
||||||
</t>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<form class="navbar-form navbar-right" role="search" t-attf-action="/runbot/build/{{build['id']}}" method="get">
|
|
||||||
<div class="form-group">
|
|
||||||
<input type="search" name="search" class="form-control" placeholder="Search" t-att-value="search or ''"/>
|
|
||||||
<button type="submit" class="btn btn-default">Search</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
<t t-set="rowclass">info</t>
|
|
||||||
<t t-if="build.global_state in ['running','done']">
|
|
||||||
<t t-if="build.global_result == 'ok'"><t t-set="rowclass">success</t></t>
|
|
||||||
<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>
|
|
||||||
<t t-if="build.global_result == 'ko'"><t t-set="rowclass">danger</t></t>
|
|
||||||
<t t-if="build.global_result == 'warn'"><t t-set="rowclass">warning</t></t>
|
|
||||||
<table class="table table-condensed tabel-bordered">
|
<table class="table table-condensed tabel-bordered">
|
||||||
<tr>
|
<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="{{rowclass}}">
|
||||||
Subject: <t t-esc="build['subject']"/><br/>
|
Subject: <t t-esc="build['subject']"/><br/>
|
||||||
Author: <t t-esc="build['author']"/><br/>
|
Author: <t t-esc="build['author']"/><br/>
|
||||||
@ -219,15 +180,8 @@
|
|||||||
<t t-if="build.real_build.nb_testing > 0"><t t-esc="build.real_build.nb_testing"/> testing </t>
|
<t t-if="build.real_build.nb_testing > 0"><t t-esc="build.real_build.nb_testing"/> testing </t>
|
||||||
<t t-if="build.real_build.nb_running > 0"><t t-esc="build.real_build.nb_running"/> running </t>
|
<t t-if="build.real_build.nb_running > 0"><t t-esc="build.real_build.nb_running"/> running </t>
|
||||||
<table class="table table-condensed">
|
<table class="table table-condensed">
|
||||||
<t t-foreach="build.real_build.children_ids" t-as="child">
|
<t t-foreach="build.real_build.children_ids.sorted('id')" t-as="child">
|
||||||
<t t-set="rowclass">info</t>
|
<t t-set="rowclass"><t t-call="runbot.build_class"><t t-set="build" t-value="child"/></t></t>
|
||||||
<t t-if="child.global_state in ['running','done']">
|
|
||||||
<t t-if="child.global_result == 'ok'"><t t-set="rowclass">success</t></t>
|
|
||||||
<t t-if="child.global_result == 'skipped'"><t t-set="rowclass">default</t></t>
|
|
||||||
<t t-if="child.global_result in ['killed', 'manually_killed']"><t t-set="rowclass">killed</t></t>
|
|
||||||
</t>
|
|
||||||
<t t-if="child.global_result == 'ko'"><t t-set="rowclass">danger</t></t>
|
|
||||||
<t t-if="child.global_result == 'warn'"><t t-set="rowclass">warning</t></t>
|
|
||||||
<tr><td t-attf-class="{{rowclass}}">
|
<tr><td t-attf-class="{{rowclass}}">
|
||||||
<a t-attf-href="/runbot/build/{{child.id}}" >Build <t t-esc="child.id"/></a>
|
<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 <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>
|
||||||
@ -256,14 +210,20 @@
|
|||||||
<th>Type</th>
|
<th>Type</th>
|
||||||
<th>Message</th>
|
<th>Message</th>
|
||||||
</tr>
|
</tr>
|
||||||
<t t-foreach="logs" t-as="l">
|
<t t-foreach="build.real_build.sudo().log_ids" t-as="l">
|
||||||
<tr t-att-class="dict(ERROR='danger', WARNING='warning', OK='success', SEPARATOR='separator').get(l.level)">
|
<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]"/>
|
||||||
<td style="white-space: nowrap;"><t t-esc="l.create_date"/></td>
|
<t t-set="logclass" t-value="dict(CRITICAL='danger', ERROR='danger', WARNING='warning', OK='success', SEPARATOR='separator').get(l.level)"/>
|
||||||
<td><b t-if="l.level != 'SEPARATOR' and l.type != 'link'" t-esc="l.level"/></td>
|
<tr t-att-class="logclass">
|
||||||
<td><t t-if="l.level != 'SEPARATOR' and l.type != 'link'" t-esc="l.type"/></td>
|
<td style="white-space: nowrap; width:1%;"><t t-esc="l.create_date"/></td>
|
||||||
<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-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">
|
||||||
<t t-if="l.type not in ('runbot', 'link')">
|
<t t-if="l.type not in ('runbot', 'link')">
|
||||||
<a t-if="l.type == 'subbuild'" t-attf-href="/runbot/build/{{l.path}}">Sub build #<t t-esc="l.path"/></a>
|
<t t-if="l.type == 'subbuild'">
|
||||||
|
<a t-attf-href="/runbot/build/{{l.path}}">Build #<t t-esc="l.path"/></a>
|
||||||
|
</t>
|
||||||
<a t-else="" t-attf-href="https://{{repo.base}}/blob/{{build['name']}}/{{l.path}}#L{{l.line}}"><t t-esc="l.name"/>:<t t-esc="l.line"/></a> <t t-esc="l.func"/>
|
<a t-else="" t-attf-href="https://{{repo.base}}/blob/{{build['name']}}/{{l.path}}#L{{l.line}}"><t t-esc="l.name"/>:<t t-esc="l.line"/></a> <t t-esc="l.func"/>
|
||||||
</t>
|
</t>
|
||||||
<t t-if="l.type == 'link' and len(l.message.split('$$')) == 3">
|
<t t-if="l.type == 'link' and len(l.message.split('$$')) == 3">
|
||||||
@ -272,12 +232,30 @@
|
|||||||
<t t-esc="message[0]"/><a t-attf-href="{{l.path}}"><i t-attf-class="fa {{message[1]}}"/></a><t t-esc="message[2]"/>
|
<t t-esc="message[0]"/><a t-attf-href="{{l.path}}"><i t-attf-class="fa {{message[1]}}"/></a><t t-esc="message[2]"/>
|
||||||
</t>
|
</t>
|
||||||
<t t-else="">
|
<t t-else="">
|
||||||
<t t-esc="message[0]"/><a t-attf-href="{{l.path}}"><t t-esc="message[1]"/></a><t t-esc="message[2]"/>
|
<t t-esc="message[0]"/><a t-attf-href="{{l.path}}"><t t-esc="message[1]"/></a><t t-esc="message[2]"/>
|
||||||
</t>
|
</t>
|
||||||
</t>
|
</t>
|
||||||
<t t-else="">
|
<t t-else="">
|
||||||
<t t-if="'\n' not in l.message" t-esc="l.message"/>
|
<t t-if="'\n' not in l.message" t-esc="l.message"/>
|
||||||
<pre t-if="'\n' in l.message" style="margin:0;padding:0; border: none;"><t t-esc="l.message"/></pre>
|
<pre t-if="'\n' in l.message" style="margin:0;padding:0; border: none;"><t t-esc="l.message"/></pre>
|
||||||
|
<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;">
|
||||||
|
<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)">
|
||||||
|
<t t-if="sl.type == 'server'">
|
||||||
|
<a t-attf-href="https://{{repo.base}}/blob/{{build['name']}}/{{sl.path}}#L{{sl.line}}"><t t-esc="sl.name"/>:<t t-esc="sl.line"/></a> <t t-esc="sl.func"/>
|
||||||
|
</t>
|
||||||
|
<t t-if="'\n' not in sl.message" t-esc="sl.message"/>
|
||||||
|
<pre t-if="'\n' in sl.message" style="margin:0;padding:0; border: none;"><t t-esc="sl.message"/></pre>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</t>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</t>
|
||||||
</t>
|
</t>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
Loading…
Reference in New Issue
Block a user