1*4882a593Smuzhiyun{% extends "basebuildpage.html" %} 2*4882a593Smuzhiyun{% load humanize %} 3*4882a593Smuzhiyun{% load projecttags %} 4*4882a593Smuzhiyun{% load field_values_filter %} 5*4882a593Smuzhiyun 6*4882a593Smuzhiyun{% block title %} {{build.get_sorted_target_list|field_values:"target"|join:", "}} {{build.machine}} - {{build.project.name}} - Toaster {% endblock %} 7*4882a593Smuzhiyun{% block parentbreadcrumb %} 8*4882a593Smuzhiyun{% if build.get_sorted_target_list.count > 0 %} 9*4882a593Smuzhiyun {{build.get_sorted_target_list.0.target}} 10*4882a593Smuzhiyun{% endif %} 11*4882a593Smuzhiyun 12*4882a593Smuzhiyun{%if build.target_set.all.count > 1%}(+{{build.target_set.all.count|add:"-1"}}){%endif%} {{build.machine}} ({{build.completed_on|date:"d/m/y H:i"}}) 13*4882a593Smuzhiyun{% endblock %} 14*4882a593Smuzhiyun 15*4882a593Smuzhiyun{% block buildinfomain %} 16*4882a593Smuzhiyun<!-- page title --> 17*4882a593Smuzhiyun<div class="{% if build.started %}col-md-10{% else %}col-md-12{% endif %}"> 18*4882a593Smuzhiyun <div class="page-header build-data"> 19*4882a593Smuzhiyun <h1>{{build.get_sorted_target_list|field_values:"target"|join:", "}} {{build.machine}}</h1> 20*4882a593Smuzhiyun </div> 21*4882a593Smuzhiyun 22*4882a593Smuzhiyun<!-- build result bar --> 23*4882a593Smuzhiyun <div class="alert {%if build.outcome == build.SUCCEEDED%}alert-success{%elif build.outcome == build.FAILED%}alert-danger{%else%}alert-info{%endif%}"> 24*4882a593Smuzhiyun <span><strong>{%if build.outcome == build.SUCCEEDED%}Completed{%elif build.outcome == build.FAILED%}Failed{%else%}{%endif%}</strong> on {{build.completed_on|date:"d/m/y H:i"}}</span> 25*4882a593Smuzhiyun {% if build.warnings.count or build.errors.count %} 26*4882a593Smuzhiyun <span>with</span> 27*4882a593Smuzhiyun {% endif %} 28*4882a593Smuzhiyun {%if build.outcome == build.SUCCEEDED or build.outcome == build.FAILED %} 29*4882a593Smuzhiyun {% if build.errors.count %} 30*4882a593Smuzhiyun <a href="#errors" class="alert-link show-errors"> {{build.errors.count}} error{{build.errors.count|pluralize}}</a> 31*4882a593Smuzhiyun {% endif %} 32*4882a593Smuzhiyun {% if build.warnings.count %} 33*4882a593Smuzhiyun {% if build.errors.count %}and{% endif %} 34*4882a593Smuzhiyun <a href="#warnings" class="show-warnings"> {{build.warnings.count}} warning{{build.warnings.count|pluralize}}</a> 35*4882a593Smuzhiyun {% endif %} 36*4882a593Smuzhiyun {% if build.cooker_log_path %} 37*4882a593Smuzhiyun <a class="pull-right log" href="{% url 'build_artifact' build.id "cookerlog" build.id %}">Download build log</a> 38*4882a593Smuzhiyun {% endif %} 39*4882a593Smuzhiyun <span class="pull-right"> 40*4882a593Smuzhiyun Build time: 41*4882a593Smuzhiyun <span data-build-field="buildtime"> 42*4882a593Smuzhiyun {% if build.outcome == build.SUCCEEDED %} 43*4882a593Smuzhiyun <a href="{% url 'buildtime' build.pk %}">{{ build.timespent_seconds|sectohms }}</a> 44*4882a593Smuzhiyun {% else %} 45*4882a593Smuzhiyun {{ build.timespent_seconds|sectohms }} 46*4882a593Smuzhiyun {% endif %} 47*4882a593Smuzhiyun </span> 48*4882a593Smuzhiyun </span> 49*4882a593Smuzhiyun 50*4882a593Smuzhiyun {%endif%} 51*4882a593Smuzhiyun</div> 52*4882a593Smuzhiyun 53*4882a593Smuzhiyun{% if build.errors.count %} 54*4882a593Smuzhiyun <div class="panel panel-default" id="errors"> 55*4882a593Smuzhiyun <div class="panel-heading"> 56*4882a593Smuzhiyun <h2 class="panel-title"> 57*4882a593Smuzhiyun <span class="glyphicon glyphicon-minus-sign"></span> 58*4882a593Smuzhiyun <a data-toggle="collapse" href="#error-info" id="error-toggle"> 59*4882a593Smuzhiyun {{build.errors.count}} error{{build.errors.count|pluralize}} 60*4882a593Smuzhiyun </a> 61*4882a593Smuzhiyun </h2> 62*4882a593Smuzhiyun </div> 63*4882a593Smuzhiyun <div class="panel-collapse collapse in" id="error-info"> 64*4882a593Smuzhiyun <div class="panel-body"> 65*4882a593Smuzhiyun <div class="{% if build.started %}col-md-10{% else %}col-md-12{% endif %}"> 66*4882a593Smuzhiyun {% for error in build.errors %} 67*4882a593Smuzhiyun <div class="alert alert-danger" data-log-message-id="{{error.pk}}"> 68*4882a593Smuzhiyun <pre>{{error.message}}</pre> 69*4882a593Smuzhiyun </div> 70*4882a593Smuzhiyun {% endfor %} 71*4882a593Smuzhiyun </div> 72*4882a593Smuzhiyun </div> 73*4882a593Smuzhiyun </div> 74*4882a593Smuzhiyun </div> 75*4882a593Smuzhiyun{% endif %} 76*4882a593Smuzhiyun 77*4882a593Smuzhiyun{%if build.outcome == build.SUCCEEDED%} 78*4882a593Smuzhiyun<!-- built images --> 79*4882a593Smuzhiyun {% if hasArtifacts %} 80*4882a593Smuzhiyun <h2 data-heading="build-artifacts">Build artifacts</h2> 81*4882a593Smuzhiyun {% for target in targets %} 82*4882a593Smuzhiyun {% if target.target.is_image %} 83*4882a593Smuzhiyun <div class="well well-transparent dashboard-section" data-artifacts-for-target="{{target.target.pk}}"> 84*4882a593Smuzhiyun {% if target.npkg > 0 %} 85*4882a593Smuzhiyun <h3> 86*4882a593Smuzhiyun <a href="{% url 'target' build.pk target.target.pk %}" data-link="target-packages"> 87*4882a593Smuzhiyun {{target.target.target}} 88*4882a593Smuzhiyun </a> 89*4882a593Smuzhiyun </h3> 90*4882a593Smuzhiyun <dl class="dl-horizontal"> 91*4882a593Smuzhiyun <dt>Packages included</dt> 92*4882a593Smuzhiyun <dd> 93*4882a593Smuzhiyun <a href="{% url 'target' build.pk target.target.pk %}"> 94*4882a593Smuzhiyun <span data-value="target-package-count">{{target.npkg}}</span> 95*4882a593Smuzhiyun </a> 96*4882a593Smuzhiyun </dd> 97*4882a593Smuzhiyun <dt>Total package size</dt> 98*4882a593Smuzhiyun <dd> 99*4882a593Smuzhiyun <span data-value="target-package-size">{{target.pkgsz|filtered_filesizeformat}}</span> 100*4882a593Smuzhiyun </dd> 101*4882a593Smuzhiyun </dl> 102*4882a593Smuzhiyun {% else %} 103*4882a593Smuzhiyun <h3>{{target.target.target}}</h3> 104*4882a593Smuzhiyun {% endif %} 105*4882a593Smuzhiyun 106*4882a593Smuzhiyun {% if target.targetHasImages %} 107*4882a593Smuzhiyun <dl class="dl-horizontal"> 108*4882a593Smuzhiyun <dt> 109*4882a593Smuzhiyun Manifests 110*4882a593Smuzhiyun </dt> 111*4882a593Smuzhiyun 112*4882a593Smuzhiyun <dd> 113*4882a593Smuzhiyun <a data-link="license-manifest" href="{% url 'build_artifact' build.pk 'licensemanifest' target.target.pk %}">License manifest</a> 114*4882a593Smuzhiyun </dd> 115*4882a593Smuzhiyun 116*4882a593Smuzhiyun {% if target.target.package_manifest_path %} 117*4882a593Smuzhiyun <dd> 118*4882a593Smuzhiyun <a data-link="package-manifest" href="{% url 'build_artifact' build.pk 'packagemanifest' target.target.pk %}">Package manifest</a> 119*4882a593Smuzhiyun </dd> 120*4882a593Smuzhiyun {% endif %} 121*4882a593Smuzhiyun </dl> 122*4882a593Smuzhiyun 123*4882a593Smuzhiyun <dl class="dl-horizontal"> 124*4882a593Smuzhiyun <dt> 125*4882a593Smuzhiyun <span class="glyphicon glyphicon-question-sign get-help" title="Image files are stored in <code>build/tmp/deploy/images/</code>"></span> 126*4882a593Smuzhiyun Image files 127*4882a593Smuzhiyun </dt> 128*4882a593Smuzhiyun <dd> 129*4882a593Smuzhiyun <ul class="list-unstyled" data-links="image-artifacts"> 130*4882a593Smuzhiyun {% for i in target.imageFiles|dictsort:"suffix" %} 131*4882a593Smuzhiyun <li> 132*4882a593Smuzhiyun <a href="{% url 'build_artifact' build.pk 'imagefile' i.id %}"> 133*4882a593Smuzhiyun {{i.suffix}} 134*4882a593Smuzhiyun </a> 135*4882a593Smuzhiyun ({{i.size|filtered_filesizeformat}}) 136*4882a593Smuzhiyun </li> 137*4882a593Smuzhiyun {% endfor %} 138*4882a593Smuzhiyun </ul> 139*4882a593Smuzhiyun </dd> 140*4882a593Smuzhiyun <dt> 141*4882a593Smuzhiyun Kernel artifacts 142*4882a593Smuzhiyun </dt> 143*4882a593Smuzhiyun <dd> 144*4882a593Smuzhiyun <ul class="list-unstyled" data-links="kernel-artifacts"> 145*4882a593Smuzhiyun {% for artifact in target.target_kernel_artifacts|dictsort:"basename" %} 146*4882a593Smuzhiyun <li> 147*4882a593Smuzhiyun <a href="{% url 'build_artifact' build.id 'targetkernelartifact' artifact.id %}">{{artifact.basename}}</a> 148*4882a593Smuzhiyun ({{artifact.file_size|filtered_filesizeformat}}) 149*4882a593Smuzhiyun </li> 150*4882a593Smuzhiyun {% endfor %} 151*4882a593Smuzhiyun </ul> 152*4882a593Smuzhiyun </dd> 153*4882a593Smuzhiyun </dl> 154*4882a593Smuzhiyun {% endif %} 155*4882a593Smuzhiyun {% if target.target_sdk_artifacts_count > 0 %} 156*4882a593Smuzhiyun <dl class="dl-horizontal"> 157*4882a593Smuzhiyun <dt> 158*4882a593Smuzhiyun SDK artifacts 159*4882a593Smuzhiyun </dt> 160*4882a593Smuzhiyun <dd> 161*4882a593Smuzhiyun <ul class="list-unstyled" data-links="sdk-artifacts"> 162*4882a593Smuzhiyun {% for artifact in target.target_sdk_artifacts|dictsort:"basename" %} 163*4882a593Smuzhiyun <li> 164*4882a593Smuzhiyun <a href="{% url 'build_artifact' build.id 'targetsdkartifact' artifact.id %}">{{artifact.basename}}</a> 165*4882a593Smuzhiyun ({{artifact.file_size|filtered_filesizeformat}}) 166*4882a593Smuzhiyun </li> 167*4882a593Smuzhiyun {% endfor %} 168*4882a593Smuzhiyun </ul> 169*4882a593Smuzhiyun </dd> 170*4882a593Smuzhiyun </dl> 171*4882a593Smuzhiyun {% endif %} 172*4882a593Smuzhiyun </div> 173*4882a593Smuzhiyun {% endif %} 174*4882a593Smuzhiyun {% endfor %} 175*4882a593Smuzhiyun {% endif %} 176*4882a593Smuzhiyun 177*4882a593Smuzhiyun{%else%} 178*4882a593Smuzhiyun<!-- error dump --> 179*4882a593Smuzhiyun{%endif%} 180*4882a593Smuzhiyun 181*4882a593Smuzhiyun<!-- other artifacts --> 182*4882a593Smuzhiyun{% if build.buildartifact_set.all.count > 0 %} 183*4882a593Smuzhiyun<h2>Other artifacts</h2> 184*4882a593Smuzhiyun 185*4882a593Smuzhiyun <div class="well well-transparent dashboard-section"> 186*4882a593Smuzhiyun <dl class="dl-horizontal"> 187*4882a593Smuzhiyun <dt> 188*4882a593Smuzhiyun <span class="glyphicon glyphicon-question-sign get-help" title="Build artifacts discovered in <i>tmp/deploy/images</i>. Usually kernel images and kernel modules."></span> 189*4882a593Smuzhiyun Other artifacts</dt> 190*4882a593Smuzhiyun <dd><div> 191*4882a593Smuzhiyun {% for ba in build.buildartifact_set.all|dictsort:"file_name" %} 192*4882a593Smuzhiyun <a href="{%url 'build_artifact' build.id 'buildartifact' ba.id %}"> 193*4882a593Smuzhiyun {{ba.get_basename}} 194*4882a593Smuzhiyun </a> 195*4882a593Smuzhiyun 196*4882a593Smuzhiyun ({{ba.file_size|filtered_filesizeformat}}) <br/> 197*4882a593Smuzhiyun {% endfor %} 198*4882a593Smuzhiyun </div> 199*4882a593Smuzhiyun </dd> 200*4882a593Smuzhiyun </dl> 201*4882a593Smuzhiyun </div> 202*4882a593Smuzhiyun 203*4882a593Smuzhiyun{% endif %} 204*4882a593Smuzhiyun 205*4882a593Smuzhiyun{% if build.started %} 206*4882a593Smuzhiyun <!-- build summary --> 207*4882a593Smuzhiyun <h2 data-role="build-summary-heading">Build summary</h2> 208*4882a593Smuzhiyun <div class="row"> 209*4882a593Smuzhiyun <div class="col-md-4 dashboard-section"> 210*4882a593Smuzhiyun <div class="well well-transparent"> 211*4882a593Smuzhiyun <h3><a href="{%url 'configuration' build.pk%}">Configuration</a></h3> 212*4882a593Smuzhiyun <dl> 213*4882a593Smuzhiyun <dt>Machine</dt><dd>{{build.machine}}</dd> 214*4882a593Smuzhiyun <dt>Distro</dt><dd>{{build.distro}}</dd> 215*4882a593Smuzhiyun <dt>Layers</dt><dd><ul class="list-unstyled">{% for i in build.layer_version_build.all|dictsort:"layer.name" %}<li>{{i.layer.name}}</li>{%endfor%}</ul></dd> 216*4882a593Smuzhiyun </dl> 217*4882a593Smuzhiyun </div> 218*4882a593Smuzhiyun </div> 219*4882a593Smuzhiyun <div class="col-md-4 dashboard-section"> 220*4882a593Smuzhiyun <div class="well well-transparent"> 221*4882a593Smuzhiyun <h3><a href="{%url 'tasks' build.pk%}">Tasks</a></h3> 222*4882a593Smuzhiyun <dl> 223*4882a593Smuzhiyun {% query build.task_build outcome=4 order__gt=0 as exectask%} 224*4882a593Smuzhiyun {% if exectask.count > 0 %} 225*4882a593Smuzhiyun <dt>Failed tasks</dt> 226*4882a593Smuzhiyun <dd> 227*4882a593Smuzhiyun {% if exectask.count == 1 %} 228*4882a593Smuzhiyun <a class="text-danger" href="{% url "task" build.id exectask.0.id %}"> 229*4882a593Smuzhiyun {{exectask.0.recipe.name}} 230*4882a593Smuzhiyun <span class="task-name">{{exectask.0.task_name}}</span> 231*4882a593Smuzhiyun </a> 232*4882a593Smuzhiyun 233*4882a593Smuzhiyun <a href="{% url 'build_artifact' build.id "tasklogfile" exectask.0.id %}"> 234*4882a593Smuzhiyun <span class="glyphicon glyphicon-download-alt get-help" title="Download task log file"></i> 235*4882a593Smuzhiyun </a> 236*4882a593Smuzhiyun 237*4882a593Smuzhiyun {% elif exectask.count > 1%} 238*4882a593Smuzhiyun <a class="text-danger" href="{% url "tasks" build.id %}?limit=25&page=1&orderby=order&filter=task_outcome:failed&default_orderby=order&filter_value=on&">{{exectask.count}}</a> 239*4882a593Smuzhiyun {% endif %} 240*4882a593Smuzhiyun </dd> 241*4882a593Smuzhiyun {% endif %} 242*4882a593Smuzhiyun <dt>Total number of tasks</dt><dd><a href="{% url 'tasks' build.pk %}">{% query build.task_build order__gt=0 as alltasks %}{{alltasks.count}}</a></dd> 243*4882a593Smuzhiyun <dt> 244*4882a593Smuzhiyun Tasks executed 245*4882a593Smuzhiyun <span class="glyphicon glyphicon-question-sign get-help" title="'Executed' tasks are those that need to be run in order to generate the task output"></span> 246*4882a593Smuzhiyun </dt> 247*4882a593Smuzhiyun <dd><a href="{% url 'tasks' build.pk %}?limit=25&page=1&orderby=order&filter=execution_outcome:executed&default_orderby=order&filter_value=on&">{% query build.task_build task_executed=1 order__gt=0 as exectask%}{{exectask.count}}</a></dd> 248*4882a593Smuzhiyun <dt> 249*4882a593Smuzhiyun Tasks not executed 250*4882a593Smuzhiyun <span class="glyphicon glyphicon-question-sign get-help" title="'Not executed' tasks don't need to run because their outcome is provided by another task"></span> 251*4882a593Smuzhiyun </dt> 252*4882a593Smuzhiyun <dd><a href="{% url 'tasks' build.pk %}?limit=25&page=1&orderby=order&filter=execution_outcome:not_executed&default_orderby=order&filter_value=on&">{% query build.task_build task_executed=0 order__gt=0 as noexectask%}{{noexectask.count}}</a></dd> 253*4882a593Smuzhiyun <dt> 254*4882a593Smuzhiyun Reuse 255*4882a593Smuzhiyun <span class="glyphicon glyphicon-question-sign get-help" title="The percentage of 'not executed' tasks over the total number of tasks, which is a measure of the efficiency of your build"></span> 256*4882a593Smuzhiyun </dt> 257*4882a593Smuzhiyun <dd> 258*4882a593Smuzhiyun {% query build.task_build order__gt=0 as texec %} 259*4882a593Smuzhiyun {% if noexectask.count|multiply:100|divide:texec.count < 0 %} 260*4882a593Smuzhiyun 0 261*4882a593Smuzhiyun {% else %} 262*4882a593Smuzhiyun {{noexectask.count|multiply:100|divide:texec.count}} 263*4882a593Smuzhiyun {% endif %} 264*4882a593Smuzhiyun % 265*4882a593Smuzhiyun </dd> 266*4882a593Smuzhiyun </dl> 267*4882a593Smuzhiyun </div> 268*4882a593Smuzhiyun </div> 269*4882a593Smuzhiyun <div class="col-md-4 dashboard-section"> 270*4882a593Smuzhiyun <div class="well well-transparent"> 271*4882a593Smuzhiyun <h3><a href="{% url 'recipes' build.pk %}">Recipes</a> & <a href="{% url 'packages' build.pk %}">Packages</a></h3> 272*4882a593Smuzhiyun <dl> 273*4882a593Smuzhiyun <dt>Recipes built</dt><dd><a href="{% url 'recipes' build.pk %}">{{recipecount}}</a></dd> 274*4882a593Smuzhiyun <dt>Packages built</dt><dd><a href="{% url 'packages' build.pk %}">{{packagecount}}</a></dd> 275*4882a593Smuzhiyun </dl> 276*4882a593Smuzhiyun </div> 277*4882a593Smuzhiyun </div> 278*4882a593Smuzhiyun </div> 279*4882a593Smuzhiyun{% endif %} <!-- end build summary --> 280*4882a593Smuzhiyun 281*4882a593Smuzhiyun{% if build.warnings.count %} 282*4882a593Smuzhiyun <div class="panel panel-default" id="warnings"> 283*4882a593Smuzhiyun <div class="panel-heading"> 284*4882a593Smuzhiyun <h2 class="panel-title"> 285*4882a593Smuzhiyun <span class="glyphicon glyphicon-warning-sign"></span> 286*4882a593Smuzhiyun <a id="warning-toggle" href="#warning-info" data-toggle="collapse">{{build.warnings.count}} warning{{build.warnings.count|pluralize}}</a> 287*4882a593Smuzhiyun </h2> 288*4882a593Smuzhiyun </div> 289*4882a593Smuzhiyun <div class="panel-collapse collapse" id="warning-info"> 290*4882a593Smuzhiyun <div class="panel-body"> 291*4882a593Smuzhiyun <div class="{% if build.started %}col-md-10{% else %}col-md-12{% endif %}"> 292*4882a593Smuzhiyun {% for warning in logmessages %}{% if warning.level == 1 %} 293*4882a593Smuzhiyun <div class="alert alert-warning" data-log-message-id="{{warning.pk}}"> 294*4882a593Smuzhiyun <pre>{{warning.message}}</pre> 295*4882a593Smuzhiyun </div> 296*4882a593Smuzhiyun {% endif %}{% endfor %} 297*4882a593Smuzhiyun </div> 298*4882a593Smuzhiyun </div> 299*4882a593Smuzhiyun </div> 300*4882a593Smuzhiyun </div> 301*4882a593Smuzhiyun{% endif %} 302*4882a593Smuzhiyun 303*4882a593Smuzhiyun</div> <!-- end 10 column row --> 304*4882a593Smuzhiyun 305*4882a593Smuzhiyun<script type="text/javascript"> 306*4882a593Smuzhiyun $(document).ready(function() { 307*4882a593Smuzhiyun //show warnings section when requested from the previous page 308*4882a593Smuzhiyun if (location.href.search('#warnings') > -1) { 309*4882a593Smuzhiyun $('#warning-info').addClass('in'); 310*4882a593Smuzhiyun } 311*4882a593Smuzhiyun 312*4882a593Smuzhiyun //show warnings section when requested from the build outcome 313*4882a593Smuzhiyun $(".show-warnings").click(function() { 314*4882a593Smuzhiyun $('#warning-info').addClass('in'); 315*4882a593Smuzhiyun }); 316*4882a593Smuzhiyun }); 317*4882a593Smuzhiyun</script> 318*4882a593Smuzhiyun 319*4882a593Smuzhiyun{% endblock %} 320