Skip to content

Commit 916088a

Browse files
build-with-container: improve source rpm detection
Improve source rpm detection by adding a new detection method that executes and rpm command in a container to get exactly the version of the source rpm that the ceph.spec file would have generated. For backwards compatibility and that I don't entirely trust myself to have tested this the old methods are still available. The old `--rpm-no-match-sha` is now an alias for `--srpm-match=any` to cause it to build any (unique) ceph srpm it finds. `--srpm-match=versionglob` retains the previous default behavior of using a glob matching on the git id or ceph version value. The new default of `--srpm-match=auto` implements the rpm command based behavior described above. All of this is wrapped in a new step `find-rpm` but that's mostly an implementation detail and for testing. Signed-off-by: John Mulligan <[email protected]>
1 parent 544d8ab commit 916088a

File tree

1 file changed

+88
-22
lines changed

1 file changed

+88
-22
lines changed

src/script/build-with-container.py

Lines changed: 88 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,7 @@ class Steps(StrEnum):
297297
TESTS = "tests"
298298
CUSTOM = "custom"
299299
SOURCE_RPM = "source-rpm"
300+
FIND_SRPM = "find-srpm"
300301
RPM = "rpm"
301302
DEBS = "debs"
302303
PACKAGES = "packages"
@@ -330,6 +331,7 @@ def __init__(self, cli):
330331
self.cli = cli
331332
self._engine = None
332333
self.distro_cache_name = ""
334+
self.current_srpm = None
333335

334336
@property
335337
def container_engine(self):
@@ -456,7 +458,7 @@ def wants(self, step, ctx, *, force=False, top=False):
456458
if ctx.cli.no_prereqs and not top:
457459
log.info("Running prerequisite steps disabled")
458460
return
459-
if step in self._did_steps:
461+
if step in self._did_steps and not force:
460462
log.info("step already done: %s", step)
461463
return
462464
if not self._did_steps:
@@ -720,11 +722,59 @@ def _glob_search(ctx, pattern):
720722
return result
721723

722724

