This is an automated email from the ASF dual-hosted git repository.
arm pushed a commit to branch arm
in repository https://gitbox.apache.org/repos/asf/tooling-trusted-releases.git
The following commit(s) were added to refs/heads/arm by this push:
new d5047c89 Disable automated staging distributions for alpha. Filter
automated distributions to only support Maven Central for now.
d5047c89 is described below
commit d5047c89d1cb0a35ad90be3965c97524f1dc2a0e
Author: Alastair McFarlane <[email protected]>
AuthorDate: Tue Mar 10 12:08:35 2026 +0000
Disable automated staging distributions for alpha. Filter automated
distributions to only support Maven Central for now.
---
atr/form.py | 14 +++++++++++++-
atr/get/distribution.py | 5 ++---
atr/post/distribution.py | 12 ++++++------
atr/shared/distribution.py | 39 +++++++++++++++++++++++++++++++++++++--
atr/templates/check-selected.html | 18 ++++++++----------
5 files changed, 66 insertions(+), 22 deletions(-)
diff --git a/atr/form.py b/atr/form.py
index d3f06ba6..4417478b 100644
--- a/atr/form.py
+++ b/atr/form.py
@@ -149,13 +149,15 @@ def json_suitable(field_value: Any) -> Any:
def label(
- description: str, documentation: str | None = None, *, default: Any = ...,
widget: Widget | None = None
+ description: str, documentation: str | None = None, *, default: Any = ...,
widget: Widget | None = None, **kwargs
) -> Any:
extra: dict[str, Any] = {}
if widget is not None:
extra["widget"] = widget.value
if documentation is not None:
extra["documentation"] = documentation
+ if len(kwargs) > 0:
+ extra.update(kwargs)
return pydantic.Field(default, description=description,
json_schema_extra=extra)
@@ -616,6 +618,7 @@ def widget(widget_type: Widget) -> Any:
def _get_choices(field_info: pydantic.fields.FieldInfo) -> list[tuple[str,
str]]: # noqa: C901
annotation = field_info.annotation
origin = get_origin(annotation)
+ json_schema_extra = field_info.json_schema_extra or {}
if origin is Literal:
return [(v, v) for v in get_args(annotation)]
@@ -627,6 +630,9 @@ def _get_choices(field_info: pydantic.fields.FieldInfo) ->
list[tuple[str, str]]
inner_type = args[0]
if isinstance(inner_type, type) and issubclass(inner_type,
enum.Enum):
# This is an enum type wrapped in Annotated, from Enum[T] or
Set[T]
+ if isinstance(json_schema_extra, dict):
+ if filter_keys :=
json_schema_extra.get("enum_filter_include", None):
+ return [(member.value, member.value) for member in
inner_type if member.value in filter_keys]
return [(member.value, member.value) for member in inner_type]
if origin is set:
@@ -634,6 +640,9 @@ def _get_choices(field_info: pydantic.fields.FieldInfo) ->
list[tuple[str, str]]
if args:
enum_class = args[0]
if isinstance(enum_class, type) and issubclass(enum_class,
enum.Enum):
+ if isinstance(json_schema_extra, dict):
+ if filter_keys :=
json_schema_extra.get("enum_filter_include", None):
+ return [(member.value, member.value) for member in
enum_class if member.value in filter_keys]
return [(member.value, member.value) for member in enum_class]
if origin is list:
@@ -643,6 +652,9 @@ def _get_choices(field_info: pydantic.fields.FieldInfo) ->
list[tuple[str, str]]
# Check for plain enum types, e.g. when Pydantic unwraps form.Enum[T]
if isinstance(annotation, type) and issubclass(annotation, enum.Enum):
+ if isinstance(json_schema_extra, dict):
+ if filter_keys := json_schema_extra.get("enum_filter_include",
None):
+ return [(member.value, member.value) for member in annotation
if member.value in filter_keys]
return [(member.value, member.value) for member in annotation]
return []
diff --git a/atr/get/distribution.py b/atr/get/distribution.py
index efcedfe8..a8742e58 100644
--- a/atr/get/distribution.py
+++ b/atr/get/distribution.py
@@ -215,10 +215,9 @@ async def _automate_form_page(project: safe.ProjectName,
version: safe.VersionNa
else util.as_url(post.distribution.automate_selected,
project_name=str(project), version_name=str(version))
)
- # TODO: Reuse the same form for now - maybe we can combine this and the
function below adding an automate=True arg
# Render the distribution form
form_html = form.render(
- model_cls=shared.distribution.DistributeForm,
+ model_cls=shared.distribution.DistributionAutomateForm,
submit_label="Distribute",
action=action,
defaults={"package": str(project), "version": str(version)},
@@ -294,7 +293,7 @@ async def _record_form_page(project: safe.ProjectName,
version: safe.VersionName
# Render the distribution form
form_html = form.render(
- model_cls=shared.distribution.DistributeForm,
+ model_cls=shared.distribution.DistributionRecordForm,
submit_label="Record distribution",
action=action,
defaults={"package": str(project), "version": str(version)},
diff --git a/atr/post/distribution.py b/atr/post/distribution.py
index fd70485d..5680c02f 100644
--- a/atr/post/distribution.py
+++ b/atr/post/distribution.py
@@ -40,7 +40,7 @@ _AUTOMATED_PLATFORMS_STAGE:
Final[tuple[shared.distribution.DistributionPlatform
async def automate_form_process_page(
session: web.Committer,
- form_data: shared.distribution.DistributeForm,
+ form_data: shared.distribution.DistributionAutomateForm,
project: safe.ProjectName,
version: safe.VersionName,
/,
@@ -114,7 +114,7 @@ async def automate_selected(
_distribution_automate: Literal["distribution/automate"],
project_name: safe.ProjectName,
version_name: safe.VersionName,
- distribute_form: shared.distribution.DistributeForm,
+ distribute_form: shared.distribution.DistributionAutomateForm,
) -> web.WerkzeugResponse:
"""
URL: /distribution/automate/<project_name>/<version_name>
@@ -169,7 +169,7 @@ async def delete(
async def record_form_process_page(
session: web.Committer,
- form_data: shared.distribution.DistributeForm,
+ form_data: shared.distribution.DistributionRecordForm,
project: safe.ProjectName,
version: safe.VersionName,
/,
@@ -222,7 +222,7 @@ async def record_selected(
_distribution_record: Literal["distribution/record"],
project_name: safe.ProjectName,
version_name: safe.VersionName,
- distribute_form: shared.distribution.DistributeForm,
+ distribute_form: shared.distribution.DistributionRecordForm,
) -> web.WerkzeugResponse:
"""
URL: /distribution/record/<project_name>/<version_name>
@@ -236,7 +236,7 @@ async def stage_automate_selected(
_distribution_stage_automate: Literal["distribution/stage/automate"],
project_name: safe.ProjectName,
version_name: safe.VersionName,
- distribute_form: shared.distribution.DistributeForm,
+ distribute_form: shared.distribution.DistributionAutomateForm,
) -> web.WerkzeugResponse:
"""
URL: /distribution/stage/automate/<project_name>/<version_name>
@@ -250,7 +250,7 @@ async def stage_record_selected(
_distribution_stage_record: Literal["distribution/stage/record"],
project_name: safe.ProjectName,
version_name: safe.VersionName,
- distribute_form: shared.distribution.DistributeForm,
+ distribute_form: shared.distribution.DistributionRecordForm,
) -> web.WerkzeugResponse:
"""
URL: /distribution/stage/record/<project_name>/<version_name>
diff --git a/atr/shared/distribution.py b/atr/shared/distribution.py
index 356c7889..b565f6ba 100644
--- a/atr/shared/distribution.py
+++ b/atr/shared/distribution.py
@@ -122,7 +122,42 @@ class DeleteForm(form.Form):
version: str = form.label("Version", widget=form.Widget.HIDDEN)
-class DistributeForm(form.Form):
+class DistributionAutomateForm(form.Form):
+ platform: form.Enum[DistributionPlatform] = form.label(
+ "Platform", widget=form.Widget.SELECT,
enum_filter_include=[DistributionPlatform.MAVEN.value]
+ )
+ owner_namespace: str = form.label(
+ "Owner or Namespace",
+ "Who owns or names the package (Maven groupId, npm @scope, Docker
namespace, "
+ "GitHub owner, ArtifactHub repo). Leave blank if not used.",
+ )
+ package: str = form.label("Package")
+ version: str = form.label("Version")
+ details: form.Bool = form.label(
+ "Include details",
+ "Include the details of the distribution in the response",
+ )
+
+ @pydantic.model_validator(mode="after")
+ def validate_owner_namespace(self) -> DistributionAutomateForm:
+ platform_name: str = self.platform.name # type: ignore[attr-defined]
+ sql_platform = self.platform.to_sql() # type: ignore[attr-defined]
+ default_owner_namespace = sql_platform.value.default_owner_namespace
+ requires_owner_namespace = sql_platform.value.requires_owner_namespace
+
+ if default_owner_namespace and (not self.owner_namespace):
+ self.owner_namespace = default_owner_namespace
+
+ if requires_owner_namespace and (not self.owner_namespace):
+ raise ValueError(f'Platform "{platform_name}" requires an owner or
namespace.')
+
+ if (not requires_owner_namespace) and (not default_owner_namespace)
and self.owner_namespace:
+ raise ValueError(f'Platform "{platform_name}" does not require an
owner or namespace.')
+
+ return self
+
+
+class DistributionRecordForm(form.Form):
platform: form.Enum[DistributionPlatform] = form.label("Platform",
widget=form.Widget.SELECT)
owner_namespace: str = form.label(
"Owner or Namespace",
@@ -137,7 +172,7 @@ class DistributeForm(form.Form):
)
@pydantic.model_validator(mode="after")
- def validate_owner_namespace(self) -> DistributeForm:
+ def validate_owner_namespace(self) -> DistributionRecordForm:
platform_name: str = self.platform.name # type: ignore[attr-defined]
sql_platform = self.platform.to_sql() # type: ignore[attr-defined]
default_owner_namespace = sql_platform.value.default_owner_namespace
diff --git a/atr/templates/check-selected.html
b/atr/templates/check-selected.html
index ef25c692..ddce95cc 100644
--- a/atr/templates/check-selected.html
+++ b/atr/templates/check-selected.html
@@ -163,16 +163,16 @@
{% if phase == "release_candidate_draft" %}
<h3 id="distribution" class="mt-4">Distribution</h3>
<p>
- While this release is in draft, you can create a staging distribution.
Use the buttons below to either create one automatically (where supported) or
record a manual distribution performed outside of ATR.
+ While this release is in draft, you can create a staging distribution.
Use the button below to record a manual distribution performed outside of ATR.
</p>
- <div class="alert alert-warning mb-4">
- <p class="fw-semibold mb-1">NOTE:</p>
- <p>At present, automated distributions are being developed. Please use
the manual record button if you need to record a distribution.</p>
- </div>
+{# <div class="alert alert-warning mb-4">#}
+{# <p class="fw-semibold mb-1">NOTE:</p>#}
+{# <p>At present, automated distributions are being developed. Please use
the manual record button if you need to record a distribution.</p>#}
+{# </div>#}
<p>
+{# <a class="btn btn-primary"#}
+{# href="{{ as_url(get.distribution.stage_automate,
project_name=release.project.name, version_name=release.version)
}}">Distribute</a>#}
<a class="btn btn-primary"
- href="{{ as_url(get.distribution.stage_automate,
project_name=release.project.name, version_name=release.version)
}}">Distribute</a>
- <a class="btn btn-secondary"
href="{{ as_url(get.distribution.stage_record,
project_name=release.project.name, version_name=release.version) }}">Record a
manual distribution</a>
</p>
<h2 id="more-actions">More actions</h2>
@@ -189,9 +189,7 @@
<thead class="table-light">
<tr>
<th scope="col">
- Check
- <br />
- Path
+ Check Path
</th>
<th scope="col">Message</th>
<th scope="col">Status</th>
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]