Skip to content

feat(debos): validate host build dependencies per use-case - #454

Open
Bjordis Collaku (bjordiscollaku) wants to merge 7 commits into
qualcomm-linux:mainfrom
bjordiscollaku:feat/check-deps
Open

feat(debos): validate host build dependencies per use-case#454
Bjordis Collaku (bjordiscollaku) wants to merge 7 commits into
qualcomm-linux:mainfrom
bjordiscollaku:feat/check-deps

Conversation

@bjordiscollaku

@bjordiscollaku Bjordis Collaku (bjordiscollaku) commented Jun 18, 2026

Copy link
Copy Markdown

Nothing on main validates the host tools the builds need before running
debos, and the two hand-maintained apt lists have drifted: the README
build-deps line is missing device-tree-compiler, u-boot-tools and file
that the CI step installs. A local make with a tool missing fails
somewhere inside debos with a confusing error rather than a clear one up
front.

check-deps.sh now owns the package lists, keyed by use-case. The Makefile
validates the right use-case before each debos call (or installs it with
AUTO_INSTALL_DEPS=yes), CI and the README run one line,
scripts/check-deps.sh --install host rootfs image flash test, and no
package name appears anywhere else.

use-case packages
host debos, make, ipxe-qemu, linux-image-arm64 (arch-dependent)
rootfs mmdebstrap, debian-archive-keyring
image dosfstools, e2fsprogs, parted, fdisk, udev
flash dosfstools, mtools, xmlstarlet, python3-defusedxml, unzip, device-tree-compiler, u-boot-tools, file, ca-certificates
test qemu-efi-aarch64, qemu-utils, ipxe-qemu, python3-pexpect, python3-pytest

Validate reads the dpkg-query Status field and requires "ok installed"
rather than trusting dpkg -s, which also exits 0 for a package in
config-files or a half-configured state; the install path is a plain
apt-get install -y --no-install-recommends. qemu-system-arm stays off
the lists: it is a Depends of debos, so installing debos pulls it in.

Four packages are named that the old apt line never was; they reached the
build via apt Recommends and are dropped once installs use
--no-install-recommends. linux-image-arm64 is a Recommends of debos, the
kernel fakemachine boots from /boot (the CI job container ships none); the
script installs linux-image-$(dpkg --print-architecture), and only where
that meta-package resolves, since a normal host already has a kernel.
ipxe-qemu is a Recommends of qemu-system-arm and ships
/usr/share/qemu/efi-virtio.rom, without which qemu will not start the
default virtio-net-pci NIC, so fakemachine and the boot test fail at
startup. qemu-utils is a Recommends of qemu-system-arm and ships qemu-img,
which ci/qemu_test.py runs first to build the boot overlay.
ca-certificates' postinst runs update-ca-certificates to generate the CA
bundle /etc/ssl/certs/ca-certificates.crt, which debos (a Go binary)
verifies https downloads against; nothing in the install set Depends on
it. udev is in the image list for a different reason: debos's
image-partition execs udevadm trigger --settle directly. It is a
Recommends of debos, and its only other route is the kernel's
initramfs-tools alternative dependency, so image names it rather than
relying on either.

Checked by replaying the workflow in the debian:trixie CI container
(public.ecr.aws/debian/debian:trixie, arm64): union install; per-use-case
validate against present, missing and config-files states; and rootfs,
UFS image and flash builds under the qemu fakemachine backend, plus the
qemu boot test, all green in that container. That does not cover the
self-hosted arm64 runner environment (/efs, artifact upload); the CI run
on this PR exercises that.

Provisioning the debos container image stays out of scope, as does
folding in build-linux-deb.py and build-u-boot-rb1.sh.

@bjordiscollaku
Bjordis Collaku (bjordiscollaku) force-pushed the feat/check-deps branch 5 times, most recently from 27b6172 to f113acf Compare June 18, 2026 06:20
@bjordiscollaku Bjordis Collaku (bjordiscollaku) changed the title feat(debos): add runtime host dependency validation feat(debos): add runtime host dependency validation for all execution environments Jun 18, 2026
@bjordiscollaku Bjordis Collaku (bjordiscollaku) changed the title feat(debos): add runtime host dependency validation for all execution environments feat(debos): add host dependency validation with per-recipe dep sets Jun 18, 2026
@bjordiscollaku Bjordis Collaku (bjordiscollaku) changed the title feat(debos): add host dependency validation with per-recipe dep sets feat(debos): fail fast on missing host dependencies, auto-install in Docker path Jun 18, 2026
@github-actions

github-actions Bot commented Jun 18, 2026

Copy link
Copy Markdown

Test Results

 2 files  ±0   6 suites  ±0   3m 33s ⏱️ ±0s
20 tests ±0  20 ✅ ±0  0 💤 ±0  0 ❌ ±0 
64 runs  ±0  64 ✅ ±0  0 💤 ±0  0 ❌ ±0 

