feat(channels): ship librefang-sidecar-telegram binary in release tarballs#5937
Conversation
The Rust Telegram sidecar (#5831) shipped only as source, so operators had to install a Rust toolchain and compile it before pointing a [[sidecar_channels]] block at the result. Bundle the binary in the release tarballs and auto-resolve it so the migration off the Python sidecar is a one-step config change. Release pipeline: for each channel-capable native target (macOS x86_64 / aarch64, linux-gnu x86_64 / aarch64, musl x86_64 / aarch64, Windows x86_64 / aarch64) release.yml and its manual mirror release-cli.yml compile the sidecar from its separate cargo workspace and bundle the binary inside the existing per-target archive next to librefang. No new release assets, so the cosign SHA256SUMS manifest and EXPECTED_PLATFORMS=12 are unchanged. macOS ad-hoc codesigns the sidecar; musl verifies it is statically linked; Windows adds the .exe to the Compress-Archive path list. Android and the mini variants are deliberately skipped (neither carries channels). Install scripts: install.sh and install.ps1 install the bundled binary when present and stay silent on older tarballs that lack it (backward compatible). Daemon: resolve_sidecar_command in librefang-channels resolves an empty or bare-stem command to the daemon's own executable directory, then ~/.librefang/bin/, then PATH. An absolute / relative path or any other program (python3 -m ...) is treated as explicit operator intent and passed through unchanged. Docs + CHANGELOG updated.
Deploying librefang with
|
| Latest commit: |
26da2e7
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://92f8987d.librefang.pages.dev |
| Branch Preview URL: | https://feat-ship-rust-sidecar-binar.librefang.pages.dev |
|
Deploying librefang-docs with
|
| Latest commit: |
26da2e7
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://943ac047.librefang-docs-web.pages.dev |
| Branch Preview URL: | https://feat-ship-rust-sidecar-binar.librefang-docs-web.pages.dev |
The librefang-sidecar-telegram binary the release pipeline ships is its own
cargo workspace, not a member of the kernel workspace, so the regular CI
RUST lane never compiles it — a break would only surface when cutting a
tag. This PR makes it release-blocking, so move the verification forward to
every PR.
ci.yml: route changes under sdk/rust/librefang-sidecar{,-telegram}/ and the
release workflows to a new rust-telegram-sidecar job (modeled on the
existing skills-wasm-sdk job). It fmt/clippy/test/builds the sidecar
natively and then runs the cross build for aarch64-unknown-linux-musl that
the release pipeline depends on, proving at PR time that cross can resolve
the out-of-workspace ../librefang-sidecar path dependency — the one risk
that previously could only be validated on a real tag.
release.yml + release-cli.yml: the four native jobs that build the sidecar
(mac / linux / musl / windows) now list both . and
sdk/rust/librefang-sidecar-telegram under Swatinem/rust-cache workspaces so
the sidecar's separate target/ is cached instead of recompiled from scratch
each run. The mini and android jobs are untouched (they do not build the
sidecar).
Closes #5936.
The Rust Telegram sidecar (#5831) shipped only as source, so using it meant installing a Rust toolchain, cloning the repo, building
librefang-sidecar-telegram, and pointing a[[sidecar_channels]]block at the resulting path.This bundles the binary inside the existing release tarballs so
librefang updatelands it at~/.librefang/bin/and the daemon auto-resolves it — making the migration off the Python sidecar a one-step config change.Part 1 — Release build (bundle inside existing tarballs)
Both workflows change in lockstep (
release-cli.ymlis the manual mirror ofrelease.yml's CLI jobs).For each channel-capable native target the in-scope jobs are
cli_mac(x86_64 + aarch64),cli_linux(x86_64-gnu + aarch64-gnu[cross]),cli_musl(x86_64 + aarch64, both cross),cli_windows(x86_64 + aarch64).Per job:
--manifest-path sdk/rust/librefang-sidecar-telegram/Cargo.toml(usingcrosswhere that job already uses cross — i.e. all ofcli_musl, and the aarch64 leg ofcli_linux).sdk/rust/librefang-sidecar-telegram/target/<target>/release/) next tolibrefangand adds it to the same archive.macOS ad-hoc codesigns it like
librefang;cli_muslverifies it is statically linked; Windows addslibrefang-sidecar-telegram.exeto theCompress-Archivepath list.No new release assets are introduced — the binary ships inside the existing per-target
librefang-<target>.tar.gz/.zip, soEXPECTED_PLATFORMS=12and the cosignSHA256SUMSmanifest are unchanged.Deliberately skipped: the
cli_androidjob and allminivariants (Android andminicarry no channels).Part 2 — Install scripts (extract the bundled binary)
install.sh(POSIX sh): after installinglibrefang, iflibrefang-sidecar-telegramis present in the extracted tarball,chmod +xit (and on macOS strip quarantine + ad-hoc codesign). Absent ⇒ skipped silently (backward compatible with older tarballs).install.ps1: mirror — iflibrefang-sidecar-telegram.exeis present, copy it to$InstallDir; absent ⇒ skipped.Part 3 — Daemon auto-resolution
resolve_sidecar_command(command, home_dir)incrates/librefang-channels/src/sidecar.rs, called once inSidecarAdapter::new(wherehome_diris already available, so the resolved command flows into both the adapter field and the spawnSpawnCtx):commandis empty or the bare stemlibrefang-sidecar-telegram(no path component).current_exe().parent()), then<home_dir>/bin/, then fall through to the original command (PATH lookup — historical behavior).python3,uv,./librefang-sidecar-telegram, …), passes through unchanged so explicit operator intent always wins.Three focused unit tests cover: resolves to
<home>/binwhen the bundled binary is present (bare stem and empty command); falls through unchanged when no bundled binary exists; leaves explicit commands untouched even when a bundled binary is on disk.Part 4 — Docs + CHANGELOG
docs/architecture/rust-telegram-sidecar.mdanddocs/src/app/configuration/channels/page.mdxnow state the binary ships in release tarballs, lands in~/.librefang/bin/vialibrefang update, and is auto-resolved — manual build no longer required. Added an "Auto-resolution" section documenting the search order.CHANGELOG.mdentry added under the existing[Unreleased]### Added.Verification
Run via the repo's
Dockerfile.rust-devimage (no native cargo on the host; Linux container, scoped commands only):cargo test -p librefang-channels --lib→ 482 passed, 0 failed (includes the 3 newresolve_sidecar_command_*tests, confirmed passing individually).cargo build --release --manifest-path sdk/rust/librefang-sidecar-telegram/Cargo.toml→ compiles clean, binary produced (~8 MB).cargo clippy -p librefang-channels --all-targets -- -D warnings→ clean.cargo fmt -p librefang-channels -- --check→ clean.sh -n web/public/install.sh→ syntax OK (shellcheck not available on the host).release.yml/release-cli.ymlvalidated as YAML.Not locally verifiable — needs CI on a real tag
The release pipeline itself cannot be exercised locally (no tag, no GitHub Actions runners, and
cargo buildfor the kernel is forbidden in-session).The workflow edits — the cross-compiled sidecar build steps, the
cross --manifest-pathinvocation for the separate workspace, the macOS codesign / musl static-link / Windows zip packaging, and the assertion that asset names and theEXPECTED_PLATFORMS=12/ cosign manifest are unchanged — must be validated by CI on a real tag (or arelease-climanual dispatch).The sidecar build was proven to compile for the container's Linux target only; per-target cross builds (aarch64, musl, Windows, macOS) are CI's responsibility.
Update — PR-time CI guard (post-review)
Added a PR-time guard so the sidecar's compilability and the cross-compile risk are no longer deferred to CI-on-tag.
ci.yml: newchangesoutputsidecar_rust(set whensdk/rust/librefang-sidecar{,-telegram}/or the release workflows change), feeding a newrust-telegram-sidecarjob modeled on the existingskills-wasm-sdkjob.The job runs
cargo fmt --check+clippy -D warnings+test+build --releaseon the sidecar workspace, thencargo install cross+cross build --release --target aarch64-unknown-linux-musl --manifest-path sdk/rust/librefang-sidecar-telegram/Cargo.toml.That cross step really runs cross on this PR, proving up front whether cross can mount and resolve the out-of-workspace
../librefang-sidecarpath dependency — the exact risk the original PR could only flag as "needs CI-on-tag validation".rust-cachelists bothsdk/rust/librefang-sidecar-telegramand the siblingsdk/rust/librefang-sidecar.release.yml+release-cli.yml: the four native sidecar-building jobs (mac / linux / musl / windows) now cache the sidecar's separatetarget/by listing.andsdk/rust/librefang-sidecar-telegramunderrust-cacheworkspaces:(mini / android untouched).If the cross step fails on this PR's CI, that is the real answer we couldn't get locally — it would mean the sidecar workspace needs a
Cross.toml/ mount tweak so cross can see../librefang-sidecar(a follow-up).Local verification (Docker dev image) of the native
rust-telegram-sidecarstep:cargo fmt --checkclean,clippy --all-targets -- -D warningsclean,cargo test41 passed,cargo build --releaseOK.All three workflow YAMLs pass
yaml.safe_loadandactionlint.The cross-musl step is intentionally CI-only.