1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
# frozen_string_literal: true
class RemoveIntegrationsType < Gitlab::Database::Migration[1.0]
disable_ddl_transaction!
MIGRATION = 'BackfillIntegrationsTypeNew'
BATCH_SIZE = 50
TABLE_NAME = :integrations
COLUMN = :type
# see db/post_migrate/20220213104531_create_indexes_on_integration_type_new.rb
def indices
[
{
name: "index_integrations_on_project_and_#{COLUMN}_where_inherit_null",
columns: [:project_id, COLUMN],
where: 'inherit_from_id IS NULL'
},
{
name: "index_integrations_on_project_id_and_#{COLUMN}_unique",
columns: [:project_id, COLUMN],
unique: true
},
{
name: "index_integrations_on_#{COLUMN}",
columns: [COLUMN]
},
{
name: "index_integrations_on_#{COLUMN}_and_instance_partial",
columns: [COLUMN, :instance],
where: 'instance = true',
unique: true
},
{
name: 'index_integrations_on_type_id_when_active_and_project_id_not_nu',
columns: [COLUMN, :id],
where: '((active = true) AND (project_id IS NOT NULL))'
},
{
name: "index_integrations_on_unique_group_id_and_#{COLUMN}",
columns: [:group_id, COLUMN],
unique: true
}
]
end
def up
ensure_batched_background_migration_is_finished(
job_class_name: MIGRATION,
table_name: TABLE_NAME,
column_name: :id,
job_arguments: [])
cleanup_unmigrated_rows!
remove_column :integrations, :type, :text
end
# WARNING: this migration is not really safe to be reverted, since doing so
# will leave the type column empty. If this migration is reverted, we will
# need to backfill it from type_new
def down
add_column :integrations, :type, 'character varying'
indices.each do |index|
add_concurrent_index TABLE_NAME, index[:columns], index.except(:columns)
end
end
# Convert any remaining unmigrated rows
def cleanup_unmigrated_rows!
tmp_index_name = 'tmp_idx_integrations_unmigrated_type_new'
add_concurrent_index :integrations, :id, where: 'type_new is null', name: tmp_index_name
define_batchable_model(:integrations).where(type_new: nil).each_batch do |batch|
min_id, max_id = batch.pick(Arel.sql('MIN(id), MAX(id)'))
connection.execute(<<~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'),
('WebexTeamsService', 'Integrations::WebexTeams'),
('YoutrackService', 'Integrations::Youtrack'),
-- EE-only integrations
('GithubService', 'Integrations::Github'),
('GitlabSlackApplicationService', 'Integrations::GitlabSlackApplication')
)
UPDATE integrations SET type_new = mapping.new_type
FROM mapping
WHERE integrations.type_new IS NULL
AND integrations.id BETWEEN #{min_id} AND #{max_id}
AND integrations.type = mapping.old_type
SQL
end
ensure
remove_concurrent_index_by_name(:integrations, tmp_index_name)
end
end
|