Extract common validations from ci services
DroneCI and TeamCity shared the same validations methods on the data received. These validations were extracted into a concern
This commit is contained in:
parent
5f1038c888
commit
a39277a4f9
4 changed files with 68 additions and 52 deletions
43
app/models/concerns/service_push_data_validations.rb
Normal file
43
app/models/concerns/service_push_data_validations.rb
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# This concern is used by registerd services such as TeamCityService and
|
||||||
|
# DroneCiService and add methods to perform validations on the received
|
||||||
|
# data.
|
||||||
|
|
||||||
|
module ServicePushDataValidations
|
||||||
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
|
def merge_request_valid?(data)
|
||||||
|
data.dig(:object_attributes, :state) == 'opened' && merge_request_unchecked?(data)
|
||||||
|
end
|
||||||
|
|
||||||
|
def push_valid?(data)
|
||||||
|
data[:total_commits_count] > 0 &&
|
||||||
|
!branch_removed?(data) &&
|
||||||
|
# prefer merge request trigger over push to avoid double builds
|
||||||
|
!opened_merge_requests?(data)
|
||||||
|
end
|
||||||
|
|
||||||
|
def tag_push_valid?(data)
|
||||||
|
data[:total_commits_count] > 0 && !branch_removed?(data)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def branch_removed?(data)
|
||||||
|
Gitlab::Git.blank_ref?(data[:after])
|
||||||
|
end
|
||||||
|
|
||||||
|
def opened_merge_requests?(data)
|
||||||
|
project.merge_requests
|
||||||
|
.opened
|
||||||
|
.from_project(project)
|
||||||
|
.from_source_branches(Gitlab::Git.ref_name(data[:ref]))
|
||||||
|
.exists?
|
||||||
|
end
|
||||||
|
|
||||||
|
def merge_request_unchecked?(data)
|
||||||
|
MergeRequest.state_machines[:merge_status]
|
||||||
|
.check_state?(data.dig(:object_attributes, :merge_status))
|
||||||
|
end
|
||||||
|
end
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
class DroneCiService < CiService
|
class DroneCiService < CiService
|
||||||
include ReactiveService
|
include ReactiveService
|
||||||
|
include ServicePushDataValidations
|
||||||
|
|
||||||
prop_accessor :drone_url, :token
|
prop_accessor :drone_url, :token
|
||||||
boolean_accessor :enable_ssl_verification
|
boolean_accessor :enable_ssl_verification
|
||||||
|
@ -96,23 +97,4 @@ class DroneCiService < CiService
|
||||||
{ type: 'checkbox', name: 'enable_ssl_verification', title: "Enable SSL verification" }
|
{ type: 'checkbox', name: 'enable_ssl_verification', title: "Enable SSL verification" }
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def tag_push_valid?(data)
|
|
||||||
data[:total_commits_count] > 0 && !Gitlab::Git.blank_ref?(data[:after])
|
|
||||||
end
|
|
||||||
|
|
||||||
def push_valid?(data)
|
|
||||||
opened_merge_requests = project.merge_requests.opened.where(source_project_id: project.id,
|
|
||||||
source_branch: Gitlab::Git.ref_name(data[:ref]))
|
|
||||||
|
|
||||||
opened_merge_requests.empty? && data[:total_commits_count] > 0 &&
|
|
||||||
!Gitlab::Git.blank_ref?(data[:after])
|
|
||||||
end
|
|
||||||
|
|
||||||
def merge_request_valid?(data)
|
|
||||||
data[:object_attributes][:state] == 'opened' &&
|
|
||||||
MergeRequest.state_machines[:merge_status].check_state?(data[:object_attributes][:merge_status])
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
class TeamcityService < CiService
|
class TeamcityService < CiService
|
||||||
include ReactiveService
|
include ReactiveService
|
||||||
|
include ServicePushDataValidations
|
||||||
|
|
||||||
prop_accessor :teamcity_url, :build_type, :username, :password
|
prop_accessor :teamcity_url, :build_type, :username, :password
|
||||||
|
|
||||||
|
@ -89,20 +90,26 @@ class TeamcityService < CiService
|
||||||
end
|
end
|
||||||
|
|
||||||
def execute(data)
|
def execute(data)
|
||||||
return unless supported_events.include?(data[:object_kind])
|
|
||||||
|
|
||||||
case data[:object_kind]
|
case data[:object_kind]
|
||||||
when 'push'
|
when 'push'
|
||||||
branch = Gitlab::Git.ref_name(data[:ref])
|
execute_push(data)
|
||||||
post_to_build_queue(data, branch) if push_valid?(data)
|
|
||||||
when 'merge_request'
|
when 'merge_request'
|
||||||
branch = data[:object_attributes][:source_branch]
|
execute_merge_request(data)
|
||||||
post_to_build_queue(data, branch) if merge_request_valid?(data)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def execute_push(data)
|
||||||
|
branch = Gitlab::Git.ref_name(data[:ref])
|
||||||
|
post_to_build_queue(data, branch) if push_valid?(data)
|
||||||
|
end
|
||||||
|
|
||||||
|
def execute_merge_request(data)
|
||||||
|
branch = data[:object_attributes][:source_branch]
|
||||||
|
post_to_build_queue(data, branch) if merge_request_valid?(data)
|
||||||
|
end
|
||||||
|
|
||||||
def read_build_page(response)
|
def read_build_page(response)
|
||||||
if response.code != 200
|
if response.code != 200
|
||||||
# If actual build link can't be determined,
|
# If actual build link can't be determined,
|
||||||
|
@ -159,27 +166,4 @@ class TeamcityService < CiService
|
||||||
def basic_auth
|
def basic_auth
|
||||||
{ username: username, password: password }
|
{ username: username, password: password }
|
||||||
end
|
end
|
||||||
|
|
||||||
def push_valid?(data)
|
|
||||||
data[:total_commits_count] > 0 &&
|
|
||||||
!branch_removed?(data) &&
|
|
||||||
no_open_merge_requests?(data)
|
|
||||||
end
|
|
||||||
|
|
||||||
def merge_request_valid?(data)
|
|
||||||
data.dig(:object_attributes, :state) == 'opened' &&
|
|
||||||
MergeRequest.state_machines[:merge_status].check_state?(data.dig(:object_attributes, :merge_status))
|
|
||||||
end
|
|
||||||
|
|
||||||
def branch_removed?(data)
|
|
||||||
Gitlab::Git.blank_ref?(data[:after])
|
|
||||||
end
|
|
||||||
|
|
||||||
def no_open_merge_requests?(data)
|
|
||||||
!project.merge_requests
|
|
||||||
.opened
|
|
||||||
.from_project(project)
|
|
||||||
.from_source_branches(Gitlab::Git.ref_name(data[:ref]))
|
|
||||||
.exists?
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,10 +7,11 @@ describe TeamcityService, :use_clean_rails_memory_store_caching do
|
||||||
include StubRequests
|
include StubRequests
|
||||||
|
|
||||||
let(:teamcity_url) { 'http://gitlab.com/teamcity' }
|
let(:teamcity_url) { 'http://gitlab.com/teamcity' }
|
||||||
|
let(:project) { create(:project) }
|
||||||
|
|
||||||
subject(:service) do
|
subject(:service) do
|
||||||
described_class.create(
|
described_class.create(
|
||||||
project: create(:project),
|
project: project,
|
||||||
properties: {
|
properties: {
|
||||||
teamcity_url: teamcity_url,
|
teamcity_url: teamcity_url,
|
||||||
username: 'mic',
|
username: 'mic',
|
||||||
|
@ -225,7 +226,7 @@ describe TeamcityService, :use_clean_rails_memory_store_caching do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns nil when ref is blank' do
|
it 'returns nil when ref is blank' do
|
||||||
data[:after] = "0000000000000000000000000000000000000000"
|
data[:after] = Gitlab::Git::BLANK_SHA
|
||||||
|
|
||||||
expect(service.execute(data)).to be_nil
|
expect(service.execute(data)).to be_nil
|
||||||
end
|
end
|
||||||
|
@ -235,6 +236,12 @@ describe TeamcityService, :use_clean_rails_memory_store_caching do
|
||||||
|
|
||||||
expect(service.execute(data)).to be_nil
|
expect(service.execute(data)).to be_nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'returns nil when a merge request is opened for the same ref' do
|
||||||
|
create(:merge_request, source_project: project, source_branch: 'dev-123_branch')
|
||||||
|
|
||||||
|
expect(service.execute(data)).to be_nil
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when merge_request' do
|
context 'when merge_request' do
|
||||||
|
@ -264,8 +271,8 @@ describe TeamcityService, :use_clean_rails_memory_store_caching do
|
||||||
expect(service.execute(data)).to be_nil
|
expect(service.execute(data)).to be_nil
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns nil when merge request is not unchecked or cannot_be_merged_recheck' do
|
it 'returns nil unless merge request is marked as unchecked' do
|
||||||
data[:object_attributes][:merge_status] = 'checked'
|
data[:object_attributes][:merge_status] = 'can_be_merged'
|
||||||
|
|
||||||
expect(service.execute(data)).to be_nil
|
expect(service.execute(data)).to be_nil
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue