2
0
mirror of https://github.com/xcat2/xcat-core.git synced 2026-09-04 20:17:55 +00:00

refactor(build): share the buildinfo stamp between the two builders

Both builders wrote the same six fields beside a published repository --
VERSION, RELEASE, BUILD_TIME, BUILD_MACHINE, COMMIT_ID, COMMIT_ID_LONG -- each
assembling them by hand, and each shelling out to hostname to do it.

builddebs.pl also ran git rev-parse a second time to get the commit, although
it had already derived the same value into $GITINFO earlier in the file. It now
uses that.

The filenames and the time formats stay as they were. deploy.sh copies
builddebs.pl's buildinfo verbatim and cluster-test.pl parses buildrpms.pl's
buildinfo.txt, so both are a contract with consumers outside this repository;
the shared helper takes the format from its caller rather than picking one.
Confirmed byte for byte that each builder's stamp is unchanged.

Covered by tests: the field names and their order, the seven-character short
commit, and that the two callers' formats still differ.

Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
This commit is contained in:
Daniel Hilst
2026-09-01 16:34:11 -03:00
parent da80f51112
commit a5f670a4cc
4 changed files with 55 additions and 24 deletions
+22
View File
@@ -33,6 +33,7 @@ our @EXPORT_OK = qw(
backup_file restore_file
sh usage
read_file write_file rewrite_file
buildinfo_text
);
# Both builders echo the commands they run under --verbose. Set once, after
@@ -42,6 +43,27 @@ our $VERBOSE = 0;
# The xCAT-probe helpers. xcat-probe reuses functions shipped by xCAT; they are COPIED
# rather than symlinked because a symlink does not survive packaging, and rather than
# maintained twice because they would drift. Both builders stage them the same way.
# The stamp both builders write beside a published repository. deploy.sh copies
# the file verbatim and cluster-test.pl parses it, so the field names and their
# order are a contract; each builder passes its own time format and writes to
# its own filename, which are part of that contract too.
sub buildinfo_text {
my (%args) = @_;
my $commit = $args{commit} // 'unknown';
my $host = $args{host};
unless (defined $host) {
$host = `hostname 2>/dev/null` || 'unknown';
chomp $host;
}
return join('', map { "$_\n" }
"VERSION=$args{version}",
"RELEASE=$args{release}",
"BUILD_TIME=" . strftime($args{time_format}, gmtime($args{epoch})),
"BUILD_MACHINE=$host",
"COMMIT_ID=" . substr($commit, 0, 7),
"COMMIT_ID_LONG=$commit");
}
# Whole-file read and write. Deliberately plain open/close rather than
# File::Slurper, so that loading this module does not oblige a deb build to
# install a module it otherwise does not need.
+4 -12
View File
@@ -36,7 +36,7 @@ use BuildUtils qw(
pin_control_version rewrite_changelog_header
reprepro_distributions reprepro_options
lock_id_for take_build_lock sh_quote
sh usage read_file write_file rewrite_file
sh usage read_file write_file rewrite_file buildinfo_text
);
# The xcat-core packages that ship as debs. xCAT-openbmc-py, xCAT-rmc and xCAT-release
@@ -338,17 +338,9 @@ SCRIPT
close $m;
chmod 0775, "$repodir/mklocalrepo.sh";
my $commit = `git -C @{[ sh_quote($ROOT) ]} rev-parse HEAD 2>/dev/null` || 'unknown';
chomp $commit;
my $host = `hostname 2>/dev/null` || 'unknown'; chomp $host;
open my $b, '>', "$repodir/buildinfo" or die "Cannot write buildinfo: $!\n";
print {$b} "VERSION=$VERSION\n",
"RELEASE=$RELEASE\n",
"BUILD_TIME=@{[ strftime('%a %b %d %H:%M:%S %Y', gmtime($EPOCH)) ]}\n",
"BUILD_MACHINE=$host\n",
"COMMIT_ID=@{[ substr($commit, 0, 7) ]}\n",
"COMMIT_ID_LONG=$commit\n";
close $b;
write_file("$repodir/buildinfo", buildinfo_text(
version => $VERSION, release => $RELEASE, epoch => $EPOCH,
commit => $GITINFO, time_format => '%a %b %d %H:%M:%S %Y'));
return;
}
+4 -12
View File
@@ -43,7 +43,7 @@ use File::Slurper qw(read_text write_text);
use File::Temp qw(tempdir tempfile);
use FindBin qw($Bin);
use lib $Bin;
use BuildUtils qw(git_revision source_date_epoch sh usage);
use BuildUtils qw(git_revision source_date_epoch sh usage buildinfo_text);
use Fcntl qw(:flock); # per-target build lock (concurrency guard; see main())
use Getopt::Long qw(GetOptions);
use POSIX qw(strftime);
@@ -811,17 +811,9 @@ EOF2
chmod 0775, "$repodir/mklocalrepo.sh";
# BUILD_TIME from SOURCE_DATE_EPOCH keeps buildinfo reproducible across rebuilds.
my $build_time = strftime("%a %b %e %H:%M:%S %Z %Y", gmtime($SOURCE_DATE_EPOCH));
my $build_machine = `hostname`; chomp $build_machine;
my $commit_short = substr($GITINFO, 0, 7);
write_text("$repodir/buildinfo.txt", <<"EOF");
VERSION=$VERSION
RELEASE=$RELEASE
BUILD_TIME=$build_time
BUILD_MACHINE=$build_machine
COMMIT_ID=$commit_short
COMMIT_ID_LONG=$GITINFO
EOF
write_text("$repodir/buildinfo.txt", buildinfo_text(
version => $VERSION, release => $RELEASE, epoch => $SOURCE_DATE_EPOCH,
commit => $GITINFO, time_format => "%a %b %e %H:%M:%S %Z %Y"));
}
# Assemble the flat MULTI-ARCH core from per-arch build outputs and sign it, in the upstream
+25
View File
@@ -308,6 +308,31 @@ is( git_revision( git => sub { "\n" }, read_file => sub { " \n" } ),
isnt( git_revision( git => sub { '' }, read_file => sub { '' } ), '',
'the one thing it must never return is empty' );
# ------------------------------------------------------- buildinfo_text --
# deploy.sh copies this file verbatim and cluster-test.pl parses it, so the
# field names and their order are a contract, not a presentation choice.
{
my $text = BuildUtils::buildinfo_text(
version => '2.18.1', release => 'snap1', epoch => 0,
commit => 'abcdef1234567890', host => 'builder',
time_format => '%Y-%m-%d',
);
is_deeply( [ map { (split /=/, $_, 2)[0] } split /\n/, $text ],
[qw(VERSION RELEASE BUILD_TIME BUILD_MACHINE COMMIT_ID COMMIT_ID_LONG)],
'the fields appear in the order the consumers expect' );
like( $text, qr/^COMMIT_ID=abcdef1\n/m, 'the short commit is seven characters' );
like( $text, qr/^COMMIT_ID_LONG=abcdef1234567890\n/m, 'and the long one is whole' );
like( $text, qr/^BUILD_TIME=1970-01-01\n/m,
"the caller's own time format is used" );
# The two builders stamp different formats, and both are consumed.
my %common = (version => '1', release => '2', epoch => 0,
commit => 'c', host => 'h');
isnt( BuildUtils::buildinfo_text(%common, time_format => '%a %b %d %H:%M:%S %Y'),
BuildUtils::buildinfo_text(%common, time_format => '%a %b %e %H:%M:%S %Z %Y'),
'each builder keeps the format its own consumers parse' );
}
# -------------------------------------------------- whole-file helpers --
{
my $dir = tempdir(CLEANUP => 1);