Files
computer-playbook/cli/contributing/update/collection_source/__main__.py
T
kevinveenbirkenbachandClaude Opus 5 f0ecf3e337 style(update): apply the formatting the gate produced
The nocheck markers were written as long single lines; ruff splits the
call across three lines and leaves the marker behind the closing paren.
Committing the formatter's own output keeps the tree and the history in
step.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 21:51:25 +02:00

159 lines
4.6 KiB
Python
Executable File

#!/usr/bin/env python3
from __future__ import annotations
import argparse
import json
import re
import subprocess
import sys
import time
from pathlib import Path
from tempfile import TemporaryDirectory
from utils.update.collection_source import (
RATIO,
SOURCES,
WINDOW,
append_sample,
decide,
load_history,
)
from . import PROJECT_ROOT
SETTING = "INFINITO_ANSIBLE_COLLECTIONS_SOURCE"
REQUIREMENTS = {
"galaxy": Path("requirements/requirements.galaxy.yml"),
"git": Path("requirements/requirements.git.yml"),
}
def read_preferred(env_file: Path) -> str:
"""The source currently tried first, as declared in default.env.
Args:
env_file: the default.env holding the setting.
"""
match = re.search(
rf"^{SETTING}=(\S+)\s*$",
env_file.read_text(
encoding="utf-8"
), # nocheck: cache-read -- write_preferred rewrites this file in the same run
re.MULTILINE,
)
if match is None:
raise SystemExit(f"{SETTING} is not declared in {env_file}")
return match.group(1)
def write_preferred(env_file: Path, source: str) -> None:
"""Point the setting at SOURCE.
Args:
env_file: the default.env holding the setting.
source: the source to try first from now on.
"""
text = env_file.read_text(
encoding="utf-8"
) # nocheck: cache-read -- rewritten on the next line
env_file.write_text(
re.sub(rf"^{SETTING}=\S+$", f"{SETTING}={source}", text, flags=re.MULTILINE),
encoding="utf-8",
)
def measure(repo_root: Path, requirements: Path, timeout: int) -> float | None:
"""Seconds a cold install from REQUIREMENTS takes, or None when it fails.
Args:
repo_root: repository root the requirements path is relative to.
requirements: the requirements file to install from.
timeout: seconds after which the install counts as failed.
"""
with TemporaryDirectory() as target:
started = time.monotonic()
try:
completed = subprocess.run(
[
sys.executable,
"-m",
"ansible.cli.galaxy",
"collection",
"install",
"-r",
str(repo_root / requirements),
"-p",
target,
"--force-with-deps",
],
capture_output=True,
text=True,
timeout=timeout,
check=False,
)
except subprocess.TimeoutExpired:
return None
elapsed = time.monotonic() - started
return elapsed if completed.returncode == 0 else None
def main() -> int:
parser = argparse.ArgumentParser(
description=(
"Time both collection sources, record the sample, and retune the "
"preferred default when one source is durably slower."
)
)
parser.add_argument("--repo-root", type=Path, default=PROJECT_ROOT)
parser.add_argument(
"--history",
type=Path,
default=None,
help="JSON file holding the rolling window of samples",
)
parser.add_argument(
"--timeout",
type=int,
default=900,
help="Seconds after which one install counts as failed",
)
args = parser.parse_args()
repo_root = args.repo_root.resolve()
env_file = repo_root / "default.env"
history_file = (
args.history or repo_root / "build" / "collection-source-history.json"
)
sample: dict[str, float | None] = {}
for source in SOURCES:
seconds = measure(repo_root, REQUIREMENTS[source], args.timeout)
sample[source] = seconds
print(f"{source}: {'failed' if seconds is None else f'{seconds:.1f}s'}")
history = append_sample(load_history(history_file), sample)
history_file.parent.mkdir(parents=True, exist_ok=True)
history_file.write_text(json.dumps(history, indent=2), encoding="utf-8")
preferred = read_preferred(env_file)
verdict = decide(history, preferred)
print(
f"samples: {verdict.samples}/{WINDOW}, "
f"medians: {verdict.medians}, preferred: {verdict.preferred}"
)
if not verdict.changed:
print("Preferred collection source stays unchanged.")
return 0
write_preferred(env_file, verdict.proposed)
print(
f"Preferred collection source {verdict.preferred} -> {verdict.proposed}: "
f"its median is at least {RATIO}x the other's over {WINDOW} samples."
)
return 0
if __name__ == "__main__":
raise SystemExit(main())