2021-02-22 17:27:13 +05:30
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
require 'spec_helper'
|
|
|
|
|
2021-09-04 01:27:46 +05:30
|
|
|
RSpec.describe Integrations::Jenkins do
|
2021-02-22 17:27:13 +05:30
|
|
|
let(:project) { create(:project) }
|
2022-07-16 23:28:13 +05:30
|
|
|
let(:jenkins_integration) { described_class.new(jenkins_params) }
|
2021-02-22 17:27:13 +05:30
|
|
|
let(:jenkins_url) { 'http://jenkins.example.com/' }
|
|
|
|
let(:jenkins_hook_url) { jenkins_url + 'project/my_project' }
|
|
|
|
let(:jenkins_username) { 'u$er name%2520' }
|
|
|
|
let(:jenkins_password) { 'pas$ word' }
|
2022-07-16 23:28:13 +05:30
|
|
|
let(:jenkins_authorization) { 'Basic ' + ::Base64.strict_encode64(jenkins_username + ':' + jenkins_password) }
|
2021-02-22 17:27:13 +05:30
|
|
|
let(:jenkins_params) do
|
|
|
|
{
|
|
|
|
active: true,
|
|
|
|
project: project,
|
|
|
|
properties: {
|
|
|
|
password: jenkins_password,
|
|
|
|
username: jenkins_username,
|
|
|
|
jenkins_url: jenkins_url,
|
|
|
|
project_name: 'my_project'
|
|
|
|
}
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
2022-02-05 19:09:49 +05:30
|
|
|
include_context Integrations::EnableSslVerification do
|
2022-07-16 23:28:13 +05:30
|
|
|
let(:integration) { jenkins_integration }
|
2022-02-05 19:09:49 +05:30
|
|
|
end
|
|
|
|
|
2021-09-30 23:02:18 +05:30
|
|
|
it_behaves_like Integrations::HasWebHook do
|
2022-07-16 23:28:13 +05:30
|
|
|
let(:integration) { jenkins_integration }
|
2021-09-30 23:02:18 +05:30
|
|
|
let(:hook_url) { "http://#{ERB::Util.url_encode jenkins_username}:#{ERB::Util.url_encode jenkins_password}@jenkins.example.com/project/my_project" }
|
2021-02-22 17:27:13 +05:30
|
|
|
end
|
|
|
|
|
2022-07-16 23:28:13 +05:30
|
|
|
it 'sets the default values', :aggregate_failures do
|
|
|
|
expect(jenkins_integration.push_events).to eq(true)
|
|
|
|
expect(jenkins_integration.merge_requests_events).to eq(false)
|
|
|
|
expect(jenkins_integration.tag_push_events).to eq(false)
|
|
|
|
end
|
|
|
|
|
2021-02-22 17:27:13 +05:30
|
|
|
describe 'username validation' do
|
2021-09-30 23:02:18 +05:30
|
|
|
let(:jenkins_integration) do
|
|
|
|
described_class.create!(
|
2021-02-22 17:27:13 +05:30
|
|
|
active: active,
|
|
|
|
project: project,
|
|
|
|
properties: {
|
|
|
|
jenkins_url: 'http://jenkins.example.com/',
|
|
|
|
password: 'password',
|
|
|
|
username: 'username',
|
|
|
|
project_name: 'my_project'
|
|
|
|
}
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
2021-09-30 23:02:18 +05:30
|
|
|
subject { jenkins_integration }
|
2021-02-22 17:27:13 +05:30
|
|
|
|
2021-09-30 23:02:18 +05:30
|
|
|
context 'when the integration is active' do
|
2021-02-22 17:27:13 +05:30
|
|
|
let(:active) { true }
|
|
|
|
|
|
|
|
context 'when password was not touched' do
|
|
|
|
before do
|
|
|
|
allow(subject).to receive(:password_touched?).and_return(false)
|
|
|
|
end
|
|
|
|
|
|
|
|
it { is_expected.not_to validate_presence_of :username }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when password was touched' do
|
|
|
|
before do
|
|
|
|
allow(subject).to receive(:password_touched?).and_return(true)
|
|
|
|
end
|
|
|
|
|
|
|
|
it { is_expected.to validate_presence_of :username }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when password is blank' do
|
|
|
|
it 'does not validate the username' do
|
|
|
|
expect(subject).not_to validate_presence_of :username
|
|
|
|
|
|
|
|
subject.password = ''
|
|
|
|
subject.save!
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-09-30 23:02:18 +05:30
|
|
|
context 'when the integration is inactive' do
|
2021-02-22 17:27:13 +05:30
|
|
|
let(:active) { false }
|
|
|
|
|
|
|
|
it { is_expected.not_to validate_presence_of :username }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe '#hook_url' do
|
|
|
|
let(:username) { nil }
|
|
|
|
let(:password) { nil }
|
2021-09-30 23:02:18 +05:30
|
|
|
let(:jenkins_integration) do
|
2021-02-22 17:27:13 +05:30
|
|
|
described_class.new(
|
|
|
|
project: project,
|
|
|
|
properties: {
|
|
|
|
jenkins_url: jenkins_url,
|
|
|
|
project_name: 'my_project',
|
|
|
|
username: username,
|
|
|
|
password: password
|
|
|
|
}
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
2021-09-30 23:02:18 +05:30
|
|
|
subject { jenkins_integration.hook_url }
|
2021-02-22 17:27:13 +05:30
|
|
|
|
|
|
|
context 'when the jenkins_url has no relative path' do
|
|
|
|
let(:jenkins_url) { 'http://jenkins.example.com/' }
|
|
|
|
|
|
|
|
it { is_expected.to eq('http://jenkins.example.com/project/my_project') }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when the jenkins_url has relative path' do
|
|
|
|
let(:jenkins_url) { 'http://organization.example.com/jenkins' }
|
|
|
|
|
|
|
|
it { is_expected.to eq('http://organization.example.com/jenkins/project/my_project') }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'userinfo is missing and username and password are set' do
|
|
|
|
let(:jenkins_url) { 'http://organization.example.com/jenkins' }
|
|
|
|
let(:username) { 'u$ername' }
|
|
|
|
let(:password) { 'pas$ word' }
|
|
|
|
|
|
|
|
it { is_expected.to eq('http://u%24ername:pas%24%20word@organization.example.com/jenkins/project/my_project') }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'userinfo is provided and username and password are set' do
|
|
|
|
let(:jenkins_url) { 'http://u:p@organization.example.com/jenkins' }
|
|
|
|
let(:username) { 'username' }
|
|
|
|
let(:password) { 'password' }
|
|
|
|
|
|
|
|
it { is_expected.to eq('http://username:password@organization.example.com/jenkins/project/my_project') }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'userinfo is provided username and password are not set' do
|
|
|
|
let(:jenkins_url) { 'http://u:p@organization.example.com/jenkins' }
|
|
|
|
|
|
|
|
it { is_expected.to eq('http://u:p@organization.example.com/jenkins/project/my_project') }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe '#test' do
|
|
|
|
it 'returns the right status' do
|
|
|
|
user = create(:user, username: 'username')
|
|
|
|
project = create(:project, name: 'project')
|
|
|
|
push_sample_data = Gitlab::DataBuilder::Push.build_sample(project, user)
|
2021-09-30 23:02:18 +05:30
|
|
|
jenkins_integration = described_class.create!(jenkins_params)
|
2021-02-22 17:27:13 +05:30
|
|
|
stub_request(:post, jenkins_hook_url).with(headers: { 'Authorization' => jenkins_authorization })
|
|
|
|
|
2021-09-30 23:02:18 +05:30
|
|
|
result = jenkins_integration.test(push_sample_data)
|
2021-02-22 17:27:13 +05:30
|
|
|
|
|
|
|
expect(result).to eq({ success: true, result: '' })
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe '#execute' do
|
|
|
|
let(:user) { create(:user, username: 'username') }
|
|
|
|
let(:namespace) { create(:group, :private) }
|
|
|
|
let(:project) { create(:project, :private, name: 'project', namespace: namespace) }
|
|
|
|
let(:push_sample_data) { Gitlab::DataBuilder::Push.build_sample(project, user) }
|
2021-09-30 23:02:18 +05:30
|
|
|
let(:jenkins_integration) { described_class.create!(jenkins_params) }
|
2021-02-22 17:27:13 +05:30
|
|
|
|
|
|
|
before do
|
|
|
|
stub_request(:post, jenkins_hook_url)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'invokes the Jenkins API' do
|
2021-09-30 23:02:18 +05:30
|
|
|
jenkins_integration.execute(push_sample_data)
|
2021-02-22 17:27:13 +05:30
|
|
|
|
|
|
|
expect(a_request(:post, jenkins_hook_url)).to have_been_made.once
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'adds default web hook headers to the request' do
|
2021-09-30 23:02:18 +05:30
|
|
|
jenkins_integration.execute(push_sample_data)
|
2021-02-22 17:27:13 +05:30
|
|
|
|
|
|
|
expect(
|
|
|
|
a_request(:post, jenkins_hook_url)
|
|
|
|
.with(headers: { 'X-Gitlab-Event' => 'Push Hook', 'Authorization' => jenkins_authorization })
|
|
|
|
).to have_been_made.once
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'request url contains properly serialized username and password' do
|
2021-09-30 23:02:18 +05:30
|
|
|
jenkins_integration.execute(push_sample_data)
|
2021-02-22 17:27:13 +05:30
|
|
|
|
|
|
|
expect(
|
|
|
|
a_request(:post, 'http://jenkins.example.com/project/my_project')
|
|
|
|
.with(headers: { 'Authorization' => jenkins_authorization })
|
|
|
|
).to have_been_made.once
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe 'Stored password invalidation' do
|
|
|
|
let(:project) { create(:project) }
|
|
|
|
|
|
|
|
context 'when a password was previously set' do
|
2021-09-30 23:02:18 +05:30
|
|
|
let(:jenkins_integration) do
|
|
|
|
described_class.create!(
|
2021-02-22 17:27:13 +05:30
|
|
|
project: project,
|
|
|
|
properties: {
|
|
|
|
jenkins_url: 'http://jenkins.example.com/',
|
|
|
|
username: 'jenkins',
|
|
|
|
password: 'password'
|
|
|
|
}
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'resets password if url changed' do
|
2021-09-30 23:02:18 +05:30
|
|
|
jenkins_integration.jenkins_url = 'http://jenkins-edited.example.com/'
|
2021-10-27 15:23:28 +05:30
|
|
|
jenkins_integration.valid?
|
2021-09-30 23:02:18 +05:30
|
|
|
|
|
|
|
expect(jenkins_integration.password).to be_nil
|
2021-02-22 17:27:13 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
it 'resets password if username is blank' do
|
2021-09-30 23:02:18 +05:30
|
|
|
jenkins_integration.username = ''
|
2021-10-27 15:23:28 +05:30
|
|
|
jenkins_integration.valid?
|
2021-09-30 23:02:18 +05:30
|
|
|
|
|
|
|
expect(jenkins_integration.password).to be_nil
|
2021-02-22 17:27:13 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
it 'does not reset password if username changed' do
|
2021-09-30 23:02:18 +05:30
|
|
|
jenkins_integration.username = 'some_name'
|
2021-10-27 15:23:28 +05:30
|
|
|
jenkins_integration.valid?
|
2021-09-30 23:02:18 +05:30
|
|
|
|
|
|
|
expect(jenkins_integration.password).to eq('password')
|
2021-02-22 17:27:13 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
it 'does not reset password if new url is set together with password, even if it\'s the same password' do
|
2021-09-30 23:02:18 +05:30
|
|
|
jenkins_integration.jenkins_url = 'http://jenkins_edited.example.com/'
|
|
|
|
jenkins_integration.password = 'password'
|
2021-10-27 15:23:28 +05:30
|
|
|
jenkins_integration.valid?
|
2021-09-30 23:02:18 +05:30
|
|
|
|
|
|
|
expect(jenkins_integration.password).to eq('password')
|
|
|
|
expect(jenkins_integration.jenkins_url).to eq('http://jenkins_edited.example.com/')
|
2021-02-22 17:27:13 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
it 'resets password if url changed, even if setter called multiple times' do
|
2021-09-30 23:02:18 +05:30
|
|
|
jenkins_integration.jenkins_url = 'http://jenkins1.example.com/'
|
|
|
|
jenkins_integration.jenkins_url = 'http://jenkins1.example.com/'
|
2021-10-27 15:23:28 +05:30
|
|
|
jenkins_integration.valid?
|
2021-09-30 23:02:18 +05:30
|
|
|
|
|
|
|
expect(jenkins_integration.password).to be_nil
|
2021-02-22 17:27:13 +05:30
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when no password was previously set' do
|
2021-09-30 23:02:18 +05:30
|
|
|
let(:jenkins_integration) do
|
|
|
|
described_class.create!(
|
2021-02-22 17:27:13 +05:30
|
|
|
project: create(:project),
|
|
|
|
properties: {
|
|
|
|
jenkins_url: 'http://jenkins.example.com/',
|
|
|
|
username: 'jenkins'
|
|
|
|
}
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'saves password if new url is set together with password' do
|
2021-09-30 23:02:18 +05:30
|
|
|
jenkins_integration.jenkins_url = 'http://jenkins_edited.example.com/'
|
|
|
|
jenkins_integration.password = 'password'
|
|
|
|
jenkins_integration.save!
|
|
|
|
|
2021-10-27 15:23:28 +05:30
|
|
|
expect(jenkins_integration.reload).to have_attributes(
|
|
|
|
jenkins_url: 'http://jenkins_edited.example.com/',
|
|
|
|
password: 'password'
|
|
|
|
)
|
2021-02-22 17:27:13 +05:30
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|