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


The following commit(s) were added to refs/heads/main by this push:
     new 7ba7f46  List existing versions on the page to start a new release
7ba7f46 is described below

commit 7ba7f46f5e2b61c039f4b76e47ac9f6fbad2ff00
Author: Sean B. Palmer <[email protected]>
AuthorDate: Wed Sep 10 14:34:52 2025 +0100

    List existing versions on the page to start a new release
---
 atr/db/interaction.py             | 18 ++++++++++++++++++
 atr/routes/start.py               |  6 +++++-
 atr/templates/start-selected.html | 37 +++++++++++++++++++++++++++++++++++++
 pyproject.toml                    |  1 +
 uv.lock                           |  2 ++
 5 files changed, 63 insertions(+), 1 deletion(-)

diff --git a/atr/db/interaction.py b/atr/db/interaction.py
index e8d968f..f7a8dad 100644
--- a/atr/db/interaction.py
+++ b/atr/db/interaction.py
@@ -25,6 +25,7 @@ from typing import Any, Final
 import aiofiles.os
 import aioshutil
 import asfquart.base as base
+import packaging.version as version
 import quart
 import sqlalchemy
 import sqlmodel
@@ -79,6 +80,23 @@ class TrustedProjectPhase(enum.Enum):
     FINISH = "finish"
 
 
+async def all_releases(project: sql.Project) -> list[sql.Release]:
+    """Get all releases for the project, sorted by version."""
+    query = sqlmodel.select(sql.Release).where(sql.Release.project_name == 
project.name)
+
+    results = []
+    async with db.session() as data:
+        for result in (await data.execute(query)).all():
+            release = result[0]
+            results.append(release)
+
+    for release in results:
+        release.project = project
+
+    results.sort(key=lambda r: version.Version(r.version), reverse=True)
+    return results
+
+
 async def candidate_drafts(project: sql.Project) -> list[sql.Release]:
     """Get the candidate drafts for the project."""
     return await releases_by_phase(project, 
sql.ReleasePhase.RELEASE_CANDIDATE_DRAFT)
diff --git a/atr/routes/start.py b/atr/routes/start.py
index 8df425c..70e452a 100644
--- a/atr/routes/start.py
+++ b/atr/routes/start.py
@@ -22,6 +22,7 @@ import quart
 import werkzeug.wrappers.response as response
 
 import atr.db as db
+import atr.db.interaction as interaction
 import atr.forms as forms
 import atr.models.sql as sql
 import atr.revision as revision
@@ -128,5 +129,8 @@ async def selected(session: routes.CommitterSession, 
project_name: str) -> respo
             # Flash the error and let the code fall through to render the 
template below
             await quart.flash(str(e), "error")
 
+    # Get all releases for the project
+    releases = await interaction.all_releases(project)
+
     # Render the template for GET requests or POST requests with validation 
errors
-    return await template.render("start-selected.html", project=project, 
form=form, routes=routes)
+    return await template.render("start-selected.html", project=project, 
form=form, routes=routes, releases=releases)
diff --git a/atr/templates/start-selected.html 
b/atr/templates/start-selected.html
index fe55db7..a755fbb 100644
--- a/atr/templates/start-selected.html
+++ b/atr/templates/start-selected.html
@@ -39,4 +39,41 @@
     </div>
   </form>
 
+  {% if releases %}
+    {% set max_revisions = 18 %}
+    <div class="mt-5">
+      <h2>Existing releases</h2>
+      <div class="row">
+        <div class="col-12">
+          <ul class="list-unstyled row g-3">
+            {% for release in releases[:max_revisions] %}
+              <li class="col-6 col-sm-4 col-md-3 col-lg-2">
+                <div class="text-nowrap">
+                  {% if release.phase.value == "release_candidate_draft" %}
+                    <span class="atr-phase-one atr-phase-symbol fs-6">{{ "①" 
}}</span>
+                  {% elif release.phase.value == "release_candidate" %}
+                    <span class="atr-phase-two atr-phase-symbol fs-6">{{ "②" 
}}</span>
+                  {% elif release.phase.value == "release_preview" %}
+                    <span class="atr-phase-three atr-phase-symbol fs-6">{{ "③" 
}}</span>
+                  {% elif release.phase.value == "release" %}
+                    <span class="atr-phase-symbol fs-6">{{ "Ⓡ" }}</span>
+                  {% endif %}
+                  {{ release.version }}
+                </div>
+              </li>
+            {% endfor %}
+            {% if releases|length > max_revisions %}
+              <li class="col-6 col-sm-4 col-md-3 col-lg-2">
+                <div class="text-center">
+                  <strong>...</strong>
+                  <span class="text-muted ms-1">{{ releases|length - 
max_revisions }} more</span>
+                </div>
+              </li>
+            {% endif %}
+          </ul>
+        </div>
+      </div>
+    </div>
+  {% endif %}
+
 {% endblock content %}
diff --git a/pyproject.toml b/pyproject.toml
index f8ff2d8..b975f46 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -31,6 +31,7 @@ dependencies = [
   "htpy (>=25.7.0,<26.0.0)",
   "hypercorn~=0.17",
   "ldap3 (==2.10.2rc2)",
+  "packaging>=25.0",
   "pgpy>=0.6.0",
   "pydantic-xml (>=2.17.2,<3.0.0)",
   "pyjwt (>=2.10.1,<3.0.0)",
diff --git a/uv.lock b/uv.lock
index b3f95ac..54c4e7b 100644
--- a/uv.lock
+++ b/uv.lock
@@ -1691,6 +1691,7 @@ dependencies = [
     { name = "htpy" },
     { name = "hypercorn" },
     { name = "ldap3" },
+    { name = "packaging" },
     { name = "pgpy" },
     { name = "pydantic-xml" },
     { name = "pyjwt" },
@@ -1744,6 +1745,7 @@ requires-dist = [
     { name = "htpy", specifier = ">=25.7.0,<26.0.0" },
     { name = "hypercorn", specifier = "~=0.17" },
     { name = "ldap3", specifier = "==2.10.2rc2" },
+    { name = "packaging", specifier = ">=25.0" },
     { name = "pgpy", specifier = ">=0.6.0" },
     { name = "pydantic-xml", specifier = ">=2.17.2,<3.0.0" },
     { name = "pyjwt", specifier = ">=2.10.1,<3.0.0" },


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

Reply via email to