diff --git a/runbot_merge/models/pull_requests.py b/runbot_merge/models/pull_requests.py
index 9c012089..988b21f8 100644
--- a/runbot_merge/models/pull_requests.py
+++ b/runbot_merge/models/pull_requests.py
@@ -900,6 +900,32 @@ class Stagings(models.Model):
# seems simpler than adding yet another indirection through a model
heads = fields.Char(required=True, help="JSON-encoded map of heads, one per repo in the project")
+ statuses = fields.Binary(compute='_compute_statuses')
+
+ @api.depends('heads')
+ def _compute_statuses(self):
+ """ Fetches statuses associated with the various heads, returned as
+ (repo, context, state, url)
+ """
+ Commits = self.env['runbot_merge.commit']
+ for st in self:
+ heads = {
+ head: repo for repo, head in json.loads(st.heads).items()
+ if not repo.endswith('^')
+ }
+ commits = Commits.search([('sha', 'in', list(heads.keys()))])
+ st.statuses = [
+ (
+ heads[commit.sha],
+ context,
+ status.get('state') or 'pending',
+ status.get('target_url') or ''
+ )
+ for commit in commits
+ for context, st in json.loads(commit.statuses).items()
+ for status in [to_status(st)]
+ ]
+
def _validate(self):
Commits = self.env['runbot_merge.commit']
for s in self:
diff --git a/runbot_merge/tests/local.py b/runbot_merge/tests/local.py
index abb06a14..db3b14dc 100644
--- a/runbot_merge/tests/local.py
+++ b/runbot_merge/tests/local.py
@@ -1,6 +1,10 @@
# -*- coding: utf-8 -*-
-import odoo
+
import pytest
+import werkzeug.test, werkzeug.wrappers
+
+import odoo
+
import fake_github
@pytest.fixture(scope='session')
@@ -96,6 +100,16 @@ def make_repo(gh, project):
])
])
return make_repo
+
+@pytest.fixture
+def page():
+ c = werkzeug.test.Client(odoo.http.root, werkzeug.wrappers.BaseResponse)
+ def get(url):
+ r = c.get(url)
+ assert r.status_code == 200
+ return r.data
+ return get
+
# TODO: project fixture
# TODO: repos (indirect/parameterize?) w/ WS hook
# + repo proxy object
diff --git a/runbot_merge/tests/remote.py b/runbot_merge/tests/remote.py
index 2e2b4f59..386de55b 100644
--- a/runbot_merge/tests/remote.py
+++ b/runbot_merge/tests/remote.py
@@ -93,6 +93,15 @@ def wait_for_hook(n=1):
# TODO: find better way to wait for roundtrip of actions which can trigger webhooks
time.sleep(10 * n)
+@pytest.fixture
+def page():
+ s = requests.Session()
+ def get(url):
+ r = s.get('http://localhost:{}{}'.format(PORT, url))
+ r.raise_for_status()
+ return r.content
+ return get
+
def wait_for_server(db, timeout=120):
""" Polls for server to be response & have installed our module.
diff --git a/runbot_merge/tests/test_basic.py b/runbot_merge/tests/test_basic.py
index 3ffdf23d..ac227aaf 100644
--- a/runbot_merge/tests/test_basic.py
+++ b/runbot_merge/tests/test_basic.py
@@ -6,6 +6,7 @@ import time
from unittest import mock
import pytest
+from lxml import html
import odoo
@@ -15,7 +16,7 @@ from test_utils import re_matches
def repo(make_repo):
return make_repo('repo')
-def test_trivial_flow(env, repo):
+def test_trivial_flow(env, repo, page):
# create base branch
m = repo.make_commit(None, "initial", None, tree={'a': 'some content'})
repo.make_ref('heads/master', m)
@@ -58,8 +59,24 @@ def test_trivial_flow(env, repo):
# get head of staging branch
staging_head = repo.commit('heads/staging.master')
- repo.post_status(staging_head.id, 'success', 'ci/runbot')
+ repo.post_status(staging_head.id, 'success', 'ci/runbot', target_url='http://foo.com/pog')
repo.post_status(staging_head.id, 'success', 'legal/cla')
+ # the should not block the merge because it's not part of the requirements
+ repo.post_status(staging_head.id, 'failure', 'ci/lint', target_url='http://ignored.com/whocares')
+
+ assert set(tuple(t) for t in pr.staging_id.statuses) == {
+ (repo.name, 'legal/cla', 'success', ''),
+ (repo.name, 'ci/runbot', 'success', 'http://foo.com/pog'),
+ (repo.name, 'ci/lint', 'failure', 'http://ignored.com/whocares'),
+ }
+ p = html.fromstring(page('/runbot_merge'))
+ s = p.cssselect('.staging div.dropdown li')
+ assert len(s) == 2
+ assert s[0].get('class') == 'bg-success'
+ assert s[0][0].text.strip() == '{}: ci/runbot'.format(repo.name)
+ assert s[1].get('class') == 'bg-danger'
+ assert s[1][0].text.strip() == '{}: ci/lint'.format(repo.name)
+
assert re.match('^force rebuild', staging_head.message)
env['runbot_merge.project']._check_progress()
diff --git a/runbot_merge/views/templates.xml b/runbot_merge/views/templates.xml
index 72ebcea8..f0982a65 100644
--- a/runbot_merge/views/templates.xml
+++ b/runbot_merge/views/templates.xml
@@ -5,7 +5,6 @@
.stagings {
display: flex;
align-items: stretch;
- overflow: hidden;
}
.stagings > li {
/* 4 to 6 stagings displayed, avoid stretching */
@@ -86,9 +85,9 @@