From 7696f262f27714edbcf520399a61be1dc7e3e158 Mon Sep 17 00:00:00 2001 From: Joshua Drake Date: Sun, 3 Dec 2006 03:12:58 +0000 Subject: [PATCH] Initial commit --- cgi-bin/.htaccess | 2 + cgi-bin/bfschmema | 274 ++++++++++++++++++ cgi-bin/envtest.pl | 15 + cgi-bin/get_bf_status_soap.pl | 30 ++ cgi-bin/newshowstat.pl | 33 +++ cgi-bin/pgstatus.pl | 401 ++++++++++++++++++++++++++ cgi-bin/register.pl | 154 ++++++++++ cgi-bin/show_history.pl | 156 +++++++++++ cgi-bin/show_history2.pl | 69 +++++ cgi-bin/show_log.pl | 327 ++++++++++++++++++++++ cgi-bin/show_members.pl | 163 +++++++++++ cgi-bin/show_stage_log.pl | 95 +++++++ cgi-bin/show_stage_log2.pl | 114 ++++++++ cgi-bin/show_status.pl | 231 +++++++++++++++ cgi-bin/show_status.pl.save | 153 ++++++++++ cgi-bin/show_status2.pl | 64 +++++ cgi-bin/show_status9.pl | 193 +++++++++++++ cgi-bin/show_status_soap.pl | 102 +++++++ cgi-bin/test.pl | 24 ++ cgi-bin/upgrade.pl | 149 ++++++++++ htdocs/bfweb.tgz | Bin 0 -> 163840 bytes htdocs/elephant-head_only.gif | Bin 0 -> 2523 bytes htdocs/elephant-icon.png | Bin 0 -> 219 bytes htdocs/elephant5.gif | Bin 0 -> 3434 bytes htdocs/elephant5a.gif | Bin 0 -> 3425 bytes htdocs/img/blank.gif | Bin 0 -> 807 bytes htdocs/img/bug.png | Bin 0 -> 928 bytes htdocs/img/camel.png | Bin 0 -> 215 bytes htdocs/img/cassert.png | Bin 0 -> 942 bytes htdocs/img/days.png | Bin 0 -> 226 bytes htdocs/img/kerberos.png | Bin 0 -> 993 bytes htdocs/img/krb.gif | Bin 0 -> 880 bytes htdocs/img/pam.png | Bin 0 -> 640 bytes htdocs/img/python.png | Bin 0 -> 306 bytes htdocs/img/ssl_icon.gif | Bin 0 -> 118 bytes htdocs/img/tcl.png | Bin 0 -> 229 bytes htdocs/img/threads.gif | Bin 0 -> 1051 bytes htdocs/img/translateicon.gif | Bin 0 -> 1048 bytes htdocs/inc/b/l.png | Bin 0 -> 2970 bytes htdocs/inc/b/r.png | Bin 0 -> 3058 bytes htdocs/inc/pgbf.css | 129 +++++++++ htdocs/inc/pgbuildfarm-banner.png | Bin 0 -> 21916 bytes htdocs/index.html | 63 +++++ htdocs/register.html | 108 +++++++ htdocs/robots.txt | 2 + schema/bfwebdb.sql | 450 ++++++++++++++++++++++++++++++ templates/bfwrapper.tt | 49 ++++ templates/bfwrapper.tt.ttc | 32 +++ templates/dashboard.tt | 77 +++++ templates/dashboard.tt.ttc | 312 +++++++++++++++++++++ templates/dyn/history.tt | 69 +++++ templates/dyn/status.tt | 80 ++++++ 52 files changed, 4120 insertions(+) create mode 100644 cgi-bin/.htaccess create mode 100644 cgi-bin/bfschmema create mode 100644 cgi-bin/envtest.pl create mode 100644 cgi-bin/get_bf_status_soap.pl create mode 100644 cgi-bin/newshowstat.pl create mode 100644 cgi-bin/pgstatus.pl create mode 100644 cgi-bin/register.pl create mode 100644 cgi-bin/show_history.pl create mode 100644 cgi-bin/show_history2.pl create mode 100644 cgi-bin/show_log.pl create mode 100644 cgi-bin/show_members.pl create mode 100644 cgi-bin/show_stage_log.pl create mode 100644 cgi-bin/show_stage_log2.pl create mode 100644 cgi-bin/show_status.pl create mode 100644 cgi-bin/show_status.pl.save create mode 100644 cgi-bin/show_status2.pl create mode 100644 cgi-bin/show_status9.pl create mode 100644 cgi-bin/show_status_soap.pl create mode 100644 cgi-bin/test.pl create mode 100644 cgi-bin/upgrade.pl create mode 100644 htdocs/bfweb.tgz create mode 100644 htdocs/elephant-head_only.gif create mode 100644 htdocs/elephant-icon.png create mode 100644 htdocs/elephant5.gif create mode 100644 htdocs/elephant5a.gif create mode 100644 htdocs/img/blank.gif create mode 100644 htdocs/img/bug.png create mode 100644 htdocs/img/camel.png create mode 100644 htdocs/img/cassert.png create mode 100644 htdocs/img/days.png create mode 100644 htdocs/img/kerberos.png create mode 100644 htdocs/img/krb.gif create mode 100644 htdocs/img/pam.png create mode 100644 htdocs/img/python.png create mode 100644 htdocs/img/ssl_icon.gif create mode 100644 htdocs/img/tcl.png create mode 100644 htdocs/img/threads.gif create mode 100644 htdocs/img/translateicon.gif create mode 100644 htdocs/inc/b/l.png create mode 100644 htdocs/inc/b/r.png create mode 100644 htdocs/inc/pgbf.css create mode 100644 htdocs/inc/pgbuildfarm-banner.png create mode 100644 htdocs/index.html create mode 100644 htdocs/register.html create mode 100644 htdocs/robots.txt create mode 100644 schema/bfwebdb.sql create mode 100644 templates/bfwrapper.tt create mode 100644 templates/bfwrapper.tt.ttc create mode 100644 templates/dashboard.tt create mode 100644 templates/dashboard.tt.ttc create mode 100644 templates/dyn/history.tt create mode 100644 templates/dyn/status.tt diff --git a/cgi-bin/.htaccess b/cgi-bin/.htaccess new file mode 100644 index 0000000..ead7338 --- /dev/null +++ b/cgi-bin/.htaccess @@ -0,0 +1,2 @@ +SetEnv BFConfDir /home/community/pgbuildfarm +SetEnv BF_DEBUG on diff --git a/cgi-bin/bfschmema b/cgi-bin/bfschmema new file mode 100644 index 0000000..1af2bcf --- /dev/null +++ b/cgi-bin/bfschmema @@ -0,0 +1,274 @@ +-- +-- PostgreSQL database dump +-- + +SET client_encoding = 'SQL_ASCII'; +SET check_function_bodies = false; + +SET SESSION AUTHORIZATION 'pgbuildfarm'; + +SET search_path = public, pg_catalog; + +-- +-- TOC entry 21 (OID 46831) +-- Name: plpgsql_call_handler(); Type: FUNC PROCEDURAL LANGUAGE; Schema: public; Owner: pgbuildfarm +-- + +CREATE FUNCTION plpgsql_call_handler() RETURNS language_handler + AS '$libdir/plpgsql', 'plpgsql_call_handler' + LANGUAGE c; + + +-- +-- TOC entry 22 (OID 46833) +-- Name: plperl_call_handler(); Type: FUNC PROCEDURAL LANGUAGE; Schema: public; Owner: pgbuildfarm +-- + +CREATE FUNCTION plperl_call_handler() RETURNS language_handler + AS '$libdir/plperl', 'plperl_call_handler' + LANGUAGE c; + + +SET SESSION AUTHORIZATION DEFAULT; + +-- +-- TOC entry 16 (OID 46832) +-- Name: plpgsql; Type: PROCEDURAL LANGUAGE; Schema: public; Owner: +-- + +CREATE TRUSTED PROCEDURAL LANGUAGE plpgsql HANDLER plpgsql_call_handler; + + +-- +-- TOC entry 17 (OID 46834) +-- Name: plperl; Type: PROCEDURAL LANGUAGE; Schema: public; Owner: +-- + +CREATE TRUSTED PROCEDURAL LANGUAGE plperl HANDLER plperl_call_handler; + + +-- +-- TOC entry 18 (OID 46835) +-- Name: plperlu; Type: PROCEDURAL LANGUAGE; Schema: public; Owner: +-- + +CREATE PROCEDURAL LANGUAGE plperlu HANDLER plperl_call_handler; + + +SET SESSION AUTHORIZATION 'pgbuildfarm'; + +-- +-- TOC entry 4 (OID 2200) +-- Name: public; Type: ACL; Schema: -; Owner: pgbuildfarm +-- + +REVOKE ALL ON SCHEMA public FROM PUBLIC; +GRANT ALL ON SCHEMA public TO PUBLIC; + + +SET SESSION AUTHORIZATION 'pgbuildfarm'; + +-- +-- TOC entry 7 (OID 17150) +-- Name: buildsystems; Type: TABLE; Schema: public; Owner: pgbuildfarm +-- + +CREATE TABLE buildsystems ( + name text NOT NULL, + secret text NOT NULL, + operating_system text NOT NULL, + os_version text NOT NULL, + compiler text NOT NULL, + compiler_version text NOT NULL, + architecture text NOT NULL, + status text NOT NULL, + sys_owner text NOT NULL, + owner_email text NOT NULL, + status_ts timestamp without time zone DEFAULT (('now'::text)::timestamp(6) with time zone)::timestamp without time zone +); + + +-- +-- TOC entry 8 (OID 17150) +-- Name: buildsystems; Type: ACL; Schema: public; Owner: pgbuildfarm +-- + +REVOKE ALL ON TABLE buildsystems FROM PUBLIC; +GRANT INSERT,SELECT ON TABLE buildsystems TO pgbfweb; + + +SET SESSION AUTHORIZATION 'pgbuildfarm'; + +-- +-- TOC entry 9 (OID 17155) +-- Name: build_status; Type: TABLE; Schema: public; Owner: pgbuildfarm +-- + +CREATE TABLE build_status ( + sysname text NOT NULL, + snapshot timestamp without time zone NOT NULL, + status integer, + stage text, + log text, + conf_sum text, + branch text, + changed_this_run text, + changed_since_success text, + log_archive bytea, + log_archive_filenames text[], + build_flags text[] +); + + +-- +-- TOC entry 10 (OID 17155) +-- Name: build_status; Type: ACL; Schema: public; Owner: pgbuildfarm +-- + +REVOKE ALL ON TABLE build_status FROM PUBLIC; +GRANT INSERT,SELECT ON TABLE build_status TO pgbfweb; + + +SET SESSION AUTHORIZATION 'pgbuildfarm'; + +-- +-- TOC entry 19 (OID 17160) +-- Name: approve(text, text); Type: FUNCTION; Schema: public; Owner: pgbuildfarm +-- + +CREATE FUNCTION approve(text, text) RETURNS void + AS 'update buildsystems set name = $2, status =''approved'' where name = $1 and status = ''pending''' + LANGUAGE sql; + + +-- +-- TOC entry 5 (OID 17162) +-- Name: pending; Type: TYPE; Schema: public; Owner: pgbuildfarm +-- + +CREATE TYPE pending AS ( + name text, + operating_system text, + os_version text, + compiler text, + compiler_version text, + architecture text, + owner_email text +); + + +-- +-- TOC entry 20 (OID 17164) +-- Name: approve2(text, text); Type: FUNCTION; Schema: public; Owner: pgbuildfarm +-- + +CREATE FUNCTION approve2(text, text) RETURNS text + AS ' update buildsystems set name = $2, status = ''approved'' where name = $1 and status = ''pending''; select owner_email || '':'' || name || '':'' || secret from buildsystems where name = $2;' + LANGUAGE sql; + + +-- +-- TOC entry 6 (OID 47855) +-- Name: pending2; Type: TYPE; Schema: public; Owner: pgbuildfarm +-- + +CREATE TYPE pending2 AS ( + name text, + operating_system text, + os_version text, + compiler text, + compiler_version text, + architecture text, + owner_email text, + "owner" text, + status_ts timestamp without time zone +); + + +-- +-- TOC entry 23 (OID 47857) +-- Name: pending(); Type: FUNCTION; Schema: public; Owner: pgbuildfarm +-- + +CREATE FUNCTION pending() RETURNS SETOF pending2 + AS 'select name,operating_system,os_version,compiler,compiler_version,architecture,owner_email, sys_owner, status_ts from buildsystems where status = ''pending'' order by status_ts ' + LANGUAGE sql; + + +-- +-- TOC entry 11 (OID 49741) +-- Name: list_subscriptions; Type: TABLE; Schema: public; Owner: pgbuildfarm +-- + +CREATE TABLE list_subscriptions ( + addr text +); + + +-- +-- TOC entry 24 (OID 55330) +-- Name: prevstat(text, text, timestamp without time zone); Type: FUNCTION; Schema: public; Owner: pgbuildfarm +-- + +CREATE FUNCTION prevstat(text, text, timestamp without time zone) RETURNS text + AS ' + select coalesce((select distinct on (snapshot) stage + from build_status + where sysname = $1 and branch = $2 and snapshot < $3 + order by snapshot desc + limit 1), ''NEW'') as prev_status +' + LANGUAGE sql; + + +-- +-- TOC entry 13 (OID 23365) +-- Name: bs_branch_snapshot_idx; Type: INDEX; Schema: public; Owner: pgbuildfarm +-- + +CREATE INDEX bs_branch_snapshot_idx ON build_status USING btree (branch, snapshot); + + +-- +-- TOC entry 14 (OID 23366) +-- Name: bs_sysname_branch_idx; Type: INDEX; Schema: public; Owner: pgbuildfarm +-- + +CREATE INDEX bs_sysname_branch_idx ON build_status USING btree (sysname, branch); + + +-- +-- TOC entry 12 (OID 23367) +-- Name: buildsystems_pkey; Type: CONSTRAINT; Schema: public; Owner: pgbuildfarm +-- + +ALTER TABLE ONLY buildsystems + ADD CONSTRAINT buildsystems_pkey PRIMARY KEY (name); + + +-- +-- TOC entry 15 (OID 23369) +-- Name: build_status_pkey; Type: CONSTRAINT; Schema: public; Owner: pgbuildfarm +-- + +ALTER TABLE ONLY build_status + ADD CONSTRAINT build_status_pkey PRIMARY KEY (sysname, snapshot); + + +-- +-- TOC entry 25 (OID 23371) +-- Name: bs_fk; Type: FK CONSTRAINT; Schema: public; Owner: pgbuildfarm +-- + +ALTER TABLE ONLY build_status + ADD CONSTRAINT bs_fk FOREIGN KEY (sysname) REFERENCES buildsystems(name) ON UPDATE CASCADE ON DELETE CASCADE; + + +-- +-- TOC entry 3 (OID 2200) +-- Name: SCHEMA public; Type: COMMENT; Schema: -; Owner: pgbuildfarm +-- + +COMMENT ON SCHEMA public IS 'Standard public schema'; + + diff --git a/cgi-bin/envtest.pl b/cgi-bin/envtest.pl new file mode 100644 index 0000000..6158d18 --- /dev/null +++ b/cgi-bin/envtest.pl @@ -0,0 +1,15 @@ +#!/usr/bin/perl + +print "Contect-Type: text/plain\n\n"; + +print "Conf: $ENV{BFConfDir}\n"; + +print `pwd`; + +print `id`; + +foreach my $key (sort keys %ENV) +{ + my $val = $ENV{$key}; + print "$key=$val\n"; +} diff --git a/cgi-bin/get_bf_status_soap.pl b/cgi-bin/get_bf_status_soap.pl new file mode 100644 index 0000000..02059e7 --- /dev/null +++ b/cgi-bin/get_bf_status_soap.pl @@ -0,0 +1,30 @@ +#!/usr/bin/perl + +use lib "/home/community/pgbuildfarm/lib/lib/perl5/site_perl"; + +use SOAP::Lite +trace; + +my $obj = SOAP::Lite + ->uri('http://www.pgbuildfarm.org/PGBuildFarm') + ->proxy('http://127.0.0.1/cgi-bin/show_status_soap.pl') + ->request->header("Host" => "www.pgbuildfarm.org") + ; + +my $data = $obj->get_status->result; +my @fields = qw( branch sysname stage status + operating_system os_version + compiler compiler_version architecture + when_ago snapshot build_flags + ); + +print "Content-Type: text/plain\n\n"; + +my $head = join (' | ', @fields); +print $head,"\n"; + +foreach my $datum (@$data) +{ + my $line = join (' | ', @{$datum}{@fields}); + print $line,"\n"; +} + diff --git a/cgi-bin/newshowstat.pl b/cgi-bin/newshowstat.pl new file mode 100644 index 0000000..80d4e62 --- /dev/null +++ b/cgi-bin/newshowstat.pl @@ -0,0 +1,33 @@ +#!/usr/bin/perl + +use strict; + +BEGIN +{ + $ENV{BFConfDir} ||= $ENV{HOME}; + require "$ENV{BFConfDir}/BuildFarmWeb.conf"; +} + +use lib $BuildFarmWeb::conf{libdir}; + +use BuildFarmWeb::Store qw(get_recent_status); + +use CGI; +use Template; + +my $template = new Template($BuildFarmWeb::conf{template_options}); + +my $query = new CGI; + +my @members = $query->param('member'); + +my $statrows = get_recent_status(@members); + +my $template_vars = {statrows=>$statrows}; + +print "Content-Type: text/html\n\n"; +$template->process("dashboard.tt",$template_vars); + + + + diff --git a/cgi-bin/pgstatus.pl b/cgi-bin/pgstatus.pl new file mode 100644 index 0000000..d3ba72a --- /dev/null +++ b/cgi-bin/pgstatus.pl @@ -0,0 +1,401 @@ +#!/usr/bin/perl + +use strict; + +use CGI; +use Digest::SHA1 qw(sha1_hex); +use MIME::Base64; +use DBI; +use DBD::Pg; +use Data::Dumper; +use Mail::Send; +use Safe; + +use vars qw($dbhost $dbname $dbuser $dbpass $dbport + $all_stat $fail_stat $change_stat $green_stat +); + +require "$ENV{BFConfDir}/BuildFarmWeb.pl"; + +die "no dbname" unless $dbname; +die "no dbuser" unless $dbuser; + +my $dsn="dbi:Pg:dbname=$dbname"; +$dsn .= ";host=$dbhost" if $dbhost; +$dsn .= ";port=$dbport" if $dbport; + +my $query = new CGI; + +my $sig = $query->path_info; +$sig =~ s!^/!!; + +my $stage = $query->param('stage'); +my $ts = $query->param('ts'); +my $animal = $query->param('animal'); +my $log = $query->param('log'); +my $res = $query->param('res'); +my $conf = $query->param('conf'); +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 $content = + "branch=$branch&res=$res&stage=$stage&animal=$animal&". + "ts=$ts&log=$log&conf=$conf"; + +my $extra_content = + "changed_files=$changed_this_run&". + "changed_since_success=$changed_since_success&"; + +unless ($animal && $ts && $stage && $sig) +{ + print + "Status: 490 bad parameters\nContent-Type: text/plain\n\n", + "bad parameters for request\n"; + exit; + +} + + +my $db = DBI->connect($dsn,$dbuser,$dbpass); + +die $DBI::errstr unless $db; + +my $gethost= + "select secret from buildsystems where name = ? and status = 'approved'"; +my $sth = $db->prepare($gethost); +$sth->execute($animal); +my ($secret)=$sth->fetchrow_array(); +$sth->finish; + +my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($ts); +$year += 1900; $mon +=1; +my $date= + sprintf("%d-%.2d-%.2d_%.2d:%.2d:%.2d",$year,$mon,$mday,$hour,$min,$sec); + +if ($ENV{BF_DEBUG} || ($ts > time) || (! $secret) ) +{ + open(TX,">../buildlogs/$animal.$date"); + print TX "sig=$sig\nlogtar-len=" , length($log_archive), + "\nstatus=$res\nstage=$stage\nconf:\n$conf\n", + "changed_this_run:\n$changed_this_run\n", + "changed_since_success:\n$changed_since_success\n", + "log:\n",$log; +# $query->save(\*TX); + close(TX); +} + +unless ($ts < time) +{ + my $gmt = gmtime($ts); + print "Status: 491 bad ts parameter - $ts ($gmt GMT) is in the future.\n", + "Context-Type: text/plain\n\n bad ts parameter - $ts ($gmt GMT) is in the future\n"; + $db->disconnect; + exit; +} + +unless ($secret) +{ + print + "Status: 495 Unknown System\nContent-Type: text/plain\n\n", + "System $animal is unknown\n"; + $db->disconnect; + exit; + +} + + + + +my $calc_sig = sha1_hex($content,$secret); +my $calc_sig2 = sha1_hex($extra_content,$content,$secret); + +if ($calc_sig ne $sig && $calc_sig2 ne $sig) +{ + + print "Status: 450 sig mismatch\nContent-Type: text/plain\n\n"; + print "$sig mismatches $calc_sig($calc_sig2) on content:\n$content"; + $db->disconnect; + exit; +} + +# undo escape-proofing of base64 data and decode it +map {tr/$@/+=/; $_ = decode_base64($_); } + ($log, $conf,$changed_this_run,$changed_since_success,$log_archive); + +($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime($ts); +$year += 1900; $mon +=1; +my $dbdate= + sprintf("%d-%.2d-%.2d %.2d:%.2d:%.2d",$year,$mon,$mday,$hour,$min,$sec); + +my $log_file_names; +my @log_file_names; +my $dirname = "../buildlogs/tmp.$$.unpacklogs"; + +if ($log_archive) +{ + my $log_handle; + my $archname = "../buildlogs/tmp.$$.tgz"; + open($log_handle,">$archname"); + binmode $log_handle; + print $log_handle $log_archive; + close $log_handle; + 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; + map { $_ = qq("$_"); } @qnames; + $log_file_names = '{' . join(',',@qnames) . '}'; + # unlink $archname; +} + +my $config_flags; +my $container = new Safe; +my $sconf = $conf; +unless ($sconf =~ s/.*(\$Script_Config)/$1/ms ) +{ + $sconf = '$Script_Config={};'; +} +my $client_conf = $container->reval("$sconf;"); + +my @config_flags = @{ $client_conf->{config_opts} || [] }; +if (@config_flags) +{ + @config_flags = grep {! m/=/ } @config_flags; + map {s/\s+//g; $_=qq("$_"); } @config_flags; + $config_flags = '{' . join(',',@config_flags) . '}' ; +} + + +my $logst = <prepare($logst); + +$sth->bind_param(1,$animal); +$sth->bind_param(2,$dbdate); +$sth->bind_param(3,$res); +$sth->bind_param(4,$stage); +$sth->bind_param(5,$log); +$sth->bind_param(6,$conf); +$sth->bind_param(7,$branch); +$sth->bind_param(8,$changed_this_run); +$sth->bind_param(9,$changed_since_success); +$sth->bind_param(10,$log_file_names); +$sth->bind_param(11,$log_archive,{ pg_type => DBD::Pg::PG_BYTEA }); +$sth->bind_param(12,$config_flags); + +$sth->execute; +$sth->finish; + +my $logst2 = <prepare($logst2); + +$/=undef; + +my $stage_start = $ts; + +foreach my $log_file( @log_file_names ) +{ + 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"); +} + + +$sth->finish; + +my $prevst = <prepare($prevst); +$sth->execute($animal,$branch,$dbdate); +my $row=$sth->fetchrow_arrayref; +my $prev_stat=$row->[0]; +$sth->finish; + +my $det_st = <prepare($det_st); +$sth->execute($animal); +$row=$sth->fetchrow_arrayref; +my ($os, $compiler,$arch) = @$row; +$sth->finish; + +$db->disconnect; + +print "Content-Type: text/plain\n\n"; +print "request was on:\n"; +print "res=$res&stage=$stage&animal=$animal&ts=$ts"; + +my $client_events = $client_conf->{mail_events}; + +if ($ENV{BF_DEBUG}) +{ + open(TX,">>../buildlogs/$animal.$date"); + print TX "\n",Dumper(\$client_conf),"\n"; + close(TX); +} + +my $bcc_stat = []; +my $bcc_chg=[]; +if (ref $client_events) +{ + my $cbcc = $client_events->{all}; + if (ref $cbcc) + { + push @$bcc_stat, @$cbcc; + } + elsif (defined $cbcc) + { + push @$bcc_stat, $cbcc; + } + if ($stage ne 'OK') + { + $cbcc = $client_events->{all}; + if (ref $cbcc) + { + push @$bcc_stat, @$cbcc; + } + elsif (defined $cbcc) + { + push @$bcc_stat, $cbcc; + } + } + $cbcc = $client_events->{change}; + if (ref $cbcc) + { + push @$bcc_chg, @$cbcc; + } + elsif (defined $cbcc) + { + push @$bcc_chg, $cbcc; + } + if ($stage eq 'OK' || $prev_stat eq 'OK') + { + $cbcc = $client_events->{green}; + if (ref $cbcc) + { + push @$bcc_chg, @$cbcc; + } + elsif (defined $cbcc) + { + push @$bcc_chg, $cbcc; + } + } +} + + +my $url = $query->url(-base => 1); + + +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 $host = `hostname`; chomp $host; + +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"); +my $fh = $msg->open; +print $fh <close; + +exit if ($stage eq $prev_stat); + +$mailto = [@$change_stat]; +push(@$mailto,@$green_stat) if ($stage eq 'OK' || $prev_stat eq 'OK'); + +$msg = new Mail::Send; + +$msg->set('From',"PG Build Farm <$me\@$host>"); + +$msg->to(@$mailto); +$msg->bcc(@$bcc_chg) if (@$bcc_chg); + +$stat_type = $prev_stat ne 'OK' ? "changed from $prev_stat failure to $stage" : + "changed from OK to $stage"; +$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"); +$fh = $msg->open; +print $fh <close; diff --git a/cgi-bin/register.pl b/cgi-bin/register.pl new file mode 100644 index 0000000..dcd3ab9 --- /dev/null +++ b/cgi-bin/register.pl @@ -0,0 +1,154 @@ +#!/usr/bin/perl + +use strict; +use DBI; +use Template; +use CGI; + +use vars qw($dbhost $dbname $dbuser $dbpass $dbport $notifyapp); + +require "$ENV{BFConfDir}/BuildFarmWeb.pl"; +#require "BuildFarmWeb.pl"; + +my $dsn="dbi:Pg:dbname=$dbname"; +$dsn .= ";host=$dbhost" if $dbhost; +$dsn .= ";port=$dbport" if $dbport; + +my $header = < + + + + PostgreSQL BuildFarm Application + + + + + +
+ +
+EOS + +my $footer = < +
+

