Skip to content

v0.12.0

Choose a tag to compare

@github-actions github-actions released this 11 Aug 14:32
· 34 commits to main since this release
v0.12.0
0062b98

Added

  • mount/1 on the SSH transport receives the client's username as :ssh_user. :app_opts is static and shared by every connection; :ssh_user is the one opt that differs per client — the username from the SSH handshake, injected by the channel into that connection's mount opts. It arrives under no_auth_needed: true as well, since the username travels in the protocol handshake rather than in authentication, which makes it a natural per-session identity for public or demo daemons where each client picks a name with ssh alice@host. It is user input, not an identity: without authentication anyone can claim any name, and a daemon with one shared account reports the same name for everybody — sanitize before display and never use it for authorization on its own. The key is absent when the connection cannot report a username, so match with a fallback rather than Keyword.fetch!/2. The SSH transport guide covers the details.

Fixed

  • Precompiled *-unknown-linux-musl NIFs no longer depend on libgcc_s.so.1 (#83). With crt-static off — and off it must be, since a NIF is a cdylib and musl cannot produce one with crt-static (rust-lang/rust#59302) — rustc links the panic unwinder via an explicit -lgcc_s, which neither -static-libgcc nor -C panic=abort removes (the reference lives in the prebuilt std, not in our crates). Every published musl artifact therefore carried a NEEDED libgcc_s.so.1 entry that stock musl systems (Alpine containers, Burrito's Linux payload, Nerves-style rootfs) cannot satisfy, and the NIF failed to relocate — this affects the whole rustler_precompiled ecosystem, not just ex_ratatui. Since no stable rustc switch embeds the unwinder under dynamic musl (-C link-self-contained=+unwind is nightly-only), a new build.rs shadows the lookup on musl targets: it copies the C toolchain's static libgcc_eh.a (the same unwinder code) into the build directory as libgcc_s.a and prepends that directory to the link search path, so -lgcc_s resolves statically and the artifact links against musl libc alone. Panics keep unwinding — rustler still catches them and raises on the Elixir side. Verified on stock alpine:3.20: the new artifact dlopens cleanly where the v0.11.2 one reproduces the reported relocation failure. Hardened after downstream validation on both musl arches: a trailing -lgcc resolves the outline-atomics helpers that GCC >= 10's libgcc_eh.a references on aarch64 (__aarch64_*, defined in libgcc.a and not exported by libgcc_s.so.1 — without it a leaner crate reusing this pattern links silently and fails to dlopen), and the release workflow now fails any musl job whose artifact carries a libgcc_s NEEDED entry or undefined unwinder/outline-atomics symbols, so a future toolchain change cannot silently republish broken artifacts. Forcing a source build from a consumer requires declaring :rustler explicitly in the consumer's dependencies (optional dependencies are not fetched transitively) — the README documents it. For already-published artifacts (0.11.2 and earlier), apk add libgcc is the workaround. The 0.10.0 entry below claimed -static-libgcc had made the musl artifacts self-contained; it had not, and that entry has been corrected in place.

  • config :rustler_precompiled, :force_build, ex_ratatui: true now actually forces a build from source. The native bridge (lib/ex_ratatui/native.ex) always put a :force_build key into the option list (derived from EX_RATATUI_BUILD) and then tried to apply the per-application config with Keyword.put_new/3, which never overwrites an existing key — so the documented rustler_precompiled escape hatch was silently ignored and the precompiled NIF was downloaded anyway. The three inputs are now resolved explicitly, highest precedence first: :force_build_all (or RUSTLER_PRECOMPILED_FORCE_BUILD_ALL), then config :rustler_precompiled, :force_build, ex_ratatui: true/false, then EX_RATATUI_BUILD. Behaviour is unchanged when the per-application config is absent.

  • Modules declaring @behaviour ExRatatui.App without use ExRatatui.App no longer crash on the optional callbacks. The server invoked handle_info/2, subscriptions/1, terminate/2, and the reducer-runtime probe __runtime__/0 unconditionally — use ExRatatui.App injects defaults for all four, so a bare @behaviour module implementing only the required callbacks raised UndefinedFunctionError the moment any of them fired (first at startup, where __runtime__/0 is read). The server now falls back to the same defaults the macro injects whenever a callback is not exported, so both forms behave identically. The reducer runtime remains opt-in through use — without the macro there is no __runtime__/0 to read — and use ExRatatui.App stays the recommended form, since it also provides start_link/1 and child_spec/1 for supervision.

  • Corrected the OTP 29 note in the README. It claimed OTP 29 had no precompiled binary and required the Rust toolchain plus EX_RATATUI_BUILD=true. Not so: the NIF ABI is backward compatible and rustler_precompiled selects the highest available version at or below the current one, so OTP 29 (NIF 2.18) loads the published 2.17 binary with no Rust toolchain. Only publishing a native 2.18 artifact is still pending upstream support. The 0.11.2 entry below carried the same error and has been corrected in place — no behaviour changed, only its description.

Changed

  • Vendored Rust dependencies bumped. time 0.3.54 → 0.3.55. As always, these compile into the precompiled NIF, so every consumer picks them up with this release regardless of their own lock.