From 59085fe977ebec25b7e7b15cfcbe82f9ed54ba6c Mon Sep 17 00:00:00 2001 From: Patrick Talbert Date: Dec 03 2020 15:32:57 +0000 Subject: ExternalBugs: Add GitLab Type For the ExternalBugs extension define a GitLab Type. Signed-off-by: Patrick Talbert --- diff --git a/extensions/ExternalBugs/lib/Type/GitLab.pm b/extensions/ExternalBugs/lib/Type/GitLab.pm new file mode 100644 index 0000000..fe53ce0 --- /dev/null +++ b/extensions/ExternalBugs/lib/Type/GitLab.pm @@ -0,0 +1,152 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +package Bugzilla::Extension::ExternalBugs::Type::GitLab; + +use strict; +use warnings; +use 5.10.1; + +use base qw(Bugzilla::Extension::ExternalBugs::Type); + +use Bugzilla::Constants; +use Bugzilla::Error; +use Bugzilla::Util qw(correct_urlbase); + +use Data::Dumper; +use JSON; +use URI; +use LWP::UserAgent; +use HTTP::Request; + +use constant TYPE => 'GitLab'; + +my $logger = Bugzilla->logger; + +sub get_data { + my ($self, $ext_bug) = @_; + my $action = ''; + + if ($ext_bug->ext_bz_bug_id =~ '/issues/') { + $action = 'issues'; + } + elsif ($ext_bug->ext_bz_bug_id =~ '/merge_requests/') { + $action = 'merge_requests'; + } + else { + ThrowUserError("ext_bz_cant_sync_id", + {badvalue => $ext_bug->ext_bz_bug_id, et_type => TYPE}); + } + + my ($group, $project, $number) + = ($ext_bug->ext_bz_bug_id =~ m{^(.*)/(.*)/-/(?:issues|merge_requests)/(.*)}); + + ThrowUserError("ext_bz_cant_sync_id", + {badvalue => $ext_bug->ext_bz_bug_id, et_type => TYPE}) + unless ($group && $project && $number); + + # e.g. https://gitlab.com/cki-project/kernel-webhooks/-/merge_requests/82 + my $url = $ext_bug->type->url; + my $last = chop($url); + $url .= $last if ($last ne '/'); + + # GitLab REST URL format: /api/v4/projects///... + # can instead be the $group + $project URL encoded. e.g. cki-project%2Fkernel-webhooks + my $projectid = $group =~ s/\//%2F/g; + $projectid .= "%2F$project" + $url .= "/api/v4/projects/$projectid/$action/$number"; + + # e.g. https://gitlab.com/api/v4/projects/cki-project%2Fkernel-webhooks/merge_requests/82 + + my $data = $self->_do_rest_call($url, 'GET'); + my $bug_data; + + # Get the information we require from the result + if ($data->{state}) { + $bug_data->{status} = $data->{state}; + } + if ($data->{title}) { + $bug_data->{description} = $data->{title}; + } + + return $bug_data; +} + +sub can_sync { + my ($self, $ext_bug) = @_; + return 1; +} + +sub _do_rest_call { + my ($self, $url, $method) = @_; + + # Send the request + my $uri = URI->new($url); + my $ua = LWP::UserAgent->new; + $ua->agent("RedHatBugzilla/" . BUGZILLA_VERSION); # :) + + if ( Bugzilla->params->{external_tracker_proxy} + && Bugzilla->params->{external_tracker_proxy} ne '') + { + $ua->proxy(['http', 'https'], Bugzilla->params->{external_tracker_proxy}); + } + + my $result = undef; + my $content = ''; ##defined $callobj ? encode_json($callobj) : ''; + + eval { + # Create a request + my @headers = ('content-type' => 'application/json;charset=UTF-8'); +## push(@headers, ('authorization' => "Basic $auth")) if ($auth); + + my $req = HTTP::Request->new($method, $uri, \@headers, $content,); + + # Pass request to the user agent and get a response back + my $res = $ua->request($req); + + $logger->debug("REST Calling: " . $uri->as_string); + + unless ($res->is_success) { + die $res->status_line; + } + + # Some calls return no content + $result = $res->content ? decode_json($res->content) : ''; + }; + + if ($@) { + my $err = $@; + ThrowUserError('ext_bz_rest_error', + {errtext => "$err", url => $url, et_type => TYPE}); + } + + if (ref $result and $result->{errors}) { + my $error = Dumper($result->{errors}); + ThrowUserError('ext_bz_rest_error', + {errtext => "$error", url => $url, et_type => TYPE}); + } + + # Log a comment, except if we were trying to log in + $logger->debug("REST Success: $url"); + + return $result; +} + +1; + +__END__ + +=head1 NAME + +Bugzilla::Extension::ExternalBugs::Type::GitLab + +=head1 DESCRIPTION + +Type represents a GitLab review or issue. It is an implementation of +L, and thus provides all methods that +L provides. + +This type can sync data from remote GitLab sites to the local site. + +=cut diff --git a/extensions/ExternalBugs/lib/WebService.pm b/extensions/ExternalBugs/lib/WebService.pm index 7822f55..6573d5c 100644 --- a/extensions/ExternalBugs/lib/WebService.pm +++ b/extensions/ExternalBugs/lib/WebService.pm @@ -1179,6 +1179,7 @@ Supported types: Bugzilla Gerrit GitHub + GitLab JIRA KBase Redmine