asf-tooling commented on issue #751:
URL:
https://github.com/apache/tooling-trusted-releases/issues/751#issuecomment-4403367153
<!-- gofannon-issue-triage-bot v2 -->
**Automated triage** — analyzed at `main@837830e8`
**Type:** `discussion` • **Classification:** `no_action` •
**Confidence:** `high`
**Application domain(s):** `distribution_platforms`, `release_lifecycle`,
`artifact_validation`
### Summary
This issue is an investigation/RFC about whether ATR should support remote
promotion of artifacts on third-party distribution platforms (e.g., promoting a
Maven Central staging deployment to production) rather than re-uploading from
ATR. The issue outlines platform-specific capabilities and caveats but does not
request a specific code change yet. It identifies that tracking which revision
was uploaded during staging would be needed, and that validation must ensure
promoted files match voted-on artifacts.
### Where this lives in the code today
#### `atr/storage/writers/distributions.py` —
`CommitteeMember.__upgrade_staging_to_final` (lines 164-197)
_currently does this_
This method already handles upgrading a staging distribution record to
final/production in the database, but it only updates the ATR record—it does
not trigger any remote promotion API call on the platform itself.
```python
async def __upgrade_staging_to_final(
self,
release_key: models.safe.ReleaseKey,
platform: models.sql.DistributionPlatform,
owner_namespace: str | None,
package: str,
version: str,
pending: bool,
upload_date: datetime.datetime | None,
api_url: str | None,
web_url: str | None,
) -> models.sql.Distribution | None:
tag = f"{release_key} {platform} {owner_namespace or ''} {package}
{version}"
existing = await self.__data.distribution(
release_key=str(release_key),
platform=platform,
owner_namespace=(owner_namespace or ""),
package=package,
version=version,
).demand(RuntimeError(f"Distribution {tag} not found"))
if existing.staging:
existing.staging = False
existing.pending = pending
existing.upload_date = upload_date
existing.api_url = api_url
existing.web_url = web_url
existing.created_by = self.__asf_uid
await self.__data.commit()
return existing
return None
```
#### `atr/storage/writers/distributions.py` — `CommitteeMember.record`
(lines 99-162)
_extension point_
The record method detects when a production record is being made for an
existing staging record and calls __upgrade_staging_to_final. This is where
remote promotion logic could be integrated in the future.
```python
async def record(
self,
release_key: models.safe.ReleaseKey,
platform: models.sql.DistributionPlatform,
owner_namespace: models.safe.Alphanumeric | None,
package: models.safe.Alphanumeric,
version: models.safe.VersionKey,
staging: bool,
pending: bool,
upload_date: datetime.datetime | None,
api_url: str | None = None,
web_url: str | None = None,
) -> tuple[models.sql.Distribution, bool]:
...
# If we're doing production and existing was for staging, upgrade it
if (not staging) and existing.staging:
upgraded = await self.__upgrade_staging_to_final(
release_key,
platform,
namespace,
str(package),
str(version),
pending,
upload_date,
api_url,
web_url,
)
...
```
#### `atr/storage/writers/distributions.py` — `CommitteeMember.automate`
(lines 64-97)
_extension point_
The automate method creates distribution workflow tasks. It already accepts
a revision_number parameter, which partially addresses the issue's requirement
of tracking which revision was staged. A promotion workflow could be added
alongside this.
```python
async def automate(
self,
release_key: models.safe.ReleaseKey,
platform: models.sql.DistributionPlatform,
committee_key: str,
owner_namespace: models.safe.Alphanumeric | None,
project_key: models.safe.ProjectKey,
version_key: models.safe.VersionKey,
phase: str,
revision_number: str | None,
package: models.safe.Alphanumeric,
version: models.safe.VersionKey,
staging: bool,
) -> models.sql.Task:
```
#### `atr/shared/distribution.py` — `DistributionPlatform` (lines 79-101)
_currently does this_
The supported distribution platforms are enumerated here. Remote promotion
support would vary per platform as described in the issue (Maven supports it,
PyPI/ArtifactHub don't, Docker/npm only with mutable tags).
```python
class DistributionPlatform(enum.Enum):
"""Wrapper enum for distribution platforms."""
ARTIFACT_HUB = "Artifact Hub"
DOCKER_HUB = "Docker Hub"
MAVEN = "Maven Central"
NPM = "npm"
NPM_SCOPED = "npm (scoped)"
PYPI = "PyPI"
```
#### `atr/post/distribution.py` — `automate_form_process_page` (lines 43-100)
_extension point_
This is where automated distribution is triggered. A 'promote' action could
be added here that, instead of re-uploading, calls a platform-specific
promotion API (e.g., Maven Central's publish endpoint).
```python
async def automate_form_process_page(
session: web.Committer,
form_data: shared.distribution.DistributionAutomateForm,
project: safe.ProjectKey,
version: safe.VersionKey,
/,
staging: bool = False,
) -> web.WerkzeugResponse:
allowed_platforms = _AUTOMATED_PLATFORMS_STAGE if staging else
_AUTOMATED_PLATFORMS
if form_data.platform not in allowed_platforms:
...
async with
storage.write_as_committee_member(committee_key=committee.key) as w:
try:
await w.distributions.automate(
release.safe_key,
dd.platform,
committee.key,
dd.owner_namespace,
project,
version,
phase.value,
release.latest_revision_number,
dd.package,
dd.version,
staging,
)
...
```
#### `atr/tasks/distribution.py` — `status_check` (lines 32-69)
_currently does this_
The background task that retries pending distributions. Remote promotion
would likely integrate into this retry/status-check loop if promotion is
asynchronous.
```python
@checks.with_model(args.DistributionStatusCheckArgs)
async def status_check(
task_args: args.DistributionStatusCheckArgs, *, task_id: int | None =
None
) -> results.Results | None:
log.info("Checking pending recorded distributions")
dists = []
async with db.session() as data:
dists = await data.distribution(
pending=True, _with_release=True, _with_release_project=True,
_limit=_BATCH_SIZE
).all()
for dist in dists:
...
```
### Where new code would go
- `atr/storage/writers/distributions.py` — after symbol
CommitteeMember.__upgrade_staging_to_final
A new method like `promote_staging_to_production` would live here, calling
platform-specific promotion APIs (e.g., Maven Central's publish endpoint) after
validating that the staged revision matches the voted-on revision.
- `atr/shared/distribution.py` — after symbol DistributionPlatform
A property or method on DistributionPlatform indicating whether the
platform supports remote promotion would be needed to gate the feature.
- `atr/tasks/checks/` — new file
A new check that validates staged artifacts match voted-on artifacts
(revision tracking) could be implemented as a task check.
### Proposed approach
This issue is an investigation/discussion rather than a concrete feature
request. It outlines the conceptual requirements for remote promotion: (1)
track which file revision was uploaded to staging, (2) validate that those
files haven't changed in subsequent revisions before allowing promotion, (3)
implement platform-specific promotion APIs where supported (currently only
Maven Central clearly supports this). The existing code already has some
infrastructure for this: `automate()` stores `revision_number`, and
`__upgrade_staging_to_final()` handles the database-side staging→production
transition. However, significant new work would be needed: per-platform
promotion API calls, revision-to-file hash tracking, and validation logic
comparing staged vs. voted-on artifacts. No concrete patch is appropriate at
this stage since the issue explicitly frames this as investigation.
### Open questions
- Which platforms should be prioritized for remote promotion support? The
issue suggests Maven Central is the clearest candidate.
- How should revision tracking be implemented? The `revision_number` field
exists on Task but there's no explicit record of which file hashes were staged
to a platform.
- Should a new SQL model be created to track per-file-per-platform staging
state (file hash, revision number, platform deployment ID)?
- For platforms with mutable tags (Docker Hub, npm), is promotion via tag
reassignment acceptable from a supply chain security perspective?
- Does this feature need to be gated behind a release policy setting so
projects can opt in/out?
_The agent reviewed this issue and is not proposing patches in this run.
Review the existing-code citations and open questions above before deciding
next steps._
### Files examined
- `atr/shared/distribution.py`
- `atr/storage/writers/distributions.py`
- `atr/tasks/distribution.py`
- `atr/get/distribution.py`
- `atr/models/distribution.py`
- `atr/post/distribution.py`
- `atr/get/finish.py`
- `atr/post/finish.py`
---
*Draft from a triage agent. A human reviewer should validate before merging
any change. The agent did not run tests or verify diffs apply.*
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]