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/08/07 17:30:38 UTC

(tooling-trusted-releases) branch sbp updated: Remove existing SVN files for test projects in test mode only

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 48845c01 Remove existing SVN files for test projects in test mode only
48845c01 is described below

commit 48845c01d0626af65ccd446c315334e9e03a6048
Author: Sean B. Palmer <se...@miscoranda.com>
AuthorDate: Fri Aug 7 18:29:50 2026 +0100

    Remove existing SVN files for test projects in test mode only
---
 atr/storage/writers/release.py | 28 ++++++++++++++++++++++++++++
 atr/storage/writers/vote.py    |  2 +-
 atr/svn/__init__.py            | 23 +++++++++++++++++++++++
 3 files changed, 52 insertions(+), 1 deletion(-)

diff --git a/atr/storage/writers/release.py b/atr/storage/writers/release.py
index 87f52617..14cdff87 100644
--- a/atr/storage/writers/release.py
+++ b/atr/storage/writers/release.py
@@ -1247,6 +1247,7 @@ class ReleaseManager(CommitteeParticipant):
             f"Released by {task_args.asf_uid} via ATR"
         )
 
+        await self.__remove_existing_publication_files(committee, preview_path, internal_url, task_args.asf_uid)
         try:
             revision = await svn.publish_release(preview_path.path, internal_url, task_args.asf_uid, log_message)
         except svn.CommandExecutionError as exc:
@@ -1294,6 +1295,33 @@ class ReleaseManager(CommitteeParticipant):
             message=f"Already published to SVN as r{revision}",
         )
 
+    async def __remove_existing_publication_files(
+        self,
+        committee: sql.Committee,
+        preview_path: safe.StatePath,
+        internal_url: str,
+        asf_uid: str,
+    ) -> None:
+        if not (config.is_test_mode() and (committee.key == "test")):
+            return
+        if config.svn_publish_kind() is not config.SvnPublishKind.LOCAL_REPOSITORY:
+            return
+        try:
+            existing = set(await svn.list_files(internal_url))
+        except svn.CommandExecutionError:
+            return
+        conflicts = [
+            str(rel_path) async for rel_path in util.paths_recursive(preview_path) if str(rel_path) in existing
+        ]
+        if not conflicts:
+            return
+        await svn.remove_files(
+            internal_url,
+            conflicts,
+            asf_uid,
+            "Remove previously published files before republishing\n\nTool: ATR",
+        )
+
 
 class CommitteeMember(ReleaseManager):
     def __init__(
diff --git a/atr/storage/writers/vote.py b/atr/storage/writers/vote.py
index bad4b873..bdb77206 100644
--- a/atr/storage/writers/vote.py
+++ b/atr/storage/writers/vote.py
@@ -407,7 +407,7 @@ class ReleaseManager(CommitteeParticipant):
                     raise storage.AccessError(
                         "Automatic SVN publish is only available in email and Trusted Vote modes", status=403
                     )
-                if self.__asf_uid not in committee.committee_members:
+                if not self.__write.authorisation.is_member_of(committee.key):
                     raise storage.AccessError("Automatic SVN publish requires a committee member initiator", status=403)
                 if automatic_publish_asf_uid is None:
                     automatic_publish_asf_uid = self.__asf_uid
diff --git a/atr/svn/__init__.py b/atr/svn/__init__.py
index 0858074b..a31a8346 100644
--- a/atr/svn/__init__.py
+++ b/atr/svn/__init__.py
@@ -299,6 +299,29 @@ async def publish_revision_matches(info: SvnInfo, author: str, message: str) ->
     return tool.strip() == ASF_TOOL
 
 
+async def remove_files(base_url: str, rel_paths: list[str], username: str, message: str) -> None:
+    log.debug(f"running svnmucc rm for user '{username}'")
+    svn_token = config.get().SVN_TOKEN
+    if svn_token is None:
+        raise ValueError("SVN_TOKEN must be set")
+    actions: list[str] = []
+    for rel_path in rel_paths:
+        actions.extend(["rm", f"{base_url}/{rel_path}"])
+    await _run_svnmucc_command(
+        *actions,
+        "--username",
+        username,
+        "--password",
+        svn_token,
+        "--non-interactive",
+        "--with-revprop",
+        f"asf:tool={ASF_TOOL}",
+        "-m",
+        message,
+        timeout_seconds=PUBLISH_TIMEOUT_SECONDS,
+    )
+
+
 async def run_command(cmd: str, *args: str, timeout_seconds: float | None = None) -> str:
     """Run a svn command asynchronously.
 


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