From 24d019352e82b4f2c29a5d8cf86068e1ffd0dea3 Mon Sep 17 00:00:00 2001 From: Bojan Marjanovic <bmarjanovic@gitlab.com> Date: Thu, 8 Feb 2024 15:03:21 +0000 Subject: [PATCH] Add basic testing functionality for group level Changelog: added EE: true --- .../concerns/integrations/actions.rb | 27 +++++++- app/models/integrations/jira.rb | 4 ++ .../concerns/integrations/group_test_data.rb | 13 ++++ .../integrations/test/group_service.rb | 25 +++++++ ee/app/models/ee/integrations/jira.rb | 9 +-- ee/spec/models/ee/integrations/jira_spec.rb | 6 +- .../integrations/test/group_service_spec.rb | 65 +++++++++++++++++++ .../integrations_actions_shared_examples.rb | 29 +++++++++ 8 files changed, 168 insertions(+), 10 deletions(-) create mode 100644 app/services/concerns/integrations/group_test_data.rb create mode 100644 app/services/integrations/test/group_service.rb create mode 100644 spec/services/integrations/test/group_service_spec.rb diff --git a/app/controllers/concerns/integrations/actions.rb b/app/controllers/concerns/integrations/actions.rb index 10e86bcc98d0c..d936247d8c897 100644 --- a/app/controllers/concerns/integrations/actions.rb +++ b/app/controllers/concerns/integrations/actions.rb @@ -46,7 +46,11 @@ def update end def test - render json: {}, status: :ok + if integration.testable? + render json: integration_test_response, status: :ok + else + render json: {}, status: :not_found + end end def reset @@ -80,4 +84,25 @@ def serialize_as_json .as_json(only: integration.json_fields) .merge(errors: integration.errors.as_json) end + + def integration_test_response + result = if integration.project_level? + ::Integrations::Test::ProjectService.new(integration, current_user, params[:event]).execute + elsif integration.group_level? + ::Integrations::Test::GroupService.new(integration, current_user, params[:event]).execute + else + {} + end + + unless result[:success] + return { + error: true, + message: s_('Integrations|Connection failed. Check your integration settings.'), + service_response: result[:result].to_s, + test_failed: true + } + end + + result[:data].presence || {} + end end diff --git a/app/models/integrations/jira.rb b/app/models/integrations/jira.rb index 268c36b351777..a30e3d868da72 100644 --- a/app/models/integrations/jira.rb +++ b/app/models/integrations/jira.rb @@ -408,6 +408,10 @@ def avatar_url ActionController::Base.helpers.image_path('illustrations/third-party-logos/integrations-logos/jira.svg') end + def testable? + group_level? || project_level? + end + private def jira_issue_match_regex diff --git a/app/services/concerns/integrations/group_test_data.rb b/app/services/concerns/integrations/group_test_data.rb new file mode 100644 index 0000000000000..716580e07b566 --- /dev/null +++ b/app/services/concerns/integrations/group_test_data.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +module Integrations + module GroupTestData + NoDataError = Class.new(ArgumentError) + + private + + def push_events_data + Gitlab::DataBuilder::Push.sample_data + end + end +end diff --git a/app/services/integrations/test/group_service.rb b/app/services/integrations/test/group_service.rb new file mode 100644 index 0000000000000..d10b460919958 --- /dev/null +++ b/app/services/integrations/test/group_service.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +module Integrations + module Test + class GroupService < Integrations::Test::BaseService + include Integrations::GroupTestData + include Gitlab::Utils::StrongMemoize + + def group + integration.group + end + strong_memoize_attr :group + + private + + def data + case event || integration.default_test_event + when 'push', 'tag_push' + push_events_data + end + end + strong_memoize_attr :data + end + end +end diff --git a/ee/app/models/ee/integrations/jira.rb b/ee/app/models/ee/integrations/jira.rb index db37579e1697e..e5211b28548e3 100644 --- a/ee/app/models/ee/integrations/jira.rb +++ b/ee/app/models/ee/integrations/jira.rb @@ -39,7 +39,7 @@ def configured_to_create_issues_from_vulnerabilities? def test(_) super.then do |result| next result unless result[:success] - next result unless project.jira_vulnerabilities_integration_enabled? + next result unless jira_vulnerabilities_integration_enabled? result.merge(data: { issuetypes: issue_types }) end @@ -103,12 +103,9 @@ def jira_project # # @return [Array] the array of objects with JIRA Issuetype ID, Name and Description def issue_types - return [] if jira_project.blank? + issuetypes = jira_project.blank? ? client.Issuetype.all : jira_project.issuetypes - jira_project - .issuetypes - .reject(&:subtask) - .map do |issue_type| + issuetypes.reject(&:subtask).map do |issue_type| { id: issue_type.id, name: issue_type.name, diff --git a/ee/spec/models/ee/integrations/jira_spec.rb b/ee/spec/models/ee/integrations/jira_spec.rb index e1d908e476a7c..ce35199222306 100644 --- a/ee/spec/models/ee/integrations/jira_spec.rb +++ b/ee/spec/models/ee/integrations/jira_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Integrations::Jira do +RSpec.describe Integrations::Jira, feature_category: :integrations do let(:jira_integration) { build(:jira_integration, **options) } let(:headers) { { 'Content-Type' => 'application/json' } } @@ -105,7 +105,7 @@ context 'when vulnerabilities integration is not enabled' do before do - allow(jira_integration.project).to receive(:jira_vulnerabilities_integration_enabled?).and_return(false) + allow(jira_integration).to receive(:jira_vulnerabilities_integration_enabled?).and_return(false) end it { is_expected.to eq(success: true, result: { jira: true }) } @@ -113,7 +113,7 @@ context 'when vulnerabilities integration is enabled' do before do - allow(jira_integration.project).to receive(:jira_vulnerabilities_integration_enabled?).and_return(true) + allow(jira_integration).to receive(:jira_vulnerabilities_integration_enabled?).and_return(true) end context 'when deployment type is cloud' do diff --git a/spec/services/integrations/test/group_service_spec.rb b/spec/services/integrations/test/group_service_spec.rb new file mode 100644 index 0000000000000..abfdf96987d8d --- /dev/null +++ b/spec/services/integrations/test/group_service_spec.rb @@ -0,0 +1,65 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Integrations::Test::GroupService, feature_category: :integrations do + include AfterNextHelpers + + describe '#execute' do + let_it_be(:group) { create(:group) } + let_it_be(:integration) { create(:integrations_slack, :group, group: group) } + let_it_be(:user) { create(:user) } + + let(:event) { nil } + let(:sample_data) { { data: 'sample' } } + let(:success_result) { { success: true, result: {} } } + + subject(:test_service) { described_class.new(integration, user, event).execute } + + before_all do + group.add_owner(user) + end + + context 'without event specified' do + it 'tests the integration with default data' do + allow(Gitlab::DataBuilder::Push).to receive(:sample_data).and_return(sample_data) + + expect(integration).to receive(:test).with(sample_data).and_return(success_result) + expect(test_service).to eq(success_result) + end + end + + context 'with event specified' do + context 'if event is not supported by integration' do + let_it_be(:integration) { create(:jira_integration, :group, group: group) } + let(:event) { 'push' } + + it 'returns error message' do + expect(test_service).to include({ status: :error, message: 'Testing not available for this event' }) + end + end + + context 'for `push` event' do + let(:event) { 'push' } + + it 'executes integration' do + allow(Gitlab::DataBuilder::Push).to receive(:sample_data).and_return(sample_data) + + expect(integration).to receive(:test).with(sample_data).and_return(success_result) + expect(test_service).to eq(success_result) + end + end + + context 'for `tag_push` event' do + let(:event) { 'tag_push' } + + it 'executes integration' do + allow(Gitlab::DataBuilder::Push).to receive(:sample_data).and_return(sample_data) + + expect(integration).to receive(:test).with(sample_data).and_return(success_result) + expect(test_service).to eq(success_result) + end + end + end + end +end diff --git a/spec/support/shared_examples/controllers/concerns/integrations/integrations_actions_shared_examples.rb b/spec/support/shared_examples/controllers/concerns/integrations/integrations_actions_shared_examples.rb index 106260e644fc9..fb8eb34651b7f 100644 --- a/spec/support/shared_examples/controllers/concerns/integrations/integrations_actions_shared_examples.rb +++ b/spec/support/shared_examples/controllers/concerns/integrations/integrations_actions_shared_examples.rb @@ -77,5 +77,34 @@ end it_behaves_like 'unknown integration' + + context 'with untestable integration' do + before do + allow_next_found_instance_of(integration.class) do |integration| + allow(integration).to receive(:testable?).and_return(false) + end + + put :test, params: routing_params + end + + it 'returns 404 Not Found' do + expect(response).to have_gitlab_http_status(:not_found) + end + end + + context 'with testable integration' do + before do + allow_next_found_instance_of(integration.class) do |integration| + allow(integration).to receive(:testable?).and_return(true) + allow(integration).to receive(:test).and_return({ success: true, data: [] }) + end + + put :test, params: routing_params + end + + it 'returns 200' do + expect(response).to have_gitlab_http_status(:ok) + end + end end end -- GitLab