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 3cd145b Use the storage interface for more KEYS functionality
3cd145b is described below
commit 3cd145b04c94c5aefe6ae024c76b66728f1d15a7
Author: Sean B. Palmer <[email protected]>
AuthorDate: Tue Jul 22 17:18:21 2025 +0100
Use the storage interface for more KEYS functionality
---
atr/blueprints/api/api.py | 3 +++
atr/routes/keys.py | 18 ++++++++----------
atr/storage/writers/keys.py | 34 ++++++++++++++++++++--------------
3 files changed, 31 insertions(+), 24 deletions(-)
diff --git a/atr/blueprints/api/api.py b/atr/blueprints/api/api.py
index 2a9c8ae..967a14c 100644
--- a/atr/blueprints/api/api.py
+++ b/atr/blueprints/api/api.py
@@ -391,6 +391,9 @@ async def keys_upload(data: models.api.KeysUploadArgs) ->
DictResponse:
outcomes: types.Outcomes[types.Key] = await
wacm.keys.ensure_associated(filetext)
# TODO: It would be nice to serialise the actual outcomes
+ # Or, perhaps better yet, to have a standard datatype mapping
+ # This would be specified in models.api, then imported into
storage.types
+ # Or perhaps it should go in models.storage or models.outcomes
api_outcomes = []
for outcome in outcomes.outcomes():
api_outcome: models.api.KeysUploadOutcome | None = None
diff --git a/atr/routes/keys.py b/atr/routes/keys.py
index 83597d8..5b92999 100644
--- a/atr/routes/keys.py
+++ b/atr/routes/keys.py
@@ -40,7 +40,6 @@ import werkzeug.wrappers.response as response
import wtforms
import atr.db as db
-import atr.db.interaction as interaction
import atr.models.sql as sql
import atr.revision as revision
import atr.routes as routes
@@ -355,17 +354,16 @@ async def import_selected_revision(
keys_text = await f.read()
if release.committee is None:
raise routes.FlashError("No committee found for release")
- selected_committees = [release.committee.name]
- try:
- _upload_results, success_count, error_count, submitted_committees =
await interaction.upload_keys(
- session.committees + session.projects, keys_text,
selected_committees
- )
- except interaction.InteractionError as e:
- return await session.redirect(compose.selected, error=str(e))
- await autogenerate_keys_file(release.committee.name,
release.committee.is_podling)
+
+ async with storage.write(session.uid) as write:
+ wacm =
write.as_committee_member(release.committee.name).result_or_raise()
+ outcomes: types.Outcomes[types.Key] = await
wacm.keys.ensure_associated(keys_text)
+ success_count = outcomes.result_count
+ error_count = outcomes.exception_count
+
message = f"Uploaded {success_count} keys,"
if error_count > 0:
- message += f" failed to upload {error_count} keys for {',
'.join(submitted_committees)}"
+ message += f" failed to upload {error_count} keys for
{release.committee.name}"
# Remove the KEYS file if 100% imported
if (success_count > 0) and (error_count == 0):
description = "Removed KEYS file after successful import through web
interface"
diff --git a/atr/storage/writers/keys.py b/atr/storage/writers/keys.py
index fdf8d2a..945c281 100644
--- a/atr/storage/writers/keys.py
+++ b/atr/storage/writers/keys.py
@@ -307,20 +307,6 @@ class CommitteeMember(CommitteeParticipant):
)
@performance_async
- async def committee(self) -> sql.Committee:
- return await self.__data.committee(name=self.__committee_name,
_public_signing_keys=True).demand(
- storage.AccessError(f"Committee not found:
{self.__committee_name}")
- )
-
- @performance_async
- async def ensure_associated(self, keys_file_text: str) ->
types.Outcomes[types.Key]:
- # TODO: Autogenerate KEYS file
- return await self.__ensure(keys_file_text, associate=True)
-
- @performance_async
- async def ensure_stored(self, keys_file_text: str) ->
types.Outcomes[types.Key]:
- return await self.__ensure(keys_file_text, associate=False)
-
async def autogenerate_keys_file(
self,
) -> types.Outcome[str]:
@@ -352,6 +338,26 @@ class CommitteeMember(CommitteeParticipant):
return types.OutcomeException(storage.AccessError(error_msg))
return types.OutcomeResult(str(committee_keys_path))
+ @performance_async
+ async def committee(self) -> sql.Committee:
+ return await self.__data.committee(name=self.__committee_name,
_public_signing_keys=True).demand(
+ storage.AccessError(f"Committee not found:
{self.__committee_name}")
+ )
+
+ @performance_async
+ async def ensure_associated(self, keys_file_text: str) ->
types.Outcomes[types.Key]:
+ outcomes: types.Outcomes[types.Key] = await
self.__ensure(keys_file_text, associate=True)
+ if outcomes.any_ok:
+ await self.autogenerate_keys_file()
+ return outcomes
+
+ @performance_async
+ async def ensure_stored(self, keys_file_text: str) ->
types.Outcomes[types.Key]:
+ outcomes: types.Outcomes[types.Key] = await
self.__ensure(keys_file_text, associate=False)
+ if outcomes.any_ok:
+ await self.autogenerate_keys_file()
+ return outcomes
+
@performance
def __block_models(self, key_block: str, ldap_data: dict[str, str]) ->
list[types.Key | Exception]:
# This cache is only held for the session
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]