From df150bae0a40ed353d5a0cb740d7930a3bdd8bf8 Mon Sep 17 00:00:00 2001
From: Doug Stull <dstull@gitlab.com>
Date: Fri, 9 Feb 2024 21:48:26 +0000
Subject: [PATCH] Re-enqueue backfilling of the default organization owners

- bad sequencing of kicking this off before feature flag
  was fully enabled

Changelog: other
---
 .../backfill_default_organization_owners.yml  |  4 +-
 ...fill_default_organization_owners_again.yml |  9 +++
 ...ue_backfill_default_organization_owners.rb | 19 +-----
 ...ue_backfill_default_organization_owners.rb | 33 ++++++++++
 db/schema_migrations/20240126210641           |  1 +
 .../backfill_default_organization_owners.rb   | 24 +------
 ...kfill_default_organization_owners_again.rb | 36 +++++++++++
 ..._default_organization_owners_again_spec.rb | 64 +++++++++++++++++++
 ...ckfill_default_organization_owners_spec.rb | 49 ++------------
 ...kfill_default_organization_owners_spec.rb} |  2 +-
 10 files changed, 153 insertions(+), 88 deletions(-)
 create mode 100644 db/docs/batched_background_migrations/backfill_default_organization_owners_again.yml
 create mode 100644 db/post_migrate/20240126210641_requeue_backfill_default_organization_owners.rb
 create mode 100644 db/schema_migrations/20240126210641
 create mode 100644 lib/gitlab/background_migration/backfill_default_organization_owners_again.rb
 create mode 100644 spec/lib/gitlab/background_migration/backfill_default_organization_owners_again_spec.rb
 rename spec/migrations/{20240108182342_queue_backfill_default_organization_owners_spec.rb => 20240126210641_requeue_backfill_default_organization_owners_spec.rb} (89%)

diff --git a/db/docs/batched_background_migrations/backfill_default_organization_owners.yml b/db/docs/batched_background_migrations/backfill_default_organization_owners.yml
index ccd7f226a4853..47fa60e6786fd 100644
--- a/db/docs/batched_background_migrations/backfill_default_organization_owners.yml
+++ b/db/docs/batched_background_migrations/backfill_default_organization_owners.yml
@@ -1,9 +1,9 @@
 ---
 migration_job_name: BackfillDefaultOrganizationOwners
-description: Populates organization_users with instance admins to the default organization.
+description: No-op in favor of re-enqueueing with BackfillDefaultOrganizationOwnersAgain
 feature_category: cell
 introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/141297
 milestone: '16.8'
 queued_migration_version: 20240108182342
 finalize_after: '2024-02-15'
-finalized_by: # version of the migration that ensured this bbm
+finalized_by: 20240126210641
diff --git a/db/docs/batched_background_migrations/backfill_default_organization_owners_again.yml b/db/docs/batched_background_migrations/backfill_default_organization_owners_again.yml
new file mode 100644
index 0000000000000..31200571f40f6
--- /dev/null
+++ b/db/docs/batched_background_migrations/backfill_default_organization_owners_again.yml
@@ -0,0 +1,9 @@
+---
+migration_job_name: BackfillDefaultOrganizationOwnersAgain
+description: Populates organization_users with instance admins to the default organization.
+feature_category: cell
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/142979
+milestone: '16.9'
+queued_migration_version: 20240126210641
+finalize_after: '2024-03-15'
+finalized_by: # version of the migration that ensured this bbm
diff --git a/db/post_migrate/20240108182342_queue_backfill_default_organization_owners.rb b/db/post_migrate/20240108182342_queue_backfill_default_organization_owners.rb
index a29fbba5cbcd0..c7956b01a1b95 100644
--- a/db/post_migrate/20240108182342_queue_backfill_default_organization_owners.rb
+++ b/db/post_migrate/20240108182342_queue_backfill_default_organization_owners.rb
@@ -2,28 +2,13 @@
 
 class QueueBackfillDefaultOrganizationOwners < Gitlab::Database::Migration[2.2]
   milestone '16.9'
