mirror of
https://github.com/kevinveenbirkenbach/docker-volume-backup.git
synced 2026-09-13 00:16:28 +00:00
The package carried no ruff configuration at all, so it ran on the defaults (E4+E7+E9+F) while infinito-nexus-core, its only consumer, holds itself to a far wider selection. Measured against that selection this tree had 224 findings. It now has none. The selector list is core's verbatim so both repositories answer to one bar. target-version stays py39 rather than core's py311, because requires-python still declares >=3.9 and pyupgrade would otherwise propose syntax the declared minimum cannot run. Every ignore carries its reason: S603/S607 in particular, since running docker and dump binaries from PATH in list form is this tool's whole job and is already injection-safe. Two conversions are judgement rather than mechanics. os.path.join(dir, '') was the rsync idiom for a trailing separator, which Path drops, so it becomes an explicit os.sep. os.path.abspath stays where Path.resolve() would follow symlinks and let a symlinked volume test as inside the snapshot subject. BREAKING CHANGE: VersionMismatch is renamed VersionMismatchError. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
99 lines
2.8 KiB
Python
99 lines
2.8 KiB
Python
from __future__ import annotations
|
|
|
|
import os
|
|
import shutil
|
|
import subprocess
|
|
from pathlib import Path
|
|
|
|
|
|
def _build_compose_cmd(project_dir: str, passthrough: list[str]) -> list[str]:
|
|
"""
|
|
Build the compose command for this project directory.
|
|
|
|
Policy:
|
|
- If `compose` wrapper exists (Infinito.Nexus): use it and delegate ALL logic to it.
|
|
- Else: use plain `docker compose` with --chdir.
|
|
- NO custom compose file/env detection in this project.
|
|
"""
|
|
pdir = Path(project_dir).resolve()
|
|
|
|
wrapper = shutil.which("compose")
|
|
if wrapper:
|
|
# "--" ensures wrapper stops parsing its own args.
|
|
return [wrapper, "--chdir", str(pdir), "--", *passthrough]
|
|
|
|
docker = shutil.which("docker")
|
|
if docker:
|
|
return [docker, "compose", "--chdir", str(pdir), *passthrough]
|
|
|
|
raise RuntimeError("Neither 'compose' nor 'docker' found in PATH")
|
|
|
|
|
|
def _find_compose_file(project_dir: str) -> Path | None:
|
|
"""
|
|
Detect a compose file in `project_dir` (case-insensitive).
|
|
|
|
Supported names:
|
|
- compose.yml / compose.yaml
|
|
- docker-compose.yml / docker-compose.yaml
|
|
"""
|
|
pdir = Path(project_dir)
|
|
if not pdir.is_dir():
|
|
return None
|
|
|
|
# Map lowercase filename -> actual Path (preserves original casing)
|
|
by_lower = {p.name.lower(): p for p in pdir.iterdir() if p.is_file()}
|
|
|
|
# Preferred order (policy decision)
|
|
candidates = [
|
|
"docker-compose.yml",
|
|
"docker-compose.yaml",
|
|
"compose.yml",
|
|
"compose.yaml",
|
|
]
|
|
|
|
for name in candidates:
|
|
found = by_lower.get(name)
|
|
if found is not None:
|
|
return found
|
|
|
|
return None
|
|
|
|
|
|
def hard_restart_docker_services(dir_path: str) -> None:
|
|
print(f"Hard restart compose services in: {dir_path}", flush=True)
|
|
|
|
down_cmd = _build_compose_cmd(dir_path, ["down"])
|
|
up_cmd = _build_compose_cmd(dir_path, ["up", "-d"])
|
|
|
|
print(">>> " + " ".join(down_cmd), flush=True)
|
|
subprocess.run(down_cmd, check=True)
|
|
|
|
print(">>> " + " ".join(up_cmd), flush=True)
|
|
subprocess.run(up_cmd, check=True)
|
|
|
|
|
|
def handle_docker_compose_services(
|
|
parent_directory: str,
|
|
hard_restart_required: list[str],
|
|
) -> None:
|
|
for entry in os.scandir(parent_directory):
|
|
if not entry.is_dir():
|
|
continue
|
|
|
|
dir_path = entry.path
|
|
name = Path(dir_path).name
|
|
|
|
print(f"Checking directory: {dir_path}", flush=True)
|
|
|
|
compose_file = _find_compose_file(dir_path)
|
|
if compose_file is None:
|
|
print("No supported compose file found. Skipping.", flush=True)
|
|
continue
|
|
|
|
if name in hard_restart_required:
|
|
print(f"{name}: hard restart required.", flush=True)
|
|
hard_restart_docker_services(dir_path)
|
|
else:
|
|
print(f"{name}: no restart required.", flush=True)
|