An RPM dependency check tool based on a repository metadata modification approach.
  • Python 98.7%
  • Shell 1.3%
Find a file
Adam Williamson 44f1bdb0ec
Some checks failed
CI via Tox / tox (pull_request) Has been cancelled
Add rdc-el-wrapper, an opinionated wrapper for ELN testing (#37)
After much discussion with @yselkowitz, this should be the best
option for ELN testing, I hope.

ELN (like other ELs) has multiple variants with repositories.
There is a mapping in Pungi config of relationships between the
variants. Each variant is expected to be repoclosure-complete,
possibly in itself, possibly with reference to some or all of
the other variants. Each variant contains only a subset of the
packages in the buildroot.

We have been asked to make it so that, given an arbitrary set of
"packages under test" for a given EL, the packages it contains
from each variant should be tested separately against that
variant, so we fail if replacing the packages in the variant with
the matching packages from the set under test would cause new
repoclosure issues in that variant, or the packages under test
for that variant have installability issues when tested against
the variant and any others it "depends" on.

Packages from the set under test that are not in any variant
should be ignored, as repoclosure of and installability within
the buildroot is not currently desired to be tested.

This wrapper script takes as inputs a compose that we should test
against, and a filesystem path containing the packages to be
tested. The compose is usually expected to be the latest compose
of the EL under test. Using the metadata, we discover all variants
in the compose that have repositories (except Buildroot, which is
ignored). We then list out the binary packages by name in each
variant repository.

We then split the set of packages-under-test into several temporary
variant repositories: each package is placed in the repo for all
variants of which the identically-named package in the compose is a
part, if any.

We then get and parse a copy of the variant mapping from the
Pungi config. Then, for each "populated" variant (that is, a
variant for which the packages-under-test set contains at least
one package), we run rmdepcheck, with the compose repos for the
variant plus any variants it "depends" on as the baserepos, the
local temporary variant repository as the newrepo, and the local
temp repos for all "depended-on" variants as addrepos. All
rmdepcheck output is passed through.

We track the return codes of each rmdepcheck run and return the
sum of each unique return code.

Signed-off-by: Adam Williamson <awilliam@redhat.com>
2026-05-01 15:46:35 -07:00
.forgejo/workflows ai-review workflow: use reusable workflow 2026-03-25 09:22:53 -07:00
tests Add non-checked base repo concept (#37) 2026-05-01 15:43:50 -07:00
.gitignore Initial version of rmdepcheck 2025-06-18 13:13:13 +02:00
CHANGELOG.md Update CHANGELOG for 1.1.0 2025-07-14 16:03:02 -07:00
COPYING Add CHANGELOG.md and COPYING 2025-06-19 14:02:35 +01:00
install.requires Add rdc-el-wrapper, an opinionated wrapper for ELN testing (#37) 2026-05-01 15:46:35 -07:00
pyproject.toml Drop XML parsing, switch to using dnf excludepkgs (#5) 2026-04-18 00:05:57 -07:00
rdc-el-wrapper.py Add rdc-el-wrapper, an opinionated wrapper for ELN testing (#37) 2026-05-01 15:46:35 -07:00
README.md Add rdc-el-wrapper, an opinionated wrapper for ELN testing (#37) 2026-05-01 15:46:35 -07:00
release.sh Initial version of rmdepcheck 2025-06-18 13:13:13 +02:00
rmdepcheck.py Add non-checked base repo concept (#37) 2026-05-01 15:43:50 -07:00
tests.requires Initial version of rmdepcheck 2025-06-18 13:13:13 +02:00
tox.ini Add a mypy check to tox configuration 2025-06-19 15:37:56 +01:00
tox.requires Drop XML parsing, switch to using dnf excludepkgs (#5) 2026-04-18 00:05:57 -07:00

rmdepcheck

rmdepcheck is an RPM dependency check tool based on a repository metadata modification approach. It works by comparing a checked repository to one or more base repositories. First, checks are run on the base repositories as-is. Next, we re-run the checks, but with the checked repository available and using dnf's excludepkgs option to hide from the base repositories all packages from the same source RPM(s) as the package(s) in the checked repositories removed. The results of the two runs are compared. New failures should indicate problems introduced by the checked repositories. Also, some relevant checks are run on the checked repositories with reference to the modified base repositories.

Optionally, other types of repository can be specified:

  • Additional base repositories which will not be modified or checked ("non-modified base repos")
  • Additional base repositories which will be modified but not checked ("non-checked base repos")
  • Additional new repositories can be specified which will not be checked directly

Non-modified base repos are intended for testing scenarios like stable Fedora releases, which have a frozen release repository which is never modified, and an updates repository which is updated.

Non-checked base repos and additional new repos are intended for Enterprise Linux distributions. These have multiple variants with repositories, and "dependencies" among them, e.g. packages in the HighAvailability variant can depend on packages in the BaseOS and Appstream variants. We may be testing an update containing packages destined for all three variants, which we split into three repositories. When testing the HA repository, we would want to have the "new package" BaseOS and Appstream repositories "in scope" but not checked ("additional new repositories"), and the "base" BaseOS and Appstream repositories "in scope" and modified, but not checked ("non-checked base repositories").

Additional new repositories might also be used for multilib scenarios; it may be desirable to use such an additional repository for packages for the multilib arch(es), if e.g. installability of these should not be tested directly.

An alternative mode allows simply testing the consequences of removing a list of source packages entirely; in this mode, in the second step, we exclude all binary packages built from the specified source packages. The installability check is skipped in this context.

rdc-el-wrapper

rdc-el-wrapper is an opinionated wrapper for running rmdepcheck on Enterprise Linux. The EL case is complicated because EL composes contain multiple variants with package repositories. These contain a subset of all packages in the buildroot. Each variant is expected to be repoclosure- complete with regard to itself and possibly some or all of the other variants; the mapping for this is kept in Pungi configuration.

Because of this we cannot just test the packages-under-test against the buildroot, as we do for Fedora. We must split the packages-under-test set into per-variant repositories, with each package included in each repository it should be part of (we assume this mapping is not changed from the compose we're testing against, and discover it from that). We then test each of the split repos against the same variant repo from the compose, with other variant repos in scope on both sides, as per the Pungi mapping. This is a lot of work but should provide the most accurate and useful results.

Requirements

rmdepcheck has no run-time Python dependencies outside the standard library. Its only external dependency is dnf. It checks for dnf, and will exit early with an error if it is not found. rmdepcheck is written primarily for Red Hat-family distributions, but should in theory be usable anywhere these utilities can be installed (and forward slashes act as directory separators).

If you use a version of dnf older than 5.2.15.0, you may see false failures for 'rich' dependencies, as older dnf versions did not handle these correctly. Use 5.4.0.0 or newer for the best handling of 'rich' dependencies (5.2.15.0 through 5.3.0.0 ignored them entirely; 5.4.0.0 checks them correctly).

Installation

Installation of rmdepcheck is entirely optional, it can be run just as well directly from the repository. Otherwise, rmdepcheck uses setuptools for installation and is PEP 518-compliant. You can build and install with e.g. the build module and pip. rmdepcheck can also be installed directly from PyPI with pip and other tools.

Usage

Simple usage looks like this:

rmdepcheck https://a.base.repo.example/repo,file:///another/baserepo file:///the/testedrepo

The repositories are specified as a comma-separated list. Repositories should be specified as URLs, but for convenience, file:// can be omitted. Only file:// , http:// and https:// URLs are accepted.

For the alternative 'removal' mode, usage looks like:

rmdepcheck --removes https://a.base.repo.example/repo,file:///another/baserepo sourcepkg1,sourcepkg2

This tests removing sourcepkg1 and sourcepkg2, and all binary packages built from them, from the base repositories.

If you want to test repositories containing packages of an arch that does not match the system on which you are testing, pass --arch <arch>, where <arch> is the arch you wish to test.

For more complex usage, see rmdepcheck --help.

Note rmdepcheck is really only intended for use as a script, not as an importable library. If you want to use it as a library go ahead, but this isn't a supported use case and bugs in it may not be addressed.

rdc-el-wrapper usage looks like this:

rdc-el-wrapper https://kojipkgs.fedoraproject.org/compose/eln/latest-Fedora-eln/compose /the/testedrepo

An optional --arch arg can be passed as for rmdepcheck. Note that you MUST NOT include file:// in the tested repo arg, and it MUST be a local filesystem path. rdc-el-wrapper does not support remote tested repos.

Testing build dependencies

You can include source package repositories in the base repository set. This has the effect of testing for build dependency breakages, as the dependencies of a source package are its build requirements. You can identify build dependency breakages in the output by the package name ending in .src.

When doing this, you must also include at least one matching binary repository, or all requirements of all source packages will be unresolvable and the tool will run slowly and produce useless output.

Example:

rmdepcheck https://a.base.repo.example/binaryrepo,https://a.base.repo.example/sourcerepo file:///the/testedrepo

License

rmdepcheck is released under the GPL, version 3 or later. See COPYING and the header of rmdepcheck.py itself.

Contributing

Issues and pull requests can be filed in Fedora Forge.

ANY USE OF AI/LLM IN THE PRODUCTION OF A PULL REQUEST MUST BE CLEARLY DISCLOSED. This is for legal reasons, as the copyrightability of LLM-generated code is (as of April 2026) disputed and unclear. This is also for technical reasons, as reviewers may need to look out for different problems when reviewing LLM-generated code, compared to human-generated code.

Please include an Assisted-by line in the commit message, specifying the model, tool and/or service used in creating the pull request, and a more detailed explanation of how LLM technologies were used in the pull request description. This can be copied/pasted from PR to PR if the workflow remains the same.

Here is a sample commit message:

Make the frobnosticator reticulate splines better

By rejigging the frobnosticator, we can reticulate splines twice as fast!

Signed-off-by: Bob Roberts <bob@example.com>
Assisted-by: OpenCode 1.3.15 | claude-4.6-opus-high

Pull requests must be signed off (use the -s git argument). By signing off your pull request you are agreeing to the Developer's Certificate of Origin:

Developer's Certificate of Origin 1.1

By making a contribution to this project, I certify that:

(a) The contribution was created in whole or in part by me and I
    have the right to submit it under the open source license
    indicated in the file; or

(b) The contribution is based upon previous work that, to the best
    of my knowledge, is covered under an appropriate open source
    license and I have the right under that license to submit that
    work with modifications, whether created in whole or in part
    by me, under the same open source license (unless I am
    permitted to submit under a different license), as indicated
    in the file; or

(c) The contribution was provided directly to me by some other
    person who certified (a), (b) or (c) and I have not modified
    it.

(d) I understand and agree that this project and the contribution
    are public and that a record of the contribution (including all
    personal information I submit with it, including my sign-off) is
    maintained indefinitely and may be redistributed consistent with
    this project or the open source license(s) involved.