#!perl use warnings; use POSIX; use WWW::Mechanize; use Getopt::Long; # get options GetOptions ("build-output=s" => \$arg_build_output, "twiki-server=s" => \$arg_twiki_server, "twiki-web=s" => \$arg_twiki_web, "twiki-parent-topic=s" => \$arg_twiki_parent_topic, "twiki-project-title=s" => \$arg_twiki_project_title, "twiki-username=s" => \$arg_twiki_username, "twiki-password=s" => \$arg_twiki_password ); # die "E: Missing arguments\n" unless (defined $arg_twiki_server && defined $arg_twiki_web && defined $arg_build_output && defined $arg_twiki_parent_topic && defined $arg_twiki_project_title); die "E: Build output file is not a file: '$arg_build_output'\n" unless (-f $arg_build_output); # # $mech->post( $url, Content => ["username"=>"smurf", Smurf=>Smurf]); # # # open and parse open BUILD, "$arg_build_output" or die "E: Couldn't open '$arg_build_output': $!\n"; my @build_lines = ; close BUILD; # # parse my $twiki_output = ""; my $separator = "-" x 80; my %simple_build_bot_params; my %simple_build_bot_env; my $project_title; my $build_date_and_time; my $source_safe_getting_result; my $source_safe_setting_result; my $source_safe_project; my $build_solution; my $build_solution_config; my $build_project_succeeded; my $build_project_failed; my $build_project_skipped; my %build_projects; my $devenv_state_current_project; # states my $parse_state = "SIMPLE-BUILD-BOT"; my @devenv_current_project_link_errors; my @devenv_current_project_link_warnings; my @devenv_current_project_compile_errors; my @devenv_current_project_compile_warnings; print STDERR "I: START PARSE\n"; foreach (@build_lines) { ## print; chomp ($line = $_); if ($line eq $separator) { # print STDERR "I: Skipped SEPARATOR\n"; next; } # parse the output info about the build-bot-invocation if ($parse_state eq "SIMPLE-BUILD-BOT") { if ($line =~ /^ENV contains this variables/) { $parse_state = "SIMPLE-BUILD-BOT-ENV"; # print STDERR "I: ENTER SIMPLE-BUILD-BOT-ENV\n"; next; } if ($line =~ /^ --([a-z-]+): '(.*)'$/) { $simple_build_bot_params{$1} = $2; } next; } #end of SIMPLE-BUILD-BOT if ($parse_state eq "SIMPLE-BUILD-BOT-ENV") { if ($line =~ /^Starting automatic build for (.*?) at (.*)/) { # print STDERR "I: ENTER SOURCE-SAFE-WORKFOLD\n"; $parse_state = "SOURCE-SAFE-WORKFOLD"; $project_title = $1; $build_date_and_time = $2; next; } if ($line =~ /([A-Z0-9_-]+) = '(.*)'$/) { $simple_build_bot_env{$1} = $2; next; } next; } # end of SIMPLE-BUILD-BOT-ENV if ($parse_state eq "SOURCE-SAFE-WORKFOLD") { if ($line =~ /^Getting SourceSafe project .*\(([0-9]+)\)/) { $source_safe_getting_result = $1; $parse_state = "SOURCE-SAFE-GETTING"; # print STDERR "I: ENTER SOURCE-SAFE-GETTING\n"; next; } if ($line =~ /^Setting SourceSafe working folder for project (.*?) \(([0-9]+)\):/) { $source_safe_project = $1; $source_safe_setting_result = $2; } next; } # end of SOURCE-SAFE-PREPARE if ($parse_state eq "SOURCE-SAFE-GETTING") { if ($line =~ /^Building '(.*?)' with config '(.*?)'/) { $parse_state = "DEVENV-BUILD"; # print STDERR "I: ENTER DEVENV-BUILD\n"; $build_solution = $1; $build_solution_config = $2; next; } next if ($line !~ /^\s*$/); if ($line =~ /:$/) { push(@source_safe_get_files, "DIR" . $line); next; } push(@source_safe_get_files, $line); next; } # end of SOURCE-SAFE-GETTING if ($parse_state eq "DEVENV-BUILD") { if ($line =~ /Rebuild All: ([0-9]+) succeeded, ([0-9]+) failed, ([0-9]+) skipped/) { $parse_state = "GET-THE-LAST-BITS"; # print STDERR "I: ENTER GET-THE-LAST-BITS\n"; $build_project_succeeded = $1; $build_project_failed = $2; $build_project_skipped = $3; next; } if ($line =~ /^------ Rebuild All started: Project: ([a-zA-Z0-9]+), Configuration: (.*?) ------$/) { $parse_state = "DEVENV-PROJECT-BUILD"; # print STDERR "I: DEVENV-PROJECT-BUILD\n"; $devenv_state_current_project = $1; $devenv_state_current_configuration = $2; @devenv_current_project_link_errors = (); @devenv_current_project_link_warnings = (); @devenv_current_project_compile_errors = (); @devenv_current_project_compile_warnings = (); $build_projects{$devenv_state_current_project}->{"config"} = $devenv_state_current_configuration; next; } next; } # end of DEVENV-BUILD if ($parse_state eq "DEVENV-PROJECT-BUILD") { if ($line =~ /Rebuild All: ([0-9]+) succeeded, ([0-9]+) failed, ([0-9]+) skipped/) { $parse_state = "GET-THE-LAST-BITS"; # print STDERR "I: ENTER GET-THE-LAST-BITS\n"; $build_project_succeeded = $1; $build_project_failed = $2; $build_project_skipped = $3; next; } if ($line =~ /(.*?) - ([0-9]+) error\(s\), ([0-9]+) warning/) { if ($devenv_state_current_project ne $1) { print STDERR "E: PARSE ERROR BECAUSE CURRENT PROJECT IS NOT EQUAL TO COMPILED PROJECT\n"; next; } $build_projects{$devenv_state_current_project}->{"num-errors"} = $2; $build_projects{$devenv_state_current_project}->{"num-warnings"} = $3; $build_projects{$devenv_state_current_project}->{"link-errors"} = [ @devenv_current_project_link_errors ]; $build_projects{$devenv_state_current_project}->{"link-warnings"} = [ @devenv_current_project_link_errors ]; $build_projects{$devenv_state_current_project}->{"compile-errors"} = [ @devenv_current_project_compile_errors ]; $build_projects{$devenv_state_current_project}->{"compile-warnings"} = [ @devenv_current_project_compile_warnings ]; $parse_state = "DEVENV-BUILD"; # print STDERR "I: ENTER DEVENV-BUILD\n"; next; } if ($line =~ /Compiling\.\.\./) { $parse_state = "DEVENV-PROJECT-BUILD-COMPILING"; # print STDERR "I: ENTER DEVENV-PROJECT-BUILD-COMPILING"; next; } next; } # end of DEVENV-PROJECT-BUILD if ($parse_state eq "DEVENV-PROJECT-BUILD-COMPILING") { if ($line =~ /Generating code\.\.\./) { $parse_state = "DEVENV-PROJECT-BUILD-GENERATING"; # print STDERR "I: ENTER DEVENV-PROJECT-BUILD-GENERATING\n"; next; } if ($line =~ /Linking\.\.\./) { $parse_state = "DEVENV-PROJECT-BUILD-LINKING"; # print STDERR "I: ENTER DEVENV-PROJECT-BUILD-LINKING\n"; next; } if ($line =~ /warning (C[0-9]+):/) { push (@devenv_current_project_compile_warnings, $line); next; } if ($line =~ /error (C[0-9]+):/) { push (@devenv_current_project_compile_errors, $line); next; } next; } # end of DEVENV-PROJECT-BUILD-COMPILING if ($parse_state eq "DEVENV-PROJECT-BUILD-GENERATING") { if ($line =~ /Linking\.\.\./) { $parse_state = "DEVENV-PROJECT-BUILD-LINKING"; # print STDERR "I: ENTER DEVENV-PROJECT-BUILD-LINKING\n"; next; } if ($line =~ /Compiling\.\.\./) { $parse_state = "DEVENV-PROJECT-BUILD-COMPILING"; # print STDERR "I: ENTER DEVENV-PROJECT-BUILD-COMPILING\n"; next; } next; } # end of DEVENV-PROJECT-BUILD-GENERATING if ($parse_state eq "DEVENV-PROJECT-BUILD-LINKING") { if ($line =~ /^Build log was saved at/) { $parse_state = "DEVENV-PROJECT-BUILD"; # print STDERR "I: ENTER DEVENV-PROJECT-BUILD\n"; next; } if ($line =~ /warning (LNK[0-9]+):/) { push (@devenv_current_project_link_warnings, $line); next; } if ($line =~ /error (LNK[0-9]+):/) { push (@devenv_current_project_link_errors, $line); next; } next; } # end of DEVENV-PROJECT-BUILD-LINKING } # # output stuff # my $wiki_topic_text = ""; if ($build_project_failed > 0) { $wiki_topic_text .= "\%BOX{\"RED\"}\%\n"; $wiki_topic_text .= "
__BUILD FAILED__
\n"; $wiki_topic_text .= "\%ENDBOX\%\n\n"; } else { $wiki_topic_text .= "\%BOX{\"GREEN\"}\%\n"; $wiki_topic_text .= "
__BUILD SUCCEEDED__
\n"; $wiki_topic_text .= "\%ENDBOX\%\n\n"; } $wiki_topic_text .= "---+ Build Log of $project_title from $build_date_and_time\n\n"; $wiki_topic_text .= "\%TOC\%\n\n"; $wiki_topic_text .= "---++ Build Statistics\n\n"; my $number_of_projects = $build_project_succeeded + $build_project_failed + $build_project_skipped; $wiki_topic_text .= "| *Number of projects* | *Succeeded* | *Failed* | *Skipped* |\n"; $wiki_topic_text .= "| *$number_of_projects* | $build_project_succeeded | $build_project_failed | $build_project_skipped |\n\n"; $wiki_topic_text .= "| *Project* | *Compile* || *Link* || *State* |\n"; $wiki_topic_text .= "|^| *Warnings* | *Errors* | *Warnings* | *Errors* |^|\n"; my $sum_lerr = 0; my $sum_cerr = 0; my $sum_lwar = 0; my $sum_cwar = 0; foreach my $project (keys %build_projects) { my $lerr = scalar(@{$build_projects{$project}->{"link-errors"}}); my $lwar = scalar(@{$build_projects{$project}->{"link-warnings"}}); my $cerr = scalar(@{$build_projects{$project}->{"compile-errors"}}); my $cwar = scalar(@{$build_projects{$project}->{"compile-warnings"}}); my $state = ""; if ($lerr == 0 && $lwar == 0 && $cerr == 0 && $cwar == 0) { $state = "\%GREEN\% __perfect__ \%ENDCOLOR\%"; } elsif ($lerr == 0 && $cerr == 0 && ($cwar != 0 || $lwar != 0)) { $state = "\%ORANGE\% __warnings__ \%ENDCOLOR\%"; } else { $state = "\%RED\% __FAILED__ \%ENDCOLOR\%"; } $sum_lerr += $lerr; $sum_cerr += $cerr; $sum_lwar += $lwar; $sum_cwar += $cwar; $lerr = "*${lerr}*" if $lerr != 0; $cerr = "*${cerr}*" if $cerr != 0; $lwar = "*${lwar}*" if $lwar != 0; $cwar = "*${cwar}*" if $cwar != 0; $wiki_topic_text .= "| $project | $cerr | $cwar | $lerr | $lwar | $state |\n"; } $wiki_topic_text .= "| *Sum* | *$sum_cerr* | *$sum_cwar* | *$sum_lerr* | *$sum_lwar* | |\n"; $wiki_topic_text .= "\n\n"; $wiki_topic_text .= "---++ Project Details\n\n"; foreach my $project (keys %build_projects) { $wiki_topic_text .= "---+++ Project: $project\n\n"; if (scalar(@{$build_projects{$project}->{"compile-warnings"}}) == 0 && scalar(@{$build_projects{$project}->{"compile-errors"}}) == 0) { $wiki_topic_text .= " * *Compile stage completed without errors and warnings*\n"; } else { $wiki_topic_text .= "---++++ Compilation\n"; if (scalar(@{$build_projects{$project}->{"compile-warnings"}}) > 0) { $wiki_topic_text .= "---+++++ Warnings\n\n"; foreach my $warning (@{$build_projects{$project}->{"compile-warnings"}}) { chomp ($warning); $wiki_topic_text .= " * $warning\n"; } } if (scalar(@{$build_projects{$project}->{"compile-errors"}}) > 0) { $wiki_topic_text .= "---+++++ Errors\n\n"; foreach my $error (@{$build_projects{$project}->{"compile-errors"}}) { chomp ($warning); $wiki_topic_text .= " * $error\n"; } } } if (scalar(@{$build_projects{$project}->{"link-warnings"}}) == 0 && scalar(@{$build_projects{$project}->{"link-errors"}}) == 0) { $wiki_topic_text .= " * *Link stage completed without errors and warnings*\n"; } else { $wiki_topic_text .= "---++++ Linking\n"; if (scalar(@{$build_projects{$project}->{"link-warnings"}}) > 0) { $wiki_topic_text .= "---+++++ Warnings\n\n"; foreach my $warning (@{$build_projects{$project}->{"link-warnings"}}) { chomp ($warning); $wiki_topic_text .= " * $warning\n"; } } if (scalar(@{$build_projects{$project}->{"link-errors"}}) > 0) { $wiki_topic_text .= "---+++++ Errors\n\n"; foreach my $error (@{$build_projects{$project}->{"link-errors"}}) { chomp ($warning); $wiki_topic_text .= " * $error\n"; } } } } $wiki_topic_text .= "\n\n---++ Environment Information\n"; $wiki_topic_text .= "\n\n---+++ simple-build-bot.pl Invocation Parameters\n\n"; $wiki_topic_text .= "| *Param* | *Value* |\n"; foreach (keys %simple_build_bot_params) { if (/^vss-password$/) { $wiki_topic_text .= "| $_ | =PASSWORD HIDDEN= |\n"; } else { $wiki_topic_text .= "| $_ | =$simple_build_bot_params{$_}= |\n"; } } $wiki_topic_text .= "\n\n"; $wiki_topic_text .= "\n\n---+++ Environment Variables\n\n"; $wiki_topic_text .= "| *Key* | *Value* |\n"; foreach (keys %simple_build_bot_env) { if (/^PATH$/ || /^LIB$/ || /^INCLUDE$/) { $wiki_topic_text .= "| $_ | "; foreach my $path (split(";", $simple_build_bot_env{$_})) { $wiki_topic_text .= "=$path= \%BR\% "; } $wiki_topic_text .= "|\n"; } elsif (/^SSPASS^/) { $wiki_topic_text .= "| $_ | =PASSWORD HIDDEN= |\n"; } else { $wiki_topic_text .= "| $_ | =$simple_build_bot_env{$_}= |\n"; } } $wiki_topic_text .= "\n\n---++ Complete Build output\n"; $wiki_topic_text .= "
\n";
my $last_was_hr = 0;
foreach (@build_lines) {
  chomp;
  if ($_ eq "-" x 80) {
    if (!$last_was_hr) {
      $twiki_topic_text .= "\n
\n"; $last_was_hr = 1; } next; } else { $last_was_hr = 0; } if (/warning [LC]/) { $wiki_topic_text .= "\%ORANGE\%${_}\%ENDCOLOR\%\n"; next; } if (/error [LC]/) { $wiki_topic_text .= "\%RED\%${_}\%ENDCOLOR\%\n"; next; } $twiki_topic_text .= $_ . "\n"; } $wiki_topic_text .= "
\n\n"; $wiki_topic_text .= strftime ("-- Main.BuildBot - %d %b %Y", localtime); # # upload topic # { package MyMech; our @ISA = qw(WWW::Mechanize); sub get_basic_credentials { return ($arg_twiki_username, $arg_twiki_password); } } my $agent = MyMech->new(); my $great_date = $build_date_and_time; $great_date =~ s/[^0-9]//g; my $twiki_url = "http://${arg_twiki_server}/cgi-bin/twiki/edit/${arg_twiki_web}/BuildLog${arg_twiki_project_title}${great_date}?templatetopic=BuildLogTemplate&topicparent=BuildLogs&Date=${build_date_and_time}&Project=${arg_twiki_project_title}&"; if ($build_project_failed > 0) { $twiki_url .= "State=Failure (Need Investigation)"; } else { $twiki_url .= "State=Success"; } # get the empty page $agent->get ($twiki_url) or die "E: GURGEL\n"; print $agent->content(); print "\n\n$twiki_url\n\n"; exit 0; $agent->form_name ("main") or die "E: SMURFA!\n"; $agent->field ("text", $twiki_output); my $response = $agent->click_button (name => "action", value => "Save"); die "E: AAAAAAAAAAARRRGGGHHH" unless $response->is_success;