| Index: appengine/swarming/templates/user_task.html
|
| diff --git a/appengine/swarming/templates/user_task.html b/appengine/swarming/templates/user_task.html
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..c0e16bc139761cef22dce1447e5c97e2dbbd42c2
|
| --- /dev/null
|
| +++ b/appengine/swarming/templates/user_task.html
|
| @@ -0,0 +1,622 @@
|
| +{% extends "swarming/base.html" %}
|
| +
|
| +
|
| +{% block headers %}
|
| +<style>
|
| + h1 {
|
| + margin-top: 10px;
|
| + margin-bottom: 10px;
|
| + }
|
| +
|
| + h2 {
|
| + margin-top: 10px;
|
| + margin-bottom: 5px;
|
| + }
|
| +
|
| + h2.inline {
|
| + display: inline;
|
| + }
|
| +
|
| + table.property_table {
|
| + font-family: monospace;
|
| + border-spacing: 0;
|
| + }
|
| +
|
| + table.property_table tbody tr:nth-child(even) {
|
| + background-color: #eeeeee;
|
| + }
|
| +
|
| + table.property_table td {
|
| + padding-left: 0.5em;
|
| + padding-right: 0.5em;
|
| + }
|
| +
|
| + table.property_table tbody tr:hover {
|
| + background-color: #eeffee;
|
| + }
|
| +
|
| + table.property_table tbody tr td:first-child {
|
| + white-space: nowrap;
|
| + }
|
| +
|
| + .failed_test {
|
| + background-color: #ffdddd;
|
| + }
|
| +
|
| + .blink {
|
| + animation: blink 1s steps(5, start) infinite;
|
| + -webkit-animation: blink 1s steps(5, start) infinite;
|
| + }
|
| + @keyframes blink {
|
| + to { visibility: hidden; }
|
| + }
|
| + @-webkit-keyframes blink {
|
| + to { visibility: hidden; }
|
| + }
|
| +
|
| + .highlight_section {
|
| + background-color: #ffffee;
|
| + border-radius: 20px;
|
| + padding: 5px;
|
| + }
|
| +
|
| + .code {
|
| + font-family: monospace;
|
| + white-space: pre-wrap;
|
| + }
|
| +
|
| + .spaced {
|
| + margin-top: 10px;
|
| + margin-bottom: 5px;
|
| + }
|
| +
|
| + .package-list {
|
| + margin-left: 1em;
|
| + }
|
| +
|
| + .package-pin-name {
|
| + font-weight: bold;
|
| + }
|
| +
|
| + .package-pin-version {
|
| + color: blue;
|
| + }
|
| +</style>
|
| +{% endblock %}
|
| +
|
| +
|
| +{% block body %}
|
| +{% import 'swarming/bot_view.html' as bot_view %}
|
| +
|
| +
|
| +{% macro summarize_array(values) %}
|
| + {% if not values %}
|
| + ‑‑
|
| + {% else %}
|
| + {{values|sum|filesizeformat}} total; {{values|length}} items;
|
| + {% if values|length <= 10 %}
|
| + ({{values|map('filesizeformat')|join('; ')}})
|
| + {% else %}
|
| + ({{values[0]|filesizeformat}}; {{values[1]|filesizeformat}}; {{values[2]|filesizeformat}}; {{values[3]|filesizeformat}}; {{values[4]|filesizeformat}}; ...; {{values[-5]|filesizeformat}}; {{values[-4]|filesizeformat}}; {{values[-3]|filesizeformat}}; {{values[-2]|filesizeformat}}; {{values[-1]|filesizeformat}})
|
| + {% endif %}
|
| + {% endif %}
|
| +{% endmacro %}
|
| +
|
| +
|
| +<h1>Task summary</h1>
|
| +<a href="/oldui/user/tasks">Back to tasks list</a>
|
| +<br/>
|
| +<h1>THIS UI WILL GO AWAY ON JAN 1, 2017. If it has something you need and the new UI doesn't have it, file a bug ASAP. </h1>
|
| +<a href="{{try_link}}">Try out the new task page UI</a>
|
| +<p>
|
| +
|
| +<div title="Information about the request itself that doesn't include what is being run; it's about the context and description.">
|
| + <h2>Request metadata</h2>
|
| + <table class="property_table">
|
| + <tbody>
|
| + <tr title="Name of the task, used for display purpose only.">
|
| + <td>Name</td>
|
| + <td>{{request.name}}</td>
|
| + </tr>
|
| + <tr title="Who triggered this task, as reported by the client.">
|
| + <td>User</td>
|
| + <td>
|
| + {% if request.user %}
|
| + {{request.user}}
|
| + {% else %}
|
| + ‑‑
|
| + {% endif %}
|
| + </td>
|
| + </tr>
|
| + <tr title="Authenticated credential used by the client to trigger this task.">
|
| + <td>Authenticated</td>
|
| + <td>
|
| + {# The only reason for this condition is to not crash on older
|
| + entities. #}
|
| + {% if request.authenticated %}
|
| + {{request.authenticated.to_bytes()}}
|
| + {% else %}
|
| + ‑‑
|
| + {% endif %}
|
| + </td>
|
| + </tr>
|
| + <tr title="What credentials that task is using when calling other services.">
|
| + <td>Running as</td>
|
| + <td>
|
| + {% if request.service_account and request.service_account != 'none' %}
|
| + {{request.service_account}}
|
| + {% else %}
|
| + ‑‑
|
| + {% endif %}
|
| + </td>
|
| + </tr>
|
| + <tr title="Task priority is between 1 and 255, lower value is higher priority. Higher priority requests are executed first.">
|
| + <td>Priority</td>
|
| + <td>{{request.priority}}</td>
|
| + </tr>
|
| + <tr title="When the request was done by the client.">
|
| + <td>Created</td>
|
| + <td>{{request.created_ts|datetimeformat}}</td>
|
| + </tr>
|
| + <tr title="When this request becomes so old it's not even worth handing to a bot. It may happen to low priority on a busy fleet.">
|
| + <td>Expiration</td>
|
| + <td>
|
| + {{request.expiration_ts|datetimeformat}}
|
| + ({{(request.expiration_ts-request.created_ts)|timedeltaformat}})
|
| + </td>
|
| + </tr>
|
| + <tr title="Tags used for searching and/or analyzing groups of tasks.">
|
| + <td>Tags</td>
|
| + <td>{{request.tags|join('<br>'|safe)}}</td>
|
| + </tr>
|
| + {% if request.pubsub_topic %}
|
| + <tr title="PubSub topic notified about task completion.">
|
| + <td>Pubsub topic</td>
|
| + <td>{{request.pubsub_topic}}</td>
|
| + </tr>
|
| + <tr title="Data passed along with PubSub notification.">
|
| + <td>Pubsub data</td>
|
| + <td>
|
| + {% if request.pubsub_userdata %}
|
| + {{request.pubsub_userdata}}
|
| + {% else %}
|
| + ‑‑
|
| + {% endif %}
|
| + </td>
|
| + </tr>
|
| + {% endif %}
|
| + <tr title="Parent task that created this task.">
|
| + <td>Parent task</td>
|
| + <td>
|
| + {% if parent_task %}
|
| + <a href="/oldui/user/task/{{parent_task.task_id}}">{{parent_task.name}}</a>
|
| + {% else %}
|
| + ‑‑
|
| + {% endif %}
|
| + </td>
|
| + </tr>
|
| + </tbody>
|
| + </table>
|
| +</div>
|
| +
|
| +<div title="Information about what was asked to be run. This is what is used for task deduplication.">
|
| + {% if request.properties.is_terminate %}
|
| + <div class="spaced">
|
| + <h2 class="inline">Bot termination request</h2>
|
| + </div>
|
| + <table class="property_table">
|
| + <tbody>
|
| + <tr title="The request dimensions is the minimum set of properties a bot must advertise to be able to execute this task.">
|
| + <td>Bot</td>
|
| + <td>{{request.properties.dimensions['id']}}</td>
|
| + </tr>
|
| + </tbody>
|
| + </table>
|
| + {% else %}
|
| + <div class="spaced">
|
| + <h2 class="inline">Request properties</h2>
|
| + {% if is_privileged_user %}
|
| + <form method="POST" action="/oldui/user/task/{{task.task_id}}/retry" style="display:inline">
|
| + <input type="submit" value="Retry" style="display:inline"></input>
|
| + <input type="hidden" name="xsrf_token" value="{{xsrf_token}}" />
|
| + </form>
|
| + {% endif %}
|
| + </div>
|
| + <table class="property_table">
|
| + <tbody>
|
| + <tr title="The request dimensions is the minimum set of properties a bot must advertise to be able to execute this task.">
|
| + <td>Request dims</td>
|
| + <td>{{bot_view.render_dict(request.properties.dimensions)}}</td>
|
| + </tr>
|
| + <tr title="The maximum number of seconds that the command may use, otherwise it is forcibly killed.">
|
| + <td>Exec timeout</td>
|
| + <td>{{request.properties.execution_timeout_secs}}</td>
|
| + </tr>
|
| + <tr title="The maximum number of seconds that the command may not output any stdout in a single shot.">
|
| + <td>I/O timeout</td>
|
| + <td>{{request.properties.io_timeout_secs}}</td>
|
| + </tr>
|
| + <tr title="Additional environment variables to the one provided by the bot.">
|
| + <td>Env vars</td>
|
| + <td>{{bot_view.render_dict(request.properties.env)}}</td>
|
| + </tr>
|
| + <tr title="If True, successful task results may be reused for subsequent requests, so the task can be deduped.">
|
| + <td>Idempotent</td>
|
| + <td>{{request.properties.idempotent}}</td>
|
| + </tr>
|
| + {% if cipd %}
|
| + <tr title="CIPD server">
|
| + <td>CIPD server</td>
|
| + <td>{{cipd.server}}</td>
|
| + </tr>
|
| + <tr title="CIPD client">
|
| + <td>CIPD client</td>
|
| + <td>{{cipd.client_package}}</td>
|
| + </tr>
|
| + {% if cipd.packages %}
|
| + <tr title="CIPD packages">
|
| + <td>CIPD packages</td>
|
| + <td>
|
| + {% for path, packages in cipd.packages %}
|
| + <div>{{path or '.'}}/</div>
|
| + <div class="package-list">
|
| + {{packages|join('<br>'|safe)}}
|
| + </div>
|
| + {% endfor %}
|
| + </td>
|
| + </tr>
|
| + {% endif %}
|
| + {% endif %}
|
| +
|
| + {% if request.properties.caches %}
|
| + <tr title="Named caches">
|
| + <td>Named caches</td>
|
| + <td>
|
| + {% for cache in request.properties.caches %}
|
| + <div>
|
| + <span>{{cache.name}}</span>:<span>{{cache.path}}</span>
|
| + </div>
|
| + {% endfor %}
|
| + </td>
|
| + </tr>
|
| + {% endif %}
|
| +
|
| + {% if request.properties.inputs_ref and request.properties.inputs_ref.isolated %}
|
| + <tr title="Inputs files">
|
| + <td>Isolated inputs</td>
|
| + <td>
|
| + <a
|
| + href="{{request.properties.inputs_ref.isolatedserver}}/browse?namespace={{request.properties.inputs_ref.namespace}}&hash={{request.properties.inputs_ref.isolated}}">
|
| + {{request.properties.inputs_ref.isolated}}
|
| + </a>
|
| + </td>
|
| + </tr>
|
| + <tr title="Extra arguments if applicable">
|
| + <td>Extra args</td>
|
| + <td>
|
| + {{request.properties.extra_args|join(' ')}}<br>
|
| + </td>
|
| + </tr>
|
| + <tr title="Expected output files">
|
| + <td>Expected outputs</td>
|
| + <td>
|
| + {% for output in request.properties.outputs %}
|
| + {{output}}<br/>
|
| + {% endfor %}
|
| + </td>
|
| + </tr>
|
| + {% else %}
|
| + {# Raw command #}
|
| + <tr title="Actual command executed by the bot.">
|
| + <td>Commands</td>
|
| + <td>
|
| + {% if request.properties.commands %}
|
| + {{request.properties.commands[0]|join(' ')}}<br>
|
| + {% elif request.properties.command %}
|
| + {{request.properties.command|join(' ')}}<br>
|
| + {% else %}
|
| + ‑‑
|
| + {% endif %}
|
| + </td>
|
| + </tr>
|
| + {% endif %}
|
| + <tr title="Secret bytes">
|
| + <td>Secret bytes</td>
|
| + <td>
|
| + {% if request.properties.has_secret_bytes %}
|
| + <strong><REDACTED></strong>
|
| + {% else %}
|
| + ‑‑
|
| + {% endif %}
|
| + </td>
|
| + </tr>
|
| + </tbody>
|
| + </table>
|
| + {% endif %}
|
| +</div>
|
| +
|
| +<div title="Information about the result: the task was run where (which bot), when and what is the result.">
|
| + <h2>Execution</h2>
|
| + <table class="property_table">
|
| + <tbody>
|
| + <tr title="The previous task executed by this bot before this task, if any.">
|
| + <td>Previous task</td>
|
| + <td>
|
| + {% if previous_task %}
|
| + <a href="/oldui/user/task/{{previous_task.task_id}}">
|
| + ← {{previous_task.name}}
|
| + </a>
|
| + {% else %}
|
| + ‑‑
|
| + {% endif %}
|
| + </td>
|
| + </tr>
|
| + <tr title="Link to the bot that executed this task, if any.">
|
| + <td>Bot</td>
|
| + <td>{{bot_view.bot_link(task.bot_id, is_privileged_user)}}</td>
|
| + </tr>
|
| + <tr title="The next task executed by this bot, if any.">
|
| + <td>Following task</td>
|
| + <td>
|
| + {% if following_task %}
|
| + <a href="/oldui/user/task/{{following_task.task_id}}">
|
| + {{following_task.name}} →
|
| + </a>
|
| + {% else %}
|
| + ‑‑
|
| + {% endif %}
|
| + </td>
|
| + </tr>
|
| + <tr class="{% if task.is_exceptional %}failed_test{% endif%}"
|
| + title="Current state of the task, may be pending, running, completed, bot_died, expired, canceled.">
|
| + <td>State</td>
|
| + <td>
|
| + {{task.to_string()}} ({{task.state}})
|
| + {% if task.can_be_canceled %}
|
| + <form id="cancel" method="POST"
|
| + action="/oldui/user/task/{{task.task_id}}/cancel"
|
| + style="display:inline">
|
| + <input type="hidden" name="xsrf_token" value="{{xsrf_token}}" />
|
| + <input type="submit" value="Cancel" style="display:inline"></input>
|
| + </form>
|
| + {% endif %}
|
| + </td>
|
| + </tr>
|
| + <tr title="When the bot was handed this task.">
|
| + <td>Started</td>
|
| + <td>{{task.started_ts|datetimeformat}}</td>
|
| + </tr>
|
| + <tr title="When the task was completed, if done.">
|
| + <td>Completed</td>
|
| + <td>{{task.completed_ts|datetimeformat}}</td>
|
| + </tr>
|
| + <tr title="Moment where the task was declared a failure by the server due to internal error or expiration.">
|
| + <td>Abandoned</td>
|
| + <td>
|
| + {{task.abandoned_ts|datetimeformat}}
|
| + {% if task.abandoned_ts %}
|
| + {% if task.started_ts %}
|
| + ({{(task.abandoned_ts-task.started_ts)|timedeltaformat}} since task started)
|
| + {% else %}
|
| + ({{(task.abandoned_ts-request.created_ts)|timedeltaformat}} since task request)
|
| + {% endif %}
|
| + {% endif %}
|
| + </td>
|
| + </tr>
|
| + <tr class="{% if task.exit_code %}failed_test{% endif%}"
|
| + title="Process exit code for each commands executed on the bot.">
|
| + <td>Exit code</td>
|
| + <td>{{task.exit_code}}</td>
|
| + </tr>
|
| + <tr title="Outputs files">
|
| + <td>Isolated outputs</td>
|
| + <td>
|
| + {% if task.outputs_ref %}
|
| + <a
|
| + href="{{task.outputs_ref.isolatedserver}}/browse?namespace={{task.outputs_ref.namespace}}&hash={{task.outputs_ref.isolated}}">
|
| + {{task.outputs_ref.isolated}}
|
| + </a>
|
| + {% else %}
|
| + ‑‑
|
| + {% endif %}
|
| + </td>
|
| + </tr>
|
| + <tr title="Children tasks that were created by this task.">
|
| + <td>Children tasks</td>
|
| + <td>
|
| + {% if children_tasks %}
|
| + {% for children in children_tasks %}
|
| + <a href="/oldui/user/task/{{children.task_id}}">{{children.name}}</a>
|
| + <br>
|
| + {% endfor %}
|
| + {% else %}
|
| + ‑‑
|
| + {% endif %}
|
| + </td>
|
| + </tr>
|
| + <tr title="This task was not executed, results from the task listed here were reused as-is.">
|
| + <td>
|
| + {% if task.deduped_from %}
|
| + <strong>Was deduped from</strong>
|
| + {% else %}
|
| + Was deduped from
|
| + {% endif %}
|
| + </td>
|
| + <td>
|
| + {% if task.deduped_from %}
|
| + <a href="/oldui/user/task/{{task.deduped_from}}">{{task.deduped_from}}</a>
|
| + {% else %}
|
| + ‑‑
|
| + {% endif %}
|
| + </td>
|
| + </tr>
|
| + <tr class="{% if task.internal_failure %}failed_test{% endif%}"
|
| + title="True if an internal Swarming error occured for this task. A BSOD is considered an internal failure.">
|
| + <td>Internal failure</td>
|
| + <td>{{task.internal_failure}}</td>
|
| + </tr>
|
| + <tr title="A task may be tried 2 times. This list the try number starting at 1.">
|
| + <td>Try number</td>
|
| + <td>{{task.try_number}}</td>
|
| + </tr>
|
| + <tr title="Last time this bot sent an update about this task.">
|
| + <td>Last updated</td>
|
| + <td>{{(now-task.modified_ts)|timedeltaformat}} ago</td>
|
| + </tr>
|
| + <tr title="Current bot dimensions.">
|
| + <td>Bot dimensions</td>
|
| + <td>
|
| + {% if task.bot_dimensions %}
|
| + {{bot_view.render_dict(task.bot_dimensions)}}
|
| + {% else %}
|
| + {{bot_view.bot_dimensions(bot)}}
|
| + {% endif %}
|
| + </td>
|
| + </tr>
|
| + {% if cipd_pins %}
|
| + <tr title="CIPD client">
|
| + <td>CIPD client</td>
|
| + <td>{{cipd_pins.client_package}}</td>
|
| + </tr>
|
| + {% if cipd_pins.packages %}
|
| + <tr title="CIPD packages">
|
| + <td>CIPD packages</td>
|
| + <td>
|
| + {% for path, packages in cipd_pins.packages %}
|
| + <div>{{path or '.'}}/</div>
|
| + <div class="package-list">
|
| + {{packages|join('<br>'|safe)}}
|
| + </div>
|
| + {% endfor %}
|
| + </td>
|
| + </tr>
|
| + {% endif %}
|
| + {% endif %}
|
| + <tr title="Current bot version. TODO(maruel): List bot version at time of task reaping.">
|
| + <td>Bot version</td>
|
| + <td>{{task.bot_version}}</td>
|
| + </tr>
|
| + <tr title="List of server versions that touched this task.">
|
| + <td>Server version</td>
|
| + <td>
|
| + {% for v in task.server_versions %}
|
| + {% if is_gae_admin %}
|
| + <a href="https://appengine.google.com/logs?&app_id={{full_appid}}&version_id={{v}}">
|
| + {{v}}
|
| + </a>
|
| + {% else %}
|
| + {{v}}
|
| + {% endif %}
|
| + {% endfor %}
|
| + </td>
|
| + </tr>
|
| + </tbody>
|
| + </table>
|
| +</div>
|
| +
|
| +<div title="Information about how fast we got the results.">
|
| + <h2>Performance</h2>
|
| + <table class="property_table">
|
| + <tbody>
|
| + <tr title="Time between when the request was done and the bot started the task.">
|
| + <td>Pending time</td>
|
| + <td>
|
| + {{bot_view.pending_star(task)}}{{task.pending_now(now)|timedeltaformat(include_ms=True)}}
|
| + </td>
|
| + </tr>
|
| + <tr title="Duration of the task, up to now if the task is still on-going.">
|
| + <td>Duration </td>
|
| + <td>{{task.duration_now(now)|timedeltaformat(include_ms=True)}}</td>
|
| + </tr>
|
| + {% if task.performance_stats_key %}
|
| + <tr title="Overhead from installing CIPD packages">
|
| + <td>Overhead CIPD packages</td>
|
| + <td>{{task.overhead_package_installation|timedeltaformat(include_ms=True)}}</td>
|
| + </tr>
|
| + <tr title="Overhead from installing isolated inputs">
|
| + <td>Overhead isolated inputs</td>
|
| + <td>{{task.overhead_isolated_inputs|timedeltaformat(include_ms=True)}}</td>
|
| + </tr>
|
| + <tr title="Overhead from pushing isolated outputs">
|
| + <td>Overhead isolated outputs</td>
|
| + <td>{{task.overhead_isolated_outputs|timedeltaformat(include_ms=True)}}</td>
|
| + </tr>
|
| + {% endif %}
|
| + <tr title="Overhead from task_runner This is bot side overheads excluding isolated setup and teardown.">
|
| + <td>Overhead bot (miscellaneous)</td>
|
| + <td>{{task.overhead_task_runner|timedeltaformat(include_ms=True)}}</td>
|
| + </tr>
|
| + <tr title="Overhead from server<-> communication. Includes DB access.">
|
| + <td>Overhead server<->bot communication</td>
|
| + <td>{{task.overhead_server|timedeltaformat(include_ms=True)}}</td>
|
| + </tr>
|
| + <tr title="Cost of running this task, as reported by the bot, if applicable.">
|
| + {% if task.cost_saved_usd %}
|
| + <td>$ USD saved</td>
|
| + <td>
|
| + <span style="color:green">{{task.cost_saved_usd|round(4) }} $</span>
|
| + </td>
|
| + {% else %}
|
| + <td>$ USD</td>
|
| + <td>
|
| + {% if task.cost_usd %}
|
| + {{task.cost_usd|round(5) }} $
|
| + {% else %}
|
| + ‑‑
|
| + {% endif %}
|
| + </td>
|
| + {% endif %}
|
| + </tr>
|
| + {% if task.performance_stats.is_valid %}
|
| + <tr title="Size of the bot cache before this task started. This cache permits to reduce the amount of items downloaded.">
|
| + <td>Initial bot cache</td>
|
| + <td>{{task.performance_stats.isolated_download.initial_size or 0|filesizeformat}} total; {{task.performance_stats.isolated_download.initial_number_items or 0}} items</td>
|
| + </tr>
|
| + <tr title="Items found in the cache so the bot didn't have to download these before starting the task. This means these items are used by multiple tasks.">
|
| + <td>Task inputs: Hot items</td>
|
| + <td>{{summarize_array(task.performance_stats.isolated_download.items_hot_array)}}</td>
|
| + </tr>
|
| + <tr title="Items missing from the cache, so they had to be downloaded before the task could start.">
|
| + <td>Task inputs: Cold items (i.e. downloaded)</td>
|
| + <td>{{summarize_array(task.performance_stats.isolated_download.items_cold_array)}}</td>
|
| + </tr>
|
| + <tr title="Task outputs (via ISOLATED_OUTDIR) that were already on the isolated server.">
|
| + <td>Task results: Hot items</td>
|
| + <td>{{summarize_array(task.performance_stats.isolated_upload.items_hot_array)}}</td>
|
| + </tr>
|
| + <tr title="Task outputs (via ISOLATED_OUTDIR) that were missing from the isolated server.">
|
| + <td>Task results: Cold items (i.e. uploaded)</td>
|
| + <td>{{summarize_array(task.performance_stats.isolated_upload.items_cold_array)}}</td>
|
| + </tr>
|
| + {% endif %}
|
| + </tbody>
|
| + </table>
|
| +</div>
|
| +
|
| +<br>
|
| +<div class=highlight_section>
|
| +<h2>Help</h2>
|
| +{% if request.properties.inputs_ref and request.properties.inputs_ref.isolated %}
|
| +<div>Download inputs files into directory <i>foo</i>:</div>
|
| +<div class=code> python isolateserver.py download -I {{request.properties.inputs_ref.isolatedserver}} --namespace {{request.properties.inputs_ref.namespace}} -s {{request.properties.inputs_ref.isolated}} --target foo</div>
|
| +<br>
|
| +{%endif%}
|
| +<div>Run this task locally:</div>
|
| +<div class=code> python swarming.py reproduce -S {{host_url}} {{task.task_id}}</div>
|
| +<br>
|
| +<div>Download output results into directory <i>foo</i>:</div>
|
| +<div class=code> python swarming.py collect -S {{host_url}} --task-output-dir=foo {{task.task_id}}</div>
|
| +<br>
|
| +<div>Looking for <i>swarming.py</i>?</div>
|
| +<div class=code> git clone https://github.com/luci/client-py</div>
|
| +</div>
|
| +
|
| +{% set output = task.get_output() %}
|
| +{% if output is not none %}
|
| +<h3>Output:</h3>
|
| +<pre>
|
| +{{task.get_output().decode('utf-8', 'replace')}}{% if is_running %}<p class="console"><span class="blink">|</span>{% endif %}
|
| +</pre>
|
| +{% endif %}
|
| +
|
| +{% endblock %}
|
|
|