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 bcd1b77 Add an endpoint to announce a release using a GitHub OIDC JWT
bcd1b77 is described below
commit bcd1b7782c37949d8520bafeee364035e61c4c52
Author: Sean B. Palmer <[email protected]>
AuthorDate: Thu Sep 4 16:11:05 2025 +0100
Add an endpoint to announce a release using a GitHub OIDC JWT
---
atr/blueprints/api/api.py | 76 +++++++++++++++++++++++++++++++++--------------
atr/models/api.py | 20 +++++++++++++
2 files changed, 73 insertions(+), 23 deletions(-)
diff --git a/atr/blueprints/api/api.py b/atr/blueprints/api/api.py
index 7537965..e117d13 100644
--- a/atr/blueprints/api/api.py
+++ b/atr/blueprints/api/api.py
@@ -259,12 +259,65 @@ async def committees_list() -> DictResponse:
).model_dump(), 200
[email protected]("/github/release/announce", methods=["POST"])
+@quart_schema.validate_request(models.api.GithubReleaseAnnounceArgs)
+async def github_release_announce(data: models.api.GithubReleaseAnnounceArgs)
-> DictResponse:
+ """
+ Announce a release with a corroborating GitHub OIDC JWT.
+ """
+ _payload, asf_uid, project = await interaction.github_trusted_jwt(data.jwt)
+ try:
+ # TODO: Add defaults
+ await announce.announce(
+ project.name,
+ data.version,
+ data.revision,
+ data.email_to,
+ data.subject,
+ data.body,
+ data.path_suffix,
+ asf_uid,
+ asf_uid,
+ )
+ except announce.AnnounceError as e:
+ raise exceptions.BadRequest(str(e))
+
+ return models.api.GithubReleaseAnnounceResults(
+ endpoint="/github/release/announce",
+ success=True,
+ ).model_dump(), 200
+
+
[email protected]("/github/ssh/register", methods=["POST"])
+@quart_schema.validate_request(models.api.GithubSshRegisterArgs)
+async def github_ssh_register(data: models.api.GithubSshRegisterArgs) ->
DictResponse:
+ """
+ Register an SSH key sent with a corroborating GitHub OIDC JWT.
+ """
+ payload, asf_uid, project = await interaction.github_trusted_jwt(data.jwt)
+ async with
storage.write_as_committee_member(util.unwrap(project.committee).name, asf_uid)
as wacm:
+ fingerprint, expires = await wacm.ssh.add_workflow_key(
+ payload["actor"],
+ payload["actor_id"],
+ project.name,
+ data.ssh_key,
+ )
+
+ return models.api.GithubSshRegisterResults(
+ endpoint="/github/ssh/register",
+ fingerprint=fingerprint,
+ project=project.name,
+ expires=expires,
+ ).model_dump(), 200
+
+
@api.BLUEPRINT.route("/github/vote/resolve", methods=["POST"])
@quart_schema.validate_request(models.api.GithubVoteResolveArgs)
async def github_vote_resolve(data: models.api.GithubVoteResolveArgs) ->
DictResponse:
"""
Resolve a vote with a corroborating GitHub OIDC JWT.
"""
+ # TODO: Need to be able to resolve and make the release immutable
_payload, asf_uid, project = await interaction.github_trusted_jwt(data.jwt)
if project.committee is None:
raise exceptions.NotFound("Project has no committee")
@@ -297,29 +350,6 @@ async def github_vote_resolve(data:
models.api.GithubVoteResolveArgs) -> DictRes
).model_dump(), 200
[email protected]("/github/ssh/register", methods=["POST"])
-@quart_schema.validate_request(models.api.GithubSshRegisterArgs)
-async def github_ssh_register(data: models.api.GithubSshRegisterArgs) ->
DictResponse:
- """
- Register an SSH key sent with a corroborating GitHub OIDC JWT.
- """
- payload, asf_uid, project = await interaction.github_trusted_jwt(data.jwt)
- async with
storage.write_as_committee_member(util.unwrap(project.committee).name, asf_uid)
as wacm:
- fingerprint, expires = await wacm.ssh.add_workflow_key(
- payload["actor"],
- payload["actor_id"],
- project.name,
- data.ssh_key,
- )
-
- return models.api.GithubSshRegisterResults(
- endpoint="/github/ssh/register",
- fingerprint=fingerprint,
- project=project.name,
- expires=expires,
- ).model_dump(), 200
-
-
@api.BLUEPRINT.route("/ignore/add", methods=["POST"])
@jwtoken.require
@quart_schema.security_scheme([{"BearerAuth": []}])
diff --git a/atr/models/api.py b/atr/models/api.py
index 8c240a2..14e4cdb 100644
--- a/atr/models/api.py
+++ b/atr/models/api.py
@@ -71,6 +71,24 @@ class CommitteesListResults(schema.Strict):
committees: Sequence[sql.Committee]
+class GithubReleaseAnnounceArgs(schema.Strict):
+ jwt: str = schema.Field(...,
**example("eyJhbGciOiJIUzI1[...]mMjLiuyu5CSpyHI="))
+ version: str = schema.Field(..., **example("0.0.1"))
+ revision: str = schema.Field(..., **example("00005"))
+ email_to: str = schema.Field(..., **example("[email protected]"))
+ subject: str = schema.Field(..., **example("[ANNOUNCE] Apache Example
1.0.0 release"))
+ body: str = schema.Field(
+ ...,
+ **example("The Apache Example team is pleased to announce the release
of Example 1.0.0..."),
+ )
+ path_suffix: str = schema.Field(..., **example("example/1.0.0"))
+
+
+class GithubReleaseAnnounceResults(schema.Strict):
+ endpoint: Literal["/github/release/announce"] =
schema.Field(alias="endpoint")
+ success: Literal[True] = schema.Field(..., **example(True))
+
+
class GithubSshRegisterArgs(schema.Strict):
jwt: str = schema.Field(...,
**example("eyJhbGciOiJIUzI1[...]mMjLiuyu5CSpyHI="))
ssh_key: str = schema.Field(
@@ -445,6 +463,7 @@ Results = Annotated[
| CommitteeKeysResults
| CommitteeProjectsResults
| CommitteesListResults
+ | GithubReleaseAnnounceResults
| GithubSshRegisterResults
| GithubVoteResolveResults
| IgnoreAddResults
@@ -499,6 +518,7 @@ validate_committee_get = validator(CommitteeGetResults)
validate_committee_keys = validator(CommitteeKeysResults)
validate_committee_projects = validator(CommitteeProjectsResults)
validate_committees_list = validator(CommitteesListResults)
+validate_github_release_announce = validator(GithubReleaseAnnounceResults)
validate_github_ssh_register = validator(GithubSshRegisterResults)
validate_github_vote_resolve = validator(GithubVoteResolveResults)
validate_ignore_add = validator(IgnoreAddResults)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]