Files
Jake WriterandClaude Opus 5.5 ebe6682b8e Fix npm camoufox fetch failing with EXDEV, and gate merges on a real package install (#828)
* fix(ts): unpack the GeoIP archive beside the database, not in os.tmpdir()

downloadMmdb() unzipped a zipped source into a directory under os.tmpdir()
and renamed the .mmdb from there into the cache. When /tmp is a different
filesystem from the cache (tmpfs /tmp, a Docker volume, a separate /home),
the rename fails with EXDEV, so `camoufox fetch` exited 1 after installing
the browser and no GeoIP database was installed. Since #820 made GeoIP AIO,
a zipped source, the default, this hits every such install of 0.5.7.

Stage the archive in a directory inside GEOIP_DIR, so the rename stays on
one filesystem and is still atomic. Found by installing 0.5.7-beta.5 from
npm on a host with a tmpfs /tmp; with the fix the real AIO download lands
in a cache on another filesystem and no staging directory is left behind.
pythonlib is unaffected: it moves the file with shutil.move.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* ci: install both packages as published and run the real fetch

Every suite ran from the source tree, so nothing exercised what a user runs:
the packed package, installed into a clean environment, fetching into an
empty cache. That is how npm 0.5.7-beta.5 shipped a `camoufox fetch` that
failed with EXDEV whenever the temporary directory and the cache were on
different filesystems.

New tier-1 gate, ci/run_install.py: builds and installs pythonlib[geoip] and
the `pnpm pack` tarball into fresh environments, runs `camoufox fetch` for
each with TMPDIR on a dedicated tmpfs mount, and checks the browser and the
GeoIP database landed and no staging directory was left. It errors out
rather than passing if TMPDIR turns out to share the work directory's
filesystem, since it could then not see the bug.

Checked locally: fails on main with the EXDEV from the release, passes with
the fix in the previous commit. It joins the required suites, so `All tests
passed` needs it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(ts): name the URL and the cause when a download fails

A network failure in the npm launcher surfaced as Node's bare "fetch
failed", which says neither what was being downloaded nor why. The new
install gate hit exactly that in CI while fetching the GeoIP database,
and a user would have no more to go on.

Route the launcher's three fetch() calls through request(), which rethrows
as "Could not download <url>: fetch failed (<code> <message>)" with the
original error as its cause.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 23:52:04 +00:00
..