99 package problems
Package maintenance is an often underappreciated, but critical area of software development. This is the primary mechanism for how software is installed on Linux distros such as Debian, Fedora, openSUSE, and Ubuntu. Also available on other OSes through homebrew on MacOS and chocolatey or winget on Windows platform. (NOTE: Source-based package systems such as Gentoo’s portage, ArchLinux’s AUR, Slackware’s pkgtools, and BSD’s ports will not be covered.)
In its most basic form, a [binary] package is an archive, like a tarball (or other formats such as ar, cpio, squashfs, etc.) plus metadata that includes the package name, version, dependencies, conflicts, etc. Additionally often contains pre-install, post-install, and post-removal actions or scripts, such as running ldconfig, creating symlinks, or updating a database (.desktop, manpages).
Most package formats involve a piece of software known as a package manager, which is responsible for resolving the dependency graph, installing the files into the correct locations, and determining which pieces of software can be upgraded, from a number of different sources known as repositories.
This is where the complexity comes from and packaging done correctly just works, to the point where the user does not even notice; however, even a small oversight can result in installation of an undesired version, prevent installation via [recursive] dependency hell or file conflicts, break the package manager, or even in extreme cases break the repository.
The latter case involves phone calls or messages from extremely irate users. It can be something small like a %pretrans scriplet in a RPM that only returns non-zero, during a fresh OS installation using a Kickstart config file, that fails the entire transaction. Or package generated using something other than dpkg-buildpackage, which results in non-uniform Debian repository metadata.
A fun apt-get error to debug is “Depends___ but it’s not going to be installed”, which needs to be followed through the dependency tree until a leaf is found, indicating the missing expected package version that cannot be resolved. Another is different repositories containing packages that “Provides” the same dependency, leading to all manner of difficult to reproduce deviations. Or to flip the perspective, as one user described it, the software only installs successfully during a certain phase of the moon.
On the RPM side, (with dnf5 now deprecated) modularity streams, aim to be a solution to branched or slotted package groups. However it can lead to trading one problem for another, in this case, filtering out RPMs which may be required to satisfy a dependency. That can sometimes be useful, as in the case of the RHEL precompiled kmod packages, is used to both select the appropriate kmod combination to install and to block upgrading to a kernel not yet supported by a kmod package.