From fdf18e24c36366b351f282786795bf16a39e9df4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Ferr=C3=A3o?= <2031761+viniciusferrao@users.noreply.github.com> Date: Fri, 9 Oct 2026 15:02:35 -0300 Subject: [PATCH] test(packaging): run the generated Debian repository helper Build a real package and repository, then execute the generated helper with representative host architectures and releases. Check its apt configuration and preserve unrelated sources. --- .github/workflows/xcat_test.yml | 2 +- xCAT-test/native/builddebs_riscv64.t | 69 ++++++++++++++++++++++ xCAT-test/unit/builddebs_riscv64.t | 88 ---------------------------- 3 files changed, 70 insertions(+), 89 deletions(-) create mode 100644 xCAT-test/native/builddebs_riscv64.t delete mode 100644 xCAT-test/unit/builddebs_riscv64.t diff --git a/.github/workflows/xcat_test.yml b/.github/workflows/xcat_test.yml index 8495fcf54..89f910c64 100644 --- a/.github/workflows/xcat_test.yml +++ b/.github/workflows/xcat_test.yml @@ -77,7 +77,7 @@ jobs: run: | log=$(mktemp) trap 'rm -f -- "$log"' EXIT - prove -v xCAT-test/native/install_profile_riscv64.t xCAT-test/native/netboot_profile_riscv64.t | tee "$log" + prove -v xCAT-test/native/install_profile_riscv64.t xCAT-test/native/netboot_profile_riscv64.t xCAT-test/native/builddebs_riscv64.t | tee "$log" ! grep -qi skipped "$log" rpm_lifecycle_test: runs-on: ubuntu-24.04 diff --git a/xCAT-test/native/builddebs_riscv64.t b/xCAT-test/native/builddebs_riscv64.t new file mode 100644 index 000000000..37b1c2ca5 --- /dev/null +++ b/xCAT-test/native/builddebs_riscv64.t @@ -0,0 +1,69 @@ +#!/usr/bin/env perl +use strict; +use warnings; +use File::Path qw(make_path); +use File::Slurper qw(read_text write_text); +use File::Temp qw(tempdir); +use FindBin; +use lib "$FindBin::Bin/../lib"; +use Test::More; +use XCAT::Test::File qw(repo_path); +use XCAT::Test::Process qw(run_command); +use XCAT::Test::Sandbox qw(sandbox_root sandbox_run); + +plan skip_all => 'requires a Debian-family package builder' + unless $^O eq 'linux' && -f '/etc/debian_version'; +require Dpkg::Control::Info; + +my $build = tempdir(CLEANUP => 1); +make_path("$build/source", "$build/home"); +for my $entry (qw(builddebs.pl build-utils Version Release xCAT-buildkit)) { + system('cp', '-a', repo_path($entry), "$build/source/") == 0 or die "Cannot copy $entry"; +} +{ + local %ENV = (%ENV, HOME => "$build/home", SOURCE_DATE_EPOCH => 1750000000, + PATH => '/usr/bin:/bin', LC_ALL => 'C'); + my ($status, $output) = run_command($^X, "$build/source/builddebs.pl", + '--package', 'xCAT-buildkit', '--dist', 'noble', '--release', 'test1', + '--dest', "$build/output"); + is($status, 0, 'the real Debian builder creates a package and repository') or diag($output); + die 'the builder did not complete' if $status; +} +my $repository = "$build/output/xcat-core"; +ok(-x "$repository/mklocalrepo.sh", 'the builder delivers an executable repository helper'); +ok(-f "$repository/dists/noble/Release", 'the helper accompanies a published repository'); + +for my $case (['riscv64', 'riscv64'], ['ppc64le', 'ppc64el'], ['x86_64', 'amd64']) { + my ($machine, $architecture) = @$case; + for my $release (qw(noble jammy)) { + subtest "$machine $release" => sub { + my $root = sandbox_root(); + make_path("$root/etc/apt/sources.list.d"); + write_text("$root/etc/lsb-release", "DISTRIB_CODENAME=$release\n"); + write_text("$root/bin/uname", "#!/bin/sh\n[ \"\$*\" = -m ] || exit 2\nprintf '%s\\n' '$machine'\n"); + chmod 0755, "$root/bin/uname" or die $!; + write_text("$root/etc/apt/sources.list.d/administrator.list", "preserved\n"); + for my $pass (1, 2) { + my ($status, $output) = sandbox_run($root, + {read_only => {$repository => '/repo'}}, '/repo/mklocalrepo.sh'); + is($status, 0, "pass $pass executes the generated helper unchanged") or diag($output); + is(read_text("$root/etc/apt/sources.list.d/xcat-core.list"), + "deb [arch=$architecture] file:///repo $release main\n", + "pass $pass selects the host architecture and distribution"); + is(read_text("$root/etc/apt/sources.list.d/administrator.list"), "preserved\n", + "pass $pass preserves unrelated sources"); + } + }; + } +} + +for my $case (['xCAT', 'xcat'], ['xCATsn', 'xcatsn']) { + my ($component, $package) = @$case; + my $control = Dpkg::Control::Info->new(repo_path("$component/debian/control")); + my ($binary) = grep { $_->{Package} eq $package } $control->get_packages(); + ok($binary, "$package has a binary package stanza"); + my %architecture = map { $_ => 1 } split /\s+/, $binary->{Architecture} // ''; + ok($architecture{$_}, "$package supports $_") for qw(riscv64 amd64 ppc64el); +} + +done_testing(); diff --git a/xCAT-test/unit/builddebs_riscv64.t b/xCAT-test/unit/builddebs_riscv64.t deleted file mode 100644 index 5dc2fc813..000000000 --- a/xCAT-test/unit/builddebs_riscv64.t +++ /dev/null @@ -1,88 +0,0 @@ -#!/usr/bin/env perl -use strict; -use warnings; - -use File::Spec; -use File::Temp qw(tempdir); -use FindBin; -use Test::More; - -# A riscv64 management node needs an xcat and xcatsn deb built for the architecture and a -# mklocalrepo.sh that points the host at the matching repository instead of amd64. -# -# The generated script is extracted from builddebs.pl and run with a stub uname ahead of -# $PATH, so the mapping under test is the shipped code. Only the path it writes is -# redirected into the sandbox, because it writes an apt source list. - -my $repo_root = File::Spec->rel2abs( File::Spec->catdir( $FindBin::Bin, '..', '..' ) ); -my $builder = File::Spec->catfile( $repo_root, 'builddebs.pl' ); -plan skip_all => "builddebs.pl not found" unless -f $builder; - -my $src = do { local $/; open my $fh, '<', $builder or die $!; <$fh> }; - -# BAIL_OUT rather than skip: a rename that stops this matching must fail loudly instead of -# silently covering nothing. -my ($script) = $src =~ /write_script\("\$repodir\/mklocalrepo\.sh", <<'SCRIPT'\);\n(.*?)\nSCRIPT\n/ms; -BAIL_OUT('could not extract mklocalrepo.sh from builddebs.pl') unless defined $script; - -my $dir = tempdir( CLEANUP => 1 ); -my $run = 0; - -# Run the generated script for one host architecture and return the apt source line it wrote. -sub sources_line_for { - my ($uname) = @_; - $run++; - my $root = File::Spec->catdir( $dir, "run$run" ); - mkdir $root; - mkdir "$root/bin"; - - open( my $stub, '>', "$root/bin/uname" ) or die $!; - print {$stub} "#!/bin/bash\necho $uname\n"; - close($stub); - chmod 0755, "$root/bin/uname"; - - my $release = File::Spec->catfile( $root, 'lsb-release' ); - open( my $rel, '>', $release ) or die $!; - print {$rel} "DISTRIB_CODENAME=noble\n"; - close($rel); - - my $listed = File::Spec->catfile( $root, 'sources.list' ); - ( my $sandboxed = $script ) =~ s{/etc/lsb-release}{$release}; - $sandboxed =~ s{/etc/apt/sources\.list\.d/\S+}{$listed}; - - my $harness = File::Spec->catfile( $root, 'harness.sh' ); - open( my $fh, '>', $harness ) or die $!; - print {$fh} "#!/bin/bash\n$sandboxed\n"; - close($fh); - - local $ENV{PATH} = "$root/bin:$ENV{PATH}"; - system( '/bin/bash', $harness ); - open( my $out, '<', $listed ) or die $!; - my $line = do { local $/; <$out> }; - close($out); - return $line; -} - -for my $case ( - [ 'riscv64', 'riscv64' ], - [ 'ppc64le', 'ppc64el' ], - [ 'x86_64', 'amd64' ], - ) -{ - my ( $uname, $want ) = @$case; - like( sources_line_for($uname), qr/^deb \[arch=\Q$want\E\] /, - "mklocalrepo.sh gives a $uname host the $want repository" ); -} - -# The debs themselves must exist for the architecture. -for my $case ( [ 'xCAT', 'xcat' ], [ 'xCATsn', 'xcatsn' ] ) { - my ( $component, $package ) = @$case; - my $control = File::Spec->catfile( $repo_root, $component, 'debian', 'control' ); - my $text = do { local $/; open my $fh, '<', $control or die $!; <$fh> }; - my ($arches) = $text =~ /^Package: \Q$package\E\nArchitecture: (.*)$/m; - ok( defined $arches, "$package declares an architecture" ); - like( $arches || '', qr/\briscv64\b/, "$package is built for riscv64" ); - like( $arches || '', qr/\bamd64\b.*\bppc64el\b/, "$package keeps amd64 and ppc64el" ); -} - -done_testing();