Commit 81bfe344 authored by Etienne Baqué's avatar Etienne Baqué

Merge branch '201855-rename-ee-integrations' into 'master'

Move EE integrations to Integrations namespace [RUN AS-IF-FOSS]

See merge request gitlab-org/gitlab!62676
parents 79f6f2ca 358f455d
......@@ -2357,11 +2357,6 @@ Gitlab/NamespacedClass:
- 'ee/app/models/project_alias.rb'
- 'ee/app/models/project_repository_state.rb'
- 'ee/app/models/project_security_setting.rb'
- 'ee/app/models/project_services/github_service.rb'
- 'ee/app/models/project_services/github_service/remote_project.rb'
- 'ee/app/models/project_services/github_service/status_message.rb'
- 'ee/app/models/project_services/github_service/status_notifier.rb'
- 'ee/app/models/project_services/gitlab_slack_application_service.rb'
- 'ee/app/models/protected_environment.rb'
- 'ee/app/models/push_rule.rb'
- 'ee/app/models/resource_iteration_event.rb'
......
......@@ -23,7 +23,7 @@ alternative authentication methods to your users.
### Remove Service Integration entries from the database
The `GithubService` class is only available in the Enterprise Edition codebase,
The GitHub integration is only available in the Enterprise Edition codebase,
so if you downgrade to the Community Edition, the following error displays:
```plaintext
......@@ -35,8 +35,8 @@ column if you didn't intend it to be used for storing the inheritance class or o
use another column for that information.)
```
All services are created automatically for every project you have, so in order
to avoid getting this error, you need to remove all instances of the
All integrations are created automatically for every project you have, so in order
to avoid getting this error, you need to remove all records with the type set to
`GithubService` from your database:
**Omnibus Installation**
......
......@@ -41,8 +41,8 @@ module EE
has_one :push_rule, ->(project) { project&.feature_available?(:push_rules) ? all : none }, inverse_of: :project
has_one :index_status
has_one :github_service
has_one :gitlab_slack_application_service
has_one :github_service, class_name: 'Integrations::Github'
has_one :gitlab_slack_application_service, class_name: 'Integrations::GitlabSlackApplication'
has_one :status_page_setting, inverse_of: :project, class_name: 'StatusPage::ProjectSetting'
has_one :compliance_framework_setting, class_name: 'ComplianceManagement::ComplianceFramework::ProjectSettings', inverse_of: :project
......@@ -151,7 +151,7 @@ module EE
scope :with_security_reports_stored, -> { where('EXISTS (?)', ::Vulnerabilities::Finding.scoped_project.select(1)) }
scope :with_security_reports, -> { where('EXISTS (?)', ::Ci::JobArtifact.security_reports.scoped_project.select(1)) }
scope :with_github_service_pipeline_events, -> { joins(:github_service).merge(GithubService.pipeline_hooks) }
scope :with_github_service_pipeline_events, -> { joins(:github_service).merge(::Integrations::Github.pipeline_hooks) }
scope :with_active_prometheus_service, -> { joins(:prometheus_service).merge(PrometheusService.active) }
scope :with_enabled_incident_sla, -> { joins(:incident_management_setting).where(project_incident_management_settings: { sla_timer: true }) }
scope :mirrored_with_enabled_pipelines, -> do
......
# frozen_string_literal: true
module Integrations
class Github < Integration
include Gitlab::Routing
include ActionView::Helpers::UrlHelper
prop_accessor :token, :repository_url
boolean_accessor :static_context
delegate :api_url, :owner, :repository_name, to: :remote_project
validates :token, presence: true, if: :activated?
validates :repository_url, public_url: true, allow_blank: true
default_value_for :pipeline_events, true
def initialize_properties
self.properties ||= { static_context: true }
end
def title
'GitHub'
end
def description
s_("GithubIntegration|Obtain statuses for commits and pull requests.")
end
def help
return unless project
docs_link = link_to _('What is repository mirroring?'), help_page_url('user/project/repository/repository_mirroring')
s_("GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}" % { docs_link: docs_link }).html_safe
end
def self.to_param
'github'
end
def fields
learn_more_link_url = help_page_path('user/project/integrations/github', anchor: 'static--dynamic-status-check-name')
learn_more_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: learn_more_link_url }
static_context_field_help = s_('GithubIntegration|Select this if you want GitHub to mark status checks as "Required". %{learn_more_link_start}Learn more%{learn_more_link_end}.').html_safe % { learn_more_link_start: learn_more_link_start, learn_more_link_end: '</a>'.html_safe }
token_url = 'https://github.com/settings/tokens'
token_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: token_url }
token_field_help = s_('GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here.').html_safe % { token_link_start: token_link_start, token_link_end: '</a>'.html_safe, status_html: '<code>repo:status</code>'.html_safe }
[
{ type: 'password',
name: "token",
required: true,
placeholder: "8d3f016698e...",
help: token_field_help },
{ type: 'text',
name: "repository_url",
title: s_('GithubIntegration|Repository URL'),
required: true,
placeholder: 'https://github.com/owner/repository' },
{ type: 'checkbox',
name: "static_context",
title: s_('GithubIntegration|Static status check names (optional)'),
help: static_context_field_help }
]
end
def self.supported_events
%w(pipeline)
end
def can_test?
project&.ci_pipelines&.any?
end
def execute(data)
return if disabled? || invalid? || irrelevant_result?(data)
status_message = StatusMessage.from_pipeline_data(project, self, data)
update_status(status_message)
end
def test(data)
begin
result = execute(data)
context = result[:context]
by_user = result.dig(:creator, :login)
result = "Status for #{context} updated by #{by_user}" if context && by_user
rescue StandardError => error
return { success: false, result: error }
end
{ success: true, result: result }
end
private
def irrelevant_result?(data)
!external_pull_request_pipeline?(data) &&
external_pull_request_pipelines_exist_for_sha?(data)
end
def external_pull_request_pipeline?(data)
id = data.dig(:object_attributes, :id)
external_pull_request_pipelines.id_in(id).exists?
end
def external_pull_request_pipelines_exist_for_sha?(data)
sha = data.dig(:object_attributes, :sha)
return false if sha.nil?
external_pull_request_pipelines.for_sha(sha).exists?
end
def external_pull_request_pipelines
@external_pull_request_pipelines ||= project
.ci_pipelines
.external_pull_request_event
end
def remote_project
RemoteProject.new(repository_url)
end
def disabled?
project.disabled_services.include?(to_param)
end
def update_status(status_message)
notifier.notify(status_message.sha,
status_message.status,
status_message.status_options)
end
def notifier
StatusNotifier.new(token, remote_repo_path, api_endpoint: api_url)
end
def remote_repo_path
"#{owner}/#{repository_name}"
end
end
end
# frozen_string_literal: true
module Integrations
class Github
class RemoteProject
def initialize(url)
@uri = URI.parse(url)
end
def api_url
if host == 'github.com'
'https://api.github.com'
else
"#{protocol}://#{host}/api/v3"
end
end
def owner
uri_path.split('/')[1]
end
def repository_name
uri_path.split('/')[2]
end
private
def host
@uri.host
end
def protocol
@uri.scheme
end
def uri_path
@uri.path.sub('.git', '')
end
end
end
end
# frozen_string_literal: true
module Integrations
class Github
class StatusMessage
include Gitlab::Routing
attr_reader :sha
def initialize(project, service, params)
@project = project
@service = service
@gitlab_status = params[:status]
@detailed_status = params[:detailed_status]
@pipeline_id = params[:id]
@sha = params[:sha]
@ref_name = params[:ref]
end
def context
context_name.truncate(255)
end
def description
"Pipeline #{@detailed_status} on GitLab".truncate(140)
end
def target_url
project_pipeline_url(@project, @pipeline_id)
end
def status
case @gitlab_status.to_s
when 'created',
'pending',
'running',
'manual'
:pending
when 'success',
'skipped'
:success
when 'failed'
:failure
when 'canceled'
:error
end
end
def status_options
{
context: context,
description: description,
target_url: target_url
}
end
def self.from_pipeline_data(project, service, data)
new(project, service, data[:object_attributes])
end
private
def context_name
if @service.static_context?
"ci/gitlab/#{::Gitlab.config.gitlab.host}"
else
"ci/gitlab/#{@ref_name}"
end
end
end
end
end
# frozen_string_literal: true
module Integrations
class Github
class StatusNotifier
def initialize(access_token, repo_path, api_endpoint: nil)
@access_token = access_token
@repo_path = repo_path
@api_endpoint = api_endpoint.presence || ::Octokit::Default.api_endpoint
end
def notify(ref, state, params = {})
client.create_status(@repo_path, ref, state, params)
end
private
def client
@client ||= Octokit::Client.new(access_token: @access_token,
api_endpoint: @api_endpoint)
end
end
end
end
# frozen_string_literal: true
module Integrations
class GitlabSlackApplication < Integration
default_value_for :category, 'chat'
has_one :slack_integration, foreign_key: :service_id
def self.supported_events
%w()
end
def show_active_box?
false
end
def editable?
false
end
def update_active_status
update(active: !!slack_integration)
end
def can_test?
false
end
def title
'Slack application'
end
def description
s_('Integrations|Enable GitLab.com slash commands in a Slack workspace.')
end
def self.to_param
'gitlab_slack_application'
end
def fields
[]
end
def chat_responder
Gitlab::Chat::Responder::Slack
end
end
end
# frozen_string_literal: true
class GithubService < Integration
include Gitlab::Routing
include ActionView::Helpers::UrlHelper
prop_accessor :token, :repository_url
boolean_accessor :static_context
delegate :api_url, :owner, :repository_name, to: :remote_project
validates :token, presence: true, if: :activated?
validates :repository_url, public_url: true, allow_blank: true
default_value_for :pipeline_events, true
def initialize_properties
self.properties ||= { static_context: true }
end
def title
'GitHub'
end
def description
s_("GithubIntegration|Obtain statuses for commits and pull requests.")
end
def help
return unless project
docs_link = link_to _('What is repository mirroring?'), help_page_url('user/project/repository/repository_mirroring')
s_("GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}" % { docs_link: docs_link }).html_safe
end
def self.to_param
'github'
end
def fields
learn_more_link_url = help_page_path('user/project/integrations/github', anchor: 'static--dynamic-status-check-name')
learn_more_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: learn_more_link_url }
static_context_field_help = s_('GithubIntegration|Select this if you want GitHub to mark status checks as "Required". %{learn_more_link_start}Learn more%{learn_more_link_end}.').html_safe % { learn_more_link_start: learn_more_link_start, learn_more_link_end: '</a>'.html_safe }
token_url = 'https://github.com/settings/tokens'
token_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: token_url }
token_field_help = s_('GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here.').html_safe % { token_link_start: token_link_start, token_link_end: '</a>'.html_safe, status_html: '<code>repo:status</code>'.html_safe }
[
{ type: 'password',
name: "token",
required: true,
placeholder: "8d3f016698e...",
help: token_field_help },
{ type: 'text',
name: "repository_url",
title: s_('GithubIntegration|Repository URL'),
required: true,
placeholder: 'https://github.com/owner/repository' },
{ type: 'checkbox',
name: "static_context",
title: s_('GithubIntegration|Static status check names (optional)'),
help: static_context_field_help }
]
end
def self.supported_events
%w(pipeline)
end
def can_test?
project&.ci_pipelines&.any?
end
def execute(data)
return if disabled? || invalid? || irrelevant_result?(data)
status_message = StatusMessage.from_pipeline_data(project, self, data)
update_status(status_message)
end
def test(data)
begin
result = execute(data)
context = result[:context]
by_user = result.dig(:creator, :login)
result = "Status for #{context} updated by #{by_user}" if context && by_user
rescue StandardError => error
return { success: false, result: error }
end
{ success: true, result: result }
end
private
def irrelevant_result?(data)
!external_pull_request_pipeline?(data) &&
external_pull_request_pipelines_exist_for_sha?(data)
end
def external_pull_request_pipeline?(data)
id = data.dig(:object_attributes, :id)
external_pull_request_pipelines.id_in(id).exists?
end
def external_pull_request_pipelines_exist_for_sha?(data)
sha = data.dig(:object_attributes, :sha)
return false if sha.nil?
external_pull_request_pipelines.for_sha(sha).exists?
end
def external_pull_request_pipelines
@external_pull_request_pipelines ||= project
.ci_pipelines
.external_pull_request_event
end
def remote_project
RemoteProject.new(repository_url)
end
def disabled?
project.disabled_services.include?(to_param)
end
def update_status(status_message)
notifier.notify(status_message.sha,
status_message.status,
status_message.status_options)
end
def notifier
StatusNotifier.new(token, remote_repo_path, api_endpoint: api_url)
end
def remote_repo_path
"#{owner}/#{repository_name}"
end
end
# frozen_string_literal: true
class GithubService
class RemoteProject
def initialize(url)
@uri = URI.parse(url)
end
def api_url
if host == 'github.com'
'https://api.github.com'
else
"#{protocol}://#{host}/api/v3"
end
end
def owner
uri_path.split('/')[1]
end
def repository_name
uri_path.split('/')[2]
end
private
def host
@uri.host
end
def protocol
@uri.scheme
end
def uri_path
@uri.path.sub('.git', '')
end
end
end
# frozen_string_literal: true
class GithubService
class StatusMessage
include Gitlab::Routing
attr_reader :sha
def initialize(project, service, params)
@project = project
@service = service
@gitlab_status = params[:status]
@detailed_status = params[:detailed_status]
@pipeline_id = params[:id]
@sha = params[:sha]
@ref_name = params[:ref]
end
def context
context_name.truncate(255)
end
def description
"Pipeline #{@detailed_status} on GitLab".truncate(140)
end
def target_url
project_pipeline_url(@project, @pipeline_id)
end
def status
case @gitlab_status.to_s
when 'created',
'pending',
'running',
'manual'
:pending
when 'success',
'skipped'
:success
when 'failed'
:failure
when 'canceled'
:error
end
end
def status_options
{
context: context,
description: description,
target_url: target_url
}
end
def self.from_pipeline_data(project, service, data)
new(project, service, data[:object_attributes])
end
private
def context_name
if @service.static_context?
"ci/gitlab/#{::Gitlab.config.gitlab.host}"
else
"ci/gitlab/#{@ref_name}"
end
end
end
end
# frozen_string_literal: true
class GithubService
class StatusNotifier
def initialize(access_token, repo_path, api_endpoint: nil)
@access_token = access_token
@repo_path = repo_path
@api_endpoint = api_endpoint.presence || ::Octokit::Default.api_endpoint
end
def notify(ref, state, params = {})
client.create_status(@repo_path, ref, state, params)
end
private
def client
@client ||= Octokit::Client.new(access_token: @access_token,
api_endpoint: @api_endpoint)
end
end
end
# frozen_string_literal: true
class GitlabSlackApplicationService < Integration
default_value_for :category, 'chat'
has_one :slack_integration, foreign_key: :service_id
def self.supported_events
%w()
end
def show_active_box?
false
end
def editable?
false
end
def update_active_status
update(active: !!slack_integration)
end
def can_test?
false
end
def title
'Slack application'
end
def description
s_('Integrations|Enable GitLab.com slash commands in a Slack workspace.')
end
def self.to_param
'gitlab_slack_application'
end
def fields
[]
end
def chat_responder
Gitlab::Chat::Responder::Slack
end
end
......@@ -12,7 +12,7 @@ module EE
override :data
def data
strong_memoize(:data) do
next pipeline_events_data if integration.is_a?(::GithubService)
next pipeline_events_data if integration.is_a?(::Integrations::Github)
super
end
......
......@@ -38,7 +38,7 @@ module EE
override :service_classes
def service_classes
[
::GithubService,
::Integrations::Github,
*super
]
end
......
# frozen_string_literal: true
module EE
module Gitlab
module Integrations
module StiType
extend ActiveSupport::Concern
extend ::Gitlab::Utils::Override
EE_NAMESPACED_INTEGRATIONS = (::Gitlab::Integrations::StiType::NAMESPACED_INTEGRATIONS + %w(
Github GitlabSlackApplication
)).freeze
private
override :namespaced_integrations
def namespaced_integrations
EE_NAMESPACED_INTEGRATIONS
end
end
end
end
end
......@@ -206,7 +206,7 @@ module EE
start: minimum_id(::MergeRequest),
finish: maximum_id(::MergeRequest)),
projects_mirrored_with_pipelines_enabled: count(::Project.mirrored_with_enabled_pipelines),
projects_reporting_ci_cd_back_to_github: count(::GithubService.active),
projects_reporting_ci_cd_back_to_github: count(::Integrations::Github.active),
status_page_projects: count(::StatusPage::ProjectSetting.enabled),
status_page_issues: count(::Issue.on_status_page, start: minimum_id(::Issue), finish: maximum_id(::Issue)),
template_repositories: add(count(::Project.with_repos_templates), count(::Project.with_groups_level_repos_templates))
......
......@@ -28,14 +28,14 @@ RSpec.describe Projects::Settings::IntegrationsController do
end
context 'sets correct services list' do
let(:active_services) { assigns(:integrations).map(&:type) }
let(:disabled_services) { %w[GithubService] }
let(:active_services) { assigns(:integrations).map(&:model_name) }
let(:disabled_services) { %w[Integrations::Github] }
it 'enables SlackSlashCommandsService and disables GitlabSlackApplication' do
get :show, params: { namespace_id: project.namespace, project_id: project }
expect(active_services).to include('SlackSlashCommandsService')
expect(active_services).not_to include('GitlabSlackApplicationService')
expect(active_services).not_to include('Integrations::GitlabSlackApplication')
end
it 'enables GitlabSlackApplication and disables SlackSlashCommandsService' do
......@@ -44,7 +44,7 @@ RSpec.describe Projects::Settings::IntegrationsController do
get :show, params: { namespace_id: project.namespace, project_id: project }
expect(active_services).to include('GitlabSlackApplicationService')
expect(active_services).to include('Integrations::GitlabSlackApplication')
expect(active_services).not_to include('SlackSlashCommandsService')
end
......
# frozen_string_literal: true
FactoryBot.define do
factory :gitlab_slack_application_service do
factory :gitlab_slack_application_service, class: 'Integrations::GitlabSlackApplication' do
project
active { true }
type { 'GitlabSlackApplicationService' }
......@@ -13,7 +13,7 @@ FactoryBot.define do
type { 'SlackSlashCommandsService' }
end
factory :github_service do
factory :github_service, class: 'Integrations::Github' do
project
type { 'GithubService' }
active { true }
......
......@@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe GithubService::RemoteProject do
RSpec.describe Integrations::Github::RemoteProject do
let(:owner) { 'MyUser' }
let(:repository_name) { 'my-project' }
let(:repo_full_path) { "#{owner}/#{repository_name}" }
......
......@@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe GithubService::StatusMessage do
RSpec.describe Integrations::Github::StatusMessage do
include Rails.application.routes.url_helpers
let(:project) { double(:project, namespace: "me", to_s: 'example_project') }
......@@ -101,7 +101,7 @@ RSpec.describe GithubService::StatusMessage do
described_class.from_pipeline_data(project, service, sample_data)
end
it 'builds an instance of GithubService::StatusMessage' do
it 'builds an instance of Integrations::Github::StatusMessage' do
expect(subject).to be_a described_class
end
......
......@@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe GithubService::StatusNotifier do
RSpec.describe Integrations::Github::StatusNotifier do
let(:access_token) { 'aaaaa' }
let(:repo_path) { 'myself/my-project' }
......
......@@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe GithubService do
RSpec.describe Integrations::Github do
let(:project) { create(:project) }
let(:pipeline) { create(:ci_pipeline, project: project) }
let(:pipeline_sample_data) { Gitlab::DataBuilder::Pipeline.build(pipeline) }
......@@ -133,13 +133,13 @@ RSpec.describe GithubService do
let(:sha) { pipeline.sha }
let(:status_options) { { context: 'security', target_url: 'https://localhost.pipeline.example.com', description: "SAST passed" } }
let(:status_message) { double(sha: sha, status: :success, status_options: status_options) }
let(:notifier) { instance_double(GithubService::StatusNotifier) }
let(:notifier) { instance_double(Integrations::Github::StatusNotifier) }
context 'the service is invalid' do
it 'does not notify GitHub of a status change' do
allow(subject).to receive(:invalid?).and_return(true)
expect(GithubService::StatusMessage).not_to receive(:from_pipeline_data)
expect(Integrations::Github::StatusMessage).not_to receive(:from_pipeline_data)
subject.execute(pipeline_sample_data)
end
......@@ -147,7 +147,7 @@ RSpec.describe GithubService do
it 'notifies GitHub of a status change' do
expect(notifier).to receive(:notify)
expect(GithubService::StatusNotifier).to receive(:new).with(token, remote_repo_path, anything)
expect(Integrations::Github::StatusNotifier).to receive(:new).with(token, remote_repo_path, anything)
.and_return(notifier)
subject.execute(pipeline_sample_data)
......@@ -156,7 +156,7 @@ RSpec.describe GithubService do
it 'uses StatusMessage to build message' do
allow(subject).to receive(:update_status)
expect(GithubService::StatusMessage)
expect(Integrations::Github::StatusMessage)
.to receive(:from_pipeline_data)
.with(project, subject, pipeline_sample_data)
.and_return(status_message)
......@@ -166,8 +166,8 @@ RSpec.describe GithubService do
describe 'passes StatusMessage values to StatusNotifier' do
before do
allow(GithubService::StatusNotifier).to receive(:new).and_return(notifier)
allow(GithubService::StatusMessage).to receive(:from_pipeline_data).and_return(status_message)
allow(Integrations::Github::StatusNotifier).to receive(:new).and_return(notifier)
allow(Integrations::Github::StatusMessage).to receive(:from_pipeline_data).and_return(status_message)
end
specify 'sha' do
......@@ -223,7 +223,7 @@ RSpec.describe GithubService do
it 'hands custom api url to StatusNotifier' do
allow(notifier).to receive(:notify)
expect(GithubService::StatusNotifier).to receive(:new).with(anything, anything, api_endpoint: api_url)
expect(Integrations::Github::StatusNotifier).to receive(:new).with(anything, anything, api_endpoint: api_url)
.and_return(notifier)
subject.execute(pipeline_sample_data)
......@@ -242,7 +242,7 @@ RSpec.describe GithubService do
it 'does not send notification' do
expect(subject).not_to receive(:update_status)
expect(GithubService::StatusMessage).not_to receive(:from_pipeline_data)
expect(Integrations::Github::StatusMessage).not_to receive(:from_pipeline_data)
expect(subject.execute(pipeline_sample_data)).to be_nil
end
......@@ -251,7 +251,7 @@ RSpec.describe GithubService do
pipeline_sample_data[:object_attributes].delete(:sha)
expect(subject).to receive(:update_status)
expect(GithubService::StatusMessage).to receive(:from_pipeline_data)
expect(Integrations::Github::StatusMessage).to receive(:from_pipeline_data)
subject.execute(pipeline_sample_data)
end
......@@ -268,7 +268,7 @@ RSpec.describe GithubService do
it 'sends notification' do
expect(subject).to receive(:update_status)
expect(GithubService::StatusMessage).to receive(:from_pipeline_data)
expect(Integrations::Github::StatusMessage).to receive(:from_pipeline_data)
subject.execute(pipeline_sample_data)
end
......
......@@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe GitlabSlackApplicationService do
RSpec.describe Integrations::GitlabSlackApplication do
describe '#chat_responder' do
it 'returns the chat responder to use' do
expect(subject.chat_responder).to eq(Gitlab::Chat::Responder::Slack)
......
......@@ -24,7 +24,7 @@ RSpec.describe CiCd::GithubSetupService do
subject.execute
end
it 'sets up GithubService project integration' do
it 'sets up Github project integration' do
allow(subject).to receive(:create_webhook)
subject.execute
......
......@@ -32,12 +32,16 @@ module Gitlab
private
def namespaced_integrations
NAMESPACED_INTEGRATIONS
end
def new_cast(value)
value = prepare_value(value)
return unless value
stripped_name = value.delete_suffix('Service')
return unless NAMESPACED_INTEGRATIONS.include?(stripped_name)
return unless namespaced_integrations.include?(stripped_name)
"Integrations::#{stripped_name}"
end
......@@ -58,3 +62,5 @@ module Gitlab
end
end
end
Gitlab::Integrations::StiType.prepend_mod
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment