You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tooling.apache.org by sb...@apache.org on 2026/05/08 14:44:28 UTC

(tooling-trusted-releases) branch sbp updated: Note in the API when a first round podling vote is carried over

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

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


The following commit(s) were added to refs/heads/sbp by this push:
     new 751c2146 Note in the API when a first round podling vote is carried over
751c2146 is described below

commit 751c21463d20999988314ccf862ee4f74aa42d43
Author: Sean B. Palmer <se...@miscoranda.com>
AuthorDate: Fri May 8 15:44:02 2026 +0100

    Note in the API when a first round podling vote is carried over
---
 atr/api/__init__.py               |  1 +
 atr/models/api.py                 |  1 +
 tests/unit/test_vote_carryover.py | 44 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 46 insertions(+)

diff --git a/atr/api/__init__.py b/atr/api/__init__.py
index 6f4ad2ff..2e74555a 100644
--- a/atr/api/__init__.py
+++ b/atr/api/__init__.py
@@ -2009,6 +2009,7 @@ async def _vote_tabulate_trusted(
                 choice=detail.choice,
                 comment=detail.comment,
                 is_binding=detail.is_binding,
+                is_carried=detail.is_carried,
                 vote_round=detail.vote_round,
                 revision_number_at_cast=detail.revision_number_at_cast,
                 receipt_message_id=detail.receipt_message_id,
diff --git a/atr/models/api.py b/atr/models/api.py
index f6d4ea42..1c513ef7 100644
--- a/atr/models/api.py
+++ b/atr/models/api.py
@@ -696,6 +696,7 @@ class TrustedBallotEntry(schema.Strict):
     choice: sql.VoteChoice = schema.example(sql.VoteChoice.YES)
     comment: str = schema.default_example("", "Looks good to me")
     is_binding: bool = schema.example(True)
+    is_carried: bool = schema.default_example(False, False)
     vote_round: int | None = schema.default_example(None, 1)
     revision_number_at_cast: str = schema.example("00005")
     receipt_message_id: str = schema.example("102ed8a-503db792-79bc789-b8ca87ce@apache.org")
diff --git a/tests/unit/test_vote_carryover.py b/tests/unit/test_vote_carryover.py
index 3b88804d..a4937f38 100644
--- a/tests/unit/test_vote_carryover.py
+++ b/tests/unit/test_vote_carryover.py
@@ -16,6 +16,7 @@
 # under the License.
 
 import datetime
+import unittest.mock as mock
 from collections.abc import AsyncIterator
 from types import SimpleNamespace
 
@@ -24,6 +25,7 @@ import sqlalchemy
 import sqlalchemy.ext.asyncio
 import sqlmodel
 
+import atr.api
 import atr.db as db
 import atr.db.interaction as interaction
 import atr.models.sql as sql
@@ -44,6 +46,48 @@ async def sqlite_sessionmaker() -> AsyncIterator[sqlalchemy.ext.asyncio.async_se
     await engine.dispose()
 
 
+@pytest.mark.asyncio
+async def test_api_vote_tabulate_trusted_surfaces_is_carried_for_carried_ballot(
+    monkeypatch: pytest.MonkeyPatch,
+) -> None:
+    detail = interaction.TrustedBallotDetail(
+        cast_at=datetime.datetime(2026, 1, 1, tzinfo=datetime.UTC),
+        choice=sql.VoteChoice.YES,
+        comment="",
+        is_binding=True,
+        is_carried=True,
+        receipt_message_id="r1@apache.org",
+        revision_number_at_cast="00001",
+        status_label="Binding",
+        voter_asf_uid="ipmc",
+        voter_fullname="IPMC Member",
+        vote_round=1,
+    )
+    summary = interaction.TrustedVoteSummary(binding_votes_yes=1)
+    monkeypatch.setattr(atr.api.interaction, "effective_trusted_ballots", mock.AsyncMock(return_value=[]))
+    monkeypatch.setattr(
+        atr.api.interaction,
+        "trusted_ballot_details_from_ballots",
+        mock.AsyncMock(return_value=([detail], summary)),
+    )
+
+    release = SimpleNamespace(
+        key="myproject-1.0.0",
+        committee=SimpleNamespace(key="myproject", is_podling=True),
+        current_vote_seq=2,
+        podling_thread_id="thread-abc",
+    )
+
+    entries, _summary, _passed = await atr.api._vote_tabulate_trusted(release, is_trusted=True)
+
+    assert entries is not None
+    assert len(entries) == 1
+    entry = entries[0]
+    assert entry.is_carried is True
+    assert entry.vote_round == 1
+    assert entry.receipt_message_id == "r1@apache.org"
+
+
 @pytest.mark.asyncio
 async def test_effective_trusted_ballots_carries_ipmc_round_one_ballot(sqlite_sessionmaker) -> None:
     async with sqlite_sessionmaker() as data:


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