From da282043beeba983e08db1e783c97ec4ecc83455 Mon Sep 17 00:00:00 2001 From: Daniel Hilst <392820+dhilst@users.noreply.github.com> Date: Tue, 1 Sep 2026 07:40:31 -0300 Subject: [PATCH] fix(build): run buildrpms.pl in a sandbox and install its fork manager in CI buildrpms_source_only.t's CLI half failed in CI: the runner has no Parallel::ForkManager, so buildrpms.pl aborted at compile time and never reached the option check the test is about. The module is needed only by the test suite -- buildrpms.pl is not a runtime dependency of any package -- so it goes in the workflow apt list. The same half also escaped its scratch tree. Before buildrpms.pl looks at @ARGV it rewrites the tracked Gitinfo in its working directory and creates $HOME/rpmbuild, so running it from the checkout left the tree dirty and reached into the developer's home to exercise argument parsing. It now runs from a staged copy with HOME pointed at the sandbox. Exit 2 is pinned rather than "non-zero", though perl also exits 2 on a compile abort -- which is exactly how this assertion stayed green in CI while the program could not load. The message assertion is what separates the two, and the comment now says so. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com> --- .github/workflows/xcat_test.yml | 2 +- xCAT-test/unit/buildrpms_source_only.t | 24 ++++++++++++++++++++++-- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/.github/workflows/xcat_test.yml b/.github/workflows/xcat_test.yml index b90553a92..92c12244d 100644 --- a/.github/workflows/xcat_test.yml +++ b/.github/workflows/xcat_test.yml @@ -7,7 +7,7 @@ jobs: steps: - uses: actions/checkout@v6 - name: Install dependencies - run: sudo env DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends --no-install-suggests build-essential fakeroot reprepro devscripts debhelper libcapture-tiny-perl libfile-slurper-perl libjson-perl libsoap-lite-perl libdbi-perl libcgi-pm-perl quilt openssh-server dpkg looptools genometools software-properties-common + run: sudo env DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends --no-install-suggests build-essential fakeroot reprepro devscripts debhelper libcapture-tiny-perl libfile-slurper-perl libjson-perl libparallel-forkmanager-perl libsoap-lite-perl libdbi-perl libcgi-pm-perl quilt openssh-server dpkg looptools genometools software-properties-common - name: Run tests run: perl github_action_xcat_test.pl diff --git a/xCAT-test/unit/buildrpms_source_only.t b/xCAT-test/unit/buildrpms_source_only.t index e7a7f42e8..b82f22d9d 100644 --- a/xCAT-test/unit/buildrpms_source_only.t +++ b/xCAT-test/unit/buildrpms_source_only.t @@ -10,6 +10,7 @@ use strict; use warnings; use Cwd qw(getcwd); +use File::Copy (); use File::Slurper qw(read_text); use File::Spec; use File::Temp qw(tempdir); @@ -103,13 +104,32 @@ ok( !grep({ $_ eq 'BINARY' } @{ run_index(source_only => 1) }), # ------------------------------------------------------------------- the CLI -- # Run the real program. --source-only and --merge-core-repos are different modes: # one builds, the other assembles trees that are already built. +# +# Run it from a copy, never from the checkout: before it looks at @ARGV, +# buildrpms.pl rewrites the tracked Gitinfo in its working directory and creates +# $HOME/rpmbuild. Running it in place left the developer's tree dirty and reached +# into their home for a test that only exercises argument parsing. Version is +# staged because the same file-scope code reads it and dies without it. +my $sandbox = tempdir(CLEANUP => 1); +for my $needed (qw(buildrpms.pl Version)) { + my $from = repo_path($needed); + BAIL_OUT("$needed is missing from the repository") unless -r $from; + File::Copy::copy($from, File::Spec->catfile($sandbox, $needed)) + or BAIL_OUT("could not stage $needed: $!"); +} + my $cwd = getcwd(); -chdir repo_path('.') or BAIL_OUT("cannot chdir to the repository root: $!"); +chdir $sandbox or BAIL_OUT("cannot chdir to the sandbox: $!"); +local $ENV{HOME} = $sandbox; my $out = qx($^X buildrpms.pl --source-only --merge-core-repos 2>&1); my $rc = $? >> 8; chdir $cwd; -isnt( $rc, 0, 'combining --source-only with --merge-core-repos is refused' ); +# 2 is usage()'s exit code, but perl also exits 2 when compilation aborts, so the +# status alone does not say the option check ran -- it passed in CI while +# buildrpms.pl could not even load Parallel::ForkManager. The message below is +# what distinguishes the two; this only pins the code usage() is meant to use. +is( $rc, 2, 'combining --source-only with --merge-core-repos is refused' ); like( $out, qr/--source-only and --merge-core-repos/, 'and the refusal names both options' );