Add dry-run apply activation plan

This commit is contained in:
jwinterm
2026-07-06 04:54:03 -04:00
parent 27f3805c19
commit 83847b205b
6 changed files with 464 additions and 3 deletions
+70
View File
@@ -4,6 +4,12 @@ import argparse
from pathlib import Path
import sys
from .activation import (
ActivationStep,
activation_steps,
blocked_steps,
write_activation_artifacts,
)
from .audit import audit_gateway
from .build import build_gateway
from .config import load_config
@@ -54,6 +60,25 @@ def main(argv: list[str] | None = None) -> int:
choices=PLATFORM_NAMES,
help="Override platform detection for dry-run checks.",
)
apply_parser = subcommands.add_parser(
"apply",
help="Show or run the transport activation sequence.",
)
apply_parser.add_argument(
"--dry-run",
action="store_true",
help="Print the activation sequence without changing services.",
)
apply_parser.add_argument(
"--write-artifacts",
action="store_true",
help="Write generated config snippets to the configured plan root.",
)
apply_parser.add_argument(
"--platform",
choices=PLATFORM_NAMES,
help="Override platform detection for dry-run checks.",
)
subcommands.add_parser("build", help="Build enabled protocol outputs.")
subcommands.add_parser("manifest", help="Write AMPB fixture manifests.")
preview_parser = subcommands.add_parser("preview", help="Preview generated outputs locally.")
@@ -132,6 +157,8 @@ def main(argv: list[str] | None = None) -> int:
return _cmd_status(config, args)
if args.command == "doctor":
return _cmd_doctor(config, args)
if args.command == "apply":
return _cmd_apply(config, args)
if args.command == "build":
return _cmd_build(config)
if args.command == "manifest":
@@ -148,6 +175,36 @@ def main(argv: list[str] | None = None) -> int:
return 1
def _cmd_apply(config, args) -> int:
if not args.dry_run:
print(
'AMPG_APPLY status=error message="live apply is not implemented; rerun with --dry-run"',
file=sys.stderr,
)
return 1
if args.write_artifacts:
for path in write_activation_artifacts(config):
print(f"AMPG_APPLY_ARTIFACT path={path} status=written")
steps = activation_steps(config, platform_provider=_platform_override(args))
for step in steps:
_print_activation_step(step)
blocked = blocked_steps(steps)
print(
"AMPG_APPLY_SUMMARY "
"mode=dry-run "
f"sites={len(config.sites)} "
f"steps={len(steps)} "
f"ready={sum(1 for step in steps if step.status == 'ready')} "
f"review={sum(1 for step in steps if step.status == 'review')} "
f"planned={sum(1 for step in steps if step.status == 'planned')} "
f"blocked={len(blocked)}"
)
return 1 if blocked else 0
def _cmd_status(config, args) -> int:
statuses = gateway_status(config, platform_provider=_platform_override(args))
for status in statuses:
@@ -235,6 +292,19 @@ def _cmd_build(config) -> int:
return 0
def _print_activation_step(step: ActivationStep) -> None:
print(
"AMPG_APPLY_STEP "
f"site={step.site_id} "
f"protocol={step.protocol} "
f"stage={step.stage} "
f"action={step.action} "
f"target={step.target} "
f"status={step.status} "
f"message=\"{_quote(step.message)}\""
)
def _print_transport_status(status: TransportStatus) -> None:
executable_path = status.executable_path or "-"
print(