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 be5a846  Migrate more distribution code to the storage interface
be5a846 is described below

commit be5a8462ccdd6502a09e2c227c72e3cf6d3660cb
Author: Sean B. Palmer <[email protected]>
AuthorDate: Mon Sep 8 15:57:56 2025 +0100

    Migrate more distribution code to the storage interface
---
 atr/models/distribution.py           |  12 ++++-
 atr/routes/distribution.py           | 100 ++++++++---------------------------
 atr/storage/writers/distributions.py |  44 +++++++++++++--
 3 files changed, 72 insertions(+), 84 deletions(-)

diff --git a/atr/models/distribution.py b/atr/models/distribution.py
index 1a5e6e4..2c54216 100644
--- a/atr/models/distribution.py
+++ b/atr/models/distribution.py
@@ -15,10 +15,11 @@
 # specific language governing permissions and limitations
 # under the License.
 
+import datetime
+
 import pydantic
 
-import atr.models.schema as schema
-import atr.models.sql as sql
+from . import basic, schema, sql
 
 
 class ArtifactHubAvailableVersion(schema.Lax):
@@ -116,3 +117,10 @@ class Data(schema.Lax):
     @classmethod
     def empty_to_none(cls, v):
         return None if v is None or (isinstance(v, str) and v.strip() == "") 