Results for commit 4ba715c. ± Comparison against base commit 9526d3a.

♻️ This comment has been updated with latest results.

@github-actions

Copy link
Copy Markdown

Test jobs for commit f113acf

@bjordiscollaku Bjordis Collaku (bjordiscollaku) changed the title feat(debos): fail fast on missing host dependencies, auto-install in Docker path feat(debos): add per-recipe host dependency validation with auto-install in Docker Jun 18, 2026

@lool Loïc Minier (lool) left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Bjordis Collaku (@bjordiscollaku) this looks very nice! I made a number of requests for small changes

Comment thread Makefile Outdated
Comment thread scripts/check-deps.sh Outdated
Comment thread scripts/check-deps.sh Outdated
Comment thread scripts/check-deps.sh Outdated
Comment thread scripts/check-deps.sh Outdated
Comment thread scripts/check-deps.sh Outdated
Comment thread debos-recipes/qualcomm-linux-debian-image.yaml Outdated
Comment thread .github/workflows/debos.yml Outdated
# file, device-tree-compiler and u-boot-tools are needed by qcom-dtb-metadata
- name: Install debos and dependencies of the recipes and local tests
run: apt -y install debian-archive-keyring debos file make mmdebstrap mtools python3-pexpect python3-pytest qemu-efi-aarch64 qemu-system-arm xmlstarlet python3-defusedxml device-tree-compiler u-boot-tools
run: apt -y install debian-archive-keyring debos dosfstools file make mmdebstrap mtools python3-pexpect python3-pytest qemu-efi-aarch64 qemu-system-arm xmlstarlet python3-defusedxml device-tree-compiler u-boot-tools

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could we drop these and set -t auto_install_deps:true during our CI?

@bjordiscollaku Bjordis Collaku (bjordiscollaku) Jun 18, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd keep the explicit list for CI, for two reasons.

That apt line installs more than the recipes' host deps: it also brings in debos itself, the local test harness (python3-pexpect, python3-pytest), qemu-*, device-tree-compiler and u-boot-tools. None of those are in any recipe's check-deps set, so auto_install_deps:true wouldn't pull them and the job would lose debos and the pytest run.

And in CI the image/flash recipes run under -b qemu, so their check runs inside the fakemachine guest where /var/lib/dpkg/status doesn't exist and it skips, so auto_install_deps is effectively inert for those two. Only rootfs runs natively. The host tools image/flash need (mkfs.vfat, mtools, and so on) have to be on the runner before debos starts, which is what this step provides.

Side note while we're here: most of that filesystem tooling is already pulled in transitively. The Debian debos package Recommends dosfstools/e2fsprogs/parted/fdisk and we install with recommends on, which is why main builds vfat+ext4 green without an explicit dosfstools. The line I added is really just belt-and-suspenders against a future --no-install-recommends.

If the duplication between the recipe lists and this step is what's bugging you, I'd rather lift the dep lists into one shared spot than drop the CI install. Happy to do that as a follow-up.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, duplication was what was on my mind; how could we avoid it?

Maybe we shouldn't be running this script from within the recipe, but just before calling debos on the recipe.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. We could move it out of the recipe and run it just before the debos call, say from the Makefile, and keep each recipe's deps as a variable there. That way they're not repeated between the recipes and the CI apt step. What do you think?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup; I think this would look clean. I wonder whether the script should have the list of use cases embedded in it, so that makefile / CI / README basically leverage check-deps.sh host , check-deps.sh image, check-deps.sh flash etc.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep agreed, and the use cases would be:

  • host: debos, make, qemu-system-arm
  • rootfs: mmdebstrap, debian-archive-keyring
  • image: dosfstools, e2fsprogs
  • flash: dosfstools, mtools, xmlstarlet, python3-defusedxml, unzip, device-tree-compiler, u-boot-tools, file
  • test: qemu-efi-aarch64, qemu-system-arm, python3-pexpect, python3-pytest

Makefile, CI, and README each call check-deps.sh <use-case>. Does that grouping look right?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't cross-checked the lists of packages, but +1 on the target names

@github-actions

Copy link
Copy Markdown

Test jobs for commit b9ac53d

@github-actions

Copy link
Copy Markdown

Test jobs for commit d1df400

@lool

Copy link
Copy Markdown
Contributor

Bjordis Collaku (@bjordiscollaku) BTW I just remembered, we also have a couple more implementations of similar logic in the same repo:

  • scripts/build-linux-deb.py
  • scripts/build-u-boot-rb1.sh

but we can address these later or even let them be. Slight preference for a Python implementation eventually, but also happy with the current shell one to start with, it's simple enough.

@obbardc

Copy link
Copy Markdown
Contributor

My comment would be to not include qemu in the list, since it's a dependency on the Debian package of debos

