4b9c17f196
This moves the logic of Project#rename_repo and all methods _only_ used by this method into a new service class: Projects::AfterRenameService. By moving this code into a separate service class we can more easily refactor it, and we also get rid of some RuboCop "disable" statements automatically. During the refactoring of this code, I removed most of the explicit logging using Gitlab::AppLogger. The data that was logged would not be useful when debugging renaming issues, as it does not add any value on top of data provided by users. I also removed a variety of comments that either mentioned something the code does in literal form, or contained various grammatical errors. Instead we now resort to more clearly named methods, removing the need for code comments. This method was chosen based on analysis in https://gitlab.com/gitlab-org/release/framework/issues/28. In this issue we determined this method has seen a total of 293 lines being changed in it. We also noticed that RuboCop determined the ABC size (https://www.softwarerenovation.com/ABCMetric.pdf) was too great.
128 lines
3.7 KiB
Ruby
128 lines
3.7 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module Projects
|
|
class UpdateService < BaseService
|
|
include UpdateVisibilityLevel
|
|
|
|
ValidationError = Class.new(StandardError)
|
|
|
|
# rubocop: disable CodeReuse/ActiveRecord
|
|
def execute
|
|
validate!
|
|
|
|
ensure_wiki_exists if enabling_wiki?
|
|
|
|
yield if block_given?
|
|
|
|
# If the block added errors, don't try to save the project
|
|
return update_failed! if project.errors.any?
|
|
|
|
if project.update(params.except(:default_branch))
|
|
after_update
|
|
|
|
success
|
|
else
|
|
update_failed!
|
|
end
|
|
rescue ValidationError => e
|
|
error(e.message)
|
|
end
|
|
# rubocop: enable CodeReuse/ActiveRecord
|
|
|
|
def run_auto_devops_pipeline?
|
|
return false if project.repository.gitlab_ci_yml || !project.auto_devops&.previous_changes&.include?('enabled')
|
|
|
|
project.auto_devops_enabled?
|
|
end
|
|
|
|
private
|
|
|
|
def validate!
|
|
unless valid_visibility_level_change?(project, params[:visibility_level])
|
|
raise ValidationError.new('New visibility level not allowed!')
|
|
end
|
|
|
|
if renaming_project_with_container_registry_tags?
|
|
raise ValidationError.new('Cannot rename project because it contains container registry tags!')
|
|
end
|
|
|
|
if changing_default_branch?
|
|
raise ValidationError.new("Could not set the default branch") unless project.change_head(params[:default_branch])
|
|
end
|
|
end
|
|
|
|
def after_update
|
|
todos_features_changes = %w(
|
|
issues_access_level
|
|
merge_requests_access_level
|
|
repository_access_level
|
|
)
|
|
project_changed_feature_keys = project.project_feature.previous_changes.keys
|
|
|
|
if project.previous_changes.include?(:visibility_level) && project.private?
|
|
# don't enqueue immediately to prevent todos removal in case of a mistake
|
|
TodosDestroyer::ProjectPrivateWorker.perform_in(1.hour, project.id)
|
|
elsif (project_changed_feature_keys & todos_features_changes).present?
|
|
TodosDestroyer::PrivateFeaturesWorker.perform_in(1.hour, project.id)
|
|
end
|
|
|
|
if project.previous_changes.include?('path')
|
|
AfterRenameService.new(project).execute
|
|
else
|
|
system_hook_service.execute_hooks_for(project, :update)
|
|
end
|
|
|
|
update_pages_config if changing_pages_related_config?
|
|
end
|
|
|
|
def changing_pages_related_config?
|
|
changing_pages_https_only? || changing_pages_access_level?
|
|
end
|
|
|
|
def update_failed!
|
|
model_errors = project.errors.full_messages.to_sentence
|
|
error_message = model_errors.presence || 'Project could not be updated!'
|
|
|
|
error(error_message)
|
|
end
|
|
|
|
def renaming_project_with_container_registry_tags?
|
|
new_path = params[:path]
|
|
|
|
new_path && new_path != project.path &&
|
|
project.has_container_registry_tags?
|
|
end
|
|
|
|
def changing_default_branch?
|
|
new_branch = params[:default_branch]
|
|
|
|
new_branch && project.repository.exists? &&
|
|
new_branch != project.default_branch
|
|
end
|
|
|
|
def enabling_wiki?
|
|
return false if project.wiki_enabled?
|
|
|
|
params.dig(:project_feature_attributes, :wiki_access_level).to_i > ProjectFeature::DISABLED
|
|
end
|
|
|
|
def changing_pages_access_level?
|
|
params.dig(:project_feature_attributes, :pages_access_level)
|
|
end
|
|
|
|
def ensure_wiki_exists
|
|
ProjectWiki.new(project, project.owner).wiki
|
|
rescue ProjectWiki::CouldNotCreateWikiError
|
|
log_error("Could not create wiki for #{project.full_name}")
|
|
Gitlab::Metrics.counter(:wiki_can_not_be_created_total, 'Counts the times we failed to create a wiki')
|
|
end
|
|
|
|
def update_pages_config
|
|
Projects::UpdatePagesConfigurationService.new(project).execute
|
|
end
|
|
|
|
def changing_pages_https_only?
|
|
project.previous_changes.include?(:pages_https_only)
|
|
end
|
|
end
|
|
end
|