Commit 101d52b3 authored by Douwe Maan's avatar Douwe Maan

Merge branch 'tc-remove-nonexisting-namespace-pending-delete-projects' into 'master'

Add migration to remove pending delete projects with non-existing namespace

Closes #36541

See merge request !13598
parents 72b5d954 d4e5ac1b
......@@ -18,7 +18,8 @@ class NamespacelessProjectDestroyWorker
rescue ActiveRecord::RecordNotFound
return
end
return unless project.namespace_id.nil? # Reject doing anything for projects that *do* have a namespace
return if project.namespace # Reject doing anything for projects that *do* have a namespace
project.team.truncate
......
---
title: Migration to remove pending delete projects with non-existing namespace
merge_request: 13598
author:
type: other
# Follow up of CleanupNamespacelessPendingDeleteProjects and it cleans
# all projects with `pending_delete = true` and for which the
# namespace no longer exists.
class CleanupNonexistingNamespacePendingDeleteProjects < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
class Project < ActiveRecord::Base
self.table_name = 'projects'
include ::EachBatch
end
class Namespace < ActiveRecord::Base
self.table_name = 'namespaces'
end
def up
find_projects.each_batch do |batch|
args = batch.pluck(:id).map { |id| [id] }
NamespacelessProjectDestroyWorker.bulk_perform_async(args)
end
end
def down
# NOOP
end
private
def find_projects
projects = Project.arel_table
namespaces = Namespace.arel_table
namespace_query = namespaces.project(1)
.where(namespaces[:id].eq(projects[:namespace_id]))
.exists.not
# SELECT "projects"."id"
# FROM "projects"
# WHERE "projects"."pending_delete" = 't'
# AND (NOT (EXISTS
# (SELECT 1
# FROM "namespaces"
# WHERE "namespaces"."id" = "projects"."namespace_id")))
Project.where(projects[:pending_delete].eq(true))
.where(namespace_query)
.select(:id)
end
end
require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20170816102555_cleanup_nonexisting_namespace_pending_delete_projects.rb')
describe CleanupNonexistingNamespacePendingDeleteProjects do
before do
# Stub after_save callbacks that will fail when Project has invalid namespace
allow_any_instance_of(Project).to receive(:ensure_storage_path_exist).and_return(nil)
allow_any_instance_of(Project).to receive(:update_project_statistics).and_return(nil)
end
describe '#up' do
set(:some_project) { create(:project) }
it 'only cleans up when namespace does not exist' do
create(:project, pending_delete: true)
project = build(:project, pending_delete: true, namespace: nil, namespace_id: Namespace.maximum(:id).to_i.succ)
project.save(validate: false)
expect(NamespacelessProjectDestroyWorker).to receive(:bulk_perform_async).with([[project.id]])
described_class.new.up
end
it 'does nothing when no pending delete projects without namespace found' do
create(:project, pending_delete: true, namespace: create(:namespace))
expect(NamespacelessProjectDestroyWorker).not_to receive(:bulk_perform_async)
described_class.new.up
end
end
end
......@@ -75,5 +75,19 @@ describe NamespacelessProjectDestroyWorker do
end
end
end
context 'project has non-existing namespace' do
let!(:project) do
project = build(:project, namespace_id: Namespace.maximum(:id).to_i.succ)
project.save(validate: false)
project
end
it 'deletes the project' do
subject.perform(project.id)
expect(Project.unscoped.all).not_to include(project)
end
end
end
end
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