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]