From 88a66287a048661f501978f9a0bfefcf1d4ebc5a Mon Sep 17 00:00:00 2001
From: Arturo Herrero <arturo.herrero@gmail.com>
Date: Fri, 9 Apr 2021 14:08:06 +0000
Subject: [PATCH] Remove records without group from webhooks

---
 ...ve-records-without-group-from-webhooks.yml |  5 ++++
 ...cords_without_group_from_webhooks_table.rb | 30 +++++++++++++++++++
 db/schema_migrations/20210330091751           |  1 +
 ..._without_group_from_webhooks_table_spec.rb | 27 +++++++++++++++++
 4 files changed, 63 insertions(+)
 create mode 100644 changelogs/unreleased/202423-remove-records-without-group-from-webhooks.yml
 create mode 100644 db/post_migrate/20210330091751_remove_records_without_group_from_webhooks_table.rb
 create mode 100644 db/schema_migrations/20210330091751
 create mode 100644 spec/migrations/remove_records_without_group_from_webhooks_table_spec.rb

diff --git a/changelogs/unreleased/202423-remove-records-without-group-from-webhooks.yml b/changelogs/unreleased/202423-remove-records-without-group-from-webhooks.yml
new file mode 100644
index 0000000000000..dff08ca6494a7
--- /dev/null
+++ b/changelogs/unreleased/202423-remove-records-without-group-from-webhooks.yml
@@ -0,0 +1,5 @@
+---
+title: Remove records without group from webhooks table
+merge_request: 57863
+author:
+type: other
diff --git a/db/post_migrate/20210330091751_remove_records_without_group_from_webhooks_table.rb b/db/post_migrate/20210330091751_remove_records_without_group_from_webhooks_table.rb
new file mode 100644
index 0000000000000..c384aa25ac425
--- /dev/null
+++ b/db/post_migrate/20210330091751_remove_records_without_group_from_webhooks_table.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+class RemoveRecordsWithoutGroupFromWebhooksTable < ActiveRecord::Migration[6.0]
+  include Gitlab::Database::MigrationHelpers
+
+  DOWNTIME = false
+
+  class WebHook < ActiveRecord::Base
+    include EachBatch
+
+    self.table_name = 'web_hooks'
+  end
+
+  class Group < ActiveRecord::Base
+    self.inheritance_column = :_type_disabled
+    self.table_name = 'namespaces'
+  end
+
+  def up
+    subquery = Group.select(1).where(Group.arel_table[:id].eq(WebHook.arel_table[:group_id]))
+
+    WebHook.each_batch(of: 500, column: :id) do |relation|
+      relation.where(type: 'GroupHook').where.not('EXISTS (?)', subquery).delete_all
+    end
+  end
+
+  def down
+    # no-op
+  end
+end
diff --git a/db/schema_migrations/20210330091751 b/db/schema_migrations/20210330091751
new file mode 100644
index 0000000000000..0536252e98010
--- /dev/null
+++ b/db/schema_migrations/20210330091751
@@ -0,0 +1 @@
+3a195b9671846409cf6665b13caad9713541d9cdd95c9f246c22b7db225ab02c
\ No newline at end of file
diff --git a/spec/migrations/remove_records_without_group_from_webhooks_table_spec.rb b/spec/migrations/remove_records_without_group_from_webhooks_table_spec.rb
new file mode 100644
index 0000000000000..a28ca12a10da3
--- /dev/null
+++ b/spec/migrations/remove_records_without_group_from_webhooks_table_spec.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+require_migration!
+require Rails.root.join('db', 'migrate', '20210325092215_add_not_valid_foreign_key_to_group_hooks.rb')
+
+RSpec.describe RemoveRecordsWithoutGroupFromWebhooksTable, schema: 20210330091751 do
+  let(:web_hooks) { table(:web_hooks) }
+  let(:groups) { table(:namespaces) }
+
+  before do
+    group = groups.create!(name: 'gitlab', path: 'gitlab-org')
+    web_hooks.create!(group_id: group.id, type: 'GroupHook')
+    web_hooks.create!(group_id: nil)
+
+    AddNotValidForeignKeyToGroupHooks.new.down
+    web_hooks.create!(group_id: non_existing_record_id, type: 'GroupHook')
+    AddNotValidForeignKeyToGroupHooks.new.up
+  end
+
+  it 'removes group hooks where the referenced group does not exist', :aggregate_failures do
+    expect { RemoveRecordsWithoutGroupFromWebhooksTable.new.up }.to change { web_hooks.count }.by(-1)
+    expect(web_hooks.where.not(group_id: groups.select(:id)).count).to eq(0)
+    expect(web_hooks.where.not(group_id: nil).count).to eq(1)
+  end
+end
-- 
GitLab