...@@ -7,8 +7,8 @@ describe Emails::PagesDomains do ...@@ -7,8 +7,8 @@ describe Emails::PagesDomains do
include EmailSpec::Matchers include EmailSpec::Matchers
include_context 'gitlab email notification' include_context 'gitlab email notification'
set(:domain) { create(:pages_domain, project: project) } let_it_be(:domain, reload: true) { create(:pages_domain, project: project) }
set(:user) { project.creator } let_it_be(:user) { project.creator }
shared_examples 'a pages domain email' do shared_examples 'a pages domain email' do
let(:recipient) { user } let(:recipient) { user }
... ...
......
...@@ -6,7 +6,7 @@ require 'email_spec' ...@@ -6,7 +6,7 @@ require 'email_spec'
describe Emails::Pipelines do describe Emails::Pipelines do
include EmailSpec::Matchers include EmailSpec::Matchers
set(:project) { create(:project, :repository) } let_it_be(:project) { create(:project, :repository) }
shared_examples_for 'correct pipeline information' do shared_examples_for 'correct pipeline information' do
it 'has a correct information' do it 'has a correct information' do
... ...
......
...@@ -13,11 +13,11 @@ describe Notify do ...@@ -13,11 +13,11 @@ describe Notify do
let(:current_user_sanitized) { 'www_example_com' } let(:current_user_sanitized) { 'www_example_com' }
set(:user) { create(:user) } let_it_be(:user) { create(:user) }
set(:current_user) { create(:user, email: "current@email.com", name: 'www.example.com') } let_it_be(:current_user) { create(:user, email: "current@email.com", name: 'www.example.com') }
set(:assignee) { create(:user, email: 'assignee@example.com', name: 'John Doe') } let_it_be(:assignee) { create(:user, email: 'assignee@example.com', name: 'John Doe') }
set(:merge_request) do let_it_be(:merge_request) do
create(:merge_request, source_project: project, create(:merge_request, source_project: project,
target_project: project, target_project: project,
author: current_user, author: current_user,
...@@ -25,7 +25,7 @@ describe Notify do ...@@ -25,7 +25,7 @@ describe Notify do
description: 'Awesome description') description: 'Awesome description')
end end
set(:issue) do let_it_be(:issue, reload: true) do
create(:issue, author: current_user, create(:issue, author: current_user,
assignees: [assignee], assignees: [assignee],
project: project, project: project,
...@@ -487,7 +487,7 @@ describe Notify do ...@@ -487,7 +487,7 @@ describe Notify do
end end
describe 'that are unmergeable' do describe 'that are unmergeable' do
set(:merge_request) do let_it_be(:merge_request) do
create(:merge_request, :conflict, create(:merge_request, :conflict,
source_project: project, source_project: project,
target_project: project, target_project: project,
...@@ -568,7 +568,7 @@ describe Notify do ...@@ -568,7 +568,7 @@ describe Notify do
end end
describe '#mail_thread' do describe '#mail_thread' do
set(:mail_thread_note) { create(:note) } let_it_be(:mail_thread_note) { create(:note) }
let(:headers) do let(:headers) do
{ {
...@@ -638,9 +638,9 @@ describe Notify do ...@@ -638,9 +638,9 @@ describe Notify do
let(:host) { Gitlab.config.gitlab.host } let(:host) { Gitlab.config.gitlab.host }
context 'in discussion' do context 'in discussion' do
set(:first_note) { create(:discussion_note_on_issue, project: project) } let_it_be(:first_note) { create(:discussion_note_on_issue, project: project) }
set(:second_note) { create(:discussion_note_on_issue, in_reply_to: first_note, project: project) } let_it_be(:second_note) { create(:discussion_note_on_issue, in_reply_to: first_note, project: project) }
set(:third_note) { create(:discussion_note_on_issue, in_reply_to: second_note, project: project) } let_it_be(:third_note) { create(:discussion_note_on_issue, in_reply_to: second_note, project: project) }
subject { described_class.note_issue_email(recipient.id, third_note.id) } subject { described_class.note_issue_email(recipient.id, third_note.id) }
...@@ -664,7 +664,7 @@ describe Notify do ...@@ -664,7 +664,7 @@ describe Notify do
end end
context 'individual issue comments' do context 'individual issue comments' do
set(:note) { create(:note_on_issue, project: project) } let_it_be(:note) { create(:note_on_issue, project: project) }
subject { described_class.note_issue_email(recipient.id, note.id) } subject { described_class.note_issue_email(recipient.id, note.id) }
... ...
......
...@@ -489,7 +489,14 @@ describe JiraService do ...@@ -489,7 +489,14 @@ describe JiraService do
@jira_service.close_issue(resource, ExternalIssue.new('JIRA-123', project)) @jira_service.close_issue(resource, ExternalIssue.new('JIRA-123', project))
expect(@jira_service).to have_received(:log_error).with("Issue transition failed", error: "Bad Request", client_url: "http://jira.example.com") expect(@jira_service).to have_received(:log_error).with(
"Issue transition failed",
error: hash_including(
exception_class: 'StandardError',
exception_message: "Bad Request"
),
client_url: "http://jira.example.com"
)
end end
it 'calls the api with jira_issue_transition_id' do it 'calls the api with jira_issue_transition_id' do
... ...
......
...@@ -5,7 +5,7 @@ require 'spec_helper' ...@@ -5,7 +5,7 @@ require 'spec_helper'
describe ApplicationSetting::TermPolicy do describe ApplicationSetting::TermPolicy do
include TermsHelper include TermsHelper
set(:term) { create(:term) } let_it_be(:term) { create(:term) }
let(:user) { create(:user) } let(:user) { create(:user) }
subject(:policy) { described_class.new(user, term) } subject(:policy) { described_class.new(user, term) }
... ...
......
...@@ -3,9 +3,9 @@ ...@@ -3,9 +3,9 @@
require 'spec_helper' require 'spec_helper'
describe Ci::PipelineSchedulePolicy, :models do describe Ci::PipelineSchedulePolicy, :models do
set(:user) { create(:user) } let_it_be(:user) { create(:user) }
set(:project) { create(:project, :repository) } let_it_be(:project) { create(:project, :repository) }
set(:pipeline_schedule) { create(:ci_pipeline_schedule, :nightly, project: project) } let_it_be(:pipeline_schedule, reload: true) { create(:ci_pipeline_schedule, :nightly, project: project) }
let(:policy) do let(:policy) do
described_class.new(user, pipeline_schedule) described_class.new(user, pipeline_schedule)
... ...
......
...@@ -5,12 +5,12 @@ require 'spec_helper' ...@@ -5,12 +5,12 @@ require 'spec_helper'
describe ProjectPolicy do describe ProjectPolicy do
include ExternalAuthorizationServiceHelpers include ExternalAuthorizationServiceHelpers
include_context 'ProjectPolicy context' include_context 'ProjectPolicy context'
set(:guest) { create(:user) } let_it_be(:guest) { create(:user) }
set(:reporter) { create(:user) } let_it_be(:reporter) { create(:user) }
set(:developer) { create(:user) } let_it_be(:developer) { create(:user) }
set(:maintainer) { create(:user) } let_it_be(:maintainer) { create(:user) }
set(:owner) { create(:user) } let_it_be(:owner) { create(:user) }
set(:admin) { create(:admin) } let_it_be(:admin) { create(:admin) }
let(:project) { create(:project, :public, namespace: owner.namespace) } let(:project) { create(:project, :public, namespace: owner.namespace) }
let(:base_guest_permissions) do let(:base_guest_permissions) do
... ...
......
...@@ -3,10 +3,10 @@ ...@@ -3,10 +3,10 @@
require 'spec_helper' require 'spec_helper'
describe ResourceLabelEventPolicy do describe ResourceLabelEventPolicy do
set(:user) { create(:user) } let_it_be(:user) { create(:user) }
set(:project) { create(:project, :private) } let_it_be(:project) { create(:project, :private) }
set(:issue) { create(:issue, project: project) } let_it_be(:issue) { create(:issue, project: project) }
set(:private_project) { create(:project, :private) } let_it_be(:private_project) { create(:project, :private) }
describe '#read_resource_label_event' do describe '#read_resource_label_event' do
context 'with non-member user' do context 'with non-member user' do
... ...
......
...@@ -811,6 +811,8 @@ describe API::Internal::Base do ...@@ -811,6 +811,8 @@ describe API::Internal::Base do
describe 'POST /internal/post_receive', :clean_gitlab_redis_shared_state do describe 'POST /internal/post_receive', :clean_gitlab_redis_shared_state do
let(:identifier) { 'key-123' } let(:identifier) { 'key-123' }
let(:branch_name) { 'feature' }
let(:push_options) { ['ci.skip', 'another push option'] }
let(:valid_params) do let(:valid_params) do
{ {
...@@ -822,192 +824,33 @@ describe API::Internal::Base do ...@@ -822,192 +824,33 @@ describe API::Internal::Base do
} }
end end
let(:branch_name) { 'feature' }
let(:changes) do let(:changes) do
"#{Gitlab::Git::BLANK_SHA} 570e7b2abdd848b95f2f578043fc23bd6f6fd24d refs/heads/#{branch_name}" "#{Gitlab::Git::BLANK_SHA} 570e7b2abdd848b95f2f578043fc23bd6f6fd24d refs/heads/#{branch_name}"
end end
let(:push_options) do subject { post api('/internal/post_receive'), params: valid_params }
['ci.skip',
'another push option']
end
before do before do
project.add_developer(user) project.add_developer(user)
allow_any_instance_of(Gitlab::Identifier).to receive(:identify).and_return(user) allow_any_instance_of(Gitlab::Identifier).to receive(:identify).and_return(user)
end end
it 'enqueues a PostReceive worker job' do it 'executes PostReceiveService' do
expect(PostReceive).to receive(:perform_async)
.with(gl_repository, identifier, changes, { ci: { skip: true } })
post api('/internal/post_receive'), params: valid_params
end
it 'decreases the reference counter and returns the result' do
expect(Gitlab::ReferenceCounter).to receive(:new).with(gl_repository)
.and_return(reference_counter)
expect(reference_counter).to receive(:decrease).and_return(true)
post api('/internal/post_receive'), params: valid_params
expect(json_response['reference_counter_decreased']).to be(true)
end
it 'returns link to create new merge request' do
post api('/internal/post_receive'), params: valid_params
message = <<~MESSAGE.strip message = <<~MESSAGE.strip
To create a merge request for #{branch_name}, visit: To create a merge request for #{branch_name}, visit:
http://#{Gitlab.config.gitlab.host}/#{project.full_path}/-/merge_requests/new?merge_request%5Bsource_branch%5D=#{branch_name} http://#{Gitlab.config.gitlab.host}/#{project.full_path}/-/merge_requests/new?merge_request%5Bsource_branch%5D=#{branch_name}
MESSAGE MESSAGE
expect(json_response['messages']).to include(build_basic_message(message)) subject
end
it 'returns the link to an existing merge request when it exists' do
merge_request = create(:merge_request, source_project: project, source_branch: branch_name, target_branch: 'master')
post api('/internal/post_receive'), params: valid_params
message = <<~MESSAGE.strip
View merge request for feature:
#{project_merge_request_url(project, merge_request)}
MESSAGE
expect(json_response['messages']).to include(build_basic_message(message))
end
it 'returns no merge request messages if printing_merge_request_link_enabled is false' do expect(json_response).to eq({
project.update!(printing_merge_request_link_enabled: false) 'messages' => [{ 'message' => message, 'type' => 'basic' }],
'reference_counter_decreased' => true
post api('/internal/post_receive'), params: valid_params })
expect(json_response['messages']).to be_blank
end
it 'does not invoke MergeRequests::PushOptionsHandlerService' do
expect(MergeRequests::PushOptionsHandlerService).not_to receive(:new)
post api('/internal/post_receive'), params: valid_params
end end
it_behaves_like 'storing arguments in the application context' do it_behaves_like 'storing arguments in the application context' do
let(:expected_params) { { user: user.username, project: project.full_path } } let(:expected_params) { { user: user.username, project: project.full_path } }
subject { post api('/internal/post_receive'), params: valid_params }
end
context 'when there are merge_request push options' do
before do
valid_params[:push_options] = ['merge_request.create']
end
it 'invokes MergeRequests::PushOptionsHandlerService' do
expect(MergeRequests::PushOptionsHandlerService).to receive(:new)
post api('/internal/post_receive'), params: valid_params
end
it 'creates a new merge request' do
expect do
Sidekiq::Testing.fake! do
post api('/internal/post_receive'), params: valid_params
end
end.to change { MergeRequest.count }.by(1)
end
it 'links to the newly created merge request' do
post api('/internal/post_receive'), params: valid_params
message = <<~MESSAGE.strip
View merge request for #{branch_name}:
http://#{Gitlab.config.gitlab.host}/#{project.full_path}/-/merge_requests/1
MESSAGE
expect(json_response['messages']).to include(build_basic_message(message))
end
it 'adds errors on the service instance to warnings' do
expect_any_instance_of(
MergeRequests::PushOptionsHandlerService
).to receive(:errors).at_least(:once).and_return(['my error'])
post api('/internal/post_receive'), params: valid_params
message = "WARNINGS:\nError encountered with push options 'merge_request.create': my error"
expect(json_response['messages']).to include(build_alert_message(message))
end
it 'adds ActiveRecord errors on invalid MergeRequest records to warnings' do
invalid_merge_request = MergeRequest.new
invalid_merge_request.errors.add(:base, 'my error')
expect_any_instance_of(
MergeRequests::CreateService
).to receive(:execute).and_return(invalid_merge_request)
post api('/internal/post_receive'), params: valid_params
message = "WARNINGS:\nError encountered with push options 'merge_request.create': my error"
expect(json_response['messages']).to include(build_alert_message(message))
end
end
context 'broadcast message exists' do
let!(:broadcast_message) { create(:broadcast_message, starts_at: 1.day.ago, ends_at: 1.day.from_now ) }
it 'outputs a broadcast message' do
post api('/internal/post_receive'), params: valid_params
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['messages']).to include(build_alert_message(broadcast_message.message))
end
end
context 'broadcast message does not exist' do
it 'does not output a broadcast message' do
post api('/internal/post_receive'), params: valid_params
expect(response).to have_gitlab_http_status(:ok)
expect(has_alert_messages?(json_response['messages'])).to be_falsey
end
end
context 'nil broadcast message' do
it 'does not output a broadcast message' do
allow(BroadcastMessage).to receive(:current).and_return(nil)
post api('/internal/post_receive'), params: valid_params
expect(response).to have_gitlab_http_status(:ok)
expect(has_alert_messages?(json_response['messages'])).to be_falsey
end
end
context 'with a redirected data' do
it 'returns redirected message on the response' do
project_moved = Gitlab::Checks::ProjectMoved.new(project, user, 'http', 'foo/baz')
project_moved.add_message
post api('/internal/post_receive'), params: valid_params
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['messages']).to include(build_basic_message(project_moved.message))
end
end
context 'with new project data' do
it 'returns new project message on the response' do
project_created = Gitlab::Checks::ProjectCreated.new(project, user, 'http')
project_created.add_message
post api('/internal/post_receive'), params: valid_params
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['messages']).to include(build_basic_message(project_created.message))
end
end end
context 'with an orphaned write deploy key' do context 'with an orphaned write deploy key' do
...@@ -1016,7 +859,7 @@ describe API::Internal::Base do ...@@ -1016,7 +859,7 @@ describe API::Internal::Base do
expect(Gitlab::Checks::ProjectMoved).not_to receive(:fetch_message) expect(Gitlab::Checks::ProjectMoved).not_to receive(:fetch_message)
post api('/internal/post_receive'), params: valid_params subject
expect(response).to have_gitlab_http_status(:ok) expect(response).to have_gitlab_http_status(:ok)
end end
...@@ -1030,7 +873,7 @@ describe API::Internal::Base do ...@@ -1030,7 +873,7 @@ describe API::Internal::Base do
expect(Gitlab::Checks::ProjectMoved).not_to receive(:fetch_message) expect(Gitlab::Checks::ProjectMoved).not_to receive(:fetch_message)
post api('/internal/post_receive'), params: valid_params subject
expect(response).to have_gitlab_http_status(:ok) expect(response).to have_gitlab_http_status(:ok)
end end
...@@ -1142,18 +985,4 @@ describe API::Internal::Base do ...@@ -1142,18 +985,4 @@ describe API::Internal::Base do
} }
) )
end end
def build_alert_message(message)
{ 'type' => 'alert', 'message' => message }
end
def build_basic_message(message)
{ 'type' => 'basic', 'message' => message }
end
def has_alert_messages?(messages)
messages.any? do |message|
message['type'] == 'alert'
end
end
end end
# frozen_string_literal: true
require 'spec_helper'
describe PostReceiveService do
include Gitlab::Routing
let_it_be(:project) { create(:project, :repository, :wiki_repo) }
let_it_be(:user) { create(:user) }
let(:identifier) { 'key-123' }
let(:gl_repository) { "project-#{project.id}" }
let(:branch_name) { 'feature' }
let(:secret_token) { Gitlab::Shell.secret_token }
let(:reference_counter) { double('ReferenceCounter') }
let(:push_options) { ['ci.skip', 'another push option'] }
let(:changes) do
"#{Gitlab::Git::BLANK_SHA} 570e7b2abdd848b95f2f578043fc23bd6f6fd24d refs/heads/#{branch_name}"
end
let(:params) do
{
gl_repository: gl_repository,
secret_token: secret_token,
identifier: identifier,
changes: changes,
push_options: push_options
}
end
let(:response) { PostReceiveService.new(user, project, params).execute }
subject { response.messages.as_json }
it 'enqueues a PostReceive worker job' do
expect(PostReceive).to receive(:perform_async)
.with(gl_repository, identifier, changes, { ci: { skip: true } })
subject
end
it 'decreases the reference counter and returns the result' do
expect(Gitlab::ReferenceCounter).to receive(:new).with(gl_repository)
.and_return(reference_counter)
expect(reference_counter).to receive(:decrease).and_return(true)
expect(response.reference_counter_decreased).to be(true)
end
it 'returns link to create new merge request' do
message = <<~MESSAGE.strip
To create a merge request for #{branch_name}, visit:
http://#{Gitlab.config.gitlab.host}/#{project.full_path}/-/merge_requests/new?merge_request%5Bsource_branch%5D=#{branch_name}
MESSAGE
expect(subject).to include(build_basic_message(message))
end
it 'returns the link to an existing merge request when it exists' do
merge_request = create(:merge_request, source_project: project, source_branch: branch_name, target_branch: 'master')
message = <<~MESSAGE.strip
View merge request for feature:
#{project_merge_request_url(project, merge_request)}
MESSAGE
expect(subject).to include(build_basic_message(message))
end
context 'when printing_merge_request_link_enabled is false' do
let(:project) { create(:project, printing_merge_request_link_enabled: false) }
it 'returns no merge request messages' do
expect(subject).to be_blank
end
end
it 'does not invoke MergeRequests::PushOptionsHandlerService' do
expect(MergeRequests::PushOptionsHandlerService).not_to receive(:new)
subject
end
context 'when there are merge_request push options' do
let(:params) { super().merge(push_options: ['merge_request.create']) }
before do
project.add_developer(user)
end
it 'invokes MergeRequests::PushOptionsHandlerService' do
expect(MergeRequests::PushOptionsHandlerService).to receive(:new).and_call_original
subject
end
it 'creates a new merge request' do
expect { Sidekiq::Testing.fake! { subject } }.to change(MergeRequest, :count).by(1)
end
it 'links to the newly created merge request' do
message = <<~MESSAGE.strip
View merge request for #{branch_name}:
http://#{Gitlab.config.gitlab.host}/#{project.full_path}/-/merge_requests/1
MESSAGE
expect(subject).to include(build_basic_message(message))
end
it 'adds errors on the service instance to warnings' do
expect_any_instance_of(
MergeRequests::PushOptionsHandlerService
).to receive(:errors).at_least(:once).and_return(['my error'])
message = "WARNINGS:\nError encountered with push options 'merge_request.create': my error"
expect(subject).to include(build_alert_message(message))
end
it 'adds ActiveRecord errors on invalid MergeRequest records to warnings' do
invalid_merge_request = MergeRequest.new
invalid_merge_request.errors.add(:base, 'my error')
message = "WARNINGS:\nError encountered with push options 'merge_request.create': my error"
expect_any_instance_of(
MergeRequests::CreateService
).to receive(:execute).and_return(invalid_merge_request)
expect(subject).to include(build_alert_message(message))
end
end
context 'broadcast message exists' do
it 'outputs a broadcast message' do
broadcast_message = create(:broadcast_message, starts_at: 1.day.ago, ends_at: 1.day.from_now)
expect(subject).to include(build_alert_message(broadcast_message.message))
end
end
context 'broadcast message does not exist' do
it 'does not output a broadcast message' do
expect(has_alert_messages?(subject)).to be_falsey
end
end
context 'nil broadcast message' do
it 'does not output a broadcast message' do
allow(BroadcastMessage).to receive(:current).and_return(nil)
expect(has_alert_messages?(subject)).to be_falsey
end
end
context 'with a redirected data' do
it 'returns redirected message on the response' do
project_moved = Gitlab::Checks::ProjectMoved.new(project, user, 'http', 'foo/baz')
project_moved.add_message
expect(subject).to include(build_basic_message(project_moved.message))
end
end
context 'with new project data' do
it 'returns new project message on the response' do
project_created = Gitlab::Checks::ProjectCreated.new(project, user, 'http')
project_created.add_message
expect(subject).to include(build_basic_message(project_created.message))
end
end
def build_alert_message(message)
{ 'type' => 'alert', 'message' => message }
end
def build_basic_message(message)
{ 'type' => 'basic', 'message' => message }
end
def has_alert_messages?(messages)
messages.any? do |message|
message['type'] == 'alert'
end
end
end
...@@ -26,16 +26,18 @@ shared_examples 'resource notes mentions migration' do |migration_class, resourc ...@@ -26,16 +26,18 @@ shared_examples 'resource notes mentions migration' do |migration_class, resourc
note1.becomes(Note).save! note1.becomes(Note).save!
note2.becomes(Note).save! note2.becomes(Note).save!
note3.becomes(Note).save! note3.becomes(Note).save!
# note4.becomes(Note).save(validate: false) note4.becomes(Note).save!
note5.becomes(Note).save(validate: false)
end end
it 'migrates mentions from note' do it 'migrates mentions from note' do
join = migration_class::JOIN join = migration_class::JOIN
conditions = migration_class::QUERY_CONDITIONS conditions = migration_class::QUERY_CONDITIONS
# there are 4 notes for each noteable_type, but one does not have mentions and # there are 5 notes for each noteable_type, but two do not have mentions and
# another one's noteable_id points to an inexistent resource # another one's noteable_id points to an inexistent resource
expect(notes.where(noteable_type: resource_class.to_s).count).to eq 4 expect(notes.where(noteable_type: resource_class.to_s).count).to eq 5
expect(user_mentions.count).to eq 0
expect do expect do
subject.perform(resource_class.name, join, conditions, true, Note.minimum(:id), Note.maximum(:id)) subject.perform(resource_class.name, join, conditions, true, Note.minimum(:id), Note.maximum(:id))
... ...
......