This is an automated email from the ASF dual-hosted git repository.
sbp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tooling-trusted-release.git
The following commit(s) were added to refs/heads/main by this push:
new 6e8371d Only show the most recent check of each type
6e8371d is described below
commit 6e8371d85e37bc34ca39eb772bca2acc60d2d054
Author: Sean B. Palmer <[email protected]>
AuthorDate: Tue Mar 25 16:22:47 2025 +0200
Only show the most recent check of each type
---
atr/routes/files.py | 50 ++++++++++++++++++++++++++----------------
atr/templates/files-check.html | 14 ++++++------
atr/templates/files-list.html | 37 ++++++++++++++++++++++++++-----
3 files changed, 70 insertions(+), 31 deletions(-)
diff --git a/atr/routes/files.py b/atr/routes/files.py
index d515634..63afced 100644
--- a/atr/routes/files.py
+++ b/atr/routes/files.py
@@ -332,6 +332,27 @@ async def root_files_add_project(
)
+async def _get_recent_tasks_by_type(
+ data: db.Session, release_name: str, file_path: str, modified: int
+) -> dict[str, models.Task]:
+ """Get the most recent task for each task type for a specific file."""
+ tasks = await data.task(
+ release_name=release_name,
+ path=str(file_path),
+ modified=modified,
+ ).all()
+
+ # Group by task_type and keep the most recent one
+ # We use the highest id to determine the most recent task
+ recent_tasks: dict[str, models.Task] = {}
+ for task in tasks:
+ # If we haven't seen this task type before or if this task is newer
+ if (task.task_type not in recent_tasks) or (task.id >
recent_tasks[task.task_type].id):
+ recent_tasks[task.task_type] = task
+
+ return recent_tasks
+
+
@committer_route("/files/list/<project_name>/<version_name>")
async def root_files_list(session: CommitterSession, project_name: str,
version_name: str) -> str:
"""Show all the files in the rsync upload directory for a release."""
@@ -355,7 +376,7 @@ async def root_files_list(session: CommitterSession,
project_name: str, version_
path_warnings = {}
path_errors = {}
path_modified = {}
- path_tasks: dict[pathlib.Path, int] = {}
+ path_tasks: dict[pathlib.Path, dict[str, models.Task]] = {}
for path in paths:
# Get template and substitutions
elements = {
@@ -389,16 +410,9 @@ async def root_files_list(session: CommitterSession,
project_name: str, version_
full_path = str(util.get_candidate_draft_dir() / project_name /
version_name / path)
path_modified[path] = int(await aiofiles.os.path.getmtime(full_path))
- # Get tasks
- tasks = await data.task(
- release_name=f"{project_name}-{version_name}",
- path=str(path),
- modified=path_modified[path],
- ).all()
- path_tasks[path] = sum(
- 1
- for task in tasks
- if (task.status == models.TaskStatus.COMPLETED) or (task.status ==
models.TaskStatus.FAILED)
+ # Get the most recent task for each type
+ path_tasks[path] = await _get_recent_tasks_by_type(
+ data, f"{project_name}-{version_name}", str(path),
path_modified[path]
)
return await quart.render_template(
@@ -417,6 +431,7 @@ async def root_files_list(session: CommitterSession,
project_name: str, version_
errors=path_errors,
modified=path_modified,
tasks=path_tasks,
+ models=models,
)
@@ -442,15 +457,12 @@ async def root_files_checks(session: CommitterSession,
project_name: str, versio
modified = int(await aiofiles.os.path.getmtime(full_path))
file_size = await aiofiles.os.path.getsize(full_path)
- # Get the tasks for this file
- tasks = await data.task(
- release_name=f"{project_name}-{version_name}",
- path=str(file_path),
- modified=modified,
- ).all()
+ # Get the most recent task for each task type
+ recent_tasks = await _get_recent_tasks_by_type(data,
f"{project_name}-{version_name}", file_path, modified)
+
+ # Convert to a list for the template
+ tasks = list(recent_tasks.values())
- # This shows all tasks, including repeated tasks
- # TODO: Only show the most recent task for each task type
all_tasks_completed = all(
task.status in (models.TaskStatus.COMPLETED,
models.TaskStatus.FAILED) for task in tasks
)
diff --git a/atr/templates/files-check.html b/atr/templates/files-check.html
index d14cf17..1e3d97c 100644
--- a/atr/templates/files-check.html
+++ b/atr/templates/files-check.html
@@ -37,15 +37,15 @@
<div class="d-flex flex-wrap gap-3">
{% with %}
{% set status_counts = {
- 'completed': tasks|selectattr("status.value", "equalto",
"completed")|list|length,
- 'failed': tasks|selectattr("status.value", "equalto",
"failed")|list|length,
- 'active': tasks|selectattr("status.value", "equalto",
"active")|list|length,
- 'queued': tasks|selectattr("status.value", "equalto",
"queued")|list|length
+ "completed": tasks|selectattr("status.value", "equalto",
"completed")|list|length,
+ "failed": tasks|selectattr("status.value", "equalto",
"failed")|list|length,
+ "active": tasks|selectattr("status.value", "equalto",
"active")|list|length,
+ "queued": tasks|selectattr("status.value", "equalto",
"queued")|list|length
} %}
{% for status, count in status_counts.items() %}
{% if count > 0 %}
- <div class="d-flex align-items-center gap-2 px-3 py-2 rounded
fw-medium {% if status == 'completed' %}bg-success-subtle border
border-success-subtle {% elif status == 'failed' %}bg-danger-subtle border
border-danger-subtle {% elif status == 'active' %}bg-info-subtle border
border-info-subtle {% else %}bg-light border{% endif %}">
+ <div class="d-flex align-items-center gap-2 px-3 py-2 rounded
fw-medium {% if status == "completed" %}bg-success-subtle border
border-success-subtle {% elif status == "failed" %}bg-danger-subtle border
border-danger-subtle {% elif status == "active" %}bg-info-subtle border
border-info-subtle {% else %}bg-light border{% endif %}">
<span class="fs-5">{{ count }}</span>
<span>
{%- if status == "queued" -%}
@@ -81,7 +81,7 @@
<div class="border border-2 rounded p-3 mb-3">
<div class="d-flex justify-content-between align-items-center mb-2">
<span class="fw-bold">{{ task.task_type.replace('_', '
').replace("verify ", "").title() }}</span>
- <span class="badge rounded-pill {% if task.status.value ==
'queued' %}bg-secondary {% elif task.status.value == 'active' %}bg-info {% elif
task.status.value == 'completed' %}bg-success {% elif task.status.value ==
'failed' %}bg-danger {% else %}bg-secondary{% endif %}">
+ <span class="badge rounded-pill {% if task.status.value ==
"queued" %}bg-secondary {% elif task.status.value == "active" %}bg-info {% elif
task.status.value == "completed" %}bg-success {% elif task.status.value ==
"failed" %}bg-danger {% else %}bg-secondary{% endif %}">
{%- if task.status.value == "queued" -%}
Pending
{%- elif task.status.value == "active" -%}
@@ -106,7 +106,7 @@
<summary class="atr-cursor-pointer user-select-none
p-2">View detailed results</summary>
{% endif %}
- {% if task.task_type == 'verify_rat_license' and
task.result[0] is mapping %}
+ {% if task.task_type == "verify_rat_license" and
task.result[0] is mapping %}
<div class="d-flex gap-3 mb-2">
<span class="badge bg-success-subtle text-success-emphasis
border border-success-subtle px-2 py-1">
<strong>{{ task.result[0].approved_licenses }}</strong>
files with approved licenses
diff --git a/atr/templates/files-list.html b/atr/templates/files-list.html
index fbfb805..548a0c9 100644
--- a/atr/templates/files-list.html
+++ b/atr/templates/files-list.html
@@ -59,7 +59,7 @@
<th>Path</th>
<th>Warnings</th>
<th>Errors</th>
- <th>Tasks</th>
+ <th>Checks</th>
</tr>
</thead>
<tbody>
@@ -81,11 +81,38 @@
{% for error in errors[path] %}<div class="alert
alert-danger p-0 px-2 mt-2 mb-0">{{ error }}</div>{% endfor %}
</td>
<td>
- {% if path in tasks %}
- <a href="{{ url_for('root_files_checks',
project_name=project_name, version_name=version_name, file_path=path) }}"
- class="btn btn-sm btn-outline-primary">View {{
tasks[path] }} check(s)</a>
+ {% if path in tasks and tasks[path]|length > 0 %}
+ {% set completed_count = namespace(value=0) %}
+ {% set failed_count = namespace(value=0) %}
+ {% set active_count = namespace(value=0) %}
+ {% set queued_count = namespace(value=0) %}
+
+ {% for task_type, task in tasks[path].items() %}
+ {% if task.status.value == 'completed' %}
+ {% set completed_count.value = completed_count.value
+ 1 %}
+ {% elif task.status.value == 'failed' %}
+ {% set failed_count.value = failed_count.value + 1 %}
+ {% elif task.status.value == 'active' %}
+ {% set active_count.value = active_count.value + 1 %}
+ {% elif task.status.value == 'queued' %}
+ {% set queued_count.value = queued_count.value + 1 %}
+ {% endif %}
+ {% endfor %}
+
+ <div class="d-flex flex-wrap gap-2 mb-2">
+ {% if completed_count.value > 0 %}<span class="badge
bg-success">{{ completed_count.value }} Passed</span>{% endif %}
+ {% if failed_count.value > 0 %}
+ <span class="badge bg-danger">{{ failed_count.value
}} {{ "Issue" if failed_count.value == 1 else "Issues" }}</span>
+ {% endif %}
+ {% if active_count.value > 0 %}<span class="badge
bg-info">{{ active_count.value }} Running</span>{% endif %}
+ {% if queued_count.value > 0 %}<span class="badge
bg-secondary">{{ queued_count.value }} Pending</span>{% endif %}
+ </div>
+
+ <a href="{{ url_for('root_files_checks',
project_name=project_name, version_name=version_name, file_path=path) }}">
+ View all check results
+ </a>
{% else %}
- No tasks
+ No check results
{% endif %}
</td>
</tr>
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]