mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-06 02:54:26 +00:00
Relocates `cli/meta/{ports,networks/suggest}` to
`cli/contributing/network/{ports,address/suggest}` so port and subnet
allocators live alongside the rest of the contributor-side tooling
(mirror, update, changelog) instead of `meta`. Mirrors the tests
into `tests/unit/cli/contributing/network/` and renames the contract
docs to `docs/contributing/tools/network/{port,address}.md`. Prog
names update from `cli meta ports suggest` / `cli meta networks
suggest` to `cli contributing network ports suggest` / `cli
contributing network address suggest`; the corresponding lint
references and `utils.meta.scan` docstring follow.
Adds a third subcommand: `cli contributing network diagnose`
(stdlib-only DNS / TCP / TLS / PMTU probe against the standard
infrastructure hosts plus interface MTU, `/etc/resolv.conf`,
`/etc/hosts`, proxy env, CA-bundle summaries). Split across `cli.py`
(orchestration), `config.py` (SPOT for hosts / per-distro install
commands), `format.py` (output + subprocess helpers), `tools.py`
(distro-aware auto-install of `iputils-ping` + `iproute2`),
`report.py` (system-info dumps + IPv6-default-route detection), and
`probes.py` (per-host probes). Exposed as `make debug-network`.
Companion `docs/contributing/actions/debugging/network.md` absorbs
the diagnose-tool walkthrough (incl. how to read MTU-induced TLS
handshake timeouts) so the merged page covers DNS / MTU / IPv6 /
connectivity end-to-end.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
40 lines
1.1 KiB
Python
40 lines
1.1 KiB
Python
"""Output and subprocess helpers."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import subprocess
|
|
import sys
|
|
from typing import TYPE_CHECKING
|
|
|
|
if TYPE_CHECKING:
|
|
from collections.abc import Sequence
|
|
|
|
|
|
def section(title: str, *, file=None) -> None:
|
|
print(f"\n=== {title} ===", flush=True, file=file or sys.stdout)
|
|
|
|
|
|
def line(label: str, value: str, *, file=None) -> None:
|
|
print(f" {label}: {value}", flush=True, file=file or sys.stdout)
|
|
|
|
|
|
def cmd_capture(argv: Sequence[str], timeout: float = 5.0) -> tuple[int, str]:
|
|
"""Run argv and return (returncode, combined stdout+stderr).
|
|
|
|
Returns (-1, "command not found: …") when the binary is missing.
|
|
Returns (-2, "timeout after …") when the call exceeds ``timeout``.
|
|
"""
|
|
try:
|
|
p = subprocess.run(
|
|
list(argv),
|
|
capture_output=True,
|
|
text=True,
|
|
timeout=timeout,
|
|
check=False,
|
|
)
|
|
return p.returncode, (p.stdout or "") + (p.stderr or "")
|
|
except FileNotFoundError:
|
|
return -1, f"command not found: {argv[0]}"
|
|
except subprocess.TimeoutExpired:
|
|
return -2, f"timeout after {timeout}s: {' '.join(argv)}"
|