plan/main names the fab package, and the resolver drops it silently when it is missing #4

Open
opened 2026-09-28 07:09:27 -03:00 by marcos-mendez · 0 comments
marcos-mendez commented 2026-09-28 07:09:27 -03:00 (Migrated from github.com)

plan/main:3 is a bare line fab. It is the only plan file in the whole
organization that names fab as a package, and after Keel-Linux/fab#9 it will
name a package that no longer exists. It does not fail loudly, and
Provides: fab does not save it, because it never reaches apt.

Why Provides does not cover this

tkldev/Makefile is include $(FAB_PATH)/common/mk/turnkey.mk, so plan/main
is resolved by fab-plan-resolve, not by apt. fab's own resolver does not
resolve virtual packages:

  • fablib/plan.py:205-206 takes the pool's answer and does
    package_name = fname.split("_")[0], then self._deps[deps[package_name]].
    The first field of the .deb filename has to be string-equal to the
    requested name, so a keel-fab_2.0.0_all.deb returned for a request of fab
    raises an uncaught KeyError.
  • _get_provided (plan.py:329) reads Provides only from packages that have
    already been fetched, and provided is subtracted from all_missing
    only at plan.py:406. Nothing in that path ever causes a provider to be
    fetched.

And the miss is silent

missing is initialised at plan.py:366 and never mutated, while brokendeps
is built by iterating it at plan.py:421-422. So resolve() returns
(spec, []) even when all_missing is non-empty: a plan entry the pool cannot
supply is dropped from the spec and nothing says so.

That is upstream code, not something Keel-Linux/fab#9 introduced, but it is
what turns this from a build failure into a silently wrong image.

Why it is latent rather than broken today

apt/pool/main/f/fab/fab_1.1.1+keel1_all.deb is still in the archive. So after
the conversion, and before anything changes here, TKLDev images built from this
recipe would keep shipping the pre-rename fab while the build host itself
runs keel-fab, which is a divergence nobody would notice. The day fab leaves
the pool they would ship no fab at all, without an error.

What closes this

  • plan/main:3 becomes keel-fab, after Keel-Linux/fab#9 is merged and the
    package is published, and before fab is removed from the pool.
  • overlay/usr/local/sbin/tkldev-setup:372, DEBIAN_FRONTEND=noninteractive apt-get install -y fab, becomes keel-fab. This one is an apt call, and
    Provides: fab does make it install keel-fab while no real fab is
    reachable, but that is not the case on a machine with the TurnKey archive
    enabled: apt prefers a real package over a virtual provider, and upstream's
    real fab is at priority 999 there. Measured in a container, apt-get install -y fab with keel-fab installed removes keel-fab and installs
    upstream's fab
    . Keel-Linux/apt#15 adds the negative pin that stops that on
    the build host; this line should name the right package regardless, since
    tkldev-setup runs on machines that do not have our pin file.
  • tests/tkldev-setup.bats:309 asserts the literal string
    apt-get install -y fab and moves with it.
  • The help text at overlay/usr/local/sbin/tkldev-setup:17 says "'fab' package
    will be installed when relevant."

Order

Not before Keel-Linux/fab#9 merges and keel-fab is published, or this recipe
stops resolving. Not after fab leaves the pool, or it silently stops shipping
a builder. Between those two, and the archive change is the one to wait for.

The resolver defects above are worth their own issue in Keel-Linux/fab
whatever happens here: resolve() returning no error for a package the pool
could not supply is the kind of thing that costs a day the first time it
matters.

`plan/main:3` is a bare line `fab`. It is the only plan file in the whole organization that names fab as a package, and after Keel-Linux/fab#9 it will name a package that no longer exists. It does not fail loudly, and `Provides: fab` does not save it, because it never reaches apt. ## Why Provides does not cover this `tkldev/Makefile` is `include $(FAB_PATH)/common/mk/turnkey.mk`, so `plan/main` is resolved by `fab-plan-resolve`, not by apt. fab's own resolver does not resolve virtual packages: - `fablib/plan.py:205-206` takes the pool's answer and does `package_name = fname.split("_")[0]`, then `self._deps[deps[package_name]]`. The first field of the `.deb` filename has to be string-equal to the requested name, so a `keel-fab_2.0.0_all.deb` returned for a request of `fab` raises an uncaught `KeyError`. - `_get_provided` (`plan.py:329`) reads `Provides` only from packages that have **already been fetched**, and `provided` is subtracted from `all_missing` only at `plan.py:406`. Nothing in that path ever causes a provider to be fetched. ## And the miss is silent `missing` is initialised at `plan.py:366` and never mutated, while `brokendeps` is built by iterating it at `plan.py:421-422`. So `resolve()` returns `(spec, [])` even when `all_missing` is non-empty: a plan entry the pool cannot supply is dropped from the spec and nothing says so. That is upstream code, not something Keel-Linux/fab#9 introduced, but it is what turns this from a build failure into a silently wrong image. ## Why it is latent rather than broken today `apt/pool/main/f/fab/fab_1.1.1+keel1_all.deb` is still in the archive. So after the conversion, and before anything changes here, TKLDev images built from this recipe would keep shipping the **pre-rename** fab while the build host itself runs `keel-fab`, which is a divergence nobody would notice. The day `fab` leaves the pool they would ship no fab at all, without an error. ## What closes this - `plan/main:3` becomes `keel-fab`, after Keel-Linux/fab#9 is merged and the package is published, and before `fab` is removed from the pool. - `overlay/usr/local/sbin/tkldev-setup:372`, `DEBIAN_FRONTEND=noninteractive apt-get install -y fab`, becomes `keel-fab`. This one *is* an apt call, and `Provides: fab` does make it install `keel-fab` while no real `fab` is reachable, but that is not the case on a machine with the TurnKey archive enabled: apt prefers a real package over a virtual provider, and upstream's real `fab` is at priority 999 there. Measured in a container, `apt-get install -y fab` with `keel-fab` installed **removes `keel-fab` and installs upstream's fab**. Keel-Linux/apt#15 adds the negative pin that stops that on the build host; this line should name the right package regardless, since tkldev-setup runs on machines that do not have our pin file. - `tests/tkldev-setup.bats:309` asserts the literal string `apt-get install -y fab` and moves with it. - The help text at `overlay/usr/local/sbin/tkldev-setup:17` says "'fab' package will be installed when relevant." ## Order Not before Keel-Linux/fab#9 merges and `keel-fab` is published, or this recipe stops resolving. Not after `fab` leaves the pool, or it silently stops shipping a builder. Between those two, and the archive change is the one to wait for. The resolver defects above are worth their own issue in `Keel-Linux/fab` whatever happens here: `resolve()` returning no error for a package the pool could not supply is the kind of thing that costs a day the first time it matters.
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
Keel-Linux/tkldev#4
No description provided.