[PATCH 3/7] testbot/WineSendLog: Add proper command line handling and options.

Francois Gouget fgouget at codeweavers.com
Tue Jun 26 06:29:25 CDT 2018


When run in --debug mode WineSendLog prints the emails it would normally
send instead of piping them to sendmail.
Also the script now prints the error messages to stderr by default to
make it easier to figure things out when running it on the command
line. The --log-only option can be used when that's not desired.

Signed-off-by: Francois Gouget <fgouget at codeweavers.com>
---
 testbot/bin/Engine.pl      |   2 +-
 testbot/bin/WineSendLog.pl | 193 +++++++++++++++++++++++++++++++------
 2 files changed, 164 insertions(+), 31 deletions(-)

diff --git a/testbot/bin/Engine.pl b/testbot/bin/Engine.pl
index ce3509440..464b6db45 100755
--- a/testbot/bin/Engine.pl
+++ b/testbot/bin/Engine.pl
@@ -320,7 +320,7 @@ sub HandleJobStatusChange($$$)
       CloseAllDBBackEnds();
       WineTestBot::Log::SetupRedirects();
 
-      exec("$BinDir/${ProjectName}SendLog.pl $JobKey") or
+      exec("$BinDir/${ProjectName}SendLog.pl --log-only $JobKey") or
       LogMsg "Unable to exec ${ProjectName}SendLog.pl: $!\n";
       exit(1);
     }
diff --git a/testbot/bin/WineSendLog.pl b/testbot/bin/WineSendLog.pl
index e03395af1..ed3453b80 100755
--- a/testbot/bin/WineSendLog.pl
+++ b/testbot/bin/WineSendLog.pl
@@ -36,14 +36,47 @@ sub BEGIN
     unshift @INC, "$::RootDir/lib";
   }
 }
+my $Name0 = $0;
+$Name0 =~ s+^.*/++;
+
 
 use Algorithm::Diff;
+
 use WineTestBot::Config;
 use WineTestBot::Jobs;
 use WineTestBot::Log;
 use WineTestBot::StepsTasks;
 
 
+#
+# Logging and error handling helpers
+#
+
+my $Debug;
+sub Debug(@)
+{
+  print STDERR @_ if ($Debug);
+}
+
+sub DebugTee($@)
+{
+  my ($File) = shift;
+  print $File @_;
+  Debug(@_);
+}
+
+my $LogOnly;
+sub Error(@)
+{
+  print STDERR "$Name0:error: ", @_ if (!$LogOnly);
+  LogMsg @_;
+}
+
+
+#
+# Log analysis
+#
+
 sub IsBotFailure($)
 {
   my ($ErrLine) = @_;
@@ -121,7 +154,7 @@ sub ReadLog($$$)
   }
   else
   {
-    LogMsg "Unable to open '$LogName' for reading: $!\n";
+    Error "Unable to open '$LogName' for reading: $!\n";
   }
 
   return \@Messages;
@@ -179,7 +212,19 @@ sub SendLog($)
   my $StepsTasks = CreateStepsTasks(undef, $Job);
   my @SortedKeys = sort @{$StepsTasks->GetKeys()};
 
-  open (SENDMAIL, "|/usr/sbin/sendmail -oi -t -odq");
+  #
+  # Send a job summary and all the logs as attachments to the developer
+  #
+
+  Debug("-------------------- Developer email --------------------\n");
+  if ($Debug)
+  {
+    open(SENDMAIL, ">>&=", 1);
+  }
+  else
+  {
+    open (SENDMAIL, "|/usr/sbin/sendmail -oi -t -odq");
+  }
   print SENDMAIL "From: $RobotEMail\n";
   print SENDMAIL "To: $To\n";
   my $Subject = "TestBot job " . $Job->Id . " results";
@@ -218,6 +263,7 @@ EOF
                     $TestFailures;
   }
 
+  # Print the job summary
   my @FailureKeys;
   foreach my $Key (@SortedKeys)
   {
@@ -322,6 +368,7 @@ EOF
     }
   }
 
