Files
flow/tests/e2e/test_dotfiles_e2e.py

106 lines
3.5 KiB
Python

"""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,
)