-
-  MIGRATION = 'BackfillDefaultOrganizationOwners'
-  DELAY_INTERVAL = 2.minutes
-  BATCH_SIZE = 3_000
-  SUB_BATCH_SIZE = 250
-  MAX_BATCH_SIZE = 10_000
-
   restrict_gitlab_migration gitlab_schema: :gitlab_main
 
   def up
-    queue_batched_background_migration(
-      MIGRATION,
-      :users,
-      :id,
-      job_interval: DELAY_INTERVAL,
-      batch_size: BATCH_SIZE,
-      sub_batch_size: SUB_BATCH_SIZE,
-      max_batch_size: MAX_BATCH_SIZE
-    )
+    # no-op
   end
 
   def down
-    delete_batched_background_migration(MIGRATION, :users, :id, [])
+    # no-op
   end
 end
diff --git a/db/post_migrate/20240126210641_requeue_backfill_default_organization_owners.rb b/db/post_migrate/20240126210641_requeue_backfill_default_organization_owners.rb
new file mode 100644
index 0000000000000..a4f8f086e22cf
--- /dev/null
+++ b/db/post_migrate/20240126210641_requeue_backfill_default_organization_owners.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+class RequeueBackfillDefaultOrganizationOwners < Gitlab::Database::Migration[2.2]
+  milestone '16.9'
+
+  OLD_MIGRATION = 'BackfillDefaultOrganizationOwners'
+  MIGRATION = 'BackfillDefaultOrganizationOwnersAgain'
+  DELAY_INTERVAL = 2.minutes
+  BATCH_SIZE = 3_000
+  SUB_BATCH_SIZE = 250
+  MAX_BATCH_SIZE = 10_000
+
+  restrict_gitlab_migration gitlab_schema: :gitlab_main
+
+  def up
+    # remove so we can re-enqueue
+    delete_batched_background_migration(OLD_MIGRATION, :users, :id, [])
+
+    queue_batched_background_migration(
+      MIGRATION,
+      :users,
+      :id,
+      job_interval: DELAY_INTERVAL,
+      batch_size: BATCH_SIZE,
+      sub_batch_size: SUB_BATCH_SIZE,
+      max_batch_size: MAX_BATCH_SIZE
+    )
+  end
+
+  def down
+    delete_batched_background_migration(MIGRATION, :users, :id, [])
+  end
+end
diff --git a/db/schema_migrations/20240126210641 b/db/schema_migrations/20240126210641
new file mode 100644
index 0000000000000..dc03ed7da9a56
--- /dev/null
+++ b/db/schema_migrations/20240126210641
@@ -0,0 +1 @@
+ec234d88c305f23c5d6b9ee9463fc2f17a02b9f5df3d648a9d0abc0a405d442b
\ No newline at end of file
diff --git a/lib/gitlab/background_migration/backfill_default_organization_owners.rb b/lib/gitlab/background_migration/backfill_default_organization_owners.rb
index 123d951a519b0..6022918845801 100644
--- a/lib/gitlab/background_migration/backfill_default_organization_owners.rb
+++ b/lib/gitlab/background_migration/backfill_default_organization_owners.rb
@@ -4,32 +4,10 @@ module Gitlab
   module BackgroundMigration
     class BackfillDefaultOrganizationOwners < BatchedMigrationJob
       operation_name :backfill_default_organization_owners # This is used as the key on collecting metrics
-      scope_to ->(relation) { relation.where(admin: true) }
       feature_category :cell
 
-      module Organizations
-        class OrganizationUser < ApplicationRecord
-          self.table_name = 'organization_users'
-          self.inheritance_column = :_type_disabled
-        end
-      end
-
       def perform
-        each_sub_batch do |sub_batch|
-          organization_users_attributes = sub_batch.map do |user|
-            {
-              user_id: user.id,
-              organization_id: ::Organizations::Organization::DEFAULT_ORGANIZATION_ID,
-              access_level: Gitlab::Access::OWNER
-            }
-          end
-
-          Organizations::OrganizationUser.upsert_all(
-            organization_users_attributes,
-            returning: false,
-            unique_by: [:organization_id, :user_id]
-          )
-        end
+        # no-op, replaced by BackfillDefaultOrganizationOwnersAgain
       end
     end
   end