723-
@Builder.set(Steps.RPM)
724-
def bc_build_rpm(ctx):
725-
"""Build RPMs from SRPM."""
726-
srpm_glob = "ceph*.src.rpm"
727-
if ctx.cli.rpm_match_sha:
725+
def _find_srpm_glob(ctx, pattern):
726+
paths = _glob_search(ctx, pattern)
727+
if len(paths) > 1:
728+
raise RuntimeError(
729+
"too many matching source rpms"
730+
f" (rename or remove unwanted files matching {pattern} in the"
731+
" ceph dir and try again)"
732+
)
733+
if not paths:
734+
log.info("No SRPM found for pattern: %s", pattern)
735+
return None
736+
return paths[0]
737+
738+
739+
def _find_srpm_by_rpm_query(ctx):
740+
log.info("Querying spec file for rpm versions") # XXX: DEBUG
741+
rpmquery_args = [
742+
"rpm", "--qf", "%{version}-%{release}\n", "--specfile", "ceph.spec"
743+
]
744+
rpmquery_cmd = ' '.join(shlex.quote(cmd) for cmd in rpmquery_args)
745+
cmd = _container_cmd(
746+
ctx,
747+
[
748+
"bash",
749+
"-c",
750+
f"cd {ctx.cli.homedir} && {rpmquery_cmd}",
751+
],
752+
)
753+
res = _run(cmd, check=False, capture_output=True)
754+
if res.returncode != 0:
755+
log.warning("Failed to list rpm versions")
756+
return None
757+
versions = set(l.strip() for l in res.stdout.decode().splitlines())
758+
if len(versions) > 1:
759+
raise RuntimeError("too many versions in rpm query")
760+
version = list(versions)[0]
761+
filename = f'ceph-{version}.src.rpm'
762+
# lazily reuse the glob match function to detect file presence even tho
763+
# it's not got any wildcard chars
764+
return _find_srpm_glob(ctx, filename)
765+
766+
767+
@Builder.set(Steps.FIND_SRPM)
768+
def bc_find_srpm(ctx):
769+
"""Find the current/matching Source RPM."""
770+
# side effects ctx setting current_srpm to a string when match is found.
771+
if ctx.cli.srpm_match == 'any':
772+
ctx.current_srpm = _find_srpm_glob(ctx, "ceph*.src.rpm")
773+
elif ctx.cli.srpm_match == 'versionglob':
774+
# in theory we could probably drop this method now that
775+
# _find_srpm_by_rpm_query exists, but this is retained in case I missed
776+
# something and that this is noticeably faster since it doesn't need to
777+
# start a container
728778
if not ctx.cli.ceph_version:
729779
head_sha = _git_current_sha(ctx)
730780
srpm_glob = f"ceph*.g{head_sha}.*.src.rpm"
@@ -740,22 +790,24 @@ def bc_build_rpm(ctx):
740790
ctx.cli.ceph_version
741791
)
742792
srpm_glob = f"ceph-{srpm_version}.*.src.rpm"
743-
paths = _glob_search(ctx, srpm_glob)
744-
if len(paths) > 1:
745-
raise RuntimeError(
746-
"too many matching source rpms"
747-
f" (rename or remove unwanted files matching {srpm_glob} in the"
748-
" ceph dir and try again)"
749-
)
750-
if not paths:
793+
ctx.current_srpm = _find_srpm_glob(ctx, srpm_glob)
794+
else:
795+
ctx.current_srpm = _find_srpm_by_rpm_query(ctx)
796+
if ctx.current_srpm:
797+
log.info("Found SRPM: %s", ctx.current_srpm)
798+
799+
800+
@Builder.set(Steps.RPM)
801+
def bc_build_rpm(ctx):
802+
"""Build RPMs from SRPM."""
803+
ctx.build.wants(Steps.FIND_SRPM, ctx, force=True)
804+
if not ctx.current_srpm:
751805
# no matches. build a new srpm
752806
ctx.build.wants(Steps.SOURCE_RPM, ctx)
753-
paths = _glob_search(ctx, srpm_glob)
754-
if not paths:
755-
raise RuntimeError(
756-
f"unable to find source rpm(s) matching {srpm_glob}"
757-
)
758-
srpm_path = pathlib.Path(ctx.cli.homedir) / paths[0]
807+
ctx.build.wants(Steps.FIND_SRPM, ctx, force=True)
808+
if not ctx.current_srpm:
809+
raise RuntimeError("unable to find source rpm(s)")
810+
srpm_path = pathlib.Path(ctx.cli.homedir) / ctx.current_srpm
759811
topdir = pathlib.Path(ctx.cli.homedir) / "rpmbuild"
760812
if ctx.cli.build_dir:
761813
topdir = (
@@ -991,11 +1043,25 @@ def parse_cli(build_step_names):
9911043
)
9921044
parser.add_argument(
9931045
"--rpm-no-match-sha",
994-
dest="rpm_match_sha",
995-
action="store_false",
1046+
dest="srpm_match",
1047+
action="store_const",
1048+
const='any',
9961049
help=(
9971050
"Do not try to build RPM packages that match the SHA of the current"
9981051
" git checkout. Use any source RPM available."
1052+
" [DEPRECATED] Use --rpm-match=any"
1053+
),
1054+
)
1055+
parser.add_argument(
1056+
"--srpm-match",
1057+
dest="srpm_match",
1058+
choices=("any", "versionglob", "auto"),
1059+
default="auto",
1060+
help=(
1061+
"Method used to detect what Source RPM (SRPM) to build:"
1062+
" 'any' looks for any ceph source rpms."
1063+
" 'versionglob' uses a glob matching against version/git id."
1064+
" 'auto' (the default) uses a version derived from ceph.spec."
9991065
),
10001066
)
10011067
parser.add_argument(

0 commit comments

Comments
 (0)