BigW Consortium Gitlab

Commit 818eab80 by Douwe Maan Committed by Luke Bennett

Merge branch 'remove-soft-removals' into 'master'

Remove soft removals related code Closes #37447 See merge request gitlab-org/gitlab-ce!15789 (cherry picked from commit 7acabf7c) d0b8f536 Remove soft removals related code e5c49b57 Added tests for removing soft removed objects
parent 797ffb4a
......@@ -385,9 +385,6 @@ gem 'ruby-prof', '~> 0.16.2'
# OAuth
gem 'oauth2', '~> 1.4'
# Soft deletion
gem 'paranoia', '~> 2.3.1'
# Health check
gem 'health_check', '~> 2.6.0'
......
......@@ -580,8 +580,6 @@ GEM
orm_adapter (0.5.0)
os (0.9.6)
parallel (1.12.0)
paranoia (2.3.1)
activerecord (>= 4.0, < 5.2)
parser (2.4.0.2)
ast (~> 2.3)
parslet (1.5.0)
......@@ -1117,7 +1115,6 @@ DEPENDENCIES
omniauth-twitter (~> 1.2.0)
omniauth_crowd (~> 2.2.0)
org-ruby (~> 0.9.12)
paranoia (~> 2.3.1)
peek (~> 1.0.1)
peek-gc (~> 0.0.2)
peek-host (~> 1.0.0)
......
......@@ -2,8 +2,9 @@ module Ci
class PipelineSchedule < ActiveRecord::Base
extend Gitlab::Ci::Model
include Importable
include IgnorableColumn
acts_as_paranoid
ignore_column :deleted_at
belongs_to :project
belongs_to :owner, class_name: 'User'
......
module Ci
class Trigger < ActiveRecord::Base
extend Gitlab::Ci::Model
include IgnorableColumn
acts_as_paranoid
ignore_column :deleted_at
belongs_to :project
belongs_to :owner, class_name: "User"
......
......@@ -10,7 +10,6 @@ module InternalId
if iid.blank?
parent = project || group
records = parent.public_send(self.class.name.tableize) # rubocop:disable GitlabSecurity/PublicSend
records = records.with_deleted if self.paranoid?
max_iid = records.maximum(:iid)
self.iid = max_iid.to_i + 1
......
......@@ -12,7 +12,7 @@ class Issue < ActiveRecord::Base
include ThrottledTouch
include IgnorableColumn
ignore_column :assignee_id, :branch_name
ignore_column :assignee_id, :branch_name, :deleted_at
DueDateStruct = Struct.new(:title, :name).freeze
NoDueDate = DueDateStruct.new('No Due Date', '0').freeze
......@@ -78,8 +78,6 @@ class Issue < ActiveRecord::Base
end
end
acts_as_paranoid
class << self
alias_method :in_parents, :in_projects
end
......
......@@ -11,7 +11,8 @@ class MergeRequest < ActiveRecord::Base
include Gitlab::Utils::StrongMemoize
ignore_column :locked_at,
:ref_fetched
:ref_fetched,
:deleted_at
belongs_to :target_project, class_name: "Project"
belongs_to :source_project, class_name: "Project"
......@@ -150,8 +151,6 @@ class MergeRequest < ActiveRecord::Base
after_save :keep_around_commit
acts_as_paranoid
def self.reference_prefix
'!'
end
......
class Namespace < ActiveRecord::Base
acts_as_paranoid without_default_scope: true
include CacheMarkdownField
include Sortable
include Gitlab::ShellAdapter
......@@ -10,6 +8,9 @@ class Namespace < ActiveRecord::Base
include AfterCommitQueue
include Storage::LegacyNamespace
include Gitlab::SQL::Pattern
include IgnorableColumn
ignore_column :deleted_at
# Prevent users from creating unreasonably deep level of nesting.
# The number 20 was taken based on maximum nesting level of
......@@ -221,12 +222,6 @@ class Namespace < ActiveRecord::Base
has_parent?
end
def soft_delete_without_removing_associations
# We can't use paranoia's `#destroy` since this will hard-delete projects.
# Project uses `pending_delete` instead of the acts_as_paranoia gem.
self.deleted_at = Time.now
end
private
def refresh_access_of_projects_invited_groups
......
......@@ -6,7 +6,6 @@ class IssueEntity < IssuableEntity
expose :updated_by_id
expose :created_at
expose :updated_at
expose :deleted_at
expose :milestone, using: API::Entities::Milestone
expose :labels, using: LabelEntity
expose :lock_version
......
module Groups
class DestroyService < Groups::BaseService
def async_execute
group.soft_delete_without_removing_associations
job_id = GroupDestroyWorker.perform_async(group.id, current_user.id)
Rails.logger.info("User #{current_user.id} scheduled a deletion of group ID #{group.id} with job ID #{job_id}")
end
......@@ -23,7 +22,7 @@ module Groups
group.chat_team&.remove_mattermost_team(current_user)
group.really_destroy!
group.destroy
end
end
end
......@@ -53,7 +53,7 @@ module Users
# Destroy the namespace after destroying the user since certain methods may depend on the namespace existing
user_data = user.destroy
namespace.really_destroy!
namespace.destroy
user_data
end
......
......@@ -4,7 +4,7 @@ class GroupDestroyWorker
def perform(group_id, user_id)
begin
group = Group.with_deleted.find(group_id)
group = Group.find(group_id)
rescue ActiveRecord::RecordNotFound
return
end
......
---
title: Remove soft removals related code
merge_request: 15789
author:
type: changed
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class RemoveSoftRemovedObjects < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
DOWNTIME = false
disable_ddl_transaction!
module SoftRemoved
extend ActiveSupport::Concern
included do
scope :soft_removed, -> { where('deleted_at IS NOT NULL') }
end
end
class User < ActiveRecord::Base
self.table_name = 'users'
include EachBatch
end
class Issue < ActiveRecord::Base
self.table_name = 'issues'
include EachBatch
include SoftRemoved
end
class MergeRequest < ActiveRecord::Base
self.table_name = 'merge_requests'
include EachBatch
include SoftRemoved
end
class Namespace < ActiveRecord::Base
self.table_name = 'namespaces'
include EachBatch
include SoftRemoved
scope :soft_removed_personal, -> { soft_removed.where(type: nil) }
scope :soft_removed_group, -> { soft_removed.where(type: 'Group') }
end
class Route < ActiveRecord::Base
self.table_name = 'routes'
include EachBatch
include SoftRemoved
end
class Project < ActiveRecord::Base
self.table_name = 'projects'
include EachBatch
include SoftRemoved
end
class CiPipelineSchedule < ActiveRecord::Base
self.table_name = 'ci_pipeline_schedules'
include EachBatch
include SoftRemoved
end
class CiTrigger < ActiveRecord::Base
self.table_name = 'ci_triggers'
include EachBatch
include SoftRemoved
end
MODELS = [Issue, MergeRequest, CiPipelineSchedule, CiTrigger].freeze
def up
disable_statement_timeout
remove_personal_routes
remove_personal_namespaces
remove_group_namespaces
remove_simple_soft_removed_rows
end
def down
# The data removed by this migration can't be restored in an automated way.
end
def remove_simple_soft_removed_rows
create_temporary_indexes
MODELS.each do |model|
say_with_time("Removing soft removed rows from #{model.table_name}") do
model.soft_removed.each_batch do |batch, index|
batch.delete_all
end
end
end
ensure
remove_temporary_indexes
end
def create_temporary_indexes
MODELS.each do |model|
index_name = temporary_index_name_for(model)
# Without this index the removal process can take a very long time. For
# example, getting the next ID of a batch for the `issues` table in
# staging would take between 15 and 20 seconds.
next if temporary_index_exists?(model)
say_with_time("Creating temporary index #{index_name}") do
add_concurrent_index(
model.table_name,
[:deleted_at, :id],
name: index_name,
where: 'deleted_at IS NOT NULL'
)
end
end
end
def remove_temporary_indexes
MODELS.each do |model|
index_name = temporary_index_name_for(model)
next unless temporary_index_exists?(model)
say_with_time("Removing temporary index #{index_name}") do
remove_concurrent_index_by_name(model.table_name, index_name)
end
end
end
def temporary_index_name_for(model)
"index_on_#{model.table_name}_tmp"
end
def temporary_index_exists?(model)
index_name = temporary_index_name_for(model)
index_exists?(model.table_name, [:deleted_at, :id], name: index_name)
end
def remove_personal_namespaces
# Some personal namespaces are left behind in case of GitLab.com. In these
# cases the associated data such as the projects and users has already been
# removed.
Namespace.soft_removed_personal.each_batch do |batch|
batch.delete_all
end
end
def remove_group_namespaces
admin_id = id_for_admin_user
unless admin_id
say 'Not scheduling soft removed groups for removal as no admin user ' \
'could be found. You will need to remove any such groups manually.'
return
end
# Left over groups can't be easily removed because we may also need to
# remove memberships, repositories, and other associated data. As a result
# we'll just schedule a Sidekiq job to remove these.
#
# As of January 5th, 2018 there are 36 groups that will be removed using
# this code.
Namespace.select(:id).soft_removed_group.each_batch(of: 10) do |batch, index|
batch.each do |ns|
schedule_group_removal(index * 5.minutes, ns.id, admin_id)
end
end
end
def schedule_group_removal(delay, group_id, user_id)
if migrate_inline?
GroupDestroyWorker.new.perform(group_id, user_id)
else
GroupDestroyWorker.perform_in(delay, group_id, user_id)
end
end
def remove_personal_routes
namespaces = Namespace.select(1)
.soft_removed
.where('namespaces.type IS NULL')
.where('routes.source_type = ?', 'Namespace')
.where('routes.source_id = namespaces.id')
Route.where('EXISTS (?)', namespaces).each_batch do |batch|
batch.delete_all
end
end
def id_for_admin_user
User.where(admin: true).limit(1).pluck(:id).first
end
def migrate_inline?
Rails.env.test? || Rails.env.development?
end
end
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class RemoveDeletedAtColumns < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
TABLES = %i[issues merge_requests namespaces ci_pipeline_schedules ci_triggers].freeze
COLUMN = :deleted_at
def up
TABLES.each do |table|
remove_column(table, COLUMN) if column_exists?(table, COLUMN)
end
end
def down
TABLES.each do |table|
unless column_exists?(table, COLUMN)
add_column(table, COLUMN, :datetime_with_timezone)
end
unless index_exists?(table, COLUMN)
add_concurrent_index(table, COLUMN)
end
end
end
end
......@@ -357,7 +357,6 @@ ActiveRecord::Schema.define(version: 20171230123729) do
t.integer "project_id"
t.integer "owner_id"
t.boolean "active", default: true
t.datetime "deleted_at"
t.datetime "created_at"
t.datetime "updated_at"
end
......@@ -467,7 +466,6 @@ ActiveRecord::Schema.define(version: 20171230123729) do
create_table "ci_triggers", force: :cascade do |t|
t.string "token"
t.datetime "deleted_at"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "project_id"
......@@ -862,7 +860,6 @@ ActiveRecord::Schema.define(version: 20171230123729) do
t.integer "iid"
t.integer "updated_by_id"
t.boolean "confidential", default: false, null: false
t.datetime "deleted_at"
t.date "due_date"
t.integer "moved_to_id"
t.integer "lock_version"
......@@ -879,7 +876,6 @@ ActiveRecord::Schema.define(version: 20171230123729) do
add_index "issues", ["author_id"], name: "index_issues_on_author_id", using: :btree
add_index "issues", ["confidential"], name: "index_issues_on_confidential", using: :btree
add_index "issues", ["deleted_at"], name: "index_issues_on_deleted_at", using: :btree
add_index "issues", ["description"], name: "index_issues_on_description_trigram", using: :gin, opclasses: {"description"=>"gin_trgm_ops"}
add_index "issues", ["milestone_id"], name: "index_issues_on_milestone_id", using: :btree
add_index "issues", ["moved_to_id"], name: "index_issues_on_moved_to_id", where: "(moved_to_id IS NOT NULL)", using: :btree
......@@ -1087,7 +1083,6 @@ ActiveRecord::Schema.define(version: 20171230123729) do
t.boolean "merge_when_pipeline_succeeds", default: false, null: false
t.integer "merge_user_id"
t.string "merge_commit_sha"
t.datetime "deleted_at"
t.string "in_progress_merge_commit_sha"
t.integer "lock_version"
t.text "title_html"
......@@ -1106,7 +1101,6 @@ ActiveRecord::Schema.define(version: 20171230123729) do
add_index "merge_requests", ["assignee_id"], name: "index_merge_requests_on_assignee_id", using: :btree
add_index "merge_requests", ["author_id"], name: "index_merge_requests_on_author_id", using: :btree
add_index "merge_requests", ["created_at"], name: "index_merge_requests_on_created_at", using: :btree
add_index "merge_requests", ["deleted_at"], name: "index_merge_requests_on_deleted_at", using: :btree
add_index "merge_requests", ["description"], name: "index_merge_requests_on_description_trigram", using: :gin, opclasses: {"description"=>"gin_trgm_ops"}
add_index "merge_requests", ["head_pipeline_id"], name: "index_merge_requests_on_head_pipeline_id", using: :btree
add_index "merge_requests", ["latest_merge_request_diff_id"], name: "index_merge_requests_on_latest_merge_request_diff_id", using: :btree
......@@ -1166,7 +1160,6 @@ ActiveRecord::Schema.define(version: 20171230123729) do
t.boolean "share_with_group_lock", default: false
t.integer "visibility_level", default: 20, null: false
t.boolean "request_access_enabled", default: false, null: false
t.datetime "deleted_at"
t.text "description_html"
t.boolean "lfs_enabled"
t.integer "parent_id"
......@@ -1176,7 +1169,6 @@ ActiveRecord::Schema.define(version: 20171230123729) do
end
add_index "namespaces", ["created_at"], name: "index_namespaces_on_created_at", using: :btree
add_index "namespaces", ["deleted_at"], name: "index_namespaces_on_deleted_at", using: :btree
add_index "namespaces", ["name", "parent_id"], name: "index_namespaces_on_name_and_parent_id", unique: true, using: :btree
add_index "namespaces", ["name"], name: "index_namespaces_on_name_trigram", using: :gin, opclasses: {"name"=>"gin_trgm_ops"}
add_index "namespaces", ["owner_id"], name: "index_namespaces_on_owner_id", using: :btree
......
......@@ -24,7 +24,6 @@ curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/
"id": 10,
"description": "my trigger",
"created_at": "2016-01-07T09:53:58.235Z",
"deleted_at": null,
"last_used": null,
"token": "6d056f63e50fe6f8c5f8f4aa10edb7",
"updated_at": "2016-01-07T09:53:58.235Z",
......@@ -55,7 +54,6 @@ curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/
"id": 10,
"description": "my trigger",
"created_at": "2016-01-07T09:53:58.235Z",
"deleted_at": null,
"last_used": null,
"token": "6d056f63e50fe6f8c5f8f4aa10edb7",
"updated_at": "2016-01-07T09:53:58.235Z",
......@@ -85,7 +83,6 @@ curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --form descri
"id": 10,
"description": "my trigger",
"created_at": "2016-01-07T09:53:58.235Z",
"deleted_at": null,
"last_used": null,
"token": "6d056f63e50fe6f8c5f8f4aa10edb7",
"updated_at": "2016-01-07T09:53:58.235Z",
......@@ -116,7 +113,6 @@ curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --form descrip
"id": 10,
"description": "my trigger",
"created_at": "2016-01-07T09:53:58.235Z",
"deleted_at": null,
"last_used": null,
"token": "6d056f63e50fe6f8c5f8f4aa10edb7",
"updated_at": "2016-01-07T09:53:58.235Z",
......@@ -146,7 +142,6 @@ curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitl
"id": 10,
"description": "my trigger",
"created_at": "2016-01-07T09:53:58.235Z",
"deleted_at": null,
"last_used": null,
"token": "6d056f63e50fe6f8c5f8f4aa10edb7",
"updated_at": "2016-01-07T09:53:58.235Z",
......
......@@ -920,7 +920,7 @@ module API
class Trigger < Grape::Entity
expose :id
expose :token, :description
expose :created_at, :updated_at, :deleted_at, :last_used
expose :created_at, :updated_at, :last_used
expose :owner, using: Entities::UserBasic
end
......
......@@ -207,7 +207,7 @@ module API
end
class Trigger < Grape::Entity
expose :token, :created_at, :updated_at, :deleted_at, :last_used
expose :token, :created_at, :updated_at, :last_used
expose :owner, using: ::API::Entities::UserBasic
end
......
......@@ -15,7 +15,6 @@ module Gitlab
query = mr_closing_issues_table.join(issue_table).on(issue_table[:id].eq(mr_closing_issues_table[:issue_id]))
.join(issue_metrics_table).on(issue_table[:id].eq(issue_metrics_table[:issue_id]))
.where(issue_table[:project_id].eq(@project.id)) # rubocop:disable Gitlab/ModuleWithInstanceVariables
.where(issue_table[:deleted_at].eq(nil))
.where(issue_table[:created_at].gteq(@options[:from])) # rubocop:disable Gitlab/ModuleWithInstanceVariables
# Load merge_requests
......
......@@ -7,7 +7,6 @@ module Gitlab
closed_at
confidential
created_at
deleted_at
description
due_date
id
......
......@@ -5,7 +5,6 @@ module Gitlab
assignee_id
author_id
created_at
deleted_at
description
head_pipeline_id
id
......
......@@ -28,7 +28,6 @@
"confidential": { "type": "boolean" },
"discussion_locked": { "type": ["boolean", "null"] },
"updated_by_id": { "type": ["string", "null"] },
"deleted_at": { "type": ["string", "null"] },
"time_estimate": { "type": "integer" },
"total_time_spent": { "type": "integer" },
"human_time_estimate": { "type": ["integer", "null"] },
......
......@@ -13,7 +13,6 @@
"updated_by_id": { "type": ["string", "null"] },
"created_at": { "type": "string" },
"updated_at": { "type": "string" },
"deleted_at": { "type": ["string", "null"] },
"time_estimate": { "type": "integer" },
"total_time_spent": { "type": "integer" },
"human_time_estimate": { "type": ["integer", "null"] },
......
......@@ -29,7 +29,6 @@ export const noteableDataMock = {
can_create_note: true,
can_update: true,
},
deleted_at: null,
description: '',
due_date: null,
human_time_estimate: null,
......@@ -283,7 +282,6 @@ export const loggedOutnoteableData = {
"updated_by_id": 1,
"created_at": "2017-02-07T10:11:18.395Z",
"updated_at": "2017-08-08T10:22:51.564Z",
"deleted_at": null,
"time_estimate": 0,
"total_time_spent": 0,
"human_time_estimate": null,
......
......@@ -15,7 +15,6 @@ const RESPONSE_MAP = {
updated_by_id: 1,
created_at: '2017-02-02T21: 49: 49.664Z',
updated_at: '2017-05-03T22: 26: 03.760Z',
deleted_at: null,
time_estimate: 0,
total_time_spent: 0,
human_time_estimate: null,
......@@ -153,7 +152,6 @@ const RESPONSE_MAP = {
updated_by_id: 1,
created_at: '2017-06-27T19:54:42.437Z',
updated_at: '2017-08-18T03:39:49.222Z',
deleted_at: null,
time_estimate: 0,
total_time_spent: 0,
human_time_estimate: null,
......
......@@ -14,7 +14,6 @@ export default {
"updated_by_id": null,
"created_at": "2017-04-07T12:27:26.718Z",
"updated_at": "2017-04-07T15:39:25.852Z",
"deleted_at": null,
"time_estimate": 0,
"total_time_spent": 0,
"human_time_estimate": null,
......
......@@ -14,7 +14,6 @@ describe Gitlab::HookData::IssueBuilder do
closed_at
confidential
created_at
deleted_at
description
due_date
id
......
......@@ -12,7 +12,6 @@ describe Gitlab::HookData::MergeRequestBuilder do
assignee_id
author_id
created_at
deleted_at
description
head_pipeline_id
id
......
......@@ -54,7 +54,6 @@
"iid": 1,
"updated_by_id": 1,
"confidential": false,
"deleted_at": null,
"due_date": null,
"moved_to_id": null,
"lock_version": null,
......@@ -134,7 +133,6 @@
"iid": 2,
"updated_by_id": 1,
"confidential": false,
"deleted_at": null,
"due_date": null,
"moved_to_id": null,
"lock_version": null,
......
......@@ -56,7 +56,6 @@
"iid": 10,
"updated_by_id": null,
"confidential": false,
"deleted_at": null,
"due_date": null,
"moved_to_id": null,
"test_ee_field": "test",
......@@ -350,7 +349,6 @@
"iid": 9,
"updated_by_id": null,
"confidential": false,
"deleted_at": null,
"due_date": null,
"moved_to_id": null,
"milestone": {
......@@ -586,7 +584,6 @@
"iid": 8,
"updated_by_id": null,
"confidential": false,
"deleted_at": null,
"due_date": null,
"moved_to_id": null,
"label_links": [
......@@ -820,7 +817,6 @@
"iid": 7,
"updated_by_id": null,
"confidential": false,
"deleted_at": null,
"due_date": null,
"moved_to_id": null,
"notes": [
......@@ -1033,7 +1029,6 @@
"iid": 6,
"updated_by_id": null,
"confidential": false,
"deleted_at": null,
"due_date": null,
"moved_to_id": null,
"notes": [
......@@ -1246,7 +1241,6 @@
"iid": 5,
"updated_by_id": null,
"confidential": false,
"deleted_at": null,
"due_date": null,
"moved_to_id": null,
"notes": [
......@@ -1459,7 +1453,6 @@
"iid": 4,
"updated_by_id": null,
"confidential": false,
"deleted_at": null,
"due_date": null,
"moved_to_id": null,
"notes": [
......@@ -1672,7 +1665,6 @@
"iid": 3,
"updated_by_id": null,
"confidential": false,
"deleted_at": null,
"due_date": null,
"moved_to_id": null,
"notes": [
......@@ -1885,7 +1877,6 @@
"iid": 2,
"updated_by_id": null,
"confidential": false,
"deleted_at": null,
"due_date": null,
"moved_to_id": null,
"notes": [
......@@ -2098,7 +2089,6 @@
"iid": 1,
"updated_by_id": null,
"confidential": false,
"deleted_at": null,
"due_date": null,
"moved_to_id": null,
"notes": [
......@@ -2504,7 +2494,6 @@
"merge_when_pipeline_succeeds": true,
"merge_user_id": null,
"merge_commit_sha": null,
"deleted_at": null,
"notes": [
{
"id": 671,
......@@ -2948,7 +2937,6 @@
"merge_when_pipeline_succeeds": false,
"merge_user_id": null,
"merge_commit_sha": null,
"deleted_at": null,
"notes": [
{
"id": 679,
......@@ -3228,7 +3216,6 @@
"merge_when_pipeline_succeeds": false,
"merge_user_id": null,
"merge_commit_sha": null,
"deleted_at": null,
"notes": [
{
"id": 777,
......@@ -3508,7 +3495,6 @@
"merge_when_pipeline_succeeds": false,
"merge_user_id": null,
"merge_commit_sha": null,
"deleted_at": null,
"notes": [
{
"id": 785,
......@@ -4198,7 +4184,6 @@
"merge_when_pipeline_succeeds": false,
"merge_user_id": null,
"merge_commit_sha": null,
"deleted_at": null,
"notes": [
{
"id": 793,
......@@ -4734,7 +4719,6 @@
"merge_when_pipeline_succeeds": false,
"merge_user_id": null,
"merge_commit_sha": null,
"deleted_at": null,
"notes": [
{
"id": 801,
......@@ -5223,7 +5207,6 @@
"merge_when_pipeline_succeeds": false,
"merge_user_id": null,
"merge_commit_sha": null,
"deleted_at": null,
"notes": [
{
"id": 809,
......@@ -5478,7 +5461,6 @@
"merge_when_pipeline_succeeds": false,
"merge_user_id": null,
"merge_commit_sha": null,
"deleted_at": null,
"notes": [
{
"id": 817,
......@@ -6168,7 +6150,6 @@
"merge_when_pipeline_succeeds": false,
"merge_user_id": null,
"merge_commit_sha": null,
"deleted_at": null,
"notes": [
{
"id": 825,
......@@ -6968,7 +6949,6 @@
"id": 123,
"token": "cdbfasdf44a5958c83654733449e585",
"project_id": 5,
"deleted_at": null,
"created_at": "2017-01-16T15:25:28.637Z",
"updated_at": "2017-01-16T15:25:28.637Z"
}
......
......@@ -54,7 +54,6 @@
"iid": 20,
"updated_by_id": 1,
"confidential": false,
"deleted_at": null,
"due_date": null,
"moved_to_id": null,
"lock_version": null,
......
......@@ -14,7 +14,6 @@ Issue:
- iid
- updated_by_id
- confidential
- deleted_at
- closed_at
- due_date
- moved_to_id
......@@ -159,7 +158,6 @@ MergeRequest:
- merge_when_pipeline_succeeds
- merge_user_id
- merge_commit_sha
- deleted_at
- in_progress_merge_commit_sha
- lock_version
- milestone_id
......@@ -293,7 +291,6 @@ Ci::Trigger:
- id
- token
- project_id
- deleted_at
- created_at
- updated_at
- owner_id
......@@ -309,7 +306,6 @@ Ci::PipelineSchedule:
- project_id
- owner_id
- active
- deleted_at
- created_at
- updated_at
Clusters::Cluster:
......
require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20171207150343_remove_soft_removed_objects.rb')
describe RemoveSoftRemovedObjects, :migration do
describe '#up' do
it 'removes various soft removed objects' do
5.times do
create_with_deleted_at(:issue)
end
regular_issue = create(:issue)
run_migration
expect(Issue.count).to eq(1)
expect(Issue.first).to eq(regular_issue)
end
it 'removes the temporary indexes once soft removed data has been removed' do
migration = described_class.new
run_migration
disable_migrations_output do
expect(migration.temporary_index_exists?(Issue)).to eq(false)
end
end
it 'removes routes of soft removed personal namespaces' do
namespace = create_with_deleted_at(:namespace)
group = create(:group)
expect(Route.where(source: namespace).exists?).to eq(true)
expect(Route.where(source: group).exists?).to eq(true)
run_migration
expect(Route.where(source: namespace).exists?).to eq(false)
expect(Route.where(source: group).exists?).to eq(true)
end
it 'schedules the removal of soft removed groups' do
group = create_with_deleted_at(:group)
admin = create(:user, admin: true)
expect_any_instance_of(GroupDestroyWorker)
.to receive(:perform)
.with(group.id, admin.id)
run_migration
end
it 'does not remove soft removed groups when no admin user could be found' do
create_with_deleted_at(:group)
expect_any_instance_of(GroupDestroyWorker)
.not_to receive(:perform)
run_migration
end
end
def run_migration
disable_migrations_output do
migrate!
end
end
def create_with_deleted_at(*args)
row = create(*args)
# We set "deleted_at" this way so we don't run into any column cache issues.
row.class.where(id: row.id).update_all(deleted_at: 1.year.ago)
row
end
end
......@@ -12,7 +12,6 @@ describe Ci::PipelineSchedule do
it { is_expected.to respond_to(:cron_timezone) }
it { is_expected.to respond_to(:description) }
it { is_expected.to respond_to(:next_run_at) }
it { is_expected.to respond_to(:deleted_at) }
describe 'validations' do
it 'does not allow invalid cron patters' do
......
......@@ -18,11 +18,6 @@ describe Issue do
subject { create(:issue) }
describe "act_as_paranoid" do
it { is_expected.to have_db_column(:deleted_at) }
it { is_expected.to have_db_index(:deleted_at) }
end
describe 'callbacks' do
describe '#ensure_metrics' do
it 'creates metrics after saving' do
......
......@@ -24,11 +24,6 @@ describe MergeRequest do
it { is_expected.to include_module(Taskable) }
end
describe "act_as_paranoid" do
it { is_expected.to have_db_column(:deleted_at) }
it { is_expected.to have_db_index(:deleted_at) }
end
describe 'validation' do
it { is_expected.to validate_presence_of(:target_branch) }
it { is_expected.to validate_presence_of(:source_branch) }
......
......@@ -410,17 +410,6 @@ describe Namespace do
end
end
describe '#soft_delete_without_removing_associations' do
let(:project1) { create(:project_empty_repo, namespace: namespace) }
it 'updates the deleted_at timestamp but preserves projects' do
namespace.soft_delete_without_removing_associations
expect(Project.all).to include(project1)
expect(namespace.deleted_at).not_to be_nil
end
end
describe '#user_ids_for_project_authorizations' do
it 'returns the user IDs for which to refresh authorizations' do
expect(namespace.user_ids_for_project_authorizations)
......
......@@ -15,7 +15,7 @@ describe Users::DestroyService do
expect { user_data['email'].to eq(user.email) }
expect { User.find(user.id) }.to raise_error(ActiveRecord::RecordNotFound)
expect { Namespace.with_deleted.find(namespace.id) }.to raise_error(ActiveRecord::RecordNotFound)
expect { Namespace.find(namespace.id) }.to raise_error(ActiveRecord::RecordNotFound)
end
it 'will delete the project' do
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment