feat(local-dev): support Linux - #7070
Closed
Yicong-Huang wants to merge 1 commit into
Closed
Conversation
Contributor
Automated Reviewer SuggestionsBased on the
|
Contributor
Backport auto-label reportThis
|
Yicong-Huang
force-pushed
the
fix/local-dev-linux
branch
from
July 29, 2026 22:44
4e2fcdf to
347c887
Compare
`bin/local-dev.sh` was macOS-only in three places. It already carried some Linux support — `_find_jdk17` globs `/usr/lib/jvm/*`, SDKMAN and asdf are probed, the docker install hint has a `Linux:` line — but the platform probes underneath were not, and the first of them was fatal. `_detect_host_lan_ip` probed `route get default` and `ipconfig getifaddr en0..en10`. Neither exists on Linux — `route` is net-tools with different syntax, `ipconfig` is macOS/Windows, and the interfaces are `eth0`/`enp*` — so `_require_host_lan_ip` aborted every `up`/`auto` there. Split the probe per platform and add the iproute2 equivalent. The scan skips loopback and the interfaces that would defeat the purpose of this address: a container bridge (docker0, br-*, veth*) is reachable from the host but not from inside another container's netns, and an overlay/VPN address (tailscale, zerotier) is not reachable from the docker bridge at all. The FATAL now names the probes that actually ran instead of always blaming the macOS ones. `svc_artifact_mtime` used BSD `stat -f "%Sm" -t FMT`. GNU coreutils reads `-f` as "file system info" and the format strings as filenames, so it wrote a diagnostic to stderr, printed filesystem fields on stdout and exited 1 — `watch`'s ARTIFACT MTIME column rendered that. `_file_mtime_str` probes for the dialect rather than branching on `uname`, so GNU coreutils on macOS works too. `listen_pid_for_port` required lsof. It ships with macOS but is not a default package on Debian/Ubuntu/Fedora, and without it every native service read as stopped — `up` relaunched services that were already running and `down` silently no-opped. Falls back to `ss` from iproute2, which is essential on any modern Linux. Also in `_install_hint`: the docker line named `docker-compose-plugin`, which only exists in Docker's own apt repo rather than stock Ubuntu, and the node / yarn / bun cases had no Linux line at all. Documents the result in bin/local-dev/README.md: a per-platform table of which probe is used where, the Linux prerequisites (iproute2, docker + compose v2, the `docker` group re-login), and why a docker-bridge address is not a valid HOST_LAN_IP even though it looks like one. Closes #7065
Yicong-Huang
force-pushed
the
fix/local-dev-linux
branch
from
July 29, 2026 22:53
347c887 to
b68bfe3
Compare
Contributor
Author
|
Superseded by #7077 — same commit, but opened from a fork branch as it should have been. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changes were proposed in this PR?
Makes
bin/local-dev.shwork on Linux, not just macOS.The script already carried some Linux support —
_find_jdk17globs/usr/lib/jvm/*, SDKMAN and asdf are probed, the docker install hint has aLinux:line — but the three platform probes underneath it were macOS-only.The first was fatal, the other two degraded silently.
1. Host LAN IP detection (the hard blocker).
_detect_host_lan_ipprobedroute get defaultandipconfig getifaddr en0..en10. Neither exists onLinux:
routeis net-tools with different syntax,ipconfigis macOS/Windows,and the interfaces are
eth0/enp*. So_require_host_lan_ipaborted everyup/auto:Split into
_detect_host_lan_ip_darwin/_detect_host_lan_ip_linuxbehind aunamedispatcher, so the macOS path is byte-for-byte what it was. The Linuxprobe follows the same two steps — interface backing the default route first,
then a scan — and the scan's exclusion list is the interesting part: this
address exists to be reachable from both the host JVMs and the lakekeeper
container, so a container bridge (
docker0,br-*,veth*) is wrong eventhough it is a perfectly good local IPv4, and an overlay/VPN address
(tailscale, zerotier, wireguard) is not reachable from the docker bridge at
all. On a typical box
hostname -Iprints10.10.10.30 172.17.0.1, andpicking the second would defeat the whole point of the variable.
The FATAL message also named only the macOS probes; on Linux none of them had
run, which made the message actively misleading. It now names the probes that
actually executed.
2. Artifact mtime.
svc_artifact_mtimeused BSDstat -f "%Sm" -t FMT.GNU coreutils reads
-fas "file system info" and the format strings asfilenames — it writes a diagnostic to stderr, prints filesystem fields on
stdout and exits 1 — so
watch's ARTIFACT MTIME column rendered that garbage(the JVM call site had no
2>/dev/nullguard at all). Replaced with_file_mtime_str, which probes for the dialect rather than branching onuname, so GNU coreutils on macOS also works.3. lsof dependency.
listen_pid_for_portrequired lsof. It ships withmacOS but is not a default package on Debian/Ubuntu/Fedora, and without it
every native service read as
stopped—uprelaunched services that werealready running, and
downsilently no-opped. Falls back tossfromiproute2, matching on the local-address column so
:18080doesn't answer for:8080.-His deliberately not used (it postdates the iproute2 in olderdistros), and the "empty output means nothing is listening" contract that
svc_running_pid/wait_for_port/ the status table rely on is preserved.Two smaller
_install_hintfixes: the docker line nameddocker-compose-plugin, which only lives in Docker's own apt repo rather thanstock Ubuntu (
docker-compose-v2), and the node / yarn / bun cases had noLinux:line at all.Docs.
bin/local-dev/README.mdgains a Supported platforms section: atable of which probe is used on which platform, the Linux prerequisites
(iproute2, docker + compose v2, and the
docker-group re-login that tripseveryone up once), and why a docker-bridge address is not a valid
HOST_LAN_IPeven though it looks like a fine local IPv4. The bash suite'sheader comment also stopped claiming a real stack "needs a Mac", and now states
that platform-specific checks report a skip rather than a pass.
Any related issues, documentation, discussions?
Closes #7065
How was this PR tested?
New coverage in the existing
infra-job suite. The LAN-IP cases run against afake
ipso the assertions don't depend on the test machine's interfaces, andthe port-listener cases run against a real listener with lsof shimmed out:
That failure is
test_is_dirty_after_seed_then_edit, pre-existing andunrelated — it reproduces identically on a pristine
upstream/maincheckouton this machine, and this PR touches neither
tui.pynor that test. Filedseparately.
End-to-end on Ubuntu 24.04.4 / x86_64, docker 29.1.3, with
HOST_LAN_IPdeliberately not exported — i.e. the exact case that used to abort:
The detected address matches the kernel's own answer and is reachable at the
MinIO port, which is what the variable is for:
lsof removed from
PATH(shimmed toexit 127) now reports the same staterather than "everything stopped" — same shell, same PIDs, so the comparison is
apples to apples:
And
watch's ARTIFACT MTIME column renders a timestamp instead of GNU stat'sdiagnostics:
macOS is unchanged by construction — the Darwin probe body is untouched and a
test asserts the dispatcher still routes to it. I have no Mac to run the suite
on, so CI's
infra (macos-latest)job is the check that matters here; its firstrun caught a test of mine that assumed
ssexists everywhere (it isLinux-only, and macOS ships lsof in the base system), which is now guarded and
green.
Was this PR authored or co-authored using generative AI tooling?
Generated-by: Claude Code (Opus 5)