Files
MrBlake 0440b6a48f
CI / php-store (push) Waiting to run
CI / python-components (push) Waiting to run
Improve artifact availability UX
2026-08-24 22:42:56 +02:00

74 lines
2.9 KiB
Python

from __future__ import annotations
from django import forms
from .client import CatalogPlugin
from .runtime import RuntimeSettings
class LifecycleConfirmForm(forms.Form):
confirmation = forms.CharField(
max_length=64,
label="Plugin-Slug zur Bestätigung",
help_text="Diese Eingabe verhindert versehentliche Lifecycle-Aktionen.",
)
version = forms.ChoiceField(required=False, label="Version")
dry_run = forms.BooleanField(
required=False,
initial=True,
label="Nur prüfen (Dry-Run)",
help_text="Plant und validiert den Vorgang, ohne Dateien oder Prozesse zu verändern.",
)
def __init__(
self,
*args,
plugin: CatalogPlugin,
action: str,
runtime: RuntimeSettings,
**kwargs,
):
super().__init__(*args, **kwargs)
self.plugin = plugin
self.action = action
self.runtime = runtime
self.fields["confirmation"].widget.attrs.update({"autocomplete": "off", "placeholder": plugin.slug})
self.fields["dry_run"].initial = runtime.default_dry_run
self.has_installable_release = True
if action in {"install", "update"}:
choices = [
(release.version, release.version)
for release in plugin.installable_releases(
runtime.netbox_version,
require_approval_marker=runtime.execution_mode == "agent",
)
]
choices.sort(reverse=True)
self.fields["version"].choices = choices
self.has_installable_release = bool(choices)
self.fields["version"].required = self.has_installable_release
self.fields["version"].disabled = not self.has_installable_release
self.fields["version"].initial = plugin.latest_version
else:
self.fields.pop("version")
for field in self.fields.values():
if not isinstance(field.widget, forms.CheckboxInput):
field.widget.attrs.setdefault("class", "form-control")
def clean_confirmation(self) -> str:
value = self.cleaned_data["confirmation"]
if value != self.plugin.slug:
raise forms.ValidationError("Der Slug stimmt nicht exakt überein.")
return value
def clean(self):
cleaned = super().clean()
if self.action in {"install", "update"} and not self.has_installable_release:
raise forms.ValidationError(
"Keine freigegebene, kompatible Plugin-Version ist verfügbar. "
"Das Source-Artefakt muss zunächst im Store synchronisiert und freigegeben werden."
)
if self.runtime.execution_mode == "dry_run" and not cleaned.get("dry_run", False):
self.add_error("dry_run", "Reale Aktionen sind in execution_mode=dry_run deaktiviert.")
return cleaned