diff --git a/lib/gitlab/background_migration/backfill_default_organization_owners_again.rb b/lib/gitlab/background_migration/backfill_default_organization_owners_again.rb
new file mode 100644
index 0000000000000..9b4cb57ca6e72
--- /dev/null
+++ b/lib/gitlab/background_migration/backfill_default_organization_owners_again.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module Gitlab
+  module BackgroundMigration
+    class BackfillDefaultOrganizationOwnersAgain < BatchedMigrationJob
+      operation_name :backfill_default_organization_owners_again # This is used as the key on collecting metrics
+      scope_to ->(relation) { relation.where(admin: true) }
+      feature_category :cell
+
+      module Organizations
+        class OrganizationUser < ApplicationRecord
+          self.table_name = 'organization_users'
+          self.inheritance_column = :_type_disabled
+        end
+      end
+
+      def perform
+        each_sub_batch do |sub_batch|
+          organization_users_attributes = sub_batch.map do |user|
+            {
+              user_id: user.id,
+              organization_id: ::Organizations::Organization::DEFAULT_ORGANIZATION_ID,
+              access_level: Gitlab::Access::OWNER
+            }
+          end
+
+          Organizations::OrganizationUser.upsert_all(
+            organization_users_attributes,
+            returning: false,
+            unique_by: [:organization_id, :user_id]
+          )
+        end
+      end
+    end
+  end
+end
diff --git a/spec/lib/gitlab/background_migration/backfill_default_organization_owners_again_spec.rb b/spec/lib/gitlab/background_migration/backfill_default_organization_owners_again_spec.rb
new file mode 100644
index 0000000000000..91fa57e78fe66
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/backfill_default_organization_owners_again_spec.rb
@@ -0,0 +1,64 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::BackfillDefaultOrganizationOwnersAgain, schema: 20240126210641, feature_category: :cell do
+  let(:organization_users) { table(:organization_users) }
+  let(:users) { table(:users) }
+
+  let!(:first_admin) { users.create!(name: 'first', email: 'first_admin@example.com', projects_limit: 1, admin: true) }
+  let!(:last_admin) { users.create!(name: 'last', email: 'last_admin@example.com', projects_limit: 1, admin: true) }
+  let!(:user) { users.create!(name: 'user', email: 'user@example.com', projects_limit: 1) }
+
+  subject(:migration) do
+    described_class.new(
+      start_id: first_admin.id,
+      end_id: user.id,
+      batch_table: :users,
+      batch_column: :id,
+      sub_batch_size: 100,
+      pause_ms: 0,
+      connection: ApplicationRecord.connection
+    )
+  end
+
+  describe '#perform' do
+    context 'with no entries for admin user in organization_users' do
+      it 'adds admins correctly with the default organization to organization_users' do
+        expect(organization_users.count).to eq(0)
+
+        expect { migration.perform }.to change { organization_users.count }.by(2)
+
+        expect(organization_user_as_owner_exists?(first_admin.id)).to be(true)
+        expect(organization_user_as_owner_exists?(last_admin.id)).to be(true)
+      end
+    end
+
+    context 'when admin already exists in organization_users as a default user' do
+      before do
+        organization_users.create!(
+          organization_id: Organizations::Organization::DEFAULT_ORGANIZATION_ID,
+          user_id: first_admin.id,
+          access_level: Gitlab::Access::GUEST
+        )
+      end
+
+      it 'updates the organization_users entry to owner' do
+        expect(organization_users.count).to eq(1)
+
+        expect { migration.perform }.to change { organization_users.count }.by(1)
+
+        expect(organization_user_as_owner_exists?(first_admin.id)).to be(true)
+        expect(organization_user_as_owner_exists?(last_admin.id)).to be(true)
+      end
+    end
+  end
+
+  def organization_user_as_owner_exists?(user_id)
+    organization_users.exists?(
+      organization_id: Organizations::Organization::DEFAULT_ORGANIZATION_ID,
+      user_id: user_id,
+      access_level: Gitlab::Access::OWNER
+    )
+  end
+end
diff --git a/spec/lib/gitlab/background_migration/backfill_default_organization_owners_spec.rb b/spec/lib/gitlab/background_migration/backfill_default_organization_owners_spec.rb
index f0763b9f4f615..c484efca2a67e 100644
--- a/spec/lib/gitlab/background_migration/backfill_default_organization_owners_spec.rb
+++ b/spec/lib/gitlab/background_migration/backfill_default_organization_owners_spec.rb
@@ -3,17 +3,10 @@
 require 'spec_helper'
 
 RSpec.describe Gitlab::BackgroundMigration::BackfillDefaultOrganizationOwners, schema: 20240108182342, feature_category: :cell do