else v
+
+
+class Metadata(schema.Strict):
+    api_url: str
+    result: basic.JSON
+    upload_date: datetime.datetime
+    web_url: str | None
diff --git a/atr/routes/distribution.py b/atr/routes/distribution.py
index 201f76a..4280cdb 100644
--- a/atr/routes/distribution.py
+++ b/atr/routes/distribution.py
@@ -463,61 +463,35 @@ async def _record_form_page(
 
 async def _record_form_process_page(fpv: FormProjectVersion, /, staging: bool 
= False) -> str:
     dd = distribution.Data.model_validate(fpv.form.data)
-    resolved = await _release_validated_and_committee_and_template(fpv, dd, 
staging)
-    if isinstance(resolved, htpy.Element):
-        return await _record_form_page(fpv, extra_content=resolved, 
staging=staging)
-    release, committee, template_url = resolved
-    api_url = template_url.format(
-        owner_namespace=dd.owner_namespace,
-        package=dd.package,
-        version=dd.version,
+    release, committee = await _release_validated_and_committee(
+        fpv.project,
+        fpv.version,
+        staging=staging,
     )
-    api_oc = await _json_from_distribution_platform(api_url, dd.platform, 
dd.version)
-
-    block = htm.Block()
 
     # In case of error, show an alert
-    def _alert(not_found: str, action: str) -> htpy.Element:
+    async def _alert(message: str) -> str:
         div = htm.Block(htpy.div(".alert.alert-danger"))
-        div.p[
-            f"The {not_found} was not found in ",
-            htpy.a(href=api_url)["the distribution platform API"],
-            f". Please {action}.",
-        ]
-        return div.collect()
+        div.p[message]
+        collected = div.collect()
+        return await _record_form_page(fpv, extra_content=collected, 
staging=staging)
+
+    async with 
storage.write_as_committee_member(committee_name=committee.name) as w:
+        try:
+            dist, added, metadata = await 
w.distributions.add_distribution_from_data(
+                release=release,
+                staging=staging,
+                dd=dd,
+            )
+        except storage.AccessError as e:
+            return await _alert(str(e))
+
+    block = htm.Block()
 
     # Distribution submitted
     block.h1["Distribution recorded"]
-    match api_oc:
-        case outcome.Result(result):
-            pass
-        case outcome.Error():
-            alert = _alert("package and version", "check the package name and 
version")
-            return await _record_form_page(fpv, extra_content=alert, 
staging=staging)
-        # We leak result, usefully, from this scope
-
-    # This must come after the api_oc match, as it uses the result
-    upload_date = _distribution_upload_date(dd.platform, result, dd.version)
-    if upload_date is None:
-        # TODO: Add a link to an issue tracker
-        alert = _alert("upload date", "report this bug to ASF Tooling")
-        return await _record_form_page(fpv, extra_content=alert, 
staging=staging)
-
-    web_url = _distribution_web_url(dd.platform, result, dd.version)
-    async with 
storage.write_as_committee_member(committee_name=committee.name) as w:
-        dist, added = await w.distributions.add_distribution(
-            release_name=release.name,
-            platform=dd.platform,
-            owner_namespace=dd.owner_namespace,
-            package=dd.package,
-            version=dd.version,
-            staging=staging,
-            upload_date=upload_date,
-            api_url=api_url,
-            web_url=web_url,
-        )
 
-    ### Record
+    ## Record
     block.h2["Record"]
     if added:
         block.p["The distribution was recorded successfully."]
@@ -552,13 +526,13 @@ async def _record_form_process_page(fpv: 
FormProjectVersion, /, staging: bool =
 
         ### API URL
         block.h3["API URL"]
-        block.pre(".mb-3")[api_url]
+        block.pre(".mb-3")[metadata.api_url]
 
         ### API response
         block.h3["API response"]
         block.details[
             htpy.summary["Show full API response"],
-            htpy.pre(".atr-pre-wrap.mb-3")[json.dumps(result, indent=2)],
+            htpy.pre(".atr-pre-wrap.mb-3")[json.dumps(metadata.result, 
indent=2)],
         ]
 
     return await template.blank("Distribution submitted", 
content=block.collect())
@@ -601,31 +575,3 @@ async def _release_validated(
         # if release.project.status != sql.ProjectStatus.ACTIVE:
         #     raise RuntimeError(f"Project {project} is not active")
     return release
-
-
-async def _release_validated_and_committee_and_template(
-    fpv: FormProjectVersion,
-    dd: distribution.Data,
-    staging: bool | None = None,
-) -> tuple[sql.Release, sql.Committee, str] | htpy.Element:
-    release, committee = await _release_validated_and_committee(
-        fpv.project,
-        fpv.version,
-        staging=staging,
-    )
-    if staging is False:
-        return release, committee, dd.platform.value.template_url
-
-    supported = {sql.DistributionPlatform.ARTIFACT_HUB, 
sql.DistributionPlatform.PYPI}
-    if dd.platform not in supported:
-        div = htm.Block(htpy.div(".alert.alert-danger"))
-        div.p["Staging is currently supported only for ArtifactHub and PyPI."]
-        return div.collect()
-
-    template_url = dd.platform.value.template_staging_url
-    if template_url is None:
-        div = htm.Block(htpy.div(".alert.alert-danger"))
-        div.p["This platform does not provide a staging API endpoint."]
-        return div.collect()
-
-    return release, committee, template_url
diff --git a/atr/storage/writers/distributions.py 
b/atr/storage/writers/distributions.py
index 7e1b1e4..4bc778f 100644
--- a/atr/storage/writers/distributions.py
+++ b/atr/storage/writers/distributions.py
@@ -142,12 +142,46 @@ class CommitteeMember(CommitteeParticipant):
             raise e
         return distribution, True
 
-    async def add_distribution_from_url(
+    async def add_distribution_from_data(
         self,
-        api_url: str,
-        platform: sql.DistributionPlatform,
-        version: str,
-    ) -> tuple[sql.Distribution, bool]: ...
+        release: sql.Release,
+        staging: bool,
+        dd: distribution.Data,
+    ) -> tuple[sql.Distribution, bool, distribution.Metadata]:
+        template_url = await self.__template_url(dd, staging)
+        api_url = template_url.format(
+            owner_namespace=dd.owner_namespace,
+            package=dd.package,
+            version=dd.version,
+        )
+        api_oc = await self.__json_from_distribution_platform(api_url, 
dd.platform, dd.version)
+        match api_oc:
+            case outcome.Result(result):
+                pass
+            case outcome.Error():
+                raise storage.AccessError("Failed to get API response from 
distribution platform")
+        upload_date = self.__distribution_upload_date(dd.platform, result, 
dd.version)
+        if upload_date is None:
+            raise storage.AccessError("Failed to get upload date from 
distribution platform")
+        web_url = self.__distribution_web_url(dd.platform, result, dd.version)
+        metadata = distribution.Metadata(
+            api_url=api_url,
+            result=result,
+            upload_date=upload_date,
+            web_url=web_url,
+        )
+        dist, added = await self.add_distribution(
+            release_name=release.name,
+            platform=dd.platform,
+            owner_namespace=dd.owner_namespace,
+            package=dd.package,
+            version=dd.version,
+            staging=staging,
+            upload_date=upload_date,
+            api_url=api_url,
+            web_url=web_url,
+        )
+        return dist, added, metadata
 
     def __distribution_upload_date(  # noqa: C901
         self,


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

Reply via email to