From e874c3483dd0102ab95147841c46ef9bf0dfe556 Mon Sep 17 00:00:00 2001 From: rob thijssen Date: Thu, 16 Apr 2026 15:30:55 +0300 Subject: [PATCH] fix(rpm): explicitly Provides user(name) to satisfy systemd unit Requires MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Diagnosing the persistent "Nothing to do" on v0.1.10 surfaced that removing %attr(,,name) from %files wasn't enough. systemd-rpm-macros ships its own rpm dep generator (/usr/lib/rpm/systemd.req) that parses User=/Group= directives from every .service file the package ships and emits Requires: user(NAME)/group(NAME) accordingly. Rpmbuild log from v0.1.10 shows these Requires are still emitted even after the %attr removal. Meanwhile the sysusers provides-generator emits group(NAME) in both unversioned and versioned forms, but only a versioned user(NAME) = when the u-line has GECOS/home/shell fields. The asymmetry leaves Requires: user(NAME) unresolvable. Add explicit Provides: user(NAME) back to both specs, with a comment documenting the actual cause (systemd unit parsing, not file attrs) so the next person touching these specs doesn't repeat the mistake. Why monsoon didn't hit this: it creates its user in %pre via groupadd/useradd (not sysusers.d), so no Provides are generated at all — matching the Requires: user(monsoon) by luck of the rpm solver treating unknown symbols as soft-fails for that path. Ours went through the sysusers Provides code path and hit the asymmetry instead. Co-Authored-By: Claude Opus 4.6 (1M context) --- cortex.spec | 9 +++++++++ neuron.spec | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/cortex.spec b/cortex.spec index cdd5133..3a0e05e 100644 --- a/cortex.spec +++ b/cortex.spec @@ -22,6 +22,15 @@ BuildRequires: systemd-rpm-macros Requires(pre): shadow-utils Requires: systemd +# systemd-rpm-macros ships a unit dep generator that parses User=/Group= +# from our .service file and emits Requires: user(cortex)/group(cortex). +# rpm's sysusers provides-generator emits the unversioned form for groups +# but only a versioned user(cortex) = for users with GECOS/home/ +# shell. Provide the unversioned user(cortex) explicitly so dnf can resolve +# the auto-generated Requires. Without this, dnf5 silently filters the +# package and reports "Nothing to do". +Provides: user(cortex) + %description Cortex is a Rust reverse-proxy that sits in front of multiple inference nodes (via neuron daemons) and presents a unified OpenAI and Anthropic diff --git a/neuron.spec b/neuron.spec index 11886da..224b04d 100644 --- a/neuron.spec +++ b/neuron.spec @@ -22,6 +22,15 @@ BuildRequires: systemd-rpm-macros Requires(pre): shadow-utils Requires: systemd +# systemd-rpm-macros ships a unit dep generator that parses User=/Group= +# from our .service file and emits Requires: user(neuron)/group(neuron). +# rpm's sysusers provides-generator emits the unversioned form for groups +# but only a versioned user(neuron) = for users with GECOS/home/ +# shell. Provide the unversioned user(neuron) explicitly so dnf can resolve +# the auto-generated Requires. Without this, dnf5 silently filters the +# package and reports "Nothing to do". +Provides: user(neuron) + %description Neuron is a per-node daemon for cortex inference clusters. It discovers local GPU hardware via nvidia-smi, manages inference harnesses (mistral.rs,