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 055b942 Add a wrapper around the revision creation code to the
storage interface
055b942 is described below
commit 055b942ca338d22dfbdd27443e63bc5a975b6065
Author: Sean B. Palmer <[email protected]>
AuthorDate: Wed Sep 10 19:33:04 2025 +0100
Add a wrapper around the revision creation code to the storage interface
---
atr/blueprints/api/api.py | 25 ++++++++++++++-----------
atr/revision.py | 2 --
atr/storage/writers/release.py | 11 +++++++++++
3 files changed, 25 insertions(+), 13 deletions(-)
diff --git a/atr/blueprints/api/api.py b/atr/blueprints/api/api.py
index dae9d8a..200ba3a 100644
--- a/atr/blueprints/api/api.py
+++ b/atr/blueprints/api/api.py
@@ -37,7 +37,6 @@ import atr.db.interaction as interaction
import atr.jwtoken as jwtoken
import atr.models as models
import atr.models.sql as sql
-import atr.revision as revision
import atr.storage as storage
import atr.storage.outcome as outcome
import atr.storage.types as types
@@ -878,11 +877,11 @@ async def release_upload(data:
models.api.ReleaseUploadArgs) -> DictResponse:
"""
asf_uid = _jwt_asf_uid()
- async with db.session() as db_data:
- project = await db_data.project(name=data.project,
_committee=True).demand(exceptions.NotFound())
- # TODO: user.is_participant(project, asf_uid)
- 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 db.session() as db_data:
+ # project = await db_data.project(name=data.project,
_committee=True).demand(exceptions.NotFound())
+ # # TODO: user.is_participant(project, asf_uid)
+ # 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)
return models.api.ReleaseUploadResults(
@@ -1331,11 +1330,15 @@ async def _upload_process_file(args:
models.api.ReleaseUploadArgs, asf_uid: str)
file_bytes = base64.b64decode(args.content, validate=True)
file_path = args.relpath.lstrip("/")
description = f"Upload via API: {file_path}"
- async with revision.create_and_manage(args.project, args.version, asf_uid,
description=description) as creating:
- target_path = pathlib.Path(creating.interim_path) / file_path
- await aiofiles.os.makedirs(target_path.parent, exist_ok=True)
- async with aiofiles.open(target_path, "wb") as f:
- await f.write(file_bytes)
+ 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:
diff --git a/atr/revision.py b/atr/revision.py
index fcf8ba5..e0aa4b6 100644
--- a/atr/revision.py
+++ b/atr/revision.py
@@ -64,8 +64,6 @@ class SafeSession:
return False
-# NOTE: The create_directory parameter is not used anymore
-# The temporary directory will always be created
@contextlib.asynccontextmanager
async def create_and_manage(
project_name: str,
diff --git a/atr/storage/writers/release.py b/atr/storage/writers/release.py
index bfbfea1..b0b2475 100644
--- a/atr/storage/writers/release.py
+++ b/atr/storage/writers/release.py
@@ -18,6 +18,7 @@
# Removing this will cause circular imports
from __future__ import annotations
+import contextlib
import datetime
from typing import TYPE_CHECKING
@@ -33,6 +34,7 @@ import atr.util as util
if TYPE_CHECKING:
import pathlib
+ from collections.abc import AsyncGenerator
class GeneralPublic:
@@ -78,6 +80,15 @@ class CommitteeParticipant(FoundationCommitter):
self.__asf_uid = asf_uid
self.__committee_name = committee_name
+ @contextlib.asynccontextmanager
+ async def create_and_manage_revision(
+ self, project_name: str, version: str, description: str
+ ) -> AsyncGenerator[revision.Creating]:
+ async with revision.create_and_manage(
+ project_name, version, self.__asf_uid, description=description
+ ) as _creating:
+ yield _creating
+
async def start(self, project_name: str, version: str) ->
tuple[sql.Release, sql.Project]:
"""Creates the initial release draft record and revision directory."""
# Get the project from the project name
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]