X-Git-Url: https://git.exim.org/buildfarm-server.git/blobdiff_plain/2c084dd5486f92cfee50ca4a078fc0342e9bf107..aee3d375b3fd228ea7bdc583b0bb9f3190927a9d:/cgi-bin/pgstatus.pl diff --git a/cgi-bin/pgstatus.pl b/cgi-bin/pgstatus.pl index 603e15f..16ac79f 100755 --- a/cgi-bin/pgstatus.pl +++ b/cgi-bin/pgstatus.pl @@ -1,11 +1,20 @@ #!/usr/bin/perl +=comment + +Copyright (c) 2003-2010, Andrew Dunstan + +See accompanying License file for license details + +=cut + use strict; use vars qw($dbhost $dbname $dbuser $dbpass $dbport $all_stat $fail_stat $change_stat $green_stat $server_time $min_script_version $min_web_script_version + $default_host $local_git_clone ); # force this before we do anything - even load modules @@ -18,9 +27,11 @@ use DBI; use DBD::Pg; use Data::Dumper; use Mail::Send; -use Safe; +use Time::ParseDate; +use Storable qw(thaw); require "$ENV{BFConfDir}/BuildFarmWeb.pl"; +my $buildlogs = "$ENV{BFConfDir}/buildlogs"; die "no dbname" unless $dbname; die "no dbuser" unless $dbuser; @@ -44,6 +55,23 @@ my $branch = $query->param('branch'); my $changed_since_success = $query->param('changed_since_success'); my $changed_this_run = $query->param('changed_files'); my $log_archive = $query->param('logtar'); +my $frozen_sconf = $query->param('frozen_sconf') || ''; + +my $brhandle; +if (open($brhandle,"../htdocs/branches_of_interest.txt")) +{ + my @branches_of_interest = <$brhandle>; + close($brhandle); + chomp(@branches_of_interest); + unless (grep {$_ eq $branch} @branches_of_interest) + { + print + "Status: 492 bad branch parameter $branch\nContent-Type: text/plain\n\n", + "bad branch parameter $branch\n"; + exit; + } +} + my $content = "branch=$branch&res=$res&stage=$stage&animal=$animal&". @@ -62,6 +90,15 @@ unless ($animal && $ts && $stage && $sig) } +unless ($branch =~ /^(HEAD|REL\d+_\d+_STABLE)$/) +{ + print + "Status: 492 bad branch parameter $branch\nContent-Type: text/plain\n\n", + "bad branch parameter $branch\n"; + exit; + +} + my $db = DBI->connect($dsn,$dbuser,$dbpass); @@ -74,6 +111,8 @@ $sth->execute($animal); my ($secret)=$sth->fetchrow_array(); $sth->finish; +my $tsdiff = time - $ts; + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($ts); $year += 1900; $mon +=1; my $date= @@ -81,17 +120,19 @@ my $date= if ($ENV{BF_DEBUG} || ($ts > time) || ($ts + 86400 < time ) || (! $secret) ) { - open(TX,">../buildlogs/$animal.$date"); + open(TX,">$buildlogs/$animal.$date"); print TX "sig=$sig\nlogtar-len=" , length($log_archive), "\nstatus=$res\nstage=$stage\nconf:\n$conf\n", + "tsdiff:$tsdiff\n", "changed_this_run:\n$changed_this_run\n", "changed_since_success:\n$changed_since_success\n", + "frozen_sconf:$frozen_sconf\n", "log:\n",$log; # $query->save(\*TX); close(TX); } -unless ($ts < time) +unless ($ts < time + 120) { my $gmt = gmtime($ts); print "Status: 491 bad ts parameter - $ts ($gmt GMT) is in the future.\n", @@ -136,7 +177,22 @@ if ($calc_sig ne $sig && $calc_sig2 ne $sig) # undo escape-proofing of base64 data and decode it map {tr/$@/+=/; $_ = decode_base64($_); } - ($log, $conf,$changed_this_run,$changed_since_success,$log_archive); + ($log, $conf,$changed_this_run,$changed_since_success,$log_archive, $frozen_sconf); + +if ($log =~/Last file mtime in snapshot: (.*)/) +{ + my $snaptime = parsedate($1); + my $brch = $branch eq 'HEAD' ? 'master' : $branch; + my $last_branch_time = time - (30 * 86400); + $last_branch_time = `TZ=UTC GIT_DIR=$local_git_clone git log -1 --pretty=format:\%ct $brch`; + if ($snaptime < ($last_branch_time - 86400)) + { + print "Status: 493 snapshot too old: $1\nContent-Type: text/plain\n\n"; + print "snapshot to old: $1\n"; + $db->disconnect; + exit; + } +} ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime($ts); $year += 1900; $mon +=1; @@ -145,12 +201,14 @@ my $dbdate= my $log_file_names; my @log_file_names; -my $dirname = "../buildlogs/tmp.$$.unpacklogs"; +my $dirname = "$buildlogs/tmp.$$.unpacklogs"; + +my $githeadref; if ($log_archive) { my $log_handle; - my $archname = "../buildlogs/tmp.$$.tgz"; + my $archname = "$buildlogs/tmp.$$.tgz"; open($log_handle,">$archname"); binmode $log_handle; print $log_handle $log_archive; @@ -158,26 +216,33 @@ if ($log_archive) mkdir $dirname; @log_file_names = `tar -z -C $dirname -xvf $archname 2>/dev/null`; map {s/\s+//g; } @log_file_names; - my @qnames = @log_file_names; + my @qnames = grep { $_ ne 'githead.log' } @log_file_names; map { $_ = qq("$_"); } @qnames; $log_file_names = '{' . join(',',@qnames) . '}'; + if (-e "$dirname/githead.log" ) + { + open(my $githead,"$dirname/githead.log"); + $githeadref = <$githead>; + chomp $githeadref; + close $githead; + } # unlink $archname; } my $config_flags; -my $container = new Safe; -my $sconf = $conf; -unless ($sconf =~ s/.*(\$Script_Config)/$1/ms ) +my $client_conf; +if ($frozen_sconf) { - $sconf = '$Script_Config={};'; + $client_conf = thaw $frozen_sconf; } -my $client_conf = $container->reval("$sconf;"); if ($min_script_version) { $client_conf->{script_version} ||= '0.0'; + my $cli_ver = $client_conf->{script_version} ; + $cli_ver =~ s/^REL_//; my ($minmajor,$minminor) = split(/\./,$min_script_version); - my ($smajor,$sminor) = split(/\./,$client_conf->{script_version}); + my ($smajor,$sminor) = split(/\./,$cli_ver); if ($minmajor > $smajor || ($minmajor == $smajor && $minminor > $sminor)) { print "Status: 460 script version too low\nContent-Type: text/plain\n\n"; @@ -193,15 +258,18 @@ if ($min_script_version) if ($min_web_script_version) { $client_conf->{web_script_version} ||= '0.0'; - my ($minmajor,$minminor) = split(/\./,$min_script_version); - my ($smajor,$sminor) = split(/\./,$client_conf->{script_version}); + my $cli_ver = $client_conf->{web_script_version} ; + $cli_ver =~ s/^REL_//; + my ($minmajor,$minminor) = split(/\./,$min_web_script_version); + my ($smajor,$sminor) = split(/\./,$cli_ver); if ($minmajor > $smajor || ($minmajor == $smajor && $minminor > $sminor)) { print "Status: 461 web script version too low\nContent-Type: text/plain\n\n"; print "Web Script version is below minimum required\n", - "Reported version: $client_conf->{web_script_version},", - "Minumum version required: $min_web_script_version\n"; + "Reported version: $client_conf->{web_script_version}, ", + "Minumum version required: $min_web_script_version\n" + ; $db->disconnect; exit; } @@ -227,23 +295,39 @@ if (@config_flags) { @config_flags = grep {! m/=/ } @config_flags; map {s/\s+//g; $_=qq("$_"); } @config_flags; + push @config_flags,'git' if $client_conf->{scm} eq 'git'; $config_flags = '{' . join(',',@config_flags) . '}' ; } +my $scm = $client_conf->{scm} || 'cvs'; +my $scmurl = $client_conf->{scm_url}; my $logst = <begin_work; +$db->do("select set_local_error_terse()"); + + $sth=$db->prepare($logst); $sth->bind_param(1,$animal); $sth->bind_param(2,$dbdate); -$sth->bind_param(3,$res); +$sth->bind_param(3,$res & 0x8fffffff); # in case we get a 64 bit int status! $sth->bind_param(4,$stage); $sth->bind_param(5,$log); $sth->bind_param(6,$conf); @@ -254,40 +338,66 @@ $sth->bind_param(10,$log_file_names); #$sth->bind_param(11,$log_archive,{ pg_type => DBD::Pg::PG_BYTEA }); $sth->bind_param(11,undef,{ pg_type => DBD::Pg::PG_BYTEA }); $sth->bind_param(12,$config_flags); +$sth->bind_param(13,$scm); +$sth->bind_param(14,$scmurl); +$sth->bind_param(15,$githeadref); +$sth->bind_param(16,$frozen_sconf,{ pg_type => DBD::Pg::PG_BYTEA }); -$sth->execute; -$sth->finish; +$sqlres = $sth->execute; -my $logst2 = <finish; -EOSQL - ; + my $logst2 = q{ + + insert into build_status_log + (sysname, snapshot, branch, log_stage, log_text, stage_duration) + values (?, ?, ?, ?, ?, ?) + + }; + + $sth = $db->prepare($logst2); + + $/=undef; + + my $stage_start = $ts; -$sth = $db->prepare($logst2); + foreach my $log_file( @log_file_names ) + { + next if $log_file =~ /^githead/; + my $handle; + open($handle,"$dirname/$log_file"); + my $mtime = (stat $handle)[9]; + my $stage_interval = $mtime - $stage_start; + $stage_start = $mtime; + my $ltext = <$handle>; + close($handle); + $ltext =~ s/\x00/\\0/g; + $sqlres = $sth->execute($animal,$dbdate,$branch,$log_file,$ltext, + "$stage_interval seconds"); + last unless $sqlres; + } -$/=undef; + $sth->finish unless $sqlres; -my $stage_start = $ts; +} -foreach my $log_file( @log_file_names ) +if (! $sqlres) { - my $handle; - open($handle,"$dirname/$log_file"); - my $mtime = (stat $handle)[9]; - my $stage_interval = $mtime - $stage_start; - $stage_start = $mtime; - my $ltext = <$handle>; - close($handle); - $sth->execute($animal,$dbdate,$branch,$log_file,$ltext, - "$stage_interval seconds"); + + print "Status: 462 database failure\nContent-Type: text/plain\n\n"; + print "Your report generated a database failure:\n", + $db->errstr, + "\n"; + $db->rollback; + $db->disconnect; + exit; } -$sth->finish; +$db->commit; my $prevst = <fetchrow_arrayref; my ($os, $compiler,$arch) = @$row; $sth->finish; - $db->begin_work; -$db->do("truncate dashboard_mat"); +# prevent occasional duplication by forcing serialization of this operation +$db->do("lock table dashboard_mat in share row exclusive mode"); +$db->do("delete from dashboard_mat"); $db->do("insert into dashboard_mat select * from dashboard_mat_data"); $db->commit; +if ($stage ne 'OK') +{ + $db->begin_work; + # prevent occasional duplication by forcing serialization of this operation + $db->do("lock table nrecent_failures in share row exclusive mode"); + $db->do("delete from nrecent_failures"); + $db->do("insert into nrecent_failures select bs.sysname, bs.snapshot, bs.branch from build_status bs where bs.stage <> 'OK' and bs.snapshot > now() - interval '90 days'"); + $db->commit; +} + $db->disconnect; print "Content-Type: text/plain\n\n"; @@ -339,7 +460,7 @@ my $client_events = $client_conf->{mail_events}; if ($ENV{BF_DEBUG}) { my $client_time = $client_conf->{current_ts}; - open(TX,">>../buildlogs/$animal.$date"); + open(TX,">>$buildlogs/$animal.$date"); print TX "\n",Dumper(\$client_conf),"\n"; print TX "server time: $server_time, client time: $client_time\n" if $client_time; close(TX); @@ -402,17 +523,21 @@ my $stat_type = $stage eq 'OK' ? 'Status' : 'Failed at Stage'; my $mailto = [@$all_stat]; push(@$mailto,@$fail_stat) if $stage ne 'OK'; -my $me = `id -un`; chomp $me; +my $me = `id -un`; chomp($me); + +my $host = `hostname`; chomp ($host); +$host = $default_host unless ($host =~ m/[.]/ || !defined($default_host)); -my $host = `hostname`; chomp $host; +my $from_addr = "PG Build Farm <$me\@$host>"; +$from_addr =~ tr /\r\n//d; my $msg = new Mail::Send; -$msg->set('From',"PG Build Farm <$me\@$host>"); $msg->to(@$mailto); $msg->bcc(@$bcc_stat) if (@$bcc_stat); $msg->subject("PGBuildfarm member $animal Branch $branch $stat_type $stage"); +$msg->set('From',$from_addr); my $fh = $msg->open; print $fh <set('From',"PG Build Farm <$me\@$host>"); $msg->to(@$mailto); $msg->bcc(@$bcc_chg) if (@$bcc_chg); @@ -452,6 +576,7 @@ $stat_type = "New member: $stage" if $prev_stat eq 'NEW'; $stat_type .= " failure" if $stage ne 'OK'; $msg->subject("PGBuildfarm member $animal Branch $branch Status $stat_type"); +$msg->set('From',$from_addr); $fh = $msg->open; print $fh <