+  # Print the log attachments
   foreach my $Key (@SortedKeys)
   {
     my $StepTask = $StepsTasks->GetItem($Key);
@@ -334,6 +381,7 @@ Content-Transfer-Encoding: 8bit
 EOF
     print SENDMAIL "Content-Disposition: attachment; filename=",
                    $StepTask->VM->Name, ".log\n\n";
+    print SENDMAIL "Not dumping logs in debug mode\n" if ($Debug);
 
     my $PrintSeparator = !1;
     my $TaskDir = $StepTask->GetTaskDir();
@@ -343,7 +391,7 @@ EOF
       while (defined($Line = <LOGFILE>))
       {
         $Line =~ s/\s*$//;
-        print SENDMAIL "$Line\n";
+        print SENDMAIL "$Line\n" if (!$Debug);
         $PrintSeparator = 1;
       }
       close LOGFILE;
@@ -356,11 +404,11 @@ EOF
       {
         if ($PrintSeparator)
         {
-          print SENDMAIL "\n";
+          print SENDMAIL "\n" if (!$Debug);
           $PrintSeparator = !1;
         }
         $Line =~ s/\s*$//;
-        print SENDMAIL "$Line\n";
+        print SENDMAIL "$Line\n" if (!$Debug);
       }
       close ERRFILE;
     }
@@ -369,10 +417,12 @@ EOF
   print SENDMAIL "--==13F70BD1-BA1B-449A-9CCB-B6A8E90CED47==--\n";
   close(SENDMAIL);
 
-  if (! defined($Job->Patch))
-  {
-    return;
-  }
+  # This is all for jobs submitted from the website
+  return if (!defined $Job->Patch);
+
+  #
+  # Build a job summary with only the new errors
+  #
 
   my $Messages = "";
   foreach my $Key (@FailureKeys)
@@ -401,7 +451,7 @@ EOF
       }
       else
       {
-        LogMsg "BotFailure found in ${LatestName}.err\n";
+        Error "BotFailure found in ${LatestName}.err\n";
       }
       if ($MessagesFromErr || $MessagesFromLog)
       {
@@ -411,15 +461,28 @@ EOF
     }
     elsif ($BotFailure)
     {
-      LogMsg "BotFailure found in $TaskDir/err\n";
+      Error "BotFailure found in $TaskDir/err\n";
     }
   }
 
+  #
+  # Send a summary of the new errors to the mailing list
+  #
+
+  Debug("\n-------------------- Mailing list email --------------------\n");
+
   my $WebSite = ($UseSSL ? "https://" : "http://") . $WebHostName;
 
   if ($Messages)
   {
-    open (SENDMAIL, "|/usr/sbin/sendmail -oi -t -odq");
+    if ($Debug)
+    {
+      open(SENDMAIL, ">>&=", 1);
+    }
+    else
+    {
+      open (SENDMAIL, "|/usr/sbin/sendmail -oi -t -odq");
+    }
     print SENDMAIL "From: $RobotEMail\n";
     print SENDMAIL "To: $To\n";
     print SENDMAIL "Cc: $WinePatchCc\n";
@@ -445,6 +508,14 @@ EOF
     print SENDMAIL $Messages;
     close SENDMAIL;
   }
+  else
+  {
+    Debug("Found no error to report to the mailing list\n");
+  }
+
+  #
+  # Create a .testbot file for the patches website
+  #
 
   my $Patch = $Job->Patch;
   if (defined $Patch->WebPatchId and -d "$DataDir/webpatches")
