Commit 91b9cbff authored by Josh Frye's avatar Josh Frye

First pass at deleting projects in the background.

parent 22772871
Please view this file on the master branch, on stable branches it's out of date. Please view this file on the master branch, on stable branches it's out of date.
v 8.6.0 (unreleased)
- Delete project and associations in a background worker
v 8.5.0 (unreleased) v 8.5.0 (unreleased)
- Ensure rake tasks that don't need a DB connection can be run without one - Ensure rake tasks that don't need a DB connection can be run without one
- Add "visibility" flag to GET /projects api endpoint - Add "visibility" flag to GET /projects api endpoint
......
...@@ -93,6 +93,10 @@ class ProjectsController < ApplicationController ...@@ -93,6 +93,10 @@ class ProjectsController < ApplicationController
return return
end end
if @project.pending_delete?
flash[:alert] = "Project queued for delete."
end
respond_to do |format| respond_to do |format|
format.html do format.html do
if @project.repository_exists? if @project.repository_exists?
...@@ -120,8 +124,8 @@ class ProjectsController < ApplicationController ...@@ -120,8 +124,8 @@ class ProjectsController < ApplicationController
def destroy def destroy
return access_denied! unless can?(current_user, :remove_project, @project) return access_denied! unless can?(current_user, :remove_project, @project)
::Projects::DestroyService.new(@project, current_user, {}).execute ::Projects::DestroyService.new(@project, current_user, {}).pending_delete!
flash[:alert] = "Project '#{@project.name}' was deleted." flash[:alert] = "Project '#{@project.name}' will be deleted."
redirect_to dashboard_projects_path redirect_to dashboard_projects_path
rescue Projects::DestroyService::DestroyError => ex rescue Projects::DestroyService::DestroyError => ex
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
# build_coverage_regex :string # build_coverage_regex :string
# build_allow_git_fetch :boolean default(TRUE), not null # build_allow_git_fetch :boolean default(TRUE), not null
# build_timeout :integer default(3600), not null # build_timeout :integer default(3600), not null
# pending_delete :boolean
# #
require 'carrierwave/orm/activerecord' require 'carrierwave/orm/activerecord'
......
...@@ -13,7 +13,7 @@ class DeleteUserService ...@@ -13,7 +13,7 @@ class DeleteUserService
user.personal_projects.each do |project| user.personal_projects.each do |project|
# Skip repository removal because we remove directory with namespace # Skip repository removal because we remove directory with namespace
# that contain all this repositories # that contain all this repositories
::Projects::DestroyService.new(project, current_user, skip_repo: true).execute ::Projects::DestroyService.new(project, current_user, skip_repo: true).pending_delete!
end end
user.destroy user.destroy
......
...@@ -9,7 +9,7 @@ class DestroyGroupService ...@@ -9,7 +9,7 @@ class DestroyGroupService
@group.projects.each do |project| @group.projects.each do |project|
# Skip repository removal because we remove directory with namespace # Skip repository removal because we remove directory with namespace
# that contain all this repositories # that contain all this repositories
::Projects::DestroyService.new(project, current_user, skip_repo: true).execute ::Projects::DestroyService.new(project, current_user, skip_repo: true).pending_delete!
end end
@group.destroy @group.destroy
......
...@@ -6,6 +6,12 @@ module Projects ...@@ -6,6 +6,12 @@ module Projects
DELETED_FLAG = '+deleted' DELETED_FLAG = '+deleted'
def pending_delete!
project.update_attribute(:pending_delete, true)
ProjectDestroyWorker.perform_in(1.minute, project.id, current_user.id, params)
end
def execute def execute
return false unless can?(current_user, :remove_project, project) return false unless can?(current_user, :remove_project, project)
......
class ProjectDestroyWorker
include Sidekiq::Worker
sidekiq_options queue: :default
def perform(project_id, user_id, params)
begin
project = Project.find(project_id)
rescue ActiveRecord::RecordNotFound
return
end
user = User.find(user_id)
::Projects::DestroyService.new(project, user, params).execute
end
end
class AddPendingDeleteToProject < ActiveRecord::Migration
def change
add_column :projects, :pending_delete, :boolean
end
end
...@@ -677,6 +677,7 @@ ActiveRecord::Schema.define(version: 20160128212447) do ...@@ -677,6 +677,7 @@ ActiveRecord::Schema.define(version: 20160128212447) do
t.string "build_coverage_regex" t.string "build_coverage_regex"
t.boolean "build_allow_git_fetch", default: true, null: false t.boolean "build_allow_git_fetch", default: true, null: false
t.integer "build_timeout", default: 3600, null: false t.integer "build_timeout", default: 3600, null: false
t.boolean "pending_delete"
end end
add_index "projects", ["builds_enabled", "shared_runners_enabled"], name: "index_projects_on_builds_enabled_and_shared_runners_enabled", using: :btree add_index "projects", ["builds_enabled", "shared_runners_enabled"], name: "index_projects_on_builds_enabled_and_shared_runners_enabled", using: :btree
...@@ -728,9 +729,9 @@ ActiveRecord::Schema.define(version: 20160128212447) do ...@@ -728,9 +729,9 @@ ActiveRecord::Schema.define(version: 20160128212447) do
t.string "type" t.string "type"
t.string "title" t.string "title"
t.integer "project_id" t.integer "project_id"
t.datetime "created_at", null: false t.datetime "created_at"
t.datetime "updated_at", null: false t.datetime "updated_at"
t.boolean "active", null: false t.boolean "active", default: false, null: false
t.text "properties" t.text "properties"
t.boolean "template", default: false t.boolean "template", default: false
t.boolean "push_events", default: true t.boolean "push_events", default: true
......
...@@ -187,7 +187,7 @@ module API ...@@ -187,7 +187,7 @@ module API
else else
present @forked_project, with: Entities::Project, present @forked_project, with: Entities::Project,
user_can_admin_project: can?(current_user, :admin_project, @forked_project) user_can_admin_project: can?(current_user, :admin_project, @forked_project)
end end
end end
# Update an existing project # Update an existing project
...@@ -246,7 +246,7 @@ module API ...@@ -246,7 +246,7 @@ module API
# DELETE /projects/:id # DELETE /projects/:id
delete ":id" do delete ":id" do
authorize! :remove_project, user_project authorize! :remove_project, user_project
::Projects::DestroyService.new(user_project, current_user, {}).execute ::Projects::DestroyService.new(user_project, current_user, {}).pending_delete!
end end
# Mark this project as forked from another # Mark this project as forked from another
......
...@@ -36,7 +36,7 @@ describe SystemHook, models: true do ...@@ -36,7 +36,7 @@ describe SystemHook, models: true do
it "project_destroy hook" do it "project_destroy hook" do
user = create(:user) user = create(:user)
project = create(:empty_project, namespace: user.namespace) project = create(:empty_project, namespace: user.namespace)
Projects::DestroyService.new(project, user, {}).execute Projects::DestroyService.new(project, user, {}).pending_delete!
expect(WebMock).to have_requested(:post, @system_hook.url).with( expect(WebMock).to have_requested(:post, @system_hook.url).with(
body: /project_destroy/, body: /project_destroy/,
headers: { 'Content-Type'=>'application/json', 'X-Gitlab-Event'=>'System Hook' } headers: { 'Content-Type'=>'application/json', 'X-Gitlab-Event'=>'System Hook' }
...@@ -65,7 +65,7 @@ describe SystemHook, models: true do ...@@ -65,7 +65,7 @@ describe SystemHook, models: true do
project = create(:project) project = create(:project)
project.team << [user, :master] project.team << [user, :master]
expect(WebMock).to have_requested(:post, @system_hook.url).with( expect(WebMock).to have_requested(:post, @system_hook.url).with(
body: /user_add_to_team/, body: /user_add_to_team/,
headers: { 'Content-Type'=>'application/json', 'X-Gitlab-Event'=>'System Hook' } headers: { 'Content-Type'=>'application/json', 'X-Gitlab-Event'=>'System Hook' }
).once ).once
end end
...@@ -76,7 +76,7 @@ describe SystemHook, models: true do ...@@ -76,7 +76,7 @@ describe SystemHook, models: true do
project.team << [user, :master] project.team << [user, :master]
project.project_members.destroy_all project.project_members.destroy_all
expect(WebMock).to have_requested(:post, @system_hook.url).with( expect(WebMock).to have_requested(:post, @system_hook.url).with(
body: /user_remove_from_team/, body: /user_remove_from_team/,
headers: { 'Content-Type'=>'application/json', 'X-Gitlab-Event'=>'System Hook' } headers: { 'Content-Type'=>'application/json', 'X-Gitlab-Event'=>'System Hook' }
).once ).once
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