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 a50d92d9 Handle phase mismatches and add further checking
a50d92d9 is described below

commit a50d92d9998eeaa36caeef146f0c29f68d75142e
Author: Sean B. Palmer <[email protected]>
AuthorDate: Wed Apr 1 20:22:43 2026 +0100

    Handle phase mismatches and add further checking
---
 atr/api/__init__.py |  9 ++++++---
 atr/post/draft.py   | 53 +++++++++++++++++++++++++++++++++++------------------
 atr/post/keys.py    |  1 +
 atr/post/sbom.py    | 19 ++++++-------------
 atr/post/upload.py  |  9 ++++++++-
 5 files changed, 56 insertions(+), 35 deletions(-)

diff --git a/atr/api/__init__.py b/atr/api/__init__.py
index 1c4af5e7..9cca2570 100644
--- a/atr/api/__init__.py
+++ b/atr/api/__init__.py
@@ -1174,9 +1174,12 @@ async def release_upload(
     #     if not (user.is_committee_member(project.committee, asf_uid) or 
user.is_admin(asf_uid)):
     #         raise exceptions.Forbidden("You do not have permission to upload 
to this project")
 
-    async with storage.write(asf_uid) as write:
-        wacp = await write.as_project_committee_participant(data.project)
-        result = await wacp.release.upload_file(data)
+    try:
+        async with storage.write(asf_uid) as write:
+            wacp = await write.as_project_committee_participant(data.project)
+            result = await wacp.release.upload_file(data)
+    except types.PhaseMismatchError as e:
+        raise exceptions.Conflict(str(e))
     if isinstance(result, sql.Quarantined):
         return {
             "endpoint": "/release/upload",
diff --git a/atr/post/draft.py b/atr/post/draft.py
index 020a4987..05518ae9 100644
--- a/atr/post/draft.py
+++ b/atr/post/draft.py
@@ -32,6 +32,7 @@ import atr.models.safe as safe
 import atr.models.sql as sql
 import atr.shared as shared
 import atr.storage as storage
+import atr.storage.types as types
 import atr.util as util
 import atr.web as web
 
@@ -55,15 +56,23 @@ async def cache_reset(
         raise base.ASFQuartException("Admin access required", errorcode=403)
 
     description = "Empty revision to restart all checks without cache for the 
whole release candidate draft"
-    async with storage.write(session) as write:
-        wacp = await write.as_project_committee_participant(project_key)
-        result = await wacp.revision.create_revision_with_quarantine(
-            project_key,
-            version_key,
-            session.uid,
-            
allowed_phases=frozenset({sql.ReleasePhase.RELEASE_CANDIDATE_DRAFT}),
-            description=description,
-            reset_to_global_cache=True,
+    try:
+        async with storage.write(session) as write:
+            wacp = await write.as_project_committee_participant(project_key)
+            result = await wacp.revision.create_revision_with_quarantine(
+                project_key,
+                version_key,
+                session.uid,
+                
allowed_phases=frozenset({sql.ReleasePhase.RELEASE_CANDIDATE_DRAFT}),
+                description=description,
+                reset_to_global_cache=True,
+            )
+    except types.PhaseMismatchError as e:
+        return await session.redirect(
+            get.compose.selected,
+            project_key=str(project_key),
+            version_key=str(version_key),
+            error=str(e),
         )
 
     success = "Release set back to global caching"
@@ -210,15 +219,23 @@ async def recheck(
         raise base.ASFQuartException("Admin access required", errorcode=403)
 
     description = "Empty revision to restart all checks without cache for the 
whole release candidate draft"
-    async with storage.write(session) as write:
-        wacp = await write.as_project_committee_participant(project_key)
-        result = await wacp.revision.create_revision_with_quarantine(
-            project_key,
-            version_key,
-            session.uid,
-            
allowed_phases=frozenset({sql.ReleasePhase.RELEASE_CANDIDATE_DRAFT}),
-            description=description,
-            set_local_cache=True,
+    try:
+        async with storage.write(session) as write:
+            wacp = await write.as_project_committee_participant(project_key)
+            result = await wacp.revision.create_revision_with_quarantine(
+                project_key,
+                version_key,
+                session.uid,
+                
allowed_phases=frozenset({sql.ReleasePhase.RELEASE_CANDIDATE_DRAFT}),
+                description=description,
+                set_local_cache=True,
+            )
+    except types.PhaseMismatchError as e:
+        return await session.redirect(
+            get.compose.selected,
+            project_key=str(project_key),
+            version_key=str(version_key),
+            error=str(e),
         )
 
     success = "All checks restarted with release-local cache"
diff --git a/atr/post/keys.py b/atr/post/keys.py
index e5351d45..69b3ece3 100644
--- a/atr/post/keys.py
+++ b/atr/post/keys.py
@@ -154,6 +154,7 @@ async def import_selected_revision(
     URL: /keys/import/<project_key>/<version_key>
     """
     await session.check_access(project_key)
+    await session.release(project_key, version_key, with_committee=False, 
with_project=False)
     async with storage.write() as write:
         wacm = await write.as_project_committee_member(project_key)
         outcomes: outcome.List[types.Key] = await 
wacm.keys.import_keys_file(project_key, version_key)
diff --git a/atr/post/sbom.py b/atr/post/sbom.py
index 04db67e4..3a96c4e1 100644
--- a/atr/post/sbom.py
+++ b/atr/post/sbom.py
@@ -23,7 +23,6 @@ import asfquart.base as base
 import quart
 
 import atr.blueprints.post as post
-import atr.db as db
 import atr.get as get
 import atr.log as log
 import atr.models.safe as safe
@@ -64,12 +63,9 @@ async def _augment(
         raise base.ASFQuartException("SBOM augmentation is only supported for 
.cdx.json files", errorcode=400)
 
     try:
-        async with db.session() as data:
-            release = await data.release(project_key=str(project_key), 
version=str(version_key)).demand(
-                RuntimeError("Release does not exist for new revision 
creation")
-            )
-            revision_number = release.safe_latest_revision_number
-            log.info(f"Augmenting SBOM for {project_key} {version_key} 
{revision_number!s} {rel_path!s}")
+        release = await session.release(project_key, version_key, 
with_committee=False, with_project=False)
+        revision_number = release.safe_latest_revision_number
+        log.info(f"Augmenting SBOM for {project_key} {version_key} 
{revision_number!s} {rel_path!s}")
         async with storage.write_as_project_committee_member(project_key) as 
wacm:
             sbom_task = await wacm.sbom.augment_cyclonedx(
                 project_key,
@@ -105,12 +101,9 @@ async def _scan(
         raise base.ASFQuartException("OSV scanning is only supported for 
.cdx.json files", errorcode=400)
 
     try:
-        async with db.session() as data:
-            release = await data.release(project_key=str(project_key), 
version=str(version_key)).demand(
-                RuntimeError("Release does not exist for OSV scan")
-            )
-            revision_number = release.safe_latest_revision_number
-            log.info(f"Starting OSV scan for {project_key!s} {version_key!s} 
{revision_number!s} {rel_path!s}")
+        release = await session.release(project_key, version_key, 
with_committee=False, with_project=False)
+        revision_number = release.safe_latest_revision_number
+        log.info(f"Starting OSV scan for {project_key!s} {version_key!s} 
{revision_number!s} {rel_path!s}")
         async with storage.write_as_project_committee_member(project_key) as 
wacm:
             sbom_task = await wacm.sbom.osv_scan_cyclonedx(
                 project_key,
diff --git a/atr/post/upload.py b/atr/post/upload.py
index 7d71c35b..3271106b 100644
--- a/atr/post/upload.py
+++ b/atr/post/upload.py
@@ -43,7 +43,7 @@ import atr.web as web
 
 
 @post.typed
-async def finalise(
+async def finalise(  # noqa: C901
     session: web.Committer,
     _upload_finalise: Literal["upload/finalise"],
     project_key: safe.ProjectKey,
@@ -108,6 +108,13 @@ async def finalise(
             project_key=str(project_key),
             version_key=str(version_key),
         )
+    except types.PhaseMismatchError as e:
+        return await session.redirect(
+            get.compose.selected,
+            error=str(e),
+            project_key=str(project_key),
+            version_key=str(version_key),
+        )
     except types.FailedError as e:
         await aioshutil.rmtree(staging_dir)
         await quart.flash(str(e), "error")


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

Reply via email to