"""End-to-end test for `flow dotfiles` against the example repo. Gated by FLOW_RUN_E2E=1 because it builds and runs a container image. Tries podman first, falls back to docker. Skips if neither is available. """ from __future__ import annotations import os import shutil import subprocess from pathlib import Path import pytest REPO_ROOT = Path(__file__).resolve().parents[2] CONTAINERFILE = Path(__file__).parent / "Containerfile" EXAMPLE_REPO = REPO_ROOT / "example" / "dotfiles-repo" IMAGE_TAG = "flow-e2e:test" def _pick_runtime() -> str | None: for binary in ("podman", "docker"): if shutil.which(binary): return binary return None @pytest.mark.skipif( os.environ.get("FLOW_RUN_E2E") != "1", reason="set FLOW_RUN_E2E=1 to run", ) def test_dotfiles_init_and_link_in_container(): runtime = _pick_runtime() if runtime is None: pytest.skip("neither podman nor docker is available") build = subprocess.run( [ runtime, "build", "-f", str(CONTAINERFILE), "-t", IMAGE_TAG, str(REPO_ROOT), ], capture_output=True, text=True, ) if build.returncode != 0: pytest.fail(f"image build failed:\n{build.stdout}\n{build.stderr}") try: # Run flow inside the container against the mounted example repo. # `flow dotfiles init` clones, so we need a real git remote — turn # the read-only example mount into a bare-ish working repo first. script = ( "set -eux; " "cp -r /example /home/flowuser/dotfiles-src; " "cd /home/flowuser/dotfiles-src; " "git init -q -b main; " "git -c user.email=e2e@example.com -c user.name=e2e add -A; " "git -c user.email=e2e@example.com -c user.name=e2e commit -q -m initial; " "cd /home/flowuser; " "flow dotfiles init --repo /home/flowuser/dotfiles-src; " "flow dotfiles link --profile linux-auto --dry-run; " "flow dotfiles status" ) result = subprocess.run( [ runtime, "run", "--rm", "-v", f"{EXAMPLE_REPO}:/example:ro", IMAGE_TAG, "-c", script, ], capture_output=True, text=True, ) assert result.returncode == 0, ( f"e2e run failed (rc={result.returncode}):\n" f"stdout: {result.stdout}\n" f"stderr: {result.stderr}" ) finally: subprocess.run( [runtime, "rmi", "-f", IMAGE_TAG], capture_output=True, text=True, )