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
commit 70d1bfd748a4f7be0ba471c22a2b4bb480a2c1c3 Author: Sean B. Palmer <[email protected]> AuthorDate: Tue Sep 9 18:45:57 2025 +0100 Allow recording distributions from GitHub during the compose phase --- atr/blueprints/api/api.py | 18 +++++++++++++----- atr/db/interaction.py | 21 +++++++++++++-------- atr/templates/about.html | 4 +++- 3 files changed, 29 insertions(+), 14 deletions(-) diff --git a/atr/blueprints/api/api.py b/atr/blueprints/api/api.py index 90b3f41..10e39cd 100644 --- a/atr/blueprints/api/api.py +++ b/atr/blueprints/api/api.py @@ -589,11 +589,19 @@ async def publisher_distribution_record(data: models.api.PublisherDistributionRe """ Record a distribution with a corroborating Trusted Publisher JWT. """ - _payload, asf_uid, project = await interaction.trusted_jwt( - data.publisher, - data.jwt, - interaction.TrustedProjectPhase.FINISH, - ) + try: + _payload, asf_uid, project = await interaction.trusted_jwt( + data.publisher, + data.jwt, + interaction.TrustedProjectPhase.FINISH, + ) + except interaction.ReleasePolicyNotFoundError: + # TODO: We could perform a more advanced query with multiple in_ statements + _payload, asf_uid, project = await interaction.trusted_jwt( + data.publisher, + data.jwt, + interaction.TrustedProjectPhase.COMPOSE, + ) async with db.session() as db_data: release_name = models.sql.release_name(project.name, data.version) release = await db_data.release( diff --git a/atr/db/interaction.py b/atr/db/interaction.py index be3bd28..8fd4869 100644 --- a/atr/db/interaction.py +++ b/atr/db/interaction.py @@ -69,6 +69,10 @@ class PublicKeyError(RuntimeError): pass +class ReleasePolicyNotFoundError(RuntimeError): + pass + + class TrustedProjectPhase(enum.Enum): COMPOSE = "compose" VOTE = "vote" @@ -472,29 +476,32 @@ async def _delete_release_data_filesystem(release_dir: pathlib.Path, release_nam async def _trusted_project(repository: str, workflow_ref: str, phase: TrustedProjectPhase) -> sql.Project: # Debugging log.info(f"GitHub OIDC JWT payload: {repository} {workflow_ref}") - repository_name, workflow_path = _trusted_project_checks(repository, workflow_ref, phase) + repository_name, workflow_path = _trusted_project_checks(repository, workflow_ref) - value_error = ValueError( + rpnf_error = ReleasePolicyNotFoundError( f"Release policy for repository {repository_name} and {phase.value} workflow path {workflow_path} not found" ) # TODO: If a policy is reused between projects, we can't get the project async with db.session() as db_data: match phase: case TrustedProjectPhase.COMPOSE: + # Searches in github_*compose*_workflow_path policy = await db_data.release_policy( github_repository_name=repository_name, github_compose_workflow_path_has=workflow_path, - ).demand(value_error) + ).demand(rpnf_error) case TrustedProjectPhase.VOTE: + # Searches in github_*vote*_workflow_path policy = await db_data.release_policy( github_repository_name=repository_name, github_vote_workflow_path_has=workflow_path, - ).demand(value_error) + ).demand(rpnf_error) case TrustedProjectPhase.FINISH: + # Searches in github_*finish*_workflow_path policy = await db_data.release_policy( github_repository_name=repository_name, github_finish_workflow_path_has=workflow_path, - ).demand(value_error) + ).demand(rpnf_error) project = await db_data.project(release_policy_id=policy.id).demand( InteractionError(f"Project for release policy {policy.id} not found") ) @@ -502,12 +509,10 @@ async def _trusted_project(repository: str, workflow_ref: str, phase: TrustedPro raise InteractionError(f"Project {project.name} has no committee") if project.committee.name not in registry.GITHUB_AUTOMATED_RELEASE_COMMITTEES: raise InteractionError(f"Project {project.name} is not in a committee that can make releases") - log.info(f"Release policy: {policy}") - log.info(f"Project: {project}") return project -def _trusted_project_checks(repository: str, workflow_ref: str, phase: TrustedProjectPhase) -> tuple[str, str]: +def _trusted_project_checks(repository: str, workflow_ref: str) -> tuple[str, str]: if not repository.startswith("apache/"): raise InteractionError("Repository must start with 'apache/'") repository_name = repository.removeprefix("apache/") diff --git a/atr/templates/about.html b/atr/templates/about.html index 2b88c20..0bd74ce 100644 --- a/atr/templates/about.html +++ b/atr/templates/about.html @@ -85,7 +85,9 @@ <td class="ui"> <code>/distribution/stage/P/V</code> </td> - <td class="cli">-</td> + <td class="cli"> + <code>atr distribution record P V plat owner pkg ver stg details</code> + </td> <td class="github">-</td> </tr> <tr> --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
