Reviewed by @viniciusferrao. Each numbered point below is his; the code changes verify + fix it.
1. --build-number over-reach / dry-run / double-stamp
- The bump now runs ONLY on a real build: `--dry-run --build-number N` prints what it would
stamp and writes nothing (previously it rewrote every spec on disk during a dry run).
- Re-stamping is idempotent AND replacing: a re-run in a reused tree with a different
--build-number strips the prior .snap<ts>.<n> before applying the new one, instead of
accumulating a second stamp (…snap57.snap58). Extracted the per-line logic into the
unit-testable MockBuildUtils::restamp_release_line and covered it in t/mockbuild-all.t.
(The headline "rewrites xcat-core / xCAT-genesis-base.spec" does not occur in the real layout:
xcat-core is a sibling of $repo_root, and there is no genesis spec under the dep tree. The
legacy nested xcat-source-code case remains a non-CD layout; left as a follow-up.)
3. --finalize-xcat-dep idempotency
- cross_copy_genesis compared only SIGMD5 (content), which is blind to signature + index state.
It now also treats a same-content-but-UNSIGNED destination rpm as not-up-to-date (new
rpm_is_signed helper) so a crash between copy and sign heals on re-run.
- finalize_xcat_dep now re-indexes+signs BOTH repos of a touched pair every run, not only when
an rpm was copied, so a crash after copy+sign but before createrepo (rpm on disk, absent from
repomd) also heals.
4. Stale run-state can mask a failed build
- A real build now wipes its per-target $run_root first (run_id is derived from the deterministic
commit time, so re-runs reused the same tree). --skip-build keeps the tree; --dry-run writes nothing.
- mockbuild-perl-packages.pl clears each package's stale status.txt/error.txt BEFORE building, and
the aggregate now treats the child worker's exit code as authoritative: a package is PASS only if
its worker exited 0 AND wrote a PASS this run (a stale PASS in a reused log dir no longer counts).
5. --skip-build can publish the wrong artifacts
- --skip-build now REQUIRES an explicit --target (without it, all three EL targets collected the
same EL-agnostic roots and cross-published them).
- Collection is scoped to this target's own per-target $build_root (the same tree a normal build
populates), not the legacy build-output/list3/list5/list6 dirs.
- The manifest version-pin validation (and the "no manifest section" guard) now also run under
--skip-build, so a collection-only publish is validated exactly like a fresh build.
2. goconserver bypassed the CD bump (minimal fix; hermetic rebuild deferred)
- goconserver/mockbuild.pl gains --release-suffix, appended to its generated `Release: 4.elN`,
and mockbuild-all.pl passes the CD suffix down -- so goconserver's NVR advances per run like
every other dep package (an additive publish is no longer a silent no-op on a frozen NVR).
- Pinned the clone to an immutable upstream commit instead of the moving `master` (0.3.3 is
unreleased -- newest tag is v0.3.2 -- so a SHA pin is required; clone now fetches by ref).
- The host build + `go mod tidy` hermeticity concern is a tracked follow-up, not in this change.
7. Docs
- BUILD.md: --target is a single value, not repeatable; conserver-xcat is built for every target
(not "not required"). POD: --parallel-targets default is 1 = serial, not "auto".
- Added a manifest<->docs consistency test (conserver-xcat present in every target section).
(6, --max-parallel not a true global cap, is a documented nice-to-have and is left as a follow-up.)
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
12 KiB
Build Guide (xcat-dep)
This guide explains how to build, validate, and package the xcat-dep dependency packages
with mockbuild-all.pl — the RPM build orchestrator for EL targets, driven by mock.
The full xCAT core is NOT built here — it is built and published separately by the
xcat-core pipeline. mockbuild-all.pl builds only the dependency packages plus the
OS-dependent xCAT-genesis-base (pulled individually out of the xcat-core source tree).
Purpose
mockbuild-all.pl is the top-level build orchestrator for the xcat-dep RPM repository.
It builds the dependency RPMs and the OS-dependent xCAT-genesis-base, then assembles:
- a binary RPM repo tree with repodata
- an SRPM repo tree with repodata
- one binary repo tarball and one SRPM repo tarball
Historical Context
The deployment flow uses two separate repositories:
xcat-corefor xCAT packages (built by the xcat-core pipeline)xcat-depfor dependency packages (built here)
An earlier iteration of this script also built the full xCAT core into one unified tree
(via a --skip-xcat toggle). That is gone: the core is always built by the xcat-core
pipeline now, and mockbuild-all.pl builds only xcat-dep plus xCAT-genesis-base.
Placeholder Conventions
This guide uses the following placeholders consistently:
<REPO_ROOT>: xcat-dep repository root (example:/root/xcat-dep)<XCAT_SOURCE>: xCAT source root (example:<REPO_ROOT>/xcat-source-code)<ARCH>: output ofuname -m(for example:x86_64,ppc64le)<OS_ID>:IDfield from/etc/os-release(for example:rhel,rocky)<REL>: integer major release fromVERSION_IDin/etc/os-release(for example:10)<TARGET>:<OS_ID>+epel-<REL>-<ARCH><RUN_ID>: build run identifier (auto-generated if omitted)
Build Pipeline Overview
mockbuild-all.pl orchestrates these build components in parallel:
<REPO_ROOT>/elilo/mockbuild.pl<REPO_ROOT>/grub2-xcat/mockbuild.pl<REPO_ROOT>/ipmitool/mockbuild.pl<REPO_ROOT>/syslinux/mockbuild.pl<REPO_ROOT>/goconserver/mockbuild.pl<REPO_ROOT>/conserver/mockbuild.pl<REPO_ROOT>/xnba/mockbuild.pl<REPO_ROOT>/mockbuild-perl-packages.pl<XCAT_SOURCE>/buildrpms.pl— only to build the OS-dependentxCAT-genesis-basepackage (unless--skip-genesisis set); the full xCAT core is built separately by the xcat-core pipeline, not here.
Each build path uses mock for chroot isolation. Top-level steps are parallelized by mockbuild-all.pl, and perl dependency builds are also parallelized internally by mockbuild-perl-packages.pl.
Per-target package manifest
packages-manifest.conf (repo root) declares, per target, exactly which packages are required —
one [<target>] section (matching --target, e.g. [alma+epel-10-x86_64]) of
<package>=<version|*> lines. For each target, mockbuild-all.pl builds only the packages
listed for it; a package absent from a target's section is not built for that target (the per-EL
perl set differs because the OS/EPEL already provides some modules). Note conserver-xcat is not
pulled in by dnf install xCAT (goconserver superseded it), yet it is listed in — and therefore
built for — every target, because some deployments still use it. The lists were derived empirically — on a clean MN of each
(EL, arch), dnf install xCAT from xcat.org latest, and the packages whose from_repo=xcat-dep
are exactly the required set. See the file header for details.
Build failures are not tolerated: any required (manifest) package that fails to build fails the whole run.
mockbuild-all.pl does more than building RPMs. In a default run it performs these stages:
- Optional chroot cleanup (
--scrub-all-chroots) - Parallel build execution — only the target's manifest packages; any failure fails the run
- Post-build chroot scrub — reclaims each build step's mock chroot (unless
--keep-buildroots) - Optional install/smoke checks inside child builders (disabled with
--skip-install) - Binary RPM collection into
repo/<ARCH>/ - Source RPM collection into
repo-src/ createrepo --updateon both repo trees- Tarball creation for both repo trees
- Summary generation (
summary.txt)
Skip and Control Flags
Use these flags to skip specific operations:
--skip-install- Skips install/smoke checks performed by child builder scripts after RPM build.
--skip-genesis- Skips the
xCAT-genesis-basebuild (<XCAT_SOURCE>/buildrpms.pl --package xCAT-genesis-base).
- Skips the
--skip-xcat-dep- Skips non-perl xcat-dep package builders (
elilo,grub2-xcat,ipmitool-xcat,syslinux-xcat,goconserver,conserver-xcat,xnba-undi).
- Skips non-perl xcat-dep package builders (
--skip-perl- Skips
<REPO_ROOT>/mockbuild-perl-packages.pl.
- Skips
--skip-build- Skips all build steps; only runs collection/repo/tarball stages from existing artifact roots.
--skip-createrepo- Skips
createrepo --update.
- Skips
--skip-tarball- Skips tarball creation for both binary and SRPM repos.
--scrub-all-chroots- Runs
mock -r <TARGET> --scrub=allbefore build and collection.
- Runs
--keep-buildroots- Keeps each build step's mock chroot after the build instead of scrubbing it. By default,
after the parallel build phase every step's buildroot (dep packages, the per-package perl
chroots, and
xCAT-genesis-base) is reclaimed withmock -r <CHROOT> --uniqueext <EXT> --scrub=chroot --scrub=bootstrap— a lock-safe scrub (a chroot still held by a concurrent build is refused and skipped). Both the build chroot and its per-uniqueext bootstrap chroot are removed (each build step gets its own bootstrap, so both must go); the shared root cache under/var/cache/mockis kept so rebuilds stay fast. This stops/var/lib/mockfrom growing unbounded across runs. Pass--keep-buildrootsto preserve a buildroot for debugging a failed build.
- Keeps each build step's mock chroot after the build instead of scrubbing it. By default,
after the parallel build phase every step's buildroot (dep packages, the per-package perl
chroots, and
--collect-dir <PATH>- Adds extra artifact roots to the collection phase (repeatable).
--dry-run- Prints planned actions without executing them.
Prerequisites
- Run as
root. mockbuild-all.pland package sources present under<REPO_ROOT>.- xCAT sources present under
<XCAT_SOURCE>.
Install baseline tooling:
dnf -y install perl perl-Parallel-ForkManager mock createrepo tar rpm-build rpmdevtools dnf-plugins-core wget git
If you will build the xCAT-genesis-base package (that is, you will not use --skip-genesis), install xCAT build dependencies:
cd <XCAT_SOURCE>
perl buildrpms.pl --install_deps
Validate mock config availability:
mock -r <TARGET> --print-root-path
Target Resolution
--target is optional.
If --target is omitted, mockbuild-all.pl derives <TARGET> from:
/etc/os-release(ID,VERSION_ID)uname -m
Equivalent derivation:
<TARGET> = <OS_ID>+epel-<REL>-<ARCH>
<TARGET> is also passed to mock as the chroot/config identifier:
mock -r <TARGET> ...
By default (no --target), mockbuild-all.pl builds all three EL releases for the host
arch: rh8, rh9, and rh10. Pass --target <TARGET> to build a single target instead; it
takes one value and is not repeatable — run the script once per target to build several, or
omit it to build all three.
Build the Dependency Repository
mockbuild-all.pl builds the xcat-dep packages (dep packages, perl packages, and the
OS-dependent xCAT-genesis-base). The full xCAT core is not built here — it is built and
published separately by the xcat-core pipeline.
cd /root/xcat-dep
perl ./mockbuild-all.pl \
--repo-root /root/xcat-dep \
--xcat-source /root/xcat-dep/xcat-source-code \
--scrub-all-chroots
Notes:
- Install/smoke checks run by default inside child builders.
- Add
--skip-installto skip those checks. - Add
--skip-genesisto skip thexCAT-genesis-basebuild (the only step that invokes<XCAT_SOURCE>/buildrpms.pl). <RUN_ID>is optional; when omitted it is timestamp-based.
Common Build Modes
xcat-dep repo (with install/smoke checks):
cd <REPO_ROOT>
perl ./mockbuild-all.pl \
--repo-root <REPO_ROOT> \
--xcat-source <XCAT_SOURCE> \
--scrub-all-chroots
xcat-dep repo (skip install/smoke checks):
cd <REPO_ROOT>
perl ./mockbuild-all.pl \
--repo-root <REPO_ROOT> \
--xcat-source <XCAT_SOURCE> \
--scrub-all-chroots \
--skip-install
Dependency repo without the xCAT-genesis-base build:
cd <REPO_ROOT>
perl ./mockbuild-all.pl \
--repo-root <REPO_ROOT> \
--xcat-source <XCAT_SOURCE> \
--scrub-all-chroots \
--skip-genesis \
--skip-install
Collection-only pass from existing build artifacts:
cd <REPO_ROOT>
perl ./mockbuild-all.pl \
--repo-root <REPO_ROOT> \
--xcat-source <XCAT_SOURCE> \
--skip-build
Cross-arch genesis-base (--finalize-xcat-dep)
xCAT-genesis-base is a noarch package whose name carries the target arch
(xCAT-genesis-base-x86_64, xCAT-genesis-base-ppc64 — xCAT collapses ppc64le to ppc64
via tarch; there is no big-endian code in it). A management node must be able to netboot
nodes of the other arch, so — as in 2.17 — the x86_64 dep repo must also ship the
ppc64 genesis and the ppc64le dep repo must ship the x86_64 genesis.
Each arch is built on its own build host, so once both per-arch repos exist, run a final, build-free pass that cross-copies the noarch genesis between them and re-indexes + re-signs the affected repos:
perl ./mockbuild-all.pl --finalize-xcat-dep \
--x86_64-repo <x86_64 repo root holding <os>/x86_64> \
--ppc64le-repo <ppc64le repo root holding <os>/ppc64le> \
--gpg-sign --gpg-key-name "xCAT Signing Key" --gpg-home <GNUPGHOME>
- If both arches were built into one shared tree, pass the same path to both options.
- Idempotent: a repo pair already carrying the fresh foreign-arch genesis is left untouched; any stale foreign-arch genesis is dropped before the fresh one is copied in.
- It builds nothing and holds no output lock — use it alone.
Output Artifacts and Paths
For each run:
- Binary repo path:
<REPO_ROOT>/build-output/mockbuild-all/<RUN_ID>/repo/<ARCH>/
- SRPM repo path:
<REPO_ROOT>/build-output/mockbuild-all/<RUN_ID>/repo-src/
- Run summary:
<REPO_ROOT>/build-output/mockbuild-all/<RUN_ID>/summary.txt
- Binary repo tarball:
<REPO_ROOT>/build-output/mockbuild-all/mockbuild-all-<TARGET>-<RUN_ID>.tar.gz
- SRPM repo tarball:
<REPO_ROOT>/build-output/mockbuild-all/mockbuild-all-<TARGET>-<RUN_ID>-srpm.tar.gz
Architecture Requirements
mockbuild-all.pl derives architecture from the build host:
<ARCH> = $(uname -m)
Because of this, to build ppc64le artifacts you must run mockbuild-all.pl on a Power host where:
uname -mreturnsppc64le- a matching mock config exists for
<TARGET>(for examplerocky+epel-10-ppc64le)
In short: build ppc64le packages on a Power machine.
Validation Commands
cat <REPO_ROOT>/build-output/mockbuild-all/<RUN_ID>/summary.txt
ls -1 <REPO_ROOT>/build-output/mockbuild-all/<RUN_ID>/repo/<ARCH>/
ls -1 <REPO_ROOT>/build-output/mockbuild-all/<RUN_ID>/repo-src/
ls -1 <REPO_ROOT>/build-output/mockbuild-all/mockbuild-all-<TARGET>-<RUN_ID>.tar.gz
ls -1 <REPO_ROOT>/build-output/mockbuild-all/mockbuild-all-<TARGET>-<RUN_ID>-srpm.tar.gz
find <REPO_ROOT>/build-output/mockbuild-all/<RUN_ID>/build-logs -type f | sort
Common Issues
Missing xCAT build script: .../buildrpms.pl- Ensure
<XCAT_SOURCE>points to a valid xCAT source tree.
- Ensure
WARN: missing dep builder script, skipping: ...- Sync the repository; one or more package build scripts are missing.
mock target not found- Validate with
mock -r <TARGET> --print-root-pathand install the required mock config packages.
- Validate with
Tests
The reusable, side-effect-free helpers live in MockBuildUtils.pm (package selection under the
--skip-* flags, version-pin matching incl. globs, RPM-identity comparison, and the cross-arch
genesis finalize logic). Focused fixture tests cover them:
prove t/ # or: perl t/mockbuild-all.t
The RPM-identity / cross_copy_genesis cases build tiny fixture rpms and are skipped
automatically if rpmbuild is unavailable.