mirror of
https://github.com/xcat2/xcat-dep.git
synced 2026-09-12 04:26:25 +00:00
feat(xcat-dep): gate the shared Genesis pool on a manifest section of its own
Every package in a suite pool is gated against debs-manifest.conf, but the OpenEmbedded Genesis release is published into pool/main/xcat-genesis-openembedded -- one pool every suite indexes, described by no [<codename>-<arch>] section. So nothing asserted the published pool was complete: its packages were checked only as they were copied, against the release checksums, and a pool that lost one afterwards would publish quietly. [shared] describes that pool -- all seven architectures, pinned '2.*' like xcat-genesis-base, because they are built FROM xcat-core and their version walks with it. A glob rather than an EVR floor: pins in this manifest are exact-or-glob (version_matches), and the '>= epoch:version-release' form is an EL-side feature of packages-manifest.conf. verify_shared_pool runs on the side tree before the swap, so an incomplete pool is never published. [shared] is not a build target, so the manifest now has two kinds of section. No code iterates sections blindly, but t/sbuild-all.t did -- twice -- so it now selects <codename>-<arch> sections and asserts the shared-pool section is not treated as a target. The consumer fixtures carry the shipped [shared] section verbatim: publishing a release against a manifest that lacks it is refused, not silently ungated. Verified the gate fails when removed, and when [shared] and the pool disagree. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
This commit is contained in:
@@ -136,3 +136,22 @@ grub2-xcat=2.12-1
|
||||
elilo-xcat=3.14-6
|
||||
xnba-undi=1.21.1-1
|
||||
xcat-genesis-base=2.*
|
||||
|
||||
# [shared] is NOT a build target. It describes the ONE pool the OpenEmbedded Genesis release is
|
||||
# published into (pool/main/xcat-genesis-openembedded), which every suite indexes and which no
|
||||
# [<codename>-<arch>] section covers. Without it nothing asserted the published pool was COMPLETE:
|
||||
# its packages were checked only as they were copied, against the release checksums, so a pool that
|
||||
# lost one afterwards would publish quietly.
|
||||
#
|
||||
# The pin tracks the paired xcat-core, like xcat-genesis-base ('2.*'): these are built FROM
|
||||
# xcat-core, so the version walks with it. A glob, not an EVR floor -- pins in THIS manifest are
|
||||
# exact-or-glob (version_matches); the '>= epoch:version-release' form is an EL-side feature of
|
||||
# packages-manifest.conf. The deb names carry the architecture with '_' folded to '-'.
|
||||
[shared]
|
||||
xcat-genesis-openembedded-x86=2.*
|
||||
xcat-genesis-openembedded-x86-64=2.*
|
||||
xcat-genesis-openembedded-ppc64=2.*
|
||||
xcat-genesis-openembedded-ppc64le=2.*
|
||||
xcat-genesis-openembedded-armv7hf=2.*
|
||||
xcat-genesis-openembedded-aarch64=2.*
|
||||
xcat-genesis-openembedded-riscv64=2.*
|
||||
|
||||
@@ -1019,9 +1019,31 @@ sub install_genesis_release_debs {
|
||||
or die "FATAL: cannot set mode on $pool/$base: $!\n";
|
||||
XCAT::GenesisRelease::verify_release_file($genesis_release_checksums, $relative, "$pool/$base");
|
||||
}
|
||||
verify_shared_pool($pool);
|
||||
return scalar(@files);
|
||||
}
|
||||
|
||||
# verify_shared_pool($pool): assert the shared Genesis pool carries every package the manifest's
|
||||
# [shared] section requires, at a version satisfying its pin. [shared] is not a build target: it
|
||||
# describes the one pool every suite indexes, which no [<codename>-<arch>] section covers. Run on
|
||||
# the SIDE TREE, before it is swapped into place, so an incomplete pool is never published.
|
||||
# Completeness only -- the release checksums cover the bytes.
|
||||
sub verify_shared_pool {
|
||||
my ($pool) = @_;
|
||||
my %req = %{ $MANIFEST{shared} // {} };
|
||||
die "FATAL: no [shared] section in $manifest -- cannot verify the shared Genesis pool\n"
|
||||
if !%req;
|
||||
my @names = sort keys %req;
|
||||
my %present = map { $_ => deb_version($pool, $_) } @names;
|
||||
my @problems = verify_repo_packages(\%req, \%present);
|
||||
if (@problems) {
|
||||
print " - $_\n" for @problems;
|
||||
die "FATAL: shared Genesis pool INCOMPLETE at $pool (" . scalar(@problems) . " problem(s))\n";
|
||||
}
|
||||
print " [verify-repo] shared pool complete: " . scalar(@names) . " packages present\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub assemble_into {
|
||||
my ($dir, $expect) = @_;
|
||||
if ($genesis_release ne '') {
|
||||
|
||||
@@ -74,7 +74,7 @@ SKIP: {
|
||||
}
|
||||
|
||||
SKIP: {
|
||||
skip 'APT repository tools are not installed', 58
|
||||
skip 'APT repository tools are not installed', 59
|
||||
unless $^O eq 'linux'
|
||||
&& command_exists('dpkg-deb')
|
||||
&& command_exists('apt-ftparchive');
|
||||
@@ -279,8 +279,13 @@ sub run_apt_consumer {
|
||||
unless ($manifest) {
|
||||
$manifest = "$args{output}/manifest.conf";
|
||||
make_path($args{output});
|
||||
# plus the shipped [shared] section verbatim: publishing a release gates the shared pool
|
||||
# against it, and a manifest without it is refused rather than silently ungated.
|
||||
my $shipped = read_binary("$repo_root/debs-manifest.conf");
|
||||
my ($shared) = $shipped =~ /^(\[shared\]\n(?:[^\[]*))/ms;
|
||||
BAIL_OUT('debs-manifest.conf has no [shared] section') unless $shared;
|
||||
write_binary($manifest,
|
||||
join('', map { "[$_-amd64]\nxcat-genesis-base=*\n" } @APT_SUITES));
|
||||
join('', map { "[$_-amd64]\nxcat-genesis-base=*\n" } @APT_SUITES) . "\n" . $shared);
|
||||
}
|
||||
return run_capture(
|
||||
$args{log},
|
||||
@@ -370,6 +375,8 @@ sub test_deb_consumer {
|
||||
} architectures();
|
||||
is_deeply([ genesis_deb_names($shared_pool) ], \@expected_packages,
|
||||
'shared APT pool contains one complete Genesis release');
|
||||
like(read_binary($log), qr/\[verify-repo\] shared pool complete: 7 packages present/,
|
||||
'the shared pool is gated against the manifest\'s [shared] section');
|
||||
my @suite_packages;
|
||||
for my $codename (@APT_SUITES) {
|
||||
push(@suite_packages, map { "$codename/$_" }
|
||||
|
||||
+4
-1
@@ -324,8 +324,11 @@ SKIP: {
|
||||
# ---- manifest <-> reality consistency (concern #3 + doc drift guard) -----------------------------
|
||||
{
|
||||
my %m = read_manifest("$RealBin/../debs-manifest.conf");
|
||||
my @targets = sort keys %m;
|
||||
# Not every section is a build target: [shared] describes the ONE pool the OpenEmbedded Genesis
|
||||
# release is published into, which no builder produces. Target sections are <codename>-<arch>.
|
||||
my @targets = grep { /^[a-z]+-(?:amd64|ppc64el)$/ } sort keys %m;
|
||||
cmp_ok(scalar(@targets), '>=', 8, 'manifest has all 8 codename x arch target sections');
|
||||
ok(!grep({ $_ eq 'shared' } @targets), 'the shared-pool section is not treated as a build target');
|
||||
|
||||
# goconserver is a compiled dep built for EVERY target (both arches, all codenames).
|
||||
my @miss_go = grep { !exists $m{$_}{'goconserver'} } @targets;
|
||||
|
||||
Reference in New Issue
Block a user