-  let(:organization_users) { table(:organization_users) }
-  let(:users) { table(:users) }
-
-  let!(:first_admin) { users.create!(name: 'first', email: 'first_admin@example.com', projects_limit: 1, admin: true) }
-  let!(:last_admin) { users.create!(name: 'last', email: 'last_admin@example.com', projects_limit: 1, admin: true) }
-  let!(:user) { users.create!(name: 'user', email: 'user@example.com', projects_limit: 1) }
-
   subject(:migration) do
     described_class.new(
-      start_id: first_admin.id,
-      end_id: user.id,
+      start_id: 1,
+      end_id: 2,
       batch_table: :users,
       batch_column: :id,
       sub_batch_size: 100,
@@ -23,42 +16,8 @@
   end
 
   describe '#perform' do
-    context 'with no entries for admin user in organization_users' do
-      it 'adds admins correctly with the default organization to organization_users' do
-        expect(organization_users.count).to eq(0)
-
-        expect { migration.perform }.to change { organization_users.count }.by(2)
-
-        expect(organization_user_as_owner_exists?(first_admin.id)).to be(true)
-        expect(organization_user_as_owner_exists?(last_admin.id)).to be(true)
-      end
-    end
-
-    context 'when admin already exists in organization_users as a default user' do
-      before do
-        organization_users.create!(
-          organization_id: Organizations::Organization::DEFAULT_ORGANIZATION_ID,
-          user_id: first_admin.id,
-          access_level: Gitlab::Access::GUEST
-        )
-      end
-
-      it 'updates the organization_users entry to owner' do
-        expect(organization_users.count).to eq(1)
-
-        expect { migration.perform }.to change { organization_users.count }.by(1)
-
-        expect(organization_user_as_owner_exists?(first_admin.id)).to be(true)
-        expect(organization_user_as_owner_exists?(last_admin.id)).to be(true)
-      end
+    it 'runs without error for no-op' do
+      migration.perform
     end
   end
-
-  def organization_user_as_owner_exists?(user_id)
-    organization_users.exists?(
-      organization_id: Organizations::Organization::DEFAULT_ORGANIZATION_ID,
-      user_id: user_id,
-      access_level: Gitlab::Access::OWNER
-    )
-  end
 end
diff --git a/spec/migrations/20240108182342_queue_backfill_default_organization_owners_spec.rb b/spec/migrations/20240126210641_requeue_backfill_default_organization_owners_spec.rb
similarity index 89%
rename from spec/migrations/20240108182342_queue_backfill_default_organization_owners_spec.rb
rename to spec/migrations/20240126210641_requeue_backfill_default_organization_owners_spec.rb
index aee7183bdb9bd..7d5887b4f14c6 100644
--- a/spec/migrations/20240108182342_queue_backfill_default_organization_owners_spec.rb
+++ b/spec/migrations/20240126210641_requeue_backfill_default_organization_owners_spec.rb
@@ -3,7 +3,7 @@
 require 'spec_helper'
 require_migration!
 
-RSpec.describe QueueBackfillDefaultOrganizationOwners, feature_category: :cell do
+RSpec.describe RequeueBackfillDefaultOrganizationOwners, feature_category: :cell do
   let!(:batched_migration) { described_class::MIGRATION }
 
   it 'schedules a new batched migration' do
-- 
GitLab