CUFP
stevieb
<p>Recently, in [id://1154398], I said I was working on a script that automates multiple test builds of a module against a number of Perlbrew instances. Below are the <c>brew_build.pl</c> (brew control) script and the <c>test.pl</c> (test runner) script, and here's the [https://github.com/stevieb9/p5-brew-build-script|git repo].</p>
<p>This works on all platforms I've tested it on (FreeBSD, Linux and Windows). For *nix, you need to have Perlbrew installed. On Windows, [https://github.com/dnmfarrell/berrybrew|Berrybrew] is required. You'll also require <c>cpanm</c> from [doc://App::cpanminus].</p>
<p>The reasoning behind this creation is due to the fact [https://travis-ci.org|Travis CI] only performs builds on Linux machines, and I wanted an easy way to perform release candidate builds on Windows as well in much the same manner.</p>
<p>It was rather quickly slapped together, but it's simply a prototype. Now that I know it works pretty well, I'm going to turn it into a proper Test module.</p>
<p>In your module, create a <c>build</c> directory in the root, and drop these two files into it. Here are some usage examples:</p>
<p>Run unit tests on all currently installed perl versions:</p>
<c>
perl build/brew_build.pl
</c>
<p>Remove all currently installed perl instances (except the one you're using), and install three new random versions, and run tests on those pristine instances (short forms for args (eg: <c>-c</c> for <c>--count</c>) are available:</p>
<c>
perl build/brew_build.pl --reload 1 --count 3
</c>
<p>Install all versions of perl available to Perlbrew, without removing existing instances, and enable verbose output:</p>
<c>
perl build/brew_build.pl -d 1 -c -1
</c>
<p>Install a specific version of perl, and run tests on all installed versions:</p>
<c>
perl build/brew_build.pl -v 5.20.1
</c>
<p>Example output (note that if one perlbrew instance fails tests, all processing stops (<c>exit;</c>) and the actual test output for the failed build is displayed along with the perl version so you can further investigate. Otherwise, on success:</p>
<c>
% perl build/brew_build.pl
perl-5.23.7
perl-5.22.1
perl-5.20.3
perl-5.18.4
perl-5.14.4
perl-5.12.5
perl-5.12.5 :: PASS
perl-5.14.4 :: PASS
perl-5.18.4 :: PASS
perl-5.20.3 :: PASS
perl-5.22.1 :: PASS
perl-5.23.7 :: PASS
</c>
<p><b>brew_build.pl</b></p>
<c>
#!/usr/bin/perl
use warnings;
use strict;
use Cwd;
use Getopt::Long;
my ($debug, $count, $reload, $version, $help);
GetOptions(
"debug=i" => \$debug,
"count=i" => \$count,
"reload=i" => \$reload,
"version=s" => \$version,
"help" => \$help,
);
if ($help){
print <<EOF;
Usage: perl build/brewbuild.pl [options]
Options:
--debug | -d: Bool, enable verbosity
--count | -c: Integer, how many random versions of perl to install.
Send in -1 to install all available versions.
--reload | -r: Bool, remove all installed perls (less the current one)
before installation of new ones
--verion | -v: String, the number portion of an available perl version
according to "perlbrew available" Note that only one is
allowed at this time
--help | -h: print this help message
EOF
exit;
}
my $cwd = getcwd();
my $is_win = 0;
$is_win = 1 if $^O =~ /Win/;
run($count);
sub perls_available {
my $brew_info = shift;
my @perls_available = $is_win
? $brew_info =~ /(\d\.\d+\.\d+_\d+)/g
: $brew_info =~ /(perl-\d\.\d+\.\d+)/g;
if ($is_win){
for (@perls_available){
s/perl-//;
}
}
return @perls_available;
}
sub perls_installed {
my $brew_info = shift;
return $is_win
? $brew_info =~ /(\d\.\d{2}\.\d(?:_\d{2}))(?!=_)\s+\[installed\]/ig
: $brew_info =~ /i.*?(perl-\d\.\d+\.\d+)/g;
}
sub instance_remove {
my @perls_installed = @_;
if ($debug) {
print "$_\n" for @perls_installed;
print "\nremoving previous installs...\n";
}
my $remove_cmd = $is_win
? 'berrybrew remove'
: 'perlbrew uninstall';
for (@perls_installed){
my $ver = $^V;
$ver =~ s/v//;
if ($_ =~ /$ver$/){
print "skipping version we're using, $_\n" if $debug;
next;
}
`$remove_cmd $_`;
}
print "\nremoval of existing perl installs complete...\n" if $debug;
}
sub instance_install {
my $count = shift;
my @perls_available = @_;
my $install_cmd = $is_win
? 'berrybrew install'
: 'perlbrew install --notest -j 4';
my @new_installs;
if ($version){
$version = $is_win ? $version : "perl-$version";
push @new_installs, $version;
}
else {
if ($count) {
while ($count > 0){
push @new_installs, $perls_available[rand @perls_available];
$count--;
}
}
}
if (@new_installs){
for (@new_installs){
print "\ninstalling $_...\n";
`$install_cmd $_`;
}
}
else {
print "\nusing existing versions only\n" if $debug;
}
}
sub results {
my $exec_cmd = $is_win
? "berrybrew exec perl $cwd\\build\\test.pl"
: "perlbrew exec perl $cwd/build/test.pl 2>/dev/null";
my $debug_exec_cmd = $is_win
? "berrybrew exec perl $cwd\\build\\test.pl"
: "perlbrew exec perl $cwd/build/test.pl";
my $result;
print "\n...executing\n" if $debug;
if ($is_win){
$result = `$exec_cmd`;
}
else {
if ($debug){
$result = `$debug_exec_cmd`;
}
else {
$result = `$exec_cmd`;
}
}
my @ver_results = split /\n\n\n/, $result;
print "\n\n";
for (@ver_results){
my $ver;
if (/^([Pp]erl-\d\.\d+\.\d+)/){
$ver = $1;
}
my $res;
if (/Result:\s+(PASS)/){
$res = $1;
}
else {
print $_;
exit;
}
print "$ver :: $res\n";
}
}
sub run {
my $count = shift // 0;
my $brew_info = $is_win
? `berrybrew available`
: `perlbrew available`;
my @perls_available = perls_available($brew_info);
$count = scalar @perls_available if $count < 0;
my @perls_installed = perls_installed($brew_info);
print "$_\n" for @perls_installed;
if ($debug){
print "$_ installed\n" for @perls_installed;
print "\n";
}
my %perl_vers;
instance_remove(@perls_installed) if $reload;
instance_install($count, @perls_available);
results();
}
</c>
<p><b>test.pl</b></p>
<c>
#!/usr/bin/perl
use warnings;
use strict;
use Cwd;
my $cwd = getcwd();
if ($^O ne 'MSWin32'){
system "cpanm --installdeps . && make && make test";
}
else {
system "cpanm --installdeps . && dmake && dmake test";
}
</c>