From 7944387b4bbcfe19a5cdb2dd6cb600dbf92c825b Mon Sep 17 00:00:00 2001 From: Daniel Hilst <392820+dhilst@users.noreply.github.com> Date: Thu, 13 Aug 2026 10:08:33 -0300 Subject: [PATCH] fix(xcat-dep): verify gate must detect a NATIVE-arch build, not a non-empty index The prior commit scoped the apt verify gate to '--arch floor UNION present arches', but detected presence with a non-empty binary-/Packages. That is wrong: every binary- index carries the Architecture:all debs (grub2-xcat, genesis), so a BUILD_PPC=false run has a non-empty binary-ppc64el index built purely from arch:all debs -- and the gate would still demand the native ppc compiled deps (ipmitool-xcat, conserver-xcat, goconserver) it never built, the exact false-fail the change was meant to remove. Detect a genuine per-arch build via a new pure helper index_has_native_arch(), which is true only when the index has a stanza with Architecture == that arch (not merely Architecture:all). Unit-tested happy + the arch:all-only sad case. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com> --- BuildUtils.pm | 16 ++++++++++++++++ sbuild-all.pl | 11 ++++++++++- t/sbuild-all.t | 21 +++++++++++++++++++++ 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/BuildUtils.pm b/BuildUtils.pm index 7e34e67..9963167 100644 --- a/BuildUtils.pm +++ b/BuildUtils.pm @@ -25,6 +25,7 @@ our @EXPORT_OK = qw( sh_quote print_step version_matches required_pkgs read_manifest standard_options verify_repo_packages verify_repo_signature parse_packages_index resolve_present_names + index_has_native_arch codename_to_version version_to_codename known_codenames chroot_name chroot_sources_list control_field genesis_deb_control @@ -223,6 +224,21 @@ sub parse_packages_index { return \%map; } +# index_has_native_arch($packages_text, $arch): true iff the Packages index has at least one stanza +# built FOR that arch (Architecture: ), as opposed to only Architecture:all debs (grub2-xcat, +# genesis) which EVERY binary- index carries. This lets the verify gate distinguish "this arch +# was actually built" from "this arch's index merely inherited the arch:all debs" -- so a genuine +# single-arch run (BUILD_PPC=false: amd64 natives + arch:all only) is not mistaken for a two-arch +# repo and made to demand native ppc deps it never built. Pure: text in, boolean out. +sub index_has_native_arch { + my ($text, $arch) = @_; + return 0 unless defined $text && defined $arch && $arch ne ''; + for my $stanza (split /\n\n+/, $text) { + return 1 if $stanza =~ /^Architecture:[ \t]*\Q$arch\E[ \t]*$/m; + } + return 0; +} + # resolve_present_names(\%parsed, $arch, \@names) -> \%present (name => upstream version | undef) # PURE. Resolves each manifest package NAME to the version actually in the parsed index (\%parsed from # parse_packages_index), reducing to the upstream version so it compares against the manifest's diff --git a/sbuild-all.pl b/sbuild-all.pl index eea59aa..c040f06 100755 --- a/sbuild-all.pl +++ b/sbuild-all.pl @@ -38,6 +38,7 @@ use FindBin qw($RealBin); use lib $RealBin; use BuildUtils qw(sh_quote print_step version_matches required_pkgs read_manifest standard_options verify_repo_packages verify_repo_signature parse_packages_index resolve_present_names + index_has_native_arch codename_to_version known_codenames chroot_name chroot_sources_list control_field genesis_deb_control deb_field deb_version deb_upstream_version deb_hash cross_copy_genesis_deb); @@ -651,8 +652,16 @@ sub verify_assembled_repo { # carries, while a genuinely single-arch run (e.g. BUILD_PPC=false, amd64 only) never # false-fails demanding an arch it did not build. my %want = map { $_ => 1 } @{ $arches || [] }; + # Add an arch iff it published NATIVE debs (a Packages stanza with Architecture == that arch), + # NOT merely a non-empty index: every binary-/Packages carries the Architecture:all debs + # (grub2-xcat, genesis), so a non-empty ppc index does NOT imply ppc was built. Native-arch + # detection keeps a genuine single-arch run (BUILD_PPC=false) from demanding the ppc section. for my $a (qw(amd64 ppc64el)) { - $want{$a} = 1 if -s "$adir/dists/$cn/main/binary-$a/Packages"; + my $idx = "$adir/dists/$cn/main/binary-$a/Packages"; + next unless -f $idx; + open my $ifh, '<', $idx or next; + local $/; my $body = <$ifh>; close $ifh; + $want{$a} = 1 if index_has_native_arch($body, $a); } # completeness: manifest (source of truth) vs the PUBLISHED index, per codename x arch. for my $a (sort keys %want) { diff --git a/t/sbuild-all.t b/t/sbuild-all.t index 5c6f93e..758d1bb 100644 --- a/t/sbuild-all.t +++ b/t/sbuild-all.t @@ -14,6 +14,7 @@ use File::Path qw(make_path); use File::Basename qw(basename); use BuildUtils qw(required_pkgs version_matches read_manifest standard_options verify_repo_packages verify_repo_signature parse_packages_index resolve_present_names + index_has_native_arch codename_to_version version_to_codename known_codenames chroot_name chroot_sources_list control_field genesis_deb_control @@ -332,4 +333,24 @@ SKIP: { like($prob[0], qr/^MISSING xcat-genesis-base\b/, '... and the gate then reports it MISSING'); } +# ---- index_has_native_arch: PURE "was this arch actually built?" (native deb vs arch:all-only) ---- +# Guards the verify gate against treating an arch:all-only index (grub2-xcat/genesis, which ride into +# EVERY binary-/Packages) as evidence the arch was built -- the BUILD_PPC=false false-fail. +{ + my $native_ppc = "Package: ipmitool-xcat\nVersion: 1.8.18-1\nArchitecture: ppc64el\n\n" + . "Package: grub2-xcat\nVersion: 2.12-1\nArchitecture: all\n"; + ok( index_has_native_arch($native_ppc, 'ppc64el'), 'native ppc64el deb -> ppc64el counts as built'); + ok(!index_has_native_arch($native_ppc, 'amd64'), 'no native amd64 stanza here -> amd64 not built'); + + my $allonly_ppc = "Package: grub2-xcat\nVersion: 2.12-1\nArchitecture: all\n\n" + . "Package: xcat-genesis-base-ppc64el\nVersion: 2.19.0\nArchitecture: all\n"; + ok(!index_has_native_arch($allonly_ppc, 'ppc64el'), + 'arch:all-only index (grub2/genesis) does NOT count ppc64el as built (BUILD_PPC=false shape)'); + + ok( index_has_native_arch("Package: x\nVersion: 1\nArchitecture: amd64\n", 'amd64'), + 'native amd64 deb -> amd64 counts as built'); + ok(!index_has_native_arch('', 'amd64'), 'empty index text -> not built'); + ok(!index_has_native_arch(undef, 'amd64'), 'undef index text -> not built (no crash)'); +} + done_testing;