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 5b80264 Add some API endpoints for release data
5b80264 is described below
commit 5b80264715cd6684afe2371811370efb57d2e732
Author: Sean B. Palmer <[email protected]>
AuthorDate: Wed Jul 2 19:34:38 2025 +0100
Add some API endpoints for release data
---
atr/blueprints/api/api.py | 69 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 69 insertions(+)
diff --git a/atr/blueprints/api/api.py b/atr/blueprints/api/api.py
index ca2bf58..6a337d4 100644
--- a/atr/blueprints/api/api.py
+++ b/atr/blueprints/api/api.py
@@ -41,6 +41,11 @@ class Pagination:
limit: int = 20
[email protected]
+class Releases(Pagination):
+ phase: str | None = None
+
+
@dataclasses.dataclass
class Task(Pagination):
status: str | None = None
@@ -140,6 +145,70 @@ async def projects_name_releases(name: str) ->
tuple[list[Mapping], int]:
return [release.model_dump() for release in releases], 200
[email protected]("/releases")
+@quart_schema.validate_querystring(Releases)
+async def releases(query_args: Releases) -> quart.Response:
+ """Paged list of releases with optional filtering by phase."""
+ _pagination_args_validate(query_args)
+ via = models.validate_instrumented_attribute
+ async with db.session() as data:
+ statement = sqlmodel.select(models.Release)
+
+ if query_args.phase:
+ try:
+ phase_value = models.ReleasePhase(query_args.phase)
+ except ValueError:
+ raise exceptions.BadRequest(f"Invalid phase:
{query_args.phase}")
+ statement = statement.where(models.Release.phase == phase_value)
+
+ statement = (
+
statement.order_by(via(models.Release.created).desc()).limit(query_args.limit).offset(query_args.offset)
+ )
+
+ paged_releases = (await data.execute(statement)).scalars().all()
+
+ count_stmt =
sqlalchemy.select(sqlalchemy.func.count(via(models.Release.name)))
+ if query_args.phase:
+ phase_value = models.ReleasePhase(query_args.phase) if
query_args.phase else None
+ if phase_value is not None:
+ count_stmt = count_stmt.where(via(models.Release.phase) ==
phase_value)
+
+ count = (await data.execute(count_stmt)).scalar_one()
+
+ result = {"data": [release.model_dump() for release in
paged_releases], "count": count}
+ return quart.jsonify(result)
+
+
[email protected]("/releases/<project>/<version>")
+@quart_schema.validate_response(models.Release, 200)
+async def releases_project_version(project: str, version: str) ->
tuple[Mapping, int]:
+ """Return a single release by project and version."""
+ async with db.session() as data:
+ release_name = models.release_name(project, version)
+ release = await
data.release(name=release_name).demand(exceptions.NotFound())
+ return release.model_dump(), 200
+
+
[email protected]("/releases/<project>/<version>/check-results")
+@quart_schema.validate_response(list[models.CheckResult], 200)
+async def releases_project_version_check_results(project: str, version: str)
-> tuple[list[Mapping], int]:
+ """List all check results for a given release."""
+ async with db.session() as data:
+ release_name = models.release_name(project, version)
+ check_results = await
data.check_result(release_name=release_name).all()
+ return [cr.model_dump() for cr in check_results], 200
+
+
[email protected]("/releases/<project>/<version>/revisions")
+@quart_schema.validate_response(list[models.Revision], 200)
+async def releases_project_version_revisions(project: str, version: str) ->
tuple[list[Mapping], int]:
+ """List all revisions for a given release."""
+ async with db.session() as data:
+ release_name = models.release_name(project, version)
+ revisions = await data.revision(release_name=release_name).all()
+ return [rev.model_dump() for rev in revisions], 200
+
+
@api.BLUEPRINT.route("/tasks")
@quart_schema.validate_querystring(Task)
async def tasks(query_args: Task) -> quart.Response:
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]