@bjordiscollaku

Copy link
Copy Markdown
Author

Bjordis Collaku (@bjordiscollaku) BTW I just remembered, we also have a couple more implementations of similar logic in the same repo:

  • scripts/build-linux-deb.py
  • scripts/build-u-boot-rb1.sh

but we can address these later or even let them be. Slight preference for a Python implementation eventually, but also happy with the current shell one to start with, it's simple enough.

Sounds good, I'll leave those two for a follow-up.

@bjordiscollaku

Copy link
Copy Markdown
Author

My comment would be to not include qemu in the list, since it's a dependency on the Debian package of debos

Agreed, dropping qemu-system-arm. I'd keep qemu-efi-aarch64 though, it's the aarch64 UEFI firmware the boot test needs and debos doesn't pull it (only Recommends: ovmf).

@obbardc

Copy link
Copy Markdown
Contributor

My comment would be to not include qemu in the list, since it's a dependency on the Debian package of debos

Agreed, dropping qemu-system-arm. I'd keep qemu-efi-aarch64 though, it's the aarch64 UEFI firmware the boot test needs and debos doesn't pull it (only Recommends: ovmf).

Yeah, that sounds good to me. Thanks!

Comment thread scripts/check-deps.sh Outdated

missing=""
for pkg in "$@"; do
dpkg -s "$pkg" >/dev/null 2>&1 || missing="$missing $pkg"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not a robust way of determining if a package is installed. Packages can be in a removed (but not purged) or broken state and would still appear under dpkg -s. Instead you could use apt-get install -s to see what apt-get would do, to see if any package installations are required.

I would call sudo apt-get install -y --no-install-recommends "$@" in the --install case, and apt-get install -qqs --no-install-recommends "$@"|grep -E '^(Inst|Conf)' in the non- --install case. Wouldn't that be much cleaner, and avoid having to second guess apt with dpkg?

It would have the effect of failing if an apt upgrade is pending, but generally that seems like a good idea anyway, and I prefer that over the fragility of calling dpkg directly. If you want to avoid that, then you could call dpkg-query -f '${Status}' -W "$@" and check for ok and installed in the second and third columns or similar.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the feedback Robie.

--install: I'll drop the pre-check and just call apt-get install -y --no-install-recommends on the set, since it's idempotent.

Validate-only: you preferred the simulate, but I'd take the dpkg-query option you offered, because of one hole I checked in the simulate. On a name apt can't resolve (a typo, or a dropped/renamed package), apt-get install -qqs <name> prints "Unable to locate package" to stderr and nothing to stdout, so grep -E '^(Inst|Conf)' matches nothing and the check reads it as satisfied. dpkg-query -f '${Status}' -W reports it not-installed there, so the gate fails closed instead.

Introduce scripts/check-deps.sh, a lightweight helper that validates
required host packages are installed before a debos recipe proceeds.
Each recipe declares its own dependency set and calls the script as its
first action (chroot: false), ensuring failures are caught immediately
with a clear diagnostic rather than mid-run with a cryptic tool error.

The script accepts an optional --install flag. When present, it runs
apt-get to install any missing packages. When absent, it reports the
missing packages to stderr and exits non-zero, directing the user to
either install them manually or pass -t auto_install_deps:true.

The Makefile sets auto_install_deps:true for the Docker container path
(USE_CONTAINER=yes), so make flash / make all work out-of-the-box
against ghcr.io/go-debos/debos:latest without requiring a pre-customised
image. The native debos path is unchanged: the check runs in
validate-only mode and fails fast if dependencies are absent.

When dpkg infrastructure is not present (e.g. inside a fakemachine qemu
VM), the script exits silently. In that environment dependencies are
expected to be installed on the real host before debos is invoked.

The GitHub Actions workflow installs all recipe dependencies on the CI
host via apt before invoking debos, including dosfstools which is now
explicitly listed. Recipes running under fakemachine skip the check
silently as described above.

Dependency sets per recipe:
  qualcomm-linux-debian-rootfs.yaml:  debian-archive-keyring mmdebstrap
  qualcomm-linux-debian-image.yaml:   dosfstools
  qualcomm-linux-debian-flash.yaml:   dosfstools mtools python3-defusedxml
                                      unzip xmlstarlet

Addresses the dependency management approach discussed in PR qualcomm-linux#371.

Signed-off-by: Bjordis Collaku <bcollaku@qti.qualcomm.com>
Address review feedback on the host dependency validation.

Move "-t auto_install_deps:true" ahead of $(DEBOS_OPTS) in the
container command so that EXTRA_DEBOS_OPTS can still override it; debos
applies the last -t value given for a key. Document why auto-installing
into the disposable container is safe.

