templates_buildsdir = $(templatesdir)/builds
+templates_builds_groupsdir = $(templates_buildsdir)/groups
+
+dist_templates_builds_groups_modules_DATA = \
+ src/templates/builds/groups/modules/list.html
+
+templates_builds_groups_modulesdir = $(templates_builds_groupsdir)/modules
+
dist_templates_builds_messages_DATA = \
src/templates/builds/messages/comment.txt \
src/templates/builds/messages/failed.txt \
return False
+ def has_failed(self):
+ """
+ Returns True if this build has failed
+ """
+ return self.has_finished() and self.data.failed
+
+ def is_successful(self):
+ """
+ Returns True if this build was successful
+ """
+ return self.has_finished() and not self.data.failed
+
def _send_email(self, *args, exclude=None, **kwargs):
"""
Convenience function which sends an email to everybody who would care
def __iter__(self):
return iter(self.builds)
+ def __len__(self):
+ return len(self.builds)
+
# UUID
@property
return list(builds)
+ @property
+ def successful_builds(self):
+ """
+ Returns all successful builds in this group
+ """
+ return [b for b in self.builds if b.is_successful()]
+
+ @property
+ def failed_builds(self):
+ """
+ Returns all failed builds in this group
+ """
+ return [b for b in self.builds if b.has_failed()]
+
# Delete
async def delete(self, user=None):
def deleted_at(self):
return self.data.deleted_at
+ # Functions to find out whether this was all successful/failed
+
+ def has_failed(self):
+ """
+ Returns True if at least one job has failed
+ """
+ return any((b.has_failed() for b in self.builds))
+
+ def is_successful(self):
+ """
+ Returns True if all jobs have been successful
+ """
+ return all((b.is_successful() for b in self.builds))
+
+ def has_finished(self):
+ """
+ Returns True if all builds have finished
+ """
+ return all((b.has_finished() for b in self.builds))
+
class Comments(base.Object):
def _get_comments(self, query, *args):
--- /dev/null
+<nav class="panel
+ {% if group.has_failed() %}
+ is-danger
+ {% elif group.is_successful() %}
+ is-success
+ {% end %}">
+ <p class="panel-heading">
+ XXX?
+
+ <span class="tags is-pulled-right">
+ {% if group.failed_builds %}
+ <span class="tag is-danger">
+ {{ _("%(num)s Failed", "%(num)s Failed", len(group.failed_builds)) \
+ % { "num" : len(group.failed_builds) } }}
+ </span>
+ {% end %}
+
+ {% if group.successful_builds %}
+ <span class="tag is-success">
+ {{ _("%(num)s Successful", "%(num)s Successful", len(group.successful_builds)) \
+ % { "num" : len(group.successful_builds) } }}
+ </span>
+ {% end %}
+ </span>
+ </p>
+
+ {% for build in group %}
+ <a class="panel-block" href="/builds/{{ build.uuid }}">
+ {% if build.has_failed() %}
+ <span class="panel-icon has-text-danger">
+ <i class="fas fa-xmark" aria-hidden="true"></i>
+ </span>
+ {% elif build.is_successful() %}
+ <span class="panel-icon has-text-success">
+ <i class="fas fa-check" aria-hidden="true"></i>
+ </span>
+ {% end %}
+
+ {{ build }}
+
+ {# Show which builds have failed (if any) #}
+ {% if build.has_failed() %}
+ {% for job in build.jobs %}
+ {% if job.is_aborted() %}
+ <span class="tag is-dark">{{ job.arch }}</span>
+ {% elif job.has_failed() %}
+ <span class="tag is-danger">{{ job.arch }}</span>
+ {% end %}
+ {% end %}
+ {% end %}
+ </a>
+ {% end %}
+
+ {# Show a button to see all builds in this group #}
+ {% if limit and limit < len(group) %}
+ {# XXX needs styling #}
+ <a class="panel-block" href="/builds/groups/{{ group.uuid }}">
+ {{ _("Show all") }}
+ </a>
+ {% end %}
+</nav>
</section>
{% end %}
+ {% if build.test_builds %}
+ <section class="section">
+ <h5 class="title is-5">{{ _("Test Builds")}}</h5>
+
+ {% module BuildGroupList(build.test_builds, limit=8) %}
+ </section>
+ {% end %}
+
{# Log #}
<section class="section">
<h5 class="title is-5">{{ _("Log") }}</h5>
# Builds
"BuildsList" : builds.ListModule,
+ # BuildGroups
+ "BuildGroupList" : builds.GroupListModule,
+
# Builders
"BuilderStats" : builders.StatsModule,
class ListModule(ui_modules.UIModule):
def render(self, builds):
return self.render_string("builds/modules/list.html", builds=builds)
+
+
+class GroupListModule(ui_modules.UIModule):
+ def render(self, group, limit=None):
+ return self.render_string("builds/groups/modules/list.html",
+ group=group, limit=limit)