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 595a841 Move the code to store an uploaded file to the release writer
595a841 is described below
commit 595a841d6e167edaf2555e2e5cf991fd939480c8
Author: Sean B. Palmer <[email protected]>
AuthorDate: Thu Sep 11 19:42:29 2025 +0100
Move the code to store an uploaded file to the release writer
---
atr/blueprints/api/api.py | 25 +++----------------------
atr/storage/writers/release.py | 24 +++++++++++++++++++++++-
2 files changed, 26 insertions(+), 23 deletions(-)
diff --git a/atr/blueprints/api/api.py b/atr/blueprints/api/api.py
index 200ba3a..f14fc49 100644
--- a/atr/blueprints/api/api.py
+++ b/atr/blueprints/api/api.py
@@ -16,7 +16,6 @@
# under the License.
-import base64
import hashlib
import pathlib
from typing import Any
@@ -883,7 +882,9 @@ async def release_upload(data:
models.api.ReleaseUploadArgs) -> DictResponse:
# 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")
- revision = await _upload_process_file(data, asf_uid)
+ async with storage.write(asf_uid) as write:
+ wacp = await write.as_project_committee_participant(data.project)
+ revision = await wacp.release.upload_file(data)
return models.api.ReleaseUploadResults(
endpoint="/release/upload",
revision=revision,
@@ -1324,23 +1325,3 @@ def _simple_check(*args: str | None) -> None:
for arg in args:
if arg == "None":
raise exceptions.BadRequest("Argument cannot be the string 'None'")
-
-
-async def _upload_process_file(args: models.api.ReleaseUploadArgs, asf_uid:
str) -> sql.Revision:
- file_bytes = base64.b64decode(args.content, validate=True)
- file_path = args.relpath.lstrip("/")
- description = f"Upload via API: {file_path}"
- async with storage.write(asf_uid) as write:
- wacm = await write.as_project_committee_participant(args.project)
- async with wacm.release.create_and_manage_revision(args.project,
args.version, description) as creating:
- target_path = pathlib.Path(creating.interim_path) / file_path
- await aiofiles.os.makedirs(target_path.parent, exist_ok=True)
- if target_path.exists():
- raise exceptions.BadRequest("File already exists")
- async with aiofiles.open(target_path, "wb") as f:
- await f.write(file_bytes)
- if creating.new is None:
- raise exceptions.InternalServerError("Failed to create revision")
- async with db.session() as data:
- release_name = sql.release_name(args.project, args.version)
- return await data.revision(release_name=release_name,
number=creating.new.number).demand(exceptions.NotFound())
diff --git a/atr/storage/writers/release.py b/atr/storage/writers/release.py
index 9b050aa..d9dd687 100644
--- a/atr/storage/writers/release.py
+++ b/atr/storage/writers/release.py
@@ -18,8 +18,10 @@
# Removing this will cause circular imports
from __future__ import annotations
+import base64
import contextlib
import datetime
+import pathlib
from typing import TYPE_CHECKING
import aiofiles.os
@@ -27,13 +29,13 @@ import aioshutil
import atr.db as db
import atr.log as log
+import atr.models.api as api
import atr.models.sql as sql
import atr.revision as revision
import atr.storage as storage
import atr.util as util
if TYPE_CHECKING:
- import pathlib
from collections.abc import AsyncGenerator
@@ -170,6 +172,26 @@ class CommitteeParticipant(FoundationCommitter):
)
return release, project
+ async def upload_file(self, args: api.ReleaseUploadArgs) -> sql.Revision:
+ file_bytes = base64.b64decode(args.content, validate=True)
+ file_path = args.relpath.lstrip("/")
+ description = f"Upload via API: {file_path}"
+ async with self.create_and_manage_revision(args.project, args.version,
description) as creating:
+ target_path = pathlib.Path(creating.interim_path) / file_path
+ await aiofiles.os.makedirs(target_path.parent, exist_ok=True)
+ if target_path.exists():
+ raise storage.AccessError("File already exists")
+ async with aiofiles.open(target_path, "wb") as f:
+ await f.write(file_bytes)
+ if creating.new is None:
+ raise storage.AccessError("Failed to create revision")
+ async with db.session() as data:
+ release_name = sql.release_name(args.project, args.version)
+ return await data.revision(
+ release_name=release_name,
+ number=creating.new.number,
+ ).demand(storage.AccessError("Revision not found"))
+
class CommitteeMember(CommitteeParticipant):
def __init__(
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]