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 24a3c90 Restore the information about a vote thread
24a3c90 is described below
commit 24a3c90f0895b771123c818ee3bfbb90e7c20f44
Author: Sean B. Palmer <[email protected]>
AuthorDate: Mon May 5 17:02:49 2025 +0100
Restore the information about a vote thread
---
atr/routes/compose.py | 4 ++
atr/routes/resolve.py | 51 ------------------
atr/routes/vote.py | 65 ++++++++++++++++++++++-
atr/templates/check-selected-candidate-forms.html | 3 ++
atr/templates/check-selected-vote-email.html | 45 ++++++++++++++++
5 files changed, 116 insertions(+), 52 deletions(-)
diff --git a/atr/routes/compose.py b/atr/routes/compose.py
index 5dc69fe..95822ee 100644
--- a/atr/routes/compose.py
+++ b/atr/routes/compose.py
@@ -38,6 +38,8 @@ async def check(
release: models.Release,
task_mid: str | None = None,
form: wtforms.Form | None = None,
+ archive_url: str | None = None,
+ vote_task: models.Task | None = None,
) -> response.Response | str:
base_path = util.release_directory(release)
@@ -82,6 +84,8 @@ async def check(
task_mid=task_mid,
form=form,
resolve_form=resolve_form,
+ vote_task=vote_task,
+ archive_url=archive_url,
)
diff --git a/atr/routes/resolve.py b/atr/routes/resolve.py
index 87eedfc..07b3041 100644
--- a/atr/routes/resolve.py
+++ b/atr/routes/resolve.py
@@ -16,10 +16,7 @@
# under the License.
import json
-import logging
-import os
-import httpx
import quart
import werkzeug.wrappers.response as response
import wtforms
@@ -207,51 +204,3 @@ async def _send_resolution(
await data.flush()
await data.commit()
return None
-
-
-async def _task_archive_url(task_mid: str) -> str | None:
- if "@" not in task_mid:
- return None
-
- # TODO: This List ID will be dynamic when we allow posting to arbitrary
lists
- lid = "user-tests.tooling.apache.org"
- url =
f"https://lists.apache.org/api/email.lua?id=%3C{task_mid}%3E&listid=%3C{lid}%3E"
- try:
- async with httpx.AsyncClient() as client:
- response = await client.get(url)
- response.raise_for_status()
- email_data = response.json()
- mid = email_data["mid"]
- if not isinstance(mid, str):
- return None
- return "https://lists.apache.org/thread/" + mid
- except Exception:
- logging.exception("Failed to get archive URL for task %s", task_mid)
- return None
-
-
-async def _task_archive_url_cached(task_mid: str | None) -> str | None:
- if "LOCAL_DEBUG" in os.environ:
- return
"https://lists.apache.org/thread/619hn4x796mh3hkk3kxg1xnl48dy2s64"
- if task_mid is None:
- return None
- if "@" not in task_mid:
- return None
-
- async with db.session() as data:
- url = await data.ns_text_get(
- "mid-url-cache",
- task_mid,
- )
- if url is not None:
- return url
-
- url = await _task_archive_url(task_mid)
- if url is not None:
- await data.ns_text_set(
- "mid-url-cache",
- task_mid,
- url,
- )
-
- return url
diff --git a/atr/routes/vote.py b/atr/routes/vote.py
index 540af6e..3928b38 100644
--- a/atr/routes/vote.py
+++ b/atr/routes/vote.py
@@ -15,6 +15,11 @@
# specific language governing permissions and limitations
# under the License.
+import json
+import logging
+import os
+
+import httpx
import quart
import werkzeug.wrappers.response as response
import wtforms
@@ -49,12 +54,22 @@ async def selected(session: routes.CommitterSession,
project_name: str, version_
project_name, version_name, with_committee=True, with_tasks=True,
phase=models.ReleasePhase.RELEASE_CANDIDATE
)
latest_vote_task = resolve.release_latest_vote_task(release)
+ archive_url = None
task_mid = None
if latest_vote_task is not None:
+ # Move task_mid_get here?
task_mid = resolve.task_mid_get(latest_vote_task)
+ archive_url = await _task_archive_url_cached(task_mid)
+
+ if ("LOCAL_DEBUG" in os.environ) and (latest_vote_task is not None):
+ logging.warning("LOCAL_DEBUG: Setting vote task to completed")
+ latest_vote_task.status = models.TaskStatus.COMPLETED
+ latest_vote_task.result = [json.dumps({"mid":
"[email protected]"})]
form = await CastVoteForm.create_form()
- return await compose.check(session, release, task_mid=task_mid, form=form)
+ return await compose.check(
+ session, release, task_mid=task_mid, form=form,
archive_url=archive_url, vote_task=latest_vote_task
+ )
@routes.committer("/vote/<project_name>/<version_name>", methods=["POST"])
@@ -135,3 +150,51 @@ async def _send_vote(
await data.commit()
return email_recipient, ""
+
+
+async def _task_archive_url(task_mid: str) -> str | None:
+ if "@" not in task_mid:
+ return None
+
+ # TODO: This List ID will be dynamic when we allow posting to arbitrary
lists
+ lid = "user-tests.tooling.apache.org"
+ url =
f"https://lists.apache.org/api/email.lua?id=%3C{task_mid}%3E&listid=%3C{lid}%3E"
+ try:
+ async with httpx.AsyncClient() as client:
+ response = await client.get(url)
+ response.raise_for_status()
+ email_data = response.json()
+ mid = email_data["mid"]
+ if not isinstance(mid, str):
+ return None
+ return "https://lists.apache.org/thread/" + mid
+ except Exception:
+ logging.exception("Failed to get archive URL for task %s", task_mid)
+ return None
+
+
+async def _task_archive_url_cached(task_mid: str | None) -> str | None:
+ if "LOCAL_DEBUG" in os.environ:
+ return
"https://lists.apache.org/thread/619hn4x796mh3hkk3kxg1xnl48dy2s64"
+ if task_mid is None:
+ return None
+ if "@" not in task_mid:
+ return None
+
+ async with db.session() as data:
+ url = await data.ns_text_get(
+ "mid-url-cache",
+ task_mid,
+ )
+ if url is not None:
+ return url
+
+ url = await _task_archive_url(task_mid)
+ if url is not None:
+ await data.ns_text_set(
+ "mid-url-cache",
+ task_mid,
+ url,
+ )
+
+ return url
diff --git a/atr/templates/check-selected-candidate-forms.html
b/atr/templates/check-selected-candidate-forms.html
index edc2fc2..f7e0848 100644
--- a/atr/templates/check-selected-candidate-forms.html
+++ b/atr/templates/check-selected-candidate-forms.html
@@ -6,6 +6,9 @@
<strong>TODO:</strong> We plan to make "Binding" dynamic based on
membership. Currently this form always says "Binding" which is known to be
wrong.
</div>
</div>
+
+{% include "check-selected-vote-email.html" %}
+
<form method="post"
action="{{ as_url(routes.vote.selected_post, project_name=project_name,
version_name=version_name) }}"
class="atr-canary py-4 px-5 mb-4 border rounded">
diff --git a/atr/templates/check-selected-vote-email.html
b/atr/templates/check-selected-vote-email.html
new file mode 100644
index 0000000..dfd01e6
--- /dev/null
+++ b/atr/templates/check-selected-vote-email.html
@@ -0,0 +1,45 @@
+
+<div class="p-3 border rounded bg-white mb-3">
+ {% if vote_task %}
+ {% if vote_task.status.value == "completed" %}
+ <p class="mb-0 text-success fw-semibold">
+ <i class="bi bi-check-circle me-1"></i> Vote thread started: {{
format_datetime(vote_task.completed) }}
+ </p>
+ {% if task_mid %}
+ <p class="mt-2 mb-0 text-muted ps-4">
+ Message-ID: <code class="user-select-all">{{ task_mid }}</code>
+ </p>
+ {% endif %}
+ {% elif vote_task.status.value == "failed" %}
+ <p class="mb-1 text-danger fw-semibold">
+ <i class="bi bi-x-circle me-1"></i> Vote thread failed: {{
format_datetime(vote_task.completed) }}
+ </p>
+ <div class="alert alert-danger mt-2 mb-0 p-2" role="alert">
+ <p class="mb-0 p-2 text-danger">{{ vote_task.error }}</p>
+ </div>
+ {% else %}
+ <p class="mb-0 text-warning fw-semibold">
+ <i class="bi bi-hourglass-split me-1"></i> Vote thread task status: {{
vote_task.status.value.upper() }}
+ {% if vote_task.started %}
+ (Started: {{ format_datetime(vote_task.started) }})
+ {% else %}
+ (Added: {{ format_datetime(vote_task.added) }})
+ {% endif %}
+ </p>
+ {% endif %}
+ {% if archive_url %}
+ <p class="mt-2 mb-0 text-muted ps-4">
+ <a href="{{ archive_url }}"
+ rel="noopener"
+ target="_blank"
+ title="View vote email thread in the archive (opens in new
window)">View vote email thread in the archive <i class="bi
bi-box-arrow-up-right ms-1"></i></a>
+ </p>
+ {% elif task_mid %}
+ <p class="mt-2 mb-0 text-muted ps-4">Could not retrieve archive URL for
this message.</p>
+ {% endif %}
+ {% else %}
+ <p class="mb-0 text-muted">
+ <i class="bi bi-question-circle me-1"></i> Vote email: No vote
initiation task found for this release.
+ </p>
+ {% endif %}
+</div>
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]