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 d8772b0  Document remaining routes code to move to the storage 
interface
d8772b0 is described below

commit d8772b0c3d1b6d7559a9247e279d30919c29dbb0
Author: Sean B. Palmer <[email protected]>
AuthorDate: Wed Sep 10 19:57:43 2025 +0100

    Document remaining routes code to move to the storage interface
---
 atr/routes/draft.py    |  2 ++
 atr/routes/keys.py     | 15 +++++++++------
 atr/routes/preview.py  | 46 ++++++----------------------------------------
 atr/routes/projects.py | 15 +++++++++------
 atr/routes/release.py  |  6 +++---
 atr/routes/resolve.py  |  1 +
 atr/routes/sbom.py     |  1 +
 atr/routes/vote.py     |  1 +
 8 files changed, 32 insertions(+), 55 deletions(-)

diff --git a/atr/routes/draft.py b/atr/routes/draft.py
index a1dbb66..73cf541 100644
--- a/atr/routes/draft.py
+++ b/atr/routes/draft.py
@@ -299,6 +299,7 @@ async def sbomgen(
             raise routes.FlashError("Internal error: New revision not found")
 
         # Create and queue the task, using paths within the new revision
+        # TODO: Move this to the storage interface
         async with db.session() as data:
             # We still need release.name for the task metadata
             sbom_task = sql.Task(
@@ -364,6 +365,7 @@ async def svnload(session: routes.CommitterSession, 
project_name: str, version_n
             "version_name": version_name,
             "asf_uid": session.uid,
         }
+        # TODO: Move this to the storage interface
         async with db.session() as data:
             svn_import_task = sql.Task(
                 task_type=sql.TaskType.SVN_IMPORT_FILES,
diff --git a/atr/routes/keys.py b/atr/routes/keys.py
index 3c033f9..b6c09ae 100644
--- a/atr/routes/keys.py
+++ b/atr/routes/keys.py
@@ -202,6 +202,7 @@ async def delete(session: routes.CommitterSession) -> 
response.Response:
         return await session.redirect(keys, error="Missing key fingerprint for 
deletion.")
 
     # Try to delete an SSH key first
+    # TODO: Use the storage interface instead
     async with db.session() as data:
         ssh_key = await data.ssh_key(fingerprint=fingerprint, 
asf_uid=session.uid).get()
         if ssh_key:
@@ -229,19 +230,21 @@ async def delete(session: routes.CommitterSession) -> 
response.Response:
 async def details(session: routes.CommitterSession, fingerprint: str) -> str | 
response.Response:
     """Display details for a specific OpenPGP key."""
     fingerprint = fingerprint.lower()
+    user_committees = []
     async with db.session() as data:
         key, is_owner = await _key_and_is_owner(data, session, fingerprint)
         form = None
         if is_owner:
             project_list = session.committees + session.projects
             user_committees = await data.committee(name_in=project_list).all()
-            committee_choices: forms.Choices = [(c.name, c.display_name or 
c.name) for c in user_committees]
+    if is_owner:
+        committee_choices: forms.Choices = [(c.name, c.display_name or c.name) 
for c in user_committees]
 
-            # TODO: Probably need to do data in a separate phase
-            form = await UpdateKeyCommitteesForm.create_form(
-                data=await quart.request.form if (quart.request.method == 
"POST") else None
-            )
-            forms.choices(form.selected_committees, committee_choices)
+        # TODO: Probably need to do data in a separate phase
+        form = await UpdateKeyCommitteesForm.create_form(
+            data=await quart.request.form if (quart.request.method == "POST") 
else None
+        )
+        forms.choices(form.selected_committees, committee_choices)
 
     if form and await form.validate_on_submit():
         async with db.session() as data:
diff --git a/atr/routes/preview.py b/atr/routes/preview.py
index 7012975..927ab61 100644
--- a/atr/routes/preview.py
+++ b/atr/routes/preview.py
@@ -17,19 +17,17 @@
 
 """preview.py"""
 
-import aiofiles.os
-import aioshutil
 import asfquart
 import quart
 import werkzeug.wrappers.response as response
 
 import atr.construct as construct
-import atr.db as db
 import atr.forms as forms
 import atr.log as log
 import atr.models.sql as sql
 import atr.routes as routes
 import atr.routes.root as root
+import atr.storage as storage
 import atr.template as template
 import atr.util as util
 
@@ -103,30 +101,11 @@ async def delete(session: routes.CommitterSession) -> 
response.Response:
         return await session.redirect(root.index, error="Missing required 
parameters")
 
     # Check that the user has access to the project
-    async with db.session() as data:
-        project = await data.project(name=project_name, 
status=sql.ProjectStatus.ACTIVE).get()
-        if not project or not any(
-            (
-                (c.name == project.committee_name)
-                and ((session.uid in c.committee_members) or (session.uid in 
c.committers))
-            )
-            for c in (await session.user_committees)
-        ):
-            return await session.redirect(root.index, error="You do not have 
access to this project")
-
-        # Delete the metadata from the database
-        async with data.begin():
-            try:
-                await _delete_preview(data, release_name)
-            except Exception as e:
-                log.exception("Error deleting preview:")
-                return await session.redirect(root.index, error=f"Error 
deleting preview: {e!s}")
-
-    # Delete the files on disk, including all revisions
-    # We can't use util.release_directory_base here because we don't have the 
release object
-    preview_dir = util.get_unfinished_dir() / project_name / version_name
-    if await aiofiles.os.path.exists(preview_dir):
-        await aioshutil.rmtree(preview_dir)
+    async with storage.write(session.uid) as write:
+        wacp = await write.as_project_committee_member(project_name)
+        await wacp.release.delete(
+            project_name, version_name, 
phase=sql.ReleasePhase.RELEASE_PREVIEW, include_downloads=False
+        )
 
     return await session.redirect(root.index, success="Preview deleted 
successfully")
 
@@ -188,16 +167,3 @@ async def view_path(
         phase_key="preview",
         content_listing=content_listing,
     )
-
-
-async def _delete_preview(data: db.Session, release_name: str) -> None:
-    """Delete a release preview and all its associated files."""
-    # Check that the release exists
-    release = await data.release(name=release_name, _project=True).get()
-    if not release:
-        raise routes.FlashError("Preview not found")
-    if release.phase != sql.ReleasePhase.RELEASE_PREVIEW:
-        raise routes.FlashError("Release is not in the preview phase")
-
-    # Delete the release record
-    await data.delete(release)
diff --git a/atr/routes/projects.py b/atr/routes/projects.py
index c2acecc..966a83f 100644
--- a/atr/routes/projects.py
+++ b/atr/routes/projects.py
@@ -265,6 +265,7 @@ async def delete(session: routes.CommitterSession) -> 
response.Response:
     if not project_name:
         return await session.redirect(projects, error="Missing project name 
for deletion.")
 
+    # TODO: Move this to the storage interface
     async with db.session() as data:
         project = await data.project(
             name=project_name, status=sql.ProjectStatus.ACTIVE, 
_releases=True, _distribution_channels=True
@@ -331,6 +332,7 @@ async def view(session: routes.CommitterSession, name: str) 
-> response.Response
     metadata_form = None
     can_edit = False
 
+    # TODO: Move this to the storage interface
     async with db.session() as data:
         project = await data.project(
             name=name, _committee=True, _committee_public_signing_keys=True, 
_release_policy=True
@@ -353,12 +355,12 @@ async def view(session: routes.CommitterSession, name: 
str) -> response.Response
 
         if metadata_form is None:
             metadata_form = await 
ProjectMetadataForm.create_form(data={"project_name": project.name})
-        if policy_form is None:
-            policy_form = await _policy_form_create(project)
-        candidate_drafts = await interaction.candidate_drafts(project)
-        candidates = await interaction.candidates(project)
-        previews = await interaction.previews(project)
-        full_releases = await interaction.full_releases(project)
+    if policy_form is None:
+        policy_form = await _policy_form_create(project)
+    candidate_drafts = await interaction.candidate_drafts(project)
+    candidates = await interaction.candidates(project)
+    previews = await interaction.previews(project)
+    full_releases = await interaction.full_releases(project)
 
     return await template.render(
         "project-view.html",
@@ -602,6 +604,7 @@ async def _project_add(form: AddForm, asf_id: str) -> 
response.Response:
     committee_name, display_name, label = form_values
 
     super_project = None
+    # TODO: Move this to the storage interface
     async with db.session() as data:
         # Get the base project to derive from
         # We're allowing derivation from a retired project here
diff --git a/atr/routes/release.py b/atr/routes/release.py
index 29d2a9e..97554c4 100644
--- a/atr/routes/release.py
+++ b/atr/routes/release.py
@@ -129,9 +129,9 @@ async def select(session: routes.CommitterSession, 
project_name: str) -> str:
             base.ASFQuartException(f"Project {project_name} not found", 
errorcode=404)
         )
         releases = await interaction.releases_in_progress(project)
-        return await template.render(
-            "release-select.html", project=project, releases=releases, 
format_datetime=util.format_datetime
-        )
+    return await template.render(
+        "release-select.html", project=project, releases=releases, 
format_datetime=util.format_datetime
+    )
 
 
 @routes.public("/release/view/<project_name>/<version_name>")
diff --git a/atr/routes/resolve.py b/atr/routes/resolve.py
index bb9a864..6e4d047 100644
--- a/atr/routes/resolve.py
+++ b/atr/routes/resolve.py
@@ -112,6 +112,7 @@ async def manual_selected_post(
     vote_result_url = util.unwrap(resolve_form.vote_result_url.data)
     await _committees_check(vote_thread_url, vote_result_url)
 
+    # TODO: Move this to the storage interface
     async with db.session() as data:
         release = await data.merge(release)
         if vote_result == "passed":
diff --git a/atr/routes/sbom.py b/atr/routes/sbom.py
index 32af892..8c360db 100644
--- a/atr/routes/sbom.py
+++ b/atr/routes/sbom.py
@@ -66,6 +66,7 @@ async def augment(
             if revision_number is None:
                 raise RuntimeError("No revision number found for new revision 
creation")
             log.info(f"Augmenting SBOM for {project_name} {version_name} 
{revision_number} {rel_path}")
+            # TODO: Move this to the storage interface
             sbom_task = sql.Task(
                 task_type=sql.TaskType.SBOM_AUGMENT,
                 task_args=tasks.sbom.FileArgs(
diff --git a/atr/routes/vote.py b/atr/routes/vote.py
index 6c8ac8d..11095b2 100644
--- a/atr/routes/vote.py
+++ b/atr/routes/vote.py
@@ -175,6 +175,7 @@ async def _send_vote(
     body_text = "\n\n".join(body)
     in_reply_to = vote_thread_mid
 
+    # TODO: Move this to the storage interface
     task = sql.Task(
         status=sql.TaskStatus.QUEUED,
         task_type=sql.TaskType.MESSAGE_SEND,


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

Reply via email to