diff --git a/runbot/models/branch.py b/runbot/models/branch.py
index f202e0e8..fae2e192 100644
--- a/runbot/models/branch.py
+++ b/runbot/models/branch.py
@@ -4,6 +4,7 @@ import re
import time
from subprocess import CalledProcessError
from odoo import models, fields, api
+from odoo.osv import expression
_logger = logging.getLogger(__name__)
_re_patch = re.compile(r'.*patch-\d+$')
@@ -23,6 +24,7 @@ class runbot_branch(models.Model):
branch_url = fields.Char(compute='_get_branch_url', string='Branch url', readonly=1)
pull_head_name = fields.Char(compute='_get_branch_infos', string='PR HEAD name', readonly=1, store=True)
target_branch_name = fields.Char(compute='_get_branch_infos', string='PR target branch', store=True)
+ pull_branch_name = fields.Char(compute='_compute_pull_branch_name', string='Branch display name')
sticky = fields.Boolean('Sticky')
closest_sticky = fields.Many2one('runbot.branch', compute='_compute_closest_sticky', string='Closest sticky')
defined_sticky = fields.Many2one('runbot.branch', string='Force sticky')
@@ -101,6 +103,10 @@ class runbot_branch(models.Model):
for branch in self:
branch.branch_config_id = branch.config_id
+ def _compute_pull_branch_name(self):
+ for branch in self:
+ branch.pull_branch_name = branch.pull_head_name.split(':')[-1] if branch.pull_head_name else branch.branch_name
+
@api.depends('name')
def _get_branch_infos(self, pull_info=None):
"""compute branch_name, branch_url, pull_head_name and target_branch_name based on name"""
@@ -151,6 +157,35 @@ class runbot_branch(models.Model):
return False
return True
+ def _get_last_branch_name_builds(self):
+ # naive way to find corresponding build, only matching branch name or pr pull_head_name and target_branch_name.
+ self.ensure_one()
+ domain = []
+ if self.pull_head_name:
+ domain = [('pull_head_name', 'like', '%%:%s' % self.pull_head_name.split(':')[-1]), ('target_branch_name', '=', self.target_branch_name)] # pr matching pull head name
+ else:
+ domain = [('name', '=', self.name)]
+ #domain += [('id', '!=', self.branch_id.id)]
+
+ e = expression.expression(domain, self)
+ where_clause, where_params = e.to_sql()
+
+ repo_ids = tuple(self.env['runbot.repo'].search([]).ids) # access rights
+ query = """
+ SELECT max(b.id)
+ FROM runbot_build b
+ WHERE b.branch_id IN (
+ SELECT id from runbot_branch WHERE %s
+ )
+ AND b.build_type IN ('normal', 'rebuild')
+ AND b.repo_id in %%s
+ GROUP BY b.repo_id
+ """ % where_clause
+
+ self.env.cr.execute(query, where_params + [repo_ids])
+ results = [r[0] for r in self.env.cr.fetchall()]
+ return self.env['runbot.build'].browse(results)
+
@api.model_create_single
def create(self, vals):
if not vals.get('config_id') and ('use-coverage' in (vals.get('name') or '')):
diff --git a/runbot/static/src/css/runbot.css b/runbot/static/src/css/runbot.css
index 97439884..5d3caee8 100644
--- a/runbot/static/src/css/runbot.css
+++ b/runbot/static/src/css/runbot.css
@@ -78,3 +78,11 @@ body, .table{
.build_buttons {
margin-left: auto
}
+
+.bg-killed {
+ background-color: #aaa;
+}
+
+.label-killed {
+ background-color: #aaa;
+}
diff --git a/runbot/templates/build.xml b/runbot/templates/build.xml
index ad125cd8..0c7615cb 100644
--- a/runbot/templates/build.xml
+++ b/runbot/templates/build.xml
@@ -133,28 +133,45 @@
+ | ||
Build |
+ + | +
|