Commit 37f1f209 authored by Stan Hu's avatar Stan Hu

Merge branch 'pks-set-full-path' into 'master'

Convert setting the full path via SetFullPath RPC

See merge request gitlab-org/gitlab!66929
parents 114b87df 3c8a1ef8
818f3d85a2c8e6596376f1d2276aa22660203a6c d513d220b183d83ae7219ec52f49aa3b4f7fc551
...@@ -472,7 +472,7 @@ end ...@@ -472,7 +472,7 @@ end
gem 'spamcheck', '~> 0.1.0' gem 'spamcheck', '~> 0.1.0'
# Gitaly GRPC protocol definitions # Gitaly GRPC protocol definitions
gem 'gitaly', '~> 14.1.0.pre.rc4' gem 'gitaly', '~> 14.2.0.pre.rc2'
# KAS GRPC protocol definitions # KAS GRPC protocol definitions
gem 'kas-grpc', '~> 0.0.2' gem 'kas-grpc', '~> 0.0.2'
......
...@@ -452,7 +452,7 @@ GEM ...@@ -452,7 +452,7 @@ GEM
rails (>= 3.2.0) rails (>= 3.2.0)
git (1.7.0) git (1.7.0)
rchardet (~> 1.8) rchardet (~> 1.8)
gitaly (14.1.0.pre.rc4) gitaly (14.2.0.pre.rc2)
grpc (~> 1.0) grpc (~> 1.0)
github-markup (1.7.0) github-markup (1.7.0)
gitlab (4.16.1) gitlab (4.16.1)
...@@ -1464,7 +1464,7 @@ DEPENDENCIES ...@@ -1464,7 +1464,7 @@ DEPENDENCIES
gettext (~> 3.3) gettext (~> 3.3)
gettext_i18n_rails (~> 1.8.0) gettext_i18n_rails (~> 1.8.0)
gettext_i18n_rails_js (~> 1.3) gettext_i18n_rails_js (~> 1.3)
gitaly (~> 14.1.0.pre.rc4) gitaly (~> 14.2.0.pre.rc2)
github-markup (~> 1.7.0) github-markup (~> 1.7.0)
gitlab-chronic (~> 0.10.5) gitlab-chronic (~> 0.10.5)
gitlab-dangerfiles (~> 2.3.0) gitlab-dangerfiles (~> 2.3.0)
......
...@@ -528,7 +528,7 @@ class Namespace < ApplicationRecord ...@@ -528,7 +528,7 @@ class Namespace < ApplicationRecord
def write_projects_repository_config def write_projects_repository_config
all_projects.find_each do |project| all_projects.find_each do |project|
project.write_repository_config project.set_full_path
project.track_project_repository project.track_project_repository
end end
end end
......
...@@ -1889,11 +1889,11 @@ class Project < ApplicationRecord ...@@ -1889,11 +1889,11 @@ class Project < ApplicationRecord
.update_all(deployed: deployment.present?, pages_deployment_id: deployment&.id) .update_all(deployed: deployment.present?, pages_deployment_id: deployment&.id)
end end
def write_repository_config(gl_full_path: full_path) def set_full_path(gl_full_path: full_path)
# We'd need to keep track of project full path otherwise directory tree # We'd need to keep track of project full path otherwise directory tree
# created with hashed storage enabled cannot be usefully imported using # created with hashed storage enabled cannot be usefully imported using
# the import rake task. # the import rake task.
repository.raw_repository.write_config(full_path: gl_full_path) repository.raw_repository.set_full_path(full_path: gl_full_path)
rescue Gitlab::Git::Repository::NoRepository => e rescue Gitlab::Git::Repository::NoRepository => e
Gitlab::AppLogger.error("Error writing to .git/config for project #{full_path} (#{id}): #{e.message}.") Gitlab::AppLogger.error("Error writing to .git/config for project #{full_path} (#{id}): #{e.message}.")
nil nil
...@@ -1917,7 +1917,7 @@ class Project < ApplicationRecord ...@@ -1917,7 +1917,7 @@ class Project < ApplicationRecord
after_create_default_branch after_create_default_branch
join_pool_repository join_pool_repository
refresh_markdown_cache! refresh_markdown_cache!
write_repository_config set_full_path
end end
def update_project_counter_caches def update_project_counter_caches
......
...@@ -83,7 +83,7 @@ module Projects ...@@ -83,7 +83,7 @@ module Projects
def update_repository_configuration def update_repository_configuration
project.reload_repository! project.reload_repository!
project.write_repository_config project.set_full_path
project.track_project_repository project.track_project_repository
end end
......
...@@ -92,7 +92,7 @@ module Projects ...@@ -92,7 +92,7 @@ module Projects
# Skip writing the config for project imports/forks because it # Skip writing the config for project imports/forks because it
# will always fail since the Git directory doesn't exist until # will always fail since the Git directory doesn't exist until
# a background job creates it (see Project#add_import_job). # a background job creates it (see Project#add_import_job).
@project.write_repository_config unless @project.import? @project.set_full_path unless @project.import?
unless @project.gitlab_project_import? unless @project.gitlab_project_import?
@project.create_wiki unless skip_wiki? @project.create_wiki unless skip_wiki?
......
...@@ -14,7 +14,7 @@ module Projects ...@@ -14,7 +14,7 @@ module Projects
result = move_repositories result = move_repositories
if result if result
project.write_repository_config project.set_full_path
project.track_project_repository project.track_project_repository
else else
rollback_folder_move rollback_folder_move
......
...@@ -14,7 +14,7 @@ module Projects ...@@ -14,7 +14,7 @@ module Projects
result = move_repositories result = move_repositories
if result if result
project.write_repository_config project.set_full_path
project.track_project_repository project.track_project_repository
else else
rollback_folder_move rollback_folder_move
......
...@@ -135,7 +135,7 @@ module Projects ...@@ -135,7 +135,7 @@ module Projects
end end
def update_repository_configuration(full_path) def update_repository_configuration(full_path)
project.write_repository_config(gl_full_path: full_path) project.set_full_path(gl_full_path: full_path)
project.track_project_repository project.track_project_repository
end end
......
---
name: set_full_path
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/66929
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/337002
milestone: '14.2'
type: development
group: group::gitaly
default_enabled: false
...@@ -142,7 +142,7 @@ to do so. In a Rails console session, run the following to migrate a project: ...@@ -142,7 +142,7 @@ to do so. In a Rails console session, run the following to migrate a project:
```ruby ```ruby
project = Project.find_by_full_path('gitlab-org/gitlab') project = Project.find_by_full_path('gitlab-org/gitlab')
project.write_repository_config project.set_full_path
``` ```
In a Rails console session, run the following to migrate all of a namespace's In a Rails console session, run the following to migrate all of a namespace's
......
...@@ -73,7 +73,7 @@ module Gitlab ...@@ -73,7 +73,7 @@ module Gitlab
if project.persisted? && mv_repositories(project) if project.persisted? && mv_repositories(project)
log " * Created #{project.name} (#{project_full_path})".color(:green) log " * Created #{project.name} (#{project_full_path})".color(:green)
project.write_repository_config project.set_full_path
ProjectCacheWorker.perform_async(project.id) ProjectCacheWorker.perform_async(project.id)
else else
......
...@@ -905,13 +905,17 @@ module Gitlab ...@@ -905,13 +905,17 @@ module Gitlab
end end
# rubocop:enable Metrics/ParameterLists # rubocop:enable Metrics/ParameterLists
def write_config(full_path:) def set_full_path(full_path:)
return unless full_path.present? return unless full_path.present?
# This guard avoids Gitaly log/error spam # This guard avoids Gitaly log/error spam
raise NoRepository, 'repository does not exist' unless exists? raise NoRepository, 'repository does not exist' unless exists?
set_config('gitlab.fullpath' => full_path) if Feature.enabled?(:set_full_path)
gitaly_repository_client.set_full_path(full_path)
else
set_config('gitlab.fullpath' => full_path)
end
end end
def set_config(entries) def set_config(entries)
......
...@@ -263,6 +263,21 @@ module Gitlab ...@@ -263,6 +263,21 @@ module Gitlab
GitalyClient.call(@storage, :repository_service, :write_ref, request, timeout: GitalyClient.fast_timeout) GitalyClient.call(@storage, :repository_service, :write_ref, request, timeout: GitalyClient.fast_timeout)
end end
def set_full_path(path)
GitalyClient.call(
@storage,
:repository_service,
:set_full_path,
Gitaly::SetFullPathRequest.new(
repository: @gitaly_repo,
path: path
),
timeout: GitalyClient.fast_timeout
)
nil
end
def set_config(entries) def set_config(entries)
return if entries.empty? return if entries.empty?
......
...@@ -1729,43 +1729,61 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do ...@@ -1729,43 +1729,61 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do
end end
end end
describe '#write_config' do describe '#set_full_path' do
before do shared_examples '#set_full_path' do
repository_rugged.config["gitlab.fullpath"] = repository_path before do
end repository_rugged.config["gitlab.fullpath"] = repository_path
end
context 'is given a path' do context 'is given a path' do
it 'writes it to disk' do it 'writes it to disk' do
repository.write_config(full_path: "not-the/real-path.git") repository.set_full_path(full_path: "not-the/real-path.git")
config = File.read(File.join(repository_path, "config")) config = File.read(File.join(repository_path, "config"))
expect(config).to include("[gitlab]") expect(config).to include("[gitlab]")
expect(config).to include("fullpath = not-the/real-path.git") expect(config).to include("fullpath = not-the/real-path.git")
end
end end
end
context 'it is given an empty path' do context 'it is given an empty path' do
it 'does not write it to disk' do it 'does not write it to disk' do
repository.write_config(full_path: "") repository.set_full_path(full_path: "")
config = File.read(File.join(repository_path, "config")) config = File.read(File.join(repository_path, "config"))
expect(config).to include("[gitlab]") expect(config).to include("[gitlab]")
expect(config).to include("fullpath = #{repository_path}") expect(config).to include("fullpath = #{repository_path}")
end
end
context 'repository does not exist' do
it 'raises NoRepository and does not call Gitaly WriteConfig' do
repository = Gitlab::Git::Repository.new('default', 'does/not/exist.git', '', 'group/project')
expect(repository.gitaly_repository_client).not_to receive(:set_full_path)
expect do
repository.set_full_path(full_path: 'foo/bar.git')
end.to raise_error(Gitlab::Git::Repository::NoRepository)
end
end end
end end
context 'repository does not exist' do context 'with :set_full_path enabled' do
it 'raises NoRepository and does not call Gitaly WriteConfig' do before do
repository = Gitlab::Git::Repository.new('default', 'does/not/exist.git', '', 'group/project') stub_feature_flags(set_full_path: true)
end
expect(repository.gitaly_repository_client).not_to receive(:write_config) it_behaves_like '#set_full_path'
end
expect do context 'with :set_full_path disabled' do
repository.write_config(full_path: 'foo/bar.git') before do
end.to raise_error(Gitlab::Git::Repository::NoRepository) stub_feature_flags(set_full_path: false)
end end
it_behaves_like '#set_full_path'
end end
end end
......
...@@ -333,4 +333,17 @@ RSpec.describe Gitlab::GitalyClient::RepositoryService do ...@@ -333,4 +333,17 @@ RSpec.describe Gitlab::GitalyClient::RepositoryService do
client.replicate(source_repository) client.replicate(source_repository)
end end
end end
describe '#set_full_path' do
let(:path) { 'repo/path' }
it 'sends a set_full_path message' do
expect_any_instance_of(Gitaly::RepositoryService::Stub)
.to receive(:set_full_path)
.with(gitaly_request_with_params(path: path), kind_of(Hash))
.and_return(double)
client.set_full_path(path)
end
end
end end
...@@ -5228,7 +5228,7 @@ RSpec.describe Project, factory_default: :keep do ...@@ -5228,7 +5228,7 @@ RSpec.describe Project, factory_default: :keep do
expect(InternalId).to receive(:flush_records!).with(project: project) expect(InternalId).to receive(:flush_records!).with(project: project)
expect(ProjectCacheWorker).to receive(:perform_async).with(project.id, [], [:repository_size]) expect(ProjectCacheWorker).to receive(:perform_async).with(project.id, [], [:repository_size])
expect(DetectRepositoryLanguagesWorker).to receive(:perform_async).with(project.id) expect(DetectRepositoryLanguagesWorker).to receive(:perform_async).with(project.id)
expect(project).to receive(:write_repository_config) expect(project).to receive(:set_full_path)
project.after_import project.after_import
end end
...@@ -5297,25 +5297,25 @@ RSpec.describe Project, factory_default: :keep do ...@@ -5297,25 +5297,25 @@ RSpec.describe Project, factory_default: :keep do
end end
end end
describe '#write_repository_config' do describe '#set_full_path' do
let_it_be(:project) { create(:project, :repository) } let_it_be(:project) { create(:project, :repository) }
it 'writes full path in .git/config when key is missing' do it 'writes full path in .git/config when key is missing' do
project.write_repository_config project.set_full_path
expect(rugged_config['gitlab.fullpath']).to eq project.full_path expect(rugged_config['gitlab.fullpath']).to eq project.full_path
end end
it 'updates full path in .git/config when key is present' do it 'updates full path in .git/config when key is present' do
project.write_repository_config(gl_full_path: 'old/path') project.set_full_path(gl_full_path: 'old/path')
expect { project.write_repository_config }.to change { rugged_config['gitlab.fullpath'] }.from('old/path').to(project.full_path) expect { project.set_full_path }.to change { rugged_config['gitlab.fullpath'] }.from('old/path').to(project.full_path)
end end
it 'does not raise an error with an empty repository' do it 'does not raise an error with an empty repository' do
project = create(:project_empty_repo) project = create(:project_empty_repo)
expect { project.write_repository_config }.not_to raise_error expect { project.set_full_path }.not_to raise_error
end end
end end
......
...@@ -335,7 +335,7 @@ RSpec.describe Projects::CreateService, '#execute' do ...@@ -335,7 +335,7 @@ RSpec.describe Projects::CreateService, '#execute' do
it 'does not write repository config' do it 'does not write repository config' do
expect_next_instance_of(Project) do |project| expect_next_instance_of(Project) do |project|
expect(project).not_to receive(:write_repository_config) expect(project).not_to receive(:set_full_path)
end end
imported_project imported_project
......
...@@ -96,13 +96,13 @@ RSpec.describe Projects::HashedStorage::MigrateRepositoryService do ...@@ -96,13 +96,13 @@ RSpec.describe Projects::HashedStorage::MigrateRepositoryService do
end end
it 'handles Gitlab::Git::CommandError' do it 'handles Gitlab::Git::CommandError' do
expect(project).to receive(:write_repository_config).and_raise(Gitlab::Git::CommandError) expect(project).to receive(:set_full_path).and_raise(Gitlab::Git::CommandError)
expect { service.execute }.not_to raise_exception expect { service.execute }.not_to raise_exception
end end
it 'ensures rollback when Gitlab::Git::CommandError' do it 'ensures rollback when Gitlab::Git::CommandError' do
expect(project).to receive(:write_repository_config).and_raise(Gitlab::Git::CommandError) expect(project).to receive(:set_full_path).and_raise(Gitlab::Git::CommandError)
expect(service).to receive(:rollback_folder_move).and_call_original expect(service).to receive(:rollback_folder_move).and_call_original
service.execute service.execute
......
...@@ -96,13 +96,13 @@ RSpec.describe Projects::HashedStorage::RollbackRepositoryService, :clean_gitlab ...@@ -96,13 +96,13 @@ RSpec.describe Projects::HashedStorage::RollbackRepositoryService, :clean_gitlab
end end
it 'handles Gitlab::Git::CommandError' do it 'handles Gitlab::Git::CommandError' do
expect(project).to receive(:write_repository_config).and_raise(Gitlab::Git::CommandError) expect(project).to receive(:set_full_path).and_raise(Gitlab::Git::CommandError)
expect { service.execute }.not_to raise_exception expect { service.execute }.not_to raise_exception
end end
it 'ensures rollback when Gitlab::Git::CommandError' do it 'ensures rollback when Gitlab::Git::CommandError' do
expect(project).to receive(:write_repository_config).and_raise(Gitlab::Git::CommandError) expect(project).to receive(:set_full_path).and_raise(Gitlab::Git::CommandError)
expect(service).to receive(:rollback_folder_move).and_call_original expect(service).to receive(:rollback_folder_move).and_call_original
service.execute service.execute
......
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