mirror of
https://github.com/xcat2/xcat-dep.git
synced 2026-09-12 12:36:23 +00:00
206 lines
7.1 KiB
Python
Executable File
206 lines
7.1 KiB
Python
Executable File
#!/usr/bin/perl
|
|
|
|
use strict;
|
|
use warnings;
|
|
|
|
use Cwd qw(abs_path);
|
|
use File::Basename qw(basename dirname);
|
|
use File::Copy qw(copy);
|
|
use File::Path qw(make_path);
|
|
use File::Temp qw(tempdir);
|
|
use FindBin;
|
|
use Getopt::Long qw(GetOptions);
|
|
use POSIX qw(strftime);
|
|
use lib "$FindBin::Bin/../lib";
|
|
use XCAT::BuildUtils qw(
|
|
capture_command
|
|
digest_manifest
|
|
read_first_line
|
|
relative_files
|
|
run_command
|
|
write_binary
|
|
);
|
|
use XCAT::GenesisRelease qw(
|
|
architectures
|
|
deb_package_name
|
|
rpm_package_name
|
|
validate_architecture
|
|
validate_release
|
|
);
|
|
|
|
my $repo_root = abs_path("$FindBin::Bin/..");
|
|
my $xcat_source = "$repo_root/../xcat-core";
|
|
my $xcat_ref = '';
|
|
my $output_dir = '';
|
|
my $work_dir = '';
|
|
my $format = 'all';
|
|
my $all = 0;
|
|
my @requested_architectures;
|
|
|
|
GetOptions(
|
|
'xcat-source=s' => \$xcat_source,
|
|
'xcat-ref=s' => \$xcat_ref,
|
|
'output-dir=s' => \$output_dir,
|
|
'work-dir=s' => \$work_dir,
|
|
'format=s' => \$format,
|
|
'architecture=s@' => \@requested_architectures,
|
|
'all!' => \$all,
|
|
) or die usage();
|
|
|
|
die "Unsupported package format: $format\n"
|
|
unless $format eq 'all' || $format eq 'rpm' || $format eq 'deb';
|
|
die "Use either --all or --architecture\n" if $all && @requested_architectures;
|
|
@requested_architectures = architectures() if $all;
|
|
@requested_architectures = ('x86_64') unless @requested_architectures;
|
|
|
|
my %seen;
|
|
@requested_architectures = grep { !$seen{$_}++ } @requested_architectures;
|
|
validate_architecture($_) for @requested_architectures;
|
|
my %requested = map { $_ => 1 } @requested_architectures;
|
|
@requested_architectures = grep { $requested{$_} } architectures();
|
|
umask(0022);
|
|
|
|
$xcat_source = abs_path($xcat_source) or die "Cannot resolve xcat-core source\n";
|
|
for my $path (qw(Version xCAT-genesis-builder/oe/build xCAT-genesis-builder/oe/export)) {
|
|
die "xcat-core source is missing $path\n" unless -f "$xcat_source/$path";
|
|
}
|
|
die "xcat-core checkout is not clean\n"
|
|
if capture_command('git', '-C', $xcat_source, 'status', '--porcelain') ne '';
|
|
|
|
my $revision = capture_command('git', '-C', $xcat_source, 'rev-parse', 'HEAD');
|
|
die "Invalid xcat-core revision: $revision\n" unless $revision =~ /^[0-9a-f]{40}$/;
|
|
if ($xcat_ref ne '') {
|
|
die "Invalid xcat-core ref: $xcat_ref\n" unless $xcat_ref =~ /^[A-Za-z0-9][A-Za-z0-9._\/-]*$/;
|
|
my $expected = capture_command(
|
|
'git', '-C', $xcat_source, 'rev-parse', '--verify', "$xcat_ref^{commit}",
|
|
);
|
|
die "xcat-core HEAD $revision does not match $xcat_ref ($expected)\n"
|
|
unless $revision eq $expected;
|
|
}
|
|
|
|
my $version = read_first_line("$xcat_source/Version");
|
|
die "Invalid xCAT version: $version\n" unless $version =~ /^\d+(?:\.\d+){1,3}$/;
|
|
my $source_date_epoch = capture_command(
|
|
'git', '-C', $xcat_source, 'show', '-s', '--format=%ct', 'HEAD',
|
|
);
|
|
die "Invalid xcat-core commit time\n" unless $source_date_epoch =~ /^\d+$/;
|
|
my $release = strftime('snap%Y%m%d%H%M', gmtime($source_date_epoch));
|
|
|
|
if ($output_dir eq '') {
|
|
$output_dir = "$repo_root/build-output/genesis-openembedded/$version-$release";
|
|
}
|
|
my $output_parent = dirname($output_dir);
|
|
make_path($output_parent) unless -d $output_parent;
|
|
$output_parent = abs_path($output_parent) or die "Cannot resolve output parent\n";
|
|
$output_dir = "$output_parent/" . basename($output_dir);
|
|
die "Output already exists: $output_dir\n" if -e $output_dir || -l $output_dir;
|
|
|
|
my $work = tempdir('xcat-genesis-release.XXXXXX', TMPDIR => 1, CLEANUP => 1);
|
|
my $staging = tempdir('.xcat-genesis-release.XXXXXX', DIR => $output_parent, CLEANUP => 1);
|
|
my $oe_work;
|
|
if ($work_dir ne '') {
|
|
make_path($work_dir) unless -d $work_dir;
|
|
$work_dir = abs_path($work_dir) or die "Cannot resolve work directory\n";
|
|
$oe_work = "$work_dir/openembedded";
|
|
} else {
|
|
$oe_work = "$work/openembedded";
|
|
}
|
|
my $oe_tmp = "$oe_work/build/tmp";
|
|
local $ENV{XCAT_GENESIS_WORK_DIR} = $oe_work;
|
|
{
|
|
local $ENV{TMPDIR} = $oe_tmp;
|
|
make_path($oe_tmp);
|
|
run_command("$xcat_source/xCAT-genesis-builder/oe/build", @requested_architectures);
|
|
}
|
|
my $effective_deploy = "$oe_tmp/deploy";
|
|
die "Invalid OpenEmbedded deploy directory: $effective_deploy\n"
|
|
unless -d $effective_deploy && !-l $effective_deploy;
|
|
|
|
for my $architecture (@requested_architectures) {
|
|
my $export = "$work/exports/$architecture";
|
|
make_path(dirname($export));
|
|
run_command(
|
|
"$xcat_source/xCAT-genesis-builder/oe/export",
|
|
$architecture, $effective_deploy, $export,
|
|
);
|
|
|
|
my $packages = "$work/packages/$architecture";
|
|
run_command(
|
|
"$FindBin::Bin/package",
|
|
'--architecture', $architecture,
|
|
'--export-dir', $export,
|
|
'--output-dir', $packages,
|
|
'--version', $version,
|
|
'--release', $release,
|
|
'--revision', $revision,
|
|
'--source-date-epoch', $source_date_epoch,
|
|
'--format', $format,
|
|
);
|
|
_collect_packages($packages, $staging, $architecture);
|
|
}
|
|
|
|
my @formats = $format eq 'all' ? qw(deb rpm) : ($format);
|
|
write_binary(
|
|
"$staging/release.manifest",
|
|
"format=xcat-genesis-packages\n"
|
|
. "version=1\n"
|
|
. "xcat_version=$version\n"
|
|
. "xcat_release=$release\n"
|
|
. "xcat_revision=$revision\n"
|
|
. "source_date_epoch=$source_date_epoch\n"
|
|
. "architectures=" . join(',', @requested_architectures) . "\n"
|
|
. "formats=" . join(',', @formats) . "\n",
|
|
);
|
|
my @release_files = grep { $_ ne 'SHA256SUMS' } relative_files($staging);
|
|
write_binary(
|
|
"$staging/SHA256SUMS",
|
|
digest_manifest($staging, 'sha256', @release_files),
|
|
);
|
|
validate_release($staging);
|
|
my @verify_args = ('--format', $format);
|
|
push(@verify_args, '--complete') if $all;
|
|
run_command("$FindBin::Bin/verify-release", @verify_args, $staging);
|
|
|
|
chmod(0755, $staging) or die "Cannot make release directory readable: $!\n";
|
|
rename($staging, $output_dir) or die "Cannot publish $output_dir: $!\n";
|
|
print "Built Genesis package release in $output_dir\n";
|
|
|
|
sub _collect_packages {
|
|
my ($source, $destination, $architecture) = @_;
|
|
if ($format eq 'all' || $format eq 'rpm') {
|
|
my $name = rpm_package_name($architecture);
|
|
_collect_one(
|
|
"$source/rpm/$name-$version-$release.noarch.rpm",
|
|
"$destination/rpm",
|
|
);
|
|
_collect_one(
|
|
"$source/srpm/$name-$version-$release.src.rpm",
|
|
"$destination/srpm",
|
|
);
|
|
}
|
|
if ($format eq 'all' || $format eq 'deb') {
|
|
my $name = deb_package_name($architecture);
|
|
_collect_one(
|
|
"$source/deb/${name}_${version}-${release}_all.deb",
|
|
"$destination/deb",
|
|
);
|
|
}
|
|
}
|
|
|
|
sub _collect_one {
|
|
my ($source, $directory) = @_;
|
|
die "Missing package artifact: $source\n" unless -f $source && !-l $source;
|
|
make_path($directory) unless -d $directory;
|
|
my $destination = "$directory/" . basename($source);
|
|
die "Duplicate package artifact: $destination\n" if -e $destination || -l $destination;
|
|
copy($source, $destination) or die "Cannot collect $source: $!\n";
|
|
}
|
|
|
|
sub usage {
|
|
return <<'USAGE';
|
|
Usage: build [--xcat-source DIR] [--xcat-ref REF] [--output-dir DIR]
|
|
[--work-dir DIR]
|
|
[--format all|rpm|deb] [--architecture ARCH ... | --all]
|
|
USAGE
|
|
}
|