mirror of
https://github.com/xcat2/xcat-core.git
synced 2026-09-04 20:17:55 +00:00
bd9c155f1a
buildrpms.pl is what actually builds xcat-core now: every core CD pipeline calls
it (ci/{el,suse,ubuntu}/Jenkinsfile.core-*), and it reaches none of these
scripts. What is left of them is a second, diverging build path that nothing
runs -- buildcore.sh has no caller at all (its one mention in
Jenkinsfile.core-el-stable is a comment), makerpm's only caller is
buildlocal.sh, and buildlocal.sh has no caller.
That divergence broke master. #7774 added a source-only mode to these scripts
rather than to buildrpms.pl, giving makerpm an unguarded
. "$(dirname "$0")/build-utils/source-only.sh"
at line 13, used on every build path (xcat_configure_rpm_build_mode,
xcat_announce_build), not only under SRCONLY. apache_config_sources.t stages
makerpm into a fixture that creates build-utils/ but copies only
sync-xcat-apache-configs into it, so makerpm died at line 13 and nothing reached
SOURCES/. Because prove -r xCAT-test/unit runs the whole suite, that reddened
xcat_pr_test on every open PR. It merged on a green run from 2026-08-27;
apache_config_sources.t landed 2026-08-30, and nothing rebuilt it in between.
Removed: makerpm, buildcore.sh, buildlocal.sh, build-utils/source-only.sh,
build-utils/buildcore-source-only.sh, and the tests that covered only them
(makerpm_source_only.t, buildcore_source_only.t). The makerpm half of
apache_config_sources.t goes with makerpm; its sync-xcat-apache-configs half
stays, because buildrpms.pl invokes that helper directly. The source-only
capability is preserved as buildrpms.pl --source-only, in the preceding commit.
build-ubunturepo is deliberately NOT touched. It is not a legacy script: both
Ubuntu core CD pipelines invoke it, github_action_xcat_test.pl:325 invokes it on
every PR, and it was last fixed this week. buildrpms.pl is RPM-only -- mock and
createrepo_c, no dpkg path -- so there is nothing to migrate it to. Giving
Debian builds an equivalent modern builder is separate work.
Verified: prove -r xCAT-test/unit before and after differs by exactly one file
-- apache_config_sources.t fails on upstream/master (4a0d9e0bb, tests 64-65) and
passes here. The other six failures are identical on both and are missing DB
modules on the machine that ran it. No remaining reference to any removed file
except the one comment in buildrpms.pl naming where its templates came from.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
245 lines
11 KiB
Perl
245 lines
11 KiB
Perl
#!/usr/bin/env perl
|
|
use strict;
|
|
use warnings;
|
|
|
|
use File::Copy qw(copy);
|
|
use File::Path qw(make_path);
|
|
use File::Slurper qw(read_text write_text);
|
|
use File::Spec;
|
|
use File::Temp qw(tempdir);
|
|
use FindBin;
|
|
use Fcntl qw(S_IMODE);
|
|
use lib "$FindBin::Bin/../lib";
|
|
use Test::More;
|
|
|
|
use XCAT::Test::File qw(repo_path slurp_repo_file);
|
|
|
|
my $sync_helper = repo_path('build-utils/sync-xcat-apache-configs');
|
|
ok( -x $sync_helper, 'the Apache configuration sync helper is executable' );
|
|
is( system( 'sh', '-n', $sync_helper ), 0,
|
|
'the Apache configuration sync helper has POSIX shell syntax' );
|
|
|
|
my ( $status, $output ) = run_command( {}, $sync_helper, '--check' );
|
|
is( $status, 0, 'the committed service-node configurations are current' )
|
|
or diag($output);
|
|
is( $output, '', 'a successful repository check is quiet' );
|
|
|
|
my @config_pairs = (
|
|
[ 'xCAT/xcat.conf', 'xCATsn/xcat.conf' ],
|
|
[ 'xCAT/xcat.conf.apach24', 'xCATsn/xcat.conf.apach24' ],
|
|
);
|
|
for my $pair (@config_pairs) {
|
|
my ( $source, $generated ) = @{$pair};
|
|
my $generated_path = repo_path($generated);
|
|
ok( !-l $generated_path, "$generated is a regular tracked file" );
|
|
is( slurp_repo_file($generated), slurp_repo_file($source),
|
|
"$generated is generated byte-for-byte from $source" );
|
|
is( sprintf( '%04o', S_IMODE( ( stat($generated_path) )[2] ) ), '0644',
|
|
"$generated has the required tracked mode" );
|
|
}
|
|
|
|
my $fixture_root = tempdir( CLEANUP => 1 );
|
|
my $fixture_helper = stage_sync_fixture($fixture_root);
|
|
write_text( File::Spec->catfile( $fixture_root, 'xCAT', 'xcat.conf' ),
|
|
"apache22 canonical\n" );
|
|
write_text( File::Spec->catfile( $fixture_root, 'xCAT', 'xcat.conf.apach24' ),
|
|
"apache24 canonical\n" );
|
|
write_text( File::Spec->catfile( $fixture_root, 'xCATsn', 'xcat.conf' ),
|
|
"apache22 stale\n" );
|
|
write_text( File::Spec->catfile( $fixture_root, 'xCATsn', 'xcat.conf.apach24' ),
|
|
"apache24 stale\n\n" );
|
|
|
|
( $status, $output ) = run_command( {}, $fixture_helper, '--check' );
|
|
is( $status, 1, '--check rejects drift in generated configurations' );
|
|
like( $output, qr{^xCATsn/xcat\.conf is out of date;}m,
|
|
'--check identifies the stale Apache 2.2 copy' );
|
|
like( $output, qr{^xCATsn/xcat\.conf\.apach24 is out of date;}m,
|
|
'--check identifies the stale Apache 2.4 copy' );
|
|
|
|
( $status, $output ) = run_command( {}, $fixture_helper, '--write' );
|
|
is( $status, 0, '--write refreshes generated configurations' )
|
|
or diag($output);
|
|
like( $output, qr{^updated xCATsn/xcat\.conf$}m,
|
|
'--write reports the refreshed Apache 2.2 copy' );
|
|
like( $output, qr{^updated xCATsn/xcat\.conf\.apach24$}m,
|
|
'--write reports the refreshed Apache 2.4 copy' );
|
|
|
|
for my $pair (@config_pairs) {
|
|
my ( $source, $generated ) = @{$pair};
|
|
my $source_path = File::Spec->catfile( $fixture_root, split( '/', $source ) );
|
|
my $generated_path =
|
|
File::Spec->catfile( $fixture_root, split( '/', $generated ) );
|
|
is( read_text($generated_path), read_text($source_path),
|
|
"--write makes $generated byte-identical to its canonical source" );
|
|
is( sprintf( '%04o', S_IMODE( ( stat($generated_path) )[2] ) ), '0644',
|
|
"--write gives $generated a deterministic file mode" );
|
|
}
|
|
|
|
( $status, $output ) = run_command( {}, $fixture_helper, '--write' );
|
|
is( $status, 0, '--write accepts already-current configurations' );
|
|
is( $output, '', '--write does not rewrite or report current configurations' );
|
|
my $current_generated =
|
|
File::Spec->catfile( $fixture_root, 'xCATsn', 'xcat.conf' );
|
|
chmod 0600, $current_generated
|
|
or die "Unable to change $current_generated mode: $!";
|
|
( $status, $output ) = run_command( {}, $fixture_helper, '--check' );
|
|
is( $status, 1, '--check rejects mode drift in generated configurations' );
|
|
like( $output, qr{^xCATsn/xcat\.conf is out of date;}m,
|
|
'--check identifies the generated configuration with mode drift' );
|
|
( $status, $output ) = run_command( {}, $fixture_helper, '--write' );
|
|
is( $status, 0, '--write repairs mode drift on current configurations' );
|
|
is( sprintf( '%04o', S_IMODE( ( stat($current_generated) )[2] ) ), '0644',
|
|
'--write normalizes a current generated configuration to mode 0644' );
|
|
is( $output, '', 'mode-only repair does not report a content update' );
|
|
|
|
my $symlink_victim = File::Spec->catfile( $fixture_root, 'symlink-victim' );
|
|
write_text( $symlink_victim, "apache22 canonical\n" );
|
|
unlink($current_generated) or die "Unable to remove $current_generated: $!";
|
|
symlink( $symlink_victim, $current_generated )
|
|
or die "Unable to create $current_generated symlink: $!";
|
|
( $status, $output ) = run_command( {}, $fixture_helper, '--check' );
|
|
is( $status, 1, '--check rejects a generated configuration symlink' );
|
|
like( $output, qr{^xCATsn/xcat\.conf is out of date;}m,
|
|
'--check identifies the generated configuration symlink' );
|
|
( $status, $output ) = run_command( {}, $fixture_helper, '--write' );
|
|
is( $status, 0, '--write replaces a generated configuration symlink' );
|
|
ok( !-l $current_generated,
|
|
'--write leaves a regular generated configuration behind' );
|
|
is( read_text($current_generated), "apache22 canonical\n",
|
|
'--write restores canonical content after replacing a symlink' );
|
|
is( read_text($symlink_victim), "apache22 canonical\n",
|
|
'--write does not modify the former symlink target' );
|
|
|
|
my $missing_generated =
|
|
File::Spec->catfile( $fixture_root, 'xCATsn', 'xcat.conf.apach24' );
|
|
unlink($missing_generated) or die "Unable to remove $missing_generated: $!";
|
|
( $status, $output ) = run_command( {}, $fixture_helper, '--check' );
|
|
is( $status, 1, '--check rejects a missing generated configuration' );
|
|
like( $output, qr{^xCATsn/xcat\.conf\.apach24 is out of date;}m,
|
|
'--check identifies the missing generated configuration' );
|
|
( $status, $output ) = run_command( {}, $fixture_helper, '--write' );
|
|
is( $status, 0, '--write recreates a missing generated configuration' )
|
|
or diag($output);
|
|
is( read_text($missing_generated), "apache24 canonical\n",
|
|
'--write preserves the canonical final newline exactly' );
|
|
is( sprintf( '%04o', S_IMODE( ( stat($missing_generated) )[2] ) ), '0644',
|
|
'--write recreates a generated configuration with mode 0644' );
|
|
|
|
my $staging_directory = tempdir( CLEANUP => 1 );
|
|
my $staging_victim = File::Spec->catfile( $fixture_root, 'staging-victim' );
|
|
write_text( $staging_victim, "do not overwrite\n" );
|
|
symlink( $staging_victim,
|
|
File::Spec->catfile( $staging_directory, 'xcat.conf' ) )
|
|
or die 'Unable to create staging symlink fixture';
|
|
( $status, $output ) =
|
|
run_command( {}, $fixture_helper, '--stage', $staging_directory );
|
|
is( $status, 0, '--stage copies canonical configurations for package builds' )
|
|
or diag($output);
|
|
is( $output, '', 'successful package staging is quiet' );
|
|
for my $name ( 'xcat.conf', 'xcat.conf.apach24' ) {
|
|
my $staged = File::Spec->catfile( $staging_directory, $name );
|
|
my $canonical = File::Spec->catfile( $fixture_root, 'xCAT', $name );
|
|
ok( !-l $staged, "--stage creates a regular $name file" );
|
|
is( read_text($staged), read_text($canonical),
|
|
"--stage copies canonical $name content" );
|
|
is( sprintf( '%04o', S_IMODE( ( stat($staged) )[2] ) ), '0644',
|
|
"--stage gives $name the required package mode" );
|
|
}
|
|
is( read_text($staging_victim), "do not overwrite\n",
|
|
'--stage replaces a destination symlink without touching its target' );
|
|
|
|
my $directory_target = File::Spec->catfile( $staging_directory, 'xcat.conf' );
|
|
unlink($directory_target) or die "Unable to remove $directory_target: $!";
|
|
mkdir($directory_target) or die "Unable to create $directory_target: $!";
|
|
( $status, $output ) =
|
|
run_command( {}, $fixture_helper, '--stage', $staging_directory );
|
|
is( $status, 1, '--stage refuses to replace a destination directory' );
|
|
like( $output, qr{ cannot replace a directory$}m,
|
|
'--stage identifies the destination directory' );
|
|
rmdir($directory_target) or die "Unable to remove $directory_target: $!";
|
|
|
|
my $canonical_path = File::Spec->catfile( $fixture_root, 'xCAT', 'xcat.conf' );
|
|
my $canonical_contents = read_text($canonical_path);
|
|
my $canonical_symlink_target =
|
|
File::Spec->catfile( $fixture_root, 'canonical-symlink-target' );
|
|
write_text( $canonical_symlink_target, $canonical_contents );
|
|
unlink($canonical_path) or die "Unable to remove $canonical_path: $!";
|
|
symlink( $canonical_symlink_target, $canonical_path )
|
|
or die "Unable to create $canonical_path symlink: $!";
|
|
( $status, $output ) = run_command( {}, $fixture_helper, '--check' );
|
|
is( $status, 1, '--check rejects a canonical configuration symlink' );
|
|
like( $output, qr{^xCAT/xcat\.conf must be a regular file$}m,
|
|
'--check identifies the canonical configuration symlink' );
|
|
unlink($canonical_path) or die "Unable to remove $canonical_path: $!";
|
|
write_text( $canonical_path, $canonical_contents );
|
|
|
|
for my $arguments (
|
|
[], ['--invalid'], [ '--check', '--write' ], ['--stage'],
|
|
[ '--stage', $staging_directory, 'extra' ]
|
|
)
|
|
{
|
|
( $status, $output ) = run_command( {}, $fixture_helper, @{$arguments} );
|
|
is( $status, 2, 'invalid invocation exits with usage status 2' );
|
|
like( $output,
|
|
qr{^Usage: sync-xcat-apache-configs --check\|--write\|--stage DIRECTORY$}m,
|
|
'invalid invocation prints concise usage' );
|
|
}
|
|
( $status, $output ) = run_command( {}, $fixture_helper, '--stage',
|
|
File::Spec->catdir( $fixture_root, 'missing-stage-directory' ) );
|
|
is( $status, 1, '--stage rejects a missing destination directory' );
|
|
like( $output, qr{ is not a directory$}m,
|
|
'--stage identifies the invalid destination directory' );
|
|
|
|
# The legacy `makerpm` half of this file went with makerpm itself; buildrpms.pl
|
|
# invokes build-utils/sync-xcat-apache-configs directly, and the helper's own
|
|
# behaviour is covered above.
|
|
|
|
my $management_debian = slurp_repo_file('xCAT/debian/install');
|
|
my $service_debian = slurp_repo_file('xCATsn/debian/install');
|
|
for my $manifest (
|
|
[ 'management', $management_debian ],
|
|
[ 'service-node', $service_debian ],
|
|
) {
|
|
my ( $label, $contents ) = @{$manifest};
|
|
like( $contents, qr{^xcat\.conf\s+etc/apache2/(?:conf\.d|conf-available)/?\s*$}m,
|
|
"$label Debian payload includes the Apache 2.2 configuration" );
|
|
like( $contents, qr{^xcat\.conf\.apach24\s+etc/apache2/(?:conf\.d|conf-available)/?\s*$}m,
|
|
"$label Debian payload includes the Apache 2.4 configuration" );
|
|
}
|
|
|
|
done_testing();
|
|
|
|
sub stage_sync_fixture {
|
|
my ($root) = @_;
|
|
make_path(
|
|
File::Spec->catdir( $root, 'build-utils' ),
|
|
File::Spec->catdir( $root, 'xCAT' ),
|
|
File::Spec->catdir( $root, 'xCATsn' ),
|
|
);
|
|
my $destination =
|
|
File::Spec->catfile( $root, 'build-utils', 'sync-xcat-apache-configs' );
|
|
copy( $sync_helper, $destination )
|
|
or die "Unable to stage the Apache configuration sync helper: $!";
|
|
chmod 0755, $destination
|
|
or die "Unable to make the staged sync helper executable: $!";
|
|
return $destination;
|
|
}
|
|
|
|
|
|
|
|
sub run_command {
|
|
my ( $environment, @command ) = @_;
|
|
my $pid = open( my $pipe, '-|' );
|
|
die "Unable to fork for @command: $!" unless defined($pid);
|
|
if ( $pid == 0 ) {
|
|
@ENV{ keys %{$environment} } = values %{$environment};
|
|
open( STDERR, '>&', STDOUT ) or die "Unable to merge stderr: $!";
|
|
exec { $command[0] } @command;
|
|
die "Unable to execute @command: $!";
|
|
}
|
|
|
|
my $command_output = do { local $/; <$pipe> } // '';
|
|
close($pipe);
|
|
return ( $? >> 8, $command_output );
|
|
}
|