Expand the dpkg-database guard and the no-missing exit into explicit
if/then blocks, and warn on stderr when the check is skipped. The guard
tests for the dpkg database rather than the dpkg binary because a
chroot:false action inside a fakemachine guest sees the host /usr, and
therefore the dpkg binary, but not /var; only the database is a
reliable signal of a queryable host.

Log the APT refresh and the exact package set before installing, and
drop apt-get's -qq so failing sources are visible.

No change to the dependency sets or to the native/CI fail-fast path;
the container path gains a documented opt-out and clearer diagnostics.

Signed-off-by: Bjordis Collaku <bcollaku@qti.qualcomm.com>
The image recipe's image-partition action formats both filesystems: the
vfat ESP (mkfs.vfat, from dosfstools) and the ext4 root (mkfs.ext4, from
e2fsprogs). Only dosfstools was declared. e2fsprogs is Priority important
in trixie, not required, so a stripped-down container is not guaranteed
to ship it; list it explicitly, mirroring the vfat tool.

Host dependency check only; no change to recipe logic or the produced
image.

Signed-off-by: Bjordis Collaku <bcollaku@qti.qualcomm.com>
The dependency check ran inside the recipes as a chroot:false action.
Under fakemachine that runs in the guest, where /var/lib/dpkg/status does
not exist, so it skipped on every fakemachine-backed build and never
validated or installed anything.

Move it out. check-deps.sh now holds the package lists keyed by use-case
(host, rootfs, image, flash, test) so the Makefile, and later CI and the
README, can call a use-case name instead of repeating a package list. The
Makefile runs the check right before each debos call, the recipes carry
no dependency logic anymore, and with the check on the host rather than a
guest it tests for the dpkg command instead of the status file.

The check validates and fails by default; AUTO_INSTALL_DEPS=yes makes it
install instead. The container path keeps calling debos directly,
provisioning that image is a separate concern, and the now-dead
-t auto_install_deps:true flag is gone.

qemu-system-arm is a Depends of debos, so it is not listed.
dosfstools, e2fsprogs, parted, fdisk and udev are Recommends of debos,
not Depends, and the image-partition action execs mkfs.vfat, mkfs.ext4,
parted, sfdisk and udevadm, so image lists them.

Signed-off-by: Bjordis Collaku <bcollaku@qti.qualcomm.com>
dpkg -s exits 0 for a package in config-files (removed, not purged) or a
half-configured state, so a package whose binaries are gone still passed
the check. Read the dpkg-query Status field and require "ok installed"
instead; held packages still pass.

On the install path, drop the pre-computed missing list and just run
apt-get install -y --no-install-recommends on the whole set. apt is
idempotent, so there is no point second-guessing it with dpkg.

Signed-off-by: Bjordis Collaku <bcollaku@qti.qualcomm.com>
Four tools reached the build only because the old CI installed with apt
Recommends enabled. This install path uses --no-install-recommends, so
name each in the use-case that needs it:

- linux-image-arm64 (host): a Recommends of debos. fakemachine boots a
  kernel from /boot and the CI job container ships none. The script
  installs linux-image-$(dpkg --print-architecture), and only where that
  meta-package resolves; a normal host has a kernel already.
- ipxe-qemu (host, test): a Recommends of qemu-system-arm. It ships
  /usr/share/qemu/efi-virtio.rom; without it qemu will not start the
  default virtio-net-pci NIC, so fakemachine and the boot test fail at
  startup.
- qemu-utils (test): a Recommends of qemu-system-arm, shipping qemu-img,
  which ci/qemu_test.py runs first to build the boot overlay.
- ca-certificates (flash): the flash recipe fetches over https and debos
  verifies against the CA bundle /etc/ssl/certs/ca-certificates.crt;
  nothing in the install set Depends on it.

udev (in the image list) is also a Recommends of debos but is not in this
set: it survives --no-install-recommends via the kernel's initramfs-tools
alternative dependency, and image lists it because image-partition execs
udevadm directly.

None of the four is new to the build; all were pulled by Recommends
before.

Signed-off-by: Bjordis Collaku <bcollaku@qti.qualcomm.com>
…ADME

Replace both hand-maintained apt lines with
scripts/check-deps.sh --install host rootfs image flash test. The two had
drifted (the README one was missing device-tree-compiler, u-boot-tools
and file); now the package names live only in check-deps.sh.

Signed-off-by: Bjordis Collaku <bcollaku@qti.qualcomm.com>
@bjordiscollaku Bjordis Collaku (bjordiscollaku) changed the title feat(debos): add per-recipe host dependency validation with auto-install in Docker feat(debos): validate host build dependencies per use-case Jul 8, 2026
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown

@github-actions

github-actions Bot commented Aug 8, 2026

Copy link
Copy Markdown

This PR is stale. Add a nice message, can mention maintainers or maintainer team to draw attention

@github-actions github-actions Bot added the Stale label Aug 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants