diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e024539..af5abb1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -43,6 +43,10 @@ Platform notes: - **Linux** builds need only Docker: `pnpm build:linux` compiles inside `swift:6.1-bookworm` and emits a tarball. Chromium must be non-Snap — the runtime rejects Snap launchers before starting, by design. +- **Rootless Docker works**, including the E2E: Chromium's nested namespace + sandbox runs fine, and the harness detects the daemon mode so exported QA + evidence comes back owned by you. Nothing binds a host port, so the suites + cannot collide with other services on a shared machine. - `pnpm test:e2e:mac` opens real windows and mutates `com.headless.app` user defaults. Don't run it in a background session or on a machine where that matters. diff --git a/apps/headless/Tests/linux-docker.sh b/apps/headless/Tests/linux-docker.sh index 69146fa..58e126a 100755 --- a/apps/headless/Tests/linux-docker.sh +++ b/apps/headless/Tests/linux-docker.sh @@ -8,9 +8,19 @@ EVIDENCE_ROOT="${HEADLESS_EVIDENCE_ROOT:-$PWD/build/qa-evidence}" mkdir -p "$EVIDENCE_ROOT" EVIDENCE_DIR="$(mktemp -d "$EVIDENCE_ROOT/linux.XXXXXX")" chmod 0777 "$EVIDENCE_DIR" +# The container writes evidence as its own non-root user, which lands on the +# host as an id this user cannot read. Which id to hand it back to depends on +# how the daemon maps them: rootful Docker maps uid to uid, so the invoking +# user's id is correct, while rootless maps container root to the invoking user +# and every other container id to an unreadable subuid. +if docker info --format '{{join .SecurityOptions ","}}' 2>/dev/null | grep -q rootless; then + EVIDENCE_OWNER="0:0" +else + EVIDENCE_OWNER="$(id -u):$(id -g)" +fi restore_evidence_owner() { docker run --rm --user root -v "$EVIDENCE_DIR:/evidence" \ - headless-p1-test chown -R "$(id -u):$(id -g)" /evidence >/dev/null 2>&1 || true + headless-p1-test chown -R "$EVIDENCE_OWNER" /evidence >/dev/null 2>&1 || true chmod 0700 "$EVIDENCE_DIR" >/dev/null 2>&1 || true } file_mode() {