+Hosting for the PostgreSQL Buildfarm is generously +provided by: +CommandPrompt, +The PostgreSQL Company +

+
+ + +EOS + +my $query = new CGI; + +my $params = $query->Vars; + +my ($os, $osv, $comp, $compv, $arch, $email, $owner) = @{$params}{ + qw(os osv comp compv arch email owner)}; + +unless ($os && $osv && $comp && $compv && $arch && $email && $owner) +{ + print "Content-Type: text/html\n\n", + $header, + "

You need to complete all the form items. Please try again.

\n", + $footer; + exit; +} + +# some idiot has a script that tries to talk to me +# this should catch and dispose of him +if (grep {/\@pgbuildfarm\.org|Content-Type:/} $os,$osv,$comp,$compv,$arch,$email,$owner) +{ + print + "Status: 403 Forbidden - go away idiot\n", + "Content-Type: text/plain\n\n"; + exit; + +} + +my $secret = ""; +my $dummyname=""; # we'll select an animal name when we approve it. +foreach (1..8) +{ + # 8 random chars is enough for the dummy name + $secret .= substr("0123456789abcdefghijklmnopqrstuvwxyz",int(rand(36)),1); + $dummyname .= substr("0123456789abcdef",int(rand(16)),1); +} +foreach (9..32) +{ + $secret .= substr("0123456789abcdef",int(rand(16)),1); +} + +my $db = DBI->connect($dsn,$dbuser,$dbpass); + +my $statement = <prepare($statement); +my $rv=$sth->execute($dummyname,$secret,$os,$osv,$comp,$compv, + $arch,$owner,$email); +my $err=$db->errstr; +print "Content-type: text/html\n\n"; +print $header + , "

PostgreSQL BuildFarm Application received

\n" + , "

Thank you. You should hear from us shortly.

" + , $footer; + + +$sth->finish; +$db->disconnect; + + +use Mail::Send; + +my $msg = new Mail::Send; + +my $me = `id -un`; + +my $host = `hostname`; + +$msg->set('From',"PG Build Farm <$me\@$host>"); + +$msg->to(@$notifyapp); +$msg->subject('New Buildfarm Application'); +my $fh = $msg->open; +print $fh "\n\nName: $dummyname\n", + "OS: $os: $osv\n", + "Arch: $arch\n", + "Comp: $comp: $compv\n", + "Owner: $owner <$email>\n"; +$fh->close; + + + + + + diff --git a/cgi-bin/show_history.pl b/cgi-bin/show_history.pl new file mode 100644 index 0000000..98a8860 --- /dev/null +++ b/cgi-bin/show_history.pl @@ -0,0 +1,156 @@ +#!/usr/bin/perl + +use strict; +use DBI; +use Template; +use CGI; + +use vars qw($dbhost $dbname $dbuser $dbpass $dbport); + + +require "$ENV{BFConfDir}/BuildFarmWeb.pl"; +#require "BuildFarmWeb.pl"; + +die "no dbname" unless $dbname; +die "no dbuser" unless $dbuser; + +my $dsn="dbi:Pg:dbname=$dbname"; +$dsn .= ";host=$dbhost" if $dbhost; +$dsn .= ";port=$dbport" if $dbport; + +my $db = DBI->connect($dsn,$dbuser,$dbpass); + +die $DBI::errstr unless $db; + +my $query = new CGI; +my $member = $query->param('nm'); $member =~ s/[^a-zA-Z0-9_ -]//g; +my $branch = $query->param('br'); $branch =~ s/[^a-zA-Z0-9_ -]//g; +my $hm = $query->param('hm'); $hm =~ s/[^a-zA-Z0-9_ -]//g; +$hm = '240' unless $hm =~ /^\d+$/; + +# we don't really need to do this join, since we only want +# one row from buildsystems. but it means we only have to run one +# query. If it gets heavy we'll split it up and run two + +my $statement = <prepare($statement); +$sth->execute($member,$branch); +while (my $row = $sth->fetchrow_hashref) +{ + $row->{owner_email} =~ s/\@/ [ a t ] /; + push(@$statrows,$row); +} +$sth->finish; + +$db->disconnect; + +my $template = new Template({EVAL_PERL => 1}); + +print "Content-Type: text/html\n\n"; + +$template->process(\*DATA, + {statrows=>$statrows, + branch=>$branch, + member => $member, + hm => $hm + }); + +exit; + +__DATA__ +[%- BLOCK cl %] class="[% SWITCH bgfor -%] + [%- CASE 'OK' %]pass[% CASE 'ContribCheck' %]warn[% CASE [ 'Check' 'InstallCheck' ] %]warnx[% CASE %]fail[% END %]" +[%- END -%] + + + + + PostgreSQL BuildFarm History + + + + + +
+ +
+

PostgreSQL BuildFarm Status History

+ + + + + + + + + +
System Detail
Farm member[% member %]
OS[% statrows.0.operating_system %] [% statrows.0.os_version %]
Compiler[% statrows.0.compiler %] [% statrows.0.compiler_version %]
Architecture[% statrows.0.architecture %]
Owner[% statrows.0.owner_email %]
+

Branch: [% branch %][% IF statrows.size >= hm %] (last [% hm %] entries shown)[% END %]

+[% BLOCK stdet %] + + [%- row.when_ago | replace('\s',' ') %] ago  + [% row.stage -%] + + [%- IF row.stage != 'OK' %]Details[% ELSE %]Config[% END -%] + + +[% END %] + +[% FOREACH offset IN [0,1,2] %][% low = offset * statrows.size / 3 ; high = -1 + (offset + 1) * statrows.size / 3 %] +[% TRY %][% PERL %] + use POSIX qw(floor); + $stash->set(low => floor($stash->get('low'))); + $stash->set(high => floor($stash->get('high'))); +[% END %][% CATCH %] [% END %] + +[% END %] +
+ + [% FOREACH xrow IN statrows.slice(low,high) %][% PROCESS stdet row=xrow %][% END %] +
+
+
+

+Hosting for the PostgreSQL Buildfarm is generously +provided by: +CommandPrompt, +The PostgreSQL Company +

+
+ + diff --git a/cgi-bin/show_history2.pl b/cgi-bin/show_history2.pl new file mode 100644 index 0000000..2bf7f13 --- /dev/null +++ b/cgi-bin/show_history2.pl @@ -0,0 +1,69 @@ +#!/usr/bin/perl + +use strict; +use DBI; +use Template; +use CGI; + +use vars qw($dbhost $dbname $dbuser $dbpass $dbport); + + +require "$ENV{BFConfDir}/BuildFarmWeb.pl"; +#require "BuildFarmWeb.pl"; + +die "no dbname" unless $dbname; +die "no dbuser" unless $dbuser; + +my $dsn="dbi:Pg:dbname=$dbname"; +$dsn .= ";host=$dbhost" if $dbhost; +$dsn .= ";port=$dbport" if $dbport; + +my $db = DBI->connect($dsn,$dbuser,$dbpass); + +die $DBI::errstr unless $db; + +my $query = new CGI; +my $member = $query->param('nm'); +my $branch = $query->param('br'); + +# we don't really need to do this join, since we only want +# one row from buildsystems. but it means we only have to run one +# query. If it gets heavy we'll split it up and run two + +my $statement = <prepare($statement); +$sth->execute($member,$branch); +while (my $row = $sth->fetchrow_hashref) +{ + push(@$statrows,$row); +} +$sth->finish; + +$db->disconnect; + +my $template = new Template({EVAL_PERL => 1, + INCLUDE_PATH => "/home/community/pgbuildfarm/templates", + }); + +print "Content-Type: text/html\n\n"; + +$template->process("dyn/history.tt", + {statrows=>$statrows, branch=>$branch, member => $member}); + diff --git a/cgi-bin/show_log.pl b/cgi-bin/show_log.pl new file mode 100644 index 0000000..929af0d --- /dev/null +++ b/cgi-bin/show_log.pl @@ -0,0 +1,327 @@ +#!/usr/bin/perl + +use strict; +use DBI; +use Template; +use CGI; +use URI::Escape; + +use vars qw($dbhost $dbname $dbuser $dbpass $dbport @log_file_names); + + +require "$ENV{BFConfDir}/BuildFarmWeb.pl"; +#require "BuildFarmWeb.pl"; + +die "no dbname" unless $dbname; +die "no dbuser" unless $dbuser; + +my $dsn="dbi:Pg:dbname=$dbname"; +$dsn .= ";host=$dbhost" if $dbhost; +$dsn .= ";port=$dbport" if $dbport; + +my $query = new CGI; + +my $system = $query->param('nm'); $system =~ s/[^a-zA-Z0-9_ -]//g; +my $logdate = $query->param('dt'); $logdate =~ s/[^a-zA-Z0-9_ -]//g; + +my $log = ""; +my $conf = ""; +my ($stage,$changed_this_run,$changed_since_success,$sysinfo,$branch); + +use vars qw($info_row); + +if ($system && $logdate) +{ + + my $db = DBI->connect($dsn,$dbuser,$dbpass); + + die $DBI::errstr unless $db; + + my $statement = <prepare($statement); + $sth->execute($system,$logdate); + my $row=$sth->fetchrow_arrayref; + $log=$row->[0]; + $conf=$row->[1] || "not recorded" ; + $stage=$row->[2] || "unknown"; + $changed_this_run = $row->[3]; + $changed_since_success = $row->[4]; + $branch = $row->[5]; + my $log_file_names = $row->[6]; + $log_file_names =~ s/^\{(.*)\}$/$1/; + @log_file_names=split(',',$log_file_names) + if $log_file_names; + $sth->finish; + + $statement = <prepare($statement); + $sth->execute($system); + $info_row=$sth->fetchrow_hashref; + $sysinfo = join(" ",@$row); + $sth->finish; + $db->disconnect; +} + +foreach my $chgd ($changed_this_run,$changed_since_success) +{ + my @lines = split(/!/,$chgd); + foreach (@lines) + { + next unless m!^pgsql/!; + s!(^\S+)(\s+)(\S+)!$1$2$3!; + } + $chgd = join("\n",@lines); + $chgd ||= 'not recorded'; + +} + +$conf =~ s/\@/ [ a t ] /g; +map {s/&/&/g; s//>/g; s/\"/"/g;} ($log,$conf); +# map {s/!/\n/g} ($changed_this_run,$changed_since_success); + + +use POSIX qw(ceil); +my $lrfactor = 7; +my $logrows = ceil(scalar(@log_file_names)/$lrfactor); +my $logcells = $lrfactor * $logrows; + +my $heading_done; +my $urldt = uri_escape($logdate); + +my $cell = 0; + + + +print "Content-Type: text/html\n\n"; + +if ($stage eq 'OK') +{ + print < + + + + PostgreSQL BuildFarm | Configuration summary for system "$system" + + + + +
+ +
+

PostgreSQL Build Farm Log

+ + + + + + + + + + + + + + + + + + +
System InformationFarm memberBranchOSCompilerArchitectureOwner
$system$branch$info_row->{operating_system} $info_row->{os_version}$info_row->{compiler} $info_row->{compiler_version}$info_row->{architecture}$info_row->{owner_email}
+EOHTML + +for my $logstage (@log_file_names) +{ + print "
\n" + unless $heading_done; + $heading_done = 1; + $cell++; + $logstage =~ s/\.log$//; + print "\n" if ($cell > 1 && $cell % $lrfactor == 1); + print "\n"; + print "\n" if ($cell % $lrfactor == 0); +} + +if ($cell) +{ + foreach my $rcell ($cell+1 .. $logcells) + { + print "\n" if ($rcell > 1 && $rcell % $lrfactor == 1); + print "\n"; + print "\n" if ($rcell % $lrfactor == 0); + } + print "
Stage Logs
$logstage
 
\n"; +} + +print < +

Configuration summary for system "$system"

+

Status 'OK' on snapshot taken $logdate

+
+$conf
+
+

Files changed this run

+
+$changed_this_run
+
+EOHTML +print <Log +
+$log
+
+EOHTML + print < +
+

+Hosting for the PostgreSQL Buildfarm is generously +provided by: +CommandPrompt, +The PostgreSQL Company +

+
+ + +EOHTML +; + + exit; +} + +print < + + + + PostgreSQL BuildFarm | Log for system "$system" failure on snapshot taken $logdate + + + +
+ +
+

PostgreSQL Build Farm Log

+

Details for system "$system" failure at stage $stage on snapshot taken $logdate

+ + + + + + + + + + + + + + + + + + +
System InformationFarm memberBranchOSCompilerArchitectureOwner
$system$branch$info_row->{operating_system} $info_row->{os_version}$info_row->{compiler} $info_row->{compiler_version}$info_row->{architecture}$info_row->{owner_email}
+EOHTML + +for my $logstage (@log_file_names) +{ + print "
\n" + unless $heading_done; + $heading_done = 1; + $cell++; + $logstage =~ s/\.log$//; + print "\n" if ($cell > 1 && $cell % $lrfactor == 1); + print "\n"; + print "\n" if ($cell % $lrfactor == 0); +} + +if ($cell) +{ + foreach my $rcell ($cell+1 .. $logcells) + { + print "\n" if ($rcell > 1 && $rcell % $lrfactor == 1); + print "\n"; + print "\n" if ($rcell % $lrfactor == 0); + } + print "
Stage Logs
$logstage
 
\n"; +} + +print <Configuration summary +
+$conf
+
+

Files changed this run

+
+$changed_this_run
+
+

Files changed since last success

+
+$changed_since_success
+
+

Log

+
+$log
+
+
+
+

+Hosting for the PostgreSQL Buildfarm is generously +provided by: +CommandPrompt, +The PostgreSQL Company +

+
+ + +EOHTML +; + + + + diff --git a/cgi-bin/show_members.pl b/cgi-bin/show_members.pl new file mode 100644 index 0000000..9846a6e --- /dev/null +++ b/cgi-bin/show_members.pl @@ -0,0 +1,163 @@ +#!/usr/bin/perl + +use strict; +use CGI; +use DBI; +use Template; + + + +use vars qw($dbhost $dbname $dbuser $dbpass $dbport $sort_by); + + +require "$ENV{BFConfDir}/BuildFarmWeb.pl"; +#require "BuildFarmWeb.pl"; + +my $query = new CGI; +my %sort_ok = ('name' => 'name' , + 'owner' => 'lower(owner_email)', + 'os' => 'lower(operating_system), os_version', + 'compiler' => 'lower(compiler), compiler_version' , + 'arch' => 'lower(architecture)' ); +$sort_by = $query->param('sort_by');$sort_by =~ s/[^a-zA-Z0-9_ -]//g; +$sort_by = $sort_ok{$sort_by} || 'name'; + +my $dsn="dbi:Pg:dbname=$dbname"; +$dsn .= ";host=$dbhost" if $dbhost; +$dsn .= ";port=$dbport" if $dbport; + +my $db = DBI->connect($dsn,$dbuser,$dbpass); + +# there is possibly some redundancy in this query, but it makes +# a lot of the processing simpler. + +my $statement = < 'HEAD', branch) + branch || ':' || + extract(days from now() - snapshot) + from build_status + where name = sysname + order by branch <> 'HEAD', branch desc, + snapshot desc + ) as branches + from buildsystems + where status = 'approved' + order by $sort_by + +EOS +; + +my $statrows=[]; +my $sth=$db->prepare($statement); +$sth->execute; +while (my $row = $sth->fetchrow_hashref) +{ + $row->{branches} =~ s/^\{(.*)\}$/$1/; + $row->{owner_email} =~ s/\@/ [ a t ] /; + push(@$statrows,$row); +} +$sth->finish; + + +$db->disconnect; + +# use Data::Dumper; print "Content-Type: text/plain\n\n",Dumper($statrows),"VERSION: ",$DBD::Pg::VERSION,"\n"; exit; + + +my $template = new Template({}); + +print "Content-Type: text/html\n\n"; + +$template->process(\*DATA,{statrows=>$statrows}); + +exit; + + +__DATA__ + + + + + PostgreSQL BuildFarm Members + + + + + + +
+ +
+

PostgreSQL BuildFarm Members

+

Click branch links to see build history. Click the heading links to resort the list. Select members by checkbox and hit the button at the bottom to create a status custom filter.

+
+ + + + + + + + + +[% alt = true %] +[% FOREACH row IN statrows %] + [% alt = ! alt %] + + + + + + + +[% END %] +
 Name
Owner
OS / VersionCompiler / VersionArchBranches reported on
(most recent report)
[% row.name %]
[% row.owner_email %]
[% row.operating_system %]
[% row.os_version %]
[% row.compiler %]
[% row.compiler_version %]
[% row.arch %][% IF ! row.branches ; ' ' ; END -%] +
    + [%- + FOREACH branch_days IN row.branches.split(',') ; + branch_fields = branch_days.split(':'); + branch = branch_fields.0; + branch_day = branch_fields.1; + %]
  • [% branch %] ([% branch_day %] days ago)
  • [% END %]
+ +
+
+
+

+Hosting for the PostgreSQL Buildfarm is generously +provided by: +CommandPrompt, +The PostgreSQL Company +

+
+ + + + + + + + + + diff --git a/cgi-bin/show_stage_log.pl b/cgi-bin/show_stage_log.pl new file mode 100644 index 0000000..52c1a37 --- /dev/null +++ b/cgi-bin/show_stage_log.pl @@ -0,0 +1,95 @@ +#!/usr/bin/perl + +use strict; +use DBI; +use Template; +use CGI; +use File::Temp qw(tempfile); + +use vars qw($dbhost $dbname $dbuser $dbpass $dbport @log_file_names); + + +require "$ENV{BFConfDir}/BuildFarmWeb.pl"; +#require "BuildFarmWeb.pl"; + +die "no dbname" unless $dbname; +die "no dbuser" unless $dbuser; + +my $dsn="dbi:Pg:dbname=$dbname"; +$dsn .= ";host=$dbhost" if $dbhost; +$dsn .= ";port=$dbport" if $dbport; + +my $query = new CGI; + +my $system = $query->param('nm'); $system =~ s/[^a-zA-Z0-9_ -]//g; +my $logdate = $query->param('dt');$logdate =~ s/[^a-zA-Z0-9_ -]//g; +my $stage = $query->param('stg');$stage =~ s/[^a-zA-Z0-9_ -]//g; + +use vars qw($tgz); + +if ($system && $logdate) +{ + + my $db = DBI->connect($dsn,$dbuser,$dbpass); + + die $DBI::errstr unless $db; + + my $statement = q( + + select log_archive + from build_status + where sysname = ? and snapshot = ? + + ); + + + + my $sth=$db->prepare($statement); + $sth->execute($system,$logdate); + my $row=$sth->fetchrow_arrayref; + $tgz=$row->[0]; + $sth->finish; + $db->disconnect; + +} + +unless ($stage) +{ + + print + "Content-Type: application/x-gzip\n", + "Content-Disposition: attachment; filename=buildfarmlog.tgz\n", + "\n", + $tgz; + exit; +} + +my $template = "buildlogXXXXXX"; +my ($fh, $filename) = tempfile($template, UNLINK => 1); +print $fh $tgz; +close($fh); + +my $output = `tar -z -O -xf $filename $stage.log 2>&1`; + +print "Content-Type: text/plain\n\n", $output, + + "-------------------------------------------------\n\n", + "Hosting for the PostgreSQL Buildfarm is generously ", + "provided by: CommandPrompt, The PostgreSQL Company"; + +; exit; + +# using
 like this on huge files can make browsers choke
+
+print "Content-Type: text/html\n\n";
+
+print <
+
+
+$output
+
+ + + +EOHTML diff --git a/cgi-bin/show_stage_log2.pl b/cgi-bin/show_stage_log2.pl new file mode 100644 index 0000000..c3ef407 --- /dev/null +++ b/cgi-bin/show_stage_log2.pl @@ -0,0 +1,114 @@ +#!/usr/bin/perl + +use strict; +use DBI; +use Template; +use CGI; +use File::Temp qw(tempfile); + +use vars qw($dbhost $dbname $dbuser $dbpass $dbport @log_file_names); + + +require "$ENV{BFConfDir}/BuildFarmWeb.pl"; +#require "BuildFarmWeb.pl"; + +die "no dbname" unless $dbname; +die "no dbuser" unless $dbuser; + +my $dsn="dbi:Pg:dbname=$dbname"; +$dsn .= ";host=$dbhost" if $dbhost; +$dsn .= ";port=$dbport" if $dbport; + +my $query = new CGI; + +my $system = $query->param('nm'); +my $logdate = $query->param('dt'); +my $stage = $query->param('stg'); + +use vars qw($tgz $output); + +if ($stage && $system && $logdate) +{ + +} + +if ($system && $logdate) +{ + + my $db = DBI->connect($dsn,$dbuser,$dbpass); + + die $DBI::errstr unless $db; + + if ($stage) + { + my $lst = q( + select log_text + from build_status_log + where sysname = ? + and snapshot = ? + and log_file_name = ? + ); + + } + + my $statement = q( + + select log_archive + from build_status + where sysname = ? and snapshot = ? + + ); + + + + my $sth=$db->prepare($statement); + $sth->execute($system,$logdate); + my $row=$sth->fetchrow_arrayref; + $tgz=$row->[0]; + $sth->finish; + $db->disconnect; + $output = `tar -z -O -xf $filename $stage.log 2>&1` + if $stage;; + + + +} + +unless ($stage) +{ + + print + "Content-Type: application/x-gzip\n", + "Content-Disposition: attachment; filename=buildfarmlog.tgz\n", + "\n", + $tgz; + exit; +} + +my $template = "buildlogXXXXXX"; +my ($fh, $filename) = tempfile($template, UNLINK => 1); +print $fh $tgz; +close($fh); + +print "Content-Type: text/plain\n\n", $output, + + "-------------------------------------------------\n\n", + "Hosting for the PostgreSQL Buildfarm is generously ", + "provided by: CommandPrompt, The PostgreSQL Company"; + +; exit; + +# using
 like this on huge files can make browsers choke
+
+print "Content-Type: text/html\n\n";
+
+print <
+
+
+$output
+
+ + + +EOHTML diff --git a/cgi-bin/show_status.pl b/cgi-bin/show_status.pl new file mode 100644 index 0000000..1e6ea32 --- /dev/null +++ b/cgi-bin/show_status.pl @@ -0,0 +1,231 @@ +#!/usr/bin/perl + +use strict; +use DBI; +use Template; +use CGI; + +use vars qw($dbhost $dbname $dbuser $dbpass $dbport); + + +require "$ENV{BFConfDir}/BuildFarmWeb.pl"; + +my $query = new CGI; +my @members = $query->param('member'); +map { s/[^a-zA-Z0-9_ -]//g; } @members; + +my $dsn="dbi:Pg:dbname=$dbname"; +$dsn .= ";host=$dbhost" if $dbhost; +$dsn .= ";port=$dbport" if $dbport; + +my $db = DBI->connect($dsn,$dbuser,$dbpass) or die("$dsn,$dbuser,$dbpass,$!"); + +# there is possibly some redundancy in this query, but it makes +# a lot of the processing simpler. + +my $statement = < now() - '30 days'::interval + ) m + where name = sysname + and s.status = 'approved' + order by branch = 'HEAD' desc, + branch desc, + snapshot desc + +EOS +; + +$statement =< now() - '30 days'::interval + ) m + where name = sysname + and s.status = 'approved' + order by branch = 'HEAD' desc, + branch desc, + snapshot desc + + + +EOS +; + +my $statrows=[]; +my $sth=$db->prepare($statement); +$sth->execute; +while (my $row = $sth->fetchrow_hashref) +{ + next if (@members && ! grep {$_ eq $row->{sysname} } @members); + $row->{build_flags} =~ s/^\{(.*)\}$/$1/; + $row->{build_flags} =~ s/,/ /g; + $row->{build_flags} =~ s/--((enable|with)-)?//g; + $row->{build_flags} =~ s/\S+=\S+//g; + push(@$statrows,$row); +} +$sth->finish; + + +$db->disconnect; + +my $template = new Template({}); + +print "Content-Type: text/html\n\n"; + +$template->process(\*DATA,{statrows=>$statrows}); + +exit; + +=comment + +[%- BLOCK img ; flag ; END -%] +[%- BLOCK imgx ; IF flag_imgs.$flag ; '' . flag . ' ' ; ELSE flag . ' ' ; END ; END -%] + +=cut + +__DATA__ +[% + flag_imgs = { + perl = '/img/camel.png', + python = '/img/python.png', + debug = '/img/bug.png', + pam => '/img/pam.png', + cassert => '/img/cassert.png', + openssl => '/img/ssl_icon.gif', + nls => '/img/translateicon.gif', + krb5 => '/img/krb.gif', + tcl => '/img/tcl.png', + 'thread-safety' => '/img/threads.gif', + 'integer-datetimes' = '/img/days.png', + } +-%] +[%- BLOCK img ; IF flag == 'depend' or flag == 'gnu-ld' ; ; ELSIF flag_imgs.$flag %][% flag %] [% ELSE %][%# + flag ; ' ' +%][% END ; END -%] +[%- BLOCK cl %] class=" [% SWITCH bgfor -%] + [%- CASE 'OK' %]pass[% CASE 'ContribCheck' %]warn[% CASE [ 'Check' 'InstallCheck' ] %]warnx[% CASE %]fail[% END %]" +[%- END -%] + + + + + PostgreSQL BuildFarm Status + + + + + +
+ +
+

PostgreSQL BuildFarm Status

+

+ Shown here is the latest status of each farm member + for each branch it has reported on in the last 30 days. +

+

+ Use the farm member link for history of that member + on the relevant branch. +

+ +[% FOREACH flagset IN flag_imgs %] + +[% IF loop.count == 5 %][% END %] +[% END %] +
Legend[% flagset.key %] = [% flagset.key %]
+
+ +[% brch = "" %] +[% FOREACH row IN statrows %] +[% IF row.branch != brch ; brch = row.branch %] + + +[% END %] + + + + + + + +[% END %] +
Branch: [% brch %]
AliasSystemStatusFlags
[% row.sysname %][% row.operating_system %] + [% row.os_version %] + [%- row.compiler %] + [% row.compiler_version %] + [%- row.architecture %] + [%- row.when_ago | replace('\s',' ') %] ago  + [% row.stage -%] + + [%- IF row.stage != 'OK' %]Details[% ELSE %]Config[% END -%][% FOREACH flag IN row.build_flags.split().sort() ; PROCESS img ; END %]
+
+
+

+Hosting for the PostgreSQL Buildfarm is generously +provided by: +CommandPrompt, +The PostgreSQL Company +

+
+ + + + + + + + + + diff --git a/cgi-bin/show_status.pl.save b/cgi-bin/show_status.pl.save new file mode 100644 index 0000000..0c64b17 --- /dev/null +++ b/cgi-bin/show_status.pl.save @@ -0,0 +1,153 @@ +#!/usr/bin/perl + +use strict; +use DBI; +use Template; +use CGI; + +use vars qw($dbhost $dbname $dbuser $dbpass $dbport); + + +require "$ENV{BFConfDir}/BuildFarmWeb.pl"; + +my $query = new CGI; +my @members = $query->param('member'); + +my $dsn="dbi:Pg:dbname=$dbname"; +$dsn .= ";host=$dbhost" if $dbhost; +$dsn .= ";port=$dbport" if $dbport; + +my $db = DBI->connect($dsn,$dbuser,$dbpass) or die("$dsn,$dbuser,$dbpass,$!"); + +# there is possibly some redundancy in this query, but it makes +# a lot of the processing simpler. + +my $statement = < now() - '30 days'::interval + ) m + where name = sysname + and s.status = 'approved' + order by case when branch = 'HEAD' then 0 else 1 end, + branch desc, + snapshot desc + +EOS +; + +my $statrows=[]; +my $sth=$db->prepare($statement); +$sth->execute; +while (my $row = $sth->fetchrow_hashref) +{ + next if (@members && ! grep {$_ eq $row->{sysname} } @members); + $row->{build_flags} =~ s/^\{(.*)\}$/$1/; + $row->{build_flags} =~ s/,/ /g; + $row->{build_flags} =~ s/--((enable|with)-)?//g; + $row->{build_flags} =~ s/\S+=\S+//g; + push(@$statrows,$row); +} +$sth->finish; + + +$db->disconnect; + +my $template = new Template({}); + +print "Content-Type: text/html\n\n"; + +$template->process(\*DATA,{statrows=>$statrows}); + +exit; + + +__DATA__ +[%- BLOCK cl %] class=" [% SWITCH bgfor -%] + [%- CASE 'OK' %]pass[% CASE 'ContribCheck' %]warn[% CASE [ 'Check' 'InstallCheck' ] %]warnx[% CASE %]fail[% END %]" +[%- END -%] + + + + + PostgreSQL BuildFarm Status + + + + +
+ +
+

PostgreSQL BuildFarm Status

+

+ Shown here is the latest status of each farm member + for each branch it has reported on in the last 30 days. +

+

+ Use the farm member link for history of that member + on the relevant branch. +

+ +[% brch = "" %] +[% FOREACH row IN statrows %] +[% IF row.branch != brch ; brch = row.branch %] + + +[% END %] + + + + + + + +[% END %] +
Branch: [% brch %]
AliasSystemStatusFlags
[% row.sysname %][% row.operating_system %] + [% row.os_version %] + [%- row.compiler %] + [% row.compiler_version %] + [%- row.architecture %] + [%- row.when_ago | replace('\s',' ') %] ago  + [% row.stage -%] + + [%- IF row.stage != 'OK' %]Details[% ELSE %]Config[% END -%][% row.build_flags %]
+
+
+ + + + + + + + + + diff --git a/cgi-bin/show_status2.pl b/cgi-bin/show_status2.pl new file mode 100644 index 0000000..a1b1ab1 --- /dev/null +++ b/cgi-bin/show_status2.pl @@ -0,0 +1,64 @@ +#!/usr/bin/perl + +use strict; +use DBI; +use Template; +use CGI; + +use vars qw($dbhost $dbname $dbuser $dbpass $dbport); + + +require "$ENV{BFConfDir}/BuildFarmWeb.pl"; + +my $query = new CGI; +my @members = $query->param('member'); + +my $dsn="dbi:Pg:dbname=$dbname"; +$dsn .= ";host=$dbhost" if $dbhost; +$dsn .= ";port=$dbport" if $dbport; + +my $db = DBI->connect($dsn,$dbuser,$dbpass) or die("$dsn,$dbuser,$dbpass,$!"); + +# there is possibly some redundancy in this query, but it makes +# a lot of the processing simpler. + +my $statement = < now() - '30 days'::interval + ) m + where name = sysname + and s.status = 'approved' + order by case when branch = 'HEAD' then 0 else 1 end, + branch desc, + snapshot desc + +EOS +; + +my $statrows=[]; +my $sth=$db->prepare($statement); +$sth->execute; +while (my $row = $sth->fetchrow_hashref) +{ + next if (@members && ! grep {$_ eq $row->{sysname} } @members); + push(@$statrows,$row); +} +$sth->finish; + + +$db->disconnect; + +my $template = new Template({INCLUDE_PATH=>"/home/community/pgbuildfarm/templates"}); + +print "Content-Type: text/html\n\n"; + +$template->process("dyn/status.tt",{statrows=>$statrows}); + diff --git a/cgi-bin/show_status9.pl b/cgi-bin/show_status9.pl new file mode 100644 index 0000000..54731d7 --- /dev/null +++ b/cgi-bin/show_status9.pl @@ -0,0 +1,193 @@ +#!/usr/bin/perl + +use strict; +use DBI; +use Template; +use CGI; + +use vars qw($dbhost $dbname $dbuser $dbpass $dbport); + + +require "$ENV{BFConfDir}/BuildFarmWeb.pl"; + +my $query = new CGI; +my @members = $query->param('member'); + +my $dsn="dbi:Pg:dbname=$dbname"; +$dsn .= ";host=$dbhost" if $dbhost; +$dsn .= ";port=$dbport" if $dbport; + +my $db = DBI->connect($dsn,$dbuser,$dbpass) or die("$dsn,$dbuser,$dbpass,$!"); + +# there is possibly some redundancy in this query, but it makes +# a lot of the processing simpler. + +my $statement = < now() - '30 days'::interval + ) m + where name = sysname + and s.status = 'approved' + order by case when branch = 'HEAD' then 0 else 1 end, + branch desc, + snapshot desc + +EOS +; + +my $statrows=[]; +my $sth=$db->prepare($statement); +$sth->execute; +while (my $row = $sth->fetchrow_hashref) +{ + next if (@members && ! grep {$_ eq $row->{sysname} } @members); + $row->{build_flags} =~ s/^\{(.*)\}$/$1/; + $row->{build_flags} =~ s/,/ /g; + $row->{build_flags} =~ s/--((enable|with)-)?//g; + $row->{build_flags} =~ s/\S+=\S+//g; + push(@$statrows,$row); +} +$sth->finish; + + +$db->disconnect; + +my $template = new Template({}); + +print "Content-Type: text/html\n\n"; + +$template->process(\*DATA,{statrows=>$statrows}); + +exit; + +=comment + +[%- BLOCK img ; flag ; END -%] +[%- BLOCK imgx ; IF flag_imgs.$flag ; '' . flag . ' ' ; ELSE flag . ' ' ; END ; END -%] + +=cut + +__DATA__ +[% + flag_imgs = { + perl = '/img/camel.png', + python = '/img/python.png', + debug = '/img/bug.png', + pam => '/img/pam.png', + cassert => '/img/cassert.png', + openssl => '/img/ssl_icon.gif', + nls => '/img/translateicon.gif', + krb5 => '/img/krb.gif', + tcl => '/img/tcl.png', + 'thread-safety' => '/img/threads.gif', + 'integer-datetimes' = '/img/days.png', + } +-%] +[%- BLOCK img ; IF flag == 'blank' %] [% ELSIF flag_imgs.$flag %][% flag %] [% ELSE %][%# + flag ; ' ' +%][% END ; END -%] +[%- BLOCK cl %] class=" [% SWITCH bgfor -%] + [%- CASE 'OK' %]pass[% CASE 'ContribCheck' %]warn[% CASE [ 'Check' 'InstallCheck' ] %]warnx[% CASE %]fail[% END %]" +[%- END -%] + + + + + PostgreSQL BuildFarm Status + + + + +
+ +
+

PostgreSQL BuildFarm Status

+

+ Shown here is the latest status of each farm member + for each branch it has reported on in the last 30 days. +

+

+ Use the farm member link for history of that member + on the relevant branch. +

+ +[% FOREACH flagset IN flag_imgs %] + +[% IF loop.count == 6 %][% END %] +[% END %] +
Legend[% flagset.key %] = [% flagset.key %]
+
+ +[% brch = "" %] +[% FOREACH row IN statrows %] +[% IF row.branch != brch ; brch = row.branch %] + + +[% END %] + + + + + + + +[% END %] +
Branch: [% brch %]
AliasSystemStatusFlags
[% row.sysname %][% row.operating_system %] + [% row.os_version %] + [%- row.compiler %] + [% row.compiler_version %] + [%- row.architecture %] + [%- row.when_ago | replace('\s',' ') %] ago  + [% row.stage -%] + + [%- IF row.stage != 'OK' %]Details[% ELSE %]Config[% END -%][% + flags = row.build_flags.split(); + FOREACH flagme IN flag_imgs.keys() ; + IF flags.grep(flagme).size > 0 ; + PROCESS img flag = flagme ; + ELSE ; + PROCESS img flag = 'blank' ; + END; + END + %]
+
+
+ + + + + + + + + + diff --git a/cgi-bin/show_status_soap.pl b/cgi-bin/show_status_soap.pl new file mode 100644 index 0000000..e51db59 --- /dev/null +++ b/cgi-bin/show_status_soap.pl @@ -0,0 +1,102 @@ +#!/usr/bin/perl + +use strict; + + +use vars qw($dbhost $dbname $dbuser $dbpass $dbport); + +require "$ENV{BFConfDir}/BuildFarmWeb.pl"; + +use lib "/home/community/pgbuildfarm/lib/lib/perl5/site_perl"; + +use SOAP::Transport::HTTP; + +SOAP::Transport::HTTP::CGI->dispatch_to('PGBuildFarm')->handle; + +exit; + +package PGBuildFarm; + +use DBI; + +sub get_status + +{ + my $class = shift; + my @members = @_; + + my $dsn="dbi:Pg:dbname=$::dbname"; + $dsn .= ";host=$::dbhost" if $::dbhost; + $dsn .= ";port=$::dbport" if $::dbport; + + my $db = DBI->connect($dsn,$::dbuser,$::dbpass) or + die("$dsn,$::dbuser,$::dbpass,$!"); + + # there is possibly some redundancy in this query, but it makes + # a lot of the processing simpler. + + my $statement =< now() - '30 days'::interval + ) m + where name = sysname + and s.status = 'approved' + order by branch = 'HEAD' desc, + branch desc, + snapshot desc + + + +EOS +; + + my $statrows=[]; + my $sth=$db->prepare($statement); + $sth->execute; + while (my $row = $sth->fetchrow_hashref) + { + next if (@members && ! grep {$_ eq $row->{sysname} } @members); + $row->{build_flags} =~ s/^\{(.*)\}$/$1/; + $row->{build_flags} =~ s/,/ /g; + $row->{build_flags} =~ s/--((enable|with)-)?//g; + $row->{build_flags} =~ s/\S+=\S+//g; + push(@$statrows,$row); + } + $sth->finish; + + + $db->disconnect; + + return $statrows; + +} + +1; + + + + + diff --git a/cgi-bin/test.pl b/cgi-bin/test.pl new file mode 100644 index 0000000..9b179d2 --- /dev/null +++ b/cgi-bin/test.pl @@ -0,0 +1,24 @@ +#!/usr/bin/perl + +#print "Content-Type: text/html\n\n"; +#print "

My quick perl hello

"; + +use CGI; + +my $query = new CGI; + +my $url = $query->url(); + +my $base = $query->url(-base=>1); + +print <path_info; +$sig =~ s!^/!!; + +my $animal = $query->param('animal'); +my $ts = $query->param('ts'); +my $os_version = $query->param('new_os'); +my $compiler_version = $query->param('new_compiler'); + +my $content = "animal=$animal\&ts=$ts"; +$content .= "\&new_os=$os_version" if $os_version; +$content .= "\&new_compiler=$compiler_version" if $compiler_version; + +require "$ENV{BFConfDir}/BuildFarmWeb.pl"; + +die "no dbname" unless $dbname; +die "no dbuser" unless $dbuser; + +my $dsn="dbi:Pg:dbname=$dbname"; +$dsn .= ";host=$dbhost" if $dbhost; +$dsn .= ";port=$dbport" if $dbport; + +unless ($animal && $ts && ($os_version || $compiler_version) && $sig) +{ + print + "Status: 490 bad parameters\nContent-Type: text/plain\n\n", + "bad parameters for request\n"; + exit; + +} + + +my $db = DBI->connect($dsn,$dbuser,$dbpass); + +die $DBI::errstr unless $db; + +my $gethost= + "select secret from buildsystems where name = ? and status = 'approved'"; +my $sth = $db->prepare($gethost); +$sth->execute($animal); +my ($secret)=$sth->fetchrow_array(); +$sth->finish; + + +unless ($secret) +{ + print + "Status: 495 Unknown System\nContent-Type: text/plain\n\n", + "System $animal is unknown\n"; + $db->disconnect; + exit; + +} + + + + +my $calc_sig = sha1_hex($content,$secret); + +if ($calc_sig ne $sig) +{ + + print "Status: 450 sig mismatch\nContent-Type: text/plain\n\n"; + print "$sig mismatches $calc_sig on content:\n$content"; + $db->disconnect; + exit; +} + +# undo escape-proofing of base64 data and decode it +map {tr/$@/+=/; $_ = decode_base64($_); } + ($os_version, $compiler_version); + +my $get_latest = q{ + + select coalesce(b.os_version, a.os_version) as os_version, + coalesce(b.compiler_version, a.compiler_version) as compiler_version + from buildsystems as a left join + ( select distinct on (name) name, compiler_version, os_version + from personality + order by name, effective_date desc + ) as b + on (a.name = b.name) + where a.name = ? + and a.status = 'approved' + +}; + +$sth = $db->prepare($get_latest); +my $rv = $sth->execute($animal); +unless($rv) +{ + print "Status: 460 old data fetch\nContent-Type: text/plain\n\n"; + print "error: ",$db->errstr,"\n"; + $db->disconnect; + exit; +} + +my ($old_os,$old_comp)=$sth->fetchrow_array(); +$sth->finish; + + + +$os_version ||= $old_os; +$compiler_version ||= $old_comp; + +my $new_personality = q{ + + insert into personality (name, os_version, compiler_version) + values (?,?,?) + +}; + + +$sth = $db->prepare($new_personality); +$rv = $sth->execute($animal,$os_version, $compiler_version); + +unless($rv) +{ + print "Status: 470 new data insert\nContent-Type: text/plain\n\n"; + print "error: $db->errstr\n"; + $db->disconnect; + exit; +} + +$sth->finish; + + + +$db->disconnect; + +print "Content-Type: text/plain\n\n"; +print "request was on:\n$content\n"; + + + diff --git a/htdocs/bfweb.tgz b/htdocs/bfweb.tgz new file mode 100644 index 0000000000000000000000000000000000000000..4ed50ab802a90c1f580b43ae9ae6947a260aa600 GIT binary patch literal 163840 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 literal 0 HcmV?d00001 diff --git a/htdocs/elephant-head_only.gif b/htdocs/elephant-head_only.gif new file mode 100644 index 0000000000000000000000000000000000000000..dd791da97791c8b067e631538057184896cb7e35 GIT binary patch literal 2523 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 JWt~$(69AVwM-c!3 literal 0 HcmV?d00001 diff --git a/htdocs/elephant5.gif b/htdocs/elephant5.gif new file mode 100644 index 0000000000000000000000000000000000000000..cb9da33d7537e733fb30a6eb27aa86c536de4aa1 GIT binary patch literal 3434 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 literal 0 HcmV?d00001 diff --git a/htdocs/elephant5a.gif b/htdocs/elephant5a.gif new file mode 100644 index 0000000000000000000000000000000000000000..076cb9db35eb583674c1f5ac17d8142133a06196 GIT binary patch literal 3425 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 literal 0 HcmV?d00001 diff --git a/htdocs/img/blank.gif b/htdocs/img/blank.gif new file mode 100644 index 0000000000000000000000000000000000000000..448d4c4b5d2eaf6fed78229822651aa45b28284b GIT binary patch literal 807 zcmZ?wbhEHbWMp7u_|Cxa|Nno6Q7{?;BQ*pRf3h%w{H_BcKzV|JgN1>Sg@wTy0HJaR AJOBUy literal 0 HcmV?d00001 diff --git a/htdocs/img/bug.png b/htdocs/img/bug.png new file mode 100644 index 0000000000000000000000000000000000000000..2e92af1d4907fc868a1c7547c9ee74400ad3a1e1 GIT binary patch literal 928 zcmZWoU1%d!6#k_9P`51g2aUKdtJw!3NFE9fvfy93o0iI^IE7LwWU;~^qeSS#2rWCI zL4u4JA>e?6bYa913+7?OfWtD&4mjN%F%Nkd+yo*-9oYyCjFN{weBNa7$$Rhl&b{Yw zzVmRt`_cN<;<>X=p9OGkb!GVt;UAgW{G7n&o?n!KIjq0Faala8Vozb}XMkH`^>2N3 zcU-Mj2|^rB{R{+>r{fzpzI+f7*#|ih1_Gc1^ne6NMJkhFK2KSuqEgps7&J}VHd`%v z9>b7fhrJ$?glWpjDdk+QEJ}I`n*z}GL!?xRt z{3MRjp;cM1_ZD0A$J>oeV4d$cnVx$-@v~`^V=OTxN92I)k|Eh9ZPFxbq)M(aK@uYl z5wy{EV4E-v7#cJMij2|{^0WHnKMIeu$d@N6MhON3bh`*ccph3V90#U_h6!DVrlDL$ zv52K5Oh{4RoAnpb}>w z^C&LN&$Z9^e-FO?bNwhhL{=!ddkG;5{B+m*)tX{sl{OxPk4*mrg-O=O# literal 0 HcmV?d00001 diff --git a/htdocs/img/camel.png b/htdocs/img/camel.png new file mode 100644 index 0000000000000000000000000000000000000000..95ca8c5e46ab514c7ac4ee73f76a51105d58f329 GIT binary patch literal 215 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmP$2MdFy{=G$!AfXgb7sn8b(_1G6avd<>aPIxS|MTtZ z2g%#?(3t4sCkx$lcKDe&)!zE9jpC#70E^98xYm^-9GM8ok zbF6XA3~AnH-62o;HoXnm@Zzopr E00^c{8vpkZ41#gMv!1h=>jzihDCl9WqFN&_NCy z3Q~{^lFdR~EJ_RB;6IQ-5M3l73XbP<@4w&|G8}jJ+~=NqbM@N7+=Yizn8IHm@_B?s zXoN%{BlmC%*Ki3(Ce6bvOv5A$S*spup&BZo$X4+X3(*h>0hIzCuz&_6z<}D6rWTu7 zjhvIu+|^y&kz*N|xv87DAt{(tb5&PyMMAMw%tc+q1!QEa!yM`m2d9#nVuU6ov6$mv zYEzn8Y(_4WF`t@=8FD|4Wu$5m| zPS;ECvbD4$k5F!yN+opOq~u89QktIwuSD~>(+C&>1E2?Vfez3HT0jFRi18ok(P%Ur z4hMrluh;8#yPZy_-EOy9twy6!6sbMSAO8tc7_V)jQaiEOe{gy1Nd4XpzE-L$zOodT;IY{N1_ro0ZC1vAX{Pzjs%jpF8|<^62LGy@~01 zv)*ie*r=bsKE2ev{bS=~vAq9h2ai9$y!B|b_+<0j!R<3o-;S;S+FjV5xN?7|R&RV- cojH5F_2$dZ>cpX$8(D3GxeOaCmkj4a7+{9`7l{9ReDb3P&;|xiS3j3^ HP6B|mLR|j?0RsaNH#9UHIB)LK;JT!1o;IsI6S+N2I3@nySp%Su*!M>Ih+L^k;M!Q+(IDCcEFVdQ&MBb@0KJ$@ZU6uP literal 0 HcmV?d00001 diff --git a/htdocs/img/krb.gif b/htdocs/img/krb.gif new file mode 100644 index 0000000000000000000000000000000000000000..c1cfcbf248dfbc1517c1062258438839e27602bc GIT binary patch literal 880 zcmbu8y=#?m426#(QgG=-(4{V&q*hR}DB|QrtNR^va|sBYM5qW3;?UyY)FqpuAl$`| zNw^?&@S~8yE^ZYR2M6hB-Qtt?U+@Qa2uV(!oV@qS)ywD3-<;RH_ND5VRZ-! zmZ=^~6p`T>mZ7E~>5=Z~mac}P)*{W*EKM-dnu?UCEX7o)5d#`Zu*fkOZKTnnS-nul zJddyl^?r;cau2s~^}0}yG!L^du{}`KhCE~;*251l>BbKB2Z9ZuMhs{uDTRZ^UPgsB>ORz$jnXn%DPaHbeRhuaT){Qq8y{y7Ax@sOuDfHCKhHxs1XC2PO#u$ zFxp6~Pt?_w|aQI@r-i7&dIB0lIH8 zaJ29s&F8?CFpr(~q+MwyO{EQKO`1q!X;B)1@gM2Ey}jMt-Pvq5olZA4HrCeGCX>l{ zJYHN}9F1CgnIHdzd1-E<19J;2ub#YrICpeu;qJ@t7a#mtxVHNC<&Ssk$Lz-P*6Xbg z_fK59z4>eO{PW}erEjOUcYc1{JbwM&YP`|*qtmy({{DOR#i#W%lY?JQ-g&z7Y~{$| HL%Q$})Rc@n literal 0 HcmV?d00001 diff --git a/htdocs/img/pam.png b/htdocs/img/pam.png new file mode 100644 index 0000000000000000000000000000000000000000..a1015e81d8de4f60e2231693ff96ee59ed242bed GIT binary patch literal 640 zcmV-`0)PF9P)1R4C7Nkt|v7O)W(C|wpP{%EIFh6}pE@B}kVK@wPq z&R+=^4_u9jo=tZ5$i?0E7wm)tLYOgGbi+X;CdN49(lW5LjA3C4bnjjdGs;k&<2QNo ze3K7`5CQ-Qf>17(34-7_jwDGi986W!R4T>uJWbQxZkOlzXf!%GIXP5VUCjxCfDjNx zvD4|WESq0jab83!8oT7Wbt5o8AZVtirXYl3triZ4_jaqzoviKjh5Nqt)hqh-{JW9S zX^Nuy1zeKrpSQlm<8hr%_x01uM-L7)g!TQ7$)IjOoIm+0wLDPJLI{mUU+j^nqZ zvjnw!ZALbb=Rt1^pr6?O_JDx<{r*a&0wF{Q;o7r%3Y_57GiE_0#+2^g76`(lG%$+Cfp2VzHRbX5DUgxwtX{#RE(X z&KXUhBZ->L{b1zYQ_@TU05pq>ivR$EAXt_qNiv_$*V@{-JCB7L{(9rPNnaVaA*?08 z{ZP3)bNz3jpJXzb$z(#IkR(aVFP`6YH6w2A3B7f*9gN(4^1ILv!!TB>HJ8g-EEdzK zt%IGDrMjDy>)#qZ{RIB+_yj?CJRX{+1wk;I%{sk#eD+!PBU_jEdOzC#dFhBoqmf7? z91cgdT4fl<>2xZJVz=9IFa(OCVzF2{okj?iN+pitTrQWvU>GU@0630YSXgMaT0Woe a&+!+^+5ifhI|Hcz0000=uLl;s%Y#s{j%+fSMyvH&KI9#bz1k_OkxMGgZ{SLy!8%>JmF6cHmnLx L^;)YV#9$2o<<%%a literal 0 HcmV?d00001 diff --git a/htdocs/img/tcl.png b/htdocs/img/tcl.png new file mode 100644 index 0000000000000000000000000000000000000000..957e760b13c4856d235a15253636448e16be24a9 GIT binary patch literal 229 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmP$2ahNR|28gFcc74LiEBiObAE1aYF-J0b5UwyNotBh zd1gt5LP$ocg1e`0!21-{JfK2PPZ!4!i_^&o5@rwVMT8ggx!MX(Qc<3zRKu`L>?lKt z^n~1B{%bC8kZcN<6<*rtzL8OaQ}FyKFGA6iGzWmf12oDhAGL9 QfQB-7y85}Sb4q9e04M=O9RL6T literal 0 HcmV?d00001 diff --git a/htdocs/img/threads.gif b/htdocs/img/threads.gif new file mode 100644 index 0000000000000000000000000000000000000000..30687676574596e1a85999ef51e3b503dee09d11 GIT binary patch literal 1051 zcmZ?wbhEHb6krfw_|5@19&?96=JY`okYd_0_DLO{f=D9NL# zz^|<&psy-yrp9Nd&2OkFZL2F{XDDH3EbnA0o z80MlB=As_psvqy66yvE9=dB*%X`JgPm**>+?4y$6t(@Sem+7aR6QYw7s-GXOn-OA^ z8ETvvW}F*lkRN558)shn(O@D-G=} z513pVys6!8a#QS-#;EDd(bHSvXST*pYe|^XSF*azWlf92x;Ce^ooA{}AFLvL%dg%VOLl17Aeti4%vwP=WJ-zYg z_3@9-FMWM=>D#MIU*6vN^zPZWkB`59dh-4AtFNEleEa`;F?|yuH z|Kr<-pWi?J{Ql|puW!G9egFIG)4yMz|NZ{*``3>@zkmGw^Xu>5-~avs$v^*q=-=Oe z|Ni~|{~w$>hB=}5lLhQU9S{l16ATQ>+4_{RRnTTejbbp{DTOws@VA;54>Y#&%iBz-2;z9E6FFgt%f>}Zxu)qj+$bor z;11yt7Zy`-IB=jtb+)rb0?0EK^V_x7bP*RFuDaFN1TsGylpBFr1qZUc#vmTrkN5ZNUN;v9%^t1gjp zv9ZYgvW27qB~oxBC1H$)-~dq+nFc5*7=h5?tryvB6)5cyzWXQm(lKQc2f{>D>zgidf0F%!SI-PFj+h-e%2^{&iIsf<#GAlEZOMGXZzom zjc1%5JAH8~x8SS7qUpj*(}ktem*2a0t)#;IDN%HB@K}DVq6+L z1}qN&dQr|xd_4`6Tzx9?zh1m)kCSASchnyt{7)D4Rtw=CDREw^e{8hckh>s#$J&d)=w z_B1u2y$wCx7#VVn-i6VK(c#HoJ~x@LuzyIgSX0y{f! zxpqA+w;P^)u*b~I4Edk`T0po>Q-pMpg#B{=6NKj^Hfg5h%gn&|rthwclB(|v*UNgX+LXrdRBr(#&~aWH z`bb_OIiVgAmR=||r1ytK)p2Y`W%>1S{$Bj6*84ATeM91<^_PWx0hCWwntEceda7NV ze9BPx*JjoST$(3S9+dcVNz#yNuH(TMJsHBtw9xePZ|GQW@1rR}F;X^Mbg5%|U?C?u StwlLDJFBXCCyb)V)Bgfb0f|Ha literal 0 HcmV?d00001 diff --git a/htdocs/inc/b/l.png b/htdocs/inc/b/l.png new file mode 100644 index 0000000000000000000000000000000000000000..19a036d7c4cad0c6ff5c75ceb3f5eba415ff01f7 GIT binary patch literal 2970 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 ALI3~& literal 0 HcmV?d00001 diff --git a/htdocs/inc/pgbf.css b/htdocs/inc/pgbf.css new file mode 100644 index 0000000..a83b2cb --- /dev/null +++ b/htdocs/inc/pgbf.css @@ -0,0 +1,129 @@ +body { + background: #fff; + margin: 0; + font-family: helvetica, trebuchet, "Lucida Grande", sans-serif; + font-size:small + } + +img { display:block; } +img.inline { display:inline; } + +a img { border:none; } +a:hover img { border: none; } + +#wrapper { + margin:0 auto; + margin-left: 5px; + /* width: 800px; */ +} + +#banner img { margin:6px 0; } + +#nav { + float:left; + width:780px; + background:#fff; + margin:0 10px 10px; +} + +#nav ul { + margin:0; + padding:0; + list-style:none; +} + +#nav li { + float:left; + margin:0 .5em 0 0; + padding:0 0 0 4px; + background: url(/inc/b/l.png) no-repeat left top; +} + +#nav li a { + display:block; + background:url(/inc/b/r.png) no-repeat right top; + padding:0 11px 0 7px; + color:#fff; + text-decoration:none; + line-height:20px; +} + +#nav li a:hover { + background: url(/inc/b/r.png) no-repeat 100% -20px; + color:rgb(17,45,137); + border: 0; +} + +#nav li:hover { background: url(/inc/b/l.png) no-repeat 0% -20px; } + +#main { + clear:both; + margin:0 5px; +} + +#main a { + text-decoration: none; + color: rgb(17,45,137); + font-weight: bold; + background: inherit; +} + +a:hover, a:active { border-bottom: 1px dotted rgb(17,45,137); } +p { padding: .3em 0; } + +table { + font-size: small; + border: 1px #aaa solid; + border-right: 0; + border-bottom: 0; +} + +th, td { + white-space: nowrap; + border: 1px #aaa solid; + border-top: 0; + border-left: 0; + padding:2px; +} + +body.members td { white-space: normal; } + +th { + background: #ddd; + color: #222; + font-size: x-small; +} + +tr.alt td { background: #eef; } + +th.head { + background: #666; + color: #fff; + text-align: center !important; + letter-spacing: .1em; +} + +.status, .detail { border-bottom: 1px #fff solid; } +tr.last td { border-bottom: 1px #aaa solid; } +.pass td.status, .pass td.detail { background: #6f6; } +.warn td.status, .warn td.detail { background: #fc3; } +.warnx td.status, .warn td.detail { background: #f99; } +.fail td.status, .fail td.detail { background: #f66; } +body.history th { text-align: right; } +body.application table { margin: 0 auto; } +body.application th { text-align: right; } +body.application th.submit { text-align: center; } + +td.branch ul { list-style: none; } + +td.branch ul, td.branch li { + margin: 0; + padding: 0; +} + +.opsys { color: black; } +.compiler { color: navy; } +.arch { color: purple; } + +td.flags { white-space: normal; font-size: x-small; } + diff --git a/htdocs/inc/pgbuildfarm-banner.png b/htdocs/inc/pgbuildfarm-banner.png new file mode 100644 index 0000000000000000000000000000000000000000..46988179e599643b3ab3b7d8ee7fc3395b1a5241 GIT binary patch literal 21916 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 + + + + PostgreSQL BuildFarm + + + + + +
+ +
+

+The PostgreSQL build farm is a distributed system for automatically testing +changes in the source code for PostgreSQL as they occur, on a wide variety +of platforms. This server is the central repository for the results of those +tests. +

+

+To see the current status of tests on various branches, check the +Status Page. +

+

+If you are interested in running a member of the build farm, then please visit +the Registration Page. +We are particularly interested in unusual platforms or combinations of +architecture, operating system and compiler. +

+

To see what is involved in running a buildfarm member, please visit the +project page at +PGFoundry and +especially read the +HowTo documentation. +

+

The build farm software should run on all platforms that can support PostgreSQL. +

+
+
+

+Hosting for the PostgreSQL Buildfarm is generously +provided by: +CommandPrompt, +The PostgreSQL Company +

+
+ + diff --git a/htdocs/register.html b/htdocs/register.html new file mode 100644 index 0000000..567bfb8 --- /dev/null +++ b/htdocs/register.html @@ -0,0 +1,108 @@ + + + + + PostgreSQL BuildFarm Application + + + + + +
+ +
+

Application to join PostgreSQL BuildFarm

+ +

Here is a short description of what is required to join the buildfarm successfully. Please read it carefully +before submitting this form.

+ +
    +
  • your machine will need to be able to contact http://www.pgbuildfarm.org + either directly or via proxy, and it will need access to a PostgreSQL CVS repository, + either the one at postgresql.org or a mirror (you can set up your own mirror using CSVup on a Linux or FreeBSD machine - + this is recommended).
  • +
  • have a working Postgresql build environment for your platform + (for Windows this means MSys/MinGW with the libz and libintl stuff, and ideally native Python and Tcl).
  • +
  • Windows only: you will need a native perl installed as well as the one in the MSys DTK. The one from ActiveState works fine.
  • +
  • download and unpack the latest release of client code from + http://pgfoundry.org/frs/?group_id=1000040
  • +
  • read instructions at + http://pgfoundry.org/docman/view.php/1000040/4/PGBuildFarm-HOWTO.txt
  • +
  • get the software running locally using flags --force --nostatus --nosend
  • +
  • register your machine on this page
  • +
  • when you receive credentials, put them in the config file, and schedule regular builds (without those flags) + for the branches you want to support - which should be at least HEAD and the most recent stable branch.
  • +
+ +

There is also some extra information in this +article about buildfarm on the O'Reilly network.

+ +
+ +

Please complete all items.

+

For Linux, please specify the name and version of the Distribution for the Operating Systems items. +Do not use the name "Linux". For example, for my test machine the Operating +Systems is "Fedora Core" and the version is "4".

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Operating System
OS Version
Compiler
Compiler Version
Architecture
Your name
Your email address
+
+
+
+

+Hosting for the PostgreSQL Buildfarm is generously +provided by: +CommandPrompt, +The PostgreSQL Company +

+
+ + + + diff --git a/htdocs/robots.txt b/htdocs/robots.txt new file mode 100644 index 0000000..1b425ee --- /dev/null +++ b/htdocs/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: /cgi-bin/ diff --git a/schema/bfwebdb.sql b/schema/bfwebdb.sql new file mode 100644 index 0000000..36f61f3 --- /dev/null +++ b/schema/bfwebdb.sql @@ -0,0 +1,450 @@ +-- +-- PostgreSQL database dump +-- + +SET client_encoding = 'SQL_ASCII'; +SET check_function_bodies = false; +SET client_min_messages = warning; + +-- +-- Name: SCHEMA public; Type: COMMENT; Schema: -; Owner: pgbuildfarm +-- + +COMMENT ON SCHEMA public IS 'Standard public schema'; + + +SET search_path = public, pg_catalog; + +-- +-- Name: plperl_call_handler(); Type: FUNCTION; Schema: public; Owner: pgbuildfarm +-- + +CREATE FUNCTION plperl_call_handler() RETURNS language_handler + AS '$libdir/plperl', 'plperl_call_handler' + LANGUAGE c; + + +ALTER FUNCTION public.plperl_call_handler() OWNER TO pgbuildfarm; + +-- +-- Name: plperl; Type: PROCEDURAL LANGUAGE; Schema: public; Owner: +-- + +CREATE TRUSTED PROCEDURAL LANGUAGE plperl HANDLER plperl_call_handler; + + +-- +-- Name: plperlu; Type: PROCEDURAL LANGUAGE; Schema: public; Owner: +-- + +CREATE PROCEDURAL LANGUAGE plperlu HANDLER plperl_call_handler; + + +-- +-- Name: plpgsql_call_handler(); Type: FUNCTION; Schema: public; Owner: pgbuildfarm +-- + +CREATE FUNCTION plpgsql_call_handler() RETURNS language_handler + AS '$libdir/plpgsql', 'plpgsql_call_handler' + LANGUAGE c; + + +ALTER FUNCTION public.plpgsql_call_handler() OWNER TO pgbuildfarm; + +-- +-- Name: plpgsql; Type: PROCEDURAL LANGUAGE; Schema: public; Owner: +-- + +CREATE TRUSTED PROCEDURAL LANGUAGE plpgsql HANDLER plpgsql_call_handler; + + +-- +-- Name: pending; Type: TYPE; Schema: public; Owner: pgbuildfarm +-- + +CREATE TYPE pending AS ( + name text, + operating_system text, + os_version text, + compiler text, + compiler_version text, + architecture text, + owner_email text +); + + +ALTER TYPE public.pending OWNER TO pgbuildfarm; + +-- +-- Name: pending2; Type: TYPE; Schema: public; Owner: pgbuildfarm +-- + +CREATE TYPE pending2 AS ( + name text, + operating_system text, + os_version text, + compiler text, + compiler_version text, + architecture text, + owner_email text, + "owner" text, + status_ts timestamp without time zone +); + + +ALTER TYPE public.pending2 OWNER TO pgbuildfarm; + +-- +-- Name: approve(text, text); Type: FUNCTION; Schema: public; Owner: pgbuildfarm +-- + +CREATE FUNCTION approve(text, text) RETURNS void + AS $_$update buildsystems set name = $2, status ='approved' where name = $1 and status = 'pending'$_$ + LANGUAGE sql; + + +ALTER FUNCTION public.approve(text, text) OWNER TO pgbuildfarm; + +-- +-- Name: approve2(text, text); Type: FUNCTION; Schema: public; Owner: pgbuildfarm +-- + +CREATE FUNCTION approve2(text, text) RETURNS text + AS $_$ update buildsystems set name = $2, status = 'approved' where name = $1 and status = 'pending'; select owner_email || ':' || name || ':' || secret from buildsystems where name = $2;$_$ + LANGUAGE sql; + + +ALTER FUNCTION public.approve2(text, text) OWNER TO pgbuildfarm; + +-- +-- Name: pending(); Type: FUNCTION; Schema: public; Owner: pgbuildfarm +-- + +CREATE FUNCTION pending() RETURNS SETOF pending2 + AS $$select name,operating_system,os_version,compiler,compiler_version,architecture,owner_email, sys_owner, status_ts from buildsystems where status = 'pending' order by status_ts $$ + LANGUAGE sql; + + +ALTER FUNCTION public.pending() OWNER TO pgbuildfarm; + +-- +-- Name: prevstat(text, text, timestamp without time zone); Type: FUNCTION; Schema: public; Owner: pgbuildfarm +-- + +CREATE FUNCTION prevstat(text, text, timestamp without time zone) RETURNS text + AS $_$ + select coalesce((select distinct on (snapshot) stage + from build_status + where sysname = $1 and branch = $2 and snapshot < $3 + order by snapshot desc + limit 1), 'NEW') as prev_status +$_$ + LANGUAGE sql; + + +ALTER FUNCTION public.prevstat(text, text, timestamp without time zone) OWNER TO pgbuildfarm; + +SET default_tablespace = ''; + +SET default_with_oids = true; + +-- +-- Name: alerts; Type: TABLE; Schema: public; Owner: pgbuildfarm; Tablespace: +-- + +CREATE TABLE alerts ( + sysname text NOT NULL, + branch text NOT NULL, + first_alert timestamp without time zone, + last_notification timestamp without time zone +); + + +ALTER TABLE public.alerts OWNER TO pgbuildfarm; + +-- +-- Name: build_status; Type: TABLE; Schema: public; Owner: pgbuildfarm; Tablespace: +-- + +CREATE TABLE build_status ( + sysname text NOT NULL, + snapshot timestamp without time zone NOT NULL, + status integer, + stage text, + log text, + conf_sum text, + branch text, + changed_this_run text, + changed_since_success text, + log_archive bytea, + log_archive_filenames text[], + build_flags text[], + report_time timestamp with time zone DEFAULT ('now'::text)::timestamp(6) with time zone +); + + +ALTER TABLE public.build_status OWNER TO pgbuildfarm; + +-- +-- Name: build_status_export; Type: VIEW; Schema: public; Owner: pgbuildfarm +-- + +CREATE VIEW build_status_export AS + SELECT build_status.sysname AS name, build_status.snapshot, build_status.stage, build_status.branch, build_status.build_flags FROM build_status; + + +ALTER TABLE public.build_status_export OWNER TO pgbuildfarm; + +-- +-- Name: build_status_log; Type: TABLE; Schema: public; Owner: pgbuildfarm; Tablespace: +-- + +CREATE TABLE build_status_log ( + sysname text NOT NULL, + snapshot timestamp without time zone NOT NULL, + branch text NOT NULL, + log_stage text NOT NULL, + log_text text, + stage_duration interval +); + + +ALTER TABLE public.build_status_log OWNER TO pgbuildfarm; + +-- +-- Name: buildsystems; Type: TABLE; Schema: public; Owner: pgbuildfarm; Tablespace: +-- + +CREATE TABLE buildsystems ( + name text NOT NULL, + secret text NOT NULL, + operating_system text NOT NULL, + os_version text NOT NULL, + compiler text NOT NULL, + compiler_version text NOT NULL, + architecture text NOT NULL, + status text NOT NULL, + sys_owner text NOT NULL, + owner_email text NOT NULL, + status_ts timestamp without time zone DEFAULT (('now'::text)::timestamp(6) with time zone)::timestamp without time zone +); + + +ALTER TABLE public.buildsystems OWNER TO pgbuildfarm; + +-- +-- Name: buildsystems_export; Type: VIEW; Schema: public; Owner: pgbuildfarm +-- + +CREATE VIEW buildsystems_export AS + SELECT buildsystems.name, buildsystems.operating_system, buildsystems.os_version, buildsystems.compiler, buildsystems.compiler_version, buildsystems.architecture FROM buildsystems WHERE (buildsystems.status = 'approved'::text); + + +ALTER TABLE public.buildsystems_export OWNER TO pgbuildfarm; + +-- +-- Name: list_subscriptions; Type: TABLE; Schema: public; Owner: pgbuildfarm; Tablespace: +-- + +CREATE TABLE list_subscriptions ( + addr text +); + + +ALTER TABLE public.list_subscriptions OWNER TO pgbuildfarm; + +-- +-- Name: penguin_save; Type: TABLE; Schema: public; Owner: pgbuildfarm; Tablespace: +-- + +CREATE TABLE penguin_save ( + branch text, + snapshot timestamp without time zone, + stage text +); + + +ALTER TABLE public.penguin_save OWNER TO pgbuildfarm; + +-- +-- Name: personality; Type: TABLE; Schema: public; Owner: pgbuildfarm; Tablespace: +-- + +CREATE TABLE personality ( + name text NOT NULL, + os_version text NOT NULL, + compiler_version text NOT NULL, + effective_date timestamp with time zone DEFAULT ('now'::text)::timestamp(6) with time zone NOT NULL +); + + +ALTER TABLE public.personality OWNER TO pgbuildfarm; + +-- +-- Name: alerts_pkey; Type: CONSTRAINT; Schema: public; Owner: pgbuildfarm; Tablespace: +-- + +ALTER TABLE ONLY alerts + ADD CONSTRAINT alerts_pkey PRIMARY KEY (sysname, branch); + + +ALTER INDEX public.alerts_pkey OWNER TO pgbuildfarm; + +-- +-- Name: build_status_log_pkey; Type: CONSTRAINT; Schema: public; Owner: pgbuildfarm; Tablespace: +-- + +ALTER TABLE ONLY build_status_log + ADD CONSTRAINT build_status_log_pkey PRIMARY KEY (sysname, snapshot, log_stage); + + +ALTER INDEX public.build_status_log_pkey OWNER TO pgbuildfarm; + +-- +-- Name: build_status_pkey; Type: CONSTRAINT; Schema: public; Owner: pgbuildfarm; Tablespace: +-- + +ALTER TABLE ONLY build_status + ADD CONSTRAINT build_status_pkey PRIMARY KEY (sysname, snapshot); + + +ALTER INDEX public.build_status_pkey OWNER TO pgbuildfarm; + +-- +-- Name: buildsystems_pkey; Type: CONSTRAINT; Schema: public; Owner: pgbuildfarm; Tablespace: +-- + +ALTER TABLE ONLY buildsystems + ADD CONSTRAINT buildsystems_pkey PRIMARY KEY (name); + + +ALTER INDEX public.buildsystems_pkey OWNER TO pgbuildfarm; + +-- +-- Name: personality_pkey; Type: CONSTRAINT; Schema: public; Owner: pgbuildfarm; Tablespace: +-- + +ALTER TABLE ONLY personality + ADD CONSTRAINT personality_pkey PRIMARY KEY (name, effective_date); + + +ALTER INDEX public.personality_pkey OWNER TO pgbuildfarm; + +-- +-- Name: bs_branch_snapshot_idx; Type: INDEX; Schema: public; Owner: pgbuildfarm; Tablespace: +-- + +CREATE INDEX bs_branch_snapshot_idx ON build_status USING btree (branch, snapshot); + + +ALTER INDEX public.bs_branch_snapshot_idx OWNER TO pgbuildfarm; + +-- +-- Name: bs_status_idx; Type: INDEX; Schema: public; Owner: pgbuildfarm; Tablespace: +-- + +CREATE INDEX bs_status_idx ON buildsystems USING btree (status); + + +ALTER INDEX public.bs_status_idx OWNER TO pgbuildfarm; + +-- +-- Name: bs_sysname_branch_idx; Type: INDEX; Schema: public; Owner: pgbuildfarm; Tablespace: +-- + +CREATE INDEX bs_sysname_branch_idx ON build_status USING btree (sysname, branch); + + +ALTER INDEX public.bs_sysname_branch_idx OWNER TO pgbuildfarm; + +-- +-- Name: bs_sysname_branch_report_idx; Type: INDEX; Schema: public; Owner: pgbuildfarm; Tablespace: +-- + +CREATE INDEX bs_sysname_branch_report_idx ON build_status USING btree (sysname, branch, report_time); + + +ALTER INDEX public.bs_sysname_branch_report_idx OWNER TO pgbuildfarm; + +-- +-- Name: $1; Type: FK CONSTRAINT; Schema: public; Owner: pgbuildfarm +-- + +ALTER TABLE ONLY personality + ADD CONSTRAINT "$1" FOREIGN KEY (name) REFERENCES buildsystems(name) ON DELETE CASCADE; + + +-- +-- Name: bs_fk; Type: FK CONSTRAINT; Schema: public; Owner: pgbuildfarm +-- + +ALTER TABLE ONLY build_status + ADD CONSTRAINT bs_fk FOREIGN KEY (sysname) REFERENCES buildsystems(name) ON UPDATE CASCADE ON DELETE CASCADE; + + +-- +-- Name: build_status_log_sysname_fkey; Type: FK CONSTRAINT; Schema: public; Owner: pgbuildfarm +-- + +ALTER TABLE ONLY build_status_log + ADD CONSTRAINT build_status_log_sysname_fkey FOREIGN KEY (sysname, snapshot) REFERENCES build_status(sysname, snapshot) ON DELETE CASCADE; + + +-- +-- Name: public; Type: ACL; Schema: -; Owner: pgbuildfarm +-- + +REVOKE ALL ON SCHEMA public FROM PUBLIC; +REVOKE ALL ON SCHEMA public FROM pgbuildfarm; +GRANT ALL ON SCHEMA public TO pgbuildfarm; +GRANT ALL ON SCHEMA public TO PUBLIC; + + +-- +-- Name: build_status; Type: ACL; Schema: public; Owner: pgbuildfarm +-- + +REVOKE ALL ON TABLE build_status FROM PUBLIC; +REVOKE ALL ON TABLE build_status FROM pgbuildfarm; +GRANT ALL ON TABLE build_status TO pgbuildfarm; +GRANT INSERT,SELECT ON TABLE build_status TO pgbfweb; +GRANT SELECT ON TABLE build_status TO rssfeed; + + +-- +-- Name: build_status_log; Type: ACL; Schema: public; Owner: pgbuildfarm +-- + +REVOKE ALL ON TABLE build_status_log FROM PUBLIC; +REVOKE ALL ON TABLE build_status_log FROM pgbuildfarm; +GRANT ALL ON TABLE build_status_log TO pgbuildfarm; +GRANT INSERT,SELECT,UPDATE,DELETE ON TABLE build_status_log TO pgbfweb; +GRANT SELECT ON TABLE build_status_log TO rssfeed; + + +-- +-- Name: buildsystems; Type: ACL; Schema: public; Owner: pgbuildfarm +-- + +REVOKE ALL ON TABLE buildsystems FROM PUBLIC; +REVOKE ALL ON TABLE buildsystems FROM pgbuildfarm; +GRANT ALL ON TABLE buildsystems TO pgbuildfarm; +GRANT INSERT,SELECT ON TABLE buildsystems TO pgbfweb; +GRANT SELECT ON TABLE buildsystems TO rssfeed; + + +-- +-- Name: personality; Type: ACL; Schema: public; Owner: pgbuildfarm +-- + +REVOKE ALL ON TABLE personality FROM PUBLIC; +REVOKE ALL ON TABLE personality FROM pgbuildfarm; +GRANT ALL ON TABLE personality TO pgbuildfarm; +GRANT INSERT,SELECT ON TABLE personality TO pgbfweb; +GRANT SELECT ON TABLE personality TO rssfeed; + + +-- +-- PostgreSQL database dump complete +-- + diff --git a/templates/bfwrapper.tt b/templates/bfwrapper.tt new file mode 100644 index 0000000..cb95ef9 --- /dev/null +++ b/templates/bfwrapper.tt @@ -0,0 +1,49 @@ + + + + + PostgreSQL BuildFarm Status + + + + + + + diff --git a/templates/bfwrapper.tt.ttc b/templates/bfwrapper.tt.ttc new file mode 100644 index 0000000..19faeb3 --- /dev/null +++ b/templates/bfwrapper.tt.ttc @@ -0,0 +1,32 @@ +#------------------------------------------------------------------------ +# Compiled template generated by the Template Toolkit version 2.14 +#------------------------------------------------------------------------ + +Template::Document->new({ + METADATA => { + 'modtime' => '1107104454', + 'name' => 'bfwrapper.tt', + }, + BLOCK => sub { + my $context = shift || die "template sub called without context\n"; + my $stash = $context->stash; + my $output = ''; + my $error; + + eval { BLOCK: { + $output .= "\n\n\n \n PostgreSQL BuildFarm Status\n \n \n\n\n\n \n\n"; + } }; + if ($@) { + $error = $context->catch($@, \$output); + die $error unless $error->type eq 'return'; + } + + return $output; + }, + DEFBLOCKS => { + + }, +}); diff --git a/templates/dashboard.tt b/templates/dashboard.tt new file mode 100644 index 0000000..e7e7ee0 --- /dev/null +++ b/templates/dashboard.tt @@ -0,0 +1,77 @@ +[% + flag_imgs = { + perl = '/img/camel.png', + python = '/img/python.png', + debug = '/img/bug.png', + pam => '/img/pam.png', + cassert => '/img/cassert.png', + openssl => '/img/ssl_icon.gif', + nls => '/img/translateicon.gif', + krb5 => '/img/krb.gif', + tcl => '/img/tcl.png', + 'thread-safety' => '/img/threads.gif', + 'integer-datetimes' = '/img/days.png', + } +-%] +[%- BLOCK img ; + IF flag == 'depend' or flag == 'gnu-ld' ; ; + ELSIF flag_imgs.$flag ; + FILTER collapse %][% flag %] + [% END ; + END; + END +-%] +[%- BLOCK cl %] class="[% SWITCH bgfor -%] + [%- CASE 'OK' %]pass[% CASE 'ContribCheck' %]warn[% CASE [ 'Check' 'InstallCheck' ] %]warnx[% CASE %]fail[% END %]" +[%- END -%] + +
+

PostgreSQL BuildFarm Status

+

+ Shown here is the latest status of each farm member + for each branch it has reported on in the last 30 days. +

+

+ Use the farm member link for history of that member + on the relevant branch. +

+ +[% FOREACH flagset IN flag_imgs %] + +[% IF loop.count == 5 %][% END %] +[% END %] +
Legend[% flagset.key %] = [% flagset.key %]
+
+ +[% brch = "" %] +[% FOREACH row IN statrows %] +[% IF row.branch != brch ; brch = row.branch %] + + +[% END %] + + + + + + + +[% END %] +
Branch: [% brch %]
AliasSystemStatusFlags
[% row.sysname %][% row.operating_system %] + [% row.os_version %] + [%- row.compiler %] + [% row.compiler_version %] + [%- row.architecture %] + [%- row.when_ago | replace('\s',' ') %] ago  + [% row.stage -%] + + [%- IF row.stage != 'OK' %]Details[% ELSE %]Config[% END -%][% FOREACH flag IN row.build_flags.split().sort() ; PROCESS img ; END %]
+
+ diff --git a/templates/dashboard.tt.ttc b/templates/dashboard.tt.ttc new file mode 100644 index 0000000..91c772a --- /dev/null +++ b/templates/dashboard.tt.ttc @@ -0,0 +1,312 @@ +#------------------------------------------------------------------------ +# Compiled template generated by the Template Toolkit version 2.14 +#------------------------------------------------------------------------ + +Template::Document->new({ + METADATA => { + 'modtime' => '1127835909', + 'name' => 'dashboard.tt', + }, + BLOCK => sub { + my $context = shift || die "template sub called without context\n"; + my $stash = $context->stash; + my $output = ''; + my $error; + + eval { BLOCK: { + #line 1 "/home/community/pgbuildfarm/templates/dashboard.tt" + $stash->set('flag_imgs', { 'perl' => '/img/camel.png', 'python' => '/img/python.png', 'debug' => '/img/bug.png', 'pam' => '/img/pam.png', 'cassert' => '/img/cassert.png', 'openssl' => '/img/ssl_icon.gif', 'nls' => '/img/translateicon.gif', 'krb5' => '/img/krb.gif', 'tcl' => '/img/tcl.png', 'thread-safety' => '/img/threads.gif', 'integer-datetimes' => '/img/days.png' }); + + + $output .= "\n
\n

PostgreSQL BuildFarm Status

\n

\n Shown here is the latest status of each farm member \n for each branch it has reported on in the last 30 days.\n

\n

\n Use the farm member link for history of that member \n on the relevant branch.\n

\n\n"; + #line 45 "/home/community/pgbuildfarm/templates/dashboard.tt" + + # FOREACH + do { + my ($value, $error, $oldloop); + my $list = $stash->get('flag_imgs'); + + unless (UNIVERSAL::isa($list, 'Template::Iterator')) { + $list = Template::Config->iterator($list) + || die $Template::Config::ERROR, "\n"; + } + + ($value, $error) = $list->get_first(); + eval { $oldloop = $stash->get('loop') }; + $stash->set('loop', $list); + eval { + LOOP: while (! $error) { + $stash->{'flagset'} = $value; + $output .= "\n\n"; + #line 44 "/home/community/pgbuildfarm/templates/dashboard.tt" + if ($stash->get(['loop', 0, 'count', 0]) eq 5) { + $output .= ""; + } + + $output .= "\n";; + ($value, $error) = $list->get_next(); + } + }; + $stash->set('loop', $oldloop); + die $@ if $@; + $error = 0 if $error && $error eq Template::Constants::STATUS_DONE; + die $error if $error; + }; + + $output .= "\n
Legendget(['flagset', 0, 'value', 0]); + $output .= "\" title=\""; + #line 43 "/home/community/pgbuildfarm/templates/dashboard.tt" + $output .= $stash->get(['flagset', 0, 'key', 0]); + $output .= "\" alt=\""; + #line 43 "/home/community/pgbuildfarm/templates/dashboard.tt" + $output .= $stash->get(['flagset', 0, 'key', 0]); + $output .= "\" height=\"16\" width=\"16\" class=\"inline\" align=\"center\"/> = "; + #line 43 "/home/community/pgbuildfarm/templates/dashboard.tt" + $output .= $stash->get(['flagset', 0, 'key', 0]); + $output .= "
\n
\n \n"; + #line 49 "/home/community/pgbuildfarm/templates/dashboard.tt" + $stash->set('brch', ''); + $output .= "\n"; + #line 81 "/home/community/pgbuildfarm/templates/dashboard.tt" + + # FOREACH + do { + my ($value, $error, $oldloop); + my $list = $stash->get('statrows'); + + unless (UNIVERSAL::isa($list, 'Template::Iterator')) { + $list = Template::Config->iterator($list) + || die $Template::Config::ERROR, "\n"; + } + + ($value, $error) = $list->get_first(); + eval { $oldloop = $stash->get('loop') }; + $stash->set('loop', $list); + eval { + LOOP: while (! $error) { + $stash->{'row'} = $value; + $output .= "\n"; + #line 54 "/home/community/pgbuildfarm/templates/dashboard.tt" + if ($stash->get(['row', 0, 'branch', 0]) ne $stash->get('brch')) { + #line 51 "/home/community/pgbuildfarm/templates/dashboard.tt" + $stash->set('brch', $stash->get(['row', 0, 'branch', 0])); + $output .= "\n\n\n"; + } + + $output .= "\nprocess('cl', { 'bgfor' => $stash->get(['row', 0, 'stage', 0]) }); + $output .= ">\n \n \n \n\n \n\n";; + ($value, $error) = $list->get_next(); + } + }; + $stash->set('loop', $oldloop); + die $@ if $@; + $error = 0 if $error && $error eq Template::Constants::STATUS_DONE; + die $error if $error; + }; + + $output .= "\n
Branch: "; + #line 52 "/home/community/pgbuildfarm/templates/dashboard.tt" + $output .= $stash->get('brch'); + $output .= "
AliasSystemStatusFlags
get(['row', 0, 'sysname', 0]); + $output .= "&br="; + #line 57 "/home/community/pgbuildfarm/templates/dashboard.tt" + $output .= $stash->get(['row', 0, 'branch', 0]); + $output .= "\"\n title=\"History\"\n >"; + #line 59 "/home/community/pgbuildfarm/templates/dashboard.tt" + $output .= $stash->get(['row', 0, 'sysname', 0]); + $output .= ""; + #line 60 "/home/community/pgbuildfarm/templates/dashboard.tt" + $output .= $stash->get(['row', 0, 'operating_system', 0]); + $output .= "\n "; + #line 61 "/home/community/pgbuildfarm/templates/dashboard.tt" + $output .= $stash->get(['row', 0, 'os_version', 0]); + $output .= " "; + #line 63 "/home/community/pgbuildfarm/templates/dashboard.tt" + $output .= $stash->get(['row', 0, 'compiler', 0]); + $output .= "\n "; + #line 64 "/home/community/pgbuildfarm/templates/dashboard.tt" + $output .= $stash->get(['row', 0, 'compiler_version', 0]); + $output .= " "; + #line 66 "/home/community/pgbuildfarm/templates/dashboard.tt" + $output .= $stash->get(['row', 0, 'architecture', 0]); + $output .= ""; + #line 69 "/home/community/pgbuildfarm/templates/dashboard.tt" + + # FILTER + $output .= do { + my $output = ''; + my $filter = $context->filter('replace', [ '\s', ' ' ]) + || $context->throw($context->error); + + $output .= $stash->get(['row', 0, 'when_ago', 0]); + + &$filter($output); + }; + + $output .= " ago \n "; + #line 70 "/home/community/pgbuildfarm/templates/dashboard.tt" + $output .= $stash->get(['row', 0, 'stage', 0]); + $output .= " get(['row', 0, 'sysname', 0]); + $output .= "&dt="; + #line 75 "/home/community/pgbuildfarm/templates/dashboard.tt" + + # FILTER + $output .= do { + my $output = ''; + my $filter = $context->filter('uri') + || $context->throw($context->error); + + $output .= $stash->get(['row', 0, 'snapshot', 0]); + + &$filter($output); + }; + + $output .= "\">"; + #line 77 "/home/community/pgbuildfarm/templates/dashboard.tt" + if ($stash->get(['row', 0, 'stage', 0]) ne 'OK') { + $output .= "Details"; + } + else { + $output .= "Config"; + } + + $output .= ""; + #line 79 "/home/community/pgbuildfarm/templates/dashboard.tt" + + # FOREACH + do { + my ($value, $error, $oldloop); + my $list = $stash->get(['row', 0, 'build_flags', 0, 'split', 0, 'sort', 0]); + + unless (UNIVERSAL::isa($list, 'Template::Iterator')) { + $list = Template::Config->iterator($list) + || die $Template::Config::ERROR, "\n"; + } + + ($value, $error) = $list->get_first(); + eval { $oldloop = $stash->get('loop') }; + $stash->set('loop', $list); + eval { + LOOP: while (! $error) { + $stash->{'flag'} = $value; + #line 79 "/home/community/pgbuildfarm/templates/dashboard.tt" + $output .= $context->process('img');; + ($value, $error) = $list->get_next(); + } + }; + $stash->set('loop', $oldloop); + die $@ if $@; + $error = 0 if $error && $error eq Template::Constants::STATUS_DONE; + die $error if $error; + }; + + $output .= "
\n
\n\n"; + } }; + if ($@) { + $error = $context->catch($@, \$output); + die $error unless $error->type eq 'return'; + } + + return $output; + }, + DEFBLOCKS => { + 'cl' => sub { + my $context = shift || die "template sub called without context\n"; + my $stash = $context->stash; + my $output = ''; + my $error; + + eval { BLOCK: { + $output .= " class=\""; + #line 27 "/home/community/pgbuildfarm/templates/dashboard.tt" + + # SWITCH + do { + my $result = $stash->get('bgfor'); + my $match; + SWITCH: { + $match = 'OK'; + $match = [ $match ] unless ref $match eq 'ARRAY'; + if (grep(/^$result$/, @$match)) { + $output .= "pass"; + last SWITCH; + } + $match = 'ContribCheck'; + $match = [ $match ] unless ref $match eq 'ARRAY'; + if (grep(/^$result$/, @$match)) { + $output .= "warn"; + last SWITCH; + } + $match = [ 'Check', 'InstallCheck' ]; + $match = [ $match ] unless ref $match eq 'ARRAY'; + if (grep(/^$result$/, @$match)) { + $output .= "warnx"; + last SWITCH; + } + $output .= "fail"; + } + }; + + $output .= "\""; + } }; + if ($@) { + $error = $context->catch($@, \$output); + die $error unless $error->type eq 'return'; + } + + return $output; + }, + 'img' => sub { + my $context = shift || die "template sub called without context\n"; + my $stash = $context->stash; + my $output = ''; + my $error; + + eval { BLOCK: { + #line 22 "/home/community/pgbuildfarm/templates/dashboard.tt" + if ($stash->get('flag') eq 'depend' || $stash->get('flag') eq 'gnu-ld') { + + } + elsif ($stash->get(['flag_imgs', 0, $stash->get('flag'), 0])) { + #line 22 "/home/community/pgbuildfarm/templates/dashboard.tt" + + # FILTER + $output .= do { + my $output = ''; + my $filter = $context->filter('collapse') + || $context->throw($context->error); + + $output .= "get(['flag_imgs', 0, $stash->get('flag'), 0]); + $output .= "\" \n title=\""; + #line 20 "/home/community/pgbuildfarm/templates/dashboard.tt" + $output .= $stash->get('flag'); + $output .= "\" alt=\""; + #line 20 "/home/community/pgbuildfarm/templates/dashboard.tt" + $output .= $stash->get('flag'); + $output .= "\" \n height=\"16\" width=\"16\" class=\"inline\" align=\"bottom\" /> \n "; + + &$filter($output); + }; + + } + + } }; + if ($@) { + $error = $context->catch($@, \$output); + die $error unless $error->type eq 'return'; + } + + return $output; + }, + }, +}); diff --git a/templates/dyn/history.tt b/templates/dyn/history.tt new file mode 100644 index 0000000..402a932 --- /dev/null +++ b/templates/dyn/history.tt @@ -0,0 +1,69 @@ +[%- BLOCK cl %] class="[% SWITCH bgfor -%] + [%- CASE 'OK' %]pass[% CASE 'ContribCheck' %]warn[% CASE [ 'Check' 'InstallCheck' ] %]warnx[% CASE %]fail[% END %]" +[%- END -%] + + + + + PostgreSQL BuildFarm History + + + + +
+ +
+

