mirror of
https://github.com/xcat2/xcat-dep.git
synced 2026-09-14 10:13:49 +00:00
build: Make builds deterministic
Port SOURCE_DATE_EPOCH patterns from xcat-core to all xcat-dep build scripts. RPM and Debian packages now produce identical output given the same Gitepoch timestamp, regardless of build host or time. EL (RPM) changes: - mockbuild-all.pl: --build-timestamp flag, deterministic run_id, tar --sort/--owner/--group/--mtime, createrepo --revision - All mockbuild.pl: SOURCE_DATE_EPOCH cascade (CLI > Gitepoch > git > time), deterministic mock config with SOURCE_DATE_EPOCH in chroot env, RPM macros for timestamp clamping and fixed buildhost - goconserver: -trimpath -buildvcs=false, canonical rpmbuild path - xnba: canonical rpmbuild path - syslinux: ZERO_AR_DATE=1 in mock env Ubuntu (Debian) changes: - All make_deb.sh: SOURCE_DATE_EPOCH fallback from Gitepoch - goconserver: deterministic SNAP_TS and changelog from epoch, -trimpath -buildvcs=false in debian/rules - syslinux: -fdebug-prefix-map for path-independent debug info - build-apt-repo.sh: gzip -n, Release Date: from SOURCE_DATE_EPOCH Verified: 31/33 package artifacts produce identical SHA256 hashes across independent builds. 2 syslinux sub-packages (devel, debugsource) have known limitations from upstream build system.
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
Gitepoch
|
||||
Gitinfo
|
||||
Release
|
||||
@@ -1,4 +1,12 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
if [ -z "${SOURCE_DATE_EPOCH:-}" ]; then
|
||||
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
if [ -f "$REPO_ROOT/Gitepoch" ]; then
|
||||
export SOURCE_DATE_EPOCH=$(cat "$REPO_ROOT/Gitepoch")
|
||||
fi
|
||||
fi
|
||||
|
||||
tar xvfz conserver-8.2.1.tar.gz
|
||||
cd conserver-8.2.1
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
if [ -z "${SOURCE_DATE_EPOCH:-}" ]; then
|
||||
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
if [ -f "$REPO_ROOT/Gitepoch" ]; then
|
||||
export SOURCE_DATE_EPOCH=$(cat "$REPO_ROOT/Gitepoch")
|
||||
fi
|
||||
fi
|
||||
|
||||
tar xvfz elilo-3.14-source.tar.gz
|
||||
cd elilo
|
||||
|
||||
+35
-2
@@ -21,6 +21,7 @@ my $mock_uniqueext = '';
|
||||
my $result_dir = "$repo_root/build-output/list3/elilo-xcat";
|
||||
my $log_dir = "$repo_root/build-logs/list3/elilo-xcat";
|
||||
my $skip_install = 0;
|
||||
my $build_timestamp;
|
||||
|
||||
GetOptions(
|
||||
'source-url=s' => \$source_url,
|
||||
@@ -31,6 +32,7 @@ GetOptions(
|
||||
'result-dir=s' => \$result_dir,
|
||||
'log-dir=s' => \$log_dir,
|
||||
'skip-install!' => \$skip_install,
|
||||
'build-timestamp=i' => \$build_timestamp,
|
||||
) or die usage();
|
||||
|
||||
die "Run as root (current uid=$>)\n" if $> != 0;
|
||||
@@ -57,6 +59,19 @@ my $mock_uniqueext_opt = $mock_uniqueext ne ''
|
||||
? ' --uniqueext ' . sh_quote($mock_uniqueext)
|
||||
: '';
|
||||
|
||||
my $SOURCE_DATE_EPOCH;
|
||||
$SOURCE_DATE_EPOCH = $build_timestamp if defined $build_timestamp;
|
||||
if (!$SOURCE_DATE_EPOCH && -f "$repo_root/Gitepoch") {
|
||||
$SOURCE_DATE_EPOCH = slurp("$repo_root/Gitepoch");
|
||||
chomp $SOURCE_DATE_EPOCH;
|
||||
}
|
||||
unless ($SOURCE_DATE_EPOCH && $SOURCE_DATE_EPOCH =~ /^\d+$/) {
|
||||
$SOURCE_DATE_EPOCH = `git -C \Q$repo_root\E log -1 --format=%ct HEAD 2>/dev/null`;
|
||||
chomp $SOURCE_DATE_EPOCH;
|
||||
}
|
||||
$SOURCE_DATE_EPOCH = time() unless $SOURCE_DATE_EPOCH =~ /^\d+$/;
|
||||
$ENV{SOURCE_DATE_EPOCH} = $SOURCE_DATE_EPOCH;
|
||||
|
||||
print_step("Configuration");
|
||||
print "repo_root: $repo_root\n";
|
||||
print "pkg_dir: $pkg_dir\n";
|
||||
@@ -93,6 +108,7 @@ my $prep_top = "$work_dir/prep";
|
||||
for my $d (qw(BUILD BUILDROOT RPMS SOURCES SPECS SRPMS)) {
|
||||
make_path("$prep_top/$d");
|
||||
}
|
||||
my $det_mock_cfg = create_deterministic_mock_cfg($mock_cfg, $SOURCE_DATE_EPOCH, $work_dir);
|
||||
copy($spec_file, "$prep_top/SPECS/elilo-xcat.spec")
|
||||
or die "Failed to copy spec to prep topdir: $!\n";
|
||||
for my $asset (@spec_assets) {
|
||||
@@ -116,9 +132,12 @@ print_step("Build SRPM with mock");
|
||||
my $srpm_out = "$work_dir/srpm";
|
||||
make_path($srpm_out);
|
||||
run(
|
||||
"mock -r " . sh_quote($mock_cfg) . $mock_uniqueext_opt .
|
||||
"mock -r " . sh_quote($det_mock_cfg) . $mock_uniqueext_opt .
|
||||
" --buildsrpm --spec " . sh_quote($spec_file) .
|
||||
" --sources " . sh_quote($pkg_dir) .
|
||||
" --define " . sh_quote("use_source_date_epoch_as_buildtime 1") .
|
||||
" --define " . sh_quote("clamp_mtime_to_source_date_epoch 1") .
|
||||
" --define " . sh_quote("_buildhost xcat-build") .
|
||||
" --resultdir " . sh_quote($srpm_out)
|
||||
);
|
||||
|
||||
@@ -131,8 +150,11 @@ print_step("Rebuild RPM with mock");
|
||||
my $rpm_out = "$work_dir/rpm";
|
||||
make_path($rpm_out);
|
||||
run(
|
||||
"mock -r " . sh_quote($mock_cfg) . $mock_uniqueext_opt .
|
||||
"mock -r " . sh_quote($det_mock_cfg) . $mock_uniqueext_opt .
|
||||
" --rebuild " . sh_quote($srpm) .
|
||||
" --define " . sh_quote("use_source_date_epoch_as_buildtime 1") .
|
||||
" --define " . sh_quote("clamp_mtime_to_source_date_epoch 1") .
|
||||
" --define " . sh_quote("_buildhost xcat-build") .
|
||||
" --resultdir " . sh_quote($rpm_out)
|
||||
);
|
||||
|
||||
@@ -221,9 +243,20 @@ Usage: $0 [options]
|
||||
--result-dir PATH Output RPM/SRPM directory (default: $result_dir)
|
||||
--log-dir PATH Log directory (default: $log_dir)
|
||||
--skip-install Skip dnf install + smoke tests
|
||||
--build-timestamp EPOCH Unix timestamp for SOURCE_DATE_EPOCH (deterministic builds)
|
||||
USAGE
|
||||
}
|
||||
|
||||
sub create_deterministic_mock_cfg {
|
||||
my ($base_cfg, $epoch, $dir) = @_;
|
||||
my $cfg_path = "$dir/mock-deterministic.cfg";
|
||||
open my $fh, '>', $cfg_path or die "Cannot write $cfg_path: $!\n";
|
||||
print $fh "include('/etc/mock/${base_cfg}.cfg')\n";
|
||||
print $fh "config_opts['environment']['SOURCE_DATE_EPOCH'] = '$epoch'\n";
|
||||
close $fh;
|
||||
return $cfg_path;
|
||||
}
|
||||
|
||||
sub parse_spec {
|
||||
my ($path) = @_;
|
||||
open my $fh, '<', $path or die "Cannot open spec $path: $!\n";
|
||||
|
||||
@@ -4,8 +4,8 @@ export CGO_ENABLED=0
|
||||
dh $@
|
||||
override_dh_auto_configure:
|
||||
override_dh_auto_build:
|
||||
go build -ldflags "-X main.Version=0.3.3" -o goconserver goconserver.go
|
||||
go build -ldflags "-X main.Version=0.3.3" -o congo cmd/congo.go
|
||||
go build -trimpath -buildvcs=false -ldflags "-X main.Version=0.3.3" -o goconserver goconserver.go
|
||||
go build -trimpath -buildvcs=false -ldflags "-X main.Version=0.3.3" -o congo cmd/congo.go
|
||||
override_dh_auto_install:
|
||||
install -D -m 755 goconserver $(CURDIR)/debian/goconserver/usr/bin/goconserver
|
||||
install -D -m 755 congo $(CURDIR)/debian/goconserver/usr/bin/congo
|
||||
|
||||
@@ -6,6 +6,20 @@ VERSION=0.3.3
|
||||
REPO=https://github.com/xcat2/goconserver.git
|
||||
REF=master
|
||||
|
||||
if [ -z "${SOURCE_DATE_EPOCH:-}" ]; then
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
if [ -f "$REPO_ROOT/Gitepoch" ]; then
|
||||
export SOURCE_DATE_EPOCH=$(cat "$REPO_ROOT/Gitepoch")
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -n "${SOURCE_DATE_EPOCH:-}" ]; then
|
||||
SNAP_TS=$(date -d "@$SOURCE_DATE_EPOCH" --utc '+%Y%m%d%H%M')
|
||||
else
|
||||
SNAP_TS=$(date '+%Y%m%d%H%M')
|
||||
fi
|
||||
FULL_VERSION="${VERSION}-snap${SNAP_TS}"
|
||||
|
||||
WORKDIR=$(mktemp -d)
|
||||
trap "rm -rf $WORKDIR" EXIT
|
||||
|
||||
@@ -27,6 +41,18 @@ go mod tidy
|
||||
|
||||
cp -rL "$SCRIPT_DIR/debian" .
|
||||
|
||||
sed -i "s/Version=${VERSION}/Version=${FULL_VERSION}/g" debian/rules
|
||||
|
||||
if [ -n "${SOURCE_DATE_EPOCH:-}" ]; then
|
||||
export DEBEMAIL="${DEBEMAIL:-xcat-build@xcat.org}"
|
||||
export DEBFULLNAME="${DEBFULLNAME:-xCAT Build}"
|
||||
deterministic_date=$(date -R -d "@$SOURCE_DATE_EPOCH" --utc)
|
||||
sed -i "1s/(.*)/(${FULL_VERSION})/" debian/changelog
|
||||
sed -i "s/^ -- .*/ -- $DEBFULLNAME <$DEBEMAIL> $deterministic_date/" debian/changelog
|
||||
else
|
||||
dch -v "$FULL_VERSION" -b -D unstable "Snap build for xCAT"
|
||||
fi
|
||||
|
||||
dpkg-buildpackage -uc -us
|
||||
|
||||
echo "Built debs:"
|
||||
|
||||
@@ -21,6 +21,7 @@ my $skip_install = 0;
|
||||
my $version = '0.3.3';
|
||||
my $go_repo = 'https://github.com/xcat2/goconserver.git';
|
||||
my $go_ref = 'master';
|
||||
my $build_timestamp;
|
||||
|
||||
GetOptions(
|
||||
'work-dir=s' => \$work_dir,
|
||||
@@ -32,6 +33,7 @@ GetOptions(
|
||||
'version=s' => \$version,
|
||||
'go-repo=s' => \$go_repo,
|
||||
'go-ref=s' => \$go_ref,
|
||||
'build-timestamp=i' => \$build_timestamp,
|
||||
) or die usage();
|
||||
|
||||
die "Run as root (current uid=$>)\n" if $> != 0;
|
||||
@@ -49,6 +51,24 @@ if (!$mock_cfg) {
|
||||
my ($rel) = $mock_cfg =~ /-(\d+)-/;
|
||||
$rel //= '10';
|
||||
|
||||
my $SOURCE_DATE_EPOCH;
|
||||
$SOURCE_DATE_EPOCH = $build_timestamp if defined $build_timestamp;
|
||||
if (!$SOURCE_DATE_EPOCH && -f "$repo_root/Gitepoch") {
|
||||
my $epoch_content = '';
|
||||
if (open my $efh, '<', "$repo_root/Gitepoch") {
|
||||
$epoch_content = <$efh>;
|
||||
close $efh;
|
||||
chomp $epoch_content;
|
||||
}
|
||||
$SOURCE_DATE_EPOCH = $epoch_content;
|
||||
}
|
||||
unless ($SOURCE_DATE_EPOCH && $SOURCE_DATE_EPOCH =~ /^\d+$/) {
|
||||
$SOURCE_DATE_EPOCH = `git -C \Q$repo_root\E log -1 --format=%ct HEAD 2>/dev/null`;
|
||||
chomp $SOURCE_DATE_EPOCH;
|
||||
}
|
||||
$SOURCE_DATE_EPOCH = time() unless $SOURCE_DATE_EPOCH =~ /^\d+$/;
|
||||
$ENV{SOURCE_DATE_EPOCH} = $SOURCE_DATE_EPOCH;
|
||||
|
||||
print_step("Configuration");
|
||||
print "repo_root: $repo_root\n";
|
||||
print "pkg_dir: $pkg_dir\n";
|
||||
@@ -69,7 +89,8 @@ print_step("Stage build environment");
|
||||
remove_tree($work_dir) if -d $work_dir;
|
||||
make_path($work_dir);
|
||||
|
||||
my $rpmbuild_top = "$work_dir/rpmbuild";
|
||||
my $rpmbuild_top = "/var/tmp/xcat-rpmbuild-goconserver";
|
||||
remove_tree($rpmbuild_top) if -d $rpmbuild_top;
|
||||
for my $d (qw(BUILD BUILDROOT RPMS SOURCES SPECS SRPMS)) {
|
||||
make_path("$rpmbuild_top/$d");
|
||||
}
|
||||
@@ -107,12 +128,12 @@ make_path($go_build_dir);
|
||||
my $ldflags = "-X main.Version=$version";
|
||||
|
||||
run("cd " . sh_quote($src_dir) . " && " .
|
||||
"go build -ldflags " . sh_quote($ldflags) .
|
||||
"go build -trimpath -buildvcs=false -ldflags " . sh_quote($ldflags) .
|
||||
" -o " . sh_quote("$go_build_dir/goconserver") . " goconserver.go" .
|
||||
" >" . sh_quote("$log_dir/go-build-server.log") . " 2>&1");
|
||||
|
||||
run("cd " . sh_quote($src_dir) . " && " .
|
||||
"go build -ldflags " . sh_quote($ldflags) .
|
||||
"go build -trimpath -buildvcs=false -ldflags " . sh_quote($ldflags) .
|
||||
" -o " . sh_quote("$go_build_dir/congo") . " cmd/congo.go" .
|
||||
" >" . sh_quote("$log_dir/go-build-client.log") . " 2>&1");
|
||||
|
||||
@@ -157,7 +178,8 @@ log_level = info
|
||||
CONF
|
||||
|
||||
my $tarball = "$rpmbuild_top/SOURCES/goconserver-$version.tar.gz";
|
||||
run("tar -C " . sh_quote($work_dir) . " -czf " . sh_quote($tarball) .
|
||||
run("tar --sort=name --owner=0 --group=0 --mtime=\@$SOURCE_DATE_EPOCH" .
|
||||
" -C " . sh_quote($work_dir) . " -czf " . sh_quote($tarball) .
|
||||
" goconserver-$version");
|
||||
|
||||
print_step("Create spec and build RPM");
|
||||
@@ -208,6 +230,9 @@ write_file($spec_file, $spec_content);
|
||||
|
||||
run(
|
||||
"rpmbuild --define " . sh_quote("_topdir $rpmbuild_top") .
|
||||
" --define " . sh_quote("use_source_date_epoch_as_buildtime 1") .
|
||||
" --define " . sh_quote("clamp_mtime_to_source_date_epoch 1") .
|
||||
" --define " . sh_quote("_buildhost xcat-build") .
|
||||
" -ba " . sh_quote($spec_file) .
|
||||
" >" . sh_quote("$log_dir/rpmbuild.log") . " 2>&1"
|
||||
);
|
||||
@@ -260,6 +285,7 @@ Options:
|
||||
--version VER Version string (default: 0.3.3)
|
||||
--go-repo URL Git repo URL (default: github.com/xcat2/goconserver)
|
||||
--go-ref REF Git ref to build (default: master)
|
||||
--build-timestamp EPOCH SOURCE_DATE_EPOCH for deterministic builds
|
||||
USAGE
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
if [ -z "${SOURCE_DATE_EPOCH:-}" ]; then
|
||||
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
if [ -f "$REPO_ROOT/Gitepoch" ]; then
|
||||
export SOURCE_DATE_EPOCH=$(cat "$REPO_ROOT/Gitepoch")
|
||||
fi
|
||||
fi
|
||||
|
||||
dpkg-buildpackage -uc -us
|
||||
|
||||
+38
-4
@@ -24,6 +24,7 @@ my $result_dir = "$repo_root/build-output/list3/grub2-xcat";
|
||||
my $log_dir = "$repo_root/build-logs/list3/grub2-xcat";
|
||||
my $skip_install = 0;
|
||||
my $skip_upstream_download = 0;
|
||||
my $build_timestamp;
|
||||
|
||||
GetOptions(
|
||||
'resource-mode=s' => \$resource_mode,
|
||||
@@ -36,6 +37,7 @@ GetOptions(
|
||||
'log-dir=s' => \$log_dir,
|
||||
'skip-install!' => \$skip_install,
|
||||
'skip-upstream-download!' => \$skip_upstream_download,
|
||||
'build-timestamp=i' => \$build_timestamp,
|
||||
) or die usage();
|
||||
|
||||
die "Run as root (current uid=$>)\n" if $> != 0;
|
||||
@@ -69,6 +71,19 @@ my $mock_uniqueext_opt = $mock_uniqueext ne ''
|
||||
? ' --uniqueext ' . sh_quote($mock_uniqueext)
|
||||
: '';
|
||||
|
||||
my $SOURCE_DATE_EPOCH;
|
||||
$SOURCE_DATE_EPOCH = $build_timestamp if defined $build_timestamp;
|
||||
if (!$SOURCE_DATE_EPOCH && -f "$repo_root/Gitepoch") {
|
||||
$SOURCE_DATE_EPOCH = slurp("$repo_root/Gitepoch");
|
||||
chomp $SOURCE_DATE_EPOCH;
|
||||
}
|
||||
unless ($SOURCE_DATE_EPOCH && $SOURCE_DATE_EPOCH =~ /^\d+$/) {
|
||||
$SOURCE_DATE_EPOCH = `git -C \Q$repo_root\E log -1 --format=%ct HEAD 2>/dev/null`;
|
||||
chomp $SOURCE_DATE_EPOCH;
|
||||
}
|
||||
$SOURCE_DATE_EPOCH = time() unless $SOURCE_DATE_EPOCH =~ /^\d+$/;
|
||||
$ENV{SOURCE_DATE_EPOCH} = $SOURCE_DATE_EPOCH;
|
||||
|
||||
print_step("Configuration");
|
||||
print "repo_root: $repo_root\n";
|
||||
print "pkg_dir: $pkg_dir\n";
|
||||
@@ -131,6 +146,8 @@ my $prep_top = "$work_dir/prep";
|
||||
for my $d (qw(BUILD BUILDROOT RPMS SOURCES SPECS SRPMS)) {
|
||||
make_path("$prep_top/$d");
|
||||
}
|
||||
my $det_mock_cfg = create_deterministic_mock_cfg($mock_cfg, $SOURCE_DATE_EPOCH, $work_dir);
|
||||
|
||||
copy($spec_file, "$prep_top/SPECS/grub2-xcat.spec")
|
||||
or die "Failed to copy spec to prep topdir: $!\n";
|
||||
for my $asset (@spec_assets) {
|
||||
@@ -152,10 +169,13 @@ print_step("Build SRPM with mock");
|
||||
my $srpm_out = "$work_dir/srpm";
|
||||
make_path($srpm_out);
|
||||
run(
|
||||
"mock -r " . sh_quote($mock_cfg) . $mock_uniqueext_opt .
|
||||
"mock -r " . sh_quote($det_mock_cfg) . $mock_uniqueext_opt .
|
||||
" --buildsrpm --spec " . sh_quote($spec_file) .
|
||||
" --sources " . sh_quote($pkg_dir) .
|
||||
" --resultdir " . sh_quote($srpm_out)
|
||||
" --resultdir " . sh_quote($srpm_out) .
|
||||
" --define 'use_source_date_epoch_as_buildtime 1'" .
|
||||
" --define 'clamp_mtime_to_source_date_epoch 1'" .
|
||||
" --define '_buildhost xcat-build'"
|
||||
);
|
||||
|
||||
my @srpms = sort glob("$srpm_out/grub2-xcat-*.src.rpm");
|
||||
@@ -167,9 +187,12 @@ print_step("Rebuild RPM with mock");
|
||||
my $rpm_out = "$work_dir/rpm";
|
||||
make_path($rpm_out);
|
||||
run(
|
||||
"mock -r " . sh_quote($mock_cfg) . $mock_uniqueext_opt .
|
||||
"mock -r " . sh_quote($det_mock_cfg) . $mock_uniqueext_opt .
|
||||
" --rebuild " . sh_quote($srpm) .
|
||||
" --resultdir " . sh_quote($rpm_out)
|
||||
" --resultdir " . sh_quote($rpm_out) .
|
||||
" --define 'use_source_date_epoch_as_buildtime 1'" .
|
||||
" --define 'clamp_mtime_to_source_date_epoch 1'" .
|
||||
" --define '_buildhost xcat-build'"
|
||||
);
|
||||
|
||||
my @all_rpms = sort glob("$rpm_out/*.rpm");
|
||||
@@ -281,9 +304,20 @@ Usage: $0 [options]
|
||||
--log-dir PATH Log directory (default: $log_dir)
|
||||
--skip-upstream-download Skip wget of upstream source RPM
|
||||
--skip-install Skip dnf install + smoke tests
|
||||
--build-timestamp EPOCH Unix timestamp for deterministic builds (SOURCE_DATE_EPOCH)
|
||||
USAGE
|
||||
}
|
||||
|
||||
sub create_deterministic_mock_cfg {
|
||||
my ($base_cfg, $epoch, $dir) = @_;
|
||||
my $cfg_path = "$dir/mock-deterministic.cfg";
|
||||
open my $fh, '>', $cfg_path or die "Cannot write $cfg_path: $!\n";
|
||||
print $fh "include('/etc/mock/${base_cfg}.cfg')\n";
|
||||
print $fh "config_opts['environment']['SOURCE_DATE_EPOCH'] = '$epoch'\n";
|
||||
close $fh;
|
||||
return $cfg_path;
|
||||
}
|
||||
|
||||
sub parse_spec {
|
||||
my ($path) = @_;
|
||||
open my $fh, '<', $path or die "Cannot open spec $path: $!\n";
|
||||
|
||||
@@ -1,4 +1,13 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
if [ -z "${SOURCE_DATE_EPOCH:-}" ]; then
|
||||
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
if [ -f "$REPO_ROOT/Gitepoch" ]; then
|
||||
export SOURCE_DATE_EPOCH=$(cat "$REPO_ROOT/Gitepoch")
|
||||
fi
|
||||
fi
|
||||
|
||||
VERSION=1.8.18
|
||||
|
||||
tar xvfz ipmitool-$VERSION.tar.gz
|
||||
|
||||
+39
-3
@@ -21,6 +21,7 @@ my $mock_uniqueext = '';
|
||||
my $result_dir = "$repo_root/build-output/list3/ipmitool-xcat";
|
||||
my $log_dir = "$repo_root/build-logs/list3/ipmitool-xcat";
|
||||
my $skip_install = 0;
|
||||
my $build_timestamp;
|
||||
|
||||
GetOptions(
|
||||
'source-url=s' => \$source_url,
|
||||
@@ -31,6 +32,7 @@ GetOptions(
|
||||
'result-dir=s' => \$result_dir,
|
||||
'log-dir=s' => \$log_dir,
|
||||
'skip-install!' => \$skip_install,
|
||||
'build-timestamp=i' => \$build_timestamp,
|
||||
) or die usage();
|
||||
|
||||
die "Run as root (current uid=$>)\n" if $> != 0;
|
||||
@@ -57,6 +59,19 @@ my $mock_uniqueext_opt = $mock_uniqueext ne ''
|
||||
? ' --uniqueext ' . sh_quote($mock_uniqueext)
|
||||
: '';
|
||||
|
||||
my $SOURCE_DATE_EPOCH;
|
||||
$SOURCE_DATE_EPOCH = $build_timestamp if defined $build_timestamp;
|
||||
if (!$SOURCE_DATE_EPOCH && -f "$repo_root/Gitepoch") {
|
||||
$SOURCE_DATE_EPOCH = slurp("$repo_root/Gitepoch");
|
||||
chomp $SOURCE_DATE_EPOCH;
|
||||
}
|
||||
unless ($SOURCE_DATE_EPOCH && $SOURCE_DATE_EPOCH =~ /^\d+$/) {
|
||||
$SOURCE_DATE_EPOCH = `git -C \Q$repo_root\E log -1 --format=%ct HEAD 2>/dev/null`;
|
||||
chomp $SOURCE_DATE_EPOCH;
|
||||
}
|
||||
$SOURCE_DATE_EPOCH = time() unless $SOURCE_DATE_EPOCH =~ /^\d+$/;
|
||||
$ENV{SOURCE_DATE_EPOCH} = $SOURCE_DATE_EPOCH;
|
||||
|
||||
print_step("Configuration");
|
||||
print "repo_root: $repo_root\n";
|
||||
print "pkg_dir: $pkg_dir\n";
|
||||
@@ -68,6 +83,7 @@ print "mock_uniqueext: " . ($mock_uniqueext ne '' ? $mock_uniqueext : '(none)')
|
||||
print "source_url: $source_url\n";
|
||||
print "source_file:$source_file\n";
|
||||
print "skip_install: $skip_install\n";
|
||||
print "SOURCE_DATE_EPOCH: $SOURCE_DATE_EPOCH\n";
|
||||
|
||||
make_path($result_dir);
|
||||
make_path($log_dir);
|
||||
@@ -90,6 +106,7 @@ print "Verified " . scalar(@spec_assets) . " Source/Patch assets from spec.\n";
|
||||
print_step("Stage files for patch-application check");
|
||||
remove_tree($work_dir) if -d $work_dir;
|
||||
my $prep_top = "$work_dir/prep";
|
||||
my $det_mock_cfg = create_deterministic_mock_cfg($mock_cfg, $SOURCE_DATE_EPOCH, $work_dir);
|
||||
for my $d (qw(BUILD BUILDROOT RPMS SOURCES SPECS SRPMS)) {
|
||||
make_path("$prep_top/$d");
|
||||
}
|
||||
@@ -116,9 +133,12 @@ print_step("Build SRPM with mock");
|
||||
my $srpm_out = "$work_dir/srpm";
|
||||
make_path($srpm_out);
|
||||
run(
|
||||
"mock -r " . sh_quote($mock_cfg) . $mock_uniqueext_opt .
|
||||
"mock -r " . sh_quote($det_mock_cfg) . $mock_uniqueext_opt .
|
||||
" --buildsrpm --spec " . sh_quote($spec_file) .
|
||||
" --sources " . sh_quote($pkg_dir) .
|
||||
" --define " . sh_quote("use_source_date_epoch_as_buildtime 1") .
|
||||
" --define " . sh_quote("clamp_mtime_to_source_date_epoch 1") .
|
||||
" --define " . sh_quote("_buildhost xcat-build") .
|
||||
" --resultdir " . sh_quote($srpm_out)
|
||||
);
|
||||
|
||||
@@ -131,8 +151,11 @@ print_step("Rebuild RPM with mock");
|
||||
my $rpm_out = "$work_dir/rpm";
|
||||
make_path($rpm_out);
|
||||
run(
|
||||
"mock -r " . sh_quote($mock_cfg) . $mock_uniqueext_opt .
|
||||
"mock -r " . sh_quote($det_mock_cfg) . $mock_uniqueext_opt .
|
||||
" --rebuild " . sh_quote($srpm) .
|
||||
" --define " . sh_quote("use_source_date_epoch_as_buildtime 1") .
|
||||
" --define " . sh_quote("clamp_mtime_to_source_date_epoch 1") .
|
||||
" --define " . sh_quote("_buildhost xcat-build") .
|
||||
" --resultdir " . sh_quote($rpm_out)
|
||||
);
|
||||
|
||||
@@ -243,9 +266,21 @@ Usage: $0 [options]
|
||||
--result-dir PATH Output RPM/SRPM directory (default: $result_dir)
|
||||
--log-dir PATH Log directory (default: $log_dir)
|
||||
--skip-install Skip dnf install + smoke tests
|
||||
--build-timestamp N Unix epoch for SOURCE_DATE_EPOCH (deterministic builds)
|
||||
USAGE
|
||||
}
|
||||
|
||||
sub create_deterministic_mock_cfg {
|
||||
my ($base_cfg, $epoch, $dir) = @_;
|
||||
make_path($dir) unless -d $dir;
|
||||
my $cfg_path = "$dir/mock-deterministic.cfg";
|
||||
open my $fh, '>', $cfg_path or die "Cannot write $cfg_path: $!\n";
|
||||
print $fh "include('/etc/mock/${base_cfg}.cfg')\n";
|
||||
print $fh "config_opts['environment']['SOURCE_DATE_EPOCH'] = '$epoch'\n";
|
||||
close $fh;
|
||||
return $cfg_path;
|
||||
}
|
||||
|
||||
sub parse_spec {
|
||||
my ($path) = @_;
|
||||
open my $fh, '<', $path or die "Cannot open spec $path: $!\n";
|
||||
@@ -298,7 +333,8 @@ sub normalize_source_archive {
|
||||
|
||||
# Repack using the expected top-level directory required by the spec.
|
||||
run(
|
||||
"tar -C " . sh_quote($normalize_dir) .
|
||||
"tar --sort=name --owner=0 --group=0 --mtime=\@$SOURCE_DATE_EPOCH" .
|
||||
" -C " . sh_quote($normalize_dir) .
|
||||
" -czf " . sh_quote($archive) .
|
||||
" " . sh_quote($expected_top)
|
||||
);
|
||||
|
||||
+41
-6
@@ -19,7 +19,8 @@ my $output_root = "$repo_root/build-output/mockbuild-all";
|
||||
my $target = '';
|
||||
my $nproc = 1;
|
||||
my $parallel_builds;
|
||||
my $run_id = strftime('%Y%m%d-%H%M%S', localtime);
|
||||
my $run_id = '';
|
||||
my $build_timestamp;
|
||||
my $skip_install = 0;
|
||||
my $skip_build = 0;
|
||||
my $skip_xcat_dep = 0;
|
||||
@@ -39,6 +40,7 @@ GetOptions(
|
||||
'nproc=i' => \$nproc,
|
||||
'parallel-builds=i' => \$parallel_builds,
|
||||
'run-id=s' => \$run_id,
|
||||
'build-timestamp=i' => \$build_timestamp,
|
||||
'skip-install!' => \$skip_install,
|
||||
'skip-build!' => \$skip_build,
|
||||
'skip-xcat-dep!' => \$skip_xcat_dep,
|
||||
@@ -56,6 +58,23 @@ die "--parallel-builds must be >= 1\n"
|
||||
if defined($parallel_builds) && $parallel_builds < 1;
|
||||
|
||||
$repo_root = abs_path($repo_root);
|
||||
|
||||
my $SOURCE_DATE_EPOCH;
|
||||
$SOURCE_DATE_EPOCH = $build_timestamp if defined $build_timestamp;
|
||||
if (!$SOURCE_DATE_EPOCH && -f "$repo_root/Gitepoch") {
|
||||
$SOURCE_DATE_EPOCH = slurp_chomp("$repo_root/Gitepoch");
|
||||
}
|
||||
unless ($SOURCE_DATE_EPOCH && $SOURCE_DATE_EPOCH =~ /^\d+$/) {
|
||||
$SOURCE_DATE_EPOCH = `git -C \Q$repo_root\E log -1 --format=%ct HEAD 2>/dev/null`;
|
||||
chomp $SOURCE_DATE_EPOCH;
|
||||
}
|
||||
$SOURCE_DATE_EPOCH = time() unless $SOURCE_DATE_EPOCH =~ /^\d+$/;
|
||||
$ENV{SOURCE_DATE_EPOCH} = $SOURCE_DATE_EPOCH;
|
||||
|
||||
if ($run_id eq '') {
|
||||
$run_id = strftime('%Y%m%d-%H%M%S', gmtime($SOURCE_DATE_EPOCH));
|
||||
}
|
||||
|
||||
$xcat_src = resolve_xcat_source($xcat_src, $repo_root);
|
||||
|
||||
my $arch = capture('uname -m');
|
||||
@@ -170,6 +189,7 @@ if (!$skip_build) {
|
||||
'--mock-uniqueext', sh_quote($step_uniqueext),
|
||||
'--result-dir', sh_quote($step_result),
|
||||
'--log-dir', sh_quote($step_log),
|
||||
'--build-timestamp', $SOURCE_DATE_EPOCH,
|
||||
($skip_install ? '--skip-install' : ()),
|
||||
);
|
||||
push @build_steps, {
|
||||
@@ -192,6 +212,7 @@ if (!$skip_build) {
|
||||
'--mock-uniqueext', sh_quote($perl_uniqueext),
|
||||
'--result-dir', sh_quote($perl_result),
|
||||
'--log-dir', sh_quote($perl_log),
|
||||
'--build-timestamp', $SOURCE_DATE_EPOCH,
|
||||
($skip_install ? '--skip-install' : ()),
|
||||
);
|
||||
push @build_steps, {
|
||||
@@ -284,19 +305,21 @@ if (!$dry_run && $copied_srpms == 0) {
|
||||
if (!$skip_createrepo) {
|
||||
run_step(
|
||||
step => 'Run createrepo',
|
||||
cmd => 'createrepo --update ' . sh_quote($repo_dir),
|
||||
cmd => 'createrepo --update --revision ' . sh_quote($SOURCE_DATE_EPOCH) . ' ' . sh_quote($repo_dir),
|
||||
log => "$log_root/createrepo.log",
|
||||
);
|
||||
run_step(
|
||||
step => 'Run createrepo for SRPM repo',
|
||||
cmd => 'createrepo --update ' . sh_quote($srpm_repo_dir),
|
||||
cmd => 'createrepo --update --revision ' . sh_quote($SOURCE_DATE_EPOCH) . ' ' . sh_quote($srpm_repo_dir),
|
||||
log => "$log_root/createrepo-srpm.log",
|
||||
);
|
||||
}
|
||||
|
||||
if (!$skip_tarball) {
|
||||
my $cmd = join(' ',
|
||||
'tar', '-C', sh_quote($run_root),
|
||||
'tar', '--sort=name', '--owner=0', '--group=0',
|
||||
"--mtime=\@$SOURCE_DATE_EPOCH",
|
||||
'-C', sh_quote($run_root),
|
||||
'-czf', sh_quote($tarball),
|
||||
'repo'
|
||||
);
|
||||
@@ -306,7 +329,9 @@ if (!$skip_tarball) {
|
||||
log => "$log_root/tarball.log",
|
||||
);
|
||||
my $srpm_cmd = join(' ',
|
||||
'tar', '-C', sh_quote($run_root),
|
||||
'tar', '--sort=name', '--owner=0', '--group=0',
|
||||
"--mtime=\@$SOURCE_DATE_EPOCH",
|
||||
'-C', sh_quote($run_root),
|
||||
'-czf', sh_quote($srpm_tarball),
|
||||
'repo-src'
|
||||
);
|
||||
@@ -365,7 +390,8 @@ Options:
|
||||
--target NAME Optional unified target in <ID>+epel-<REL>-<ARCH> format
|
||||
--nproc N Parallel jobs for buildrpms.pl (default: 1)
|
||||
--parallel-builds N Max concurrent top-level build steps (default: auto=queued steps)
|
||||
--run-id ID Run identifier suffix (default: timestamp)
|
||||
--run-id ID Run identifier suffix (default: derived from build timestamp)
|
||||
--build-timestamp EPOCH Unix epoch for deterministic builds (default: Gitepoch or git log)
|
||||
--skip-install Skip install/smoke tests in child builder scripts
|
||||
--skip-build Skip all build steps and only collect/create repo/tarballs
|
||||
--skip-xcat-dep Skip xcat-dep mockbuild.pl package steps
|
||||
@@ -705,6 +731,15 @@ sub uniq {
|
||||
return grep { defined($_) && !$seen{$_}++ } @_;
|
||||
}
|
||||
|
||||
sub slurp_chomp {
|
||||
my ($path) = @_;
|
||||
open my $fh, '<', $path or die "Cannot read $path: $!\n";
|
||||
my $line = <$fh>;
|
||||
close $fh;
|
||||
chomp $line if defined $line;
|
||||
return $line // '';
|
||||
}
|
||||
|
||||
sub sh_quote {
|
||||
my ($s) = @_;
|
||||
$s = '' if !defined $s;
|
||||
|
||||
@@ -19,6 +19,7 @@ my $packages_csv = '';
|
||||
my $jobs = 0;
|
||||
my $skip_install = 0;
|
||||
my $allow_erasing = 0;
|
||||
my $build_timestamp;
|
||||
|
||||
GetOptions(
|
||||
'work-dir=s' => \$work_dir,
|
||||
@@ -30,6 +31,7 @@ GetOptions(
|
||||
'jobs=i' => \$jobs,
|
||||
'skip-install!' => \$skip_install,
|
||||
'allow-erasing!' => \$allow_erasing,
|
||||
'build-timestamp=i' => \$build_timestamp,
|
||||
) or die usage();
|
||||
|
||||
die "Run as root (current uid=$>)\n" if $> != 0;
|
||||
@@ -46,6 +48,20 @@ if (!$mock_cfg) {
|
||||
my $mock_uniqueext_opt = $mock_uniqueext ne ''
|
||||
? ' --uniqueext ' . sh_quote($mock_uniqueext)
|
||||
: '';
|
||||
|
||||
my $SOURCE_DATE_EPOCH;
|
||||
$SOURCE_DATE_EPOCH = $build_timestamp if defined $build_timestamp;
|
||||
if (!$SOURCE_DATE_EPOCH && -f "$repo_root/Gitepoch") {
|
||||
$SOURCE_DATE_EPOCH = slurp("$repo_root/Gitepoch");
|
||||
chomp $SOURCE_DATE_EPOCH;
|
||||
}
|
||||
unless ($SOURCE_DATE_EPOCH && $SOURCE_DATE_EPOCH =~ /^\d+$/) {
|
||||
$SOURCE_DATE_EPOCH = `git -C \Q$repo_root\E log -1 --format=%ct HEAD 2>/dev/null`;
|
||||
chomp $SOURCE_DATE_EPOCH;
|
||||
}
|
||||
$SOURCE_DATE_EPOCH = time() unless $SOURCE_DATE_EPOCH =~ /^\d+$/;
|
||||
$ENV{SOURCE_DATE_EPOCH} = $SOURCE_DATE_EPOCH;
|
||||
|
||||
if (!$result_dir) {
|
||||
$result_dir = "$repo_root/build-output/list6/perl/$arch";
|
||||
}
|
||||
@@ -277,6 +293,8 @@ sub build_package {
|
||||
make_path($pkg_result);
|
||||
make_path($pkg_log);
|
||||
|
||||
my $det_mock_cfg = create_deterministic_mock_cfg($mock_cfg, $SOURCE_DATE_EPOCH, $pkg_run_dir);
|
||||
|
||||
my $run_log = "$pkg_log/run.log";
|
||||
open my $runfh, '>', $run_log or die "Cannot write $run_log: $!\n";
|
||||
open STDOUT, '>&', $runfh or die "Cannot redirect stdout to $run_log: $!\n";
|
||||
@@ -341,9 +359,12 @@ sub build_package {
|
||||
my $srpm_result = "$pkg_run_dir/srpm";
|
||||
make_path($srpm_result);
|
||||
run(
|
||||
"mock -r " . sh_quote($mock_cfg) . $mock_uniqueext_opt .
|
||||
"mock -r " . sh_quote($det_mock_cfg) . $mock_uniqueext_opt .
|
||||
" --buildsrpm --spec " . sh_quote($spec) .
|
||||
" --sources " . sh_quote($source_dir) .
|
||||
" --define " . sh_quote("use_source_date_epoch_as_buildtime 1") .
|
||||
" --define " . sh_quote("clamp_mtime_to_source_date_epoch 1") .
|
||||
" --define " . sh_quote("_buildhost xcat-build") .
|
||||
" --resultdir " . sh_quote($srpm_result) .
|
||||
" > " . sh_quote("$pkg_log/mock-buildsrpm.log") . " 2>&1"
|
||||
);
|
||||
@@ -353,8 +374,11 @@ sub build_package {
|
||||
}
|
||||
|
||||
run(
|
||||
"mock -r " . sh_quote($mock_cfg) . $mock_uniqueext_opt .
|
||||
"mock -r " . sh_quote($det_mock_cfg) . $mock_uniqueext_opt .
|
||||
" --rebuild " . sh_quote($srpm_path) .
|
||||
" --define " . sh_quote("use_source_date_epoch_as_buildtime 1") .
|
||||
" --define " . sh_quote("clamp_mtime_to_source_date_epoch 1") .
|
||||
" --define " . sh_quote("_buildhost xcat-build") .
|
||||
" --resultdir " . sh_quote($rebuild_result) .
|
||||
" > " . sh_quote("$pkg_log/mock-rebuild.log") . " 2>&1"
|
||||
);
|
||||
@@ -453,6 +477,7 @@ Usage: $0 [options]
|
||||
--result-dir PATH Output directory (default: build-output/list6/perl/<ARCH>)
|
||||
--log-dir PATH Log directory (default: build-logs/list6/perl/<ARCH>)
|
||||
--packages LIST Comma-separated subset of packages to build
|
||||
--build-timestamp EPOCH Unix epoch for SOURCE_DATE_EPOCH (deterministic builds)
|
||||
--skip-install Skip dnf install + perl module import checks
|
||||
--allow-erasing Allow dnf to erase conflicting packages during install smoke tests
|
||||
USAGE
|
||||
@@ -594,6 +619,16 @@ sub resolve_mock_cfg {
|
||||
return $candidate;
|
||||
}
|
||||
|
||||
sub create_deterministic_mock_cfg {
|
||||
my ($base_cfg, $epoch, $dir) = @_;
|
||||
my $cfg_path = "$dir/mock-deterministic.cfg";
|
||||
open my $fh, '>', $cfg_path or die "Cannot write $cfg_path: $!\n";
|
||||
print $fh "include('/etc/mock/${base_cfg}.cfg')\n";
|
||||
print $fh "config_opts['environment']['SOURCE_DATE_EPOCH'] = '$epoch'\n";
|
||||
close $fh;
|
||||
return $cfg_path;
|
||||
}
|
||||
|
||||
sub resolve_source_urls {
|
||||
my ($spec_path) = @_;
|
||||
open my $fh, '<', $spec_path or return ();
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
if [ -z "${SOURCE_DATE_EPOCH:-}" ]; then
|
||||
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
if [ -f "$REPO_ROOT/Gitepoch" ]; then
|
||||
export SOURCE_DATE_EPOCH=$(cat "$REPO_ROOT/Gitepoch")
|
||||
fi
|
||||
fi
|
||||
|
||||
tar xvfj syslinux-3.86.tar.bz2
|
||||
cd syslinux-3.86
|
||||
cp -rL ../debian .
|
||||
@@ -8,6 +15,7 @@ cp -rL ../debian .
|
||||
# GCC >= 10 defaults to -fno-common; syslinux 3.86 relies on common symbols
|
||||
# GCC 15 promotes implicit-function-declaration and incompatible-pointer-types to errors
|
||||
sed -i '/^GCCWARN := -W -Wall/s/$/ -fcommon -Wno-error=implicit-function-declaration -Wno-error=incompatible-pointer-types -Wno-error=int-conversion/' MCONFIG
|
||||
sed -i "s|^GCCWARN := .*|& -fdebug-prefix-map=$(pwd)=.|" MCONFIG
|
||||
|
||||
# glibc >= 2.28 moved major()/minor() to sys/sysmacros.h
|
||||
# extlinux/main.c:843 calls major()/minor() unconditionally in 3.86
|
||||
|
||||
+38
-4
@@ -22,6 +22,7 @@ my $result_dir = "$repo_root/build-output/list3/syslinux-xcat";
|
||||
my $log_dir = "$repo_root/build-logs/list3/syslinux-xcat";
|
||||
my $skip_install = 0;
|
||||
my $skip_upstream_download = 0;
|
||||
my $build_timestamp;
|
||||
|
||||
GetOptions(
|
||||
'source-url=s' => \$source_url,
|
||||
@@ -33,6 +34,7 @@ GetOptions(
|
||||
'log-dir=s' => \$log_dir,
|
||||
'skip-install!' => \$skip_install,
|
||||
'skip-upstream-download!' => \$skip_upstream_download,
|
||||
'build-timestamp=i' => \$build_timestamp,
|
||||
) or die usage();
|
||||
|
||||
die "Run as root (current uid=$>)\n" if $> != 0;
|
||||
@@ -64,6 +66,19 @@ my $mock_uniqueext_opt = $mock_uniqueext ne ''
|
||||
? ' --uniqueext ' . sh_quote($mock_uniqueext)
|
||||
: '';
|
||||
|
||||
my $SOURCE_DATE_EPOCH;
|
||||
$SOURCE_DATE_EPOCH = $build_timestamp if defined $build_timestamp;
|
||||
if (!$SOURCE_DATE_EPOCH && -f "$repo_root/Gitepoch") {
|
||||
$SOURCE_DATE_EPOCH = slurp("$repo_root/Gitepoch");
|
||||
chomp $SOURCE_DATE_EPOCH;
|
||||
}
|
||||
unless ($SOURCE_DATE_EPOCH && $SOURCE_DATE_EPOCH =~ /^\d+$/) {
|
||||
$SOURCE_DATE_EPOCH = `git -C \Q$repo_root\E log -1 --format=%ct HEAD 2>/dev/null`;
|
||||
chomp $SOURCE_DATE_EPOCH;
|
||||
}
|
||||
$SOURCE_DATE_EPOCH = time() unless $SOURCE_DATE_EPOCH =~ /^\d+$/;
|
||||
$ENV{SOURCE_DATE_EPOCH} = $SOURCE_DATE_EPOCH;
|
||||
|
||||
print_step("Configuration");
|
||||
print "repo_root: $repo_root\n";
|
||||
print "pkg_dir: $pkg_dir\n";
|
||||
@@ -115,6 +130,7 @@ my $prep_top = "$work_dir/prep";
|
||||
for my $d (qw(BUILD BUILDROOT RPMS SOURCES SPECS SRPMS)) {
|
||||
make_path("$prep_top/$d");
|
||||
}
|
||||
my $det_mock_cfg = create_deterministic_mock_cfg($mock_cfg, $SOURCE_DATE_EPOCH, $work_dir);
|
||||
copy($spec_file, "$prep_top/SPECS/syslinux-xcat.spec")
|
||||
or die "Failed to copy spec to prep topdir: $!\n";
|
||||
for my $asset (@all_assets) {
|
||||
@@ -136,10 +152,13 @@ print_step("Build SRPM with mock");
|
||||
my $srpm_out = "$work_dir/srpm";
|
||||
make_path($srpm_out);
|
||||
run(
|
||||
"mock -r " . sh_quote($mock_cfg) . $mock_uniqueext_opt .
|
||||
"mock -r " . sh_quote($det_mock_cfg) . $mock_uniqueext_opt .
|
||||
" --buildsrpm --spec " . sh_quote($spec_file) .
|
||||
" --sources " . sh_quote($pkg_dir) .
|
||||
" --resultdir " . sh_quote($srpm_out)
|
||||
" --resultdir " . sh_quote($srpm_out) .
|
||||
" --define " . sh_quote("use_source_date_epoch_as_buildtime 1") .
|
||||
" --define " . sh_quote("clamp_mtime_to_source_date_epoch 1") .
|
||||
" --define " . sh_quote("_buildhost xcat-build")
|
||||
);
|
||||
|
||||
my @srpms = sort glob("$srpm_out/*.src.rpm");
|
||||
@@ -151,9 +170,12 @@ print_step("Rebuild RPM with mock");
|
||||
my $rpm_out = "$work_dir/rpm";
|
||||
make_path($rpm_out);
|
||||
run(
|
||||
"mock -r " . sh_quote($mock_cfg) . $mock_uniqueext_opt .
|
||||
"mock -r " . sh_quote($det_mock_cfg) . $mock_uniqueext_opt .
|
||||
" --rebuild " . sh_quote($srpm) .
|
||||
" --resultdir " . sh_quote($rpm_out)
|
||||
" --resultdir " . sh_quote($rpm_out) .
|
||||
" --define " . sh_quote("use_source_date_epoch_as_buildtime 1") .
|
||||
" --define " . sh_quote("clamp_mtime_to_source_date_epoch 1") .
|
||||
" --define " . sh_quote("_buildhost xcat-build")
|
||||
);
|
||||
|
||||
my @all_rpms = sort glob("$rpm_out/*.rpm");
|
||||
@@ -265,11 +287,23 @@ Usage: $0 [options]
|
||||
--mock-uniqueext TXT Optional mock --uniqueext suffix to isolate concurrent builds
|
||||
--result-dir PATH Output RPM/SRPM directory (default: $result_dir)
|
||||
--log-dir PATH Log directory (default: $log_dir)
|
||||
--build-timestamp EPOCH SOURCE_DATE_EPOCH for deterministic builds
|
||||
--skip-upstream-download Skip wget download step
|
||||
--skip-install Skip dnf install + smoke tests
|
||||
USAGE
|
||||
}
|
||||
|
||||
sub create_deterministic_mock_cfg {
|
||||
my ($base_cfg, $epoch, $dir) = @_;
|
||||
my $cfg_path = "$dir/mock-deterministic.cfg";
|
||||
open my $fh, '>', $cfg_path or die "Cannot write $cfg_path: $!\n";
|
||||
print $fh "include('/etc/mock/${base_cfg}.cfg')\n";
|
||||
print $fh "config_opts['environment']['SOURCE_DATE_EPOCH'] = '$epoch'\n";
|
||||
print $fh "config_opts['environment']['ZERO_AR_DATE'] = '1'\n";
|
||||
close $fh;
|
||||
return $cfg_path;
|
||||
}
|
||||
|
||||
sub parse_spec {
|
||||
my ($path) = @_;
|
||||
open my $fh, '<', $path or die "Cannot open spec $path: $!\n";
|
||||
|
||||
+9
-1
@@ -1,3 +1,11 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
dpkg-buildpackage -uc -us -R./build/rules.fromBIN
|
||||
if [ -z "${SOURCE_DATE_EPOCH:-}" ]; then
|
||||
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
if [ -f "$REPO_ROOT/Gitepoch" ]; then
|
||||
export SOURCE_DATE_EPOCH=$(cat "$REPO_ROOT/Gitepoch")
|
||||
fi
|
||||
fi
|
||||
|
||||
dpkg-buildpackage -uc -us -R./build/rules.fromBIN
|
||||
|
||||
+28
-2
@@ -20,6 +20,7 @@ my $mock_uniqueext = '';
|
||||
my $result_dir = "$repo_root/build-output/list3/xnba-undi";
|
||||
my $log_dir = "$repo_root/build-logs/list3/xnba-undi";
|
||||
my $skip_install = 0;
|
||||
my $build_timestamp;
|
||||
|
||||
GetOptions(
|
||||
'work-dir=s' => \$work_dir,
|
||||
@@ -28,6 +29,7 @@ GetOptions(
|
||||
'result-dir=s' => \$result_dir,
|
||||
'log-dir=s' => \$log_dir,
|
||||
'skip-install!' => \$skip_install,
|
||||
'build-timestamp=i' => \$build_timestamp,
|
||||
) or die usage();
|
||||
|
||||
die "Run as root (current uid=$>)\n" if $> != 0;
|
||||
@@ -46,6 +48,24 @@ if (!$mock_cfg) {
|
||||
$mock_cfg = resolve_mock_cfg($os_id, '10', $arch);
|
||||
}
|
||||
|
||||
my $SOURCE_DATE_EPOCH;
|
||||
$SOURCE_DATE_EPOCH = $build_timestamp if defined $build_timestamp;
|
||||
if (!$SOURCE_DATE_EPOCH && -f "$repo_root/Gitepoch") {
|
||||
my $epoch_content = '';
|
||||
if (open my $efh, '<', "$repo_root/Gitepoch") {
|
||||
$epoch_content = <$efh>;
|
||||
close $efh;
|
||||
chomp $epoch_content;
|
||||
}
|
||||
$SOURCE_DATE_EPOCH = $epoch_content;
|
||||
}
|
||||
unless ($SOURCE_DATE_EPOCH && $SOURCE_DATE_EPOCH =~ /^\d+$/) {
|
||||
$SOURCE_DATE_EPOCH = `git -C \Q$repo_root\E log -1 --format=%ct HEAD 2>/dev/null`;
|
||||
chomp $SOURCE_DATE_EPOCH;
|
||||
}
|
||||
$SOURCE_DATE_EPOCH = time() unless $SOURCE_DATE_EPOCH =~ /^\d+$/;
|
||||
$ENV{SOURCE_DATE_EPOCH} = $SOURCE_DATE_EPOCH;
|
||||
|
||||
print_step("Configuration");
|
||||
print "repo_root: $repo_root\n";
|
||||
print "pkg_dir: $pkg_dir\n";
|
||||
@@ -60,7 +80,8 @@ make_path($log_dir);
|
||||
|
||||
print_step("Stage build environment");
|
||||
remove_tree($work_dir) if -d $work_dir;
|
||||
my $rpmbuild_top = "$work_dir/rpmbuild";
|
||||
my $rpmbuild_top = "/var/tmp/xcat-rpmbuild-xnba";
|
||||
remove_tree($rpmbuild_top) if -d $rpmbuild_top;
|
||||
for my $d (qw(BUILD BUILDROOT RPMS SOURCES SPECS SRPMS)) {
|
||||
make_path("$rpmbuild_top/$d");
|
||||
}
|
||||
@@ -75,7 +96,8 @@ copy("$binary_dir/xnba.efi", "$src_dir/binary/xnba.efi")
|
||||
or die "Failed to copy xnba.efi: $!\n";
|
||||
|
||||
my $tarball = "$rpmbuild_top/SOURCES/xnba-$version.tar.gz";
|
||||
run("tar -C " . sh_quote($work_dir) . " -czf " . sh_quote($tarball) . " xnba-$version");
|
||||
run("tar --sort=name --owner=0 --group=0 --mtime=\@$SOURCE_DATE_EPOCH" .
|
||||
" -C " . sh_quote($work_dir) . " -czf " . sh_quote($tarball) . " xnba-$version");
|
||||
|
||||
# Create simplified spec that uses pre-built binaries
|
||||
my $simple_spec = <<'SPEC';
|
||||
@@ -120,6 +142,9 @@ print_step("Build RPM");
|
||||
my $rpmbuild_cmd = join(' ',
|
||||
'rpmbuild',
|
||||
'--define', sh_quote("_topdir $rpmbuild_top"),
|
||||
'--define', sh_quote("use_source_date_epoch_as_buildtime 1"),
|
||||
'--define', sh_quote("clamp_mtime_to_source_date_epoch 1"),
|
||||
'--define', sh_quote("_buildhost xcat-build"),
|
||||
'-ba',
|
||||
sh_quote("$rpmbuild_top/SPECS/xnba-undi.spec"),
|
||||
);
|
||||
@@ -149,6 +174,7 @@ Options:
|
||||
--result-dir PATH Output directory for RPMs
|
||||
--log-dir PATH Output directory for logs
|
||||
--skip-install Skip install verification
|
||||
--build-timestamp EPOCH Unix timestamp for reproducible builds
|
||||
USAGE
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user