#!/usr/bin/perl -w # Test-AutoBuild: Continuous, unattended, automated software builds # # By Daniel P. Berrange # Copyright (C) 2002-2006 Daniel P. Berrange # # Based on Rolling builds version 2.0 # # By Richard W.M. Jones # http://annexia.org/freeware/rollingbuild/ # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # $Id: auto-build,v 1.10 2007/12/08 21:03:02 danpb Exp $ use strict; use warnings; use Carp qw(confess cluck); use Data::Dumper; use File::Spec; use Getopt::Long; use Date::Manip; use Test::AutoBuild; use Test::AutoBuild::ErrorReport; my $config_file = File::Spec->catfile($ENV{HOME}, "auto-build.conf"); my $verbose = 0; my $debug = 0; my $help = 0; my $timestamp = time; # Handle command line arguments if (!GetOptions ('config=s' => \$config_file, 'timestamp=s' => \$timestamp, 'help+' => \$help, 'debug+' => \$debug, 'verbose+' => \$verbose) || $help) { &show_help($help ? \*STDOUT : \*STDERR); exit ($help ? 0 : 3); } # If timestamp is not an integer, then assume its a textual # date representation & convert it into a timestamp if ($timestamp !~ /^\d+$/) { my $date = ParseDate($timestamp); if (!$date) { print STDERR "Cannot parse timestamp string '$timestamp'\n"; &show_help(\*STDERR); exit 4; } $timestamp = UnixDate($date, "%s"); } # Validate the config file actually exists, and can be read! if (!-f $config_file) { print STDERR "Configuration file '$config_file' does not exist\n"; &show_help(\*STDERR); exit 4; } elsif (!-r _) { print STDERR "Configuration file '$config_file' cannot be read\n"; &show_help(\*STDERR); exit 4; } # Hook in some custom signal handlers for doing # random useful stuff $SIG{__DIE__} = sub { if (UNIVERSAL::isa($_[0], "Template::Exception")) { die $_[0]; } else { die Test::AutoBuild::ErrorReport->new(message => $_[0]); } }; if ($verbose) { $SIG{__WARN__} = sub { cluck $@ }; $Carp::MaxArgLen = 0; # Unlimited! } else { $Carp::MaxArgLen = 300; # Defaults to 64 which is lame with long filenames } $SIG{USR1} = sub { print STDERR Carp::longmess("Got SIG-USR1, generating stack trace"); }; # Finally run the build my $auto_build = Test::AutoBuild->new(config => $config_file, verbose => $verbose, debug => $debug); # Replace the original handler, so we can pull in $auto_build state $SIG{__DIE__} = sub { if (UNIVERSAL::isa($_[0], "Template::Exception")) { die $_[0]; } else { die Test::AutoBuild::ErrorReport->new(message => $_[0], engine => $auto_build); } }; # Another handy signal handler $SIG{USR2} = sub { print STDERR Carp::longmess("Got SIG-USR2, dumping runtime"); print STDERR Dumper($auto_build); }; $auto_build->run($timestamp); if ($auto_build->failed()) { if ($verbose) { print STDOUT "Build failed: ", $auto_build->log, "\n"; } exit 1; } elsif ($auto_build->aborted()) { my $error = $auto_build->log; print STDERR "\n"; print STDERR "A fatal error caused the build engine to abort:\n"; print STDERR "\n"; print STDERR " ", $error, "\n"; print STDERR "\n"; if (UNIVERSAL::isa($error, "Test::AutoBuild::ErrorReport")) { $error = $error->root_cause(); my $file = $error->log(); print STDERR "A full report of the problem has been saved in $file\n"; print STDERR "Please attach this file when filing a bug report\n"; print STDERR "\n"; } exit 2; } exit 0; sub show_help { my $fh = shift; print $fh < is the command used to execute the Test-AutoBuild software build automation framework. It is intended to execute a single iteration of the build engine and then quit with its exit status providing an indication of the build success / fail status (see the C section later in this manual page). To perform a continous automated build this command would be launched on a frequent basis from cron. Locking will ensure that two instances do not execute concurrently, so it can safely be triggered every 5 minutes. =head1 OPTIONS The following command line options are valid: =over 4 =item --config=FILE Specify an alternative path to the configuration file for the build process. If ommitted, will default to looking for the file $HOME/auto-build.conf. The configuration data is loaded by the L module, so refer to that module's manual page for details of permitted syntax. The file will also be pre-processed by the L