debian-mirror-gitlab/app/services/projects/update_remote_mirror_service.rb

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

120 lines
3.6 KiB
Ruby
Raw Normal View History

2018-11-18 11:00:15 +05:30
# frozen_string_literal: true
2018-10-15 14:42:47 +05:30
module Projects
class UpdateRemoteMirrorService < BaseService
2021-01-03 14:25:43 +05:30
include Gitlab::Utils::StrongMemoize
2019-10-12 21:52:04 +05:30
MAX_TRIES = 3
2018-10-15 14:42:47 +05:30
2019-10-12 21:52:04 +05:30
def execute(remote_mirror, tries)
2018-10-15 14:42:47 +05:30
return success unless remote_mirror.enabled?
2021-04-29 21:17:54 +05:30
# Blocked URLs are a hard failure, no need to attempt to retry
2023-03-04 22:38:38 +05:30
if Gitlab::UrlBlocker.blocked_url?(normalized_url(remote_mirror.url), schemes: Project::VALID_MIRROR_PROTOCOLS)
2021-04-29 21:17:54 +05:30
hard_retry_or_fail(remote_mirror, _('The remote mirror URL is invalid.'), tries)
return error(remote_mirror.last_error)
2020-09-03 11:15:55 +05:30
end
2019-10-12 21:52:04 +05:30
update_mirror(remote_mirror)
2018-12-05 23:21:45 +05:30
2019-10-12 21:52:04 +05:30
success
rescue Gitlab::Git::CommandError => e
# This happens if one of the gitaly calls above fail, for example when
# branches have diverged, or the pre-receive hook fails.
2021-04-29 21:17:54 +05:30
hard_retry_or_fail(remote_mirror, e.message, tries)
2018-10-15 14:42:47 +05:30
2019-10-12 21:52:04 +05:30
error(e.message)
2021-06-08 01:23:25 +05:30
rescue StandardError => e
2021-04-29 21:17:54 +05:30
remote_mirror.hard_fail!(e.message)
2019-10-12 21:52:04 +05:30
raise e
end
private
2021-01-03 14:25:43 +05:30
def normalized_url(url)
strong_memoize(:normalized_url) do
CGI.unescape(Gitlab::UrlSanitizer.sanitize(url))
end
end
2019-10-12 21:52:04 +05:30
def update_mirror(remote_mirror)
remote_mirror.update_start!
2020-06-23 00:09:42 +05:30
2020-11-24 15:15:51 +05:30
# LFS objects must be sent first, or the push has dangling pointers
2022-03-02 08:16:31 +05:30
lfs_status = send_lfs_objects!(remote_mirror)
2020-11-24 15:15:51 +05:30
2021-10-27 15:23:28 +05:30
response = remote_mirror.update_repository
2022-03-02 08:16:31 +05:30
failed, failure_message = failure_status(lfs_status, response, remote_mirror)
# When the issue https://gitlab.com/gitlab-org/gitlab/-/issues/349262 is closed,
# we can move this block within failure_status.
if failed
remote_mirror.mark_as_failed!(failure_message)
else
remote_mirror.update_finish!
end
end
def failure_status(lfs_status, response, remote_mirror)
message = ''
failed = false
lfs_sync_failed = false
if lfs_status&.dig(:status) == :error
lfs_sync_failed = true
message += "Error synchronizing LFS files:"
message += "\n\n#{lfs_status[:message]}\n\n"
2022-07-16 23:28:13 +05:30
failed = Feature.enabled?(:remote_mirror_fail_on_lfs, project)
2022-03-02 08:16:31 +05:30
end
2018-10-15 14:42:47 +05:30
2020-05-24 23:13:21 +05:30
if response.divergent_refs.any?
2022-03-02 08:16:31 +05:30
message += "Some refs have diverged and have not been updated on the remote:"
2020-05-24 23:13:21 +05:30
message += "\n\n#{response.divergent_refs.join("\n")}"
2022-03-02 08:16:31 +05:30
failed = true
end
2019-10-12 21:52:04 +05:30
2022-03-02 08:16:31 +05:30
if message.present?
2023-06-20 00:43:36 +05:30
Gitlab::AppJsonLogger.info(
message: "Error synching remote mirror",
project_id: project.id,
project_path: project.full_path,
remote_mirror_id: remote_mirror.id,
lfs_sync_failed: lfs_sync_failed,
divergent_ref_list: response.divergent_refs
)
2020-05-24 23:13:21 +05:30
end
2022-03-02 08:16:31 +05:30
[failed, message]
2019-10-12 21:52:04 +05:30
end
2020-11-24 15:15:51 +05:30
def send_lfs_objects!(remote_mirror)
return unless project.lfs_enabled?
# TODO: Support LFS sync over SSH
# https://gitlab.com/gitlab-org/gitlab/-/issues/249587
2021-09-30 23:02:18 +05:30
return unless remote_mirror.url =~ %r{\Ahttps?://}i
2020-11-24 15:15:51 +05:30
return unless remote_mirror.password_auth?
Lfs::PushService.new(
project,
current_user,
url: remote_mirror.bare_url,
credentials: remote_mirror.credentials
).execute
end
2021-04-29 21:17:54 +05:30
def hard_retry_or_fail(mirror, message, tries)
2019-10-12 21:52:04 +05:30
if tries < MAX_TRIES
2021-04-29 21:17:54 +05:30
mirror.hard_retry!(message)
2018-10-15 14:42:47 +05:30
else
2019-10-12 21:52:04 +05:30
# It's not likely we'll be able to recover from this ourselves, so we'll
# notify the users of the problem, and don't trigger any sidekiq retries
# Instead, we'll wait for the next change to try the push again, or until
# a user manually retries.
2021-04-29 21:17:54 +05:30
mirror.hard_fail!(message)
2018-10-15 14:42:47 +05:30
end
end
end
end