Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'spec/models/integrations/bamboo_spec.rb')
-rw-r--r--spec/models/integrations/bamboo_spec.rb287
1 files changed, 287 insertions, 0 deletions
diff --git a/spec/models/integrations/bamboo_spec.rb b/spec/models/integrations/bamboo_spec.rb
new file mode 100644
index 00000000000..0ba1595bbd8
--- /dev/null
+++ b/spec/models/integrations/bamboo_spec.rb
@@ -0,0 +1,287 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Integrations::Bamboo, :use_clean_rails_memory_store_caching do
+ include ReactiveCachingHelpers
+ include StubRequests
+
+ let(:bamboo_url) { 'http://gitlab.com/bamboo' }
+
+ let_it_be(:project) { create(:project) }
+
+ subject(:service) do
+ described_class.create!(
+ project: project,
+ properties: {
+ bamboo_url: bamboo_url,
+ username: 'mic',
+ password: 'password',
+ build_key: 'foo'
+ }
+ )
+ end
+
+ describe 'Associations' do
+ it { is_expected.to belong_to :project }
+ it { is_expected.to have_one :service_hook }
+ end
+
+ describe 'Validations' do
+ context 'when service is active' do
+ before do
+ subject.active = true
+ end
+
+ it { is_expected.to validate_presence_of(:build_key) }
+ it { is_expected.to validate_presence_of(:bamboo_url) }
+ it_behaves_like 'issue tracker service URL attribute', :bamboo_url
+
+ describe '#username' do
+ it 'does not validate the presence of username if password is nil' do
+ subject.password = nil
+
+ expect(subject).not_to validate_presence_of(:username)
+ end
+
+ it 'validates the presence of username if password is present' do
+ subject.password = 'secret'
+
+ expect(subject).to validate_presence_of(:username)
+ end
+ end
+
+ describe '#password' do
+ it 'does not validate the presence of password if username is nil' do
+ subject.username = nil
+
+ expect(subject).not_to validate_presence_of(:password)
+ end
+
+ it 'validates the presence of password if username is present' do
+ subject.username = 'john'
+
+ expect(subject).to validate_presence_of(:password)
+ end
+ end
+ end
+
+ context 'when service is inactive' do
+ before do
+ subject.active = false
+ end
+
+ it { is_expected.not_to validate_presence_of(:build_key) }
+ it { is_expected.not_to validate_presence_of(:bamboo_url) }
+ it { is_expected.not_to validate_presence_of(:username) }
+ it { is_expected.not_to validate_presence_of(:password) }
+ end
+ end
+
+ describe 'Callbacks' do
+ describe 'before_update :reset_password' do
+ context 'when a password was previously set' do
+ it 'resets password if url changed' do
+ bamboo_service = service
+
+ bamboo_service.bamboo_url = 'http://gitlab1.com'
+ bamboo_service.save!
+
+ expect(bamboo_service.password).to be_nil
+ end
+
+ it 'does not reset password if username changed' do
+ bamboo_service = service
+
+ bamboo_service.username = 'some_name'
+ bamboo_service.save!
+
+ expect(bamboo_service.password).to eq('password')
+ end
+
+ it "does not reset password if new url is set together with password, even if it's the same password" do
+ bamboo_service = service
+
+ bamboo_service.bamboo_url = 'http://gitlab_edited.com'
+ bamboo_service.password = 'password'
+ bamboo_service.save!
+
+ expect(bamboo_service.password).to eq('password')
+ expect(bamboo_service.bamboo_url).to eq('http://gitlab_edited.com')
+ end
+ end
+
+ it 'saves password if new url is set together with password when no password was previously set' do
+ bamboo_service = service
+ bamboo_service.password = nil
+
+ bamboo_service.bamboo_url = 'http://gitlab_edited.com'
+ bamboo_service.password = 'password'
+ bamboo_service.save!
+
+ expect(bamboo_service.password).to eq('password')
+ expect(bamboo_service.bamboo_url).to eq('http://gitlab_edited.com')
+ end
+ end
+ end
+
+ describe '#execute' do
+ it 'runs update and build action' do
+ stub_update_and_build_request
+
+ subject.execute(Gitlab::DataBuilder::Push::SAMPLE_DATA)
+ end
+ end
+
+ describe '#build_page' do
+ it 'returns the contents of the reactive cache' do
+ stub_reactive_cache(service, { build_page: 'foo' }, 'sha', 'ref')
+
+ expect(service.build_page('sha', 'ref')).to eq('foo')
+ end
+ end
+
+ describe '#commit_status' do
+ it 'returns the contents of the reactive cache' do
+ stub_reactive_cache(service, { commit_status: 'foo' }, 'sha', 'ref')
+
+ expect(service.commit_status('sha', 'ref')).to eq('foo')
+ end
+ end
+
+ shared_examples 'reactive cache calculation' do
+ describe '#build_page' do
+ subject { service.calculate_reactive_cache('123', 'unused')[:build_page] }
+
+ it 'returns a specific URL when status is 500' do
+ stub_request(status: 500)
+
+ is_expected.to eq('http://gitlab.com/bamboo/browse/foo')
+ end
+
+ it 'returns a specific URL when response has no results' do
+ stub_request(body: %q({"results":{"results":{"size":"0"}}}))
+
+ is_expected.to eq('http://gitlab.com/bamboo/browse/foo')
+ end
+
+ it 'returns a build URL when bamboo_url has no trailing slash' do
+ stub_request(body: bamboo_response)
+
+ is_expected.to eq('http://gitlab.com/bamboo/browse/42')
+ end
+
+ context 'bamboo_url has trailing slash' do
+ let(:bamboo_url) { 'http://gitlab.com/bamboo/' }
+
+ it 'returns a build URL' do
+ stub_request(body: bamboo_response)
+
+ is_expected.to eq('http://gitlab.com/bamboo/browse/42')
+ end
+ end
+ end
+
+ describe '#commit_status' do
+ subject { service.calculate_reactive_cache('123', 'unused')[:commit_status] }
+
+ it 'sets commit status to :error when status is 500' do
+ stub_request(status: 500)
+
+ is_expected.to eq(:error)
+ end
+
+ it 'sets commit status to "pending" when status is 404' do
+ stub_request(status: 404)
+
+ is_expected.to eq('pending')
+ end
+
+ it 'sets commit status to "pending" when response has no results' do
+ stub_request(body: %q({"results":{"results":{"size":"0"}}}))
+
+ is_expected.to eq('pending')
+ end
+
+ it 'sets commit status to "success" when build state contains Success' do
+ stub_request(body: bamboo_response(build_state: 'YAY Success!'))
+
+ is_expected.to eq('success')
+ end
+
+ it 'sets commit status to "failed" when build state contains Failed' do
+ stub_request(body: bamboo_response(build_state: 'NO Failed!'))
+
+ is_expected.to eq('failed')
+ end
+
+ it 'sets commit status to "pending" when build state contains Pending' do
+ stub_request(body: bamboo_response(build_state: 'NO Pending!'))
+
+ is_expected.to eq('pending')
+ end
+
+ it 'sets commit status to :error when build state is unknown' do
+ stub_request(body: bamboo_response(build_state: 'FOO BAR!'))
+
+ is_expected.to eq(:error)
+ end
+
+ Gitlab::HTTP::HTTP_ERRORS.each do |http_error|
+ it "sets commit status to :error with a #{http_error.name} error" do
+ WebMock.stub_request(:get, 'http://gitlab.com/bamboo/rest/api/latest/result/byChangeset/123?os_authType=basic')
+ .to_raise(http_error)
+
+ expect(Gitlab::ErrorTracking)
+ .to receive(:log_exception)
+ .with(instance_of(http_error), project_id: project.id)
+
+ is_expected.to eq(:error)
+ end
+ end
+ end
+ end
+
+ describe '#calculate_reactive_cache' do
+ context 'when Bamboo API returns single result' do
+ let(:bamboo_response_template) do
+ %q({"results":{"results":{"size":"1","result":{"buildState":"%{build_state}","planResultKey":{"key":"42"}}}}})
+ end
+
+ it_behaves_like 'reactive cache calculation'
+ end
+
+ context 'when Bamboo API returns an array of results and we only consider the last one' do
+ let(:bamboo_response_template) do
+ %q({"results":{"results":{"size":"2","result":[{"buildState":"%{build_state}","planResultKey":{"key":"41"}},{"buildState":"%{build_state}","planResultKey":{"key":"42"}}]}}})
+ end
+
+ it_behaves_like 'reactive cache calculation'
+ end
+ end
+
+ def stub_update_and_build_request(status: 200, body: nil)
+ bamboo_full_url = 'http://gitlab.com/bamboo/updateAndBuild.action?buildKey=foo&os_authType=basic'
+
+ stub_bamboo_request(bamboo_full_url, status, body)
+ end
+
+ def stub_request(status: 200, body: nil)
+ bamboo_full_url = 'http://gitlab.com/bamboo/rest/api/latest/result/byChangeset/123?os_authType=basic'
+
+ stub_bamboo_request(bamboo_full_url, status, body)
+ end
+
+ def stub_bamboo_request(url, status, body)
+ stub_full_request(url).to_return(
+ status: status,
+ headers: { 'Content-Type' => 'application/json' },
+ body: body
+ ).with(basic_auth: %w(mic password))
+ end
+
+ def bamboo_response(build_state: 'success')
+ # reference: https://docs.atlassian.com/atlassian-bamboo/REST/6.2.5/#d2e786
+ bamboo_response_template % { build_state: build_state }
+ end
+end