Skip to content

v1.9.0 — sync, doctor, metrics, completions

Latest

Choose a tag to compare

@github-actions github-actions released this 26 Sep 10:27
· 14 commits to main since this release

What's new

See exactly what crosses the wire

A build reports its sync as a side effect. These make the transfer the subject:

  • fh sync --dry-run connects, exchanges the manifest, and reports what would move — file count, bytes, what the agent already has, and the share of the project that would cross the network — without sending a single file. --list additionally names every path.
  • fh sync performs the sync without running a build, warming the workspace for the next run.
  • fh why <path> explains one path: it will be uploaded, it is already on the agent as a content-addressed hit, or it is excluded — naming the rule that excluded it.

fh doctor — one command to tell you what's wrong

Validates configuration, token handling, transport, declared toolchains, and the agent's reachability, disk, queue depth, and load. The probe is deliberately two-phase, because a single failed request cannot distinguish "the daemon is not running" from "the daemon is there and rejected your token" — and those need completely different fixes. Nothing is synced and no run slot is used. Exits 125 when something is actually broken, so it is usable from a script.

Prometheus metrics (opt-in)

fhd --listen 0.0.0.0:9876 --token "$FARHAND_TOKEN" --metrics-port 9100

13 metric names covering runs, slots, queue depth, active builds per project, disk, load, and memory, plus /healthz for container probes. Binds separately from the agent port so it can be firewalled on its own, and a metrics port that cannot bind logs an error instead of taking the agent down. Hand-rolled over a TcpListener — this is one static text endpoint, and a web framework in the daemon's dependency tree would be a poor trade. See docs/observability.md for the metric reference, alert rules, and an importable Grafana dashboard.

Shell completions and man pages

fh completions bash > /etc/bash_completion.d/fh
fh man --dir /usr/share/man/man1

Generated from the same clap definitions the binary uses, so they cannot describe a stale interface. Both need no host, no config, and no network.

Watch mode is configurable

Watch mode now honours each template's ignoreExtra, so a project can declare paths that must not trigger a rebuild. The debounce is tunable with --watch-debounce (default 150 ms) for editors that save in bursts and for network filesystems. The built-in feedback-loop guards stay unconditional on purpose: a negated template pattern cannot un-ignore target/, which would otherwise rebuild on our own output forever.

Progress while the delta is packed

[============          ]  47% 12/25 packing delta  0.3s

Driven by real per-entry callbacks from the packer, not a timer guessing at progress, and rendered only when stdout is a terminal so redirected output and CI logs stay clean.

Packaging

  • Nix: a flake.nix exposing fh and fhd plus a dev shell with rust-analyzer, cargo-audit, and cargo-deny, and a default.nix for non-flake consumers.
  • crates.io: the crates are ready to publish under the farhand-* namespace — the name farhand is taken on crates.io by an unrelated project. The executables remain fh and fhd.
  • Homebrew: the formula is current again (see below).

Fixes

  • brew install farhand served v1.7.0 while v1.8.0 and v1.8.1 had shipped. The formula's URLs interpolate its own version, so it pointed at 1.7.0's artifacts with a version string that matched its own checksum — no error, just old binaries, including the Windows stack overflow that made the client crash before printing its version.
  • fh --help described sync as "Clean remote project workspaces or caches." The subcommand had been inserted between Clean and its doc comment, so clap attached the wrong description.
  • The Prometheus endpoint emitted duplicate # HELP/# TYPE pairs for the load-average family — a scrape-time parse error, not a cosmetic one. Label values now escape quotes, backslashes, and newlines, since a project name comes from a directory name and Unix allows newlines in those.
  • fh doctor warned about unencrypted transport on a loopback target, contradicting its own advice, while a real sync reported "would cross the network" after the bytes had crossed.

Gates added

Several of the bugs above were invisible from a Linux box or from a green build, so each class now has a check that fails when it should:

  • musl target and a 1 MiB main-thread stack (Windows parity) in CI
  • an MSRV gate at the real minimum (1.88)
  • shell script syntax, since the install and packaging scripts are how most people install farhand and nothing executed them
  • a nightly job that runs the release build command and asserts the executables are still named fh and fhd — release.yml only runs on a tag, so selector drift there would otherwise be invisible until a release was already cut
  • a nightly job comparing the Homebrew formula against the latest published release
  • a test comparing the metric reference in docs/observability.md against what the endpoint actually emits