From ce080c6dcec309fa3bcfb922c834266166e57af4 Mon Sep 17 00:00:00 2001 From: David Walsh Date: Mon, 31 Jul 2017 16:44:31 -0500 Subject: Bug 1383108 - Sync security groups with Phabricator push connector r=dkl --- extensions/Push/lib/Connector/Phabricator.pm | 126 ++++++++++++++++++++------- 1 file changed, 94 insertions(+), 32 deletions(-) (limited to 'extensions/Push/lib') diff --git a/extensions/Push/lib/Connector/Phabricator.pm b/extensions/Push/lib/Connector/Phabricator.pm index be0ea9b58..092d63dd3 100644 --- a/extensions/Push/lib/Connector/Phabricator.pm +++ b/extensions/Push/lib/Connector/Phabricator.pm @@ -15,18 +15,22 @@ use base 'Bugzilla::Extension::Push::Connector::Base'; use Bugzilla::Bug; use Bugzilla::Constants; -use Bugzilla::Extension::PhabBugz::Util qw(intersect make_revision_public get_revisions_by_ids); +use Bugzilla::Error; +use Bugzilla::Extension::PhabBugz::Util qw(add_comment_to_revision + create_private_revision_policy edit_revision_policy get_bug_role_phids + get_revisions_by_ids intersect make_revision_public make_revision_private); use Bugzilla::Extension::Push::Constants; -use Bugzilla::Extension::Push::Util; +use Bugzilla::Extension::Push::Util qw(is_public); use Bugzilla::User; use List::Util qw(any); -use constant PHAB_CONTENT_TYPE => 'text/x-phabricator-request'; +use constant PHAB_CONTENT_TYPE => 'text/x-phabricator-request'; use constant PHAB_ATTACHMENT_PATTERN => qr/^phabricator-D(\d+)/; sub options { return ( - { name => 'phabricator_url', + { + name => 'phabricator_url', label => 'Phabricator URL', type => 'string', default => '', @@ -40,11 +44,11 @@ sub should_send { return 0 unless Bugzilla->params->{phabricator_enabled}; - return 0 unless $message->routing_key =~ /^(?:attachment|bug)\.modify:.*\bbug_group\b/; + return 0 + unless $message->routing_key =~ + /^(?:attachment|bug)\.modify:.*\bbug_group\b/; - my $data = $message->payload_decoded; - my $bug_data = $self->_get_bug_data($data) || return 0; - my $bug = Bugzilla::Bug->new( { id => $bug_data->{id}, cache => 1 } ); + my $bug = $self->_get_bug_by_data( $message->payload_decoded ) || return 0; return $bug->has_attachment_with_mimetype(PHAB_CONTENT_TYPE); } @@ -55,43 +59,101 @@ sub send { my $logger = Bugzilla->push_ext->logger; my $data = $message->payload_decoded; - my $bug_data = $self->_get_bug_data($data) || return 0; - my $bug = Bugzilla::Bug->new( { id => $bug_data->{id}, cache => 1 } ); + my $bug = $self->_get_bug_by_data($data) || return PUSH_RESULT_OK; + + my $is_public = is_public($bug); + + my $phab_sync_groups = Bugzilla->params->{phabricator_sync_groups}; + ThrowUserError('invalid_phabricator_sync_groups') unless $phab_sync_groups; + + my $sync_group_names = [ split( '[,\s]+', $phab_sync_groups ) ]; + + my $bug_groups = $bug->groups_in; + my $bug_group_names = [ map { $_->name } @$bug_groups ]; + + my @set_groups = intersect( $bug_group_names, $sync_group_names ); + + if ( !$is_public && !@set_groups ) { + my $phab_error_message = + 'Revision is being made private due to unknown Bugzilla groups.'; + + my @revisions = $self->_get_attachment_revisions($bug); + foreach my $revision (@revisions) { + add_comment_to_revision( $revision->{phid}, $phab_error_message ); + make_revision_private( $revision->{phid} ); + } + + my $num_revisions = 0 + @revisions; + my $bmo_error_message = + ( $num_revisions > 1 + ? 'Multiple revisions were' + : 'One revision was' ) + . ' made private due to unknown Bugzilla groups.'; + + my $user = + Bugzilla->set_user( + Bugzilla::User->new( { name => 'conduit@mozilla.bugs' } ) ); + $bug->add_comment( $bmo_error_message, { isprivate => 0 } ); + my $bug_changes = $bug->update(); + $bug->send_changes($bug_changes); - if(!is_public($bug)) { - $logger->info('Bailing on send because the bug is not public'); return PUSH_RESULT_OK; } + my $policy_phid; + my $subscribers; + if ( !$is_public ) { + $policy_phid = create_private_revision_policy( $bug, \@set_groups ); + $subscribers = get_bug_role_phids($bug); + } + + my @revisions = $self->_get_attachment_revisions($bug); + foreach my $revision (@revisions) { + my $revision_phid = $revision->{phid}; + + if ($is_public) { + make_revision_public($revision_phid); + } + else { + edit_revision_policy( $revision_phid, $policy_phid, $subscribers ); + } + } + + return PUSH_RESULT_OK; +} + +sub _get_attachment_revisions() { + my ( $self, $bug ) = @_; + + my @revisions; + my @attachments = grep { - $_->isobsolete == 0 && - $_->contenttype eq PHAB_CONTENT_TYPE && - $_->attacher->login eq 'phab-bot@bmo.tld' + $_->isobsolete == 0 + && $_->contenttype eq PHAB_CONTENT_TYPE + && $_->attacher->login ne 'phab-bot@bmo.tld' } @{ $bug->attachments() }; - if(@attachments){ - my @rev_ids; + if (@attachments) { + my @revision_ids; foreach my $attachment (@attachments) { - my ($rev_id) = ($attachment->filename =~ PHAB_ATTACHMENT_PATTERN); - next if !$rev_id; - push(@rev_ids, int($rev_id)); + my ($revision_id) = + ( $attachment->filename =~ PHAB_ATTACHMENT_PATTERN ); + next if !$revision_id; + push( @revision_ids, int($revision_id) ); } - if(@rev_ids) { - $logger->info('Getting info for revisions: '); - $logger->info(@rev_ids); - - my @rev_details = get_revisions_by_ids(\@rev_ids); - foreach my $rev_detail (@rev_details) { - my $rev_phid = $rev_detail->{phid}; - $logger->info('Making revision $rev_phid public:'); - $logger->info($rev_phid); - make_revision_public($rev_phid); - } + if (@revision_ids) { + @revisions = get_revisions_by_ids( \@revision_ids ); } } - return PUSH_RESULT_OK; + return @revisions; +} + +sub _get_bug_by_data { + my ( $self, $data ) = @_; + my $bug_data = $self->_get_bug_data($data) || return 0; + my $bug = Bugzilla::Bug->new( { id => $bug_data->{id} } ); } sub _get_bug_data { -- cgit v1.2.3-24-g4f1b