Commit c4465178 authored by Andreas Brandl's avatar Andreas Brandl

Merge branch '333506-update-integrations-type_new-trigger' into 'master'

Use dynamic mapping in trigger to sync `integrations.type_new`

See merge request gitlab-org/gitlab!68558
parents 230c1015 21db2a36
# frozen_string_literal: true
class UpdateIntegrationsTriggerTypeNewOnInsert < ActiveRecord::Migration[6.1]
include Gitlab::Database::SchemaHelpers
FUNCTION_NAME = 'integrations_set_type_new'
def up
# Update `type_new` dynamically based on `type`.
#
# The old class names are in the format `AbcService`, and the new ones `Integrations::Abc`.
create_trigger_function(FUNCTION_NAME, replace: true) do
<<~SQL
UPDATE integrations SET type_new = regexp_replace(NEW.type, '\\A(.+)Service\\Z', 'Integrations::\\1')
WHERE integrations.id = NEW.id;
RETURN NULL;
SQL
end
end
def down
# We initially went with this static mapping since we assumed that new integrations could
# just use the correct class name directly in `type`, but this will complicate the data migration
# since we plan to drop `type` at some point and replace it with `type_new`, so we still need
# to keep this column filled for all records.
create_trigger_function(FUNCTION_NAME, replace: true) do
<<~SQL
WITH mapping(old_type, new_type) AS (VALUES
('AsanaService', 'Integrations::Asana'),
('AssemblaService', 'Integrations::Assembla'),
('BambooService', 'Integrations::Bamboo'),
('BugzillaService', 'Integrations::Bugzilla'),
('BuildkiteService', 'Integrations::Buildkite'),
('CampfireService', 'Integrations::Campfire'),
('ConfluenceService', 'Integrations::Confluence'),
('CustomIssueTrackerService', 'Integrations::CustomIssueTracker'),
('DatadogService', 'Integrations::Datadog'),
('DiscordService', 'Integrations::Discord'),
('DroneCiService', 'Integrations::DroneCi'),
('EmailsOnPushService', 'Integrations::EmailsOnPush'),
('EwmService', 'Integrations::Ewm'),
('ExternalWikiService', 'Integrations::ExternalWiki'),
('FlowdockService', 'Integrations::Flowdock'),
('HangoutsChatService', 'Integrations::HangoutsChat'),
('IrkerService', 'Integrations::Irker'),
('JenkinsService', 'Integrations::Jenkins'),
('JiraService', 'Integrations::Jira'),
('MattermostService', 'Integrations::Mattermost'),
('MattermostSlashCommandsService', 'Integrations::MattermostSlashCommands'),
('MicrosoftTeamsService', 'Integrations::MicrosoftTeams'),
('MockCiService', 'Integrations::MockCi'),
('MockMonitoringService', 'Integrations::MockMonitoring'),
('PackagistService', 'Integrations::Packagist'),
('PipelinesEmailService', 'Integrations::PipelinesEmail'),
('PivotaltrackerService', 'Integrations::Pivotaltracker'),
('PrometheusService', 'Integrations::Prometheus'),
('PushoverService', 'Integrations::Pushover'),
('RedmineService', 'Integrations::Redmine'),
('SlackService', 'Integrations::Slack'),
('SlackSlashCommandsService', 'Integrations::SlackSlashCommands'),
('TeamcityService', 'Integrations::Teamcity'),
('UnifyCircuitService', 'Integrations::UnifyCircuit'),
('YoutrackService', 'Integrations::Youtrack'),
('WebexTeamsService', 'Integrations::WebexTeams'),
-- EE-only integrations
('GithubService', 'Integrations::Github'),
('GitlabSlackApplicationService', 'Integrations::GitlabSlackApplication')
)
UPDATE integrations SET type_new = mapping.new_type
FROM mapping
WHERE integrations.id = NEW.id
AND mapping.old_type = NEW.type;
RETURN NULL;
SQL
end
end
end
0d04487e59b783f0aa88ddd4f79716ae570ba87528b15bd07400aa4b1cef92c1
\ No newline at end of file
......@@ -14,53 +14,8 @@ CREATE FUNCTION integrations_set_type_new() RETURNS trigger
LANGUAGE plpgsql
AS $$
BEGIN
WITH mapping(old_type, new_type) AS (VALUES
('AsanaService', 'Integrations::Asana'),
('AssemblaService', 'Integrations::Assembla'),
('BambooService', 'Integrations::Bamboo'),
('BugzillaService', 'Integrations::Bugzilla'),
('BuildkiteService', 'Integrations::Buildkite'),
('CampfireService', 'Integrations::Campfire'),
('ConfluenceService', 'Integrations::Confluence'),
('CustomIssueTrackerService', 'Integrations::CustomIssueTracker'),
('DatadogService', 'Integrations::Datadog'),
('DiscordService', 'Integrations::Discord'),
('DroneCiService', 'Integrations::DroneCi'),
('EmailsOnPushService', 'Integrations::EmailsOnPush'),
('EwmService', 'Integrations::Ewm'),
('ExternalWikiService', 'Integrations::ExternalWiki'),
('FlowdockService', 'Integrations::Flowdock'),
('HangoutsChatService', 'Integrations::HangoutsChat'),
('IrkerService', 'Integrations::Irker'),
('JenkinsService', 'Integrations::Jenkins'),
('JiraService', 'Integrations::Jira'),
('MattermostService', 'Integrations::Mattermost'),
('MattermostSlashCommandsService', 'Integrations::MattermostSlashCommands'),
('MicrosoftTeamsService', 'Integrations::MicrosoftTeams'),
('MockCiService', 'Integrations::MockCi'),
('MockMonitoringService', 'Integrations::MockMonitoring'),
('PackagistService', 'Integrations::Packagist'),
('PipelinesEmailService', 'Integrations::PipelinesEmail'),
('PivotaltrackerService', 'Integrations::Pivotaltracker'),
('PrometheusService', 'Integrations::Prometheus'),
('PushoverService', 'Integrations::Pushover'),
('RedmineService', 'Integrations::Redmine'),
('SlackService', 'Integrations::Slack'),
('SlackSlashCommandsService', 'Integrations::SlackSlashCommands'),
('TeamcityService', 'Integrations::Teamcity'),
('UnifyCircuitService', 'Integrations::UnifyCircuit'),
('YoutrackService', 'Integrations::Youtrack'),
('WebexTeamsService', 'Integrations::WebexTeams'),
-- EE-only integrations
('GithubService', 'Integrations::Github'),
('GitlabSlackApplicationService', 'Integrations::GitlabSlackApplication')
)
UPDATE integrations SET type_new = mapping.new_type
FROM mapping
WHERE integrations.id = NEW.id
AND mapping.old_type = NEW.type;
UPDATE integrations SET type_new = regexp_replace(NEW.type, '\A(.+)Service\Z', 'Integrations::\1')
WHERE integrations.id = NEW.id;
RETURN NULL;
END
# frozen_string_literal: true
require 'spec_helper'
require_migration!
RSpec.describe UpdateIntegrationsTriggerTypeNewOnInsert do
let(:migration) { described_class.new }
let(:integrations) { table(:integrations) }
shared_examples 'transforms known types' do
# This matches Gitlab::Integrations::StiType at the time the original trigger
# was added in db/migrate/20210721135638_add_triggers_to_integrations_type_new.rb
let(:namespaced_integrations) do
%w[
Asana Assembla Bamboo Bugzilla Buildkite Campfire Confluence CustomIssueTracker Datadog
Discord DroneCi EmailsOnPush Ewm ExternalWiki Flowdock HangoutsChat Irker Jenkins Jira Mattermost
MattermostSlashCommands MicrosoftTeams MockCi MockMonitoring Packagist PipelinesEmail Pivotaltracker
Prometheus Pushover Redmine Slack SlackSlashCommands Teamcity UnifyCircuit WebexTeams Youtrack
Github GitlabSlackApplication
]
end
it 'sets `type_new` to the transformed `type` class name' do
namespaced_integrations.each do |type|
integration = integrations.create!(type: "#{type}Service")
expect(integration.reload).to have_attributes(
type: "#{type}Service",
type_new: "Integrations::#{type}"
)
end
end
end
describe '#up' do
before do
migrate!
end
describe 'INSERT trigger with dynamic mapping' do
it_behaves_like 'transforms known types'
it 'transforms unknown types if it ends in "Service"' do
integration = integrations.create!(type: 'AcmeService')
expect(integration.reload).to have_attributes(
type: 'AcmeService',
type_new: 'Integrations::Acme'
)
end
it 'ignores "Service" occurring elsewhere in the type' do
integration = integrations.create!(type: 'ServiceAcmeService')
expect(integration.reload).to have_attributes(
type: 'ServiceAcmeService',
type_new: 'Integrations::ServiceAcme'
)
end
it 'copies unknown types if it does not end with "Service"' do
integration = integrations.create!(type: 'Integrations::Acme')
expect(integration.reload).to have_attributes(
type: 'Integrations::Acme',
type_new: 'Integrations::Acme'
)
end
end
end
describe '#down' do
before do
migration.up
migration.down
end
describe 'INSERT trigger with static mapping' do
it_behaves_like 'transforms known types'
it 'ignores types that are already namespaced' do
integration = integrations.create!(type: 'Integrations::Asana')
expect(integration.reload).to have_attributes(
type: 'Integrations::Asana',
type_new: nil
)
end
it 'ignores types that are unknown' do
integration = integrations.create!(type: 'FooBar')
expect(integration.reload).to have_attributes(
type: 'FooBar',
type_new: nil
)
end
end
end
end
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