Commit a8659bb4 authored by Pavel Shutsin's avatar Pavel Shutsin

Merge branch '321611_remove_protected_tags' into 'master'

Do not mirror protected tags restricted for a creation

See merge request gitlab-org/gitlab!80388
parents a5835ae4 e72300fc
---
name: verify_protected_tags_for_pull_mirror
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/80388
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/352494
milestone: '14.9'
type: development
group: group::source code
default_enabled: false
...@@ -105,6 +105,8 @@ module Projects ...@@ -105,6 +105,8 @@ module Projects
tags = repository_tags_with_target tags = repository_tags_with_target
tags_to_remove = []
tags.each do |tag| tags.each do |tag|
old_tag = old_tags[tag.name] old_tag = old_tags[tag.name]
tag_target = tag.dereferenced_target.sha tag_target = tag.dereferenced_target.sha
...@@ -112,21 +114,40 @@ module Projects ...@@ -112,21 +114,40 @@ module Projects
next if old_tag_target == tag_target next if old_tag_target == tag_target
Git::TagPushService.new( if Feature.enabled?(:verify_protected_tags_for_pull_mirror, project, default_enabled: :yaml) && !can_create_tag?(tag)
project, tags_to_remove << tag
current_user, next
change: { end
oldrev: old_tag_target,
newrev: tag_target, change = { oldrev: old_tag_target, newrev: tag_target, ref: tag_reference(tag) }
ref: "#{Gitlab::Git::TAG_REF_PREFIX}#{tag.name}"
}, Git::TagPushService.new(project, current_user, change: change, mirror_update: true).execute
mirror_update: true end
).execute
if tags_to_remove.present?
refs = tags_to_remove.map { |tag| tag_reference(tag) }
project.repository.delete_refs(*refs)
project.repository.expire_tags_cache
# Only take 10 tags to keep the error message short
not_allowed_tags = tags_to_remove.first(10).map { |tag| "'#{tag.name}'" }
not_allowed_tags << 'and others' if tags_to_remove.count > 10
raise UpdateError, "You are not allowed to create tags: #{not_allowed_tags.join(', ')} as they are protected."
end end
fetch_result fetch_result
end end
def can_create_tag?(tag)
::Gitlab::UserAccess.new(current_user, container: project).can_create_tag?(tag.name)
end
def tag_reference(tag)
"#{Gitlab::Git::TAG_REF_PREFIX}#{tag.name}"
end
def update_lfs_objects def update_lfs_objects
result = Projects::LfsPointers::LfsImportService.new(project).execute result = Projects::LfsPointers::LfsImportService.new(project).execute
......
...@@ -98,13 +98,13 @@ RSpec.describe Projects::UpdateMirrorService do ...@@ -98,13 +98,13 @@ RSpec.describe Projects::UpdateMirrorService do
end end
end end
context "updating tags" do context 'updating tags', :aggregate_failures do
it "creates new tags, expiring cache if there are tag changes" do it 'creates new tags, expiring cache if there are tag changes' do
stub_fetch_mirror(project) stub_fetch_mirror(project)
expect(project.repository).to receive(:expire_tags_cache).and_call_original expect(project.repository).to receive(:expire_tags_cache).and_call_original
service.execute expect(service.execute).to eq(status: :success)
expect(project.repository.tag_names).to include('new-tag') expect(project.repository.tag_names).to include('new-tag')
end end
...@@ -114,17 +114,69 @@ RSpec.describe Projects::UpdateMirrorService do ...@@ -114,17 +114,69 @@ RSpec.describe Projects::UpdateMirrorService do
expect(project.repository).not_to receive(:expire_tags_cache) expect(project.repository).not_to receive(:expire_tags_cache)
service.execute expect(service.execute).to eq(status: :success)
end end
it "only invokes Git::TagPushService for tags pointing to commits" do it 'only invokes Git::TagPushService for tags pointing to commits' do
stub_fetch_mirror(project) stub_fetch_mirror(project)
allow(Git::TagPushService).to receive(:new).and_call_original
expect(Git::TagPushService).to receive(:new) expect(Git::TagPushService).to receive(:new)
.with(project, project.first_owner, change: hash_including(ref: 'refs/tags/new-tag'), mirror_update: true) .with(project, project.first_owner, change: hash_including(ref: 'refs/tags/new-tag'), mirror_update: true)
.and_return(double(execute: true)) .and_return(double(execute: true))
service.execute expect(service.execute).to eq(status: :success)
end
describe 'Protected tags mirroring' do
context 'when user has permissions to create a protected tag' do
let!(:protected_tag) { create(:protected_tag, project: project, name: 'protected-tag') }
it 'creates the protected tag' do
stub_fetch_mirror(project)
expect(project.repository).to receive(:expire_tags_cache).and_call_original
expect(Git::TagPushService).to receive(:new).and_call_original.twice
expect(service.execute).to eq(status: :success)
expect(project.repository.tag_names).to include('new-tag', 'protected-tag')
end
end
context 'when user cannot create a protected tag' do
let!(:protected_tag) { create(:protected_tag, :no_one_can_create, project: project, name: 'protected-tag') }
it 'creates only tags that user can create' do
stub_fetch_mirror(project)
expect(Git::TagPushService).to receive(:new).and_call_original.once
expect(service.execute).to eq(
message: "You are not allowed to create tags: 'protected-tag' as they are protected.",
status: :error
)
expect(project.repository.tag_names).not_to include('protected-tag')
expect(project.repository.tag_names).to include('new-tag')
end
context 'when feature flag is disabled' do
before do
stub_feature_flags(verify_protected_tags_for_pull_mirror: false)
end
it 'creates the protected tag' do
stub_fetch_mirror(project)
expect(project.repository).to receive(:expire_tags_cache).and_call_original
expect(Git::TagPushService).to receive(:new).and_call_original.twice
expect(service.execute).to eq(status: :success)
expect(project.repository.tag_names).to include('new-tag', 'protected-tag')
end
end
end
end end
end end
...@@ -464,6 +516,9 @@ RSpec.describe Projects::UpdateMirrorService do ...@@ -464,6 +516,9 @@ RSpec.describe Projects::UpdateMirrorService do
# New tag # New tag
rugged.references.create('refs/tags/new-tag', masterrev) rugged.references.create('refs/tags/new-tag', masterrev)
# Protected tag
rugged.references.create('refs/tags/protected-tag', masterrev)
# New tag that point to a blob # New tag that point to a blob
rugged.references.create('refs/tags/new-tag-on-blob', 'c74175afd117781cbc983664339a0f599b5bb34e') rugged.references.create('refs/tags/new-tag-on-blob', 'c74175afd117781cbc983664339a0f599b5bb34e')
......
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