summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--changelogs/unreleased/36860-migrate-issues-author.yml5
-rw-r--r--db/migrate/20170825104051_migrate_issues_to_ghost_user.rb36
-rw-r--r--db/migrate/20170901071411_add_foreign_key_to_issue_author.rb14
-rw-r--r--db/schema.rb3
-rw-r--r--spec/migrations/migrate_issues_to_ghost_user_spec.rb51
5 files changed, 108 insertions, 1 deletions
diff --git a/changelogs/unreleased/36860-migrate-issues-author.yml b/changelogs/unreleased/36860-migrate-issues-author.yml
new file mode 100644
index 00000000000..3e9fcc55836
--- /dev/null
+++ b/changelogs/unreleased/36860-migrate-issues-author.yml
@@ -0,0 +1,5 @@
+---
+title: Migrate issues authored by deleted user to the Ghost user
+merge_request:
+author:
+type: fixed
diff --git a/db/migrate/20170825104051_migrate_issues_to_ghost_user.rb b/db/migrate/20170825104051_migrate_issues_to_ghost_user.rb
new file mode 100644
index 00000000000..294141e4fdb
--- /dev/null
+++ b/db/migrate/20170825104051_migrate_issues_to_ghost_user.rb
@@ -0,0 +1,36 @@
+class MigrateIssuesToGhostUser < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ class User < ActiveRecord::Base
+ self.table_name = 'users'
+ end
+
+ class Issue < ActiveRecord::Base
+ self.table_name = 'issues'
+
+ include ::EachBatch
+ end
+
+ def reset_column_in_migration_models
+ ActiveRecord::Base.clear_cache!
+
+ ::User.reset_column_information
+ end
+
+ def up
+ reset_column_in_migration_models
+
+ # we use the model method because rewriting it is too complicated and would require copying multiple methods
+ ghost_id = ::User.ghost.id
+
+ Issue.where('NOT EXISTS (?)', User.unscoped.select(1).where('issues.author_id = users.id')).each_batch do |relation|
+ relation.update_all(author_id: ghost_id)
+ end
+ end
+
+ def down
+ end
+end
diff --git a/db/migrate/20170901071411_add_foreign_key_to_issue_author.rb b/db/migrate/20170901071411_add_foreign_key_to_issue_author.rb
new file mode 100644
index 00000000000..ab6e9fb565a
--- /dev/null
+++ b/db/migrate/20170901071411_add_foreign_key_to_issue_author.rb
@@ -0,0 +1,14 @@
+class AddForeignKeyToIssueAuthor < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_foreign_key(:issues, :users, column: :author_id, on_delete: :nullify)
+ end
+
+ def down
+ remove_foreign_key(:issues, column: :author_id)
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index a5f867df9ae..9b45861cde7 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 20170824162758) do
+ActiveRecord::Schema.define(version: 20170901071411) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -1707,6 +1707,7 @@ ActiveRecord::Schema.define(version: 20170824162758) do
add_foreign_key "issue_assignees", "users", name: "fk_5e0c8d9154", on_delete: :cascade
add_foreign_key "issue_metrics", "issues", on_delete: :cascade
add_foreign_key "issues", "projects", name: "fk_899c8f3231", on_delete: :cascade
+ add_foreign_key "issues", "users", column: "author_id", name: "fk_05f1e72feb", on_delete: :cascade
add_foreign_key "label_priorities", "labels", on_delete: :cascade
add_foreign_key "label_priorities", "projects", on_delete: :cascade
add_foreign_key "labels", "namespaces", column: "group_id", on_delete: :cascade
diff --git a/spec/migrations/migrate_issues_to_ghost_user_spec.rb b/spec/migrations/migrate_issues_to_ghost_user_spec.rb
new file mode 100644
index 00000000000..cfd4021fbac
--- /dev/null
+++ b/spec/migrations/migrate_issues_to_ghost_user_spec.rb
@@ -0,0 +1,51 @@
+require 'spec_helper'
+require Rails.root.join('db', 'migrate', '20170825104051_migrate_issues_to_ghost_user.rb')
+
+describe MigrateIssuesToGhostUser, :migration do
+ describe '#up' do
+ let(:projects) { table(:projects) }
+ let(:issues) { table(:issues) }
+ let(:users) { table(:users) }
+
+ before do
+ projects.create!(name: 'gitlab')
+ user = users.create(email: 'test@example.com')
+ issues.create(title: 'Issue 1', author_id: nil, project_id: 1)
+ issues.create(title: 'Issue 2', author_id: user.id, project_id: 1)
+ end
+
+ context 'when ghost user exists' do
+ let!(:ghost) { users.create(ghost: true, email: 'ghost@example.com') }
+
+ it 'does not create a new user' do
+ expect { schema_migrate_up! }.not_to change { User.count }
+ end
+
+ it 'migrates issues where author = nil to the ghost user' do
+ schema_migrate_up!
+
+ expect(issues.first.reload.author_id).to eq(ghost.id)
+ end
+
+ it 'does not change issues authored by an existing user' do
+ expect { schema_migrate_up! }.not_to change { issues.second.reload.author_id}
+ end
+ end
+
+ context 'when ghost user does not exist' do
+ it 'creates a new user' do
+ expect { schema_migrate_up! }.to change { User.count }.by(1)
+ end
+
+ it 'migrates issues where author = nil to the ghost user' do
+ schema_migrate_up!
+
+ expect(issues.first.reload.author_id).to eq(User.ghost.id)
+ end
+
+ it 'does not change issues authored by an existing user' do
+ expect { schema_migrate_up! }.not_to change { issues.second.reload.author_id}
+ end
+ end
+ end
+end