2020-02-14 19:08:48 -05:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
# PostReceiveService class
|
|
|
|
#
|
|
|
|
# Used for scheduling related jobs after a push action has been performed
|
|
|
|
class PostReceiveService
|
2020-03-04 19:07:49 -05:00
|
|
|
attr_reader :user, :repository, :project, :params
|
2020-02-14 19:08:48 -05:00
|
|
|
|
2020-03-04 19:07:49 -05:00
|
|
|
def initialize(user, repository, project, params)
|
2020-02-14 19:08:48 -05:00
|
|
|
@user = user
|
2020-03-04 19:07:49 -05:00
|
|
|
@repository = repository
|
2020-02-14 19:08:48 -05:00
|
|
|
@project = project
|
|
|
|
@params = params
|
|
|
|
end
|
|
|
|
|
|
|
|
def execute
|
|
|
|
response = Gitlab::InternalPostReceive::Response.new
|
|
|
|
|
|
|
|
push_options = Gitlab::PushOptions.new(params[:push_options])
|
2021-08-18 20:11:16 -04:00
|
|
|
mr_options = push_options.get(:merge_request)
|
2020-02-14 19:08:48 -05:00
|
|
|
|
|
|
|
response.reference_counter_decreased = Gitlab::ReferenceCounter.new(params[:gl_repository]).decrease
|
|
|
|
|
2021-08-18 20:11:16 -04:00
|
|
|
# The PostReceive worker will normally invalidate the cache. However, it
|
|
|
|
# runs asynchronously. If push options require us to create a new merge
|
|
|
|
# request synchronously, we can't rely on that, so invalidate the cache here
|
|
|
|
repository&.expire_branches_cache if mr_options&.fetch(:create, false)
|
|
|
|
|
2020-02-14 19:08:48 -05:00
|
|
|
PostReceive.perform_async(params[:gl_repository], params[:identifier],
|
|
|
|
params[:changes], push_options.as_json)
|
|
|
|
|
|
|
|
if mr_options.present?
|
2020-03-04 19:07:49 -05:00
|
|
|
message = process_mr_push_options(mr_options, params[:changes])
|
2020-02-14 19:08:48 -05:00
|
|
|
response.add_alert_message(message)
|
|
|
|
end
|
|
|
|
|
|
|
|
response.add_alert_message(broadcast_message)
|
|
|
|
response.add_merge_request_urls(merge_request_urls)
|
|
|
|
|
2021-06-22 11:06:55 -04:00
|
|
|
# Neither User nor Repository are guaranteed to be returned; an orphaned write deploy
|
2020-02-14 19:08:48 -05:00
|
|
|
# key could be used
|
2021-06-22 11:06:55 -04:00
|
|
|
if user && repository
|
|
|
|
redirect_message = Gitlab::Checks::ContainerMoved.fetch_message(user, repository)
|
|
|
|
project_created_message = Gitlab::Checks::ProjectCreated.fetch_message(user, repository)
|
2020-02-14 19:08:48 -05:00
|
|
|
|
|
|
|
response.add_basic_message(redirect_message)
|
|
|
|
response.add_basic_message(project_created_message)
|
2020-12-03 13:10:10 -05:00
|
|
|
|
|
|
|
record_onboarding_progress
|
2020-02-14 19:08:48 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
response
|
|
|
|
end
|
|
|
|
|
2020-03-04 19:07:49 -05:00
|
|
|
def process_mr_push_options(push_options, changes)
|
2021-03-24 23:09:35 -04:00
|
|
|
Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/28494')
|
2020-03-04 19:07:49 -05:00
|
|
|
return unless repository
|
|
|
|
|
|
|
|
unless repository.repo_type.project?
|
|
|
|
return push_options_warning('Push options are only supported for projects')
|
|
|
|
end
|
2020-02-14 19:08:48 -05:00
|
|
|
|
|
|
|
service = ::MergeRequests::PushOptionsHandlerService.new(
|
2021-05-11 23:10:21 -04:00
|
|
|
project: project, current_user: user, changes: changes, push_options: push_options
|
2020-02-14 19:08:48 -05:00
|
|
|
).execute
|
|
|
|
|
|
|
|
if service.errors.present?
|
|
|
|
push_options_warning(service.errors.join("\n\n"))
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def push_options_warning(warning)
|
|
|
|
options = Array.wrap(params[:push_options]).map { |p| "'#{p}'" }.join(' ')
|
|
|
|
"WARNINGS:\nError encountered with push options #{options}: #{warning}"
|
|
|
|
end
|
|
|
|
|
|
|
|
def merge_request_urls
|
2020-03-04 19:07:49 -05:00
|
|
|
return [] unless repository&.repo_type&.project?
|
|
|
|
|
2021-05-11 23:10:21 -04:00
|
|
|
::MergeRequests::GetUrlsService.new(project: project).execute(params[:changes])
|
2020-02-14 19:08:48 -05:00
|
|
|
end
|
2020-10-29 17:08:54 -04:00
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
def broadcast_message
|
|
|
|
banner = nil
|
|
|
|
|
|
|
|
if project
|
2022-03-07 07:16:11 -05:00
|
|
|
scoped_messages = BroadcastMessage.current_banner_messages(current_path: project.full_path).select do |message|
|
2020-10-29 17:08:54 -04:00
|
|
|
message.target_path.present? && message.matches_current_path(project.full_path)
|
|
|
|
end
|
|
|
|
|
|
|
|
banner = scoped_messages.last
|
|
|
|
end
|
|
|
|
|
|
|
|
banner ||= BroadcastMessage.current_banner_messages.last
|
|
|
|
|
|
|
|
banner&.message
|
|
|
|
end
|
2020-12-03 13:10:10 -05:00
|
|
|
|
|
|
|
def record_onboarding_progress
|
2021-06-22 11:06:55 -04:00
|
|
|
return unless project
|
|
|
|
|
2022-09-09 20:09:59 -04:00
|
|
|
Onboarding::ProgressService.new(project.namespace).execute(action: :git_write)
|
2020-12-03 13:10:10 -05:00
|
|
|
end
|
2020-02-14 19:08:48 -05:00
|
|
|
end
|
2020-04-21 23:09:19 -04:00
|
|
|
|
2021-05-11 17:10:21 -04:00
|
|
|
PostReceiveService.prepend_mod_with('PostReceiveService')
|