aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/MGA/Advisories.pm175
1 files changed, 170 insertions, 5 deletions
diff --git a/lib/MGA/Advisories.pm b/lib/MGA/Advisories.pm
index 689ad59..aaba0f7 100644
--- a/lib/MGA/Advisories.pm
+++ b/lib/MGA/Advisories.pm
@@ -10,6 +10,8 @@ use Email::Simple;
use Email::Simple::Creator;
use LWP::UserAgent;
use File::Basename;
+use HTTP::Cookies;
+use XMLRPC::Lite;
#use Data::Dump qw(dd);
our $config_file = '/usr/share/mga-advisories/config';
@@ -33,6 +35,11 @@ my %tools = (
pkgname => sub { $_[0] =~ m/(.+)-[^-]+-[^-]+/; $1; },
);
+my %bz = (
+ proxy => undef,
+ cookies => undef,
+);
+
my @report_logs;
sub report_log {
push @report_logs, @_;
@@ -55,6 +62,93 @@ sub save_status {
DumpFile($statusfile, $advdb->{advisories}{$adv}{status});
}
+sub init_bz {
+ return 1 if ($bz{proxy});
+ return 0 if (!$config->{bugzilla_url});
+
+ my $cookiefile = $ENV{HOME} . '/.mga-advisories/bugzilla-cookies.txt';
+ if (!-d dirname($cookiefile)) {
+ return 0 unless mkdir dirname($cookiefile);
+ }
+
+ $bz{cookies} = new HTTP::Cookies(
+ file => $cookiefile,
+ ignore_discard => 1,
+ autosave => 1
+ );
+
+ # Q. Do I need to load the cookies or does this happen magically?
+
+ $bz{proxy} = XMLRPC::Lite->proxy(
+ $config->{bugzilla_url},
+ cookie_jar => $bz{cookies}
+ );
+ #$bz{proxy}->import(+trace => 'debug');
+
+ return 1;
+}
+
+sub call_bz {
+ my ($method, @args) = @_;
+
+ return 0 if (!init_bz());
+
+ my $soapresult = $bz{proxy}->call($method, @args);
+ if ($soapresult->fault) {
+ if ($soapresult->faultcode == 410) {
+ # We need to login
+
+ # Q. Do we need to save manually?
+ $bz{cookies}->save();
+ # TODO: chmod the jar... to 600
+
+ if (login_bz()) {
+ # Try the call again now we're logged in.
+ $soapresult = $bz{proxy}->call($method, @args);
+ return $soapresult->result unless $soapresult->fault;
+ }
+ }
+
+ my ($package, $filename, $line) = caller;
+ report_log(
+ $soapresult->faultcode . ' ' . $soapresult->faultstring .
+ " in SOAP call near $filename line $line."
+ );
+ return 0;
+ }
+ return $soapresult->result;
+}
+
+sub login_bz {
+ if ($config->{bugzilla_login} && $config->{bugzilla_password}) {
+ my $password = $config->{bugzilla_password};
+ if ( $password =~ /^file:\/\// ) {
+ if (open(my $fh, '<:encoding(UTF-8)', substr $password, 7)) {
+ while (my $row = <$fh>) {
+ chomp $row;
+ $password = $row;
+ last;
+ }
+ close $fh;
+ } else {
+ print STDERR "Warning: Cannot open bugzilla password file\n";
+ return 0;
+ }
+ }
+ my $soapresult = $bz{proxy}->call(
+ 'User.login',
+ {
+ login => $config->{bugzilla_login},
+ password => $password,
+ remember => 1
+ }
+ );
+ return 1 unless $soapresult->fault;
+ }
+ return 0;
+}
+
+
sub get_advisories_from_dir {
my %advisories;
foreach my $advfile (glob "$config->{advisories_dir}/*.adv") {
@@ -83,24 +177,95 @@ sub next_id {
}
sub assign_id {
- my ($bugnum) = @_;
- my $advfile = "$config->{advisories_dir}/$bugnum.adv";
+ my ($advname) = @_;
+ my $advfile = "$config->{advisories_dir}/$advname.adv";
$advfile =~ s/\.adv\.adv$/.adv/;
my $adv = LoadFile($advfile);
if ($adv->{ID}) {
- print STDERR "$bugnum already has an ID assigned: $adv->{ID}\n";
+ print STDERR "$advname already has an ID assigned: $adv->{ID}\n";
return;
}
my $type = $config->{advisory_types}{$adv->{type}}{prefix};
if (!$type) {
- print STDERR "Unknow type $adv->{type}\n";
+ print STDERR "Unknown type $adv->{type}\n";
return;
}
+
+ if (!init_bz()) {
+ print STDERR "Warning: Cannot check bugzilla. Please double check manually\n";
+ } else {
+ # Advisories are not always just [0-9]+.adv, but are
+ # sometimes [0-9]+.mga3.adv etc. so extract the real bug number
+ # Perhaps this should actually be the first bug from the advisory references?
+ my $bugnum = $advname;
+ $bugnum =~ s/[^0-9]//g;
+
+ if (my $result = call_bz('Bug.get', {ids => [$bugnum]})) {
+ my $failed = 0;
+ my $bug = $result->{bugs}->[0];
+ print "Found Bug: " . $bug->{summary} . "\n";
+
+ printf "%-40s", "Checking for QA validation keyword… ";
+ my $found_keyword = 0;
+ if (scalar($bug->{keywords}) > 0) {
+ my $keywords = $bug->{keywords};
+ foreach my $keyword (@$keywords) {
+ if ('validated_update' eq $keyword) {
+ $found_keyword = 1;
+ last;
+ }
+ }
+ }
+ if ($found_keyword) {
+ print "✔\n";
+ } else {
+ print "✘\n";
+ $failed = 1;
+ }
+
+ printf "%-40s", "Checking dependent bugs… ";
+ my $depends = $bug->{depends_on};
+ if (scalar(@$depends) < 1) {
+ print "✔ (None found)\n";
+ } else {
+ my $first = 1;
+ foreach my $dependent_bug_num (@$depends) {
+ print ', ' if (!$first);
+ $first = 0;
+
+ if ($result = call_bz('Bug.get', {ids => [$dependent_bug_num]})) {
+ my $blocking_bug = $result->{bugs}->[0];
+
+ if ($blocking_bug->{is_open}) {
+ print "✘ $dependent_bug_num";
+ $failed = 1;
+ } else {
+ print "✔ $dependent_bug_num";
+ }
+ } else {
+ print "? $dependent_bug_num\n";
+ print STDERR "Error: There was a problem communicating with bugzilla for bug $dependent_bug_num\n";
+ return;
+ }
+ }
+ print "\n";
+ }
+
+ if ($failed) {
+ print STDERR "Error: Bugzilla cross check failed.\n";
+ return;
+ }
+ } else {
+ print STDERR "Warning: Cannot check bugzilla. Please double check manually\n";
+ }
+ }
+
+ printf "%-40s", "Assigning ID to advisory $advname… ";
$adv->{ID} = next_id($type, keys %{get_advisories_from_dir()});
open(my $fh, '>>', $advfile) or die "Error opening $advfile";
print $fh "ID: $adv->{ID}\n";
close $fh;
- print "Assigned ID $adv->{ID} to advisory $bugnum\n";
+ print "✔ $adv->{ID}\n";
}
sub advdb_dumpfile {