@@ -452,9 +523,12 @@ EOF
     my $BaseName = "$DataDir/webpatches/" . $Patch->WebPatchId;
     if (open (my $result, ">", "$BaseName.testbot"))
     {
-      print $result "Status: " . ($Messages ? "Failed" : "OK") . "\n";
-      print $result "Job-ID: " . $Job->Id . "\n";
-      print $result "URL: $WebSite/JobDetails.pl?Key=" . $Job->GetKey() . "\n";
+      Debug("\n-------------------- WebPatches report --------------------\n");
+      # Only take into account new errors to decide whether the job was
+      # successful or not.
+      DebugTee($result, "Status: ". ($Messages ? "Failed" : "OK") ."\n");
+      DebugTee($result, "Job-ID: ". $Job->Id ."\n");
+      DebugTee($result, "URL: $WebSite/JobDetails.pl?Key=". $Job->GetKey() ."\n");
 
       foreach my $Key (@SortedKeys)
       {
@@ -496,7 +570,7 @@ EOF
     }
     else
     {
-      LogMsg "Job " . $Job->Id . ": Unable to open '$BaseName.testbot' for writing: $!";
+      Error "Job ". $Job->Id .": Unable to open '$BaseName.testbot' for writing: $!";
     }
   }
 }
@@ -509,37 +583,96 @@ EOF
 $ENV{PATH} = "/usr/bin:/bin";
 delete $ENV{ENV};
 
-my $JobId = $ARGV[0];
-if (! $JobId)
+my $Usage;
+sub ValidateNumber($$)
+{
+  my ($Name, $Value) = @_;
+
+  # Validate and untaint the value
+  return $1 if ($Value =~ /^(\d+)$/);
+  Error "$Value is not a valid $Name\n";
+  $Usage = 2;
+  return undef;
+}
+
+my ($JobId);
+while (@ARGV)
 {
-  die "Usage: WineSendLog.pl JobId";
+  my $Arg = shift @ARGV;
+  if ($Arg eq "--debug")
+  {
+    $Debug = 1;
+  }
+  elsif ($Arg eq "--log-only")
+  {
+    $LogOnly = 1;
+  }
+  elsif ($Arg =~ /^(?:-\?|-h|--help)$/)
+  {
+    $Usage = 0;
+    last;
+  }
+  elsif ($Arg =~ /^-/)
+  {
+    Error "unknown option '$Arg'\n";
+    $Usage = 2;
+    last;
+  }
+  elsif (!defined $JobId)
+  {
+    $JobId = ValidateNumber('job id', $Arg);
+  }
+  else
+  {
+    Error "unexpected argument '$Arg'\n";
+    $Usage = 2;
+    last;
+  }
 }
 
-# Untaint parameters
-if ($JobId =~ /^(\d+)$/)
+# Check parameters
+if (!defined $Usage)
 {
-  $JobId = $1;
+  if (!defined $JobId)
+  {
+    Error "you must specify the job id\n";
+    $Usage = 2;
+  }
 }
-else
+if (defined $Usage)
 {
-  LogMsg "Invalid JobId $JobId\n";
-  exit(1);
+  if ($Usage)
+  {
+    Error "try '$Name0 --help' for more information\n";
+    exit $Usage;
+  }
+  print "Usage: $Name0 [--debug] [--help] JOBID\n";
+  print "\n";
+  print "Analyze the job's logs and notifies the developer and the patches website.\n";
+  print "\n";
+  print "Where:\n";
+  print "  JOBID      Id of the job to report on.\n";
+  print "  --debug    More verbose messages for debugging.\n";
+  print "  --log-only Only send error messages to the log instead of also printing them\n";
+  print "             on stderr.\n";
+  print "  --help     Shows this usage message.\n";
+  exit 0;
 }
 
 my $Job = CreateJobs()->GetItem($JobId);
-if (! defined($Job))
+if (!defined $Job)
 {
-  LogMsg "Job $JobId doesn't exist\n";
-  exit(1);
+  Error "Job $JobId doesn't exist\n";
+  exit 1;
 }
 
 
 #
-# Analyze the log and notify the developer
+# Analyze the log, notify the developer and the Patches website
 #
 
 SendLog($Job);
 
 LogMsg "Log for job $JobId sent\n";
 
-exit(0);
+exit 0;
-- 
2.18.0




More information about the wine-devel mailing list