Skip to content

Commit

Permalink
Dynamic BuildRequires: Prevent generation of unsatisfied dependency
Browse files Browse the repository at this point in the history
When the %generate_buildrequires section behaved unpredictable,
it was possible to successfully build a package with unsatisfied
BuildRequires. Now, the build will fail.

Fixes #1246
  • Loading branch information
hroncok committed Oct 19, 2023
1 parent c3a4bca commit a1639d7
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 4 deletions.
20 changes: 16 additions & 4 deletions mock/py/mockbuild/backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -737,18 +737,20 @@ def rebuild_package(self, spec_path, timeout, check, dynamic_buildrequires):
if additional_opts == ['']:
additional_opts = []

def get_command(mode):
def get_command(mode, checkdeps=False):
nodeps_opt = [] if checkdeps else ['--nodeps']
command = [self.config['rpmbuild_command']] + mode + \
[self._rpmbuild_noclean_option] + \
['--target', self.rpmbuild_arch, '--nodeps'] + \
['--target', self.rpmbuild_arch] + nodeps_opt + \
check_opt + [spec_path] + additional_opts
command = ["bash", "--login", "-c"] + [' '.join(command)]
return command

bd_out = self.make_chroot_path(self.buildroot.builddir)
max_loops = int(self.config.get('dynamic_buildrequires_max_loops'))
success = False
if dynamic_buildrequires and self.config.get('dynamic_buildrequires'):
dynamic_buildrequires = dynamic_buildrequires and self.config.get('dynamic_buildrequires')
if dynamic_buildrequires:
while not success and max_loops > 0:
# run rpmbuild+installSrpmDeps until
# * it fails
Expand Down Expand Up @@ -787,7 +789,17 @@ def get_command(mode):
# on re-doing it
mode += ['--noprep']

self.buildroot.doChroot(get_command(mode),
# When we used dynamic buildrequires, we must let rpmbuild check deps.
# The rpmbuild -ba call executes the %generate_buildrequires once again
# in order to actually add the BuildRequires to the SRPM metadata.
# Since the output of the %generate_buildrequires section isn't
# controlled by mock, it is possible (albeit unlikely) that the list
# of generated BuildRequires will differ now, as it is not guaranteed
# to remain stable.
# By instructing rpmbuild to check dependencies, we ensure a failure
# if a new unsatisfied dependency is generated.
# See https://github.com/rpm-software-management/mock/issues/1246
self.buildroot.doChroot(get_command(mode, checkdeps=dynamic_buildrequires),
shell=False, logger=self.buildroot.build_log, timeout=timeout,
uid=self.buildroot.chrootuid, gid=self.buildroot.chrootgid,
user=self.buildroot.chrootuser,
Expand Down
16 changes: 16 additions & 0 deletions releng/release-notes-next/generate_buildrequires.bug
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
When Mock completes the installation of all the requirements generated
by `%generate_buildrequries`, it calls `rpmbuild -ba` to perform a final build
of the package.

During the final build, `%generate_buildrequries` runs again in order to
generate a list of `BuildRequires` to be added to the built SRPM metadata.
An arbitrary `%generate_buildrequries` section may generate different
requirements that may not have been installed.

Previously, the `rpmbuild -ba` call used the `--nodeps` option,
hence it was possible to successfully build a package with
unsatisfiable BuildRequires in the built SRPM metadata.

The `--nodeps` option is no longer used in the final `rpmbuild -ba` call.
If `%generate_buildrequries` attempts to generate new unsatisfied requirements
during the final build, the build will fail.

0 comments on commit a1639d7

Please sign in to comment.