Commit a39277a4 authored by Raphael Tweitmann's avatar Raphael Tweitmann Committed by Fabio Pitino

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
parent 5f1038c8
# 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 @@ ...@@ -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 ...@@ -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 @@ ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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
......
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