[hero_lifecycle] expose webserver-admin templates to dependents via links/DEP_* (avoid sibling-path & vendoring) #152

Open
opened 2026-06-14 17:09:03 +00:00 by sameh-farouk · 1 comment
Member

Consumers of the hero_lifecycle webserver-admin (askama) shell must reference its shared partials (parts/hero_head.html, hero_scripts.html, hero_connection_status.html, component panes). Today the only options are all flawed:

  • relative sibling path (../../../hero_lib/... in askama.toml) — breaks cargo check in CI / any build where hero_lib is a git dependency, not a sibling checkout (see hero_planner#23).
  • vendoring (copy the partials into the consumer) — self-contained but drifts from upstream.
  • build.rs + cargo metadata to copy from the resolved dep — no drift, but invoking cargo from a build script risks a nested-cargo lock deadlock.

Proposed proper fix: have hero_lifecycle expose its webserver templates dir to dependents via cargo's links / DEP_* protocol — declare links = "hero_lifecycle" and emit cargo:templates_dir=<abs path> from its build.rs; dependent admins read DEP_HERO_LIFECYCLE_TEMPLATES_DIR in their own build.rs and copy from the resolved dependency (no sibling, no drift, works in CI). Benefits every webserver-admin consumer.

(Longer term, the Dioxus hero_admin_lib_dx admin is a compiled component library with no templates to copy at all, which sidesteps this entirely — hero_planner is migrating to it.)

Context: hero_planner#23 (the CI break), hero_planner currently uses the vendored interim. Related shared-admin: #151.

Consumers of the hero_lifecycle **webserver-admin** (askama) shell must reference its shared partials (`parts/hero_head.html`, `hero_scripts.html`, `hero_connection_status.html`, component panes). Today the only options are all flawed: - **relative sibling path** (`../../../hero_lib/...` in askama.toml) — breaks `cargo check` in CI / any build where hero_lib is a git dependency, not a sibling checkout (see hero_planner#23). - **vendoring** (copy the partials into the consumer) — self-contained but **drifts** from upstream. - **build.rs + `cargo metadata`** to copy from the resolved dep — no drift, but invoking cargo from a build script risks a nested-cargo lock deadlock. **Proposed proper fix:** have `hero_lifecycle` expose its webserver templates dir to dependents via cargo's `links` / `DEP_*` protocol — declare `links = "hero_lifecycle"` and emit `cargo:templates_dir=<abs path>` from its build.rs; dependent admins read `DEP_HERO_LIFECYCLE_TEMPLATES_DIR` in their own build.rs and copy from the **resolved dependency** (no sibling, no drift, works in CI). Benefits every webserver-admin consumer. (Longer term, the **Dioxus `hero_admin_lib_dx`** admin is a compiled component library with no templates to copy at all, which sidesteps this entirely — hero_planner is migrating to it.) Context: hero_planner#23 (the CI break), hero_planner currently uses the vendored interim. Related shared-admin: #151.
Author
Member

The underlying problem is real: consumers reference the shared askama partials via a relative sibling path (../../../hero_lib/... in askama.toml) that breaks when hero_lib is a git dep in CI (see hero_planner#23), or vendor copies that drift.

But adding links = "hero_lifecycle" (the proposed fix) breaks cargo dependency resolution for any graph that already contains two distinct package-nodes of hero_lifecycle. Cargo's rule is one links package per dependency graph — two distinct sources/revisions = two packages = hard conflict, with no consumer opt-out (the conflict lives in the producer they pull twice). Reproduced with cargo 1.96.0. Three current graphs in the org checkout already hit it:

  • hero_codescalers — hero_lifecycle 0.6.0 from hero_lib.git?branch=main AND ?branch=development
  • hero_bundle — from hero_lib.git?branch=development (direct) AND via hero_blueprint.git (transitive)
  • hero_lib itself — path copy + ?branch=main copy

~43 repos depend on hero_lifecycle; all inherit the constraint. So the first-pass "safe, zero existing links=" reasoning is wrong — the collision is self-induced by the new key, not a pre-existing name clash.

Non-breaking alternatives:

  • (a) emit cargo:templates_dir= from a build.rs without the links key (consumer reads it through a non-links channel) — keeps the metadata idea, drops the collision.
  • (b) skip template-sharing entirely via a Dioxus hero_admin_lib_dx component lib (no templates to copy) — note that crate does not exist yet (confirmed absent in checkout + scan).

Urgency: low. Exactly one active consumer would benefit (hero_planner_admin), and it builds today via byte-identical vendored copies. The real value is preventing future drift — possibly throwaway if planner moves to Dioxus (#18). Recommendation: do not add links; if doing anything now, the producer-side build.rs-without-links is the safe minimal step. Coordinate any hero_lifecycle Cargo.toml change since it's a base-platform crate.

## Triage (verified on-box) — difficulty: **M**, and ⚠️ the proposed `links` fix is itself **BREAKING** **The underlying problem is real:** consumers reference the shared askama partials via a relative sibling path (`../../../hero_lib/...` in askama.toml) that breaks when hero_lib is a git dep in CI (see hero_planner#23), or vendor copies that drift. **But adding `links = "hero_lifecycle"` (the proposed fix) breaks cargo dependency *resolution*** for any graph that already contains two distinct package-nodes of `hero_lifecycle`. Cargo's rule is **one `links` package per dependency graph** — two distinct sources/revisions = two packages = hard conflict, with **no consumer opt-out** (the conflict lives in the producer they pull twice). Reproduced with cargo 1.96.0. Three **current** graphs in the org checkout already hit it: - **hero_codescalers** — hero_lifecycle 0.6.0 from `hero_lib.git?branch=main` AND `?branch=development` - **hero_bundle** — from `hero_lib.git?branch=development` (direct) AND via `hero_blueprint.git` (transitive) - **hero_lib** itself — path copy + `?branch=main` copy ~43 repos depend on `hero_lifecycle`; all inherit the constraint. So the first-pass "safe, zero existing `links=`" reasoning is wrong — the collision is **self-induced by the new key**, not a pre-existing name clash. **Non-breaking alternatives:** - (a) emit `cargo:templates_dir=` from a `build.rs` **without** the `links` key (consumer reads it through a non-`links` channel) — keeps the metadata idea, drops the collision. - (b) skip template-sharing entirely via a Dioxus `hero_admin_lib_dx` component lib (no templates to copy) — note that crate **does not exist yet** (confirmed absent in checkout + scan). **Urgency: low.** Exactly **one** active consumer would benefit (`hero_planner_admin`), and it builds today via byte-identical vendored copies. The real value is preventing future drift — possibly throwaway if planner moves to Dioxus (#18). Recommendation: do **not** add `links`; if doing anything now, the producer-side `build.rs`-without-`links` is the safe minimal step. Coordinate any `hero_lifecycle` Cargo.toml change since it's a base-platform crate.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lhumina_code/hero_lib#152
No description provided.