Skip to content

Commit 5690d5f

Browse files
committed
csmock: add experimental --hermetic-build option
Using this requires setting up the lockfile and local repo earlier using regular mock, as described here: https://github.com/rpm-software-management/mock/blob/main/docs/feature-hermetic-builds.md This requires that the required scanners are either provided by the host or present in the buildroot. For instance `-t gcc` will work only if `gcc` is a build dependency. `-t cppcheck` will work if the `--use-host-cppcheck` param is used. PSSECAUT-1524
1 parent 8203630 commit 5690d5f

File tree

1 file changed

+44
-2
lines changed

1 file changed

+44
-2
lines changed

csmock/csmock

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import shutil
3030
import subprocess
3131
import sys
3232
import time
33+
from typing import Optional, Tuple
3334

3435
# local imports
3536
import csmock.common.util
@@ -203,6 +204,8 @@ class MockWrapper:
203204
self.results = results
204205
self.mock_profile = props.mock_profile
205206
self.mock_root_override = props.mock_root_override
207+
self.hermetic_build = props.hermetic_build
208+
self.srpm = props.srpm
206209
self.pid = os.getpid()
207210
self.scrub_done = props.skip_mock_init
208211
self.init_done = props.skip_mock_init
@@ -282,6 +285,17 @@ echo \"$self_pid\" > \"$lock_file\"'" \
282285
"--disable-plugin=yum_cache"]
283286
self.def_cmd += [f"--config-opts=root={self.mock_root_override}"]
284287

288+
if self.hermetic_build is not None:
289+
(lockfile, repo_dir) = self.hermetic_build
290+
291+
hermetic_cmd = [mock, "--hermetic-build", lockfile, repo_dir, "--short-circuit=prep", "-N", self.srpm]
292+
ec = self.results.exec_cmd(hermetic_cmd)
293+
if ec != 0:
294+
self.results.error("failed to set up hermetic chroot", ec=ec)
295+
296+
# provide the offline repo for subsequent mock commands
297+
self.def_cmd += [f"--config-opts=offline_local_repository={repo_dir}"]
298+
285299
return self
286300

287301
def __exit__(self, exc_type, exc_val, exc_tb):
@@ -403,7 +417,8 @@ echo \"$self_pid\" > \"$lock_file\"'" \
403417
self.init_done = True
404418

405419
# run `mock --calculate-build-dependencies`
406-
srpm_deps_ok = srpm is None or self.install_deps(srpm)
420+
# skip for hermetic builds (deps should be calculated prior)
421+
srpm_deps_ok = srpm is None or self.hermetic_build is not None or self.install_deps(srpm)
407422
if not srpm_deps_ok and not try_only:
408423
srpm_base = os.path.basename(srpm)
409424
self.results.error(f"failed to install build dependencies of {srpm_base}", ec=ec_by_scrub)
@@ -422,6 +437,13 @@ echo \"$self_pid\" > \"$lock_file\"'" \
422437
if not missing_deps:
423438
# no misssing dependencies
424439
return srpm_deps_ok
440+
441+
if self.hermetic_build and missing_deps:
442+
self.results.print_with_ts(
443+
f"WARN: Proceeding with hermetic build despite missing deps: {strlist_to_shell_cmd(missing_deps)}"
444+
)
445+
return srpm_deps_ok
446+
425447
if try_only:
426448
return False
427449

@@ -476,7 +498,7 @@ class ScanProps:
476498
self.shell_cmd_to_build = None
477499
self.srpm = None
478500
self.base_srpm = None
479-
self.mock_profile = None
501+
self.mock_profile: Optional[str] = None
480502
self.base_mock_profile = None
481503
self.mock_root_override = None
482504
self.any_tool = False
@@ -486,6 +508,7 @@ class ScanProps:
486508
self.imp_csgrep_filters = []
487509
self.cswrap_path = None
488510
self.kfp_git_url = None
511+
self.hermetic_build: Optional[Tuple] = None
489512

490513
def enable_cswrap(self):
491514
if self.cswrap_enabled:
@@ -862,6 +885,14 @@ exceeds the specified limit (defaults to 1024).")
862885
help='override the build root directory for mock (disables yum and root cache)'
863886
)
864887

888+
parser.add_argument(
889+
"--hermetic-build",
890+
nargs=2,
891+
metavar=("LOCKFILE", "REPO_DIRECTORY"),
892+
help="perform a hermetic (fully offline) build using a pre-generated "
893+
"lockfile and offline RPM repository (see mock --hermetic-build)",
894+
)
895+
865896
# --skip-patches, --diff-patches, and --shell-cmd are mutually exclusive
866897
group = parser.add_mutually_exclusive_group()
867898
group.add_argument(
@@ -996,6 +1027,17 @@ exceeds the specified limit (defaults to 1024).")
9961027

9971028
props.mock_root_override = args.mock_root_override
9981029

1030+
if args.hermetic_build is not None:
1031+
(lockfile, repo_dir) = args.hermetic_build
1032+
require_file(parser, lockfile)
1033+
if not os.path.isdir(repo_dir):
1034+
parser.error(f"not a directory: {repo_dir}")
1035+
if not os.path.isdir(os.path.join(repo_dir, "repodata")):
1036+
parser.error(f"repo directory missing repodata/: {repo_dir}")
1037+
props.hermetic_build = (os.path.realpath(lockfile), os.path.realpath(repo_dir))
1038+
props.mock_profile = "hermetic-build"
1039+
props.skip_mock_init = True
1040+
9991041
# append the list of packages to install specified on command-line
10001042
for pkg in args.install:
10011043
props.install_pkgs += pkg.split()

0 commit comments

Comments
 (0)