diff options
-rw-r--r-- | extensions/PhabBugz/lib/Feed.pm | 51 | ||||
-rw-r--r-- | extensions/PhabBugz/lib/WebService.pm | 59 | ||||
-rw-r--r-- | extensions/PhabBugz/template/en/default/hook/global/user-error-errors.html.tmpl | 4 |
3 files changed, 112 insertions, 2 deletions
diff --git a/extensions/PhabBugz/lib/Feed.pm b/extensions/PhabBugz/lib/Feed.pm index 96c0830a2..5d9d894f1 100644 --- a/extensions/PhabBugz/lib/Feed.pm +++ b/extensions/PhabBugz/lib/Feed.pm @@ -14,6 +14,7 @@ use IO::Async::Loop; use List::Util qw(first); use List::MoreUtils qw(any); use Moo; +use Scalar::Util qw(blessed); use Try::Tiny; use Bugzilla::Constants; @@ -165,6 +166,51 @@ sub feed_query { }; $self->save_last_id($story_id, 'feed'); } + + # Process any build targets as well. + my $dbh = Bugzilla->dbh; + + INFO("Checking for revisions in draft mode"); + my $build_targets = $dbh->selectall_arrayref( + "SELECT name, value FROM phabbugz WHERE name LIKE 'build_target_%'", + { Slice => {} } + ); + + my $delete_build_target = $dbh->prepare( + "DELETE FROM phabbugz WHERE name = ? AND VALUE = ?" + ); + + foreach my $target (@$build_targets) { + my ($revision_id) = ($target->{name} =~ /^build_target_(\d+)$/); + my $build_target = $target->{value}; + + # FIXME: Remove debugging + use Data::Dumper; print STDERR Dumper $target; + + next unless $revision_id && $build_target; + + INFO("Processing revision $revision_id with build target $build_target"); + + my $revision = + Bugzilla::Extension::PhabBugz::Revision->new_from_query( + { + ids => [ int($revision_id) ] + } + ); + + with_writable_database { + $self->process_revision_change($revision); + }; + + # Set the build target to a passing status to + # allow the revision to exit draft state + request( 'harbormaster.sendmessage', { + buildTargetPHID => $build_target, + type => 'pass' + } ); + + $delete_build_target->execute($target->{name}, $target->{value}); + } } sub user_query { @@ -297,7 +343,10 @@ sub process_revision_change { my ($self, $revision_phid, $story_text) = @_; # Load the revision from Phabricator - my $revision = Bugzilla::Extension::PhabBugz::Revision->new_from_query({ phids => [ $revision_phid ] }); + my $revision = + blessed $revision_phid + ? $revision_phid + : Bugzilla::Extension::PhabBugz::Revision->new_from_query({ phids => [ $revision_phid ] }); my $secure_revision = Bugzilla::Extension::PhabBugz::Project->new_from_query( diff --git a/extensions/PhabBugz/lib/WebService.pm b/extensions/PhabBugz/lib/WebService.pm index f018ba702..56afc93fe 100644 --- a/extensions/PhabBugz/lib/WebService.pm +++ b/extensions/PhabBugz/lib/WebService.pm @@ -20,7 +20,7 @@ use Bugzilla::Constants; use Bugzilla::Error; use Bugzilla::Extension::Push::Util qw(is_public); use Bugzilla::User; -use Bugzilla::Util qw(detaint_natural datetime_from time_ago); +use Bugzilla::Util qw(detaint_natural datetime_from time_ago trick_taint); use Bugzilla::WebService::Constants; use Bugzilla::Extension::PhabBugz::Constants; @@ -54,6 +54,7 @@ use constant PUBLIC_METHODS => qw( revision update_reviewer_statuses needs_review + set_build_target ); sub revision { @@ -398,8 +399,64 @@ sub _phabricator_precheck { unless $user->login eq PHAB_AUTOMATION_USER; } +sub set_build_target { + my ( $self, $params ) = @_; + + # Phabricator only supports sending credentials via HTTP Basic Auth + # so we exploit that function to pass in an API key as the password + # of basic auth. BMO does not support basic auth but does support + # use of API keys. + my $http_auth = Bugzilla->cgi->http('Authorization'); + $http_auth =~ s/^Basic\s+//; + $http_auth = decode_base64($http_auth); + my ($login, $api_key) = split(':', $http_auth); + $params->{'Bugzilla_login'} = $login; + $params->{'Bugzilla_api_key'} = $api_key; + + my $user = Bugzilla->login(LOGIN_REQUIRED); + + # Ensure PhabBugz is on + ThrowUserError('phabricator_not_enabled') + unless Bugzilla->params->{phabricator_enabled}; + + # Validate that the requesting user's email matches phab-bot + ThrowUserError('phabricator_unauthorized_user') + unless $user->login eq PHAB_AUTOMATION_USER; + + my $revision_id = $params->{revision_id}; + my $build_target = $params->{build_target}; + + ThrowUserError('invalid_phabricator_revision_id') + unless detaint_natural($revision_id); + + ThrowUserError('invalid_phabricator_build_target') + unless $build_target =~ /^PHID-HMBT-[a-zA-Z0-9]+$/; + trick_taint($build_target); + + Bugzilla->dbh->do( + "INSERT INTO phabbugz (name, value) VALUES (?, ?)", + undef, + 'build_target_' . $revision_id, + $build_target + ); + + return { result => 1 }; +} + sub rest_resources { return [ + # Set build target in Phabricator + qr{^/phabbugz/build_target/(\d+)/(PHID-HMBT-.*)$}, { + POST => { + method => 'set_build_target', + params => sub { + return { + revision_id => $_[0], + build_target => $_[1] + }; + } + } + }, # Revision creation qr{^/phabbugz/revision/([^/]+)$}, { POST => { diff --git a/extensions/PhabBugz/template/en/default/hook/global/user-error-errors.html.tmpl b/extensions/PhabBugz/template/en/default/hook/global/user-error-errors.html.tmpl index f1366e7b6..0274f72ce 100644 --- a/extensions/PhabBugz/template/en/default/hook/global/user-error-errors.html.tmpl +++ b/extensions/PhabBugz/template/en/default/hook/global/user-error-errors.html.tmpl @@ -22,6 +22,10 @@ [% title = "Invalid Phabricator Revision ID" %] You must provide a valid Phabricator revision ID. +[% ELSIF error == "invalid_phabricator_build_target" %] + [% title = "Invalid Phabricator Build Target" %] + You must provide a valid Phabricator Build Target PHID. + [% ELSIF error == "phabricator_not_enabled" %] [% title = "Phabricator Support Not Enabled" %] The Phabricator to Bugzilla library, PhabBugz, |