mirror of
https://github.com/odoo/runbot.git
synced 2025-03-15 23:45:44 +07:00
[IMP] runbot: add kill button (+ deathrow state)
Allow logged users to kill builds that are pending or testing. The kill button solves the following problem: When you have a community and enterprise branch with pull request. The enterprise PR gets fetched before the branch by runbot, so it builds with the community master branch instead of the corresponding community branch. As the branch shares the same HEAD as the PR, so no other build is done for the branch. Previously you had to wait the build to finish building, then rebuild it from the branch, taking twice the time necessary. Now you'll be able to kill & rebuild it just after pushing the branch. Also having a kill button is globally a nice to have feature.
This commit is contained in:
parent
a3d30e9d3c
commit
fb1e1dfd53
@ -375,7 +375,7 @@ class runbot_repo(osv.osv):
|
||||
domain_host = domain + [('host', '=', host)]
|
||||
|
||||
# schedule jobs (transitions testing -> running, kill jobs, ...)
|
||||
build_ids = Build.search(cr, uid, domain_host + [('state', 'in', ['testing', 'running'])])
|
||||
build_ids = Build.search(cr, uid, domain_host + [('state', 'in', ['testing', 'running', 'deathrow'])])
|
||||
Build._schedule(cr, uid, build_ids)
|
||||
|
||||
# launch new tests
|
||||
@ -598,9 +598,9 @@ class runbot_build(osv.osv):
|
||||
'subject': fields.text('Subject'),
|
||||
'sequence': fields.integer('Sequence', select=1),
|
||||
'modules': fields.char("Modules to Install"),
|
||||
'result': fields.char('Result'), # ok, ko, warn, skipped, killed
|
||||
'result': fields.char('Result'), # ok, ko, warn, skipped, killed, manually_killed
|
||||
'pid': fields.integer('Pid'),
|
||||
'state': fields.char('Status'), # pending, testing, running, done, duplicate
|
||||
'state': fields.char('Status'), # pending, testing, running, done, duplicate, deathrow
|
||||
'job': fields.char('Job'), # job_*
|
||||
'job_start': fields.datetime('Job start'),
|
||||
'job_end': fields.datetime('Job end'),
|
||||
@ -1128,7 +1128,10 @@ class runbot_build(osv.osv):
|
||||
default_timeout = int(icp.get_param(cr, uid, 'runbot.timeout', default=1800)) / 60
|
||||
|
||||
for build in self.browse(cr, uid, ids, context=context):
|
||||
if build.state == 'pending':
|
||||
if build.state == 'deathrow':
|
||||
build._kill(result='manually_killed')
|
||||
continue
|
||||
elif build.state == 'pending':
|
||||
# allocate port and schedule first job
|
||||
port = self._find_port(cr, uid)
|
||||
values = {
|
||||
@ -1271,6 +1274,16 @@ class runbot_build(osv.osv):
|
||||
build._github_status()
|
||||
build._local_cleanup()
|
||||
|
||||
def _ask_kill(self, cr, uid, ids, context=None):
|
||||
user = self.pool['res.users'].browse(cr, uid, uid, context=context)
|
||||
for build in self.browse(cr, SUPERUSER_ID, ids, context=context):
|
||||
if build.state == 'pending':
|
||||
build._skip()
|
||||
build.log('_ask_kill', 'Skipping build %s, requested by user %s (%s)' % build.dest, user.name, uid)
|
||||
elif build.state in ['testing', 'running']:
|
||||
build.write({'state': 'deathrow'})
|
||||
build.log('_ask_kill', 'Killing build %s, requested by user %s (%s)' % build.dest, user.name, uid)
|
||||
|
||||
def _reap(self, cr, uid, ids):
|
||||
while True:
|
||||
try:
|
||||
@ -1338,7 +1351,7 @@ class RunbotController(http.Controller):
|
||||
|
||||
build_ids = []
|
||||
if repo:
|
||||
filters = {key: post.get(key, '1') for key in ['pending', 'testing', 'running', 'done']}
|
||||
filters = {key: post.get(key, '1') for key in ['pending', 'testing', 'running', 'done', 'deathrow']}
|
||||
domain = [('repo_id','=',repo.id)]
|
||||
domain += [('state', '!=', key) for key, value in filters.iteritems() if value == '0']
|
||||
if search:
|
||||
@ -1548,6 +1561,13 @@ class RunbotController(http.Controller):
|
||||
repo_id = registry['runbot.build']._force(cr, uid, [int(build_id)])
|
||||
return werkzeug.utils.redirect('/runbot/repo/%s' % repo_id + ('?search=%s' % search if search else ''))
|
||||
|
||||
@http.route(['/runbot/build/<build_id>/kill'], type='http', auth="user", methods=['POST'], csrf=False)
|
||||
def build_ask_kill(self, build_id, search=None, **post):
|
||||
registry, cr, uid = request.registry, request.cr, request.uid
|
||||
build = registry['runbot.build'].browse(cr, uid, build_id)
|
||||
build._ask_kill()
|
||||
return werkzeug.utils.redirect('/runbot/repo/%s' % build.repo_id + ('?search=%s' % search if search else ''))
|
||||
|
||||
@http.route([
|
||||
'/runbot/badge/<int:repo_id>/<branch>.svg',
|
||||
'/runbot/badge/<any(default,flat):theme>/<int:repo_id>/<branch>.svg',
|
||||
@ -1558,7 +1578,7 @@ class RunbotController(http.Controller):
|
||||
('branch_id.branch_name', '=', branch),
|
||||
('branch_id.sticky', '=', True),
|
||||
('state', 'in', ['testing', 'running', 'done']),
|
||||
('result', '!=', 'skipped'),
|
||||
('result', 'not in', ['skipped', 'manually_killed']),
|
||||
]
|
||||
|
||||
last_update = '__last_update'
|
||||
|
@ -187,6 +187,7 @@
|
||||
<filter string="Running" domain="[('state','=', 'running')]"/>
|
||||
<filter string="Done" domain="[('state','=','done')]"/>
|
||||
<filter string="Duplicate" domain="[('state','=', 'duplicate')]"/>
|
||||
<filter string="Deathrow" domain="[('state','=', 'deathrow')]"/>
|
||||
<separator />
|
||||
<group expand="0" string="Group By...">
|
||||
<filter string="Repo" domain="[]" context="{'group_by':'repo_id'}"/>
|
||||
@ -254,6 +255,7 @@
|
||||
</template>
|
||||
|
||||
<template id="runbot.build_name">
|
||||
<t t-if="bu['state']=='deathrow'"><i class="text-info fa fa-crosshairs"/> killing</t>
|
||||
<t t-if="bu['state']=='pending'"><i class="text-default fa fa-pause"/> pending</t>
|
||||
<t t-if="bu['state']=='testing'"><i class="text-info fa fa-spinner"/> testing <t t-esc="bu['job']"/> <small t-if="not hide_time"><t t-esc="bu['job_time']"/></small></t>
|
||||
<t t-if="bu['result']=='ok'"><i class="text-success fa fa-thumbs-up"/><small t-if="not hide_time"> age <t t-esc="bu['job_age']"/> time <t t-esc="bu['job_time']"/></small></t>
|
||||
@ -261,6 +263,7 @@
|
||||
<t t-if="bu['result']=='warn'"><i class="text-warning fa fa-warning"/><small t-if="not hide_time"> age <t t-esc="bu['job_age']"/> time <t t-esc="bu['job_time']"/></small></t>
|
||||
<t t-if="bu['result']=='skipped'"><i class="text-danger fa fa-ban"/> skipped</t>
|
||||
<t t-if="bu['result']=='killed'"><i class="text-danger fa fa-times"/> killed</t>
|
||||
<t t-if="bu['result']=='manually_killed'"><i class="text-danger fa fa-times"/> manually killed</t>
|
||||
|
||||
<t t-if="bu['server_match'] in ('default', 'fuzzy')">
|
||||
<i class="text-warning fa fa-question-circle fa-fw"
|
||||
@ -284,9 +287,12 @@
|
||||
<li><a t-attf-href="http://{{bu['domain']}}/?db={{bu['real_dest']}}-base">Connect base <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>
|
||||
<li t-if="bu['state'] in ['done','running'] and bu_index==0" groups="runbot.group_user">
|
||||
<li t-if="bu['state'] in ['done','running','deathrow'] and bu_index==0" groups="runbot.group_user">
|
||||
<a href="#" class="runbot-rebuild" t-att-data-runbot-build="bu['id']">Rebuild <i class="fa fa-refresh"/></a>
|
||||
</li>
|
||||
<li t-if="bu['state'] in ['pending','testing','running']" groups="runbot.group_user">
|
||||
<a href="#" class="runbot-kill" t-att-data-runbot-build="bu['id']">Kill <i class="fa fa-crosshairs"/></a>
|
||||
</li>
|
||||
<li t-if="bu['state']!='testing' and bu['state']!='pending'" class="divider"></li>
|
||||
<li><a t-attf-href="/runbot/build/{{bu['id']}}">Logs <i class="fa fa-file-text-o"/></a></li>
|
||||
<li t-if="bu['host']"><a t-attf-href="http://{{bu['host']}}/runbot/static/build/#{bu['real_dest']}/logs/job_10_test_base.txt">Full base logs <i class="fa fa-file-text-o"/></a></li>
|
||||
@ -413,11 +419,12 @@
|
||||
<t t-foreach="br['builds']" t-as="bu">
|
||||
<t t-if="bu['state']=='pending'"><t t-set="klass">default</t></t>
|
||||
<t t-if="bu['state']=='testing'"><t t-set="klass">info</t></t>
|
||||
<t t-if="bu['state']=='deathrow'"><t t-set="klass">default</t></t>
|
||||
<t t-if="bu['state'] in ['running','done'] and bu['result'] == 'ko'"><t t-set="klass">danger</t></t>
|
||||
<t t-if="bu['state'] in ['running','done'] and bu['result'] == 'warn'"><t t-set="klass">warning</t></t>
|
||||
<t t-if="bu['state'] in ['running','done'] and bu['result'] == 'ok'"><t t-set="klass">success</t></t>
|
||||
<t t-if="bu['state'] in ['running','done'] and bu['result'] == 'skipped'"><t t-set="klass">default</t></t>
|
||||
<t t-if="bu['state'] in ['running','done'] and bu['result'] == 'killed'"><t t-set="klass">killed</t></t>
|
||||
<t t-if="bu['state'] in ['running','done'] and bu['result'] in ['killed', 'manually_killed']"><t t-set="klass">killed</t></t>
|
||||
<td t-attf-class="{{klass}}">
|
||||
<t t-call="runbot.build_button"><t t-set="klass">btn-group-sm</t></t>
|
||||
<t t-if="bu['subject']">
|
||||
@ -489,11 +496,12 @@
|
||||
<t t-foreach="br['builds']" t-as="bu">
|
||||
<t t-if="bu['state']=='pending'"><t t-set="klass">default</t></t>
|
||||
<t t-if="bu['state']=='testing'"><t t-set="klass">info</t></t>
|
||||
<t t-if="bu['state']=='deathrow'"><t t-set="klass">default</t></t>
|
||||
<t t-if="bu['state'] in ['running','done'] and bu['result'] == 'ko'"><t t-set="klass">danger</t></t>
|
||||
<t t-if="bu['state'] in ['running','done'] and bu['result'] == 'warn'"><t t-set="klass">warning</t></t>
|
||||
<t t-if="bu['state'] in ['running','done'] and bu['result'] == 'ok'"><t t-set="klass">success</t></t>
|
||||
<t t-if="bu['state'] in ['running','done'] and bu['result'] == 'skipped'"><t t-set="klass">default</t></t>
|
||||
<t t-if="bu['state'] in ['running','done'] and bu['result'] == 'killed'"><t t-set="klass">killed</t></t>
|
||||
<t t-if="bu['state'] in ['running','done'] and bu['result'] in ['killed', 'manually_killed']"><t t-set="klass">killed</t></t>
|
||||
<div t-attf-class="bg-{{klass}} col-md-4">
|
||||
<i class="fa fa-at"></i>
|
||||
<t t-esc="bu['author']"/>
|
||||
|
@ -4,7 +4,17 @@
|
||||
$(function() {
|
||||
$('a.runbot-rebuild').click(function() {
|
||||
var $f = $('<form method="POST">'),
|
||||
url = _.str.sprintf('/runbot/build/%s/force', $(this).data('runbot-build')) + window.location.search;
|
||||
url = _.str.sprintf('/runbot/build/%s/force', $(this).data('runbot-build')) + window.location.search;
|
||||
$f.attr('action', url);
|
||||
$f.appendTo($('body'));
|
||||
$f.submit();
|
||||
return false;
|
||||
});
|
||||
});
|
||||
$(function() {
|
||||
$('a.runbot-kill').click(function() {
|
||||
var $f = $('<form method="POST">'),
|
||||
url = _.str.sprintf('/runbot/build/%s/kill', $(this).data('runbot-build')) + window.location.search;
|
||||
$f.attr('action', url);
|
||||
$f.appendTo($('body'));
|
||||
$f.submit();
|
||||
|
Loading…
Reference in New Issue
Block a user