PostgreSQL BuildFarm Status History

+ + + + + + + + +
System Detail
Farm member[% member %]
OS[% statrows.0.operating_system %] [% statrows.0.os_version %]
Compiler[% statrows.0.compiler %] [% statrows.0.compiler_version %]
Architecture[% statrows.0.architecture %]
+

Branch: [% branch %][% IF statrows.size >= 240 %] (last 240 entries shown)[% END %]

+[% BLOCK stdet %] + + [%- row.when_ago | replace('\s',' ') %] ago  + [% row.stage -%] + + [%- IF row.stage != 'OK' %]Details[% ELSE %]Config[% END -%] + + +[% END %] + +[% FOREACH offset IN [0,1,2] %][% low = offset * statrows.size / 3 ; high = -1 + (offset + 1) * statrows.size / 3 %] +[% TRY %][% PERL %] + use POSIX qw(floor); + $stash->set(low => floor($stash->get('low'))); + $stash->set(high => floor($stash->get('high'))); +[% END %][% CATCH %] [% END %] + +[% END %] +
+ + [% FOREACH xrow IN statrows.slice(low,high) %][% PROCESS stdet row=xrow %][% END %] +
+
+
+ + diff --git a/templates/dyn/status.tt b/templates/dyn/status.tt new file mode 100644 index 0000000..17ee2ac --- /dev/null +++ b/templates/dyn/status.tt @@ -0,0 +1,80 @@ +[%- BLOCK cl %] class=" [% SWITCH bgfor -%] + [%- CASE 'OK' %]pass[% CASE 'ContribCheck' %]warn[% CASE [ 'Check' 'InstallCheck' ] %]warnx[% CASE %]fail[% END %]" +[%- END -%] + + + + + PostgreSQL BuildFarm Status + + + + +
+ +
+

PostgreSQL BuildFarm Status

+

+ Shown here is the latest status of each farm member + for each branch it has reported on in the last 30 days. +

+

+ Use the farm member link for history of that member + on the relevant branch. +

+ +[% brch = "" %] +[% FOREACH row IN statrows %] +[% IF row.branch != brch ; brch = row.branch %] + + +[% END %] + + + + + + +[% END %] +
Branch: [% brch %]
AliasSystemStatus
[% row.sysname %][% row.operating_system %] + [% row.os_version %] + [%- row.compiler %] + [% row.compiler_version %] + [%- row.architecture %] + [%- row.when_ago | replace('\s',' ') %] ago  + [% row.stage -%] + + [%- IF row.stage != 'OK' %]Details[% ELSE %]Config[% END -%]
+
+
+ + + + + + + + + + -- 2.30.2