diff --git a/db/post_migrate/20240325131114_move_self_managed_cr_to_instance.rb b/db/post_migrate/20240325131114_move_self_managed_cr_to_instance.rb new file mode 100644 index 0000000000000000000000000000000000000000..d41d6af4f7d3352b057bf750fb6bd6e81d23b9eb --- /dev/null +++ b/db/post_migrate/20240325131114_move_self_managed_cr_to_instance.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +class MoveSelfManagedCrToInstance < Gitlab::Database::Migration[2.2] + milestone '17.0' + + disable_ddl_transaction! + + restrict_gitlab_migration gitlab_schema: :gitlab_main + + def up + # the migration needs to run only on self-managed + return if Gitlab.com? + + sql = <<~SQL + UPDATE member_roles mr SET name = CONCAT(mr.name, ' (', g.name, ' - ', g.id, ')'), namespace_id = NULL + FROM namespaces g WHERE mr.namespace_id IS NOT NULL AND + g.id = mr.namespace_id + SQL + + execute(sql) + end + + def down; end +end diff --git a/db/schema_migrations/20240325131114 b/db/schema_migrations/20240325131114 new file mode 100644 index 0000000000000000000000000000000000000000..f241e126ea71fc491508b349293a509db6e50da0 --- /dev/null +++ b/db/schema_migrations/20240325131114 @@ -0,0 +1 @@ +1a934bf4e7dbc8355b0c38a4e6231b2021115c19b3e078f07de56ada378604e1 \ No newline at end of file diff --git a/spec/migrations/20240325131114_move_self_managed_cr_to_instance_spec.rb b/spec/migrations/20240325131114_move_self_managed_cr_to_instance_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..1a6e9c7bddc69702836dc125a881344a2cbe6245 --- /dev/null +++ b/spec/migrations/20240325131114_move_self_managed_cr_to_instance_spec.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: true + +require 'spec_helper' + +require_migration! + +RSpec.describe MoveSelfManagedCrToInstance, feature_category: :permissions do + let(:migration) { described_class.new } + + let(:namespaces) { table(:namespaces) } + let(:member_roles) { table(:member_roles) } + + let(:group_1) { namespaces.create!(name: 'Group 1', path: 'group1') } + let(:group_dupl) { namespaces.create!(name: 'Group 1', path: 'group_duplicated') } + let(:group_2) { namespaces.create!(name: 'Other group', path: 'other_group') } + + let!(:group_1_role_1) { member_roles.create!(name: 'foo', namespace_id: group_1.id, base_access_level: 10) } + let!(:group_1_role_2) { member_roles.create!(name: 'other role', namespace_id: group_1.id, base_access_level: 10) } + let!(:group_dupl_role_1) { member_roles.create!(name: 'foo', namespace_id: group_dupl.id, base_access_level: 10) } + let!(:group_2_role) { member_roles.create!(name: 'foo', namespace_id: group_2.id, base_access_level: 10) } + let!(:instance_role) { member_roles.create!(name: 'foo', namespace_id: nil, base_access_level: 10) } + + describe '#up' do + context 'when on self managed' do + it 'sets namespace_id to nil and updates name', :aggregate_failures do + migration.up + + expect(group_1_role_1.reload.name).to eq("foo (Group 1 - #{group_1.id})") + expect(group_1_role_1.namespace_id).to be_nil + expect(group_1_role_2.reload.name).to eq("other role (Group 1 - #{group_1.id})") + expect(group_1_role_2.namespace_id).to be_nil + expect(group_dupl_role_1.reload.name).to eq("foo (Group 1 - #{group_dupl.id})") + expect(group_dupl_role_1.namespace_id).to be_nil + expect(group_2_role.reload.name).to eq("foo (Other group - #{group_2.id})") + expect(group_2_role.namespace_id).to be_nil + expect(instance_role.reload.name).to eq('foo') # no update for instance-level role + expect(instance_role.namespace_id).to be_nil + end + end + + context 'when on SaaS', :saas do + it 'does not update the custom roles', :aggregate_failures do + migration.up + + expect(group_1_role_1.reload.name).to eq('foo') + expect(group_1_role_1.namespace_id).to eq(group_1.id) + expect(group_1_role_2.reload.name).to eq('other role') + expect(group_1_role_2.namespace_id).to eq(group_1.id) + expect(group_2_role.reload.name).to eq('foo') + expect(group_2_role.namespace_id).to eq(group_2.id) + expect(instance_role.reload.name).to eq('foo') + expect(instance_role.namespace_id).to be_nil + end + end + end +end