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 17be8e9  Separate the lists of binding, committer, and other votes
17be8e9 is described below

commit 17be8e99ad4822ca2ee49fe62c6823cf9827b9b2
Author: Sean B. Palmer <[email protected]>
AuthorDate: Mon Jun 30 14:39:22 2025 +0100

    Separate the lists of binding, committer, and other votes
---
 atr/routes/vote.py | 46 ++++++++++++++++++++++++++++++++--------------
 1 file changed, 32 insertions(+), 14 deletions(-)

diff --git a/atr/routes/vote.py b/atr/routes/vote.py
index 6a3e8ca..3563375 100644
--- a/atr/routes/vote.py
+++ b/atr/routes/vote.py
@@ -19,6 +19,7 @@ import enum
 import json
 import logging
 import time
+from collections.abc import Generator
 
 import aiohttp
 import quart
@@ -476,33 +477,27 @@ def _tabulate_vote_resolution(
     outcome = "passed" if passed else "failed"
     body.append(f"The vote on {release.project.name} {release.version} 
{outcome}.")
     body.append("")
+
     body.append("The vote thread is archived at the following URL:")
     body.append("")
     body.append(f"https://lists.apache.org/thread/{thread_id}";)
     body.append("")
 
-    body.append("The votes were cast as follows:")
-    body.append("")
-    for vote_email in tabulated_votes.values():
-        match vote_email.vote:
-            case Vote.YES:
-                symbol = "+1"
-            case Vote.NO:
-                symbol = "-1"
-            case Vote.ABSTAIN:
-                symbol = "0"
-            case Vote.UNKNOWN:
-                symbol = "?"
-        body.append(f"{symbol} {vote_email.asf_uid_or_email} 
({vote_email.status.value.lower()})")
-    body.append("")
+    body.extend(_tabulate_vote_resolution_votes(tabulated_votes, 
{VoteStatus.BINDING}))
+
     binding_total = summary["binding_votes"]
     body.append(f"There were {binding_total} binding {'vote' if (binding_total 
== 1) else 'votes'}.")
     body.append("")
+
     binding_yes = summary["binding_votes_yes"]
     binding_no = summary["binding_votes_no"]
     binding_abstain = summary["binding_votes_abstain"]
     body.append(f"Of these binding votes, {binding_yes} were +1, {binding_no} 
were -1, and {binding_abstain} were 0.")
     body.append("")
+
+    body.extend(_tabulate_vote_resolution_votes(tabulated_votes, 
{VoteStatus.COMMITTER}))
+    body.extend(_tabulate_vote_resolution_votes(tabulated_votes, 
{VoteStatus.CONTRIBUTOR, VoteStatus.UNKNOWN}))
+
     body.append("Thank you for your participation.")
     body.append("")
     body.append("Sincerely,")
@@ -510,6 +505,29 @@ def _tabulate_vote_resolution(
     return "\n".join(body)
 
 
+def _tabulate_vote_resolution_votes(tabulated_votes: dict[str, VoteEmail], 
statuses: set[VoteStatus]) -> Generator[str]:
+    header: str | None = f"The {' and '.join(status.value.lower() for status 
in statuses)} votes were cast as follows:"
+    for vote_email in tabulated_votes.values():
+        if vote_email.status not in statuses:
+            continue
+        if header is not None:
+            yield header
+            yield ""
+            header = None
+        match vote_email.vote:
+            case Vote.YES:
+                symbol = "+1"
+            case Vote.NO:
+                symbol = "-1"
+            case Vote.ABSTAIN:
+                symbol = "0"
+            case Vote.UNKNOWN:
+                symbol = "?"
+        yield f"{symbol} {vote_email.asf_uid_or_email} 
({vote_email.status.value.lower()})"
+    if header is None:
+        yield ""
+
+
 async def _tabulate_vote_status(asf_uid: str, list_raw: str, committee: 
models.Committee | None) -> VoteStatus:
     status = VoteStatus.UNKNOWN
 


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to