You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tooling.apache.org by ar...@apache.org on 2026/04/13 10:22:22 UTC

(tooling-trusted-releases) 01/01: #1002 - Validate vote duration (and fix API recipient handling)

This is an automated email from the ASF dual-hosted git repository.

arm pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tooling-trusted-releases.git

commit f2672f18253c5b6e0ee754437323e9ca13979234
Author: Alastair McFarlane <ar...@apache.org>
AuthorDate: Mon Apr 13 11:03:50 2026 +0100

    #1002 - Validate vote duration (and fix API recipient handling)
---
 atr/api/__init__.py  | 5 +++++
 atr/get/voting.py    | 4 ++--
 atr/models/api.py    | 4 +++-
 atr/shared/voting.py | 6 ++++++
 atr/util.py          | 8 ++++++++
 5 files changed, 24 insertions(+), 3 deletions(-)

diff --git a/atr/api/__init__.py b/atr/api/__init__.py
index 003a0774..fcee20f2 100644
--- a/atr/api/__init__.py
+++ b/atr/api/__init__.py
@@ -1609,6 +1609,9 @@ async def vote_start(
             permitted_recipients = util.permitted_voting_recipients(asf_uid, wacp.committee_key)
             if data.email_to not in permitted_recipients:
                 raise exceptions.Forbidden("Invalid mailing list choice")
+
+            util.validate_email_recipients(data)
+            util.validate_vote_duration(data.vote_duration)
             # TODO: Get fullname and use instead of asf_uid
             task = await wacp.vote.start(
                 data.email_to,
@@ -1620,6 +1623,8 @@ async def vote_start(
                 data.body,
                 asf_uid,
                 asf_uid,
+                email_cc=data.email_cc,
+                email_bcc=data.email_bcc,
             )
     # except Exception as e:
     #     import traceback
diff --git a/atr/get/voting.py b/atr/get/voting.py
index 22c4ca3a..cdf2c054 100644
--- a/atr/get/voting.py
+++ b/atr/get/voting.py
@@ -71,8 +71,8 @@ async def selected_revision(
         permitted_recipients = util.permitted_voting_recipients(session.uid, committee.key)
 
         min_hours = 72
-        if release.release_policy and (release.release_policy.min_hours is not None):
-            min_hours = release.release_policy.min_hours
+        if release.project.release_policy and (release.project.release_policy.min_hours is not None):
+            min_hours = release.project.release_policy.min_hours
 
         default_subject_template = await construct.start_vote_subject_default(project_key)
         default_body_template = await construct.start_vote_default(project_key)
diff --git a/atr/models/api.py b/atr/models/api.py
index b0d27689..a623b2ca 100644
--- a/atr/models/api.py
+++ b/atr/models/api.py
@@ -613,7 +613,9 @@ class VoteStartArgs(schema.Strict):
     version: safe.VersionKey = schema.example("0.0.1")
     revision: safe.RevisionNumber = schema.example("00005")
     email_to: str = schema.example("dev@example.apache.org")
-    vote_duration: int = schema.example(10)
+    email_cc: list[str] = schema.default_example([], "[dev@example.apache.org]")
+    email_bcc: list[str] = schema.default_example([], "[dev@example.apache.org]")
+    vote_duration: int = schema.example(72)
     subject: str = schema.example("[VOTE] Apache Example 0.0.1 release")
     body: str = schema.example("The Apache Example team is pleased to announce the release of Example 0.0.1...")
 
diff --git a/atr/shared/voting.py b/atr/shared/voting.py
index dd44e20d..2ad1306e 100644
--- a/atr/shared/voting.py
+++ b/atr/shared/voting.py
@@ -34,6 +34,12 @@ class StartVotingForm(form.Form):
     subject_template_hash: str = form.label("Subject template hash", widget=form.Widget.HIDDEN)
     body: str = form.label("Body", widget=form.Widget.CUSTOM)
 
+    @pydantic.field_validator("vote_duration")
+    @classmethod
+    def validate_vote_duration(cls, field):
+        util.validate_vote_duration(field)
+        return field
+
     @pydantic.model_validator(mode="after")
     def _validate_recipients(self) -> "StartVotingForm":
         util.validate_email_recipients(self)
diff --git a/atr/util.py b/atr/util.py
index 7d5be1ab..77f3504f 100644
--- a/atr/util.py
+++ b/atr/util.py
@@ -1118,6 +1118,14 @@ def validate_trusted_publishing_constraints(
             raise ValueError("GitHub workflow paths must start with '.github/workflows/'.")
 
 
+def validate_vote_duration(duration: int):
+    if duration == 0:
+        return
+    if duration > 0:
+        if duration < 72 or duration > 168:
+            raise ValueError("Vote duration must be between 0 and 168")
+
+
 # TODO: AM put these rules into safe.versionkey
 def version_key_error(version_key: str) -> str | None:
     """Check if the given version name is valid."""


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@tooling.apache.org
For additional commands, e-mail: commits-help@tooling.apache.org