Commit 235a261d authored by Gabriel Mazetto's avatar Gabriel Mazetto

Merge branch 'pks-gitaly-fetch-remote-params' into 'master'

Convert users of `FetchRemote` to use `RemoteParams` [RUN ALL RSPEC] [RUN AS-IF-FOSS]

See merge request gitlab-org/gitlab!57118
parents 6faa1fe1 05fa1356
...@@ -938,6 +938,8 @@ class Repository ...@@ -938,6 +938,8 @@ class Repository
end end
def fetch_as_mirror(url, forced: false, refmap: :all_refs, remote_name: nil, prune: true) def fetch_as_mirror(url, forced: false, refmap: :all_refs, remote_name: nil, prune: true)
return fetch_remote(remote_name, url: url, refmap: refmap, forced: forced, prune: prune) if Feature.enabled?(:fetch_remote_params, project, default_enabled: :yaml)
unless remote_name unless remote_name
remote_name = "tmp-#{SecureRandom.hex}" remote_name = "tmp-#{SecureRandom.hex}"
tmp_remote_name = true tmp_remote_name = true
......
---
name: fetch_remote_params
introduced_by_url:
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/325528
milestone: '13.12'
type: development
group: group::gitaly
default_enabled: false
...@@ -797,15 +797,19 @@ module Gitlab ...@@ -797,15 +797,19 @@ module Gitlab
# Fetch remote for repository # Fetch remote for repository
# #
# remote - remote name # remote - remote name
# url - URL of the remote to fetch. `remote` is not used in this case.
# refmap - if url is given, determines which references should get fetched where
# ssh_auth - SSH known_hosts data and a private key to use for public-key authentication # ssh_auth - SSH known_hosts data and a private key to use for public-key authentication
# forced - should we use --force flag? # forced - should we use --force flag?
# no_tags - should we use --no-tags flag? # no_tags - should we use --no-tags flag?
# prune - should we use --prune flag? # prune - should we use --prune flag?
# check_tags_changed - should we ask gitaly to calculate whether any tags changed? # check_tags_changed - should we ask gitaly to calculate whether any tags changed?
def fetch_remote(remote, ssh_auth: nil, forced: false, no_tags: false, prune: true, check_tags_changed: false) def fetch_remote(remote, url: nil, refmap: nil, ssh_auth: nil, forced: false, no_tags: false, prune: true, check_tags_changed: false)
wrapped_gitaly_errors do wrapped_gitaly_errors do
gitaly_repository_client.fetch_remote( gitaly_repository_client.fetch_remote(
remote, remote,
url: url,
refmap: refmap,
ssh_auth: ssh_auth, ssh_auth: ssh_auth,
forced: forced, forced: forced,
no_tags: no_tags, no_tags: no_tags,
......
...@@ -70,13 +70,21 @@ module Gitlab ...@@ -70,13 +70,21 @@ module Gitlab
end.join end.join
end end
def fetch_remote(remote, ssh_auth:, forced:, no_tags:, timeout:, prune: true, check_tags_changed: false) # rubocop: disable Metrics/ParameterLists
# The `remote` parameter is going away soonish anyway, at which point the
# Rubocop warning can be enabled again.
def fetch_remote(remote, url:, refmap:, ssh_auth:, forced:, no_tags:, timeout:, prune: true, check_tags_changed: false)
request = Gitaly::FetchRemoteRequest.new( request = Gitaly::FetchRemoteRequest.new(
repository: @gitaly_repo, remote: remote, force: forced, repository: @gitaly_repo, remote: remote, force: forced,
no_tags: no_tags, timeout: timeout, no_prune: !prune, no_tags: no_tags, timeout: timeout, no_prune: !prune,
check_tags_changed: check_tags_changed check_tags_changed: check_tags_changed
) )
if url
request.remote_params = Gitaly::Remote.new(url: url,
mirror_refmaps: Array.wrap(refmap).map(&:to_s))
end
if ssh_auth&.ssh_mirror_url? if ssh_auth&.ssh_mirror_url?
if ssh_auth.ssh_key_auth? && ssh_auth.ssh_private_key.present? if ssh_auth.ssh_key_auth? && ssh_auth.ssh_private_key.present?
request.ssh_key = ssh_auth.ssh_private_key request.ssh_key = ssh_auth.ssh_private_key
...@@ -89,6 +97,7 @@ module Gitlab ...@@ -89,6 +97,7 @@ module Gitlab
GitalyClient.call(@storage, :repository_service, :fetch_remote, request, timeout: GitalyClient.long_timeout) GitalyClient.call(@storage, :repository_service, :fetch_remote, request, timeout: GitalyClient.long_timeout)
end end
# rubocop: enable Metrics/ParameterLists
def create_repository def create_repository
request = Gitaly::CreateRepositoryRequest.new(repository: @gitaly_repo) request = Gitaly::CreateRepositoryRequest.new(repository: @gitaly_repo)
......
...@@ -36,7 +36,11 @@ module Gitlab ...@@ -36,7 +36,11 @@ module Gitlab
# updating the timestamp. # updating the timestamp.
project.update_column(:last_repository_updated_at, Time.zone.now) project.update_column(:last_repository_updated_at, Time.zone.now)
project.repository.fetch_remote('github', forced: false) if Feature.enabled?(:fetch_remote_params, project, default_enabled: :yaml)
project.repository.fetch_remote('github', url: project.import_url, refmap: Gitlab::GithubImport.refmap, forced: false)
else
project.repository.fetch_remote('github', forced: false)
end
pname = project.path_with_namespace pname = project.path_with_namespace
......
...@@ -521,7 +521,9 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do ...@@ -521,7 +521,9 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do
no_tags: true, no_tags: true,
timeout: described_class::GITLAB_PROJECTS_TIMEOUT, timeout: described_class::GITLAB_PROJECTS_TIMEOUT,
prune: false, prune: false,
check_tags_changed: false check_tags_changed: false,
url: nil,
refmap: nil
} }
expect(repository.gitaly_repository_client).to receive(:fetch_remote).with('remote-name', expected_opts) expect(repository.gitaly_repository_client).to receive(:fetch_remote).with('remote-name', expected_opts)
......
...@@ -122,67 +122,89 @@ RSpec.describe Gitlab::GitalyClient::RepositoryService do ...@@ -122,67 +122,89 @@ RSpec.describe Gitlab::GitalyClient::RepositoryService do
end end
describe '#fetch_remote' do describe '#fetch_remote' do
let(:remote) { 'remote-name' } shared_examples 'a fetch' do
it 'sends a fetch_remote_request message' do
it 'sends a fetch_remote_request message' do expected_remote_params = Gitaly::Remote.new(
expected_request = gitaly_request_with_params( url: url, http_authorization_header: "", mirror_refmaps: [])
remote: remote,
ssh_key: '', expected_request = gitaly_request_with_params(
known_hosts: '', remote: remote,
force: false, remote_params: url ? expected_remote_params : nil,
no_tags: false, ssh_key: '',
no_prune: false, known_hosts: '',
check_tags_changed: false force: false,
) no_tags: false,
no_prune: false,
check_tags_changed: false
)
expect_any_instance_of(Gitaly::RepositoryService::Stub)
.to receive(:fetch_remote)
.with(expected_request, kind_of(Hash))
.and_return(double(value: true))
client.fetch_remote(remote, url: url, refmap: nil, ssh_auth: nil, forced: false, no_tags: false, timeout: 1, check_tags_changed: false)
end
expect_any_instance_of(Gitaly::RepositoryService::Stub) context 'SSH auth' do
.to receive(:fetch_remote) where(:ssh_mirror_url, :ssh_key_auth, :ssh_private_key, :ssh_known_hosts, :expected_params) do
.with(expected_request, kind_of(Hash)) false | false | 'key' | 'known_hosts' | {}
.and_return(double(value: true)) false | true | 'key' | 'known_hosts' | {}
true | false | 'key' | 'known_hosts' | { known_hosts: 'known_hosts' }
true | true | 'key' | 'known_hosts' | { ssh_key: 'key', known_hosts: 'known_hosts' }
true | true | 'key' | nil | { ssh_key: 'key' }
true | true | nil | 'known_hosts' | { known_hosts: 'known_hosts' }
true | true | nil | nil | {}
true | true | '' | '' | {}
end
client.fetch_remote(remote, ssh_auth: nil, forced: false, no_tags: false, timeout: 1, check_tags_changed: false) with_them do
let(:ssh_auth) do
double(
:ssh_auth,
ssh_mirror_url?: ssh_mirror_url,
ssh_key_auth?: ssh_key_auth,
ssh_private_key: ssh_private_key,
ssh_known_hosts: ssh_known_hosts
)
end
it do
expected_remote_params = Gitaly::Remote.new(
url: url, http_authorization_header: "", mirror_refmaps: [])
expected_request = gitaly_request_with_params({
remote: remote,
remote_params: url ? expected_remote_params : nil,
ssh_key: '',
known_hosts: '',
force: false,
no_tags: false,
no_prune: false
}.update(expected_params))
expect_any_instance_of(Gitaly::RepositoryService::Stub)
.to receive(:fetch_remote)
.with(expected_request, kind_of(Hash))
.and_return(double(value: true))
client.fetch_remote(remote, url: url, refmap: nil, ssh_auth: ssh_auth, forced: false, no_tags: false, timeout: 1)
end
end
end
end end
context 'SSH auth' do context 'with remote' do
where(:ssh_mirror_url, :ssh_key_auth, :ssh_private_key, :ssh_known_hosts, :expected_params) do it_behaves_like 'a fetch' do
false | false | 'key' | 'known_hosts' | {} let(:remote) { 'remote-name' }
false | true | 'key' | 'known_hosts' | {} let(:url) { nil }
true | false | 'key' | 'known_hosts' | { known_hosts: 'known_hosts' }
true | true | 'key' | 'known_hosts' | { ssh_key: 'key', known_hosts: 'known_hosts' }
true | true | 'key' | nil | { ssh_key: 'key' }
true | true | nil | 'known_hosts' | { known_hosts: 'known_hosts' }
true | true | nil | nil | {}
true | true | '' | '' | {}
end end
end
with_them do context 'with URL' do
let(:ssh_auth) do it_behaves_like 'a fetch' do
double( let(:remote) { "" }
:ssh_auth, let(:url) { 'https://example.com/git/repo.git' }
ssh_mirror_url?: ssh_mirror_url,
ssh_key_auth?: ssh_key_auth,
ssh_private_key: ssh_private_key,
ssh_known_hosts: ssh_known_hosts
)
end
it do
expected_request = gitaly_request_with_params({
remote: remote,
ssh_key: '',
known_hosts: '',
force: false,
no_tags: false,
no_prune: false
}.update(expected_params))
expect_any_instance_of(Gitaly::RepositoryService::Stub)
.to receive(:fetch_remote)
.with(expected_request, kind_of(Hash))
.and_return(double(value: true))
client.fetch_remote(remote, ssh_auth: ssh_auth, forced: false, no_tags: false, timeout: 1)
end
end end
end end
end end
......
...@@ -3,7 +3,8 @@ ...@@ -3,7 +3,8 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe Gitlab::GithubImport::Importer::PullRequestsImporter do RSpec.describe Gitlab::GithubImport::Importer::PullRequestsImporter do
let(:project) { create(:project, import_source: 'foo/bar') } let(:url) { 'https://github.com/foo/bar.git' }
let(:project) { create(:project, import_source: 'foo/bar', import_url: url) }
let(:client) { double(:client) } let(:client) { double(:client) }
let(:pull_request) do let(:pull_request) do
...@@ -147,14 +148,10 @@ RSpec.describe Gitlab::GithubImport::Importer::PullRequestsImporter do ...@@ -147,14 +148,10 @@ RSpec.describe Gitlab::GithubImport::Importer::PullRequestsImporter do
end end
end end
describe '#update_repository' do shared_examples '#update_repository' do
it 'updates the repository' do it 'updates the repository' do
importer = described_class.new(project, client) importer = described_class.new(project, client)
expect(project.repository)
.to receive(:fetch_remote)
.with('github', forced: false)
expect_next_instance_of(Gitlab::Import::Logger) do |logger| expect_next_instance_of(Gitlab::Import::Logger) do |logger|
expect(logger) expect(logger)
.to receive(:info) .to receive(:info)
...@@ -173,6 +170,28 @@ RSpec.describe Gitlab::GithubImport::Importer::PullRequestsImporter do ...@@ -173,6 +170,28 @@ RSpec.describe Gitlab::GithubImport::Importer::PullRequestsImporter do
end end
end end
describe '#update_repository with :fetch_remote_params enabled' do
before do
stub_feature_flags(fetch_remote_params: true)
expect(project.repository)
.to receive(:fetch_remote)
.with('github', forced: false, url: url, refmap: Gitlab::GithubImport.refmap)
end
it_behaves_like '#update_repository'
end
describe '#update_repository with :fetch_remote_params disabled' do
before do
stub_feature_flags(fetch_remote_params: false)
expect(project.repository)
.to receive(:fetch_remote)
.with('github', forced: false)
end
it_behaves_like '#update_repository'
end
describe '#update_repository?' do describe '#update_repository?' do
let(:importer) { described_class.new(project, client) } let(:importer) { described_class.new(project, client) }
......
...@@ -1123,6 +1123,70 @@ RSpec.describe Repository do ...@@ -1123,6 +1123,70 @@ RSpec.describe Repository do
end end
end end
describe '#fetch_as_mirror' do
let(:url) { "http://example.com" }
context 'when :fetch_remote_params is enabled' do
let(:remote_name) { "remote-name" }
before do
stub_feature_flags(fetch_remote_params: true)
end
it 'fetches the URL without creating a remote' do
expect(repository).not_to receive(:add_remote)
expect(repository)
.to receive(:fetch_remote)
.with(remote_name, url: url, forced: false, prune: true, refmap: :all_refs)
.and_return(nil)
repository.fetch_as_mirror(url, remote_name: remote_name)
end
end
context 'when :fetch_remote_params is disabled' do
before do
stub_feature_flags(fetch_remote_params: false)
end
shared_examples 'a fetch' do
it 'adds and fetches a remote' do
expect(repository)
.to receive(:add_remote)
.with(expected_remote, url, mirror_refmap: :all_refs)
.and_return(nil)
expect(repository)
.to receive(:fetch_remote)
.with(expected_remote, forced: false, prune: true)
.and_return(nil)
repository.fetch_as_mirror(url, remote_name: remote_name)
end
end
context 'with temporary remote' do
let(:remote_name) { nil }
let(:expected_remote_suffix) { "123456" }
let(:expected_remote) { "tmp-#{expected_remote_suffix}" }
before do
expect(repository)
.to receive(:async_remove_remote).with(expected_remote).and_return(nil)
allow(SecureRandom).to receive(:hex).and_return(expected_remote_suffix)
end
it_behaves_like 'a fetch'
end
context 'with remote name' do
let(:remote_name) { "foo" }
let(:expected_remote) { "foo" }
it_behaves_like 'a fetch'
end
end
end
describe '#fetch_ref' do describe '#fetch_ref' do
let(:broken_repository) { create(:project, :broken_storage).repository } let(:broken_repository) { create(:project, :broken_storage).repository }
......
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