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-releases.git


The following commit(s) were added to refs/heads/main by this push:
     new fcdad6d7 Augment manual vote resolution validation
fcdad6d7 is described below

commit fcdad6d7d184ed58766897d0d17973f6f121f27d
Author: Dave Fisher <[email protected]>
AuthorDate: Mon Mar 2 13:07:02 2026 -0800

    Augment manual vote resolution validation
---
 atr/post/manual.py          | 20 +++++++++++---------
 atr/storage/writers/vote.py | 23 +++++++++++++++++------
 2 files changed, 28 insertions(+), 15 deletions(-)

diff --git a/atr/post/manual.py b/atr/post/manual.py
index c3c34612..9d001a04 100644
--- a/atr/post/manual.py
+++ b/atr/post/manual.py
@@ -71,7 +71,7 @@ async def resolve_selected(
             destination = get.compose.selected
 
     async with storage.write_as_project_committee_member(str(project_name)) as 
wacm:
-        success_message = await wacm.vote.resolve_manually(str(project_name), 
release, vote_result)
+        success_message = await wacm.vote.resolve_manually(str(project_name), 
str(version_name), vote_result)
 
     return await session.redirect(
         destination,
@@ -137,22 +137,24 @@ async def _committee_label(thread_id: str) -> str | None:
 
 
 async def _committees_check(vote_thread_url: str, vote_result_url: str) -> 
None:
-    vote_thread_id = 
vote_thread_url.removeprefix("https://lists.apache.org/thread/";)
-    result_thread_id = 
vote_result_url.removeprefix("https://lists.apache.org/thread/";)
-
+    # The two arguments to this function are guaranteed to begin with this 
prefix
+    # Validation was performed by the Pydantic field validator 
ResolveVoteForm.validate_urls
+    guaranteed_prefix = "https://lists.apache.org/thread/";
+    vote_thread_id = vote_thread_url.removeprefix(guaranteed_prefix)
     try:
         vote_committee_label = await _committee_label(vote_thread_id)
     except util.FetchError as e:
         raise RuntimeError(f"Failed to fetch vote thread metadata from URL 
{e.url}: {e!s}")
+    if vote_committee_label is None:
+        raise RuntimeError("Vote committee not found")
+
+    result_thread_id = vote_result_url.removeprefix(guaranteed_prefix)
     try:
         result_committee_label = await _committee_label(result_thread_id)
     except util.FetchError as e:
         raise RuntimeError(f"Failed to fetch vote thread metadata from URL 
{e.url}: {e!s}")
+    if result_committee_label is None:
+        raise RuntimeError("Result committee not found")
 
     if vote_committee_label != result_committee_label:
         raise RuntimeError("Vote committee and result committee do not match")
-
-    if vote_committee_label is None:
-        raise RuntimeError("Vote committee not found")
-    if result_committee_label is None:
-        raise RuntimeError("Result committee not found")
diff --git a/atr/storage/writers/vote.py b/atr/storage/writers/vote.py
index ecb4f03d..f61aa905 100644
--- a/atr/storage/writers/vote.py
+++ b/atr/storage/writers/vote.py
@@ -268,13 +268,24 @@ class CommitteeMember(CommitteeParticipant):
     async def resolve_manually(
         self,
         project_name: str,
-        release: sql.Release,
+        version_name: str,
         vote_result: Literal["passed", "failed"],
     ) -> str:
-        # Attach the existing release to the session
-        release = await self.__data.merge(release)
-        if release.phase != sql.ReleasePhase.RELEASE_CANDIDATE:
-            raise ValueError("Release is not in the candidate phase")
+        release = await self.__data.release(
+            name=sql.release_name(project_name, version_name),
+            phase=sql.ReleasePhase.RELEASE_CANDIDATE,
+            _project=True,
+            _committee=True,
+        ).demand(storage.AccessError("Release not found"))
+
+        if not release.vote_manual:
+            raise ValueError("Release is not configured for manual voting")
+
+        if release.vote_started is None:
+            raise ValueError("Vote has not been started")
+
+        if (release.project.committee is not None) and 
release.project.committee.is_podling:
+            raise ValueError("Podling releases require the standard two round 
vote process")
 
         if vote_result == "passed":
             release.phase = sql.ReleasePhase.RELEASE_PREVIEW
@@ -295,7 +306,7 @@ class CommitteeMember(CommitteeParticipant):
         self.__write_as.append_to_audit_log(
             asf_uid=self.__asf_uid,
             project_name=project_name,
-            version_name=release.version,
+            version_name=version_name,
             vote_result=vote_result,
         )
         return success_message


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

Reply via email to