Commit 885ae6e9 authored by Patrick Steinhardt's avatar Patrick Steinhardt

checks: Convert PushRuleChecks to allow for batching

The PushRuleChecks are implemented as BaseSingleChecker, where they
always operate on a single change only. This is inefficient for a subset
of push rules, most namely for the file size rules: we could load all
blobs via a single RPC call and inspect their sizes instead of doing an
RPC call per change.

Prepare for this change by converting the PushRules to be implemented as
BaseBulkChecker. For now, nothing really changes: we just deconstruct
the bulk changes into SingleChangeAccesses and then pass those into our
subrules. But with this change in place, we can easily convert subsets
of our push rules to use batching.
parent 1f3f6579
...@@ -3,12 +3,12 @@ ...@@ -3,12 +3,12 @@
module EE module EE
module Gitlab module Gitlab
module Checks module Checks
module SingleChangeAccess module ChangesAccess
extend ActiveSupport::Concern extend ActiveSupport::Concern
extend ::Gitlab::Utils::Override extend ::Gitlab::Utils::Override
override :ref_level_checks override :bulk_access_checks!
def ref_level_checks def bulk_access_checks!
super super
PushRuleCheck.new(self).validate! PushRuleCheck.new(self).validate!
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
module EE module EE
module Gitlab module Gitlab
module Checks module Checks
class PushRuleCheck < ::Gitlab::Checks::BaseSingleChecker class PushRuleCheck < ::Gitlab::Checks::BaseBulkChecker
def validate! def validate!
return unless push_rule return unless push_rule
...@@ -19,17 +19,25 @@ module EE ...@@ -19,17 +19,25 @@ module EE
# @return [Nil] returns nil unless an error is raised # @return [Nil] returns nil unless an error is raised
# @raise [Gitlab::GitAccess::ForbiddenError] if check fails # @raise [Gitlab::GitAccess::ForbiddenError] if check fails
def check_tag_or_branch! def check_tag_or_branch!
if tag_name changes_access.single_change_accesses.each do |single_change_access|
PushRules::TagCheck.new(change_access).validate! if single_change_access.tag_name
else PushRules::TagCheck.new(single_change_access).validate!
PushRules::BranchCheck.new(change_access).validate! else
PushRules::BranchCheck.new(single_change_access).validate!
end
end end
nil
end end
# @return [Nil] returns nil unless an error is raised # @return [Nil] returns nil unless an error is raised
# @raise [Gitlab::GitAccess::ForbiddenError] if check fails # @raise [Gitlab::GitAccess::ForbiddenError] if check fails
def check_file_size! def check_file_size!
PushRules::FileSizeCheck.new(change_access).validate! changes_access.single_change_accesses.each do |single_change_access|
PushRules::FileSizeCheck.new(single_change_access).validate!
end
nil
end end
# Run the checks one after the other. # Run the checks one after the other.
......
...@@ -3,9 +3,16 @@ ...@@ -3,9 +3,16 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe EE::Gitlab::Checks::PushRuleCheck do RSpec.describe EE::Gitlab::Checks::PushRuleCheck do
include_context 'push rules checks context' include_context 'changes access checks context'
let(:push_rule) { create(:push_rule, :commit_message) } let(:push_rule) { create(:push_rule, :commit_message) }
let(:project) { create(:project, :public, :repository, push_rule: push_rule) }
before do
allow(project.repository).to receive(:new_commits).and_return(
project.repository.commits_between('be93687618e4b132087f430a4d8fc3a609c9b77c', '54fcc214b94e78d7a41a9a8fe6d87a5e59500e51')
)
end
shared_examples "push checks" do shared_examples "push checks" do
before do before do
...@@ -28,8 +35,11 @@ RSpec.describe EE::Gitlab::Checks::PushRuleCheck do ...@@ -28,8 +35,11 @@ RSpec.describe EE::Gitlab::Checks::PushRuleCheck do
end end
context 'when tag name exists' do context 'when tag name exists' do
before do let(:changes) do
allow(change_access).to receive(:tag_name).and_return(true) [
# Update of a tag.
{ oldrev: oldrev, newrev: newrev, ref: 'refs/tags/name' }
]
end end
it 'validates tags push rules' do it 'validates tags push rules' do
...@@ -43,8 +53,11 @@ RSpec.describe EE::Gitlab::Checks::PushRuleCheck do ...@@ -43,8 +53,11 @@ RSpec.describe EE::Gitlab::Checks::PushRuleCheck do
end end
context 'when tag name does not exists' do context 'when tag name does not exists' do
before do let(:changes) do
allow(change_access).to receive(:tag_name).and_return(false) [
# Update of a branch.
{ oldrev: oldrev, newrev: newrev, ref: 'refs/heads/name' }
]
end end
it 'validates branches push rules' do it 'validates branches push rules' do
...@@ -56,6 +69,24 @@ RSpec.describe EE::Gitlab::Checks::PushRuleCheck do ...@@ -56,6 +69,24 @@ RSpec.describe EE::Gitlab::Checks::PushRuleCheck do
subject.validate! subject.validate!
end end
end end
context 'when tag and branch exist' do
let(:changes) do
[
{ oldrev: oldrev, newrev: newrev, ref: 'refs/heads/name' },
{ oldrev: oldrev, newrev: newrev, ref: 'refs/tags/name' }
]
end
it 'validates tag and branch push rules' do
expect_any_instance_of(EE::Gitlab::Checks::PushRules::TagCheck)
.to receive(:validate!)
expect_any_instance_of(EE::Gitlab::Checks::PushRules::BranchCheck)
.to receive(:validate!)
subject.validate!
end
end
end end
describe '#validate!' do describe '#validate!' do
......
...@@ -2,13 +2,28 @@ ...@@ -2,13 +2,28 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe Gitlab::Checks::SingleChangeAccess do RSpec.describe Gitlab::Checks::ChangesAccess do
describe '#validate!' do describe '#validate!' do
include_context 'push rules checks context' include_context 'push rules checks context'
let(:push_rule) { create(:push_rule, deny_delete_tag: true) } let(:push_rule) { create(:push_rule, deny_delete_tag: true) }
let(:changes) do
[
{ oldrev: oldrev, newrev: newrev, ref: ref }
]
end
let(:changes_access) do
Gitlab::Checks::ChangesAccess.new(
changes,
project: project,
user_access: user_access,
protocol: protocol,
logger: logger
)
end
subject { change_access } subject { changes_access }
it_behaves_like 'check ignored when push rule unlicensed' it_behaves_like 'check ignored when push rule unlicensed'
......
...@@ -112,3 +112,5 @@ module Gitlab ...@@ -112,3 +112,5 @@ module Gitlab
end end
end end
end end
Gitlab::Checks::ChangesAccess.prepend_mod_with('Gitlab::Checks::ChangesAccess')
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