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/08/05 08:56:25 UTC

(tooling-trusted-releases) branch arm updated: #1488 - allow archiving project with archived releases

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

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


The following commit(s) were added to refs/heads/arm by this push:
     new fc8f7829 #1488 - allow archiving project with archived releases
fc8f7829 is described below

commit fc8f78297cf5a95e83e32c2ef86ad4b5981f0841
Author: Alastair McFarlane <ar...@apache.org>
AuthorDate: Wed Aug 5 09:55:55 2026 +0100

    #1488 - allow archiving project with archived releases
---
 atr/db/interaction.py | 15 ++++++++++++---
 atr/get/projects.py   | 10 +++++-----
 atr/post/projects.py  |  7 +++++--
 3 files changed, 22 insertions(+), 10 deletions(-)

diff --git a/atr/db/interaction.py b/atr/db/interaction.py
index bd126fd1..31b6bd46 100644
--- a/atr/db/interaction.py
+++ b/atr/db/interaction.py
@@ -565,12 +565,21 @@ def project_order_key(project: sql.Project, latest_release: datetime.datetime |
 
 async def project_release_counts(data: db.Session) -> dict[str, tuple[int, int]]:
     via = sql.validate_instrumented_attribute
-    non_draft_case = sqlalchemy.case((via(sql.Release.phase) != sql.ReleasePhase.RELEASE_CANDIDATE_DRAFT, 1), else_=0)
+    active_case = sqlalchemy.case(
+        (
+            sqlalchemy.and_(
+                via(sql.Release.phase) != sql.ReleasePhase.RELEASE_CANDIDATE_DRAFT,
+                via(sql.Release.is_archived).is_(False),
+            ),
+            1,
+        ),
+        else_=0,
+    )
     query = sqlmodel.select(
-        sql.Release.project_key, sqlalchemy.func.count(), sqlalchemy.func.sum(non_draft_case)
+        sql.Release.project_key, sqlalchemy.func.count(), sqlalchemy.func.sum(active_case)
     ).group_by(via(sql.Release.project_key))
     result = await data.execute(query)
-    return {key: (total, non_draft) for key, total, non_draft in result.all()}
+    return {key: (total, active) for key, total, active in result.all()}
 
 
 async def release_completed_svn_publish_task(
diff --git a/atr/get/projects.py b/atr/get/projects.py
index a0267b70..8c4d134d 100644
--- a/atr/get/projects.py
+++ b/atr/get/projects.py
@@ -188,7 +188,7 @@ async def projects(session: web.Committer, _projects: Literal["projects"]) -> st
             continue
         if project.committee and committee_project_counts[str(project.committee.key)] <= 1:
             continue
-        total_releases, non_draft_releases = release_counts.get(str(project.key), (0, 0))
+        total_releases, active_releases = release_counts.get(str(project.key), (0, 0))
         if total_releases == 0:
             action_forms[str(project.key)] = await form.render(
                 model_cls=shared.projects.DeleteSelectedProject,
@@ -203,7 +203,7 @@ async def projects(session: web.Committer, _projects: Literal["projects"]) -> st
                     " ready to delete only if the vote passes, and you must then return to complete it."
                 ),
             )
-        elif non_draft_releases == 0:
+        elif active_releases == 0:
             action_forms[str(project.key)] = await form.render(
                 model_cls=shared.projects.ArchiveSelectedProject,
                 action=util.as_url(post.projects.archive),
@@ -215,7 +215,7 @@ async def projects(session: web.Committer, _projects: Literal["projects"]) -> st
                 confirm=(
                     "This starts a binding CAP approval vote by the committee PMC. ATR will mark the project"
                     " ready to archive only if the vote passes, and you must then return to complete it, which"
-                    " deletes the draft releases and retires the project."
+                    " deletes any draft releases and retires the project."
                 ),
             )
 
@@ -553,7 +553,7 @@ async def _delete_form(project: sql.Project) -> htm.Element | None:
             ),
             empty=True,
         )
-    elif all(r.phase == sql.ReleasePhase.RELEASE_CANDIDATE_DRAFT for r in releases):
+    elif not any((r.phase != sql.ReleasePhase.RELEASE_CANDIDATE_DRAFT) and (not r.is_archived) for r in releases):
         delete_form = await form.render(
             model_cls=shared.projects.ArchiveSelectedProject,
             action=util.as_url(post.projects.archive),
@@ -565,7 +565,7 @@ async def _delete_form(project: sql.Project) -> htm.Element | None:
             confirm=(
                 "This starts a binding CAP approval vote by the committee PMC. ATR will mark the project"
                 " ready to archive only if the vote passes, and you must then return to complete it, which"
-                " deletes the draft releases and retires the project."
+                " deletes any draft releases and retires the project."
             ),
         )
     return delete_form
diff --git a/atr/post/projects.py b/atr/post/projects.py
index e6435353..6bb7f78a 100644
--- a/atr/post/projects.py
+++ b/atr/post/projects.py
@@ -188,8 +188,11 @@ def _action_eligibility_error(
         return None
     if (not completing) and (not releases):
         return f"Project '{project.key}' has no releases to archive."
-    if not all(r.phase == sql.ReleasePhase.RELEASE_CANDIDATE_DRAFT for r in releases):
-        return f"Project '{project.key}' has non-draft releases and cannot be archived."
+    active_releases = [
+        r for r in releases if (r.phase != sql.ReleasePhase.RELEASE_CANDIDATE_DRAFT) and (not r.is_archived)
+    ]
+    if active_releases:
+        return f"Project '{project.key}' has active releases and cannot be archived."
     if not completing:
         return None
     new_drafts = [r for r in releases if (requested_at is None) or (r.created > requested_at)]


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