"""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 not shutil.which(binary): continue result = subprocess.run( [binary, "version"], capture_output=True, text=True, ) if result.returncode == 0: 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. # --skip system avoids the _root/ paths which would try to sudo-link # over /etc/hostname; we already cover the link path on non-system # packages. 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 --skip system; " # Verify real symlinks were created and point into the dotfiles dir. "test -L /home/flowuser/.zshrc; " "test -L /home/flowuser/.gitconfig; " "readlink /home/flowuser/.zshrc | grep -q '/dotfiles/_shared/zsh/.zshrc'; " "readlink /home/flowuser/.gitconfig | grep -q '/dotfiles/_shared/git/.gitconfig'; " # Idempotency: rerun should be a no-op. "flow dotfiles link --profile linux-auto --skip system; " "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, )