| {% extends "basebuildpage.html" %} |
| {% load humanize %} |
| {% load projecttags %} |
| {% load field_values_filter %} |
| |
| {% block title %} {{build.get_sorted_target_list|field_values:"target"|join:", "}} {{build.machine}} - {{build.project.name}} - Toaster {% endblock %} |
| {% block parentbreadcrumb %} |
| {% if build.get_sorted_target_list.count > 0 %} |
| {{build.get_sorted_target_list.0.target}} |
| {% endif %} |
| |
| {%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"}}) |
| {% endblock %} |
| |
| {% block buildinfomain %} |
| <!-- page title --> |
| <div class="{% if build.started %}col-md-10{% else %}col-md-12{% endif %}"> |
| <div class="page-header build-data"> |
| <h1>{{build.get_sorted_target_list|field_values:"target"|join:", "}} {{build.machine}}</h1> |
| </div> |
| |
| <!-- build result bar --> |
| <div class="alert {%if build.outcome == build.SUCCEEDED%}alert-success{%elif build.outcome == build.FAILED%}alert-danger{%else%}alert-info{%endif%}"> |
| <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> |
| {% if build.warnings.count or build.errors.count %} |
| <span>with</span> |
| {% endif %} |
| {%if build.outcome == build.SUCCEEDED or build.outcome == build.FAILED %} |
| {% if build.errors.count %} |
| <a href="#errors" class="alert-link show-errors"> {{build.errors.count}} error{{build.errors.count|pluralize}}</a> |
| {% endif %} |
| {% if build.warnings.count %} |
| {% if build.errors.count %}and{% endif %} |
| <a href="#warnings" class="show-warnings"> {{build.warnings.count}} warning{{build.warnings.count|pluralize}}</a> |
| {% endif %} |
| {% if build.cooker_log_path %} |
| <a class="pull-right log" href="{% url 'build_artifact' build.id "cookerlog" build.id %}">Download build log</a> |
| {% endif %} |
| <span class="pull-right"> |
| Build time: |
| <span data-build-field="buildtime"> |
| {% if build.outcome == build.SUCCEEDED %} |
| <a href="{% url 'buildtime' build.pk %}">{{ build.timespent_seconds|sectohms }}</a> |
| {% else %} |
| {{ build.timespent_seconds|sectohms }} |
| {% endif %} |
| </span> |
| </span> |
| |
| {%endif%} |
| </div> |
| |
| {% if build.errors.count %} |
| <div class="panel panel-default" id="errors"> |
| <div class="panel-heading"> |
| <h2 class="panel-title"> |
| <span class="glyphicon glyphicon-minus-sign"></span> |
| <a data-toggle="collapse" href="#error-info" id="error-toggle"> |
| {{build.errors.count}} error{{build.errors.count|pluralize}} |
| </a> |
| </h2> |
| </div> |
| <div class="panel-collapse collapse in" id="error-info"> |
| <div class="panel-body"> |
| <div class="{% if build.started %}col-md-10{% else %}col-md-12{% endif %}"> |
| {% for error in build.errors %} |
| <div class="alert alert-danger" data-log-message-id="{{error.pk}}"> |
| <pre>{{error.message}}</pre> |
| </div> |
| {% endfor %} |
| </div> |
| </div> |
| </div> |
| </div> |
| {% endif %} |
| |
| {%if build.outcome == build.SUCCEEDED%} |
| <!-- built images --> |
| {% if hasArtifacts %} |
| <h2 data-heading="build-artifacts">Build artifacts</h2> |
| {% for target in targets %} |
| {% if target.target.is_image %} |
| <div class="well well-transparent dashboard-section" data-artifacts-for-target="{{target.target.pk}}"> |
| {% if target.npkg > 0 %} |
| <h3> |
| <a href="{% url 'target' build.pk target.target.pk %}" data-link="target-packages"> |
| {{target.target.target}} |
| </a> |
| </h3> |
| <dl class="dl-horizontal"> |
| <dt>Packages included</dt> |
| <dd> |
| <a href="{% url 'target' build.pk target.target.pk %}"> |
| <span data-value="target-package-count">{{target.npkg}}</span> |
| </a> |
| </dd> |
| <dt>Total package size</dt> |
| <dd> |
| <span data-value="target-package-size">{{target.pkgsz|filtered_filesizeformat}}</span> |
| </dd> |
| </dl> |
| {% else %} |
| <h3>{{target.target.target}}</h3> |
| {% endif %} |
| |
| {% if target.targetHasImages %} |
| <dl class="dl-horizontal"> |
| <dt> |
| Manifests |
| </dt> |
| |
| <dd> |
| <a data-link="license-manifest" href="{% url 'build_artifact' build.pk 'licensemanifest' target.target.pk %}">License manifest</a> |
| </dd> |
| |
| {% if target.target.package_manifest_path %} |
| <dd> |
| <a data-link="package-manifest" href="{% url 'build_artifact' build.pk 'packagemanifest' target.target.pk %}">Package manifest</a> |
| </dd> |
| {% endif %} |
| </dl> |
| |
| <dl class="dl-horizontal"> |
| <dt> |
| <span class="glyphicon glyphicon-question-sign get-help" title="Image files are stored in <code>build/tmp/deploy/images/</code>"></span> |
| Image files |
| </dt> |
| <dd> |
| <ul class="list-unstyled" data-links="image-artifacts"> |
| {% for i in target.imageFiles|dictsort:"suffix" %} |
| <li> |
| <a href="{% url 'build_artifact' build.pk 'imagefile' i.id %}"> |
| {{i.suffix}} |
| </a> |
| ({{i.size|filtered_filesizeformat}}) |
| </li> |
| {% endfor %} |
| </ul> |
| </dd> |
| <dt> |
| Kernel artifacts |
| </dt> |
| <dd> |
| <ul class="list-unstyled" data-links="kernel-artifacts"> |
| {% for artifact in target.target_kernel_artifacts|dictsort:"basename" %} |
| <li> |
| <a href="{% url 'build_artifact' build.id 'targetkernelartifact' artifact.id %}">{{artifact.basename}}</a> |
| ({{artifact.file_size|filtered_filesizeformat}}) |
| </li> |
| {% endfor %} |
| </ul> |
| </dd> |
| </dl> |
| {% endif %} |
| {% if target.target_sdk_artifacts_count > 0 %} |
| <dl class="dl-horizontal"> |
| <dt> |
| SDK artifacts |
| </dt> |
| <dd> |
| <ul class="list-unstyled" data-links="sdk-artifacts"> |
| {% for artifact in target.target_sdk_artifacts|dictsort:"basename" %} |
| <li> |
| <a href="{% url 'build_artifact' build.id 'targetsdkartifact' artifact.id %}">{{artifact.basename}}</a> |
| ({{artifact.file_size|filtered_filesizeformat}}) |
| </li> |
| {% endfor %} |
| </ul> |
| </dd> |
| </dl> |
| {% endif %} |
| </div> |
| {% endif %} |
| {% endfor %} |
| {% endif %} |
| |
| {%else%} |
| <!-- error dump --> |
| {%endif%} |
| |
| <!-- other artifacts --> |
| {% if build.buildartifact_set.all.count > 0 %} |
| <h2>Other artifacts</h2> |
| |
| <div class="well well-transparent dashboard-section"> |
| <dl class="dl-horizontal"> |
| <dt> |
| <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> |
| Other artifacts</dt> |
| <dd><div> |
| {% for ba in build.buildartifact_set.all|dictsort:"file_name" %} |
| <a href="{%url 'build_artifact' build.id 'buildartifact' ba.id %}"> |
| {{ba.get_basename}} |
| </a> |
| |
| ({{ba.file_size|filtered_filesizeformat}}) <br/> |
| {% endfor %} |
| </div> |
| </dd> |
| </dl> |
| </div> |
| |
| {% endif %} |
| |
| {% if build.started %} |
| <!-- build summary --> |
| <h2 data-role="build-summary-heading">Build summary</h2> |
| <div class="row"> |
| <div class="col-md-4 dashboard-section"> |
| <div class="well well-transparent"> |
| <h3><a href="{%url 'configuration' build.pk%}">Configuration</a></h3> |
| <dl> |
| <dt>Machine</dt><dd>{{build.machine}}</dd> |
| <dt>Distro</dt><dd>{{build.distro}}</dd> |
| <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> |
| </dl> |
| </div> |
| </div> |
| <div class="col-md-4 dashboard-section"> |
| <div class="well well-transparent"> |
| <h3><a href="{%url 'tasks' build.pk%}">Tasks</a></h3> |
| <dl> |
| {% query build.task_build outcome=4 order__gt=0 as exectask%} |
| {% if exectask.count > 0 %} |
| <dt>Failed tasks</dt> |
| <dd> |
| {% if exectask.count == 1 %} |
| <a class="text-danger" href="{% url "task" build.id exectask.0.id %}"> |
| {{exectask.0.recipe.name}} |
| <span class="task-name">{{exectask.0.task_name}}</span> |
| </a> |
| |
| <a href="{% url 'build_artifact' build.id "tasklogfile" exectask.0.id %}"> |
| <span class="glyphicon glyphicon-download-alt get-help" title="Download task log file"></i> |
| </a> |
| |
| {% elif exectask.count > 1%} |
| <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> |
| {% endif %} |
| </dd> |
| {% endif %} |
| <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> |
| <dt> |
| Tasks executed |
| <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> |
| </dt> |
| <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> |
| <dt> |
| Tasks not executed |
| <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> |
| </dt> |
| <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> |
| <dt> |
| Reuse |
| <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> |
| </dt> |
| <dd> |
| {% query build.task_build order__gt=0 as texec %} |
| {% if noexectask.count|multiply:100|divide:texec.count < 0 %} |
| 0 |
| {% else %} |
| {{noexectask.count|multiply:100|divide:texec.count}} |
| {% endif %} |
| % |
| </dd> |
| </dl> |
| </div> |
| </div> |
| <div class="col-md-4 dashboard-section"> |
| <div class="well well-transparent"> |
| <h3><a href="{% url 'recipes' build.pk %}">Recipes</a> & <a href="{% url 'packages' build.pk %}">Packages</a></h3> |
| <dl> |
| <dt>Recipes built</dt><dd><a href="{% url 'recipes' build.pk %}">{{recipecount}}</a></dd> |
| <dt>Packages built</dt><dd><a href="{% url 'packages' build.pk %}">{{packagecount}}</a></dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| {% endif %} <!-- end build summary --> |
| |
| {% if build.warnings.count %} |
| <div class="panel panel-default" id="warnings"> |
| <div class="panel-heading"> |
| <h2 class="panel-title"> |
| <span class="glyphicon glyphicon-warning-sign"></span> |
| <a id="warning-toggle" href="#warning-info" data-toggle="collapse">{{build.warnings.count}} warning{{build.warnings.count|pluralize}}</a> |
| </h2> |
| </div> |
| <div class="panel-collapse collapse" id="warning-info"> |
| <div class="panel-body"> |
| <div class="{% if build.started %}col-md-10{% else %}col-md-12{% endif %}"> |
| {% for warning in logmessages %}{% if warning.level == 1 %} |
| <div class="alert alert-warning" data-log-message-id="{{warning.pk}}"> |
| <pre>{{warning.message}}</pre> |
| </div> |
| {% endif %}{% endfor %} |
| </div> |
| </div> |
| </div> |
| </div> |
| {% endif %} |
| |
| </div> <!-- end 10 column row --> |
| |
| <script type="text/javascript"> |
| $(document).ready(function() { |
| //show warnings section when requested from the previous page |
| if (location.href.search('#warnings') > -1) { |
| $('#warning-info').addClass('in'); |
| } |
| |
| //show warnings section when requested from the build outcome |
| $(".show-warnings").click(function() { |
| $('#warning-info').addClass('in'); |
| }); |
| }); |
| </script> |
| |
| {% endblock %} |