This is an automated email from the ASF dual-hosted git repository.
arm pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tooling-trusted-releases.git
The following commit(s) were added to refs/heads/main by this push:
new 025a0cd Allow phase and UID to be passed out to workflows
025a0cd is described below
commit 025a0cdceb3def52639e308a0ba84d6aacb38572
Author: Alastair McFarlane <[email protected]>
AuthorDate: Tue Jan 13 17:29:36 2026 +0000
Allow phase and UID to be passed out to workflows
---
atr/api/__init__.py | 15 ++++++++++-----
atr/db/interaction.py | 18 +++++++++++-------
atr/models/api.py | 2 ++
atr/post/distribution.py | 12 +++++++++++-
atr/storage/writers/distributions.py | 2 ++
atr/tasks/gha.py | 3 +++
6 files changed, 39 insertions(+), 13 deletions(-)
diff --git a/atr/api/__init__.py b/atr/api/__init__.py
index ee94a8e..2cb7b68 100644
--- a/atr/api/__init__.py
+++ b/atr/api/__init__.py
@@ -256,23 +256,28 @@ async def committees_list() -> DictResponse:
async def distribute_ssh_register(data: models.api.DistributeSshRegisterArgs)
-> DictResponse:
"""
Register an SSH key sent with a corroborating Trusted Publisher JWT,
- validating the requested version is in the correct phase.
+ validating the requested release is in the correct phase.
"""
- payload, asf_uid, project = await interaction.trusted_jwt_for_version(
- data.publisher, data.jwt, interaction.TrustedProjectPhase(data.phase),
data.version
+ payload, asf_uid, project, release = await
interaction.trusted_jwt_for_dist(
+ data.publisher,
+ data.jwt,
+ data.asf_uid,
+ interaction.TrustedProjectPhase(data.phase),
+ data.project_name,
+ data.version,
)
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,
+ release.project_name,
data.ssh_key,
)
return models.api.DistributeSshRegisterResults(
endpoint="/distribute/ssh/register",
fingerprint=fingerprint,
- project=project.name,
+ project=release.project_name,
expires=expires,
).model_dump(), 200
diff --git a/atr/db/interaction.py b/atr/db/interaction.py
index beef1ec..bc27ef4 100644
--- a/atr/db/interaction.py
+++ b/atr/db/interaction.py
@@ -397,14 +397,18 @@ async def trusted_jwt(publisher: str, jwt: str, phase:
TrustedProjectPhase) -> t
return payload, asf_uid, project
-async def trusted_jwt_for_version(
- publisher: str, jwt: str, phase: TrustedProjectPhase, version_name: str
-) -> tuple[dict[str, Any], str, sql.Project]:
- payload, asf_uid, project = await trusted_jwt(publisher, jwt, phase)
+async def trusted_jwt_for_dist(
+ publisher: str, jwt: str, asf_uid: str, phase: TrustedProjectPhase,
project_name: str, version_name: str
+) -> tuple[dict[str, Any], str, sql.Project, sql.Release]:
+ payload, _asf_uid = await validate_trusted_jwt(publisher, jwt)
+ # payload, asf_uid, project = await trusted_jwt(publisher, jwt, phase)
async with db.session() as db_data:
- release = await db_data.release(project_name=project.name,
version=version_name).get()
+ project = await db_data.project(name=project_name,
_committee=True).demand(
+ InteractionError(f"Project {project_name} does not exist")
+ )
+ release = await db_data.release(project_name=project_name,
version=version_name).get()
if not release:
- raise InteractionError(f"Release {version_name} does not exist in
project {project.name}")
+ raise InteractionError(f"Release {version_name} does not exist in
project {project_name}")
if (phase == TrustedProjectPhase.COMPOSE) and (release.phase !=
sql.ReleasePhase.RELEASE_CANDIDATE_DRAFT):
raise InteractionError(f"Release {version_name} is not in compose
phase")
if (phase == TrustedProjectPhase.VOTE) and (release.phase !=
sql.ReleasePhase.RELEASE_CANDIDATE):
@@ -412,7 +416,7 @@ async def trusted_jwt_for_version(
if (phase == TrustedProjectPhase.FINISH) and (release.phase !=
sql.ReleasePhase.RELEASE_PREVIEW):
raise InteractionError(f"Release {version_name} is not in finish
phase")
- return payload, asf_uid, project
+ return payload, asf_uid, project, release
async def unfinished_releases(asfuid: str) -> list[tuple[str, str,
list[sql.Release]]]:
diff --git a/atr/models/api.py b/atr/models/api.py
index 4be4f96..e4dcb59 100644
--- a/atr/models/api.py
+++ b/atr/models/api.py
@@ -72,6 +72,8 @@ class DistributeSshRegisterArgs(schema.Strict):
jwt: str = schema.example("eyJhbGciOiJIUzI1[...]mMjLiuyu5CSpyHI=")
ssh_key: str = schema.example("ssh-ed25519
AAAAC3NzaC1lZDI1NTEgH5C9okWi0dh25AAAAIOMqqnkVzrm0SdG6UOoqKLsabl9GKJl")
phase: str = schema.Field(strict=False, default="compose",
json_schema_extra={"examples": ["compose", "finish"]})
+ asf_uid: str = schema.example("user")
+ project_name: str = schema.example("tooling")
version: str = schema.example("0.0.1")
diff --git a/atr/post/distribution.py b/atr/post/distribution.py
index f5aea27..706bafa 100644
--- a/atr/post/distribution.py
+++ b/atr/post/distribution.py
@@ -21,8 +21,10 @@ from typing import Final
import atr.blueprints.post as post
import atr.db as db
+import atr.db.interaction as interaction
import atr.get as get
import atr.models.distribution as distribution
+import atr.models.sql as sql
import atr.shared as shared
import atr.storage as storage
import atr.web as web
@@ -63,7 +65,14 @@ async def automate_form_process_page(
release, committee = await
shared.distribution.release_validated_and_committee(
project, version, staging=staging, release_policy=True
)
-
+ phase = interaction.TrustedProjectPhase.COMPOSE
+ match release.phase:
+ case sql.ReleasePhase.RELEASE_PREVIEW:
+ phase = interaction.TrustedProjectPhase.FINISH
+ case sql.ReleasePhase.RELEASE_CANDIDATE:
+ phase = interaction.TrustedProjectPhase.VOTE
+ case sql.ReleasePhase.RELEASE_CANDIDATE_DRAFT:
+ phase = interaction.TrustedProjectPhase.COMPOSE
async with
storage.write_as_committee_member(committee_name=committee.name) as w:
try:
await w.distributions.automate(
@@ -73,6 +82,7 @@ async def automate_form_process_page(
dd.owner_namespace,
project,
version,
+ phase.value,
release.latest_revision_number,
dd.package,
dd.version,
diff --git a/atr/storage/writers/distributions.py
b/atr/storage/writers/distributions.py
index d74404b..9179eed 100644
--- a/atr/storage/writers/distributions.py
+++ b/atr/storage/writers/distributions.py
@@ -105,6 +105,7 @@ class CommitteeMember(CommitteeParticipant):
owner_namespace: str | None,
project_name: str,
version_name: str,
+ phase: str,
revision_number: str | None,
package: str,
version: str,
@@ -119,6 +120,7 @@ class CommitteeMember(CommitteeParticipant):
version=version,
project_name=project_name,
version_name=version_name,
+ phase=phase,
platform=platform.name,
staging=staging,
asf_uid=self.__asf_uid,
diff --git a/atr/tasks/gha.py b/atr/tasks/gha.py
index 09741bc..115e5c4 100644
--- a/atr/tasks/gha.py
+++ b/atr/tasks/gha.py
@@ -48,6 +48,7 @@ class DistributionWorkflow(schema.Strict):
staging: bool = schema.description("Whether this is a staging
distribution")
project_name: str = schema.description("Project name in ATR")
version_name: str = schema.description("Version name in ATR")
+ phase: str = schema.description("Release phase in ATR")
asf_uid: str = schema.description("ASF UID of the user triggering the
workflow")
committee_name: str = schema.description("Committee name in ATR")
platform: str = schema.description("Distribution platform")
@@ -67,7 +68,9 @@ async def trigger_workflow(args: DistributionWorkflow, *,
task_id: int | None =
"ref": "main",
"inputs": {
"atr-id": unique_id,
+ "asf-uid": args.asf_uid,
"project": args.project_name,
+ "phase": args.phase,
"version": args.version_name,
"distribution-owner-namespace": args.namespace,
"distribution-package": args.package,
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]