From 828eed60025b20f5908b195d135c3f4cab59ef7d Mon Sep 17 00:00:00 2001 From: dklawren Date: Wed, 28 Feb 2018 10:00:05 -0500 Subject: Bug 1437384 - phabbugz_feed.pl in PhabBugz extension should be extended to also query for new users in Phab --- extensions/PhabBugz/bin/update_project_members.pl | 8 +- extensions/PhabBugz/lib/Feed.pm | 206 ++++++++++++++++++---- extensions/PhabBugz/lib/Revision.pm | 1 + 3 files changed, 181 insertions(+), 34 deletions(-) (limited to 'extensions') diff --git a/extensions/PhabBugz/bin/update_project_members.pl b/extensions/PhabBugz/bin/update_project_members.pl index a0449a915..2a305da3d 100755 --- a/extensions/PhabBugz/bin/update_project_members.pl +++ b/extensions/PhabBugz/bin/update_project_members.pl @@ -65,10 +65,10 @@ foreach my $group (@$sync_groups) { }); } - my @group_members = get_group_members($group); - - $project->set_members(\@group_members); - $project->update(); + if (my @group_members = get_group_members($group)) { + $project->set_members(\@group_members); + $project->update(); + } } sub get_group_members { diff --git a/extensions/PhabBugz/lib/Feed.pm b/extensions/PhabBugz/lib/Feed.pm index f91d108ec..c7d6d0a29 100644 --- a/extensions/PhabBugz/lib/Feed.pm +++ b/extensions/PhabBugz/lib/Feed.pm @@ -14,11 +14,13 @@ use List::MoreUtils qw(any); use Moo; use Bugzilla::Constants; +use Bugzilla::Search; use Bugzilla::Util qw(diff_arrays); use Bugzilla::Extension::PhabBugz::Constants; use Bugzilla::Extension::PhabBugz::Policy; use Bugzilla::Extension::PhabBugz::Revision; +use Bugzilla::Extension::PhabBugz::User; use Bugzilla::Extension::PhabBugz::Util qw( add_security_sync_comments create_private_revision_policy @@ -61,22 +63,18 @@ sub feed_query { return; } + # PROCESS NEW FEED TRANSACTIONS + $self->logger->info("FEED: Fetching new transactions"); - my $last_id = $dbh->selectrow_array(" - SELECT value FROM phabbugz WHERE name = 'feed_last_id'"); - $last_id ||= 0; - $self->logger->debug("QUERY LAST_ID: $last_id"); + my $story_last_id = $self->get_last_id('feed'); # Check for new transctions (stories) - my $transactions = $self->feed_transactions($last_id); - if (!@$transactions) { - $self->logger->info("FEED: No new transactions"); - return; - } + my $new_stories = $self->new_stories($story_last_id); + $self->logger->info("FEED: No new stories") unless @$new_stories; # Process each story - foreach my $story_data (@$transactions) { + foreach my $story_data (@$new_stories) { my $story_id = $story_data->{id}; my $story_phid = $story_data->{phid}; my $author_phid = $story_data->{authorPHID}; @@ -92,7 +90,7 @@ sub feed_query { # Only interested in changes to revisions for now. if ($object_phid !~ /^PHID-DREV/) { $self->logger->debug("SKIPPING: Not a revision change"); - $self->save_feed_last_id($story_id); + $self->save_last_id($story_id, 'feed'); next; } @@ -102,22 +100,40 @@ sub feed_query { my $user = Bugzilla::User->new({ id => $phab_users->[0]->{id}, cache => 1 }); if ($user->login eq PHAB_AUTOMATION_USER) { $self->logger->debug("SKIPPING: Change made by phabricator user"); - $self->save_feed_last_id($story_id); + $self->save_last_id($story_id, 'feed'); next; } } $self->process_revision_change($object_phid, $story_text); - $self->save_feed_last_id($story_id); + $self->save_last_id($story_id, 'feed'); } -} -sub save_feed_last_id { - my ($self, $story_id) = @_; - # Store the largest last key so we can start from there in the next session - $self->logger->debug("UPDATING FEED_LAST_ID: $story_id"); - Bugzilla->dbh->do("REPLACE INTO phabbugz (name, value) VALUES ('feed_last_id', ?)", - undef, $story_id); + # PROCESS NEW USERS + + $self->logger->info("FEED: Fetching new users"); + + my $user_last_id = $self->get_last_id('user'); + + # Check for new users + my $new_users = $self->new_users($user_last_id); + $self->logger->info("FEED: No new users") unless @$new_users; + + # Process each new user + foreach my $user_data (@$new_users) { + my $user_id = $user_data->{id}; + my $user_login = $user_data->{fields}{username}; + my $user_realname = $user_data->{fields}{realName}; + my $object_phid = $user_data->{phid}; + + $self->logger->debug("USER ID: $user_id"); + $self->logger->debug("USER LOGIN: $user_login"); + $self->logger->debug("USER REALNAME: $user_realname"); + $self->logger->debug("OBJECT PHID: $object_phid"); + + $self->process_new_user($user_data); + $self->save_last_id($user_id, 'user'); + } } sub process_revision_change { @@ -154,10 +170,7 @@ sub process_revision_change { # Pre setup before making changes my $old_user = set_phab_user(); - - my $is_shadow_db = Bugzilla->is_shadow_db; - Bugzilla->switch_to_main_db if $is_shadow_db; - + my $is_shadow_db = Bugzilla->is_shadow_db; Bugzilla->switch_to_main_db if $is_shadow_db; my $dbh = Bugzilla->dbh; $dbh->bz_start_transaction; @@ -347,21 +360,154 @@ sub process_revision_change { Bugzilla->set_user($old_user); - $self->logger->info("SUCCESS"); + $self->logger->info('SUCCESS: Revision D' . $revision->id . ' processed'); } -sub feed_transactions { - my ($self, $after) = @_; +sub process_new_user { + my ( $self, $user_data ) = @_; + + # Load the user data into a proper object + my $phab_user = Bugzilla::Extension::PhabBugz::User->new($user_data); + + if (!$phab_user->bugzilla_id) { + $self->logger->debug("SKIPPING: No bugzilla id associated with user"); + return; + } + + my $bug_user = $phab_user->bugzilla_user; + + # Pre setup before querying DB + my $old_user = set_phab_user(); + + Bugzilla->switch_to_shadow_db(); + + my $params = { + f3 => 'OP', + j3 => 'OR', + + # User must be either reporter, assignee, qa_contact + # or on the cc list of the bug + f4 => 'cc', + o4 => 'equals', + v4 => $bug_user->login, + + f5 => 'assigned_to', + o5 => 'equals', + v5 => $bug_user->login, + + f6 => 'qa_contact', + o6 => 'equals', + v6 => $bug_user->login, + + f7 => 'reporter', + o7 => 'equals', + v7 => $bug_user->login, + + f9 => 'CP', + + # The bug needs to be private + f10 => 'bug_group', + o10 => 'isnotempty', + + # And the bug must have one or more attachments + # that are connected to revisions + f11 => 'attachments.filename', + o11 => 'regexp', + v11 => '^phabricator-D[[:digit:]]+-url[[.period.]]txt$', + }; + + my $search = Bugzilla::Search->new( fields => [ 'bug_id' ], + params => $params, + order => [ 'bug_id' ] ); + my $data = $search->data; + + # the first value of each row should be the bug id + my @bug_ids = map { shift @$_ } @$data; + + foreach my $bug_id (@bug_ids) { + $self->logger->debug("Processing bug $bug_id"); + + my $bug = Bugzilla::Bug->new({ id => $bug_id, cache => 1 }); + + my @attachments = + grep { is_attachment_phab_revision($_) } @{ $bug->attachments() }; + + foreach my $attachment (@attachments) { + my ($revision_id) = ($attachment->filename =~ PHAB_ATTACHMENT_PATTERN); + $self->logger->debug("Processing revision D$revision_id"); + + my $revision = Bugzilla::Extension::PhabBugz::Revision->new_from_query( + { ids => [ int($revision_id) ] }); + + $revision->add_subscriber($phab_user->phid); + $revision->update(); + + $self->logger->debug("Revision $revision_id updated"); + } + } + + Bugzilla->set_user($old_user); + + $self->logger->info('SUCCESS: User ' . $phab_user->id . ' processed'); +} + +################## +# Helper Methods # +################## + +sub new_stories { + my ( $self, $after ) = @_; my $data = { view => 'text' }; $data->{after} = $after if $after; - my $result = request('feed.query_id', $data); - unless (ref $result->{result}{data} eq 'ARRAY' - && @{ $result->{result}{data} }) + my $result = request( 'feed.query_id', $data ); + unless ( ref $result->{result}{data} eq 'ARRAY' + && @{ $result->{result}{data} } ) { return []; } + # Guarantee that the data is in ascending ID order return [ sort { $a->{id} <=> $b->{id} } @{ $result->{result}{data} } ]; } +sub new_users { + my ( $self, $after ) = @_; + my $data = { + order => [ "id" ], + attachments => { + 'external-accounts' => 1 + } + }; + $data->{before} = $after if $after; + my $result = request( 'user.search', $data ); + unless ( ref $result->{result}{data} eq 'ARRAY' + && @{ $result->{result}{data} } ) + { + return []; + } + + # Guarantee that the data is in ascending ID order + return [ sort { $a->{id} <=> $b->{id} } @{ $result->{result}{data} } ]; +} + +sub get_last_id { + my ( $self, $type ) = @_; + my $type_full = $type . "_last_id"; + my $last_id = Bugzilla->dbh->selectrow_array( " + SELECT value FROM phabbugz WHERE name = ?", undef, $type_full ); + $last_id ||= 0; + $self->logger->debug( "QUERY " . uc($type_full) . ": $last_id" ); + return $last_id; +} + +sub save_last_id { + my ( $self, $last_id, $type ) = @_; + + # Store the largest last key so we can start from there in the next session + my $type_full = $type . "_last_id"; + $self->logger->debug( "UPDATING " . uc($type_full) . ": $last_id" ); + Bugzilla->dbh->do( "REPLACE INTO phabbugz (name, value) VALUES (?, ?)", + undef, $type_full, $last_id ); +} + 1; diff --git a/extensions/PhabBugz/lib/Revision.pm b/extensions/PhabBugz/lib/Revision.pm index 144232ccb..a897acf31 100644 --- a/extensions/PhabBugz/lib/Revision.pm +++ b/extensions/PhabBugz/lib/Revision.pm @@ -9,6 +9,7 @@ package Bugzilla::Extension::PhabBugz::Revision; use 5.10.1; use Moo; +use Scalar::Util qw(blessed); use Types::Standard -all; use Type::Utils; -- cgit v1.2.3-24-g4f1b