From 7f7c3e1a8aeba5d21c332c8cacdf8af9067199c4 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Wed, 14 Sep 2016 19:23:04 +0800 Subject: [PATCH 001/175] Add notification tests for it --- ...send_pipeline_notification_service_spec.rb | 67 +++++++++++++++++-- 1 file changed, 61 insertions(+), 6 deletions(-) diff --git a/spec/services/ci/send_pipeline_notification_service_spec.rb b/spec/services/ci/send_pipeline_notification_service_spec.rb index 288302cc94f..9c840967aed 100644 --- a/spec/services/ci/send_pipeline_notification_service_spec.rb +++ b/spec/services/ci/send_pipeline_notification_service_spec.rb @@ -11,23 +11,30 @@ describe Ci::SendPipelineNotificationService, services: true do let(:project) { create(:project) } let(:user) { create(:user) } - - subject{ described_class.new(pipeline) } + let(:pusher) { user } + let(:watcher) { pusher } describe '#execute' do before do reset_delivered_emails! + pipeline.project.team << [watcher, Gitlab::Access::DEVELOPER] end shared_examples 'sending emails' do - it 'sends an email to pipeline user' do + it 'sends emails' do perform_enqueued_jobs do subject.execute([user.email]) end - email = ActionMailer::Base.deliveries.last - expect(email.subject).to include(email_subject) - expect(email.to).to eq([user.email]) + expected_receivers = [pusher, watcher].uniq.sort_by(&:email) + actual = ActionMailer::Base.deliveries.sort_by(&:to) + + expect(expected_receivers.size).to eq(actual.size) + + actual.zip(expected_receivers).each do |(email, receiver)| + expect(email.subject).to include(email_subject) + expect(email.to).to eq([receiver.email]) + end end end @@ -36,6 +43,30 @@ describe Ci::SendPipelineNotificationService, services: true do let(:email_subject) { "Pipeline ##{pipeline.id} has succeeded" } it_behaves_like 'sending emails' + + context 'with pipeline from someone else' do + let(:pusher) { create(:user) } + + context 'with success pipeline notification on' do + let(:watcher) { user } + + before do + watcher.global_notification_setting. + update(level: 'custom', success_pipeline: true) + end + + it_behaves_like 'sending emails' + end + + context 'with success pipeline notification off' do + before do + watcher.global_notification_setting. + update(level: 'custom', success_pipeline: false) + end + + it_behaves_like 'sending emails' + end + end end context 'with failed pipeline' do @@ -43,6 +74,30 @@ describe Ci::SendPipelineNotificationService, services: true do let(:email_subject) { "Pipeline ##{pipeline.id} has failed" } it_behaves_like 'sending emails' + + context 'with pipeline from someone else' do + let(:pusher) { create(:user) } + + context 'with failed pipeline notification on' do + let(:watcher) { user } + + before do + watcher.global_notification_setting. + update(level: 'custom', failed_pipeline: true) + end + + it_behaves_like 'sending emails' + end + + context 'with failed pipeline notification off' do + before do + watcher.global_notification_setting. + update(level: 'custom', failed_pipeline: false) + end + + it_behaves_like 'sending emails' + end + end end end end From 8ea702cfe590e94ea496609f85ba0f23bda2dcce Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Wed, 14 Sep 2016 19:42:16 +0800 Subject: [PATCH 002/175] Revert "Split notification integration into another branch" This reverts commit 1404aa8677969a03ed56e8f8350257f317f576d8. --- app/models/ci/pipeline.rb | 9 +++++++++ app/models/notification_setting.rb | 4 +++- .../ci/send_pipeline_notification_service.rb | 10 ++-------- app/services/notification_service.rb | 16 ++++++++++++++++ .../send_pipeline_notification_service_spec.rb | 2 +- 5 files changed, 31 insertions(+), 10 deletions(-) diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 4fdb5fef4fb..c293096f5c9 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -82,6 +82,10 @@ module Ci PipelineHooksWorker.perform_async(id) end end + + after_transition any => [:success, :failed] do |pipeline, transition| + SendPipelineNotificationService.new(pipeline).execute + end end # ref can't be HEAD or SHA, can only be branch/tag name @@ -110,6 +114,11 @@ module Ci project.id end + # For now the only user who participants is the user who triggered + def participants(current_user = nil) + [user] + end + def valid_commit_sha if self.sha == Gitlab::Git::BLANK_SHA self.errors.add(:sha, " cant be 00000000 (branch removal)") diff --git a/app/models/notification_setting.rb b/app/models/notification_setting.rb index 121b598b8f3..43fc218de2b 100644 --- a/app/models/notification_setting.rb +++ b/app/models/notification_setting.rb @@ -32,7 +32,9 @@ class NotificationSetting < ActiveRecord::Base :reopen_merge_request, :close_merge_request, :reassign_merge_request, - :merge_merge_request + :merge_merge_request, + :failed_pipeline, + :success_pipeline ] store :events, accessors: EMAIL_EVENTS, coder: JSON diff --git a/app/services/ci/send_pipeline_notification_service.rb b/app/services/ci/send_pipeline_notification_service.rb index ceb182801f7..cfbcad5dadf 100644 --- a/app/services/ci/send_pipeline_notification_service.rb +++ b/app/services/ci/send_pipeline_notification_service.rb @@ -6,14 +6,8 @@ module Ci @pipeline = new_pipeline end - def execute(recipients) - email_template = "pipeline_#{pipeline.status}_email" - - return unless Notify.respond_to?(email_template) - - recipients.each do |to| - Notify.public_send(email_template, pipeline, to).deliver_later - end + def execute(recipients = nil) + notification_service.pipeline_finished(pipeline, recipients) end end end diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index 72712afc07e..65091c2b8af 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -312,6 +312,22 @@ class NotificationService mailer.project_was_not_exported_email(current_user, project, errors).deliver_later end + def pipeline_finished(pipeline, recipients = nil) + email_template = "pipeline_#{pipeline.status}_email" + + return unless mailer.respond_to?(email_template) + + recipients ||= build_recipients( + pipeline, + pipeline.project, + nil, # The acting user, who won't be added to recipients + action: pipeline.status) + + recipients.each do |to| + mailer.public_send(email_template, pipeline, to.email).deliver_later + end + end + protected # Get project/group users with CUSTOM notification level diff --git a/spec/services/ci/send_pipeline_notification_service_spec.rb b/spec/services/ci/send_pipeline_notification_service_spec.rb index 9c840967aed..110e16410c5 100644 --- a/spec/services/ci/send_pipeline_notification_service_spec.rb +++ b/spec/services/ci/send_pipeline_notification_service_spec.rb @@ -23,7 +23,7 @@ describe Ci::SendPipelineNotificationService, services: true do shared_examples 'sending emails' do it 'sends emails' do perform_enqueued_jobs do - subject.execute([user.email]) + subject.execute end expected_receivers = [pusher, watcher].uniq.sort_by(&:email) From 1c38dbcadc23485ce1421f10d6062fb00221e0e1 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Wed, 14 Sep 2016 19:45:18 +0800 Subject: [PATCH 003/175] Revert "Revert this until we do notifications" This reverts commit c5e0305d5fe150acd74a66efa46e3ee741642978. --- app/services/notification_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index 65091c2b8af..4fef2395c6f 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -640,6 +640,6 @@ class NotificationService # Build event key to search on custom notification level # Check NotificationSetting::EMAIL_EVENTS def build_custom_key(action, object) - "#{action}_#{object.class.name.underscore}".to_sym + "#{action}_#{object.class.model_name.name.underscore}".to_sym end end From 691ed8aca410e8025582579cfa8454b1e54acb12 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Wed, 14 Sep 2016 20:00:36 +0800 Subject: [PATCH 004/175] recipients should be a list of emails --- app/services/notification_service.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index 4fef2395c6f..d4976aa8362 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -321,10 +321,10 @@ class NotificationService pipeline, pipeline.project, nil, # The acting user, who won't be added to recipients - action: pipeline.status) + action: pipeline.status).map(&:email) recipients.each do |to| - mailer.public_send(email_template, pipeline, to.email).deliver_later + mailer.public_send(email_template, pipeline, to).deliver_later end end From f049bdeb9dc08f52671e5919c83a6cf55865b246 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Wed, 14 Sep 2016 21:40:19 +0800 Subject: [PATCH 005/175] Add CHANGELOG entry [ci skip] --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bcaf62ac0aa..dad5df73203 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -246,6 +246,7 @@ Please view this file on the master branch, on stable branches it's out of date. - Set path for all JavaScript cookies to honor GitLab's subdirectory setting !5627 (Mike Greiling) - Fix blame table layout width - Spec testing if issue authors can read issues on private projects + - Add CI notifications. Who triggered a pipeline would receive an email after the pipeline is succeeded or failed. Users could also update notification settings accordingly. !6342 - Fix bug where pagination is still displayed despite all todos marked as done (ClemMakesApps) - Request only the LDAP attributes we need !6187 - Center build stage columns in pipeline overview (ClemMakesApps) From 9c2d40649e0792652c3d41d3c19f2e45c0db5b03 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Wed, 14 Sep 2016 21:43:52 +0800 Subject: [PATCH 006/175] Remove pusher support because it's covered by notifications --- .../project_services/pipelines_email_service.rb | 14 ++------------ .../pipeline_email_service_spec.rb | 8 -------- 2 files changed, 2 insertions(+), 20 deletions(-) diff --git a/app/models/project_services/pipelines_email_service.rb b/app/models/project_services/pipelines_email_service.rb index ec3c1bc85ee..b4e36a7c3de 100644 --- a/app/models/project_services/pipelines_email_service.rb +++ b/app/models/project_services/pipelines_email_service.rb @@ -1,10 +1,9 @@ class PipelinesEmailService < Service prop_accessor :recipients - boolean_accessor :add_pusher boolean_accessor :notify_only_broken_pipelines validates :recipients, presence: true, - if: ->(s) { s.activated? && !s.add_pusher? } + if: ->(s) { s.activated? } def initialize_properties self.properties ||= { notify_only_broken_pipelines: true } @@ -57,9 +56,6 @@ class PipelinesEmailService < Service { type: 'textarea', name: 'recipients', placeholder: 'Emails separated by comma' }, - { type: 'checkbox', - name: 'add_pusher', - label: 'Add pusher to recipients list' }, { type: 'checkbox', name: 'notify_only_broken_pipelines' }, ] @@ -85,12 +81,6 @@ class PipelinesEmailService < Service end def retrieve_recipients(data) - all_recipients = recipients.to_s.split(',').reject(&:blank?) - - if add_pusher? && data[:user].try(:[], :email) - all_recipients << data[:user][:email] - end - - all_recipients + recipients.to_s.split(',').reject(&:blank?) end end diff --git a/spec/models/project_services/pipeline_email_service_spec.rb b/spec/models/project_services/pipeline_email_service_spec.rb index 1368a2925e8..68a96b9251f 100644 --- a/spec/models/project_services/pipeline_email_service_spec.rb +++ b/spec/models/project_services/pipeline_email_service_spec.rb @@ -23,14 +23,6 @@ describe PipelinesEmailService do end it { is_expected.to validate_presence_of(:recipients) } - - context 'when pusher is added' do - before do - subject.add_pusher = true - end - - it { is_expected.not_to validate_presence_of(:recipients) } - end end context 'when service is inactive' do From 811de6ac73ea68ae3361ec49d2094d4f2006f493 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Wed, 14 Sep 2016 21:57:04 +0800 Subject: [PATCH 007/175] Add test for sending pipeline notifications --- spec/models/ci/pipeline_spec.rb | 54 +++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index 550a890797e..f564a2d4fdd 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -523,4 +523,58 @@ describe Ci::Pipeline, models: true do expect(pipeline.merge_requests).to be_empty end end + + describe 'notifications when pipeline success or failed' do + before do + ActionMailer::Base.deliveries.clear + + pipeline.enqueue + pipeline.run + end + + shared_examples 'sending a notification' do + it 'sends an email' do + sent_to = ActionMailer::Base.deliveries.flat_map(&:to) + expect(sent_to).to contain_exactly(pipeline.user.email) + end + end + + shared_examples 'not sending any notification' do + it 'does not send any email' do + expect(ActionMailer::Base.deliveries).to be_empty + end + end + + context 'with success pipeline' do + before do + perform_enqueued_jobs do + pipeline.success + end + end + end + + context 'with failed pipeline' do + before do + perform_enqueued_jobs do + pipeline.drop + end + end + end + + context 'with skipped pipeline' do + before do + perform_enqueued_jobs do + pipeline.skip + end + end + end + + context 'with cancelled pipeline' do + before do + perform_enqueued_jobs do + pipeline.cancel + end + end + end + end end From aafd42c49d516d301d72a4f43d7e56d7bf168d80 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Wed, 14 Sep 2016 22:12:31 +0800 Subject: [PATCH 008/175] How could I forget this? --- spec/models/ci/pipeline_spec.rb | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index f564a2d4fdd..dc1d1de12a1 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -528,6 +528,7 @@ describe Ci::Pipeline, models: true do before do ActionMailer::Base.deliveries.clear + pipeline.update(user: create(:user)) pipeline.enqueue pipeline.run end @@ -548,9 +549,11 @@ describe Ci::Pipeline, models: true do context 'with success pipeline' do before do perform_enqueued_jobs do - pipeline.success + pipeline.succeed end end + + it_behaves_like 'sending a notification' end context 'with failed pipeline' do @@ -559,6 +562,8 @@ describe Ci::Pipeline, models: true do pipeline.drop end end + + it_behaves_like 'sending a notification' end context 'with skipped pipeline' do @@ -567,6 +572,8 @@ describe Ci::Pipeline, models: true do pipeline.skip end end + + it_behaves_like 'not sending any notification' end context 'with cancelled pipeline' do @@ -575,6 +582,8 @@ describe Ci::Pipeline, models: true do pipeline.cancel end end + + it_behaves_like 'not sending any notification' end end end From 55f2e6ab21d4e23675fd3b1e9f5e0a5d59ea3976 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Thu, 15 Sep 2016 00:03:10 +0800 Subject: [PATCH 009/175] We're using BaseService --- app/services/ci/send_pipeline_notification_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/services/ci/send_pipeline_notification_service.rb b/app/services/ci/send_pipeline_notification_service.rb index cfbcad5dadf..d330fa1a73c 100644 --- a/app/services/ci/send_pipeline_notification_service.rb +++ b/app/services/ci/send_pipeline_notification_service.rb @@ -1,5 +1,5 @@ module Ci - class SendPipelineNotificationService + class SendPipelineNotificationService < BaseService attr_reader :pipeline def initialize(new_pipeline) From bac500fdeb3ac9b29c26fd8b48a0b1974c894413 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Mon, 19 Sep 2016 13:44:36 +0800 Subject: [PATCH 010/175] It no longer needs a block, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6342#note_15434727 --- app/models/project_services/pipelines_email_service.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/models/project_services/pipelines_email_service.rb b/app/models/project_services/pipelines_email_service.rb index b4e36a7c3de..ec27aa88f16 100644 --- a/app/models/project_services/pipelines_email_service.rb +++ b/app/models/project_services/pipelines_email_service.rb @@ -1,9 +1,7 @@ class PipelinesEmailService < Service prop_accessor :recipients boolean_accessor :notify_only_broken_pipelines - validates :recipients, - presence: true, - if: ->(s) { s.activated? } + validates :recipients, presence: true, if: :activated? def initialize_properties self.properties ||= { notify_only_broken_pipelines: true } From d39b1959d80f857e57fe67696c8d4525cb5966d9 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Mon, 19 Sep 2016 13:47:11 +0800 Subject: [PATCH 011/175] Prefer methods from EmailHelpers, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6342/diffs#note_15434869 --- spec/models/ci/pipeline_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index dc1d1de12a1..03dd8867b18 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -526,7 +526,7 @@ describe Ci::Pipeline, models: true do describe 'notifications when pipeline success or failed' do before do - ActionMailer::Base.deliveries.clear + reset_delivered_emails! pipeline.update(user: create(:user)) pipeline.enqueue From 572585665f838584b9547831528f26fb60df8d0f Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Mon, 19 Sep 2016 13:54:16 +0800 Subject: [PATCH 012/175] Use EmailHelpers where possible, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6342#note_15434860 --- spec/models/ci/pipeline_spec.rb | 5 ++--- spec/support/email_helpers.rb | 6 +++++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index 03dd8867b18..050ab50f84f 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -535,14 +535,13 @@ describe Ci::Pipeline, models: true do shared_examples 'sending a notification' do it 'sends an email' do - sent_to = ActionMailer::Base.deliveries.flat_map(&:to) - expect(sent_to).to contain_exactly(pipeline.user.email) + should_only_email(pipeline.user) end end shared_examples 'not sending any notification' do it 'does not send any email' do - expect(ActionMailer::Base.deliveries).to be_empty + should_email_no_one end end diff --git a/spec/support/email_helpers.rb b/spec/support/email_helpers.rb index 0bfc4685532..dfb252544e7 100644 --- a/spec/support/email_helpers.rb +++ b/spec/support/email_helpers.rb @@ -1,6 +1,6 @@ module EmailHelpers def sent_to_user?(user) - ActionMailer::Base.deliveries.map(&:to).flatten.count(user.email) == 1 + ActionMailer::Base.deliveries.flat_map(&:to).count(user.email) == 1 end def reset_delivered_emails! @@ -20,4 +20,8 @@ module EmailHelpers def should_not_email(user) expect(sent_to_user?(user)).to be_falsey end + + def should_email_no_one + expect(ActionMailer::Base.deliveries).to be_empty + end end From 230bae9d48505ac59bfdc61ae739192416d18e92 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Mon, 19 Sep 2016 13:57:55 +0800 Subject: [PATCH 013/175] Update the other sites for reset_delivered_emails! as well --- spec/mailers/shared/notify.rb | 2 +- .../pipeline_email_service_spec.rb | 2 +- spec/services/notification_service_spec.rb | 28 +++++++++---------- spec/workers/build_email_worker_spec.rb | 2 +- spec/workers/emails_on_push_worker_spec.rb | 4 +-- 5 files changed, 19 insertions(+), 19 deletions(-) diff --git a/spec/mailers/shared/notify.rb b/spec/mailers/shared/notify.rb index 3956d05060b..49867aa5cc4 100644 --- a/spec/mailers/shared/notify.rb +++ b/spec/mailers/shared/notify.rb @@ -7,7 +7,7 @@ shared_context 'gitlab email notification' do let(:new_user_address) { 'newguy@example.com' } before do - ActionMailer::Base.deliveries.clear + reset_delivered_emails! email = recipient.emails.create(email: "notifications@example.com") recipient.update_attribute(:notification_email, email.email) stub_incoming_email_setting(enabled: true, address: "reply+%{key}@#{Gitlab.config.gitlab.host}") diff --git a/spec/models/project_services/pipeline_email_service_spec.rb b/spec/models/project_services/pipeline_email_service_spec.rb index 68a96b9251f..e2d8eaf6a1f 100644 --- a/spec/models/project_services/pipeline_email_service_spec.rb +++ b/spec/models/project_services/pipeline_email_service_spec.rb @@ -13,7 +13,7 @@ describe PipelinesEmailService do end before do - ActionMailer::Base.deliveries.clear + reset_delivered_emails! end describe 'Validations' do diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb index 699b9925b4e..84c22631c67 100644 --- a/spec/services/notification_service_spec.rb +++ b/spec/services/notification_service_spec.rb @@ -17,7 +17,7 @@ describe NotificationService, services: true do it 'sends no emails when no new mentions are present' do send_notifications - expect(ActionMailer::Base.deliveries).to be_empty + should_email_no_one end it 'emails new mentions with a watch level higher than participant' do @@ -27,7 +27,7 @@ describe NotificationService, services: true do it 'does not email new mentions with a watch level equal to or less than participant' do send_notifications(@u_participating, @u_mentioned) - expect(ActionMailer::Base.deliveries).to be_empty + should_email_no_one end end @@ -79,7 +79,7 @@ describe NotificationService, services: true do # Ensure create SentNotification by noteable = issue 6 times, not noteable = note expect(SentNotification).to receive(:record).with(issue, any_args).exactly(8).times - ActionMailer::Base.deliveries.clear + reset_delivered_emails! notification.new_note(note) @@ -111,7 +111,7 @@ describe NotificationService, services: true do context 'participating' do context 'by note' do before do - ActionMailer::Base.deliveries.clear + reset_delivered_emails! note.author = @u_lazy_participant note.save notification.new_note(note) @@ -134,7 +134,7 @@ describe NotificationService, services: true do @u_watcher.notification_settings_for(note.project).participating! @u_watcher.notification_settings_for(note.project.group).global! update_custom_notification(:new_note, @u_custom_global) - ActionMailer::Base.deliveries.clear + reset_delivered_emails! end it do @@ -173,7 +173,7 @@ describe NotificationService, services: true do expect(SentNotification).to receive(:record).with(confidential_issue, any_args).exactly(4).times - ActionMailer::Base.deliveries.clear + reset_delivered_emails! notification.new_note(note) @@ -196,7 +196,7 @@ describe NotificationService, services: true do before do build_team(note.project) note.project.team << [note.author, :master] - ActionMailer::Base.deliveries.clear + reset_delivered_emails! end describe '#new_note' do @@ -238,7 +238,7 @@ describe NotificationService, services: true do before do build_team(note.project) note.project.team << [note.author, :master] - ActionMailer::Base.deliveries.clear + reset_delivered_emails! end describe '#new_note' do @@ -273,7 +273,7 @@ describe NotificationService, services: true do before do build_team(note.project) - ActionMailer::Base.deliveries.clear + reset_delivered_emails! allow_any_instance_of(Commit).to receive(:author).and_return(@u_committer) update_custom_notification(:new_note, @u_guest_custom, project) update_custom_notification(:new_note, @u_custom_global) @@ -348,7 +348,7 @@ describe NotificationService, services: true do before do build_team(issue.project) add_users_with_subscription(issue.project, issue) - ActionMailer::Base.deliveries.clear + reset_delivered_emails! update_custom_notification(:new_issue, @u_guest_custom, project) update_custom_notification(:new_issue, @u_custom_global) end @@ -408,7 +408,7 @@ describe NotificationService, services: true do label.toggle_subscription(guest) label.toggle_subscription(admin) - ActionMailer::Base.deliveries.clear + reset_delivered_emails! notification.new_issue(confidential_issue, @u_disabled) @@ -604,7 +604,7 @@ describe NotificationService, services: true do label_2.toggle_subscription(guest) label_2.toggle_subscription(admin) - ActionMailer::Base.deliveries.clear + reset_delivered_emails! notification.relabeled_issue(confidential_issue, [label_2], @u_disabled) @@ -733,7 +733,7 @@ describe NotificationService, services: true do add_users_with_subscription(merge_request.target_project, merge_request) update_custom_notification(:new_merge_request, @u_guest_custom, project) update_custom_notification(:new_merge_request, @u_custom_global) - ActionMailer::Base.deliveries.clear + reset_delivered_emails! end describe '#new_merge_request' do @@ -1111,7 +1111,7 @@ describe NotificationService, services: true do before do build_team(project) - ActionMailer::Base.deliveries.clear + reset_delivered_emails! end describe '#project_was_moved' do diff --git a/spec/workers/build_email_worker_spec.rb b/spec/workers/build_email_worker_spec.rb index 788b92c1b84..a1aa336361a 100644 --- a/spec/workers/build_email_worker_spec.rb +++ b/spec/workers/build_email_worker_spec.rb @@ -24,7 +24,7 @@ describe BuildEmailWorker do end it "gracefully handles an input SMTP error" do - ActionMailer::Base.deliveries.clear + reset_delivered_emails! allow(Notify).to receive(:build_success_email).and_raise(Net::SMTPFatalError) subject.perform(build.id, [user.email], data.stringify_keys) diff --git a/spec/workers/emails_on_push_worker_spec.rb b/spec/workers/emails_on_push_worker_spec.rb index 036d037f3f9..fc652f6f4c3 100644 --- a/spec/workers/emails_on_push_worker_spec.rb +++ b/spec/workers/emails_on_push_worker_spec.rb @@ -87,7 +87,7 @@ describe EmailsOnPushWorker do context "when there is an SMTP error" do before do - ActionMailer::Base.deliveries.clear + reset_delivered_emails! allow(Notify).to receive(:repository_push_email).and_raise(Net::SMTPFatalError) allow(subject).to receive_message_chain(:logger, :info) perform @@ -112,7 +112,7 @@ describe EmailsOnPushWorker do original.call(Mail.new(mail.encoded)) end - ActionMailer::Base.deliveries.clear + reset_delivered_emails! end it "sends the mail to each of the recipients" do From beb47c257a6673addb44fc6573c176f6be6cbd1b Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Mon, 19 Sep 2016 14:01:58 +0800 Subject: [PATCH 014/175] Try to slightly optimize EmailHeleprs --- spec/support/email_helpers.rb | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/spec/support/email_helpers.rb b/spec/support/email_helpers.rb index dfb252544e7..2931967de35 100644 --- a/spec/support/email_helpers.rb +++ b/spec/support/email_helpers.rb @@ -1,6 +1,8 @@ module EmailHelpers - def sent_to_user?(user) - ActionMailer::Base.deliveries.flat_map(&:to).count(user.email) == 1 + def sent_to_user?(user, recipients = nil) + recipients ||= ActionMailer::Base.deliveries.flat_map(&:to) + + recipients.count(user.email) == 1 end def reset_delivered_emails! @@ -8,17 +10,19 @@ module EmailHelpers end def should_only_email(*users) - users.each {|user| should_email(user) } recipients = ActionMailer::Base.deliveries.flat_map(&:to) + + users.each { |user| should_email(user, recipients) } + expect(recipients.count).to eq(users.count) end - def should_email(user) - expect(sent_to_user?(user)).to be_truthy + def should_email(user, recipients = nil) + expect(sent_to_user?(user, recipients)).to be_truthy end - def should_not_email(user) - expect(sent_to_user?(user)).to be_falsey + def should_not_email(user, recipients = nil) + expect(sent_to_user?(user, recipients)).to be_falsey end def should_email_no_one From 612820b2964e77397b6d85f74eb96888b72c4cbd Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Mon, 26 Sep 2016 19:04:02 +0800 Subject: [PATCH 015/175] Fix test by having a real commit --- spec/models/ci/pipeline_spec.rb | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index 050ab50f84f..787042cf055 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -525,10 +525,18 @@ describe Ci::Pipeline, models: true do end describe 'notifications when pipeline success or failed' do + let(:project) { create(:project) } + + let(:pipeline) do + create(:ci_pipeline, + project: project, + sha: project.commit('master').sha, + user: create(:user)) + end + before do reset_delivered_emails! - pipeline.update(user: create(:user)) pipeline.enqueue pipeline.run end From 56562d26dd1346d8db4fc673d711b3b6a77851cd Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Wed, 28 Sep 2016 15:27:11 +0800 Subject: [PATCH 016/175] Fix spelling, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6342#note_16074432 --- app/models/ci/pipeline.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index c293096f5c9..fd50abe1c36 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -114,7 +114,7 @@ module Ci project.id end - # For now the only user who participants is the user who triggered + # For now the only user who participates is the user who triggered def participants(current_user = nil) [user] end From 12a6bbc36a85fce8e4025470ea559a2830617eb9 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Wed, 28 Sep 2016 15:28:01 +0800 Subject: [PATCH 017/175] Prefix _ to show that it's intended unused, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6342#note_16073734 --- app/models/ci/pipeline.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index fd50abe1c36..61bb89a0a23 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -115,7 +115,7 @@ module Ci end # For now the only user who participates is the user who triggered - def participants(current_user = nil) + def participants(_current_user = nil) [user] end From 9622ef64e41058b8dec97c98f568d8fdea95fd61 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Wed, 28 Sep 2016 15:39:54 +0800 Subject: [PATCH 018/175] Introduce email_recipients and use include? Feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6342#note_16075554 https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6342#note_16075622 --- spec/support/email_helpers.rb | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/spec/support/email_helpers.rb b/spec/support/email_helpers.rb index 2931967de35..caa6ab1345a 100644 --- a/spec/support/email_helpers.rb +++ b/spec/support/email_helpers.rb @@ -1,8 +1,6 @@ module EmailHelpers - def sent_to_user?(user, recipients = nil) - recipients ||= ActionMailer::Base.deliveries.flat_map(&:to) - - recipients.count(user.email) == 1 + def sent_to_user?(user, recipients = email_recipients) + recipients.include?(user.email) end def reset_delivered_emails! @@ -10,22 +8,26 @@ module EmailHelpers end def should_only_email(*users) - recipients = ActionMailer::Base.deliveries.flat_map(&:to) + recipients = email_recipients users.each { |user| should_email(user, recipients) } expect(recipients.count).to eq(users.count) end - def should_email(user, recipients = nil) + def should_email(user, recipients = email_recipients) expect(sent_to_user?(user, recipients)).to be_truthy end - def should_not_email(user, recipients = nil) + def should_not_email(user, recipients = email_recipients) expect(sent_to_user?(user, recipients)).to be_falsey end def should_email_no_one expect(ActionMailer::Base.deliveries).to be_empty end + + def email_recipients + ActionMailer::Base.deliveries.flat_map(&:to) + end end From eeeb96c9d0cab9c5da850809a9614e2a01fdb7d2 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Wed, 28 Sep 2016 17:22:06 +0800 Subject: [PATCH 019/175] Change service to be a worker, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6342#note_16118195 --- app/models/ci/pipeline.rb | 4 ++-- .../project_services/pipelines_email_service.rb | 4 ++-- .../ci/send_pipeline_notification_service.rb | 13 ------------- app/workers/send_pipeline_notification_worker.rb | 9 +++++++++ spec/models/ci/pipeline_spec.rb | 6 ++++-- .../send_pipeline_notification_worker_spec.rb} | 4 ++-- 6 files changed, 19 insertions(+), 21 deletions(-) delete mode 100644 app/services/ci/send_pipeline_notification_service.rb create mode 100644 app/workers/send_pipeline_notification_worker.rb rename spec/{services/ci/send_pipeline_notification_service_spec.rb => workers/send_pipeline_notification_worker_spec.rb} (96%) diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 61bb89a0a23..d534fdc0560 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -83,8 +83,8 @@ module Ci end end - after_transition any => [:success, :failed] do |pipeline, transition| - SendPipelineNotificationService.new(pipeline).execute + after_transition any => [:success, :failed] do |pipeline| + SendPipelineNotificationWorker.perform_async(pipeline.id) end end diff --git a/app/models/project_services/pipelines_email_service.rb b/app/models/project_services/pipelines_email_service.rb index ec27aa88f16..4cebb9e7f93 100644 --- a/app/models/project_services/pipelines_email_service.rb +++ b/app/models/project_services/pipelines_email_service.rb @@ -31,8 +31,8 @@ class PipelinesEmailService < Service return unless all_recipients.any? - pipeline = Ci::Pipeline.find(data[:object_attributes][:id]) - Ci::SendPipelineNotificationService.new(pipeline).execute(all_recipients) + pipeline_id = data[:object_attributes][:id] + SendPipelineNotificationWorker.perform_async(pipeline_id, all_recipients) end def can_test? diff --git a/app/services/ci/send_pipeline_notification_service.rb b/app/services/ci/send_pipeline_notification_service.rb deleted file mode 100644 index d330fa1a73c..00000000000 --- a/app/services/ci/send_pipeline_notification_service.rb +++ /dev/null @@ -1,13 +0,0 @@ -module Ci - class SendPipelineNotificationService < BaseService - attr_reader :pipeline - - def initialize(new_pipeline) - @pipeline = new_pipeline - end - - def execute(recipients = nil) - notification_service.pipeline_finished(pipeline, recipients) - end - end -end diff --git a/app/workers/send_pipeline_notification_worker.rb b/app/workers/send_pipeline_notification_worker.rb new file mode 100644 index 00000000000..d4837d815a5 --- /dev/null +++ b/app/workers/send_pipeline_notification_worker.rb @@ -0,0 +1,9 @@ +class SendPipelineNotificationWorker + include Sidekiq::Worker + + def perform(pipeline_id, recipients = nil) + pipeline = Ci::Pipeline.find(pipeline_id) + + NotificationService.new.pipeline_finished(pipeline, recipients) + end +end diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index 787042cf055..6ea712ae1b3 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -537,8 +537,10 @@ describe Ci::Pipeline, models: true do before do reset_delivered_emails! - pipeline.enqueue - pipeline.run + perform_enqueued_jobs do + pipeline.enqueue + pipeline.run + end end shared_examples 'sending a notification' do diff --git a/spec/services/ci/send_pipeline_notification_service_spec.rb b/spec/workers/send_pipeline_notification_worker_spec.rb similarity index 96% rename from spec/services/ci/send_pipeline_notification_service_spec.rb rename to spec/workers/send_pipeline_notification_worker_spec.rb index 110e16410c5..0670d67501a 100644 --- a/spec/services/ci/send_pipeline_notification_service_spec.rb +++ b/spec/workers/send_pipeline_notification_worker_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe Ci::SendPipelineNotificationService, services: true do +describe SendPipelineNotificationWorker, services: true do let(:pipeline) do create(:ci_pipeline, project: project, @@ -23,7 +23,7 @@ describe Ci::SendPipelineNotificationService, services: true do shared_examples 'sending emails' do it 'sends emails' do perform_enqueued_jobs do - subject.execute + subject.perform(pipeline.id) end expected_receivers = [pusher, watcher].uniq.sort_by(&:email) From c065f5360fb3c89ab66fc2b744243b0eef166355 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Wed, 28 Sep 2016 17:29:53 +0800 Subject: [PATCH 020/175] That's no longer a service [ci skip] --- spec/workers/send_pipeline_notification_worker_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/workers/send_pipeline_notification_worker_spec.rb b/spec/workers/send_pipeline_notification_worker_spec.rb index 0670d67501a..f03231498a2 100644 --- a/spec/workers/send_pipeline_notification_worker_spec.rb +++ b/spec/workers/send_pipeline_notification_worker_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe SendPipelineNotificationWorker, services: true do +describe SendPipelineNotificationWorker do let(:pipeline) do create(:ci_pipeline, project: project, From 8dd580f4022fa01521264cfbd6eaeb92d39430b5 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Fri, 30 Sep 2016 00:12:10 +0800 Subject: [PATCH 021/175] It's already async, from Project#execute_services, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6342/diffs#note_16132555 --- app/models/project_services/pipelines_email_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/project_services/pipelines_email_service.rb b/app/models/project_services/pipelines_email_service.rb index 4cebb9e7f93..e2cb1df81b5 100644 --- a/app/models/project_services/pipelines_email_service.rb +++ b/app/models/project_services/pipelines_email_service.rb @@ -32,7 +32,7 @@ class PipelinesEmailService < Service return unless all_recipients.any? pipeline_id = data[:object_attributes][:id] - SendPipelineNotificationWorker.perform_async(pipeline_id, all_recipients) + SendPipelineNotificationWorker.new.perform(pipeline_id, all_recipients) end def can_test? From 6bab69aa0c0a6383a7eda5d74504939891f30f41 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Fri, 30 Sep 2016 01:15:03 +0800 Subject: [PATCH 022/175] Show it as successful pipeline, rather than success pipeline Feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6342#note_16132150 --- app/helpers/notifications_helper.rb | 9 +++++++++ .../shared/notifications/_custom_notifications.html.haml | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/app/helpers/notifications_helper.rb b/app/helpers/notifications_helper.rb index 7e8369d0a05..03cc8f2b6bd 100644 --- a/app/helpers/notifications_helper.rb +++ b/app/helpers/notifications_helper.rb @@ -74,4 +74,13 @@ module NotificationsHelper return unless notification_setting.source_type hidden_field_tag "#{notification_setting.source_type.downcase}_id", notification_setting.source_id end + + def notification_event_name(event) + case event + when :success_pipeline + 'Successful pipeline' + else + event.to_s.humanize + end + end end diff --git a/app/views/shared/notifications/_custom_notifications.html.haml b/app/views/shared/notifications/_custom_notifications.html.haml index b704981e3db..a82fc95df84 100644 --- a/app/views/shared/notifications/_custom_notifications.html.haml +++ b/app/views/shared/notifications/_custom_notifications.html.haml @@ -27,5 +27,5 @@ %label{ for: field_id } = check_box("notification_setting", event, id: field_id, class: "js-custom-notification-event", checked: notification_setting.events[event]) %strong - = event.to_s.humanize + = notification_event_name(event) = icon("spinner spin", class: "custom-notification-event-loading") From 776877c27deec6d44b1f95f16af5852653d8b946 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Fri, 14 Oct 2016 20:07:14 +0800 Subject: [PATCH 023/175] Pipeline#user could be nil. Feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6342#note_16956937 --- app/models/ci/pipeline.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index d534fdc0560..0ed1c496022 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -116,7 +116,7 @@ module Ci # For now the only user who participates is the user who triggered def participants(_current_user = nil) - [user] + [user].compact end def valid_commit_sha From 0a11d53153d692f8c2b3c5125c5cd5e5042c08b3 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Mon, 17 Oct 2016 18:03:42 +0800 Subject: [PATCH 024/175] Fix test failure due to bad rebase, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6342/diffs#note_17043090 --- spec/workers/send_pipeline_notification_worker_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/workers/send_pipeline_notification_worker_spec.rb b/spec/workers/send_pipeline_notification_worker_spec.rb index f03231498a2..8d358992c7c 100644 --- a/spec/workers/send_pipeline_notification_worker_spec.rb +++ b/spec/workers/send_pipeline_notification_worker_spec.rb @@ -5,7 +5,7 @@ describe SendPipelineNotificationWorker do create(:ci_pipeline, project: project, sha: project.commit('master').sha, - user: user, + user: pusher, status: status) end From 98217bc0674253f30dea3892a8e833436b89d5b9 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Mon, 17 Oct 2016 18:03:53 +0800 Subject: [PATCH 025/175] should_email_no_one -> should_not_email_anyone, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6342/diffs#note_17039876 --- spec/models/ci/pipeline_spec.rb | 2 +- spec/services/notification_service_spec.rb | 4 ++-- spec/support/email_helpers.rb | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index 6ea712ae1b3..85820a9dc57 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -551,7 +551,7 @@ describe Ci::Pipeline, models: true do shared_examples 'not sending any notification' do it 'does not send any email' do - should_email_no_one + should_not_email_anyone end end diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb index 84c22631c67..8ce35354c22 100644 --- a/spec/services/notification_service_spec.rb +++ b/spec/services/notification_service_spec.rb @@ -17,7 +17,7 @@ describe NotificationService, services: true do it 'sends no emails when no new mentions are present' do send_notifications - should_email_no_one + should_not_email_anyone end it 'emails new mentions with a watch level higher than participant' do @@ -27,7 +27,7 @@ describe NotificationService, services: true do it 'does not email new mentions with a watch level equal to or less than participant' do send_notifications(@u_participating, @u_mentioned) - should_email_no_one + should_not_email_anyone end end diff --git a/spec/support/email_helpers.rb b/spec/support/email_helpers.rb index caa6ab1345a..36f5a2d5975 100644 --- a/spec/support/email_helpers.rb +++ b/spec/support/email_helpers.rb @@ -23,7 +23,7 @@ module EmailHelpers expect(sent_to_user?(user, recipients)).to be_falsey end - def should_email_no_one + def should_not_email_anyone expect(ActionMailer::Base.deliveries).to be_empty end From b4e751557ad35d7c5fbed55328892c43a4c84ba5 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Mon, 17 Oct 2016 18:09:43 +0800 Subject: [PATCH 026/175] Use run_after_commit to avoid race condition, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6342/diffs#note_17038749 --- app/models/ci/pipeline.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 0ed1c496022..2a0865abd4b 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -84,7 +84,9 @@ module Ci end after_transition any => [:success, :failed] do |pipeline| - SendPipelineNotificationWorker.perform_async(pipeline.id) + pipeline.run_after_commit do + SendPipelineNotificationWorker.perform_async(pipeline.id) + end end end From 2e067480a9824228542c229a09aa4b6f006dc6f3 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Mon, 17 Oct 2016 18:12:07 +0800 Subject: [PATCH 027/175] Rename for a more consistent pipeline worker name, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6342/diffs#note_17039533 --- app/models/ci/pipeline.rb | 2 +- app/models/project_services/pipelines_email_service.rb | 2 +- ...e_notification_worker.rb => pipeline_notification_worker.rb} | 2 +- ...tion_worker_spec.rb => pipeline_notification_worker_spec.rb} | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) rename app/workers/{send_pipeline_notification_worker.rb => pipeline_notification_worker.rb} (84%) rename spec/workers/{send_pipeline_notification_worker_spec.rb => pipeline_notification_worker_spec.rb} (98%) diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 2a0865abd4b..5604296cba5 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -85,7 +85,7 @@ module Ci after_transition any => [:success, :failed] do |pipeline| pipeline.run_after_commit do - SendPipelineNotificationWorker.perform_async(pipeline.id) + PipelineNotificationWorker.perform_async(pipeline.id) end end end diff --git a/app/models/project_services/pipelines_email_service.rb b/app/models/project_services/pipelines_email_service.rb index e2cb1df81b5..745f9bd1b43 100644 --- a/app/models/project_services/pipelines_email_service.rb +++ b/app/models/project_services/pipelines_email_service.rb @@ -32,7 +32,7 @@ class PipelinesEmailService < Service return unless all_recipients.any? pipeline_id = data[:object_attributes][:id] - SendPipelineNotificationWorker.new.perform(pipeline_id, all_recipients) + PipelineNotificationWorker.new.perform(pipeline_id, all_recipients) end def can_test? diff --git a/app/workers/send_pipeline_notification_worker.rb b/app/workers/pipeline_notification_worker.rb similarity index 84% rename from app/workers/send_pipeline_notification_worker.rb rename to app/workers/pipeline_notification_worker.rb index d4837d815a5..f4e9a4cf245 100644 --- a/app/workers/send_pipeline_notification_worker.rb +++ b/app/workers/pipeline_notification_worker.rb @@ -1,4 +1,4 @@ -class SendPipelineNotificationWorker +class PipelineNotificationWorker include Sidekiq::Worker def perform(pipeline_id, recipients = nil) diff --git a/spec/workers/send_pipeline_notification_worker_spec.rb b/spec/workers/pipeline_notification_worker_spec.rb similarity index 98% rename from spec/workers/send_pipeline_notification_worker_spec.rb rename to spec/workers/pipeline_notification_worker_spec.rb index 8d358992c7c..c641d7a7801 100644 --- a/spec/workers/send_pipeline_notification_worker_spec.rb +++ b/spec/workers/pipeline_notification_worker_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe SendPipelineNotificationWorker do +describe PipelineNotificationWorker do let(:pipeline) do create(:ci_pipeline, project: project, From 7e1b9196c413927e4db5e38c40ee944ef6d29884 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Mon, 17 Oct 2016 18:13:39 +0800 Subject: [PATCH 028/175] Move the entry to 8.13.0, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6342/diffs#note_17039513 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dad5df73203..dd88b348734 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ Please view this file on the master branch, on stable branches it's out of date. - Change user & group landing page routing from /u/:username to /:username - Prevent running GfmAutocomplete setup for each diff note !6569 - Added documentation for .gitattributes files + - Add CI notifications. Who triggered a pipeline would receive an email after the pipeline is succeeded or failed. Users could also update notification settings accordingly. !6342 - AbstractReferenceFilter caches project_refs on RequestStore when active - Replaced the check sign to arrow in the show build view. !6501 - Add a /wip slash command to toggle the Work In Progress status of a merge request. !6259 (tbalthazar) @@ -246,7 +247,6 @@ Please view this file on the master branch, on stable branches it's out of date. - Set path for all JavaScript cookies to honor GitLab's subdirectory setting !5627 (Mike Greiling) - Fix blame table layout width - Spec testing if issue authors can read issues on private projects - - Add CI notifications. Who triggered a pipeline would receive an email after the pipeline is succeeded or failed. Users could also update notification settings accordingly. !6342 - Fix bug where pagination is still displayed despite all todos marked as done (ClemMakesApps) - Request only the LDAP attributes we need !6187 - Center build stage columns in pipeline overview (ClemMakesApps) From 0f21b1313b853d92b722b32ac25b8ad6a4860a63 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Mon, 17 Oct 2016 18:18:16 +0800 Subject: [PATCH 029/175] Skip if cannot find pipeline, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6342/diffs#note_17038807 --- app/workers/pipeline_notification_worker.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/workers/pipeline_notification_worker.rb b/app/workers/pipeline_notification_worker.rb index f4e9a4cf245..68e72f7382f 100644 --- a/app/workers/pipeline_notification_worker.rb +++ b/app/workers/pipeline_notification_worker.rb @@ -2,7 +2,9 @@ class PipelineNotificationWorker include Sidekiq::Worker def perform(pipeline_id, recipients = nil) - pipeline = Ci::Pipeline.find(pipeline_id) + pipeline = Ci::Pipeline.find_by(id: pipeline_id) + + return unless pipeline NotificationService.new.pipeline_finished(pipeline, recipients) end From 12ef494db812de3790ad5f42152f9b3fdf8c9f3c Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Tue, 18 Oct 2016 18:48:02 +0800 Subject: [PATCH 030/175] Use Array rather than compact, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6342#note_17089690 --- app/models/ci/pipeline.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 941b01c29e0..d1c68300067 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -120,7 +120,7 @@ module Ci # For now the only user who participates is the user who triggered def participants(_current_user = nil) - [user].compact + Array(user) end def valid_commit_sha From 045c6715330d25adff95304a3de908037c63a163 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Tue, 18 Oct 2016 20:02:35 +0800 Subject: [PATCH 031/175] Use bcc for pipeline emails because: We use bcc here because we don't want to generate this emails for a thousand times. This could be potentially expensive in a loop, and recipients would contain all project watchers so it could be a lot. --- app/mailers/emails/pipelines.rb | 17 +++++++++++------ app/services/notification_service.rb | 4 +--- spec/models/ci/pipeline_spec.rb | 2 +- spec/support/email_helpers.rb | 8 ++++---- .../pipeline_notification_worker_spec.rb | 14 ++++++-------- 5 files changed, 23 insertions(+), 22 deletions(-) diff --git a/app/mailers/emails/pipelines.rb b/app/mailers/emails/pipelines.rb index 601c8b5cd62..9460a6cd2be 100644 --- a/app/mailers/emails/pipelines.rb +++ b/app/mailers/emails/pipelines.rb @@ -1,22 +1,27 @@ module Emails module Pipelines - def pipeline_success_email(pipeline, to) - pipeline_mail(pipeline, to, 'succeeded') + def pipeline_success_email(pipeline, recipients) + pipeline_mail(pipeline, recipients, 'succeeded') end - def pipeline_failed_email(pipeline, to) - pipeline_mail(pipeline, to, 'failed') + def pipeline_failed_email(pipeline, recipients) + pipeline_mail(pipeline, recipients, 'failed') end private - def pipeline_mail(pipeline, to, status) + def pipeline_mail(pipeline, recipients, status) @project = pipeline.project @pipeline = pipeline @merge_request = pipeline.merge_requests.first add_headers - mail(to: to, subject: pipeline_subject(status), skip_premailer: true) do |format| + # We use bcc here because we don't want to generate this emails for a + # thousand times. This could be potentially expensive in a loop, and + # recipients would contain all project watchers so it could be a lot. + mail(bcc: recipients, + subject: pipeline_subject(status), + skip_premailer: true) do |format| format.html { render layout: false } format.text end diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index d4976aa8362..d5d69248af7 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -323,9 +323,7 @@ class NotificationService nil, # The acting user, who won't be added to recipients action: pipeline.status).map(&:email) - recipients.each do |to| - mailer.public_send(email_template, pipeline, to).deliver_later - end + mailer.public_send(email_template, pipeline, recipients).deliver_later end protected diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index caf191e11ae..4032029b80b 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -536,7 +536,7 @@ describe Ci::Pipeline, models: true do shared_examples 'sending a notification' do it 'sends an email' do - should_only_email(pipeline.user) + should_only_email(pipeline.user, kind: :bcc) end end diff --git a/spec/support/email_helpers.rb b/spec/support/email_helpers.rb index 36f5a2d5975..a946f10f71a 100644 --- a/spec/support/email_helpers.rb +++ b/spec/support/email_helpers.rb @@ -7,8 +7,8 @@ module EmailHelpers ActionMailer::Base.deliveries.clear end - def should_only_email(*users) - recipients = email_recipients + def should_only_email(*users, kind: :to) + recipients = email_recipients(kind: kind) users.each { |user| should_email(user, recipients) } @@ -27,7 +27,7 @@ module EmailHelpers expect(ActionMailer::Base.deliveries).to be_empty end - def email_recipients - ActionMailer::Base.deliveries.flat_map(&:to) + def email_recipients(kind: :to) + ActionMailer::Base.deliveries.flat_map(&kind) end end diff --git a/spec/workers/pipeline_notification_worker_spec.rb b/spec/workers/pipeline_notification_worker_spec.rb index c641d7a7801..c334b2057a6 100644 --- a/spec/workers/pipeline_notification_worker_spec.rb +++ b/spec/workers/pipeline_notification_worker_spec.rb @@ -26,15 +26,13 @@ describe PipelineNotificationWorker do subject.perform(pipeline.id) end - expected_receivers = [pusher, watcher].uniq.sort_by(&:email) - actual = ActionMailer::Base.deliveries.sort_by(&:to) + emails = ActionMailer::Base.deliveries + actual = emails.flat_map(&:bcc).sort + expected_receivers = [pusher, watcher].map(&:email).uniq.sort - expect(expected_receivers.size).to eq(actual.size) - - actual.zip(expected_receivers).each do |(email, receiver)| - expect(email.subject).to include(email_subject) - expect(email.to).to eq([receiver.email]) - end + expect(actual).to eq(expected_receivers) + expect(emails.size).to eq(1) + expect(emails.last.subject).to include(email_subject) end end From cefc7eb15bd7526a7c40fc0a1ca3534c2a12a0ef Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Tue, 18 Oct 2016 20:53:28 +0800 Subject: [PATCH 032/175] Fix test for bcc changes --- spec/models/project_services/pipeline_email_service_spec.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/spec/models/project_services/pipeline_email_service_spec.rb b/spec/models/project_services/pipeline_email_service_spec.rb index e2d8eaf6a1f..57baff3354f 100644 --- a/spec/models/project_services/pipeline_email_service_spec.rb +++ b/spec/models/project_services/pipeline_email_service_spec.rb @@ -58,8 +58,7 @@ describe PipelinesEmailService do end it 'sends email' do - sent_to = ActionMailer::Base.deliveries.flat_map(&:to) - expect(sent_to).to contain_exactly(recipient) + should_only_email(double(email: recipient), kind: :bcc) end end @@ -71,7 +70,7 @@ describe PipelinesEmailService do end it 'does not send email' do - expect(ActionMailer::Base.deliveries).to be_empty + should_not_email_anyone end end From a87b6cc3f550dff2fd4189970a3d2456052987a3 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Thu, 20 Oct 2016 17:15:38 +0800 Subject: [PATCH 033/175] Move CHANGELOG entry --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b65f5842b4..ae990fcc44c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ Please view this file on the master branch, on stable branches it's out of date. ## 8.14.0 (2016-11-22) - Adds user project membership expired event to clarify why user was removed (Callum Dryden) + - Add CI notifications. Who triggered a pipeline would receive an email after the pipeline is succeeded or failed. Users could also update notification settings accordingly. !6342 ## 8.13.0 (2016-10-22) @@ -30,7 +31,6 @@ Please view this file on the master branch, on stable branches it's out of date. - The instrumentation for Banzai::Renderer has been restored - Change user & group landing page routing from /u/:username to /:username - Added documentation for .gitattributes files - - Add CI notifications. Who triggered a pipeline would receive an email after the pipeline is succeeded or failed. Users could also update notification settings accordingly. !6342 - Move Pipeline Metrics to separate worker - AbstractReferenceFilter caches project_refs on RequestStore when active - Replaced the check sign to arrow in the show build view. !6501 From 1cdad622aacf9ae7e7d61e575aaa77dddf7ae7b9 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Thu, 20 Oct 2016 18:13:45 +0800 Subject: [PATCH 034/175] Should send to notification_email instead, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6342#note_17146325 --- app/services/notification_service.rb | 2 +- spec/models/project_services/pipeline_email_service_spec.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index d5d69248af7..2cc9a9fd7bf 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -321,7 +321,7 @@ class NotificationService pipeline, pipeline.project, nil, # The acting user, who won't be added to recipients - action: pipeline.status).map(&:email) + action: pipeline.status).map(&:notification_email) mailer.public_send(email_template, pipeline, recipients).deliver_later end diff --git a/spec/models/project_services/pipeline_email_service_spec.rb b/spec/models/project_services/pipeline_email_service_spec.rb index 57baff3354f..4f56bceda44 100644 --- a/spec/models/project_services/pipeline_email_service_spec.rb +++ b/spec/models/project_services/pipeline_email_service_spec.rb @@ -58,7 +58,7 @@ describe PipelinesEmailService do end it 'sends email' do - should_only_email(double(email: recipient), kind: :bcc) + should_only_email(double(notification_email: recipient), kind: :bcc) end end From 64e2d884d6c8d822ae6e7d4d26af054396b74921 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 20 Oct 2016 12:15:29 +0200 Subject: [PATCH 035/175] Return conflict error in label API when title is taken by group label --- app/models/project.rb | 4 ---- lib/api/labels.rb | 6 +++--- spec/requests/api/labels_spec.rb | 15 ++++++++++++++- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/app/models/project.rb b/app/models/project.rb index 653c38322c5..2bd04547a58 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -1062,10 +1062,6 @@ class Project < ActiveRecord::Base forks.count end - def find_label(name) - labels.find_by(name: name) - end - def origin_merge_requests merge_requests.where(source_project_id: self.id) end diff --git a/lib/api/labels.rb b/lib/api/labels.rb index 642e6345b9e..40d7f4a5151 100644 --- a/lib/api/labels.rb +++ b/lib/api/labels.rb @@ -29,8 +29,8 @@ module API required_attributes! [:name, :color] attrs = attributes_for_keys [:name, :color, :description] - label = user_project.find_label(attrs[:name]) + label = available_labels.find_by(title: attrs[:name]) conflict!('Label already exists') if label label = user_project.labels.create(attrs) @@ -54,7 +54,7 @@ module API authorize! :admin_label, user_project required_attributes! [:name] - label = user_project.find_label(params[:name]) + label = user_project.labels.find_by(title: params[:name]) not_found!('Label') unless label label.destroy @@ -75,7 +75,7 @@ module API authorize! :admin_label, user_project required_attributes! [:name] - label = user_project.find_label(params[:name]) + label = user_project.labels.find_by(title: params[:name]) not_found!('Label not found') unless label attrs = attributes_for_keys [:new_name, :color, :description] diff --git a/spec/requests/api/labels_spec.rb b/spec/requests/api/labels_spec.rb index 1da9988978b..840112299bc 100644 --- a/spec/requests/api/labels_spec.rb +++ b/spec/requests/api/labels_spec.rb @@ -83,7 +83,20 @@ describe API::API, api: true do expect(json_response['message']['title']).to eq(['is invalid']) end - it 'returns 409 if label already exists' do + it 'returns 409 if label already exists in group' do + group = create(:group) + group_label = create(:group_label, group: group) + project.update(group: group) + + post api("/projects/#{project.id}/labels", user), + name: group_label.name, + color: '#FFAABB' + + expect(response).to have_http_status(409) + expect(json_response['message']).to eq('Label already exists') + end + + it 'returns 409 if label already exists in project' do post api("/projects/#{project.id}/labels", user), name: 'label1', color: '#FFAABB' From 6061c9fa3d942c4b1aa466ee8f5f8eb3ae48853e Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Fri, 21 Oct 2016 18:16:39 +0800 Subject: [PATCH 036/175] Send only to users have :read_build access, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6342#note_17193335 --- app/policies/ci/build_policy.rb | 2 +- app/policies/ci/pipeline_policy.rb | 4 + app/services/notification_service.rb | 9 +- .../pipeline_notification_worker_spec.rb | 172 ++++++++++-------- 4 files changed, 113 insertions(+), 74 deletions(-) create mode 100644 app/policies/ci/pipeline_policy.rb diff --git a/app/policies/ci/build_policy.rb b/app/policies/ci/build_policy.rb index 2232e231cf8..8b25332b73c 100644 --- a/app/policies/ci/build_policy.rb +++ b/app/policies/ci/build_policy.rb @@ -5,7 +5,7 @@ module Ci # If we can't read build we should also not have that # ability when looking at this in context of commit_status - %w(read create update admin).each do |rule| + %w[read create update admin].each do |rule| cannot! :"#{rule}_commit_status" unless can? :"#{rule}_build" end end diff --git a/app/policies/ci/pipeline_policy.rb b/app/policies/ci/pipeline_policy.rb new file mode 100644 index 00000000000..3d2eef1c50c --- /dev/null +++ b/app/policies/ci/pipeline_policy.rb @@ -0,0 +1,4 @@ +module Ci + class PipelinePolicy < BuildPolicy + end +end diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index 2cc9a9fd7bf..f48255b2e6c 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -489,9 +489,14 @@ class NotificationService end def reject_users_without_access(recipients, target) - return recipients unless target.is_a?(Issuable) + ability = case target + when Issuable + :"read_#{target.to_ability_name}" + when Ci::Pipeline + :read_build # We have build trace in pipeline emails + end - ability = :"read_#{target.to_ability_name}" + return recipients unless ability recipients.select do |user| user.can?(ability, target) diff --git a/spec/workers/pipeline_notification_worker_spec.rb b/spec/workers/pipeline_notification_worker_spec.rb index c334b2057a6..d487a719680 100644 --- a/spec/workers/pipeline_notification_worker_spec.rb +++ b/spec/workers/pipeline_notification_worker_spec.rb @@ -17,84 +17,114 @@ describe PipelineNotificationWorker do describe '#execute' do before do reset_delivered_emails! - pipeline.project.team << [watcher, Gitlab::Access::DEVELOPER] + pipeline.project.team << [pusher, Gitlab::Access::DEVELOPER] end - shared_examples 'sending emails' do - it 'sends emails' do + context 'when watcher has developer access' do + before do + pipeline.project.team << [watcher, Gitlab::Access::DEVELOPER] + end + + shared_examples 'sending emails' do + it 'sends emails' do + perform_enqueued_jobs do + subject.perform(pipeline.id) + end + + emails = ActionMailer::Base.deliveries + actual = emails.flat_map(&:bcc).sort + expected_receivers = receivers.map(&:email).uniq.sort + + expect(actual).to eq(expected_receivers) + expect(emails.size).to eq(1) + expect(emails.last.subject).to include(email_subject) + end + end + + context 'with success pipeline' do + let(:status) { 'success' } + let(:email_subject) { "Pipeline ##{pipeline.id} has succeeded" } + let(:receivers) { [pusher, watcher] } + + it_behaves_like 'sending emails' + + context 'with pipeline from someone else' do + let(:pusher) { create(:user) } + let(:watcher) { user } + + context 'with success pipeline notification on' do + before do + watcher.global_notification_setting. + update(level: 'custom', success_pipeline: true) + end + + it_behaves_like 'sending emails' + end + + context 'with success pipeline notification off' do + let(:receivers) { [pusher] } + + before do + watcher.global_notification_setting. + update(level: 'custom', success_pipeline: false) + end + + it_behaves_like 'sending emails' + end + end + + context 'with failed pipeline' do + let(:status) { 'failed' } + let(:email_subject) { "Pipeline ##{pipeline.id} has failed" } + + it_behaves_like 'sending emails' + + context 'with pipeline from someone else' do + let(:pusher) { create(:user) } + let(:watcher) { user } + + context 'with failed pipeline notification on' do + before do + watcher.global_notification_setting. + update(level: 'custom', failed_pipeline: true) + end + + it_behaves_like 'sending emails' + end + + context 'with failed pipeline notification off' do + let(:receivers) { [pusher] } + + before do + watcher.global_notification_setting. + update(level: 'custom', failed_pipeline: false) + end + + it_behaves_like 'sending emails' + end + end + end + end + end + + context 'when watcher has no read_build access' do + let(:status) { 'failed' } + let(:email_subject) { "Pipeline ##{pipeline.id} has failed" } + let(:watcher) { create(:user) } + + before do + pipeline.project.team << [watcher, Gitlab::Access::GUEST] + + watcher.global_notification_setting. + update(level: 'custom', failed_pipeline: true) + perform_enqueued_jobs do subject.perform(pipeline.id) end - - emails = ActionMailer::Base.deliveries - actual = emails.flat_map(&:bcc).sort - expected_receivers = [pusher, watcher].map(&:email).uniq.sort - - expect(actual).to eq(expected_receivers) - expect(emails.size).to eq(1) - expect(emails.last.subject).to include(email_subject) end - end - context 'with success pipeline' do - let(:status) { 'success' } - let(:email_subject) { "Pipeline ##{pipeline.id} has succeeded" } - - it_behaves_like 'sending emails' - - context 'with pipeline from someone else' do - let(:pusher) { create(:user) } - - context 'with success pipeline notification on' do - let(:watcher) { user } - - before do - watcher.global_notification_setting. - update(level: 'custom', success_pipeline: true) - end - - it_behaves_like 'sending emails' - end - - context 'with success pipeline notification off' do - before do - watcher.global_notification_setting. - update(level: 'custom', success_pipeline: false) - end - - it_behaves_like 'sending emails' - end - end - end - - context 'with failed pipeline' do - let(:status) { 'failed' } - let(:email_subject) { "Pipeline ##{pipeline.id} has failed" } - - it_behaves_like 'sending emails' - - context 'with pipeline from someone else' do - let(:pusher) { create(:user) } - - context 'with failed pipeline notification on' do - let(:watcher) { user } - - before do - watcher.global_notification_setting. - update(level: 'custom', failed_pipeline: true) - end - - it_behaves_like 'sending emails' - end - - context 'with failed pipeline notification off' do - before do - watcher.global_notification_setting. - update(level: 'custom', failed_pipeline: false) - end - - it_behaves_like 'sending emails' - end + it 'does not send emails' do + should_only_email(pusher, kind: :bcc) end end end From 2c09d2a13d83494f195fda8620e322dff7738dc5 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Fri, 21 Oct 2016 18:22:09 +0800 Subject: [PATCH 037/175] Test against notification email --- spec/support/email_helpers.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/support/email_helpers.rb b/spec/support/email_helpers.rb index a946f10f71a..3e979f2f470 100644 --- a/spec/support/email_helpers.rb +++ b/spec/support/email_helpers.rb @@ -1,6 +1,6 @@ module EmailHelpers def sent_to_user?(user, recipients = email_recipients) - recipients.include?(user.email) + recipients.include?(user.notification_email) end def reset_delivered_emails! From f388fceb4cc64d67b95e45cdbe77c9907803d6f1 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Sat, 22 Oct 2016 01:10:47 +0800 Subject: [PATCH 038/175] Make sure pusher has the read_build privilege --- spec/models/ci/pipeline_spec.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index ab05150c97e..65e663be411 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -542,6 +542,8 @@ describe Ci::Pipeline, models: true do before do reset_delivered_emails! + project.team << [pipeline.user, Gitlab::Access::DEVELOPER] + perform_enqueued_jobs do pipeline.enqueue pipeline.run From 383b0e9686a5f7a98cd21e6c5a7c9974f9ea3b80 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Sat, 22 Oct 2016 01:11:59 +0800 Subject: [PATCH 039/175] Well pusher's privilege for read_build could be removed --- app/services/notification_service.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index f48255b2e6c..6697840cc26 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -323,7 +323,9 @@ class NotificationService nil, # The acting user, who won't be added to recipients action: pipeline.status).map(&:notification_email) - mailer.public_send(email_template, pipeline, recipients).deliver_later + if recipients.any? + mailer.public_send(email_template, pipeline, recipients).deliver_later + end end protected From 02b624740d1153ac242cabada937272dc9925fca Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Mon, 24 Oct 2016 17:39:04 +0800 Subject: [PATCH 040/175] include PipelineQueue, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6342#note_17353703 --- app/workers/pipeline_notification_worker.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/workers/pipeline_notification_worker.rb b/app/workers/pipeline_notification_worker.rb index 68e72f7382f..cdb860b6675 100644 --- a/app/workers/pipeline_notification_worker.rb +++ b/app/workers/pipeline_notification_worker.rb @@ -1,5 +1,6 @@ class PipelineNotificationWorker include Sidekiq::Worker + include PipelineQueue def perform(pipeline_id, recipients = nil) pipeline = Ci::Pipeline.find_by(id: pipeline_id) From 5416d0e0837f69f35a3a9deaf947fd62e5293661 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Fri, 21 Oct 2016 16:22:43 +0800 Subject: [PATCH 041/175] Pass `@ref` along so we know which pipeline to show Closes #23615 --- app/controllers/application_controller.rb | 3 ++- app/controllers/projects/commits_controller.rb | 9 ++++++++- .../projects/merge_requests_controller.rb | 14 ++++++++++++-- app/helpers/ci_status_helper.rb | 5 +++++ app/helpers/commits_helper.rb | 8 +++++--- app/models/commit.rb | 4 ++++ app/views/projects/commits/_commit.html.haml | 4 ++-- app/views/projects/commits/_commit_list.html.haml | 2 +- app/views/projects/commits/_commits.html.haml | 5 +---- app/views/projects/commits/show.html.haml | 2 +- .../projects/merge_requests/branch_from.html.haml | 2 +- .../projects/merge_requests/branch_to.html.haml | 2 +- .../merge_requests/show/_commits.html.haml | 2 +- 13 files changed, 44 insertions(+), 18 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 37600ed875c..517ad4f03f3 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -192,9 +192,10 @@ class ApplicationController < ActionController::Base end # JSON for infinite scroll via Pager object - def pager_json(partial, count) + def pager_json(partial, count, locals = {}) html = render_to_string( partial, + locals: locals, layout: false, formats: [:html] ) diff --git a/app/controllers/projects/commits_controller.rb b/app/controllers/projects/commits_controller.rb index c2e7bf1ffec..aba87b6144b 100644 --- a/app/controllers/projects/commits_controller.rb +++ b/app/controllers/projects/commits_controller.rb @@ -26,8 +26,15 @@ class Projects::CommitsController < Projects::ApplicationController respond_to do |format| format.html - format.json { pager_json("projects/commits/_commits", @commits.size) } format.atom { render layout: false } + + format.json do + pager_json( + 'projects/commits/_commits', + @commits.size, + project: @project, + ref: @ref) + end end end end diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index 2ee53f7ceda..eff79b63cee 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -352,13 +352,23 @@ class Projects::MergeRequestsController < Projects::ApplicationController def branch_from # This is always source @source_project = @merge_request.nil? ? @project : @merge_request.source_project - @commit = @repository.commit(params[:ref]) if params[:ref].present? + + if params[:ref].present? + @ref = params[:ref] + @commit = @repository.commit(@ref) + end + render layout: false end def branch_to @target_project = selected_target_project - @commit = @target_project.commit(params[:ref]) if params[:ref].present? + + if params[:ref].present? + @ref = params[:ref] + @commit = @target_project.commit(@ref) + end + render layout: false end diff --git a/app/helpers/ci_status_helper.rb b/app/helpers/ci_status_helper.rb index b7f48630bd4..7d1b41b8fbe 100644 --- a/app/helpers/ci_status_helper.rb +++ b/app/helpers/ci_status_helper.rb @@ -54,6 +54,11 @@ module CiStatusHelper custom_icon(icon_name) end + def render_commit_ref_status(commit, ref = nil, **args) + pipeline = commit.pipelines_for(ref).last + render_pipeline_status(pipeline, **args) + end + def render_commit_status(commit, tooltip_placement: 'auto left') project = commit.project path = pipelines_namespace_project_commit_path(project.namespace, project, commit) diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb index 33dcee49aee..ed402b698fb 100644 --- a/app/helpers/commits_helper.rb +++ b/app/helpers/commits_helper.rb @@ -25,9 +25,11 @@ module CommitsHelper end end - def commit_to_html(commit, project, inline = true) - template = inline ? "inline_commit" : "commit" - render "projects/commits/#{template}", commit: commit, project: project unless commit.nil? + def commit_to_html(commit, ref, project) + render 'projects/commits/commit', + commit: commit, + ref: ref, + project: project end # Breadcrumb links for a Project and, if applicable, a tree path diff --git a/app/models/commit.rb b/app/models/commit.rb index e64fd1e0c1b..02e06657306 100644 --- a/app/models/commit.rb +++ b/app/models/commit.rb @@ -225,6 +225,10 @@ class Commit ) end + def pipelines_for(ref) + project.pipelines.where(sha: sha, ref: ref) + end + def pipelines @pipeline ||= project.pipelines.where(sha: sha) end diff --git a/app/views/projects/commits/_commit.html.haml b/app/views/projects/commits/_commit.html.haml index fb48aef0559..00bf812f33f 100644 --- a/app/views/projects/commits/_commit.html.haml +++ b/app/views/projects/commits/_commit.html.haml @@ -20,13 +20,13 @@ = commit.short_id - if commit.status .visible-xs-inline - = render_commit_status(commit) + = render_commit_ref_status(commit, ref) - if commit.description? %a.text-expander.hidden-xs.js-toggle-button ... .commit-actions.hidden-xs - if commit.status - = render_commit_status(commit) + = render_commit_ref_status(commit, ref) = clipboard_button(clipboard_text: commit.id) = link_to commit.short_id, namespace_project_commit_path(project.namespace, project, commit), class: "commit-short-id btn btn-transparent" = link_to_browse_code(project, commit) diff --git a/app/views/projects/commits/_commit_list.html.haml b/app/views/projects/commits/_commit_list.html.haml index 46e4de40042..ce416caa494 100644 --- a/app/views/projects/commits/_commit_list.html.haml +++ b/app/views/projects/commits/_commit_list.html.haml @@ -11,4 +11,4 @@ %li.warning-row.unstyled #{number_with_delimiter(hidden)} additional commits have been omitted to prevent performance issues. - else - %ul.content-list= render commits, project: @project + %ul.content-list= render commits, project: @project, ref: @ref diff --git a/app/views/projects/commits/_commits.html.haml b/app/views/projects/commits/_commits.html.haml index dd12eae8f7e..943ec24cfb5 100644 --- a/app/views/projects/commits/_commits.html.haml +++ b/app/views/projects/commits/_commits.html.haml @@ -1,13 +1,10 @@ -- unless defined?(project) - - project = @project - - commits, hidden = limited_commits(@commits) - commits.chunk { |c| c.committed_date.in_time_zone.to_date }.each do |day, commits| %li.commit-header= "#{day.strftime('%d %b, %Y')} #{pluralize(commits.count, 'commit')}" %li.commits-row %ul.list-unstyled.commit-list - = render commits, project: project + = render commits, project: project, ref: ref - if hidden > 0 %li.alert.alert-warning diff --git a/app/views/projects/commits/show.html.haml b/app/views/projects/commits/show.html.haml index 876c8002627..9628cbd1634 100644 --- a/app/views/projects/commits/show.html.haml +++ b/app/views/projects/commits/show.html.haml @@ -35,7 +35,7 @@ %div{id: dom_id(@project)} %ol#commits-list.list-unstyled.content_list - = render "commits", project: @project + = render 'commits', project: @project, ref: @ref = spinner :javascript diff --git a/app/views/projects/merge_requests/branch_from.html.haml b/app/views/projects/merge_requests/branch_from.html.haml index 4f90dde6fa8..f99f1946a5e 100644 --- a/app/views/projects/merge_requests/branch_from.html.haml +++ b/app/views/projects/merge_requests/branch_from.html.haml @@ -1 +1 @@ -= commit_to_html(@commit, @source_project, false) += commit_to_html(@commit, @ref, @source_project) if @commit diff --git a/app/views/projects/merge_requests/branch_to.html.haml b/app/views/projects/merge_requests/branch_to.html.haml index 67a7a6bcec9..a8b3c5d950a 100644 --- a/app/views/projects/merge_requests/branch_to.html.haml +++ b/app/views/projects/merge_requests/branch_to.html.haml @@ -1 +1 @@ -= commit_to_html(@commit, @target_project, false) += commit_to_html(@commit, @ref, @target_project) if @commit diff --git a/app/views/projects/merge_requests/show/_commits.html.haml b/app/views/projects/merge_requests/show/_commits.html.haml index 0b05785430b..b488f343214 100644 --- a/app/views/projects/merge_requests/show/_commits.html.haml +++ b/app/views/projects/merge_requests/show/_commits.html.haml @@ -3,4 +3,4 @@ Most recent commits displayed first %ol#commits-list.list-unstyled - = render "projects/commits/commits", project: @merge_request.project + = render "projects/commits/commits", project: @merge_request.project, ref: @merge_request.source_branch From 17dfcf6d547c0153a8650df6e330c66397e4b2c9 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Mon, 24 Oct 2016 23:23:28 +0800 Subject: [PATCH 042/175] Add a test for showing correct pipeline --- spec/features/commits_spec.rb | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/spec/features/commits_spec.rb b/spec/features/commits_spec.rb index 5910803df51..cd53a485ef4 100644 --- a/spec/features/commits_spec.rb +++ b/spec/features/commits_spec.rb @@ -12,11 +12,15 @@ describe 'Commits' do end let!(:pipeline) do - FactoryGirl.create :ci_pipeline, project: project, sha: project.commit.sha + create(:ci_pipeline, + project: project, + ref: project.default_branch, + sha: project.commit.sha, + status: :success) end context 'commit status is Generic Commit Status' do - let!(:status) { FactoryGirl.create :generic_commit_status, pipeline: pipeline } + let!(:status) { create(:generic_commit_status, pipeline: pipeline) } before do project.team << [@user, :reporter] @@ -39,7 +43,7 @@ describe 'Commits' do end context 'commit status is Ci Build' do - let!(:build) { FactoryGirl.create :ci_build, pipeline: pipeline } + let!(:build) { create(:ci_build, pipeline: pipeline) } let(:artifacts_file) { fixture_file_upload(Rails.root + 'spec/fixtures/banana_sample.gif', 'image/gif') } context 'when logged as developer' do @@ -48,13 +52,22 @@ describe 'Commits' do end describe 'Project commits' do + let!(:pipeline_from_other_branch) do + create(:ci_pipeline, + project: project, + ref: 'fix', + sha: project.commit.sha, + status: :failed) + end + before do visit namespace_project_commits_path(project.namespace, project, :master) end - it 'shows build status' do + it 'shows correct build status from default branch' do page.within("//li[@id='commit-#{pipeline.short_sha}']") do - expect(page).to have_css(".ci-status-link") + expect(page).to have_css('.ci-status-link') + expect(page).to have_css('.ci-status-icon-success') end end end From 7fac0e17e9ceed12da831d40db0e2480b12b48ff Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Mon, 24 Oct 2016 23:24:32 +0800 Subject: [PATCH 043/175] Add CHANGELOG entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bee10eb4101..815c5332a90 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ Please view this file on the master branch, on stable branches it's out of date. - Add hover to trash icon in notes !7008 (blackst0ne) - Simpler arguments passed to named_route on toggle_award_url helper method - Fix: Backup restore doesn't clear cache + - Fix showing pipeline status from correct branch !7034 - Use MergeRequestsClosingIssues cache data on Issue#closed_by_merge_requests method - Fix documents and comments on Build API `scope` - Refactor email, use setter method instead AR callbacks for email attribute (Semyon Pupkov) From 51a012b8a855874df71802fdaa807559ff9817ae Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Tue, 25 Oct 2016 22:59:19 +0800 Subject: [PATCH 044/175] Be more specific, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7034#note_17397109 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index def94165c97..102c3b883e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,7 @@ Please view this file on the master branch, on stable branches it's out of date. - Escape ref and path for relative links !6050 (winniehell) - Simpler arguments passed to named_route on toggle_award_url helper method - Fix: Backup restore doesn't clear cache - - Fix showing pipeline status from correct branch !7034 + - Fix showing pipeline status for a given commit from correct branch !7034 - Use MergeRequestsClosingIssues cache data on Issue#closed_by_merge_requests method - Fix Sign in page 'Forgot your password?' link overlaps on medium-large screens - Fix documents and comments on Build API `scope` From b4ef158a63807c850c1a17c75d66cd166c309047 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Thu, 27 Oct 2016 00:48:32 +0800 Subject: [PATCH 045/175] Still show status from pipelines, see: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7034#note_17397201 https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7034#note_17397461 https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6801#note_17468470 https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7034#note_17482654 --- app/helpers/ci_status_helper.rb | 19 ++++++++++-------- app/models/commit.rb | 21 +++++++++++++------- app/views/projects/commits/_commit.html.haml | 4 ++-- 3 files changed, 27 insertions(+), 17 deletions(-) diff --git a/app/helpers/ci_status_helper.rb b/app/helpers/ci_status_helper.rb index 7d1b41b8fbe..7851949ccf0 100644 --- a/app/helpers/ci_status_helper.rb +++ b/app/helpers/ci_status_helper.rb @@ -54,15 +54,18 @@ module CiStatusHelper custom_icon(icon_name) end - def render_commit_ref_status(commit, ref = nil, **args) - pipeline = commit.pipelines_for(ref).last - render_pipeline_status(pipeline, **args) - end - - def render_commit_status(commit, tooltip_placement: 'auto left') + def render_commit_status(commit, ref: nil, tooltip_placement: 'auto left') project = commit.project - path = pipelines_namespace_project_commit_path(project.namespace, project, commit) - render_status_with_link('commit', commit.status, path, tooltip_placement: tooltip_placement) + path = pipelines_namespace_project_commit_path( + project.namespace, + project, + commit) + + render_status_with_link( + 'commit', + commit.status_for(ref), + path, + tooltip_placement: tooltip_placement) end def render_pipeline_status(pipeline, tooltip_placement: 'auto left') diff --git a/app/models/commit.rb b/app/models/commit.rb index 02e06657306..337b7445b46 100644 --- a/app/models/commit.rb +++ b/app/models/commit.rb @@ -51,12 +51,14 @@ class Commit end attr_accessor :raw + attr_reader :statuses def initialize(raw_commit, project) raise "Nil as raw commit passed" unless raw_commit @raw = raw_commit @project = project + @statuses = {} end def id @@ -225,17 +227,22 @@ class Commit ) end - def pipelines_for(ref) - project.pipelines.where(sha: sha, ref: ref) - end - def pipelines - @pipeline ||= project.pipelines.where(sha: sha) + project.pipelines.where(sha: sha) end def status - return @status if defined?(@status) - @status ||= pipelines.status + status_for(nil) + end + + def status_for(ref) + if statuses.key?(ref) + statuses[ref] + elsif ref + statuses[ref] = pipelines.where(ref: ref).status + else + statuses[ref] = pipelines.status + end end def revert_branch_name diff --git a/app/views/projects/commits/_commit.html.haml b/app/views/projects/commits/_commit.html.haml index 00bf812f33f..9303243b119 100644 --- a/app/views/projects/commits/_commit.html.haml +++ b/app/views/projects/commits/_commit.html.haml @@ -20,13 +20,13 @@ = commit.short_id - if commit.status .visible-xs-inline - = render_commit_ref_status(commit, ref) + = render_commit_status(commit, ref: ref) - if commit.description? %a.text-expander.hidden-xs.js-toggle-button ... .commit-actions.hidden-xs - if commit.status - = render_commit_ref_status(commit, ref) + = render_commit_status(commit, ref: ref) = clipboard_button(clipboard_text: commit.id) = link_to commit.short_id, namespace_project_commit_path(project.namespace, project, commit), class: "commit-short-id btn btn-transparent" = link_to_browse_code(project, commit) From 6f6a8d2a671cf3bc2df2832081f528d9b06e27be Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Thu, 27 Oct 2016 01:37:41 +0800 Subject: [PATCH 046/175] Also update for default project page, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7034#note_17397573 --- app/views/projects/_last_commit.html.haml | 9 +++++---- app/views/projects/commits/_commit.html.haml | 4 ++-- app/views/projects/show.html.haml | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/app/views/projects/_last_commit.html.haml b/app/views/projects/_last_commit.html.haml index 630ae7d6140..593967d9310 100644 --- a/app/views/projects/_last_commit.html.haml +++ b/app/views/projects/_last_commit.html.haml @@ -1,7 +1,8 @@ -- if commit.status - = link_to builds_namespace_project_commit_path(commit.project.namespace, commit.project, commit), class: "ci-status ci-#{commit.status}" do - = ci_icon_for_status(commit.status) - = ci_label_for_status(commit.status) +- status = commit.status_for(ref) +- if status + = link_to builds_namespace_project_commit_path(commit.project.namespace, commit.project, commit), class: "ci-status ci-#{status}" do + = ci_icon_for_status(status) + = ci_label_for_status(status) = link_to commit.short_id, namespace_project_commit_path(project.namespace, project, commit), class: "commit_short_id" = link_to_gfm commit.title, namespace_project_commit_path(project.namespace, project, commit), class: "commit-row-message" diff --git a/app/views/projects/commits/_commit.html.haml b/app/views/projects/commits/_commit.html.haml index 9303243b119..c5830b5b7f7 100644 --- a/app/views/projects/commits/_commit.html.haml +++ b/app/views/projects/commits/_commit.html.haml @@ -18,14 +18,14 @@ %span.commit-row-message.visible-xs-inline · = commit.short_id - - if commit.status + - if commit.status_for(ref) .visible-xs-inline = render_commit_status(commit, ref: ref) - if commit.description? %a.text-expander.hidden-xs.js-toggle-button ... .commit-actions.hidden-xs - - if commit.status + - if commit.status_for(ref) = render_commit_status(commit, ref: ref) = clipboard_button(clipboard_text: commit.id) = link_to commit.short_id, namespace_project_commit_path(project.namespace, project, commit), class: "commit-short-id btn btn-transparent" diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml index ba16c641462..69a3bc5f046 100644 --- a/app/views/projects/show.html.haml +++ b/app/views/projects/show.html.haml @@ -79,7 +79,7 @@ = render 'shared/notifications/button', notification_setting: @notification_setting - if @repository.commit .project-last-commit{ class: container_class } - = render 'projects/last_commit', commit: @repository.commit, project: @project + = render 'projects/last_commit', commit: @repository.commit, ref: current_ref, project: @project %div{ class: container_class } - if @project.archived? From 141cb35dc5e8154f336e08ec7a38e150128577d6 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Thu, 27 Oct 2016 03:44:53 +0800 Subject: [PATCH 047/175] Also pass ref here --- app/views/projects/blob/_blob.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/projects/blob/_blob.html.haml b/app/views/projects/blob/_blob.html.haml index 3ffc3fcb7ac..149ee7c59d6 100644 --- a/app/views/projects/blob/_blob.html.haml +++ b/app/views/projects/blob/_blob.html.haml @@ -20,7 +20,7 @@ %ul.blob-commit-info.hidden-xs - blob_commit = @repository.last_commit_for_path(@commit.id, blob.path) - = render blob_commit, project: @project + = render blob_commit, project: @project, ref: @ref %div#blob-content-holder.blob-content-holder %article.file-holder From fb19d9f4e2c552ac81c9ff0e8aaff6f0e0686fc3 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Fri, 28 Oct 2016 03:05:41 +0800 Subject: [PATCH 048/175] Use multi-line conditions in view, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7034#note_17522557 --- app/views/projects/merge_requests/branch_from.html.haml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/views/projects/merge_requests/branch_from.html.haml b/app/views/projects/merge_requests/branch_from.html.haml index f99f1946a5e..3837c4b388d 100644 --- a/app/views/projects/merge_requests/branch_from.html.haml +++ b/app/views/projects/merge_requests/branch_from.html.haml @@ -1 +1,2 @@ -= commit_to_html(@commit, @ref, @source_project) if @commit +- if @commit + = commit_to_html(@commit, @ref, @source_project) From f4b9de38edb3152888cb8e9ea0f9e48a6f08dd26 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Fri, 28 Oct 2016 03:12:12 +0800 Subject: [PATCH 049/175] It's not used as a public API right now, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7034#note_17522443 --- app/models/commit.rb | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/app/models/commit.rb b/app/models/commit.rb index 337b7445b46..20bb93f4663 100644 --- a/app/models/commit.rb +++ b/app/models/commit.rb @@ -51,7 +51,6 @@ class Commit end attr_accessor :raw - attr_reader :statuses def initialize(raw_commit, project) raise "Nil as raw commit passed" unless raw_commit @@ -236,12 +235,12 @@ class Commit end def status_for(ref) - if statuses.key?(ref) - statuses[ref] + if @statuses.key?(ref) + @statuses[ref] elsif ref - statuses[ref] = pipelines.where(ref: ref).status + @statuses[ref] = pipelines.where(ref: ref).status else - statuses[ref] = pipelines.status + @statuses[ref] = pipelines.status end end From 3e6a527e686e27b3cd9e048a17f1b491023d07d1 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Fri, 28 Oct 2016 03:47:49 +0800 Subject: [PATCH 050/175] Add tests for Commit#status and Commit#status_for, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7034#note_17543036 --- spec/models/commit_spec.rb | 45 +++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/spec/models/commit_spec.rb b/spec/models/commit_spec.rb index 51be3f36135..468e198e9ea 100644 --- a/spec/models/commit_spec.rb +++ b/spec/models/commit_spec.rb @@ -210,7 +210,50 @@ eos end describe '#status' do - # TODO: kamil + shared_examples 'giving the status from pipeline' do + it do + expect(commit.status).to eq(Ci::Pipeline.status) + end + end + + context 'with pipelines' do + let!(:pipeline) do + create(:ci_empty_pipeline, project: project, sha: commit.sha) + end + + it_behaves_like 'giving the status from pipeline' + end + + context 'without pipelines' do + it_behaves_like 'giving the status from pipeline' + end + end + + describe '#status_for' do + let!(:pipeline_from_master) do + create(:ci_empty_pipeline, + project: project, + sha: commit.sha, + ref: 'master', + status: 'failed') + end + + let!(:pipeline_from_fix) do + create(:ci_empty_pipeline, + project: project, + sha: commit.sha, + ref: 'fix', + status: 'success') + end + + it 'gives pipelines from a particular branch' do + expect(commit.status_for('master')).to eq(pipeline_from_master.status) + expect(commit.status_for('fix')).to eq(pipeline_from_fix.status) + end + + it 'gives compound status if ref is nil' do + expect(commit.status_for(nil)).to eq(commit.status) + end end describe '#participants' do From e036abf3a2f969036a2c4d59441a4d7a068d7ca4 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Fri, 28 Oct 2016 03:53:18 +0800 Subject: [PATCH 051/175] Always use multiline in view --- app/views/projects/merge_requests/branch_to.html.haml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/views/projects/merge_requests/branch_to.html.haml b/app/views/projects/merge_requests/branch_to.html.haml index a8b3c5d950a..d69b71790a0 100644 --- a/app/views/projects/merge_requests/branch_to.html.haml +++ b/app/views/projects/merge_requests/branch_to.html.haml @@ -1 +1,2 @@ -= commit_to_html(@commit, @ref, @target_project) if @commit +- if @commit + = commit_to_html(@commit, @ref, @target_project) From 0fa15505345c78ec0aa5576b100cecd269714503 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20R=C3=BCger?= Date: Sat, 29 Oct 2016 02:37:29 +0200 Subject: [PATCH 052/175] Update deckar01-task_list gem to 1.0.6 ChangeLog: https://github.com/deckar01/task_list/compare/1.0.5...1.0.6 --- Gemfile | 2 +- Gemfile.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index 5f16cc063e2..e485f21ad62 100644 --- a/Gemfile +++ b/Gemfile @@ -100,7 +100,7 @@ gem 'seed-fu', '~> 2.3.5' # Markdown and HTML processing gem 'html-pipeline', '~> 1.11.0' -gem 'deckar01-task_list', '1.0.5', require: 'task_list/railtie' +gem 'deckar01-task_list', '1.0.6', require: 'task_list/railtie' gem 'gitlab-markup', '~> 1.5.0' gem 'redcarpet', '~> 3.3.3' gem 'RedCloth', '~> 4.3.2' diff --git a/Gemfile.lock b/Gemfile.lock index f8116e1894f..0d7eafc12a2 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -159,7 +159,7 @@ GEM database_cleaner (1.5.3) debug_inspector (0.0.2) debugger-ruby_core_source (1.3.8) - deckar01-task_list (1.0.5) + deckar01-task_list (1.0.6) activesupport (~> 4.0) html-pipeline rack (~> 1.0) @@ -843,7 +843,7 @@ DEPENDENCIES creole (~> 0.5.0) d3_rails (~> 3.5.0) database_cleaner (~> 1.5.0) - deckar01-task_list (= 1.0.5) + deckar01-task_list (= 1.0.6) default_value_for (~> 3.0.0) devise (~> 4.2) devise-two-factor (~> 3.0.0) From 7c84037e6caa5044ab391ef9d9e6a7528a856abe Mon Sep 17 00:00:00 2001 From: "Luke \"Jared\" Bennett" Date: Mon, 17 Oct 2016 17:14:46 +0000 Subject: [PATCH 053/175] Added Element extension with .matches and .closest --- app/assets/javascripts/extensions/element.js.es6 | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/extensions/element.js.es6 b/app/assets/javascripts/extensions/element.js.es6 index c74fc9ad074..afb2f0d6956 100644 --- a/app/assets/javascripts/extensions/element.js.es6 +++ b/app/assets/javascripts/extensions/element.js.es6 @@ -1,5 +1,7 @@ -/* eslint-disable */ -Element.prototype.matches = Element.prototype.matches || Element.prototype.msMatches; +/* global Element */ +/* eslint-disable consistent-return, max-len */ + +Element.prototype.matches = Element.prototype.matches || Element.prototype.msMatchesSelector; Element.prototype.closest = function closest(selector, selectedElement = this) { if (!selectedElement) return; From 6aa615842262f2500270d13aa735634637fd0d67 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Wed, 2 Nov 2016 16:19:25 +0800 Subject: [PATCH 054/175] Add failed_pipeline and success_pipeline to API doc --- doc/api/notification_settings.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/api/notification_settings.md b/doc/api/notification_settings.md index ff6c9e4931c..b3ceaf296a2 100644 --- a/doc/api/notification_settings.md +++ b/doc/api/notification_settings.md @@ -4,7 +4,7 @@ **Valid notification levels** -The notification levels are defined in the `NotificationSetting::level` model enumeration. Currently, these levels are recognized: +The notification levels are defined in the `NotificationSetting.level` model enumeration. Currently, these levels are recognized: ``` disabled @@ -28,6 +28,8 @@ reopen_merge_request close_merge_request reassign_merge_request merge_merge_request +failed_pipeline +success_pipeline ``` ## Global notification settings From acfe394018df50bfc08aa9e41265231747675646 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Fri, 28 Oct 2016 14:32:07 +0200 Subject: [PATCH 055/175] Add PoC for resource serializers --- app/serializers/base_serializer.rb | 24 +++++++++++++ app/serializers/entity_request.rb | 16 +++++++++ app/serializers/environment_entity.rb | 17 +++++++++ app/serializers/environment_serializer.rb | 3 ++ app/serializers/project_entity.rb | 8 +++++ app/serializers/request_aware_entity.rb | 11 ++++++ spec/serializers/entity_request_spec.rb | 26 ++++++++++++++ .../environment_serializer_spec.rb | 35 +++++++++++++++++++ 8 files changed, 140 insertions(+) create mode 100644 app/serializers/base_serializer.rb create mode 100644 app/serializers/entity_request.rb create mode 100644 app/serializers/environment_entity.rb create mode 100644 app/serializers/environment_serializer.rb create mode 100644 app/serializers/project_entity.rb create mode 100644 app/serializers/request_aware_entity.rb create mode 100644 spec/serializers/entity_request_spec.rb create mode 100644 spec/serializers/environment_serializer_spec.rb diff --git a/app/serializers/base_serializer.rb b/app/serializers/base_serializer.rb new file mode 100644 index 00000000000..f9f7135551b --- /dev/null +++ b/app/serializers/base_serializer.rb @@ -0,0 +1,24 @@ +class BaseSerializer + def initialize(request = {}) + @request = EntityRequest.new(request) + @opts = { request: @request } + end + + def set(opts) + @request.merge!(opts) + self + end + + def represent(resource, opts = {}) + self.class.entity_class + .represent(resource, @opts.reverse_merge(opts)) + end + + def self.entity(entity_class) + @entity_class ||= entity_class + end + + def self.entity_class + @entity_class + end +end diff --git a/app/serializers/entity_request.rb b/app/serializers/entity_request.rb new file mode 100644 index 00000000000..12ceb38b284 --- /dev/null +++ b/app/serializers/entity_request.rb @@ -0,0 +1,16 @@ +class EntityRequest + # We use EntityRequest object to collect parameters and variables + # from the controller. Because options that are being passed to the entity + # do appear in each entity object in the chain, we need a way to pass data + # that is present in the controller (see #20045). + # + def initialize(parameters) + merge!(parameters) + end + + def merge!(parameters) + parameters.each do |key, value| + define_singleton_method(key) { value } + end + end +end diff --git a/app/serializers/environment_entity.rb b/app/serializers/environment_entity.rb new file mode 100644 index 00000000000..9415f1dd450 --- /dev/null +++ b/app/serializers/environment_entity.rb @@ -0,0 +1,17 @@ +class EnvironmentEntity < Grape::Entity + include RequestAwareEntity + include Gitlab::Routing.url_helpers + + expose :id + expose :name + expose :project, with: ProjectEntity + expose :last_deployment, + as: :deployment, + using: API::Entities::Deployment + + expose :environment_path + + def environment_path + request.path + end +end diff --git a/app/serializers/environment_serializer.rb b/app/serializers/environment_serializer.rb new file mode 100644 index 00000000000..91955542f25 --- /dev/null +++ b/app/serializers/environment_serializer.rb @@ -0,0 +1,3 @@ +class EnvironmentSerializer < BaseSerializer + entity EnvironmentEntity +end diff --git a/app/serializers/project_entity.rb b/app/serializers/project_entity.rb new file mode 100644 index 00000000000..b8e23db470b --- /dev/null +++ b/app/serializers/project_entity.rb @@ -0,0 +1,8 @@ +class ProjectEntity < Grape::Entity + expose :id + expose :name + + expose :test do |project| + 'something' + end +end diff --git a/app/serializers/request_aware_entity.rb b/app/serializers/request_aware_entity.rb new file mode 100644 index 00000000000..f6b6f64d0f8 --- /dev/null +++ b/app/serializers/request_aware_entity.rb @@ -0,0 +1,11 @@ +module RequestAwareEntity + # We use SerializableRequest class to collect parameters and variables + # from the controller. Because options that are being passed to the entity + # are appear in each entity in the chain, we need a way to access data + # that is present in the controller (see #20045). + # + def request + options[:request] || + raise(StandardError, 'Request not set!!') + end +end diff --git a/spec/serializers/entity_request_spec.rb b/spec/serializers/entity_request_spec.rb new file mode 100644 index 00000000000..1c220a7b95d --- /dev/null +++ b/spec/serializers/entity_request_spec.rb @@ -0,0 +1,26 @@ +require 'spec_helper' + +describe EntityRequest do + subject do + described_class.new(user: 'user', project: 'some project') + end + + describe 'methods created' do + it 'defines accessible attributes' do + expect(subject.user).to eq 'user' + expect(subject.project).to eq 'some project' + end + + it 'raises error when attribute is not defined' do + expect { subject.some_method }.to raise_error NoMethodError + end + end + + describe '#merge!' do + before { subject.merge!(build: 'some build') } + + it 'appends parameters' do + expect(subject.build).to eq 'some build' + end + end +end diff --git a/spec/serializers/environment_serializer_spec.rb b/spec/serializers/environment_serializer_spec.rb new file mode 100644 index 00000000000..3470863681c --- /dev/null +++ b/spec/serializers/environment_serializer_spec.rb @@ -0,0 +1,35 @@ +require 'spec_helper' + +describe EnvironmentSerializer do + let(:serializer) do + described_class.new(path: 'some path').represent(resource) + end + + context 'when there is a single object provided' do + let(:resource) { create(:environment) } + + it 'shows json' do + puts serializer.to_json + end + + it 'it generates payload for single object' do + expect(parsed_json).to be_an_instance_of Hash + end + end + + context 'when there is a collection of objects provided' do + let(:resource) { create_list(:environment, 2) } + + it 'shows json' do + puts serializer.to_json + end + + it 'generates payload for collection' do + expect(parsed_json).to be_an_instance_of Array + end + end + + def parsed_json + JSON.parse(serializer.to_json) + end +end From f1e9c97d64b96bdd398616743ad048f8d147e26b Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Wed, 2 Nov 2016 14:36:21 +0100 Subject: [PATCH 056/175] Use entity request object in environment entity --- app/serializers/environment_entity.rb | 14 +++++++++++--- app/serializers/project_entity.rb | 4 +++- app/serializers/request_aware_entity.rb | 5 ----- spec/serializers/environment_serializer_spec.rb | 17 ++++++++--------- 4 files changed, 22 insertions(+), 18 deletions(-) diff --git a/app/serializers/environment_entity.rb b/app/serializers/environment_entity.rb index 9415f1dd450..006b2841e8f 100644 --- a/app/serializers/environment_entity.rb +++ b/app/serializers/environment_entity.rb @@ -9,9 +9,17 @@ class EnvironmentEntity < Grape::Entity as: :deployment, using: API::Entities::Deployment - expose :environment_path + expose :gitlab_path do |environment| + namespace_project_environment_path( + environment.project.namespace, + environment.project, + environment + ) + end - def environment_path - request.path + expose :can_read? + + def can_read? + Ability.allowed?(request.user, :read_environment, @object) end end diff --git a/app/serializers/project_entity.rb b/app/serializers/project_entity.rb index b8e23db470b..047366eb687 100644 --- a/app/serializers/project_entity.rb +++ b/app/serializers/project_entity.rb @@ -1,8 +1,10 @@ class ProjectEntity < Grape::Entity + include RequestAwareEntity + expose :id expose :name expose :test do |project| - 'something' + request.user.email end end diff --git a/app/serializers/request_aware_entity.rb b/app/serializers/request_aware_entity.rb index f6b6f64d0f8..fc7d1698b1a 100644 --- a/app/serializers/request_aware_entity.rb +++ b/app/serializers/request_aware_entity.rb @@ -1,9 +1,4 @@ module RequestAwareEntity - # We use SerializableRequest class to collect parameters and variables - # from the controller. Because options that are being passed to the entity - # are appear in each entity in the chain, we need a way to access data - # that is present in the controller (see #20045). - # def request options[:request] || raise(StandardError, 'Request not set!!') diff --git a/spec/serializers/environment_serializer_spec.rb b/spec/serializers/environment_serializer_spec.rb index 3470863681c..cd9486111f1 100644 --- a/spec/serializers/environment_serializer_spec.rb +++ b/spec/serializers/environment_serializer_spec.rb @@ -2,18 +2,21 @@ require 'spec_helper' describe EnvironmentSerializer do let(:serializer) do - described_class.new(path: 'some path').represent(resource) + described_class.new(path: 'some path', user: user) + .represent(resource) end + let(:user) { create(:user) } + context 'when there is a single object provided' do let(:resource) { create(:environment) } it 'shows json' do - puts serializer.to_json + puts serializer.as_json end it 'it generates payload for single object' do - expect(parsed_json).to be_an_instance_of Hash + expect(serializer.as_json).to be_an_instance_of Hash end end @@ -21,15 +24,11 @@ describe EnvironmentSerializer do let(:resource) { create_list(:environment, 2) } it 'shows json' do - puts serializer.to_json + puts serializer.as_json end it 'generates payload for collection' do - expect(parsed_json).to be_an_instance_of Array + expect(serializer.as_json).to be_an_instance_of Array end end - - def parsed_json - JSON.parse(serializer.to_json) - end end From 573921cb9d0b139dec324fb1368feb1347b51624 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Thu, 3 Nov 2016 12:54:10 +0100 Subject: [PATCH 057/175] Implement entities needed for environments folders --- app/serializers/base_serializer.rb | 12 ++++----- app/serializers/build_entity.rb | 20 ++++++++++++++ app/serializers/commit_entity.rb | 10 +++++++ app/serializers/deployment_entity.rb | 27 +++++++++++++++++++ app/serializers/environment_entity.rb | 22 +++++++-------- app/serializers/request_aware_entity.rb | 10 ++++--- spec/factories/deployments.rb | 4 +-- .../environment_serializer_spec.rb | 15 ++++++++--- 8 files changed, 93 insertions(+), 27 deletions(-) create mode 100644 app/serializers/build_entity.rb create mode 100644 app/serializers/commit_entity.rb create mode 100644 app/serializers/deployment_entity.rb diff --git a/app/serializers/base_serializer.rb b/app/serializers/base_serializer.rb index f9f7135551b..aeb01dc2ad5 100644 --- a/app/serializers/base_serializer.rb +++ b/app/serializers/base_serializer.rb @@ -1,17 +1,17 @@ class BaseSerializer - def initialize(request = {}) - @request = EntityRequest.new(request) + def initialize(parameters = {}) + @entity = self.class.entity_class + @request = EntityRequest.new(parameters) @opts = { request: @request } end - def set(opts) - @request.merge!(opts) + def set(parameters) + @request.merge!(parameters) self end def represent(resource, opts = {}) - self.class.entity_class - .represent(resource, @opts.reverse_merge(opts)) + @entity.represent(resource, @opts.reverse_merge(opts)) end def self.entity(entity_class) diff --git a/app/serializers/build_entity.rb b/app/serializers/build_entity.rb new file mode 100644 index 00000000000..38169ab9864 --- /dev/null +++ b/app/serializers/build_entity.rb @@ -0,0 +1,20 @@ +class BuildEntity < Grape::Entity + include RequestAwareEntity + + expose :id + expose :name + + expose :build_url do |build| + @urls.namespace_project_build_url( + build.project.namespace, + build.project, + build) + end + + expose :retry_url do |build| + @urls.retry_namespace_project_build_url( + build.project.namespace, + build.project, + build) + end +end diff --git a/app/serializers/commit_entity.rb b/app/serializers/commit_entity.rb new file mode 100644 index 00000000000..ae53de0c750 --- /dev/null +++ b/app/serializers/commit_entity.rb @@ -0,0 +1,10 @@ +class CommitEntity < API::Entities::RepoCommit + include RequestAwareEntity + + expose :commit_url do |commit| + @urls.namespace_project_tree_url( + @request.project.namespace, + @request.project, + id: commit.id) + end +end diff --git a/app/serializers/deployment_entity.rb b/app/serializers/deployment_entity.rb new file mode 100644 index 00000000000..3462b188337 --- /dev/null +++ b/app/serializers/deployment_entity.rb @@ -0,0 +1,27 @@ +class DeploymentEntity < Grape::Entity + include RequestAwareEntity + + expose :id + expose :iid + expose :sha + + expose :ref do + expose :name do |deployment| + deployment.ref + end + + expose :ref_url do |deployment| + @urls.namespace_project_tree_url( + deployment.project.namespace, + deployment.project, + id: deployment.ref) + end + end + + expose :tag + expose :last? + expose :user, using: API::Entities::UserBasic + expose :commit, using: CommitEntity + expose :deployable, using: BuildEntity + expose :manual_actions +end diff --git a/app/serializers/environment_entity.rb b/app/serializers/environment_entity.rb index 006b2841e8f..6b037e65e55 100644 --- a/app/serializers/environment_entity.rb +++ b/app/serializers/environment_entity.rb @@ -1,25 +1,21 @@ class EnvironmentEntity < Grape::Entity include RequestAwareEntity - include Gitlab::Routing.url_helpers expose :id expose :name + expose :state + expose :external_url + expose :environment_type expose :project, with: ProjectEntity - expose :last_deployment, - as: :deployment, - using: API::Entities::Deployment + expose :last_deployment, using: DeploymentEntity + expose :stoppable? - expose :gitlab_path do |environment| - namespace_project_environment_path( + expose :environmenturl do |environment| + @urls.namespace_project_environment_url( environment.project.namespace, environment.project, - environment - ) + environment) end - expose :can_read? - - def can_read? - Ability.allowed?(request.user, :read_environment, @object) - end + expose :created_at, :updated_at end diff --git a/app/serializers/request_aware_entity.rb b/app/serializers/request_aware_entity.rb index fc7d1698b1a..1586507492d 100644 --- a/app/serializers/request_aware_entity.rb +++ b/app/serializers/request_aware_entity.rb @@ -1,6 +1,10 @@ module RequestAwareEntity - def request - options[:request] || - raise(StandardError, 'Request not set!!') + attr_reader :request + + def initialize(object, options = {}) + super(object, options) + + @request = options.fetch(:request) + @urls = Gitlab::Routing.url_helpers end end diff --git a/spec/factories/deployments.rb b/spec/factories/deployments.rb index 6f24bf58d14..8c8e5dc54c2 100644 --- a/spec/factories/deployments.rb +++ b/spec/factories/deployments.rb @@ -1,9 +1,9 @@ FactoryGirl.define do factory :deployment, class: Deployment do - sha '97de212e80737a608d939f648d959671fb0a0142' + sha 'b83d6e391c22777fca1ed3012fce84f633d7fed0' ref 'master' tag false - project nil + project environment factory: :environment diff --git a/spec/serializers/environment_serializer_spec.rb b/spec/serializers/environment_serializer_spec.rb index cd9486111f1..f7de6c450ab 100644 --- a/spec/serializers/environment_serializer_spec.rb +++ b/spec/serializers/environment_serializer_spec.rb @@ -2,17 +2,25 @@ require 'spec_helper' describe EnvironmentSerializer do let(:serializer) do - described_class.new(path: 'some path', user: user) + described_class + .new(user: user, project: project) .represent(resource) end let(:user) { create(:user) } context 'when there is a single object provided' do - let(:resource) { create(:environment) } + let(:deployment) do + create(:deployment, deployable: deployable, + user: user) + end + + let(:deployable) { create(:ci_build) } + let(:project) { deployment.project } + let(:resource) { deployment.environment } it 'shows json' do - puts serializer.as_json + pp serializer.as_json end it 'it generates payload for single object' do @@ -21,6 +29,7 @@ describe EnvironmentSerializer do end context 'when there is a collection of objects provided' do + let(:project) { create(:empty_project) } let(:resource) { create_list(:environment, 2) } it 'shows json' do From 52d333b9f4793ca677b938317f4c8e480b835284 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Thu, 3 Nov 2016 13:35:57 +0100 Subject: [PATCH 058/175] Remove duplication from build serializer entity --- app/serializers/build_entity.rb | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/app/serializers/build_entity.rb b/app/serializers/build_entity.rb index 38169ab9864..b37bff0b500 100644 --- a/app/serializers/build_entity.rb +++ b/app/serializers/build_entity.rb @@ -5,16 +5,20 @@ class BuildEntity < Grape::Entity expose :name expose :build_url do |build| - @urls.namespace_project_build_url( - build.project.namespace, - build.project, - build) + url_to(:namespace_project_build, build) end expose :retry_url do |build| - @urls.retry_namespace_project_build_url( - build.project.namespace, - build.project, - build) + url_to(:retry_namespace_project_build, build) + end + + expose :play_url, if: ->(build, _) { build.manual? } do |build| + url_to(:retry_namespace_project_build, build) + end + + private + + def url_to(route, build) + @urls.send("#{route}_url", build.project.namespace, build.project, build) end end From 9176a19e3d858a6d64a2254260febe000474af6d Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Thu, 3 Nov 2016 20:41:51 +0800 Subject: [PATCH 059/175] Add pipelines to notifications documentation --- doc/workflow/notifications.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/workflow/notifications.md b/doc/workflow/notifications.md index 1b49a5c385f..4824b4e34b9 100644 --- a/doc/workflow/notifications.md +++ b/doc/workflow/notifications.md @@ -66,6 +66,7 @@ Below is the table of events users can be notified of: In all of the below cases, the notification will be sent to: - Participants: - the author and assignee of the issue/merge request + - the author of the pipeline - authors of comments on the issue/merge request - anyone mentioned by `@username` in the issue/merge request title or description - anyone mentioned by `@username` in any of the comments on the issue/merge request @@ -88,6 +89,8 @@ In all of the below cases, the notification will be sent to: | Reopen merge request | | | Merge merge request | | | New comment | The above, plus anyone mentioned by `@username` in the comment, with notification level "Mention" or higher | +| Failed pipeline | The author of the pipeline and watchers | +| Successful pipeline | The author of the pipeline and watchers | In addition, if the title or description of an Issue or Merge Request is From 7dd6485a0fd7fc264f86f389da3ab846c62e8724 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Thu, 3 Nov 2016 13:42:22 +0100 Subject: [PATCH 060/175] Add manual actions for deployment serialization --- app/serializers/deployment_entity.rb | 2 +- spec/serializers/environment_serializer_spec.rb | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/app/serializers/deployment_entity.rb b/app/serializers/deployment_entity.rb index 3462b188337..d3ed6a5eef4 100644 --- a/app/serializers/deployment_entity.rb +++ b/app/serializers/deployment_entity.rb @@ -23,5 +23,5 @@ class DeploymentEntity < Grape::Entity expose :user, using: API::Entities::UserBasic expose :commit, using: CommitEntity expose :deployable, using: BuildEntity - expose :manual_actions + expose :manual_actions, using: BuildEntity end diff --git a/spec/serializers/environment_serializer_spec.rb b/spec/serializers/environment_serializer_spec.rb index f7de6c450ab..2c94a076aba 100644 --- a/spec/serializers/environment_serializer_spec.rb +++ b/spec/serializers/environment_serializer_spec.rb @@ -10,6 +10,11 @@ describe EnvironmentSerializer do let(:user) { create(:user) } context 'when there is a single object provided' do + before do + create(:ci_build, :manual, name: 'manual1', + pipeline: deployable.pipeline) + end + let(:deployment) do create(:deployment, deployable: deployable, user: user) From 3bf3c2c23f348569292ff5f2a6382c12741c5dc3 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Thu, 3 Nov 2016 20:46:26 +0800 Subject: [PATCH 061/175] Fix CHANGELOG --- CHANGELOG.md | 28 +--------------------------- 1 file changed, 1 insertion(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 95a2b0de3b0..f2a219fc5ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,34 +1,8 @@ Please view this file on the master branch, on stable branches it's out of date. ## 8.14.0 (2016-11-22) - - Adds user project membership expired event to clarify why user was removed (Callum Dryden) - - Add CI notifications. Who triggered a pipeline would receive an email after the pipeline is succeeded or failed. Users could also update notification settings accordingly. !6342 - - Trim leading and trailing whitespace on project_path (Linus Thiel) - - Prevent award emoji via notes for issues/MRs authored by user (barthc) - - Adds an optional path parameter to the Commits API to filter commits by path (Luis HGO) - - Fix extra space on Build sidebar on Firefox !7060 - - Fix HipChat notifications rendering (airatshigapov, eisnerd) - - Add hover to trash icon in notes !7008 (blackst0ne) - - Escape ref and path for relative links !6050 (winniehell) - - Simpler arguments passed to named_route on toggle_award_url helper method - - Fix: Backup restore doesn't clear cache - - Use MergeRequestsClosingIssues cache data on Issue#closed_by_merge_requests method - - Fix Sign in page 'Forgot your password?' link overlaps on medium-large screens - - Fix documents and comments on Build API `scope` - - Refactor email, use setter method instead AR callbacks for email attribute (Semyon Pupkov) - -## 8.13.1 (unreleased) - - Fix bug where labels would be assigned to issues that were moved - - Fix error in generating labels - - Fix reply-by-email not working due to queue name mismatch - - Fixed hidden pipeline graph on commit and MR page !6895 - - Expire and build repository cache after project import - - Fix 404 for group pages when GitLab setup uses relative url - - Simpler arguments passed to named_route on toggle_award_url helper method - - Fix unauthorized users dragging on issue boards - - Better handle when no users were selected for adding to group or project. (Linus Thiel) - - Only show register tab if signup enabled. +- Add CI notifications. Who triggered a pipeline would receive an email after the pipeline is succeeded or failed. Users could also update notification settings accordingly. !6342 - Fix Milestone dropdown not stay selected for `Upcoming` and `No Milestone` option !7117 - Backups do not fail anymore when using tar on annex and custom_hooks only. !5814 - Adds user project membership expired event to clarify why user was removed (Callum Dryden) From 00800f4dd38ed6827ff413d8bdfa8112c27cfa03 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Thu, 3 Nov 2016 20:49:48 +0800 Subject: [PATCH 062/175] Try to reduce conflicts --- CHANGELOG.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f2a219fc5ca..2c193bfb9dc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,6 @@ Please view this file on the master branch, on stable branches it's out of date. ## 8.14.0 (2016-11-22) - -- Add CI notifications. Who triggered a pipeline would receive an email after the pipeline is succeeded or failed. Users could also update notification settings accordingly. !6342 - Fix Milestone dropdown not stay selected for `Upcoming` and `No Milestone` option !7117 - Backups do not fail anymore when using tar on annex and custom_hooks only. !5814 - Adds user project membership expired event to clarify why user was removed (Callum Dryden) @@ -22,6 +20,7 @@ Please view this file on the master branch, on stable branches it's out of date. - Hides project activity tabs when features are disabled - Only show one error message for an invalid email !5905 (lycoperdon) - Added guide describing how to upgrade PostgreSQL using Slony +- Add CI notifications. Who triggered a pipeline would receive an email after the pipeline is succeeded or failed. Users could also update notification settings accordingly. !6342 - Fix sidekiq stats in admin area (blackst0ne) - Added label description as tooltip to issue board list title - Created cycle analytics bundle JavaScript file From c3dae798e16dee0b64bc8c9fd0e0e21b2502318e Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Thu, 3 Nov 2016 14:01:35 +0100 Subject: [PATCH 063/175] Extend tests for environments serializer --- app/serializers/environment_entity.rb | 2 +- .../environment_serializer_spec.rb | 21 +++++++++++++------ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/app/serializers/environment_entity.rb b/app/serializers/environment_entity.rb index 6b037e65e55..0a6c5e7f87f 100644 --- a/app/serializers/environment_entity.rb +++ b/app/serializers/environment_entity.rb @@ -10,7 +10,7 @@ class EnvironmentEntity < Grape::Entity expose :last_deployment, using: DeploymentEntity expose :stoppable? - expose :environmenturl do |environment| + expose :environment_url do |environment| @urls.namespace_project_environment_url( environment.project.namespace, environment.project, diff --git a/spec/serializers/environment_serializer_spec.rb b/spec/serializers/environment_serializer_spec.rb index 2c94a076aba..81393beb416 100644 --- a/spec/serializers/environment_serializer_spec.rb +++ b/spec/serializers/environment_serializer_spec.rb @@ -24,21 +24,30 @@ describe EnvironmentSerializer do let(:project) { deployment.project } let(:resource) { deployment.environment } - it 'shows json' do - pp serializer.as_json - end - it 'it generates payload for single object' do expect(serializer.as_json).to be_an_instance_of Hash end + + it 'contains important elements of environment' do + expect(serializer.as_json) + .to include(:name, :external_url, :environment_url, :last_deployment) + end + + it 'contains relevant information about last deployment' do + last_deployment = serializer.as_json.fetch(:last_deployment) + + expect(last_deployment) + .to include(:ref, :user, :commit, :deployable, :manual_actions) + end end context 'when there is a collection of objects provided' do let(:project) { create(:empty_project) } let(:resource) { create_list(:environment, 2) } - it 'shows json' do - puts serializer.as_json + it 'contains important elements of environment' do + expect(serializer.as_json.first) + .to include(:last_deployment, :name, :external_url) end it 'generates payload for collection' do From 6c94adea3541914e7c36fb2e36a0f3ee44d2bcb4 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Thu, 3 Nov 2016 14:08:13 +0100 Subject: [PATCH 064/175] Remove project entity that was part of the PoC --- app/serializers/environment_entity.rb | 2 +- app/serializers/project_entity.rb | 10 ---------- 2 files changed, 1 insertion(+), 11 deletions(-) delete mode 100644 app/serializers/project_entity.rb diff --git a/app/serializers/environment_entity.rb b/app/serializers/environment_entity.rb index 0a6c5e7f87f..0035d369e61 100644 --- a/app/serializers/environment_entity.rb +++ b/app/serializers/environment_entity.rb @@ -6,7 +6,7 @@ class EnvironmentEntity < Grape::Entity expose :state expose :external_url expose :environment_type - expose :project, with: ProjectEntity + expose :project, with: API::Entities::BasicProjectDetails expose :last_deployment, using: DeploymentEntity expose :stoppable? diff --git a/app/serializers/project_entity.rb b/app/serializers/project_entity.rb deleted file mode 100644 index 047366eb687..00000000000 --- a/app/serializers/project_entity.rb +++ /dev/null @@ -1,10 +0,0 @@ -class ProjectEntity < Grape::Entity - include RequestAwareEntity - - expose :id - expose :name - - expose :test do |project| - request.user.email - end -end From a68e7e605aa684e88523f6e28f995c3b497945c6 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Thu, 3 Nov 2016 14:22:19 +0100 Subject: [PATCH 065/175] Add basic tests for build entity used by serialzier --- spec/serializers/build_entity_spec.rb | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 spec/serializers/build_entity_spec.rb diff --git a/spec/serializers/build_entity_spec.rb b/spec/serializers/build_entity_spec.rb new file mode 100644 index 00000000000..b7acc2066ba --- /dev/null +++ b/spec/serializers/build_entity_spec.rb @@ -0,0 +1,24 @@ +require 'spec_helper' + +describe BuildEntity do + subject do + described_class.new(build, request: double).as_json + end + + context 'when build is a regular job' do + let(:build) { create(:ci_build) } + + it 'contains url to build page and retry action' do + expect(subject).to include(:build_url, :retry_url) + expect(subject).not_to include(:play_url) + end + end + + context 'when build is a manual action' do + let(:build) { create(:ci_build, :manual) } + + it 'contains url to play action' do + expect(subject).to include(:play_url) + end + end +end From 3c3e61aaca34d1113d3cfb6076462beaf353e739 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Thu, 3 Nov 2016 14:24:10 +0100 Subject: [PATCH 066/175] Exclude project information from environment entity --- app/serializers/environment_entity.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/app/serializers/environment_entity.rb b/app/serializers/environment_entity.rb index 0035d369e61..e80a4335f53 100644 --- a/app/serializers/environment_entity.rb +++ b/app/serializers/environment_entity.rb @@ -6,7 +6,6 @@ class EnvironmentEntity < Grape::Entity expose :state expose :external_url expose :environment_type - expose :project, with: API::Entities::BasicProjectDetails expose :last_deployment, using: DeploymentEntity expose :stoppable? From f203ca5c932cc24787e1c44c5801c15923cd04ab Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Thu, 3 Nov 2016 15:13:57 +0100 Subject: [PATCH 067/175] Fix specs related to deployments and environments --- app/serializers/build_entity.rb | 2 +- spec/factories/deployments.rb | 4 ++-- spec/serializers/environment_serializer_spec.rb | 6 ++++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/app/serializers/build_entity.rb b/app/serializers/build_entity.rb index b37bff0b500..203bd747ad9 100644 --- a/app/serializers/build_entity.rb +++ b/app/serializers/build_entity.rb @@ -13,7 +13,7 @@ class BuildEntity < Grape::Entity end expose :play_url, if: ->(build, _) { build.manual? } do |build| - url_to(:retry_namespace_project_build, build) + url_to(:play_namespace_project_build, build) end private diff --git a/spec/factories/deployments.rb b/spec/factories/deployments.rb index 8c8e5dc54c2..6f24bf58d14 100644 --- a/spec/factories/deployments.rb +++ b/spec/factories/deployments.rb @@ -1,9 +1,9 @@ FactoryGirl.define do factory :deployment, class: Deployment do - sha 'b83d6e391c22777fca1ed3012fce84f633d7fed0' + sha '97de212e80737a608d939f648d959671fb0a0142' ref 'master' tag false - project + project nil environment factory: :environment diff --git a/spec/serializers/environment_serializer_spec.rb b/spec/serializers/environment_serializer_spec.rb index 81393beb416..32f144faf54 100644 --- a/spec/serializers/environment_serializer_spec.rb +++ b/spec/serializers/environment_serializer_spec.rb @@ -8,6 +8,7 @@ describe EnvironmentSerializer do end let(:user) { create(:user) } + let(:project) { create(:project) } context 'when there is a single object provided' do before do @@ -17,11 +18,12 @@ describe EnvironmentSerializer do let(:deployment) do create(:deployment, deployable: deployable, - user: user) + user: user, + project: project, + sha: project.commit.id) end let(:deployable) { create(:ci_build) } - let(:project) { deployment.project } let(:resource) { deployment.environment } it 'it generates payload for single object' do From ee4c8b75de6b04a8c2ed755b1b409dab9f0536c5 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Thu, 3 Nov 2016 23:26:15 +0800 Subject: [PATCH 068/175] Fix CHANGELOG --- CHANGELOG.md | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 188e6ca0332..67dafd4e422 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,28 +1,6 @@ Please view this file on the master branch, on stable branches it's out of date. ## 8.14.0 (2016-11-22) - - Adds user project membership expired event to clarify why user was removed (Callum Dryden) - - Trim leading and trailing whitespace on project_path (Linus Thiel) - - Prevent award emoji via notes for issues/MRs authored by user (barthc) - - Adds an optional path parameter to the Commits API to filter commits by path (Luis HGO) - - Fix extra space on Build sidebar on Firefox !7060 - - Fix HipChat notifications rendering (airatshigapov, eisnerd) - - Add hover to trash icon in notes !7008 (blackst0ne) - - Fix sidekiq stats in admin area (blackst0ne) - - Escape ref and path for relative links !6050 (winniehell) - - Fixed link typo on /help/ui to Alerts section. !6915 (Sam Rose) - - Fix filtering of milestones with quotes in title (airatshigapov) - - Simpler arguments passed to named_route on toggle_award_url helper method - - Fix typo in framework css class. !7086 (Daniel Voogsgerd) - - Fix: Backup restore doesn't clear cache - - Fix showing pipeline status for a given commit from correct branch !7034 - - API: Fix project deploy keys 400 and 500 errors when adding an existing key. !6784 (Joshua Welsh) - - Replace jquery.cookie plugin with js.cookie !7085 - - Use MergeRequestsClosingIssues cache data on Issue#closed_by_merge_requests method - - Fix Sign in page 'Forgot your password?' link overlaps on medium-large screens - - Fix documents and comments on Build API `scope` - - Refactor email, use setter method instead AR callbacks for email attribute (Semyon Pupkov) - - Backups do not fail anymore when using tar on annex and custom_hooks only. !5814 - Adds user project membership expired event to clarify why user was removed (Callum Dryden) - Trim leading and trailing whitespace on project_path (Linus Thiel) @@ -47,6 +25,7 @@ Please view this file on the master branch, on stable branches it's out of date. - Fixed link typo on /help/ui to Alerts section. !6915 (Sam Rose) - Fix filtering of milestones with quotes in title (airatshigapov) - Refactor less readable existance checking code from CoffeeScript !6289 (jlogandavison) +- Fix showing pipeline status for a given commit from correct branch !7034 - Update mail_room and enable sentinel support to Reply By Email (!7101) - Add task completion status in Issues and Merge Requests tabs: "X of Y tasks completed" (!6527, @gmesalazar) - Simpler arguments passed to named_route on toggle_award_url helper method From 1ae557c106e94c20742d0788dc7eb604603faa08 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Thu, 3 Nov 2016 23:39:37 +0800 Subject: [PATCH 069/175] Merge status_for and status, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7034#note_17742297 --- app/helpers/ci_status_helper.rb | 2 +- app/models/commit.rb | 6 +- app/views/projects/_last_commit.html.haml | 2 +- app/views/projects/commits/_commit.html.haml | 4 +- spec/models/commit_spec.rb | 74 ++++++++++---------- 5 files changed, 43 insertions(+), 45 deletions(-) diff --git a/app/helpers/ci_status_helper.rb b/app/helpers/ci_status_helper.rb index 7851949ccf0..3decedace4f 100644 --- a/app/helpers/ci_status_helper.rb +++ b/app/helpers/ci_status_helper.rb @@ -63,7 +63,7 @@ module CiStatusHelper render_status_with_link( 'commit', - commit.status_for(ref), + commit.status(ref), path, tooltip_placement: tooltip_placement) end diff --git a/app/models/commit.rb b/app/models/commit.rb index 20bb93f4663..1fbda6f6acc 100644 --- a/app/models/commit.rb +++ b/app/models/commit.rb @@ -230,11 +230,7 @@ class Commit project.pipelines.where(sha: sha) end - def status - status_for(nil) - end - - def status_for(ref) + def status(ref = nil) if @statuses.key?(ref) @statuses[ref] elsif ref diff --git a/app/views/projects/_last_commit.html.haml b/app/views/projects/_last_commit.html.haml index 593967d9310..8aa503159f9 100644 --- a/app/views/projects/_last_commit.html.haml +++ b/app/views/projects/_last_commit.html.haml @@ -1,4 +1,4 @@ -- status = commit.status_for(ref) +- status = commit.status(ref) - if status = link_to builds_namespace_project_commit_path(commit.project.namespace, commit.project, commit), class: "ci-status ci-#{status}" do = ci_icon_for_status(status) diff --git a/app/views/projects/commits/_commit.html.haml b/app/views/projects/commits/_commit.html.haml index c5830b5b7f7..fd70de9c13d 100644 --- a/app/views/projects/commits/_commit.html.haml +++ b/app/views/projects/commits/_commit.html.haml @@ -18,14 +18,14 @@ %span.commit-row-message.visible-xs-inline · = commit.short_id - - if commit.status_for(ref) + - if commit.status(ref) .visible-xs-inline = render_commit_status(commit, ref: ref) - if commit.description? %a.text-expander.hidden-xs.js-toggle-button ... .commit-actions.hidden-xs - - if commit.status_for(ref) + - if commit.status(ref) = render_commit_status(commit, ref: ref) = clipboard_button(clipboard_text: commit.id) = link_to commit.short_id, namespace_project_commit_path(project.namespace, project, commit), class: "commit-short-id btn btn-transparent" diff --git a/spec/models/commit_spec.rb b/spec/models/commit_spec.rb index 468e198e9ea..203fb6596a6 100644 --- a/spec/models/commit_spec.rb +++ b/spec/models/commit_spec.rb @@ -210,49 +210,51 @@ eos end describe '#status' do - shared_examples 'giving the status from pipeline' do - it do - expect(commit.status).to eq(Ci::Pipeline.status) + context 'without arguments for compound status' do + shared_examples 'giving the status from pipeline' do + it do + expect(commit.status).to eq(Ci::Pipeline.status) + end + end + + context 'with pipelines' do + let!(:pipeline) do + create(:ci_empty_pipeline, project: project, sha: commit.sha) + end + + it_behaves_like 'giving the status from pipeline' + end + + context 'without pipelines' do + it_behaves_like 'giving the status from pipeline' end end - context 'with pipelines' do - let!(:pipeline) do - create(:ci_empty_pipeline, project: project, sha: commit.sha) + context 'when a particular ref is specified' do + let!(:pipeline_from_master) do + create(:ci_empty_pipeline, + project: project, + sha: commit.sha, + ref: 'master', + status: 'failed') end - it_behaves_like 'giving the status from pipeline' - end + let!(:pipeline_from_fix) do + create(:ci_empty_pipeline, + project: project, + sha: commit.sha, + ref: 'fix', + status: 'success') + end - context 'without pipelines' do - it_behaves_like 'giving the status from pipeline' - end - end + it 'gives pipelines from a particular branch' do + expect(commit.status('master')).to eq(pipeline_from_master.status) + expect(commit.status('fix')).to eq(pipeline_from_fix.status) + end - describe '#status_for' do - let!(:pipeline_from_master) do - create(:ci_empty_pipeline, - project: project, - sha: commit.sha, - ref: 'master', - status: 'failed') - end - - let!(:pipeline_from_fix) do - create(:ci_empty_pipeline, - project: project, - sha: commit.sha, - ref: 'fix', - status: 'success') - end - - it 'gives pipelines from a particular branch' do - expect(commit.status_for('master')).to eq(pipeline_from_master.status) - expect(commit.status_for('fix')).to eq(pipeline_from_fix.status) - end - - it 'gives compound status if ref is nil' do - expect(commit.status_for(nil)).to eq(commit.status) + it 'gives compound status if ref is nil' do + expect(commit.status(nil)).to eq(commit.status) + end end end From 0902ba524f6bfa7f7f6d234378c8847b541d1586 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Thu, 3 Nov 2016 23:43:17 +0800 Subject: [PATCH 070/175] Initialize @statuses in status rather than constructor Feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7034#note_17742312 --- app/models/commit.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/models/commit.rb b/app/models/commit.rb index 1fbda6f6acc..9e7fde9503d 100644 --- a/app/models/commit.rb +++ b/app/models/commit.rb @@ -57,7 +57,6 @@ class Commit @raw = raw_commit @project = project - @statuses = {} end def id @@ -231,6 +230,8 @@ class Commit end def status(ref = nil) + @statuses ||= {} + if @statuses.key?(ref) @statuses[ref] elsif ref From f3c3d8e63ba078e55c0ce516e19ec11cea429e43 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Fri, 4 Nov 2016 00:00:03 +0800 Subject: [PATCH 071/175] There's no such method --- spec/models/commit_spec.rb | 4 ---- 1 file changed, 4 deletions(-) diff --git a/spec/models/commit_spec.rb b/spec/models/commit_spec.rb index 203fb6596a6..e3bb3482d67 100644 --- a/spec/models/commit_spec.rb +++ b/spec/models/commit_spec.rb @@ -205,10 +205,6 @@ eos end end - describe '#ci_commits' do - # TODO: kamil - end - describe '#status' do context 'without arguments for compound status' do shared_examples 'giving the status from pipeline' do From 4664188824efd968fe870ec5f7893598e6b078f3 Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Gray Date: Thu, 3 Nov 2016 09:26:22 -0500 Subject: [PATCH 072/175] Update avatar container name so it doesnt conflict with other image containers --- app/assets/stylesheets/framework/avatar.scss | 10 +++++----- app/views/admin/groups/_group.html.haml | 2 +- app/views/admin/groups/show.html.haml | 2 +- app/views/admin/projects/index.html.haml | 2 +- app/views/groups/edit.html.haml | 2 +- app/views/groups/show.html.haml | 2 +- app/views/projects/_home_panel.html.haml | 2 +- app/views/projects/edit.html.haml | 2 +- app/views/shared/groups/_group.html.haml | 2 +- app/views/shared/projects/_project.html.haml | 2 +- app/views/users/_groups.html.haml | 2 +- 11 files changed, 15 insertions(+), 15 deletions(-) diff --git a/app/assets/stylesheets/framework/avatar.scss b/app/assets/stylesheets/framework/avatar.scss index ce117c3fba5..202ed5ae8fe 100644 --- a/app/assets/stylesheets/framework/avatar.scss +++ b/app/assets/stylesheets/framework/avatar.scss @@ -4,7 +4,7 @@ margin-right: $margin-right; } -.avatar-container { +.avatar-circle { float: left; margin-right: 15px; border-radius: $avatar_radius; @@ -27,7 +27,7 @@ } .avatar { - @extend .avatar-container; + @extend .avatar-circle; width: 40px; height: 40px; padding: 0; @@ -64,8 +64,8 @@ &.s160 { font-size: 96px; line-height: 158px; } } -.image-container { - @extend .avatar-container; +.avatar-container { + @extend .avatar-circle; overflow: hidden; display: flex; @@ -76,4 +76,4 @@ margin: 0; align-self: center; } -} \ No newline at end of file +} diff --git a/app/views/admin/groups/_group.html.haml b/app/views/admin/groups/_group.html.haml index 05c88ca1cc8..664bb417c6a 100644 --- a/app/views/admin/groups/_group.html.haml +++ b/app/views/admin/groups/_group.html.haml @@ -16,7 +16,7 @@ %span.visibility-icon.has-tooltip{data: { container: 'body', placement: 'left' }, title: visibility_icon_description(group)} = visibility_level_icon(group.visibility_level, fw: false) - .image-container.s40 + .avatar-container.s40 = image_tag group_icon(group), class: "avatar s40 hidden-xs" .title = link_to [:admin, group], class: 'group-name' do diff --git a/app/views/admin/groups/show.html.haml b/app/views/admin/groups/show.html.haml index a7c1a4f5038..40871e32913 100644 --- a/app/views/admin/groups/show.html.haml +++ b/app/views/admin/groups/show.html.haml @@ -13,7 +13,7 @@ Group info: %ul.well-list %li - .image-container.s60 + .avatar-container.s60 = image_tag group_icon(@group), class: "avatar s60" %li %span.light Name: diff --git a/app/views/admin/projects/index.html.haml b/app/views/admin/projects/index.html.haml index 10dce6f3d8f..b37b8d4fee7 100644 --- a/app/views/admin/projects/index.html.haml +++ b/app/views/admin/projects/index.html.haml @@ -76,7 +76,7 @@ .title = link_to [:admin, project.namespace.becomes(Namespace), project] do .dash-project-avatar - .image-container.s40 + .avatar-container.s40 = project_icon(project, alt: '', class: 'avatar project-avatar s40') %span.project-full-name %span.namespace-name diff --git a/app/views/groups/edit.html.haml b/app/views/groups/edit.html.haml index f84ac37fa8f..fe5837eccfd 100644 --- a/app/views/groups/edit.html.haml +++ b/app/views/groups/edit.html.haml @@ -8,7 +8,7 @@ .form-group .col-sm-offset-2.col-sm-10 - .image-container.s160 + .avatar-container.s160 = image_tag group_icon(@group), alt: '', class: 'avatar group-avatar s160' %p.light - if @group.avatar? diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml index 275581b3af8..b439b40a75a 100644 --- a/app/views/groups/show.html.haml +++ b/app/views/groups/show.html.haml @@ -6,7 +6,7 @@ .cover-block.groups-cover-block %div{ class: container_class } - .image-container.s70.group-avatar + .avatar-container.s70.group-avatar = image_tag group_icon(@group), class: "avatar s70 avatar-tile" .group-info .cover-title diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml index e67b66d1fff..5a04c3318cf 100644 --- a/app/views/projects/_home_panel.html.haml +++ b/app/views/projects/_home_panel.html.haml @@ -1,7 +1,7 @@ - empty_repo = @project.empty_repo? .project-home-panel.text-center{ class: ("empty-project" if empty_repo) } %div{ class: container_class } - .image-container.s70.project-avatar + .avatar-container.s70.project-avatar = project_icon(@project, alt: @project.name, class: 'avatar s70 avatar-tile') %h1.project-title = @project.name diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml index c40ad06969e..93d5fb063e8 100644 --- a/app/views/projects/edit.html.haml +++ b/app/views/projects/edit.html.haml @@ -118,7 +118,7 @@ Project avatar .form-group - if @project.avatar? - .image-container.s160 + .avatar-container.s160 = project_icon("#{@project.namespace.to_param}/#{@project.to_param}", alt: '', class: 'avatar project-avatar s160') %p.light - if @project.avatar_in_git diff --git a/app/views/shared/groups/_group.html.haml b/app/views/shared/groups/_group.html.haml index 562291a61df..19221e3391f 100644 --- a/app/views/shared/groups/_group.html.haml +++ b/app/views/shared/groups/_group.html.haml @@ -24,7 +24,7 @@ %span.visibility-icon.has-tooltip{data: { container: 'body', placement: 'left' }, title: visibility_icon_description(group)} = visibility_level_icon(group.visibility_level, fw: false) - .image-container.s40 + .avatar-container.s40 = image_tag group_icon(group), class: "avatar s40 hidden-xs" .title = link_to group, class: 'group-name' do diff --git a/app/views/shared/projects/_project.html.haml b/app/views/shared/projects/_project.html.haml index 3d2122a159c..264391fe84f 100644 --- a/app/views/shared/projects/_project.html.haml +++ b/app/views/shared/projects/_project.html.haml @@ -32,7 +32,7 @@ = link_to project_path(project), class: dom_class(project) do - if avatar .dash-project-avatar - .image-container.s40 + .avatar-container.s40 - if use_creator_avatar = image_tag avatar_icon(project.creator.email, 40), class: "avatar s40", alt:'' - else diff --git a/app/views/users/_groups.html.haml b/app/views/users/_groups.html.haml index 78f253f9023..eff6c80d144 100644 --- a/app/views/users/_groups.html.haml +++ b/app/views/users/_groups.html.haml @@ -1,5 +1,5 @@ .clearfix - groups.each do |group| = link_to group, class: 'profile-groups-avatars inline', title: group.name do - .image-container.s40 + .avatar-container.s40 = image_tag group_icon(group), class: 'avatar group-avatar s40' From ce1dc4c25d3464b7a9a1b21d93157c9fed98f705 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Fri, 4 Nov 2016 02:42:27 +0800 Subject: [PATCH 073/175] Update for CHANGELOG --- CHANGELOG.md | 1 - changelogs/unreleased/show-status-from-branch.yml | 4 ++++ 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 changelogs/unreleased/show-status-from-branch.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index edcfedece5b..7efa9efa4f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,7 +38,6 @@ entry. - Fix filtering of milestones with quotes in title (airatshigapov) - Fix issue boards dragging bug in Safari - Refactor less readable existance checking code from CoffeeScript !6289 (jlogandavison) -- Fix showing pipeline status for a given commit from correct branch !7034 - Update mail_room and enable sentinel support to Reply By Email (!7101) - Add task completion status in Issues and Merge Requests tabs: "X of Y tasks completed" (!6527, @gmesalazar) - Simpler arguments passed to named_route on toggle_award_url helper method diff --git a/changelogs/unreleased/show-status-from-branch.yml b/changelogs/unreleased/show-status-from-branch.yml new file mode 100644 index 00000000000..6e51bf6932f --- /dev/null +++ b/changelogs/unreleased/show-status-from-branch.yml @@ -0,0 +1,4 @@ +--- +title: Fix showing pipeline status for a given commit from correct branch +merge_request: 7034 +author: Lin Jen-Shin From 17a6f942e0119ee8f1fab5b0476c73fd61a98191 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Fri, 4 Nov 2016 03:01:26 +0800 Subject: [PATCH 074/175] Update CHANGELOG --- CHANGELOG.md | 1 - changelogs/unreleased/pipeline-notifications.yml | 6 ++++++ 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 changelogs/unreleased/pipeline-notifications.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c193bfb9dc..82ede293a72 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,7 +20,6 @@ Please view this file on the master branch, on stable branches it's out of date. - Hides project activity tabs when features are disabled - Only show one error message for an invalid email !5905 (lycoperdon) - Added guide describing how to upgrade PostgreSQL using Slony -- Add CI notifications. Who triggered a pipeline would receive an email after the pipeline is succeeded or failed. Users could also update notification settings accordingly. !6342 - Fix sidekiq stats in admin area (blackst0ne) - Added label description as tooltip to issue board list title - Created cycle analytics bundle JavaScript file diff --git a/changelogs/unreleased/pipeline-notifications.yml b/changelogs/unreleased/pipeline-notifications.yml new file mode 100644 index 00000000000..e415444020f --- /dev/null +++ b/changelogs/unreleased/pipeline-notifications.yml @@ -0,0 +1,6 @@ +--- +title: Add CI notifications. Who triggered a pipeline would receive an email after + the pipeline is succeeded or failed. Users could also update notification settings + accordingly +merge_request: 6342 +author: Lin Jen-Shin From 251a20a30df6321191122f1d332f29757a2fc735 Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Thu, 3 Nov 2016 19:17:42 +0000 Subject: [PATCH 075/175] Split out markdown cache storage into a separate method --- lib/banzai/renderer.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/banzai/renderer.rb b/lib/banzai/renderer.rb index ce048a36fa0..f31fb6c3f71 100644 --- a/lib/banzai/renderer.rb +++ b/lib/banzai/renderer.rb @@ -46,7 +46,7 @@ module Banzai return html if html.present? html = cacheless_render_field(object, field) - object.update_column(html_field, html) unless object.new_record? || object.destroyed? + update_object(object, html_field, html) unless object.new_record? || object.destroyed? html end @@ -166,5 +166,9 @@ module Banzai return unless cache_key Rails.cache.send(:expanded_key, full_cache_key(cache_key, pipeline_name)) end + + def update_object(object, html_field, html) + object.update_column(html_field, html) + end end end From bea83d2579ca3b8ca48802f5c114cea60bce396e Mon Sep 17 00:00:00 2001 From: Hiroyuki Sato Date: Thu, 27 Oct 2016 10:47:14 +0900 Subject: [PATCH 076/175] Remove an extra leading space from diff content --- app/assets/javascripts/diff.js | 4 --- app/assets/stylesheets/pages/diff.scss | 33 ++++++++++--------- app/helpers/diff_helper.rb | 7 ++-- app/views/projects/diffs/_line.html.haml | 4 +-- ...remove-heading-space-from-diff-content.yml | 4 +++ spec/helpers/diff_helper_spec.rb | 2 +- 6 files changed, 28 insertions(+), 26 deletions(-) create mode 100644 changelogs/unreleased/remove-heading-space-from-diff-content.yml diff --git a/app/assets/javascripts/diff.js b/app/assets/javascripts/diff.js index 4ddafff428f..82bfdcea0ca 100644 --- a/app/assets/javascripts/diff.js +++ b/app/assets/javascripts/diff.js @@ -43,10 +43,6 @@ bottom: unfoldBottom, offset: offset, unfold: unfold, - // indent is used to compensate for single space indent to fit - // '+' and '-' prepended to diff lines, - // see https://gitlab.com/gitlab-org/gitlab-ce/issues/707 - indent: 1, view: file.data('view') }; return $.get(link, params, function(response) { diff --git a/app/assets/stylesheets/pages/diff.scss b/app/assets/stylesheets/pages/diff.scss index fde138c874d..99fdea15218 100644 --- a/app/assets/stylesheets/pages/diff.scss +++ b/app/assets/stylesheets/pages/diff.scss @@ -92,20 +92,6 @@ &.noteable_line { position: relative; - - &.old { - &::before { - content: '-'; - position: absolute; - } - } - - &.new { - &::before { - content: '+'; - position: absolute; - } - } } span { @@ -151,8 +137,9 @@ .line_content { display: block; margin: 0; - padding: 0 0.5em; + padding: 0 1.5em; border: none; + position: relative; &.parallel { display: table-cell; @@ -161,6 +148,22 @@ word-break: break-all; } } + + &.old { + &::before { + content: '-'; + position: absolute; + left: 0.5em; + } + } + + &.new { + &::before { + content: '+'; + position: absolute; + left: 0.5em; + } + } } .text-file.diff-wrap-lines table .line_holder td span { diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb index 0725c3f4c56..f489f9aa0d6 100644 --- a/app/helpers/diff_helper.rb +++ b/app/helpers/diff_helper.rb @@ -51,12 +51,11 @@ module DiffHelper html.html_safe end - def diff_line_content(line, line_type = nil) + def diff_line_content(line) if line.blank? - "  ".html_safe + " ".html_safe else - line[0] = ' ' if %w[new old].include?(line_type) - line + line.sub(/^[\-+ ]/, '').html_safe end end diff --git a/app/views/projects/diffs/_line.html.haml b/app/views/projects/diffs/_line.html.haml index 7042e9f1fc9..a3e4b5b777e 100644 --- a/app/views/projects/diffs/_line.html.haml +++ b/app/views/projects/diffs/_line.html.haml @@ -25,9 +25,9 @@ %a{href: "##{line_code}", data: { linenumber: link_text }} %td.line_content.noteable_line{ class: type, data: (diff_view_line_data(line_code, diff_file.position(line), type) unless plain) }< - if email - %pre= diff_line_content(line.text, type) + %pre= diff_line_content(line.text) - else - = diff_line_content(line.text, type) + = diff_line_content(line.text) - discussions = local_assigns.fetch(:discussions, nil) - if discussions && !line.meta? diff --git a/changelogs/unreleased/remove-heading-space-from-diff-content.yml b/changelogs/unreleased/remove-heading-space-from-diff-content.yml new file mode 100644 index 00000000000..1ea85784d29 --- /dev/null +++ b/changelogs/unreleased/remove-heading-space-from-diff-content.yml @@ -0,0 +1,4 @@ +--- +title: Remove an extra leading space from diff paste data +merge_request: 7133 +author: Hiroyuki Sato diff --git a/spec/helpers/diff_helper_spec.rb b/spec/helpers/diff_helper_spec.rb index 9c7c79f57c6..837e7afa7e8 100644 --- a/spec/helpers/diff_helper_spec.rb +++ b/spec/helpers/diff_helper_spec.rb @@ -61,7 +61,7 @@ describe DiffHelper do describe '#diff_line_content' do it 'returns non breaking space when line is empty' do - expect(diff_line_content(nil)).to eq('  ') + expect(diff_line_content(nil)).to eq(' ') end it 'returns the line itself' do From 27528d4490804c4bf5e16f44d12f9825cf7c6cef Mon Sep 17 00:00:00 2001 From: the-undefined Date: Thu, 3 Nov 2016 06:34:52 +0000 Subject: [PATCH 077/175] Move spinach public snippet feature to rspec spec - Add rspec feature for public snippets - Remove spinach test for public snippets --- features/snippets/public_snippets.feature | 10 -------- features/steps/snippets/public_snippets.rb | 25 ------------------- .../features/snippets/public_snippets_spec.rb | 19 ++++++++++++++ 3 files changed, 19 insertions(+), 35 deletions(-) delete mode 100644 features/snippets/public_snippets.feature delete mode 100644 features/steps/snippets/public_snippets.rb create mode 100644 spec/features/snippets/public_snippets_spec.rb diff --git a/features/snippets/public_snippets.feature b/features/snippets/public_snippets.feature deleted file mode 100644 index c2afb63b6d8..00000000000 --- a/features/snippets/public_snippets.feature +++ /dev/null @@ -1,10 +0,0 @@ -Feature: Public snippets - Scenario: Unauthenticated user should see public snippets - Given There is public "Personal snippet one" snippet - And I visit snippet page "Personal snippet one" - Then I should see snippet "Personal snippet one" - - Scenario: Unauthenticated user should see raw public snippets - Given There is public "Personal snippet one" snippet - And I visit snippet raw page "Personal snippet one" - Then I should see raw snippet "Personal snippet one" diff --git a/features/steps/snippets/public_snippets.rb b/features/steps/snippets/public_snippets.rb deleted file mode 100644 index 2ebdca5ed30..00000000000 --- a/features/steps/snippets/public_snippets.rb +++ /dev/null @@ -1,25 +0,0 @@ -class Spinach::Features::PublicSnippets < Spinach::FeatureSteps - include SharedAuthentication - include SharedPaths - include SharedSnippet - - step 'I should see snippet "Personal snippet one"' do - expect(page).to have_no_xpath("//i[@class='public-snippet']") - end - - step 'I should see raw snippet "Personal snippet one"' do - expect(page).to have_text(snippet.content) - end - - step 'I visit snippet page "Personal snippet one"' do - visit snippet_path(snippet) - end - - step 'I visit snippet raw page "Personal snippet one"' do - visit raw_snippet_path(snippet) - end - - def snippet - @snippet ||= PersonalSnippet.find_by!(title: "Personal snippet one") - end -end diff --git a/spec/features/snippets/public_snippets_spec.rb b/spec/features/snippets/public_snippets_spec.rb new file mode 100644 index 00000000000..34300ccb940 --- /dev/null +++ b/spec/features/snippets/public_snippets_spec.rb @@ -0,0 +1,19 @@ +require 'rails_helper' + +feature 'Public Snippets', feature: true do + scenario 'Unauthenticated user should see public snippets' do + public_snippet = create(:personal_snippet, :public) + + visit snippet_path(public_snippet) + + expect(page).to have_content(public_snippet.content) + end + + scenario 'Unauthenticated user should see raw public snippets' do + public_snippet = create(:personal_snippet, :public) + + visit raw_snippet_path(public_snippet) + + expect(page).to have_content(public_snippet.content) + end +end From a2c1178c21796933916bb44b3d6b8e4d11d89d7f Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Fri, 4 Nov 2016 10:16:30 +0100 Subject: [PATCH 078/175] Expose commit author if author exists --- app/serializers/commit_entity.rb | 2 ++ spec/serializers/environment_serializer_spec.rb | 11 ++++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/app/serializers/commit_entity.rb b/app/serializers/commit_entity.rb index ae53de0c750..3b6c2323e3e 100644 --- a/app/serializers/commit_entity.rb +++ b/app/serializers/commit_entity.rb @@ -1,6 +1,8 @@ class CommitEntity < API::Entities::RepoCommit include RequestAwareEntity + expose :author, using: API::Entities::UserBasic + expose :commit_url do |commit| @urls.namespace_project_tree_url( @request.project.namespace, diff --git a/spec/serializers/environment_serializer_spec.rb b/spec/serializers/environment_serializer_spec.rb index 32f144faf54..37bc086826c 100644 --- a/spec/serializers/environment_serializer_spec.rb +++ b/spec/serializers/environment_serializer_spec.rb @@ -7,6 +7,7 @@ describe EnvironmentSerializer do .represent(resource) end + let(:json) { serializer.as_json } let(:user) { create(:user) } let(:project) { create(:project) } @@ -27,16 +28,16 @@ describe EnvironmentSerializer do let(:resource) { deployment.environment } it 'it generates payload for single object' do - expect(serializer.as_json).to be_an_instance_of Hash + expect(json).to be_an_instance_of Hash end it 'contains important elements of environment' do - expect(serializer.as_json) + expect(json) .to include(:name, :external_url, :environment_url, :last_deployment) end it 'contains relevant information about last deployment' do - last_deployment = serializer.as_json.fetch(:last_deployment) + last_deployment = json.fetch(:last_deployment) expect(last_deployment) .to include(:ref, :user, :commit, :deployable, :manual_actions) @@ -48,12 +49,12 @@ describe EnvironmentSerializer do let(:resource) { create_list(:environment, 2) } it 'contains important elements of environment' do - expect(serializer.as_json.first) + expect(json.first) .to include(:last_deployment, :name, :external_url) end it 'generates payload for collection' do - expect(serializer.as_json).to be_an_instance_of Array + expect(json).to be_an_instance_of Array end end end From c315332b8a90d26197ad93a6e982888aa575e2d4 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Fri, 4 Nov 2016 10:19:29 +0100 Subject: [PATCH 079/175] Refine build entity tests a little --- spec/serializers/build_entity_spec.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/spec/serializers/build_entity_spec.rb b/spec/serializers/build_entity_spec.rb index b7acc2066ba..2282b560d7f 100644 --- a/spec/serializers/build_entity_spec.rb +++ b/spec/serializers/build_entity_spec.rb @@ -1,10 +1,12 @@ require 'spec_helper' describe BuildEntity do - subject do - described_class.new(build, request: double).as_json + let(:entity) do + described_class.new(build, request: double) end + subject { entity.as_json } + context 'when build is a regular job' do let(:build) { create(:ci_build) } From 7108e2e75362aec227765820e116e3d7bc1ac08d Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Fri, 4 Nov 2016 09:29:52 +0000 Subject: [PATCH 080/175] Fix new branch button spec 1. We can create the note directly on the issue, rather than attaching it after creation. 2. We need to update the MergeRequestClosesIssues relation to ensure that the issue know that it's closed by the MR. 3. We should also check that the unavailable button is displayed - not just that the available button is displayed. --- spec/features/issues/new_branch_button_spec.rb | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/spec/features/issues/new_branch_button_spec.rb b/spec/features/issues/new_branch_button_spec.rb index fb0c4704285..755f4eb1b0b 100644 --- a/spec/features/issues/new_branch_button_spec.rb +++ b/spec/features/issues/new_branch_button_spec.rb @@ -18,8 +18,8 @@ feature 'Start new branch from an issue', feature: true do end context "when there is a referenced merge request" do - let(:note) do - create(:note, :on_issue, :system, project: project, + let!(:note) do + create(:note, :on_issue, :system, project: project, noteable: issue, note: "Mentioned in !#{referenced_mr.iid}") end let(:referenced_mr) do @@ -28,12 +28,13 @@ feature 'Start new branch from an issue', feature: true do end before do - issue.notes << note + referenced_mr.cache_merge_request_closes_issues!(user) visit namespace_project_issue_path(project.namespace, project, issue) end it "hides the new branch button", js: true do + expect(page).to have_css('#new-branch .unavailable') expect(page).not_to have_css('#new-branch .available') expect(page).to have_content /1 Related Merge Request/ end From 277712cc670684ed6df162f810f860215da2a7ee Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 7 Oct 2016 16:18:42 +0100 Subject: [PATCH 081/175] Creates new list from a new label Closes #23026 --- CHANGELOG.md | 1 + .../components/new_list_dropdown.js.es6 | 13 +++++++++++++ app/assets/javascripts/create_label.js.es6 | 2 ++ spec/features/boards/boards_spec.rb | 19 +++++++++++++++++++ 4 files changed, 35 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index dd6b4e0ba11..615f7e42088 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ entry. - Adds support for the `token` attribute in project hooks API (Gauvain Pocentek) - Adds an optional path parameter to the Commits API to filter commits by path (Luis HGO) - Fix Markdown styling inside reference links (Jan Zdráhal) +- Create new issue board list after creating a new label - Fix extra space on Build sidebar on Firefox !7060 - Fail gracefully when creating merge request with non-existing branch (alexsanford) - Fix mobile layout issues in admin user overview page !7087 diff --git a/app/assets/javascripts/boards/components/new_list_dropdown.js.es6 b/app/assets/javascripts/boards/components/new_list_dropdown.js.es6 index fe1a6dc7ea0..14f618fd5d5 100644 --- a/app/assets/javascripts/boards/components/new_list_dropdown.js.es6 +++ b/app/assets/javascripts/boards/components/new_list_dropdown.js.es6 @@ -2,6 +2,19 @@ $(() => { const Store = gl.issueBoards.BoardsStore; + $(document).off('created.label').on('created.label', (e, label) => { + Store.new({ + title: label.title, + position: Store.state.lists.length - 2, + list_type: 'label', + label: { + id: label.id, + title: label.title, + color: label.color + } + }); + }); + $('.js-new-board-list').each(function () { const $this = $(this); new gl.CreateLabelDropdown($this.closest('.dropdown').find('.dropdown-new-label'), $this.data('namespace-path'), $this.data('project-path')); diff --git a/app/assets/javascripts/create_label.js.es6 b/app/assets/javascripts/create_label.js.es6 index f20580b1279..744aa0afa03 100644 --- a/app/assets/javascripts/create_label.js.es6 +++ b/app/assets/javascripts/create_label.js.es6 @@ -115,6 +115,8 @@ .show(); } else { this.$dropdownBack.trigger('click'); + + $(document).trigger('created.label', label); } }); } diff --git a/spec/features/boards/boards_spec.rb b/spec/features/boards/boards_spec.rb index a92075fec8f..6cb8753e8fc 100644 --- a/spec/features/boards/boards_spec.rb +++ b/spec/features/boards/boards_spec.rb @@ -380,6 +380,25 @@ describe 'Issue Boards', feature: true, js: true do wait_for_board_cards(1, 5) end + + it 'creates new list from a new label' do + click_button 'Create new list' + + wait_for_ajax + + click_link 'Create new label' + + fill_in('new_label_name', with: 'Testing New Label') + + first('.suggest-colors a').click + + click_button 'Create' + + wait_for_ajax + wait_for_vue_resource + + expect(page).to have_selector('.board', count: 5) + end end end From 3c4a7f915dfece1ea15185b9f2a1ea5c54e7643f Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Mon, 17 Oct 2016 07:48:48 -0400 Subject: [PATCH 082/175] Add width to caret to rid ourselves of the shift Add CHANGELOG uses fa-fw from font awesome instead of using declaring fix width explicitly moves changelog entry under 8.14 rebased with master --- CHANGELOG.md | 1 + app/views/projects/diffs/_file_header.html.haml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9411cc62003..027e7ea74b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ entry. - Show correct environment log in admin/logs (@duk3luk3 !7191) - Fix Milestone dropdown not stay selected for `Upcoming` and `No Milestone` option !7117 +- Diff collapse won't shift when collapsing. - Backups do not fail anymore when using tar on annex and custom_hooks only. !5814 - Adds user project membership expired event to clarify why user was removed (Callum Dryden) - Trim leading and trailing whitespace on project_path (Linus Thiel) diff --git a/app/views/projects/diffs/_file_header.html.haml b/app/views/projects/diffs/_file_header.html.haml index 73993f35b39..d3ed8e1bf38 100644 --- a/app/views/projects/diffs/_file_header.html.haml +++ b/app/views/projects/diffs/_file_header.html.haml @@ -1,4 +1,4 @@ -%i.fa.diff-toggle-caret +%i.fa.diff-toggle-caret.fa-fw - if defined?(blob) && blob && diff_file.submodule? %span = icon('archive fw') From 3968b07d7ea1fd2ca07e427a487ea94ca0c6081d Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Fri, 4 Nov 2016 13:08:58 +0100 Subject: [PATCH 083/175] Add tests for serialization entities, add user entity --- app/serializers/commit_entity.rb | 2 +- app/serializers/deployment_entity.rb | 2 +- app/serializers/user_entity.rb | 2 ++ spec/serializers/build_entity_spec.rb | 5 +++ spec/serializers/commit_entity_spec.rb | 44 ++++++++++++++++++++++++++ spec/serializers/user_entity_spec.rb | 23 ++++++++++++++ 6 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 app/serializers/user_entity.rb create mode 100644 spec/serializers/commit_entity_spec.rb create mode 100644 spec/serializers/user_entity_spec.rb diff --git a/app/serializers/commit_entity.rb b/app/serializers/commit_entity.rb index 3b6c2323e3e..827782e85bb 100644 --- a/app/serializers/commit_entity.rb +++ b/app/serializers/commit_entity.rb @@ -1,7 +1,7 @@ class CommitEntity < API::Entities::RepoCommit include RequestAwareEntity - expose :author, using: API::Entities::UserBasic + expose :author, using: UserEntity expose :commit_url do |commit| @urls.namespace_project_tree_url( diff --git a/app/serializers/deployment_entity.rb b/app/serializers/deployment_entity.rb index d3ed6a5eef4..d743b44c4a0 100644 --- a/app/serializers/deployment_entity.rb +++ b/app/serializers/deployment_entity.rb @@ -20,7 +20,7 @@ class DeploymentEntity < Grape::Entity expose :tag expose :last? - expose :user, using: API::Entities::UserBasic + expose :user, using: UserEntity expose :commit, using: CommitEntity expose :deployable, using: BuildEntity expose :manual_actions, using: BuildEntity diff --git a/app/serializers/user_entity.rb b/app/serializers/user_entity.rb new file mode 100644 index 00000000000..43754ea94f7 --- /dev/null +++ b/app/serializers/user_entity.rb @@ -0,0 +1,2 @@ +class UserEntity < API::Entities::UserBasic +end diff --git a/spec/serializers/build_entity_spec.rb b/spec/serializers/build_entity_spec.rb index 2282b560d7f..2734f5bedca 100644 --- a/spec/serializers/build_entity_spec.rb +++ b/spec/serializers/build_entity_spec.rb @@ -14,6 +14,11 @@ describe BuildEntity do expect(subject).to include(:build_url, :retry_url) expect(subject).not_to include(:play_url) end + + it 'does not contain sensitive information' do + expect(subject).not_to include(/token/) + expect(subject).not_to include(/variables/) + end end context 'when build is a manual action' do diff --git a/spec/serializers/commit_entity_spec.rb b/spec/serializers/commit_entity_spec.rb new file mode 100644 index 00000000000..628e35c9a28 --- /dev/null +++ b/spec/serializers/commit_entity_spec.rb @@ -0,0 +1,44 @@ +require 'spec_helper' + +describe CommitEntity do + let(:entity) do + described_class.new(commit, request: request) + end + + let(:request) { double('request') } + let(:project) { create(:project) } + let(:commit) { project.commit } + + subject { entity.as_json } + + before do + allow(request).to receive(:project).and_return(project) + end + + context 'when commit author is a user' do + before do + create(:user, email: commit.author_email) + end + + it 'contains information about user' do + expect(subject.fetch(:author)).not_to be_nil + end + end + + context 'when commit author is not a user' do + it 'does not contain author details' do + expect(subject.fetch(:author)).to be_nil + end + end + + it 'contains commit URL' do + expect(subject).to include(:commit_url) + end + + it 'needs to receive project in the request' do + expect(request).to receive(:project) + .and_return(project) + + subject + end +end diff --git a/spec/serializers/user_entity_spec.rb b/spec/serializers/user_entity_spec.rb new file mode 100644 index 00000000000..c5d11cbcf5e --- /dev/null +++ b/spec/serializers/user_entity_spec.rb @@ -0,0 +1,23 @@ +require 'spec_helper' + +describe UserEntity do + let(:entity) { described_class.new(user) } + let(:user) { create(:user) } + subject { entity.as_json } + + it 'exposes user name and login' do + expect(subject).to include(:username, :name) + end + + it 'does not expose passwords' do + expect(subject).not_to include(/password/) + end + + it 'does not expose tokens' do + expect(subject).not_to include(/token/) + end + + it 'does not expose 2FA OTPs' do + expect(subject).not_to include(/otp/) + end +end From e49fb264e6cb5eff44330d69d34b5f74ef262659 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Fri, 4 Nov 2016 13:23:06 +0100 Subject: [PATCH 084/175] Add tests for deployment and environment entitites --- spec/serializers/deployment_entity_spec.rb | 20 ++++++++++++++++++++ spec/serializers/environment_entity_spec.rb | 18 ++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 spec/serializers/deployment_entity_spec.rb create mode 100644 spec/serializers/environment_entity_spec.rb diff --git a/spec/serializers/deployment_entity_spec.rb b/spec/serializers/deployment_entity_spec.rb new file mode 100644 index 00000000000..51b6de91571 --- /dev/null +++ b/spec/serializers/deployment_entity_spec.rb @@ -0,0 +1,20 @@ +require 'spec_helper' + +describe DeploymentEntity do + let(:entity) do + described_class.new(deployment, request: double) + end + + let(:deployment) { create(:deployment) } + + subject { entity.as_json } + + it 'exposes internal deployment id' do + expect(subject).to include(:iid) + end + + it 'exposes nested information about branch' do + expect(subject[:ref][:name]).to eq 'master' + expect(subject[:ref][:ref_url]).not_to be_empty + end +end diff --git a/spec/serializers/environment_entity_spec.rb b/spec/serializers/environment_entity_spec.rb new file mode 100644 index 00000000000..4ca8c299147 --- /dev/null +++ b/spec/serializers/environment_entity_spec.rb @@ -0,0 +1,18 @@ +require 'spec_helper' + +describe EnvironmentEntity do + let(:entity) do + described_class.new(environment, request: double) + end + + let(:environment) { create(:environment) } + subject { entity.as_json } + + it 'exposes latest deployment' do + expect(subject).to include(:last_deployment) + end + + it 'exposes core elements of environment' do + expect(subject).to include(:id, :name, :state, :environment_url) + end +end From 6bcc52a53678ca68001189c801497862d3f6e758 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Thu, 27 Oct 2016 14:59:52 +0200 Subject: [PATCH 085/175] Refine Git garbage collection --- .../admin/application_settings_controller.rb | 5 + app/models/application_setting.rb | 17 +++ app/services/projects/housekeeping_service.rb | 59 +++++++-- .../application_settings/_form.html.haml | 39 ++++++ app/workers/git_garbage_collect_worker.rb | 47 ++++++- changelogs/unreleased/git-gc-improvements.yml | 4 + ...dd_housekeeping_to_application_settings.rb | 32 +++++ db/schema.rb | 5 + doc/administration/housekeeping.md | 8 ++ lib/gitlab/backend/shell.rb | 13 -- lib/gitlab/exclusive_lease.rb | 68 ++++------ spec/lib/gitlab/backend/shell_spec.rb | 1 - spec/lib/gitlab/exclusive_lease_spec.rb | 27 +++- spec/models/application_setting_spec.rb | 18 +++ .../projects/housekeeping_service_spec.rb | 28 +++- .../git_garbage_collect_worker_spec.rb | 122 ++++++++++++++++-- 16 files changed, 410 insertions(+), 83 deletions(-) create mode 100644 changelogs/unreleased/git-gc-improvements.yml create mode 100644 db/migrate/20161031155516_add_housekeeping_to_application_settings.rb diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb index 86e808314f4..52e0256943a 100644 --- a/app/controllers/admin/application_settings_controller.rb +++ b/app/controllers/admin/application_settings_controller.rb @@ -117,6 +117,11 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController :send_user_confirmation_email, :container_registry_token_expire_delay, :enabled_git_access_protocol, + :housekeeping_enabled, + :housekeeping_bitmaps_enabled, + :housekeeping_incremental_repack_period, + :housekeeping_full_repack_period, + :housekeeping_gc_period, repository_storages: [], restricted_visibility_levels: [], import_sources: [], diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb index 6e7a90e7d9c..fa5188ca27b 100644 --- a/app/models/application_setting.rb +++ b/app/models/application_setting.rb @@ -85,6 +85,18 @@ class ApplicationSetting < ActiveRecord::Base presence: { message: 'Domain blacklist cannot be empty if Blacklist is enabled.' }, if: :domain_blacklist_enabled? + validates :housekeeping_incremental_repack_period, + presence: true, + numericality: { only_integer: true, greater_than: 0 } + + validates :housekeeping_full_repack_period, + presence: true, + numericality: { only_integer: true, greater_than: :housekeeping_incremental_repack_period } + + validates :housekeeping_gc_period, + presence: true, + numericality: { only_integer: true, greater_than: :housekeeping_full_repack_period } + validates_each :restricted_visibility_levels do |record, attr, value| unless value.nil? value.each do |level| @@ -168,6 +180,11 @@ class ApplicationSetting < ActiveRecord::Base container_registry_token_expire_delay: 5, repository_storages: ['default'], user_default_external: false, + housekeeping_enabled: true, + housekeeping_bitmaps_enabled: true, + housekeeping_incremental_repack_period: 10, + housekeeping_full_repack_period: 50, + housekeeping_gc_period: 200, ) end diff --git a/app/services/projects/housekeeping_service.rb b/app/services/projects/housekeeping_service.rb index c3dfc8cfbe8..4b8946f8ee2 100644 --- a/app/services/projects/housekeeping_service.rb +++ b/app/services/projects/housekeeping_service.rb @@ -7,6 +7,8 @@ # module Projects class HousekeepingService < BaseService + include Gitlab::CurrentSettings + LEASE_TIMEOUT = 3600 class LeaseTaken < StandardError @@ -20,13 +22,14 @@ module Projects end def execute - raise LeaseTaken unless try_obtain_lease + lease_uuid = try_obtain_lease + raise LeaseTaken unless lease_uuid.present? - execute_gitlab_shell_gc + execute_gitlab_shell_gc(lease_uuid) end def needed? - @project.pushes_since_gc >= 10 + pushes_since_gc > 0 && period_match? && housekeeping_enabled? end def increment! @@ -37,19 +40,59 @@ module Projects private - def execute_gitlab_shell_gc - GitGarbageCollectWorker.perform_async(@project.id) + def execute_gitlab_shell_gc(lease_uuid) + GitGarbageCollectWorker.perform_async(@project.id, task, lease_key, lease_uuid) ensure - Gitlab::Metrics.measure(:reset_pushes_since_gc) do - @project.reset_pushes_since_gc + if pushes_since_gc >= gc_period + Gitlab::Metrics.measure(:reset_pushes_since_gc) do + @project.reset_pushes_since_gc + end end end def try_obtain_lease Gitlab::Metrics.measure(:obtain_housekeeping_lease) do - lease = ::Gitlab::ExclusiveLease.new("project_housekeeping:#{@project.id}", timeout: LEASE_TIMEOUT) + lease = ::Gitlab::ExclusiveLease.new(lease_key, timeout: LEASE_TIMEOUT) lease.try_obtain end end + + def lease_key + "project_housekeeping:#{@project.id}" + end + + def pushes_since_gc + @project.pushes_since_gc + end + + def task + if pushes_since_gc % gc_period == 0 + :gc + elsif pushes_since_gc % full_repack_period == 0 + :full_repack + else + :incremental_repack + end + end + + def period_match? + [gc_period, full_repack_period, repack_period].any? { |period| pushes_since_gc % period == 0 } + end + + def housekeeping_enabled? + current_application_settings.housekeeping_enabled + end + + def gc_period + current_application_settings.housekeeping_gc_period + end + + def full_repack_period + current_application_settings.housekeeping_full_repack_period + end + + def repack_period + current_application_settings.housekeeping_incremental_repack_period + end end end diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml index 28003e5f509..450ec322f2c 100644 --- a/app/views/admin/application_settings/_form.html.haml +++ b/app/views/admin/application_settings/_form.html.haml @@ -422,5 +422,44 @@ Enable this option to include the name of the author of the issue, merge request or comment in the email body instead. + %fieldset + %legend Automatic Git repository housekeeping + .form-group + .col-sm-offset-2.col-sm-10 + .checkbox + = f.label :housekeeping_enabled do + = f.check_box :housekeeping_enabled + Enable automatic repository housekeeping (git repack, git gc) + .help-block + If you keep automatic housekeeping disabled for a long time Git + repository access on your GitLab server will become slower and your + repositories will use more disk space. We recommend to always leave + this enabled. + .checkbox + = f.label :housekeeping_bitmaps_enabled do + = f.check_box :housekeeping_bitmaps_enabled + Enable Git pack file bitmap creation + .help-block + Creating pack file bitmaps makes housekeeping take a little longer but + bitmaps should accelerate 'git clone' performance. + .form-group + = f.label :housekeeping_incremental_repack_period, 'Incremental repack period', class: 'control-label col-sm-2' + .col-sm-10 + = f.number_field :housekeeping_incremental_repack_period, class: 'form-control' + .help-block + Number of Git pushes after which an incremental 'git repack' is run. + .form-group + = f.label :housekeeping_full_repack_period, 'Full repack period', class: 'control-label col-sm-2' + .col-sm-10 + = f.number_field :housekeeping_full_repack_period, class: 'form-control' + .help-block + Number of Git pushes after which a full 'git repack' is run. + .form-group + = f.label :housekeeping_gc_period, 'Git GC period', class: 'control-label col-sm-2' + .col-sm-10 + = f.number_field :housekeeping_gc_period, class: 'form-control' + .help-block + Number of Git pushes after which 'git gc' is run. + .form-actions = f.submit 'Save', class: 'btn btn-save' diff --git a/app/workers/git_garbage_collect_worker.rb b/app/workers/git_garbage_collect_worker.rb index 65f8093b5b0..d369b639ae9 100644 --- a/app/workers/git_garbage_collect_worker.rb +++ b/app/workers/git_garbage_collect_worker.rb @@ -1,17 +1,58 @@ class GitGarbageCollectWorker include Sidekiq::Worker - include Gitlab::ShellAdapter include DedicatedSidekiqQueue + include Gitlab::CurrentSettings sidekiq_options retry: false - def perform(project_id) + def perform(project_id, task = :gc, lease_key = nil, lease_uuid = nil) project = Project.find(project_id) + task = task.to_sym + + cmd = command(task) + repo_path = project.repository.path_to_repo + description = "'#{cmd.join(' ')}' in #{repo_path}" + + Gitlab::GitLogger.info(description) + + output, status = Gitlab::Popen.popen(cmd, repo_path) + Gitlab::GitLogger.error("#{description} failed:\n#{output}") unless status.zero? - gitlab_shell.gc(project.repository_storage_path, project.path_with_namespace) # Refresh the branch cache in case garbage collection caused a ref lookup to fail + flush_ref_caches(project) if task == :gc + ensure + Gitlab::ExclusiveLease.cancel(lease_key, lease_uuid) if lease_key.present? && lease_uuid.present? + end + + private + + def command(task) + case task + when :gc + git(write_bitmaps: bitmaps_enabled?) + %w[gc] + when :full_repack + git(write_bitmaps: bitmaps_enabled?) + %w[repack -A -d --pack-kept-objects] + when :incremental_repack + # Normal git repack fails when bitmaps are enabled. It is impossible to + # create a bitmap here anyway. + git(write_bitmaps: false) + %w[repack -d] + else + raise "Invalid gc task: #{task.inspect}" + end + end + + def flush_ref_caches(project) project.repository.after_create_branch project.repository.branch_names project.repository.has_visible_content? end + + def bitmaps_enabled? + current_application_settings.housekeeping_bitmaps_enabled + end + + def git(write_bitmaps:) + config_value = write_bitmaps ? 'true' : 'false' + %W[git -c repack.writeBitmaps=#{config_value}] + end end diff --git a/changelogs/unreleased/git-gc-improvements.yml b/changelogs/unreleased/git-gc-improvements.yml new file mode 100644 index 00000000000..f15e667ce87 --- /dev/null +++ b/changelogs/unreleased/git-gc-improvements.yml @@ -0,0 +1,4 @@ +--- +title: Finer-grained Git gargage collection +merge_request: 6588 +author: diff --git a/db/migrate/20161031155516_add_housekeeping_to_application_settings.rb b/db/migrate/20161031155516_add_housekeeping_to_application_settings.rb new file mode 100644 index 00000000000..5a451fb575b --- /dev/null +++ b/db/migrate/20161031155516_add_housekeeping_to_application_settings.rb @@ -0,0 +1,32 @@ +# See http://doc.gitlab.com/ce/development/migration_style_guide.html +# for more information on how to write migrations for GitLab. + +class AddHousekeepingToApplicationSettings < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + # Set this constant to true if this migration requires downtime. + DOWNTIME = false + + # When a migration requires downtime you **must** uncomment the following + # constant and define a short and easy to understand explanation as to why the + # migration requires downtime. + # DOWNTIME_REASON = '' + + disable_ddl_transaction! + + def up + add_column_with_default(:application_settings, :housekeeping_enabled, :boolean, default: true, allow_null: false) + add_column_with_default(:application_settings, :housekeeping_bitmaps_enabled, :boolean, default: true, allow_null: false) + add_column_with_default(:application_settings, :housekeeping_incremental_repack_period, :integer, default: 10, allow_null: false) + add_column_with_default(:application_settings, :housekeeping_full_repack_period, :integer, default: 50, allow_null: false) + add_column_with_default(:application_settings, :housekeeping_gc_period, :integer, default: 200, allow_null: false) + end + + def down + remove_column(:application_settings, :housekeeping_enabled, :boolean, default: true, allow_null: false) + remove_column(:application_settings, :housekeeping_bitmaps_enabled, :boolean, default: true, allow_null: false) + remove_column(:application_settings, :housekeeping_incremental_repack_period, :integer, default: 10, allow_null: false) + remove_column(:application_settings, :housekeeping_full_repack_period, :integer, default: 50, allow_null: false) + remove_column(:application_settings, :housekeeping_gc_period, :integer, default: 200, allow_null: false) + end +end diff --git a/db/schema.rb b/db/schema.rb index dc088925d97..48cb24ed20d 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -98,6 +98,11 @@ ActiveRecord::Schema.define(version: 20161103171205) do t.text "help_page_text_html" t.text "shared_runners_text_html" t.text "after_sign_up_text_html" + t.boolean "housekeeping_enabled", default: true, null: false + t.boolean "housekeeping_bitmaps_enabled", default: true, null: false + t.integer "housekeeping_incremental_repack_period", default: 10, null: false + t.integer "housekeeping_full_repack_period", default: 50, null: false + t.integer "housekeeping_gc_period", default: 200, null: false end create_table "audit_events", force: :cascade do |t| diff --git a/doc/administration/housekeeping.md b/doc/administration/housekeeping.md index ad1fa98b63b..f846c06ca42 100644 --- a/doc/administration/housekeeping.md +++ b/doc/administration/housekeeping.md @@ -3,6 +3,14 @@ > [Introduced][ce-2371] in GitLab 8.4. --- +## Automatic housekeeping + +GitLab automatically runs `git gc` and `git repack` on repositories +after Git pushes. If needed you can change how often this happens, or +to turn it off, go to **Admin area > Settings** +(`/admin/application_settings`). + +## Manual housekeeping The housekeeping function runs `git gc` ([man page][man]) on the current project Git repository. diff --git a/lib/gitlab/backend/shell.rb b/lib/gitlab/backend/shell.rb index 9cec71a3222..82e194c1af1 100644 --- a/lib/gitlab/backend/shell.rb +++ b/lib/gitlab/backend/shell.rb @@ -127,19 +127,6 @@ module Gitlab 'rm-project', storage, "#{name}.git"]) end - # Gc repository - # - # storage - project storage path - # path - project path with namespace - # - # Ex. - # gc("/path/to/storage", "gitlab/gitlab-ci") - # - def gc(storage, path) - Gitlab::Utils.system_silent([gitlab_shell_projects_path, 'gc', - storage, "#{path}.git"]) - end - # Add new key to gitlab-shell # # Ex. diff --git a/lib/gitlab/exclusive_lease.rb b/lib/gitlab/exclusive_lease.rb index 7e8f35e9298..2dd42704396 100644 --- a/lib/gitlab/exclusive_lease.rb +++ b/lib/gitlab/exclusive_lease.rb @@ -1,66 +1,52 @@ +require 'securerandom' + module Gitlab # This class implements an 'exclusive lease'. We call it a 'lease' # because it has a set expiry time. We call it 'exclusive' because only # one caller may obtain a lease for a given key at a time. The # implementation is intended to work across GitLab processes and across - # servers. It is a 'cheap' alternative to using SQL queries and updates: + # servers. It is a cheap alternative to using SQL queries and updates: # you do not need to change the SQL schema to start using # ExclusiveLease. # - # It is important to choose the timeout wisely. If the timeout is very - # high (1 hour) then the throughput of your operation gets very low (at - # most once an hour). If the timeout is lower than how long your - # operation may take then you cannot count on exclusivity. For example, - # if the timeout is 10 seconds and you do an operation which may take 20 - # seconds then two overlapping operations may hold a lease for the same - # key at the same time. - # - # This class has no 'cancel' method. I originally decided against adding - # it because it would add complexity and a false sense of security. The - # complexity: instead of setting '1' we would have to set a UUID, and to - # delete it we would have to execute Lua on the Redis server to only - # delete the key if the value was our own UUID. Otherwise there is a - # chance that when you intend to cancel your lease you actually delete - # someone else's. The false sense of security: you cannot design your - # system to rely too much on the lease being cancelled after use because - # the calling (Ruby) process may crash or be killed. You _cannot_ count - # on begin/ensure blocks to cancel a lease, because the 'ensure' does - # not always run. Think of 'kill -9' from the Unicorn master for - # instance. - # - # If you find that leases are getting in your way, ask yourself: would - # it be enough to lower the lease timeout? Another thing that might be - # appropriate is to only use a lease for bulk/automated operations, and - # to ignore the lease when you get a single 'manual' user request (a - # button click). - # class ExclusiveLease - def initialize(key, timeout:) - @key, @timeout = key, timeout + LUA_CANCEL_SCRIPT = <<-EOS + local key, uuid = KEYS[1], ARGV[1] + if redis.call("get", key) == uuid then + redis.call("del", key) + end + EOS + + def self.cancel(key, uuid) + Gitlab::Redis.with do |redis| + redis.eval(LUA_CANCEL_SCRIPT, keys: [redis_key(key)], argv: [uuid]) + end end - # Try to obtain the lease. Return true on success, + def self.redis_key(key) + "gitlab:exclusive_lease:#{key}" + end + + def initialize(key, timeout:) + @redis_key = self.class.redis_key(key) + @timeout = timeout + @uuid = SecureRandom.uuid + end + + # Try to obtain the lease. Return lease UUID on success, # false if the lease is already taken. def try_obtain # Performing a single SET is atomic Gitlab::Redis.with do |redis| - !!redis.set(redis_key, '1', nx: true, ex: @timeout) + redis.set(@redis_key, @uuid, nx: true, ex: @timeout) && @uuid end end # Returns true if the key for this lease is set. def exists? Gitlab::Redis.with do |redis| - redis.exists(redis_key) + redis.exists(@redis_key) end end - - # No #cancel method. See comments above! - - private - - def redis_key - "gitlab:exclusive_lease:#{@key}" - end end end diff --git a/spec/lib/gitlab/backend/shell_spec.rb b/spec/lib/gitlab/backend/shell_spec.rb index f826d0d1b04..4b08a02ec73 100644 --- a/spec/lib/gitlab/backend/shell_spec.rb +++ b/spec/lib/gitlab/backend/shell_spec.rb @@ -14,7 +14,6 @@ describe Gitlab::Shell, lib: true do it { is_expected.to respond_to :add_repository } it { is_expected.to respond_to :remove_repository } it { is_expected.to respond_to :fork_repository } - it { is_expected.to respond_to :gc } it { is_expected.to respond_to :add_namespace } it { is_expected.to respond_to :rm_namespace } it { is_expected.to respond_to :mv_namespace } diff --git a/spec/lib/gitlab/exclusive_lease_spec.rb b/spec/lib/gitlab/exclusive_lease_spec.rb index 6b3bd08b978..a366d68a146 100644 --- a/spec/lib/gitlab/exclusive_lease_spec.rb +++ b/spec/lib/gitlab/exclusive_lease_spec.rb @@ -5,32 +5,47 @@ describe Gitlab::ExclusiveLease, type: :redis do describe '#try_obtain' do it 'cannot obtain twice before the lease has expired' do - lease = Gitlab::ExclusiveLease.new(unique_key, timeout: 3600) - expect(lease.try_obtain).to eq(true) + lease = described_class.new(unique_key, timeout: 3600) + expect(lease.try_obtain).to be_present expect(lease.try_obtain).to eq(false) end it 'can obtain after the lease has expired' do timeout = 1 - lease = Gitlab::ExclusiveLease.new(unique_key, timeout: timeout) + lease = described_class.new(unique_key, timeout: timeout) lease.try_obtain # start the lease sleep(2 * timeout) # lease should have expired now - expect(lease.try_obtain).to eq(true) + expect(lease.try_obtain).to be_present end end describe '#exists?' do it 'returns true for an existing lease' do - lease = Gitlab::ExclusiveLease.new(unique_key, timeout: 3600) + lease = described_class.new(unique_key, timeout: 3600) lease.try_obtain expect(lease.exists?).to eq(true) end it 'returns false for a lease that does not exist' do - lease = Gitlab::ExclusiveLease.new(unique_key, timeout: 3600) + lease = described_class.new(unique_key, timeout: 3600) expect(lease.exists?).to eq(false) end end + + describe '.cancel' do + it 'can cancel a lease' do + uuid = new_lease(unique_key) + expect(uuid).to be_present + expect(new_lease(unique_key)).to eq(false) + + described_class.cancel(unique_key, uuid) + expect(new_lease(unique_key)).to be_present + end + + def new_lease(key) + described_class.new(key, timeout: 3600).try_obtain + end + end end diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb index 2b76e056f3c..b950fcdd81a 100644 --- a/spec/models/application_setting_spec.rb +++ b/spec/models/application_setting_spec.rb @@ -98,6 +98,24 @@ describe ApplicationSetting, models: true do end end end + + context 'housekeeping settings' do + it { is_expected.not_to allow_value(0).for(:housekeeping_incremental_repack_period) } + + it 'wants the full repack period to be longer than the incremental repack period' do + subject.housekeeping_incremental_repack_period = 2 + subject.housekeeping_full_repack_period = 1 + + expect(subject).not_to be_valid + end + + it 'wants the gc period to be longer than the full repack period' do + subject.housekeeping_full_repack_period = 2 + subject.housekeeping_gc_period = 1 + + expect(subject).not_to be_valid + end + end end context 'restricted signup domains' do diff --git a/spec/services/projects/housekeeping_service_spec.rb b/spec/services/projects/housekeeping_service_spec.rb index cf90b33dfb4..57a5aa5cedc 100644 --- a/spec/services/projects/housekeeping_service_spec.rb +++ b/spec/services/projects/housekeeping_service_spec.rb @@ -14,8 +14,10 @@ describe Projects::HousekeepingService do describe '#execute' do it 'enqueues a sidekiq job' do - expect(subject).to receive(:try_obtain_lease).and_return(true) - expect(GitGarbageCollectWorker).to receive(:perform_async).with(project.id) + expect(subject).to receive(:try_obtain_lease).and_return(:the_uuid) + expect(subject).to receive(:lease_key).and_return(:the_lease_key) + expect(subject).to receive(:task).and_return(:the_task) + expect(GitGarbageCollectWorker).to receive(:perform_async).with(project.id, :the_task, :the_lease_key, :the_uuid) subject.execute expect(project.reload.pushes_since_gc).to eq(0) @@ -58,4 +60,26 @@ describe Projects::HousekeepingService do end.to change { project.pushes_since_gc }.from(0).to(1) end end + + it 'uses all three kinds of housekeeping we offer' do + allow(subject).to receive(:try_obtain_lease).and_return(:the_uuid) + allow(subject).to receive(:lease_key).and_return(:the_lease_key) + + # At push 200 + expect(GitGarbageCollectWorker).to receive(:perform_async).with(project.id, :gc, :the_lease_key, :the_uuid). + exactly(1).times + # At push 50, 100, 150 + expect(GitGarbageCollectWorker).to receive(:perform_async).with(project.id, :full_repack, :the_lease_key, :the_uuid). + exactly(3).times + # At push 10, 20, ... (except those above) + expect(GitGarbageCollectWorker).to receive(:perform_async).with(project.id, :incremental_repack, :the_lease_key, :the_uuid). + exactly(16).times + + 201.times do + subject.increment! + subject.execute if subject.needed? + end + + expect(project.pushes_since_gc).to eq(1) + end end diff --git a/spec/workers/git_garbage_collect_worker_spec.rb b/spec/workers/git_garbage_collect_worker_spec.rb index c9f5aae0815..ae258bde26d 100644 --- a/spec/workers/git_garbage_collect_worker_spec.rb +++ b/spec/workers/git_garbage_collect_worker_spec.rb @@ -1,3 +1,6 @@ +require 'digest' +require 'fileutils' + require 'spec_helper' describe GitGarbageCollectWorker do @@ -6,16 +9,12 @@ describe GitGarbageCollectWorker do subject { GitGarbageCollectWorker.new } - before do - allow(subject).to receive(:gitlab_shell).and_return(shell) - end - describe "#perform" do - it "runs `git gc`" do - expect(shell).to receive(:gc).with( - project.repository_storage_path, - project.path_with_namespace). - and_return(true) + it "flushes ref caches when the task is 'gc'" do + expect(subject).to receive(:command).with(:gc).and_return([:the, :command]) + expect(Gitlab::Popen).to receive(:popen). + with([:the, :command], project.repository.path_to_repo).and_return(["", 0]) + expect_any_instance_of(Repository).to receive(:after_create_branch).and_call_original expect_any_instance_of(Repository).to receive(:branch_names).and_call_original expect_any_instance_of(Repository).to receive(:branch_count).and_call_original @@ -23,5 +22,110 @@ describe GitGarbageCollectWorker do subject.perform(project.id) end + + shared_examples 'gc tasks' do + before { allow(subject).to receive(:bitmaps_enabled?).and_return(bitmaps_enabled) } + + it 'incremental repack adds a new packfile' do + create_objects(project) + before_packs = packs(project) + + expect(before_packs.count).to be >= 1 + + subject.perform(project.id, 'incremental_repack') + after_packs = packs(project) + + # Exactly one new pack should have been created + expect(after_packs.count).to eq(before_packs.count + 1) + + # Previously existing packs are still around + expect(before_packs & after_packs).to eq(before_packs) + end + + it 'full repack consolidates into 1 packfile' do + create_objects(project) + subject.perform(project.id, 'incremental_repack') + before_packs = packs(project) + + expect(before_packs.count).to be >= 2 + + subject.perform(project.id, 'full_repack') + after_packs = packs(project) + + expect(after_packs.count).to eq(1) + + # Previously existing packs should be gone now + expect(after_packs - before_packs).to eq(after_packs) + + expect(File.exist?(bitmap_path(after_packs.first))).to eq(bitmaps_enabled) + end + + it 'gc consolidates into 1 packfile and updates packed-refs' do + create_objects(project) + before_packs = packs(project) + before_packed_refs = packed_refs(project) + + expect(before_packs.count).to be >= 1 + + subject.perform(project.id, 'gc') + after_packed_refs = packed_refs(project) + after_packs = packs(project) + + expect(after_packs.count).to eq(1) + + # Previously existing packs should be gone now + expect(after_packs - before_packs).to eq(after_packs) + + # The packed-refs file should have been updated during 'git gc' + expect(before_packed_refs).not_to eq(after_packed_refs) + + expect(File.exist?(bitmap_path(after_packs.first))).to eq(bitmaps_enabled) + end + end + + context 'with bitmaps enabled' do + let(:bitmaps_enabled) { true } + + include_examples 'gc tasks' + end + + context 'with bitmaps disabled' do + let(:bitmaps_enabled) { false } + + include_examples 'gc tasks' + end + end + + # Create a new commit on a random new branch + def create_objects(project) + rugged = project.repository.rugged + old_commit = rugged.branches.first.target + new_commit_sha = Rugged::Commit.create( + rugged, + message: "hello world #{SecureRandom.hex(6)}", + author: Gitlab::Git::committer_hash(email: 'foo@bar', name: 'baz'), + committer: Gitlab::Git::committer_hash(email: 'foo@bar', name: 'baz'), + tree: old_commit.tree, + parents: [old_commit], + ) + project.repository.update_ref!( + "refs/heads/#{SecureRandom.hex(6)}", + new_commit_sha, + Gitlab::Git::BLANK_SHA + ) + end + + def packs(project) + Dir["#{project.repository.path_to_repo}/objects/pack/*.pack"] + end + + def packed_refs(project) + path = "#{project.repository.path_to_repo}/packed-refs" + FileUtils.touch(path) + File.read(path) + end + + def bitmap_path(pack) + pack.sub(/\.pack\z/, '.bitmap') end end From c5eca4a632d3be058a0094d269fb0aac88e130d5 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Fri, 4 Nov 2016 14:34:10 +0100 Subject: [PATCH 086/175] Remove unused 'require' --- spec/workers/git_garbage_collect_worker_spec.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/spec/workers/git_garbage_collect_worker_spec.rb b/spec/workers/git_garbage_collect_worker_spec.rb index ae258bde26d..e471a68a49a 100644 --- a/spec/workers/git_garbage_collect_worker_spec.rb +++ b/spec/workers/git_garbage_collect_worker_spec.rb @@ -1,4 +1,3 @@ -require 'digest' require 'fileutils' require 'spec_helper' From 6d6fb561a79716e7b12b7b63ba103724a3f60d29 Mon Sep 17 00:00:00 2001 From: Dimitrie Hoekstra Date: Tue, 1 Nov 2016 01:41:28 +0100 Subject: [PATCH 087/175] added various changes to commit title area --- app/assets/stylesheets/pages/commit.scss | 36 +++++++ .../projects/commit/_commit_box.html.haml | 93 ++++++++++--------- 2 files changed, 83 insertions(+), 46 deletions(-) diff --git a/app/assets/stylesheets/pages/commit.scss b/app/assets/stylesheets/pages/commit.scss index 8ecf7fcb96d..d4890f03a71 100644 --- a/app/assets/stylesheets/pages/commit.scss +++ b/app/assets/stylesheets/pages/commit.scss @@ -36,6 +36,42 @@ padding: 10px 0; margin-bottom: 0; + .commitable-meta { + display: inline-block; + line-height: 18px; + } + + .commit-hash-full { + @media (max-width: $screen-md-min) { + width: 80px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + display: inline-block; + vertical-align: bottom; + } + } + + .commitable-actions { + @media (min-width: $screen-sm) { + float: right; + padding-top: 0; + } + + .dropdown{ + @media (max-width: $screen-sm) { + width: 100%; + margin-top: 10px; + } + } + + .dropdown-toggle { + @media (max-width: $screen-sm) { + width: 100%; + } + } + } + .commit-options-dropdown-caret { @media (max-width: $screen-sm) { margin-left: 0; diff --git a/app/views/projects/commit/_commit_box.html.haml b/app/views/projects/commit/_commit_box.html.haml index d8c95376b94..cca3a962816 100644 --- a/app/views/projects/commit/_commit_box.html.haml +++ b/app/views/projects/commit/_commit_box.html.haml @@ -1,52 +1,53 @@ .commit-info-row.commit-info-row-header - %span.hidden-xs.hidden-sm Commit - = link_to @commit.short_id, namespace_project_commit_path(@project.namespace, @project, @commit), class: "monospace js-details-short" - = link_to("#", class: "js-details-expand hidden-xs hidden-sm") do - %span.text-expander - \... - %span.js-details-content.hide - = link_to @commit.id, namespace_project_commit_path(@project.namespace, @project, @commit), class: "monospace hidden-xs hidden-sm" - = clipboard_button(clipboard_text: @commit.id) - %span.hidden-xs authored - #{time_ago_with_tooltip(@commit.authored_date)} - %span by - = author_avatar(@commit, size: 24) - %strong - = commit_author_link(@commit, avatar: true, size: 24) - - if @commit.different_committer? - %span.light Committed by + .commitable-meta + %strong Commit + %strong.monospace.js-details-short= @commit.short_id + = link_to("#", class: "js-details-expand hidden-xs hidden-sm") do + %span.text-expander + \... + %span.js-details-content.hide + %strong.monospace.commit-hash-full= @commit.id + = clipboard_button(clipboard_text: @commit.id) + %span.hidden-xs authored + #{time_ago_with_tooltip(@commit.authored_date)} + %span by + = author_avatar(@commit, size: 24) %strong - = commit_committer_link(@commit, avatar: true, size: 24) - #{time_ago_with_tooltip(@commit.committed_date)} - - .pull-right.commit-action-buttons - - if defined?(@notes_count) && @notes_count > 0 - %span.btn.disabled.btn-grouped.hidden-xs.append-right-10 - = icon('comment') - = @notes_count - = link_to namespace_project_tree_path(@project.namespace, @project, @commit), class: "btn btn-default append-right-10 hidden-xs hidden-sm" do - Browse Files - .dropdown.inline - %a.btn.btn-default.dropdown-toggle{ data: { toggle: "dropdown" } } - %span.hidden-xs Options - = icon('caret-down', class: ".commit-options-dropdown-caret") - %ul.dropdown-menu.dropdown-menu-align-right - %li.visible-xs-block.visible-sm-block - = link_to namespace_project_tree_path(@project.namespace, @project, @commit) do - Browse Files - - unless @commit.has_been_reverted?(current_user) + = commit_author_link(@commit, avatar: true, size: 24) + - if @commit.different_committer? + %span.light Committed by + %strong + = commit_committer_link(@commit, avatar: true, size: 24) + #{time_ago_with_tooltip(@commit.committed_date)} + .commitable-actions + .commit-action-buttons + - if defined?(@notes_count) && @notes_count > 0 + %span.btn.disabled.btn-grouped.hidden-xs.append-right-10 + = icon('comment') + = @notes_count + = link_to namespace_project_tree_path(@project.namespace, @project, @commit), class: "btn btn-default append-right-10 hidden-xs hidden-sm" do + Browse Files + .dropdown.inline + %a.btn.btn-default.dropdown-toggle{ data: { toggle: "dropdown" } } + %span Options + = icon('caret-down', class: ".commit-options-dropdown-caret") + %ul.dropdown-menu.dropdown-menu-align-right + %li.visible-xs-block.visible-sm-block + = link_to namespace_project_tree_path(@project.namespace, @project, @commit) do + Browse Files + - unless @commit.has_been_reverted?(current_user) + %li.clearfix + = revert_commit_link(@commit, namespace_project_commit_path(@project.namespace, @project, @commit.id), has_tooltip: false) %li.clearfix - = revert_commit_link(@commit, namespace_project_commit_path(@project.namespace, @project, @commit.id), has_tooltip: false) - %li.clearfix - = cherry_pick_commit_link(@commit, namespace_project_commit_path(@project.namespace, @project, @commit.id), has_tooltip: false) - %li.clearfix - = link_to "Tag", new_namespace_project_tag_path(@project.namespace, @project, ref: @commit) - %li.divider - %li.dropdown-header - Download - - unless @commit.parents.length > 1 - %li= link_to "Email Patches", namespace_project_commit_path(@project.namespace, @project, @commit, format: :patch) - %li= link_to "Plain Diff", namespace_project_commit_path(@project.namespace, @project, @commit, format: :diff) + = cherry_pick_commit_link(@commit, namespace_project_commit_path(@project.namespace, @project, @commit.id), has_tooltip: false) + %li.clearfix + = link_to "Tag", new_namespace_project_tag_path(@project.namespace, @project, ref: @commit) + %li.divider + %li.dropdown-header + Download + - unless @commit.parents.length > 1 + %li= link_to "Email Patches", namespace_project_commit_path(@project.namespace, @project, @commit, format: :patch) + %li= link_to "Plain Diff", namespace_project_commit_path(@project.namespace, @project, @commit, format: :diff) .commit-box %h3.commit-title From 30d4cce00c8e98395f177df590b4e2cdc15e0572 Mon Sep 17 00:00:00 2001 From: Dimitrie Hoekstra Date: Tue, 1 Nov 2016 10:35:34 +0000 Subject: [PATCH 088/175] Update commit.scss to have correct linting --- app/assets/stylesheets/pages/commit.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/stylesheets/pages/commit.scss b/app/assets/stylesheets/pages/commit.scss index d4890f03a71..04d2d2ba622 100644 --- a/app/assets/stylesheets/pages/commit.scss +++ b/app/assets/stylesheets/pages/commit.scss @@ -58,7 +58,7 @@ padding-top: 0; } - .dropdown{ + .dropdown { @media (max-width: $screen-sm) { width: 100%; margin-top: 10px; From ff3379641a075748fc6b79e0701e533a763caa85 Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Gray Date: Tue, 1 Nov 2016 16:47:15 -0500 Subject: [PATCH 089/175] Update commit page styles --- app/assets/stylesheets/pages/commit.scss | 46 ++++++--------- .../projects/commit/_commit_box.html.haml | 57 +++++++++---------- 2 files changed, 44 insertions(+), 59 deletions(-) diff --git a/app/assets/stylesheets/pages/commit.scss b/app/assets/stylesheets/pages/commit.scss index 04d2d2ba622..47d3e72679b 100644 --- a/app/assets/stylesheets/pages/commit.scss +++ b/app/assets/stylesheets/pages/commit.scss @@ -36,13 +36,17 @@ padding: 10px 0; margin-bottom: 0; - .commitable-meta { - display: inline-block; - line-height: 18px; + @media (min-width: $screen-sm-min) { + display: flex; + align-items: center; + + .commit-meta { + flex: 1; + } } .commit-hash-full { - @media (max-width: $screen-md-min) { + @media (max-width: $screen-sm-max) { width: 80px; white-space: nowrap; overflow: hidden; @@ -52,31 +56,24 @@ } } - .commitable-actions { - @media (min-width: $screen-sm) { - float: right; - padding-top: 0; + .commit-action-buttons { + i { + color: $gl-icon-color; + font-size: 13px; + margin-right: 3px; } - .dropdown { - @media (max-width: $screen-sm) { + @media (max-width: $screen-xs-max) { + .dropdown { width: 100%; margin-top: 10px; } - } - .dropdown-toggle { - @media (max-width: $screen-sm) { + .dropdown-toggle { width: 100%; } } } - - .commit-options-dropdown-caret { - @media (max-width: $screen-sm) { - margin-left: 0; - } - } } .avatar { @@ -224,17 +221,6 @@ } } -.commit-action-buttons { - position: relative; - top: -1px; - - i { - color: $gl-icon-color; - font-size: 13px; - margin-right: 3px; - } -} - /* * Commit message textarea for web editor and * custom merge request message diff --git a/app/views/projects/commit/_commit_box.html.haml b/app/views/projects/commit/_commit_box.html.haml index cca3a962816..0ebc38d16cf 100644 --- a/app/views/projects/commit/_commit_box.html.haml +++ b/app/views/projects/commit/_commit_box.html.haml @@ -1,5 +1,5 @@ .commit-info-row.commit-info-row-header - .commitable-meta + .commit-meta %strong Commit %strong.monospace.js-details-short= @commit.short_id = link_to("#", class: "js-details-expand hidden-xs hidden-sm") do @@ -19,35 +19,34 @@ %strong = commit_committer_link(@commit, avatar: true, size: 24) #{time_ago_with_tooltip(@commit.committed_date)} - .commitable-actions - .commit-action-buttons - - if defined?(@notes_count) && @notes_count > 0 - %span.btn.disabled.btn-grouped.hidden-xs.append-right-10 - = icon('comment') - = @notes_count - = link_to namespace_project_tree_path(@project.namespace, @project, @commit), class: "btn btn-default append-right-10 hidden-xs hidden-sm" do - Browse Files - .dropdown.inline - %a.btn.btn-default.dropdown-toggle{ data: { toggle: "dropdown" } } - %span Options - = icon('caret-down', class: ".commit-options-dropdown-caret") - %ul.dropdown-menu.dropdown-menu-align-right - %li.visible-xs-block.visible-sm-block - = link_to namespace_project_tree_path(@project.namespace, @project, @commit) do - Browse Files - - unless @commit.has_been_reverted?(current_user) - %li.clearfix - = revert_commit_link(@commit, namespace_project_commit_path(@project.namespace, @project, @commit.id), has_tooltip: false) + .commit-action-buttons + - if defined?(@notes_count) && @notes_count > 0 + %span.btn.disabled.btn-grouped.hidden-xs.append-right-10 + = icon('comment') + = @notes_count + = link_to namespace_project_tree_path(@project.namespace, @project, @commit), class: "btn btn-default append-right-10 hidden-xs hidden-sm" do + Browse Files + .dropdown.inline + %a.btn.btn-default.dropdown-toggle{ data: { toggle: "dropdown" } } + %span Options + = icon('caret-down') + %ul.dropdown-menu.dropdown-menu-align-right + %li.visible-xs-block.visible-sm-block + = link_to namespace_project_tree_path(@project.namespace, @project, @commit) do + Browse Files + - unless @commit.has_been_reverted?(current_user) %li.clearfix - = cherry_pick_commit_link(@commit, namespace_project_commit_path(@project.namespace, @project, @commit.id), has_tooltip: false) - %li.clearfix - = link_to "Tag", new_namespace_project_tag_path(@project.namespace, @project, ref: @commit) - %li.divider - %li.dropdown-header - Download - - unless @commit.parents.length > 1 - %li= link_to "Email Patches", namespace_project_commit_path(@project.namespace, @project, @commit, format: :patch) - %li= link_to "Plain Diff", namespace_project_commit_path(@project.namespace, @project, @commit, format: :diff) + = revert_commit_link(@commit, namespace_project_commit_path(@project.namespace, @project, @commit.id), has_tooltip: false) + %li.clearfix + = cherry_pick_commit_link(@commit, namespace_project_commit_path(@project.namespace, @project, @commit.id), has_tooltip: false) + %li.clearfix + = link_to "Tag", new_namespace_project_tag_path(@project.namespace, @project, ref: @commit) + %li.divider + %li.dropdown-header + Download + - unless @commit.parents.length > 1 + %li= link_to "Email Patches", namespace_project_commit_path(@project.namespace, @project, @commit, format: :patch) + %li= link_to "Plain Diff", namespace_project_commit_path(@project.namespace, @project, @commit, format: :diff) .commit-box %h3.commit-title From 050c8dc7fc03ac356fc1f68d1d4b7396414cb7b9 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Thu, 3 Nov 2016 13:43:16 +0000 Subject: [PATCH 090/175] Apply `*_params_ce + *_params_ee` pattern to MergeRequestsController --- .../projects/merge_requests_controller.rb | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index 30f1cf4e5be..19afe9a3deb 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -589,12 +589,27 @@ class Projects::MergeRequestsController < Projects::ApplicationController end def merge_request_params - params.require(:merge_request).permit( - :title, :assignee_id, :source_project_id, :source_branch, - :target_project_id, :target_branch, :milestone_id, - :state_event, :description, :task_num, :force_remove_source_branch, - :lock_version, label_ids: [] - ) + params.require(:merge_request) + .permit(merge_request_params_ce) + end + + def merge_request_params_ce + [ + :assignee_id, + :description, + :force_remove_source_branch, + :lock_version, + :milestone_id, + :source_branch, + :source_project_id, + :state_event, + :target_branch, + :target_project_id, + :task_num, + :title, + + label_ids: [] + ] end def merge_params From 1db9f826c16053e32a1d234bf40b2ca399779cdf Mon Sep 17 00:00:00 2001 From: Rodolfo Santos Date: Fri, 16 Sep 2016 08:02:42 -0300 Subject: [PATCH 091/175] Add setting to only allow merge requests to be merged when all discussions are resolved MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- app/controllers/projects_controller.rb | 5 +- app/models/merge_request.rb | 7 +++ .../_merge_request_settings.html.haml | 4 ++ .../merge_requests/widget/_open.html.haml | 4 +- .../open/_unresolved_discussions.html.haml | 6 ++ ...setting-to-check-unresolved-discussion.yml | 4 ++ ...w_merge_if_all_discussions_are_resolved.rb | 17 ++++++ db/schema.rb | 1 + doc/api/projects.md | 10 ++++ lib/api/entities.rb | 1 + lib/api/projects.rb | 9 ++- .../merge_requests_controller_spec.rb | 26 +++++++++ spec/factories/merge_requests.rb | 5 ++ ...f_mergeable_with_unresolved_discussions.rb | 53 +++++++++++++++++ spec/models/merge_request_spec.rb | 58 ++++++++++++++++++- spec/requests/api/projects_spec.rb | 36 +++++++++++- 16 files changed, 238 insertions(+), 8 deletions(-) create mode 100644 app/views/projects/merge_requests/widget/open/_unresolved_discussions.html.haml create mode 100644 changelogs/unreleased/20968-add-setting-to-check-unresolved-discussion.yml create mode 100644 db/migrate/20160914131004_only_allow_merge_if_all_discussions_are_resolved.rb create mode 100644 spec/features/merge_requests/check_if_mergeable_with_unresolved_discussions.rb diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index bce5e29d8d8..ee72c8ba72f 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -334,8 +334,9 @@ class ProjectsController < Projects::ApplicationController :issues_tracker_id, :default_branch, :visibility_level, :import_url, :last_activity_at, :namespace_id, :avatar, :build_allow_git_fetch, :build_timeout_in_minutes, :build_coverage_regex, - :public_builds, :only_allow_merge_if_build_succeeds, :request_access_enabled, - :lfs_enabled, project_feature_attributes + :public_builds, :only_allow_merge_if_build_succeeds, + :only_allow_merge_if_all_discussions_are_resolved, + :request_access_enabled, :lfs_enabled, project_feature_attributes ) end diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 6b8ac3fb48b..d76feb9680e 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -425,6 +425,7 @@ class MergeRequest < ActiveRecord::Base return false if work_in_progress? return false if broken? return false unless skip_ci_check || mergeable_ci_state? + return false unless mergeable_discussions_state? true end @@ -493,6 +494,12 @@ class MergeRequest < ActiveRecord::Base discussions_resolvable? && diff_discussions.none?(&:to_be_resolved?) end + def mergeable_discussions_state? + return true unless project.only_allow_merge_if_all_discussions_are_resolved? + + discussions_resolved? + end + def hook_attrs attrs = { source: source_project.try(:hook_attrs), diff --git a/app/views/projects/_merge_request_settings.html.haml b/app/views/projects/_merge_request_settings.html.haml index 80053dd501b..6e143c4b570 100644 --- a/app/views/projects/_merge_request_settings.html.haml +++ b/app/views/projects/_merge_request_settings.html.haml @@ -12,3 +12,7 @@ %span.descr Builds need to be configured to enable this feature. = link_to icon('question-circle'), help_page_path('user/project/merge_requests/merge_when_build_succeeds', anchor: 'only-allow-merge-requests-to-be-merged-if-the-build-succeeds') + .checkbox + = f.label :only_allow_merge_if_all_discussions_are_resolved do + = f.check_box :only_allow_merge_if_all_discussions_are_resolved + %strong Only allow merge requests to be merged if all discussions are resolved diff --git a/app/views/projects/merge_requests/widget/_open.html.haml b/app/views/projects/merge_requests/widget/_open.html.haml index 842b6df310d..01314eb37d0 100644 --- a/app/views/projects/merge_requests/widget/_open.html.haml +++ b/app/views/projects/merge_requests/widget/_open.html.haml @@ -23,8 +23,10 @@ = render 'projects/merge_requests/widget/open/merge_when_build_succeeds' - elsif !@merge_request.can_be_merged_by?(current_user) = render 'projects/merge_requests/widget/open/not_allowed' - - elsif !@merge_request.mergeable_ci_state? && @pipeline && @pipeline.failed? + - elsif !@merge_request.mergeable_ci_state? = render 'projects/merge_requests/widget/open/build_failed' + - elsif !@merge_request.mergeable_discussions_state? + = render 'projects/merge_requests/widget/open/unresolved_discussions' - elsif @merge_request.can_be_merged? || resolved_conflicts = render 'projects/merge_requests/widget/open/accept' diff --git a/app/views/projects/merge_requests/widget/open/_unresolved_discussions.html.haml b/app/views/projects/merge_requests/widget/open/_unresolved_discussions.html.haml new file mode 100644 index 00000000000..35d5677ee37 --- /dev/null +++ b/app/views/projects/merge_requests/widget/open/_unresolved_discussions.html.haml @@ -0,0 +1,6 @@ +%h4 + = icon('exclamation-triangle') + This merge request has unresolved discussions + +%p + Please resolve these discussions to allow this merge request to be merged. \ No newline at end of file diff --git a/changelogs/unreleased/20968-add-setting-to-check-unresolved-discussion.yml b/changelogs/unreleased/20968-add-setting-to-check-unresolved-discussion.yml new file mode 100644 index 00000000000..8f03746ff80 --- /dev/null +++ b/changelogs/unreleased/20968-add-setting-to-check-unresolved-discussion.yml @@ -0,0 +1,4 @@ +--- +title: Add setting to only allow merge requests to be merged when all discussions are resolved +merge_request: 7125 +author: Rodolfo Arruda diff --git a/db/migrate/20160914131004_only_allow_merge_if_all_discussions_are_resolved.rb b/db/migrate/20160914131004_only_allow_merge_if_all_discussions_are_resolved.rb new file mode 100644 index 00000000000..fad62d716b3 --- /dev/null +++ b/db/migrate/20160914131004_only_allow_merge_if_all_discussions_are_resolved.rb @@ -0,0 +1,17 @@ +class OnlyAllowMergeIfAllDiscussionsAreResolved < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + disable_ddl_transaction! + + def up + add_column_with_default(:projects, + :only_allow_merge_if_all_discussions_are_resolved, + :boolean, + default: false) + end + + def down + remove_column(:projects, :only_allow_merge_if_all_discussions_are_resolved) + end +end diff --git a/db/schema.rb b/db/schema.rb index dc088925d97..5476b0c93e5 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -905,6 +905,7 @@ ActiveRecord::Schema.define(version: 20161103171205) do t.boolean "has_external_wiki" t.boolean "lfs_enabled" t.text "description_html" + t.boolean "only_allow_merge_if_all_discussions_are_resolved", default: false, null: false end add_index "projects", ["ci_id"], name: "index_projects_on_ci_id", using: :btree diff --git a/doc/api/projects.md b/doc/api/projects.md index 4f4b20a1874..bbb3bfb4995 100644 --- a/doc/api/projects.md +++ b/doc/api/projects.md @@ -89,6 +89,7 @@ Parameters: "public_builds": true, "shared_with_groups": [], "only_allow_merge_if_build_succeeds": false, + "only_allow_merge_if_all_discussions_are_resolved": false, "request_access_enabled": false }, { @@ -151,6 +152,7 @@ Parameters: "public_builds": true, "shared_with_groups": [], "only_allow_merge_if_build_succeeds": false, + "only_allow_merge_if_all_discussions_are_resolved": false, "request_access_enabled": false } ] @@ -429,6 +431,7 @@ Parameters: } ], "only_allow_merge_if_build_succeeds": false, + "only_allow_merge_if_all_discussions_are_resolved": false, "request_access_enabled": false } ``` @@ -602,6 +605,7 @@ Parameters: | `import_url` | string | no | URL to import repository from | | `public_builds` | boolean | no | If `true`, builds can be viewed by non-project-members | | `only_allow_merge_if_build_succeeds` | boolean | no | Set whether merge requests can only be merged with successful builds | +| `only_allow_merge_if_all_discussions_are_resolved` | boolean | no | Set whether merge requests can only be merged when all the discussions are resolved | | `lfs_enabled` | boolean | no | Enable LFS | | `request_access_enabled` | boolean | no | Allow users to request member access | @@ -634,6 +638,7 @@ Parameters: | `import_url` | string | no | URL to import repository from | | `public_builds` | boolean | no | If `true`, builds can be viewed by non-project-members | | `only_allow_merge_if_build_succeeds` | boolean | no | Set whether merge requests can only be merged with successful builds | +| `only_allow_merge_if_all_discussions_are_resolved` | boolean | no | Set whether merge requests can only be merged when all the discussions are resolved | | `lfs_enabled` | boolean | no | Enable LFS | | `request_access_enabled` | boolean | no | Allow users to request member access | @@ -665,6 +670,7 @@ Parameters: | `import_url` | string | no | URL to import repository from | | `public_builds` | boolean | no | If `true`, builds can be viewed by non-project-members | | `only_allow_merge_if_build_succeeds` | boolean | no | Set whether merge requests can only be merged with successful builds | +| `only_allow_merge_if_all_discussions_are_resolved` | boolean | no | Set whether merge requests can only be merged when all the discussions are resolved | | `lfs_enabled` | boolean | no | Enable LFS | | `request_access_enabled` | boolean | no | Allow users to request member access | @@ -752,6 +758,7 @@ Example response: "public_builds": true, "shared_with_groups": [], "only_allow_merge_if_build_succeeds": false, + "only_allow_merge_if_all_discussions_are_resolved": false, "request_access_enabled": false } ``` @@ -820,6 +827,7 @@ Example response: "public_builds": true, "shared_with_groups": [], "only_allow_merge_if_build_succeeds": false, + "only_allow_merge_if_all_discussions_are_resolved": false, "request_access_enabled": false } ``` @@ -908,6 +916,7 @@ Example response: "public_builds": true, "shared_with_groups": [], "only_allow_merge_if_build_succeeds": false, + "only_allow_merge_if_all_discussions_are_resolved": false, "request_access_enabled": false } ``` @@ -996,6 +1005,7 @@ Example response: "public_builds": true, "shared_with_groups": [], "only_allow_merge_if_build_succeeds": false, + "only_allow_merge_if_all_discussions_are_resolved": false, "request_access_enabled": false } ``` diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 1f378ba1635..01e31f6f7d1 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -100,6 +100,7 @@ module API end expose :only_allow_merge_if_build_succeeds expose :request_access_enabled + expose :only_allow_merge_if_all_discussions_are_resolved end class Member < UserBasic diff --git a/lib/api/projects.rb b/lib/api/projects.rb index da16e24d7ea..6b856128c2e 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -139,7 +139,8 @@ module API :shared_runners_enabled, :snippets_enabled, :visibility_level, - :wiki_enabled] + :wiki_enabled, + :only_allow_merge_if_all_discussions_are_resolved] attrs = map_public_to_visibility_level(attrs) @project = ::Projects::CreateService.new(current_user, attrs).execute if @project.saved? @@ -193,7 +194,8 @@ module API :shared_runners_enabled, :snippets_enabled, :visibility_level, - :wiki_enabled] + :wiki_enabled, + :only_allow_merge_if_all_discussions_are_resolved] attrs = map_public_to_visibility_level(attrs) @project = ::Projects::CreateService.new(user, attrs).execute if @project.saved? @@ -275,7 +277,8 @@ module API :shared_runners_enabled, :snippets_enabled, :visibility_level, - :wiki_enabled] + :wiki_enabled, + :only_allow_merge_if_all_discussions_are_resolved] attrs = map_public_to_visibility_level(attrs) authorize_admin_project authorize! :rename_project, user_project if attrs[:name].present? diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb index 940d54f8686..79820e9a435 100644 --- a/spec/controllers/projects/merge_requests_controller_spec.rb +++ b/spec/controllers/projects/merge_requests_controller_spec.rb @@ -297,6 +297,32 @@ describe Projects::MergeRequestsController do end end end + + context 'when project project has unresolved discussion' do + before do + project.update_column(:only_allow_merge_if_all_discussions_are_resolved, allowed) + end + + context "when the only_allow_merge_if_all_discussions_are_resolved? is true" do + let(:allowed) { true } + + it 'returns :failed' do + merge_with_sha + + expect(assigns(:status)).to eq(:failed) + end + end + + context "when the only_allow_merge_if_all_discussions_are_resolved? is false" do + let(:allowed) { false } + + it 'returns :failed' do + merge_with_sha + + expect(assigns(:status)).to eq(:success) + end + end + end end end diff --git a/spec/factories/merge_requests.rb b/spec/factories/merge_requests.rb index f780e01253c..37eb49c94df 100644 --- a/spec/factories/merge_requests.rb +++ b/spec/factories/merge_requests.rb @@ -68,6 +68,11 @@ FactoryGirl.define do factory :closed_merge_request, traits: [:closed] factory :reopened_merge_request, traits: [:reopened] factory :merge_request_with_diffs, traits: [:with_diffs] + factory :merge_request_with_diff_notes do + after(:create) do |mr| + create(:diff_note_on_merge_request, noteable: mr, project: mr.source_project) + end + end factory :labeled_merge_request do transient do diff --git a/spec/features/merge_requests/check_if_mergeable_with_unresolved_discussions.rb b/spec/features/merge_requests/check_if_mergeable_with_unresolved_discussions.rb new file mode 100644 index 00000000000..100ddda0167 --- /dev/null +++ b/spec/features/merge_requests/check_if_mergeable_with_unresolved_discussions.rb @@ -0,0 +1,53 @@ +require 'spec_helper' + +feature 'Check if mergeable with unresolved discussions', js: true, feature: true do + let!(:user) { create(:user) } + let!(:project) { create(:project, :public, only_allow_merge_if_all_discussions_are_resolved: allowed) } + let!(:merge_request) { create(:merge_request_with_diff_notes, source_project: project, author: user, title: "Bug NS-04" ) } + + before do + login_as user + project.team << [user, :master] + end + + context 'when only_allow_merge_if_all_discussions_are_resolved is false' do + let(:allowed) { false } + + it 'allows MR to be merged' do + visit_merge_request(merge_request) + + expect(page).to have_button 'Accept Merge Request' + end + end + + context 'when only_allow_merge_if_all_discussions_are_resolved is true' do + let(:allowed) { true } + + context "when discussions are resolved" do + + before do + merge_request.discussions.each { |d| d.resolve!(user) } + end + + it 'allows MR to be merged' do + visit_merge_request(merge_request) + + expect(page).to have_button 'Accept Merge Request' + end + end + + context "when discussions are unresolved" do + + it 'does not allow to merge' do + visit_merge_request(merge_request) + + expect(page).not_to have_button 'Accept Merge Request' + expect(page).to have_content('This merge request has unresolved discussions') + end + end + end + + def visit_merge_request(merge_request) + visit namespace_project_merge_request_path(merge_request.project.namespace, merge_request.project, merge_request) + end +end diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 1067ff7bb4d..f3d0373e6d7 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -837,6 +837,17 @@ describe MergeRequest, models: true do expect(subject.mergeable_state?).to be_falsey end end + + context "when project settings restrict to merge only when all the discussions are resolved" do + before do + project.only_allow_merge_if_all_discussions_are_resolved = true + allow(subject).to receive(:mergeable_discussions_state?) { false } + end + + it 'returns false' do + expect(subject.mergeable_state?).to be_falsey + end + end end end @@ -887,7 +898,52 @@ describe MergeRequest, models: true do end end - describe '#environments' do + describe '#mergeable_discussions_state?' do + let!(:user) { create(:user) } + let!(:project) { create(:project, only_allow_merge_if_all_discussions_are_resolved: allowed) } + + subject { create(:merge_request_with_diff_notes, source_project: project) } + + context 'when is true' do + let(:allowed) { true } + + context 'when discussions are resolved' do + before do + subject.discussions.each { |d| d.resolve!(user) } + end + + it 'returns true' do + expect(subject.mergeable_discussions_state?).to be_truthy + end + end + + context 'when discussions are unresolved' do + before do + subject.discussions.map(&:unresolve!) + end + + it 'returns false' do + expect(subject.mergeable_discussions_state?).to be_falsey + end + end + end + + context 'when is false' do + let(:allowed) { false } + + context 'when discussions are unresolved' do + before do + subject.discussions.map(&:unresolve!) + end + + it 'returns true' do + expect(subject.mergeable_discussions_state?).to be_truthy + end + end + end + end + + describe "#environments" do let(:project) { create(:project) } let(:merge_request) { create(:merge_request, source_project: project) } diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index 973928d007a..3c8f0ac531a 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -256,7 +256,8 @@ describe API::API, api: true do merge_requests_enabled: false, wiki_enabled: false, only_allow_merge_if_build_succeeds: false, - request_access_enabled: true + request_access_enabled: true, + only_allow_merge_if_all_discussions_are_resolved: false }) post api('/projects', user), project @@ -327,6 +328,22 @@ describe API::API, api: true do expect(json_response['only_allow_merge_if_build_succeeds']).to be_truthy end + it 'sets a project as allowing merge even if discussions are unresolved' do + project = attributes_for(:project, { only_allow_merge_if_all_discussions_are_resolved: false }) + + post api('/projects', user), project + + expect(json_response['only_allow_merge_if_all_discussions_are_resolved']).to be_falsey + end + + it 'sets a project as allowing merge only if all discussions are resolved' do + project = attributes_for(:project, { only_allow_merge_if_all_discussions_are_resolved: true }) + + post api('/projects', user), project + + expect(json_response['only_allow_merge_if_all_discussions_are_resolved']).to be_truthy + end + context 'when a visibility level is restricted' do before do @project = attributes_for(:project, { public: true }) @@ -448,6 +465,22 @@ describe API::API, api: true do post api("/projects/user/#{user.id}", admin), project expect(json_response['only_allow_merge_if_build_succeeds']).to be_truthy end + + it 'sets a project as allowing merge even if discussions are unresolved' do + project = attributes_for(:project, { only_allow_merge_if_all_discussions_are_resolved: false }) + + post api("/projects/user/#{user.id}", admin), project + + expect(json_response['only_allow_merge_if_all_discussions_are_resolved']).to be_falsey + end + + it 'sets a project as allowing merge only if all discussions are resolved' do + project = attributes_for(:project, { only_allow_merge_if_all_discussions_are_resolved: true }) + + post api("/projects/user/#{user.id}", admin), project + + expect(json_response['only_allow_merge_if_all_discussions_are_resolved']).to be_truthy + end end describe "POST /projects/:id/uploads" do @@ -509,6 +542,7 @@ describe API::API, api: true do expect(json_response['shared_with_groups'][0]['group_name']).to eq(group.name) expect(json_response['shared_with_groups'][0]['group_access_level']).to eq(link.group_access) expect(json_response['only_allow_merge_if_build_succeeds']).to eq(project.only_allow_merge_if_build_succeeds) + expect(json_response['only_allow_merge_if_all_discussions_are_resolved']).to eq(project.only_allow_merge_if_all_discussions_are_resolved) end it 'returns a project by path name' do From 3f029144607428aa21e81d1d4b40544b835f3d80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Wed, 26 Oct 2016 19:19:17 +0200 Subject: [PATCH 092/175] Complete and improve specs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- app/controllers/projects_controller.rb | 4 +- .../merge_requests_controller_spec.rb | 68 +++++++++++++++---- ...f_mergeable_with_unresolved_discussions.rb | 50 +++++++++----- spec/models/merge_request_spec.rb | 39 +++++------ 4 files changed, 105 insertions(+), 56 deletions(-) diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index ee72c8ba72f..6988527a3be 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -334,9 +334,9 @@ class ProjectsController < Projects::ApplicationController :issues_tracker_id, :default_branch, :visibility_level, :import_url, :last_activity_at, :namespace_id, :avatar, :build_allow_git_fetch, :build_timeout_in_minutes, :build_coverage_regex, - :public_builds, :only_allow_merge_if_build_succeeds, + :public_builds, :only_allow_merge_if_build_succeeds, :request_access_enabled, :only_allow_merge_if_all_discussions_are_resolved, - :request_access_enabled, :lfs_enabled, project_feature_attributes + :lfs_enabled, project_feature_attributes ) end diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb index 79820e9a435..49127aecc63 100644 --- a/spec/controllers/projects/merge_requests_controller_spec.rb +++ b/spec/controllers/projects/merge_requests_controller_spec.rb @@ -298,28 +298,68 @@ describe Projects::MergeRequestsController do end end - context 'when project project has unresolved discussion' do - before do - project.update_column(:only_allow_merge_if_all_discussions_are_resolved, allowed) - end + describe 'only_allow_merge_if_all_discussions_are_resolved? setting' do + let(:merge_request) { create(:merge_request_with_diff_notes, source_project: project, author: user) } - context "when the only_allow_merge_if_all_discussions_are_resolved? is true" do - let(:allowed) { true } + context 'when enabled' do + before do + project.update_column(:only_allow_merge_if_all_discussions_are_resolved, true) + end - it 'returns :failed' do - merge_with_sha + context 'with unresolved discussion' do + before do + expect(merge_request).not_to be_discussions_resolved + end - expect(assigns(:status)).to eq(:failed) + it 'returns :failed' do + merge_with_sha + + expect(assigns(:status)).to eq(:failed) + end + end + + context 'with all discussions resolved' do + before do + merge_request.discussions.each { |d| d.resolve!(user) } + expect(merge_request).to be_discussions_resolved + end + + it 'returns :success' do + merge_with_sha + + expect(assigns(:status)).to eq(:success) + end end end - context "when the only_allow_merge_if_all_discussions_are_resolved? is false" do - let(:allowed) { false } + context 'when disabled' do + before do + project.update_column(:only_allow_merge_if_all_discussions_are_resolved, false) + end - it 'returns :failed' do - merge_with_sha + context 'with unresolved discussion' do + before do + expect(merge_request).not_to be_discussions_resolved + end - expect(assigns(:status)).to eq(:success) + it 'returns :success' do + merge_with_sha + + expect(assigns(:status)).to eq(:success) + end + end + + context 'with all discussions resolved' do + before do + merge_request.discussions.each { |d| d.resolve!(user) } + expect(merge_request).to be_discussions_resolved + end + + it 'returns :success' do + merge_with_sha + + expect(assigns(:status)).to eq(:success) + end end end end diff --git a/spec/features/merge_requests/check_if_mergeable_with_unresolved_discussions.rb b/spec/features/merge_requests/check_if_mergeable_with_unresolved_discussions.rb index 100ddda0167..7f11db3c417 100644 --- a/spec/features/merge_requests/check_if_mergeable_with_unresolved_discussions.rb +++ b/spec/features/merge_requests/check_if_mergeable_with_unresolved_discussions.rb @@ -1,30 +1,30 @@ require 'spec_helper' feature 'Check if mergeable with unresolved discussions', js: true, feature: true do - let!(:user) { create(:user) } - let!(:project) { create(:project, :public, only_allow_merge_if_all_discussions_are_resolved: allowed) } - let!(:merge_request) { create(:merge_request_with_diff_notes, source_project: project, author: user, title: "Bug NS-04" ) } + let(:user) { create(:user) } + let(:project) { create(:project) } + let!(:merge_request) { create(:merge_request_with_diff_notes, source_project: project, author: user) } before do login_as user project.team << [user, :master] end - context 'when only_allow_merge_if_all_discussions_are_resolved is false' do - let(:allowed) { false } - - it 'allows MR to be merged' do - visit_merge_request(merge_request) - - expect(page).to have_button 'Accept Merge Request' + context 'when project.only_allow_merge_if_all_discussions_are_resolved == true' do + before do + project.update_column(:only_allow_merge_if_all_discussions_are_resolved, true) end - end - context 'when only_allow_merge_if_all_discussions_are_resolved is true' do - let(:allowed) { true } + context 'with unresolved discussions' do + it 'does not allow to merge' do + visit_merge_request(merge_request) - context "when discussions are resolved" do + expect(page).not_to have_button 'Accept Merge Request' + expect(page).to have_content('This merge request has unresolved discussions') + end + end + context 'with all discussions resolved' do before do merge_request.discussions.each { |d| d.resolve!(user) } end @@ -35,14 +35,30 @@ feature 'Check if mergeable with unresolved discussions', js: true, feature: tru expect(page).to have_button 'Accept Merge Request' end end + end - context "when discussions are unresolved" do + context 'when project.only_allow_merge_if_all_discussions_are_resolved == false' do + before do + project.update_column(:only_allow_merge_if_all_discussions_are_resolved, false) + end + context 'with unresolved discussions' do it 'does not allow to merge' do visit_merge_request(merge_request) - expect(page).not_to have_button 'Accept Merge Request' - expect(page).to have_content('This merge request has unresolved discussions') + expect(page).to have_button 'Accept Merge Request' + end + end + + context 'with all discussions resolved' do + before do + merge_request.discussions.each { |d| d.resolve!(user) } + end + + it 'allows MR to be merged' do + visit_merge_request(merge_request) + + expect(page).to have_button 'Accept Merge Request' end end end diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index f3d0373e6d7..fb032a89d50 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -825,11 +825,8 @@ describe MergeRequest, models: true do end context 'when failed' do - before { allow(subject).to receive(:broken?) { false } } - - context 'when project settings restrict to merge only if build succeeds and build failed' do + context 'when #mergeable_ci_state? is false' do before do - project.only_allow_merge_if_build_succeeds = true allow(subject).to receive(:mergeable_ci_state?) { false } end @@ -838,9 +835,8 @@ describe MergeRequest, models: true do end end - context "when project settings restrict to merge only when all the discussions are resolved" do + context 'when #mergeable_discussions_state? is false' do before do - project.only_allow_merge_if_all_discussions_are_resolved = true allow(subject).to receive(:mergeable_discussions_state?) { false } end @@ -899,45 +895,42 @@ describe MergeRequest, models: true do end describe '#mergeable_discussions_state?' do - let!(:user) { create(:user) } - let!(:project) { create(:project, only_allow_merge_if_all_discussions_are_resolved: allowed) } + let(:merge_request) { create(:merge_request_with_diff_notes, source_project: project) } - subject { create(:merge_request_with_diff_notes, source_project: project) } + context 'when project.only_allow_merge_if_all_discussions_are_resolved == true' do + let(:project) { create(:project, only_allow_merge_if_all_discussions_are_resolved: true) } - context 'when is true' do - let(:allowed) { true } - - context 'when discussions are resolved' do + context 'with all discussions resolved' do before do - subject.discussions.each { |d| d.resolve!(user) } + merge_request.discussions.each { |d| d.resolve!(merge_request.author) } end it 'returns true' do - expect(subject.mergeable_discussions_state?).to be_truthy + expect(merge_request.mergeable_discussions_state?).to be_truthy end end - context 'when discussions are unresolved' do + context 'with unresolved discussions' do before do - subject.discussions.map(&:unresolve!) + merge_request.discussions.each(&:unresolve!) end it 'returns false' do - expect(subject.mergeable_discussions_state?).to be_falsey + expect(merge_request.mergeable_discussions_state?).to be_falsey end end end - context 'when is false' do - let(:allowed) { false } + context 'when project.only_allow_merge_if_all_discussions_are_resolved == false' do + let(:project) { create(:project, only_allow_merge_if_all_discussions_are_resolved: false) } - context 'when discussions are unresolved' do + context 'with unresolved discussions' do before do - subject.discussions.map(&:unresolve!) + merge_request.discussions.each(&:unresolve!) end it 'returns true' do - expect(subject.mergeable_discussions_state?).to be_truthy + expect(merge_request.mergeable_discussions_state?).to be_truthy end end end From 065ba130585cbce5a2835def94a650d26493abb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Mon, 31 Oct 2016 16:00:42 +0100 Subject: [PATCH 093/175] Add documentation for the "Only allow merge requests to be merged if all discussions are resolved" feature MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- ..._merge_if_all_discussions_are_resolved.png | Bin 0 -> 24693 bytes ...ge_if_all_discussions_are_resolved_msg.png | Bin 0 -> 6940 bytes .../merge_request_discussion_resolution.md | 18 ++++++++++++++++++ .../merge_when_build_succeeds.md | 4 ++-- 4 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 doc/user/project/merge_requests/img/only_allow_merge_if_all_discussions_are_resolved.png create mode 100644 doc/user/project/merge_requests/img/only_allow_merge_if_all_discussions_are_resolved_msg.png diff --git a/doc/user/project/merge_requests/img/only_allow_merge_if_all_discussions_are_resolved.png b/doc/user/project/merge_requests/img/only_allow_merge_if_all_discussions_are_resolved.png new file mode 100644 index 0000000000000000000000000000000000000000..52c8acf15e02e51caf7df99fb5febaeb054162e2 GIT binary patch literal 24693 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�ZcJ8QhH;Wl-ZB7 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 MdsVq|8Pl)-10vh$`v3p{ literal 0 HcmV?d00001 diff --git a/doc/user/project/merge_requests/img/only_allow_merge_if_all_discussions_are_resolved_msg.png b/doc/user/project/merge_requests/img/only_allow_merge_if_all_discussions_are_resolved_msg.png new file mode 100644 index 0000000000000000000000000000000000000000..79ba5c362c7543a0bb83e99e753434333f29bc13 GIT binary patch literal 6940 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 [Introduced][ce-7125] in GitLab 8.14. + +You can prevent merge requests from being merged until all discussions are resolved. + +Navigate to your project's settings page, select the +**Only allow merge requests to be merged if all discussions are resolved** check +box and hit **Save** for the changes to take effect. + +![Only allow merge if all the discussions are resolved settings](img/only_allow_merge_if_all_discussions_are_resolved.png) + +From now on, you will not be able to merge from the UI until all discussions +are resolved. + +![Only allow merge if all the discussions are resolved message](img/only_allow_merge_if_all_discussions_are_resolved_msg.png) + [ce-5022]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5022 +[ce-7125]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7125 [resolve-discussion-button]: img/resolve_discussion_button.png [resolve-comment-button]: img/resolve_comment_button.png [discussion-view]: img/discussion_view.png diff --git a/doc/user/project/merge_requests/merge_when_build_succeeds.md b/doc/user/project/merge_requests/merge_when_build_succeeds.md index c138061fd40..d4e5b5de685 100644 --- a/doc/user/project/merge_requests/merge_when_build_succeeds.md +++ b/doc/user/project/merge_requests/merge_when_build_succeeds.md @@ -40,7 +40,7 @@ hit **Save** for the changes to take effect. ![Only allow merge if build succeeds settings](img/merge_when_build_succeeds_only_if_succeeds_settings.png) -From now on, every time the pipelinefails you will not be able to merge the +From now on, every time the pipeline fails you will not be able to merge the merge request from the UI, until you make all relevant builds pass. -![Only allow merge if build succeeds msg](img/merge_when_build_succeeds_only_if_succeeds_msg.png) +![Only allow merge if build succeeds message](img/merge_when_build_succeeds_only_if_succeeds_msg.png) From 6a9fb20fe157fba158a79d645742239796239124 Mon Sep 17 00:00:00 2001 From: Ahmad Sherif Date: Wed, 2 Nov 2016 16:23:46 +0200 Subject: [PATCH 094/175] Fix applying GitHub-imported labels when importing job is interrupted Closes #24075 --- CHANGELOG.md | 1 + lib/gitlab/github_import/importer.rb | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9411cc62003..c055d1f384e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -66,6 +66,7 @@ entry. - In all filterable drop downs, put input field in focus only after load is complete (Ido @leibo) - Improve search query parameter naming in /admin/users !7115 (YarNayar) - Fix table pagination to be responsive +- Fix applying GitHub-imported labels when importing job is interrupted - Allow to search for user by secondary email address in the admin interface(/admin/users) !7115 (YarNayar) - Updated commit SHA styling on the branches page. diff --git a/lib/gitlab/github_import/importer.rb b/lib/gitlab/github_import/importer.rb index ecc28799737..bdabc71194d 100644 --- a/lib/gitlab/github_import/importer.rb +++ b/lib/gitlab/github_import/importer.rb @@ -59,6 +59,8 @@ module Gitlab end end end + + ensure_labels_are_cached end def import_milestones @@ -234,6 +236,14 @@ module Gitlab end end + def ensure_labels_are_cached + return unless @labels.empty? + + project.labels.select(:id, :title).find_each do |label| + @labels[label.title] = label.id + end + end + def fetch_resources(resource_type, *opts) return if imported?(resource_type) From eaa0303b3d2f1480222c94a85d356b055f7100b3 Mon Sep 17 00:00:00 2001 From: Ahmad Sherif Date: Wed, 2 Nov 2016 22:37:56 +0200 Subject: [PATCH 095/175] Cache imported GH labels no matter what --- lib/gitlab/github_import/importer.rb | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/lib/gitlab/github_import/importer.rb b/lib/gitlab/github_import/importer.rb index bdabc71194d..90cf38a8513 100644 --- a/lib/gitlab/github_import/importer.rb +++ b/lib/gitlab/github_import/importer.rb @@ -52,15 +52,14 @@ module Gitlab fetch_resources(:labels, repo, per_page: 100) do |labels| labels.each do |raw| begin - label = LabelFormatter.new(project, raw).create! - @labels[label.title] = label.id + LabelFormatter.new(project, raw).create! rescue => e errors << { type: :label, url: Gitlab::UrlSanitizer.sanitize(raw.url), errors: e.message } end end end - ensure_labels_are_cached + cache_labels! end def import_milestones @@ -236,9 +235,7 @@ module Gitlab end end - def ensure_labels_are_cached - return unless @labels.empty? - + def cache_labels! project.labels.select(:id, :title).find_each do |label| @labels[label.title] = label.id end From b0a4635be395f0ce14e15e1671d7acfc2360d1ba Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Fri, 4 Nov 2016 15:00:39 +0100 Subject: [PATCH 096/175] Simplify implementation of entity serializers --- app/serializers/base_serializer.rb | 10 ++-------- app/serializers/build_entity.rb | 2 +- app/serializers/commit_entity.rb | 6 +++--- app/serializers/deployment_entity.rb | 2 +- app/serializers/entity_request.rb | 4 ---- app/serializers/environment_entity.rb | 2 +- app/serializers/request_aware_entity.rb | 11 ++++++----- spec/serializers/entity_request_spec.rb | 8 -------- 8 files changed, 14 insertions(+), 31 deletions(-) diff --git a/app/serializers/base_serializer.rb b/app/serializers/base_serializer.rb index aeb01dc2ad5..de9a181db90 100644 --- a/app/serializers/base_serializer.rb +++ b/app/serializers/base_serializer.rb @@ -1,17 +1,11 @@ class BaseSerializer def initialize(parameters = {}) - @entity = self.class.entity_class @request = EntityRequest.new(parameters) - @opts = { request: @request } - end - - def set(parameters) - @request.merge!(parameters) - self end def represent(resource, opts = {}) - @entity.represent(resource, @opts.reverse_merge(opts)) + self.class.entity_class + .represent(resource, opts.merge(request: @request)) end def self.entity(entity_class) diff --git a/app/serializers/build_entity.rb b/app/serializers/build_entity.rb index 203bd747ad9..3d9ac66de0e 100644 --- a/app/serializers/build_entity.rb +++ b/app/serializers/build_entity.rb @@ -19,6 +19,6 @@ class BuildEntity < Grape::Entity private def url_to(route, build) - @urls.send("#{route}_url", build.project.namespace, build.project, build) + send("#{route}_url", build.project.namespace, build.project, build) end end diff --git a/app/serializers/commit_entity.rb b/app/serializers/commit_entity.rb index 827782e85bb..f7eba6fc1e3 100644 --- a/app/serializers/commit_entity.rb +++ b/app/serializers/commit_entity.rb @@ -4,9 +4,9 @@ class CommitEntity < API::Entities::RepoCommit expose :author, using: UserEntity expose :commit_url do |commit| - @urls.namespace_project_tree_url( - @request.project.namespace, - @request.project, + namespace_project_tree_url( + request.project.namespace, + request.project, id: commit.id) end end diff --git a/app/serializers/deployment_entity.rb b/app/serializers/deployment_entity.rb index d743b44c4a0..ad6fc8d665b 100644 --- a/app/serializers/deployment_entity.rb +++ b/app/serializers/deployment_entity.rb @@ -11,7 +11,7 @@ class DeploymentEntity < Grape::Entity end expose :ref_url do |deployment| - @urls.namespace_project_tree_url( + namespace_project_tree_url( deployment.project.namespace, deployment.project, id: deployment.ref) diff --git a/app/serializers/entity_request.rb b/app/serializers/entity_request.rb index 12ceb38b284..456ba1174c0 100644 --- a/app/serializers/entity_request.rb +++ b/app/serializers/entity_request.rb @@ -5,10 +5,6 @@ class EntityRequest # that is present in the controller (see #20045). # def initialize(parameters) - merge!(parameters) - end - - def merge!(parameters) parameters.each do |key, value| define_singleton_method(key) { value } end diff --git a/app/serializers/environment_entity.rb b/app/serializers/environment_entity.rb index e80a4335f53..ee4392cc46d 100644 --- a/app/serializers/environment_entity.rb +++ b/app/serializers/environment_entity.rb @@ -10,7 +10,7 @@ class EnvironmentEntity < Grape::Entity expose :stoppable? expose :environment_url do |environment| - @urls.namespace_project_environment_url( + namespace_project_environment_url( environment.project.namespace, environment.project, environment) diff --git a/app/serializers/request_aware_entity.rb b/app/serializers/request_aware_entity.rb index 1586507492d..ff8c1142abc 100644 --- a/app/serializers/request_aware_entity.rb +++ b/app/serializers/request_aware_entity.rb @@ -1,10 +1,11 @@ module RequestAwareEntity - attr_reader :request + extend ActiveSupport::Concern - def initialize(object, options = {}) - super(object, options) + included do + include Gitlab::Routing.url_helpers + end - @request = options.fetch(:request) - @urls = Gitlab::Routing.url_helpers + def request + @options.fetch(:request) end end diff --git a/spec/serializers/entity_request_spec.rb b/spec/serializers/entity_request_spec.rb index 1c220a7b95d..86654adfd54 100644 --- a/spec/serializers/entity_request_spec.rb +++ b/spec/serializers/entity_request_spec.rb @@ -15,12 +15,4 @@ describe EntityRequest do expect { subject.some_method }.to raise_error NoMethodError end end - - describe '#merge!' do - before { subject.merge!(build: 'some build') } - - it 'appends parameters' do - expect(subject.build).to eq 'some build' - end - end end From 8c2143a0a7330768211b8a03a6693ac823679339 Mon Sep 17 00:00:00 2001 From: Felipe Artur Date: Thu, 27 Oct 2016 19:20:47 -0200 Subject: [PATCH 097/175] Allow to test JIRA service when project does not have repository --- app/models/project_services/jira_service.rb | 15 +++++ app/views/projects/services/_form.html.haml | 7 ++- changelogs/unreleased/issue_23032.yml | 4 ++ .../project_services/jira_service_spec.rb | 56 +++++++++++++++++-- 4 files changed, 75 insertions(+), 7 deletions(-) create mode 100644 changelogs/unreleased/issue_23032.yml diff --git a/app/models/project_services/jira_service.rb b/app/models/project_services/jira_service.rb index 0a493b7a12b..2dbe0075465 100644 --- a/app/models/project_services/jira_service.rb +++ b/app/models/project_services/jira_service.rb @@ -163,6 +163,21 @@ class JiraService < IssueTrackerService add_comment(data, issue_key) end + # reason why service cannot be tested + def disabled_title + "Please fill in Password and Username." + end + + def can_test? + username.present? && password.present? + end + + # JIRA does not need test data. + # We are requesting the project that belongs to the project key. + def test_data(user = nil, project = nil) + nil + end + def test_settings return unless url.present? # Test settings by getting the project diff --git a/app/views/projects/services/_form.html.haml b/app/views/projects/services/_form.html.haml index 752fbc21a11..b41edeb2c7e 100644 --- a/app/views/projects/services/_form.html.haml +++ b/app/views/projects/services/_form.html.haml @@ -12,6 +12,9 @@ = form.submit 'Save changes', class: 'btn btn-save'   - if @service.valid? && @service.activated? - - disabled = @service.can_test? ? '':'disabled' - = link_to 'Test settings', test_namespace_project_service_path(@project.namespace, @project, @service), class: "btn #{disabled}", title: @service.disabled_title + - unless @service.can_test? + - disabled_class = 'disabled' + - disabled_title = @service.disabled_title + + = link_to 'Test settings', test_namespace_project_service_path(@project.namespace, @project, @service), class: "btn #{disabled_class}", title: disabled_title = link_to "Cancel", namespace_project_services_path(@project.namespace, @project), class: "btn btn-cancel" diff --git a/changelogs/unreleased/issue_23032.yml b/changelogs/unreleased/issue_23032.yml new file mode 100644 index 00000000000..d376cf52112 --- /dev/null +++ b/changelogs/unreleased/issue_23032.yml @@ -0,0 +1,4 @@ +--- +title: Allow to test JIRA service settings without having a repository +merge_request: +author: diff --git a/spec/models/project_services/jira_service_spec.rb b/spec/models/project_services/jira_service_spec.rb index ee0e38bd373..05ee4a08391 100644 --- a/spec/models/project_services/jira_service_spec.rb +++ b/spec/models/project_services/jira_service_spec.rb @@ -33,6 +33,41 @@ describe JiraService, models: true do end end + describe '#can_test?' do + let(:jira_service) { described_class.new } + + it 'returns false if username is blank' do + allow(jira_service).to receive_messages( + url: 'http://jira.example.com', + username: '', + password: '12345678' + ) + + expect(jira_service.can_test?).to be_falsy + end + + it 'returns false if password is blank' do + allow(jira_service).to receive_messages( + url: 'http://jira.example.com', + username: 'tester', + password: '' + ) + + expect(jira_service.can_test?).to be_falsy + end + + it 'returns true if password and username are present' do + jira_service = described_class.new + allow(jira_service).to receive_messages( + url: 'http://jira.example.com', + username: 'tester', + password: '12345678' + ) + + expect(jira_service.can_test?).to be_truthy + end + end + describe "Execute" do let(:user) { create(:user) } let(:project) { create(:project) } @@ -46,16 +81,19 @@ describe JiraService, models: true do service_hook: true, url: 'http://jira.example.com', username: 'gitlab_jira_username', - password: 'gitlab_jira_password' + password: 'gitlab_jira_password', + project_key: 'GitLabProject' ) @jira_service.save - project_url = 'http://gitlab_jira_username:gitlab_jira_password@jira.example.com/rest/api/2/issue/JIRA-123' - @transitions_url = 'http://gitlab_jira_username:gitlab_jira_password@jira.example.com/rest/api/2/issue/JIRA-123/transitions' - @comment_url = 'http://gitlab_jira_username:gitlab_jira_password@jira.example.com/rest/api/2/issue/JIRA-123/comment' + project_issues_url = 'http://gitlab_jira_username:gitlab_jira_password@jira.example.com/rest/api/2/issue/JIRA-123' + @project_url = 'http://gitlab_jira_username:gitlab_jira_password@jira.example.com/rest/api/2/project/GitLabProject' + @transitions_url = 'http://gitlab_jira_username:gitlab_jira_password@jira.example.com/rest/api/2/issue/JIRA-123/transitions' + @comment_url = 'http://gitlab_jira_username:gitlab_jira_password@jira.example.com/rest/api/2/issue/JIRA-123/comment' - WebMock.stub_request(:get, project_url) + WebMock.stub_request(:get, @project_url) + WebMock.stub_request(:get, project_issues_url) WebMock.stub_request(:post, @transitions_url) WebMock.stub_request(:post, @comment_url) end @@ -99,6 +137,14 @@ describe JiraService, models: true do body: /this-is-a-custom-id/ ).once end + + context "when testing" do + it "tries to get jira project" do + @jira_service.execute(nil) + + expect(WebMock).to have_requested(:get, @project_url) + end + end end describe "Stored password invalidation" do From d72103299df312185e33aca94d58d46d626bd28e Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Fri, 4 Nov 2016 14:27:05 +0000 Subject: [PATCH 098/175] Update GitLab Workhorse to v1.0.0 --- GITLAB_WORKHORSE_VERSION | 2 +- doc/install/installation.md | 2 +- doc/update/8.13-to-8.14.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/GITLAB_WORKHORSE_VERSION b/GITLAB_WORKHORSE_VERSION index 7ada0d303f3..3eefcb9dd5b 100644 --- a/GITLAB_WORKHORSE_VERSION +++ b/GITLAB_WORKHORSE_VERSION @@ -1 +1 @@ -0.8.5 +1.0.0 diff --git a/doc/install/installation.md b/doc/install/installation.md index 7e947e4b2ba..b5e2640b380 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -403,7 +403,7 @@ If you are not using Linux you may have to run `gmake` instead of cd /home/git sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-workhorse.git cd gitlab-workhorse - sudo -u git -H git checkout v0.8.5 + sudo -u git -H git checkout v1.0.0 sudo -u git -H make ### Initialize Database and Activate Advanced Features diff --git a/doc/update/8.13-to-8.14.md b/doc/update/8.13-to-8.14.md index 787511fd6cf..46ea19d11d0 100644 --- a/doc/update/8.13-to-8.14.md +++ b/doc/update/8.13-to-8.14.md @@ -84,7 +84,7 @@ GitLab 8.1. ```bash cd /home/git/gitlab-workhorse sudo -u git -H git fetch --all -sudo -u git -H git checkout v0.8.5 +sudo -u git -H git checkout v1.0.0 sudo -u git -H make ``` From b9b508ad055db7633e44178cb4a00ef934313b04 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Fri, 4 Nov 2016 22:43:02 +0800 Subject: [PATCH 099/175] Remove author according to the document https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/development/changelog.md --- changelogs/unreleased/show-status-from-branch.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelogs/unreleased/show-status-from-branch.yml b/changelogs/unreleased/show-status-from-branch.yml index 6e51bf6932f..1afc230c05c 100644 --- a/changelogs/unreleased/show-status-from-branch.yml +++ b/changelogs/unreleased/show-status-from-branch.yml @@ -1,4 +1,4 @@ --- title: Fix showing pipeline status for a given commit from correct branch merge_request: 7034 -author: Lin Jen-Shin +author: From 99410a4750b514b8d58a6d44f687ef29ecebc7cc Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Fri, 4 Nov 2016 22:43:43 +0800 Subject: [PATCH 100/175] Fetch locals to avoid undefined method/local error Feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7034/diffs#note_17868074 --- app/views/projects/_last_commit.html.haml | 1 + app/views/projects/commits/_commit.html.haml | 1 + app/views/projects/commits/_commits.html.haml | 1 + 3 files changed, 3 insertions(+) diff --git a/app/views/projects/_last_commit.html.haml b/app/views/projects/_last_commit.html.haml index 8aa503159f9..8e23d51b224 100644 --- a/app/views/projects/_last_commit.html.haml +++ b/app/views/projects/_last_commit.html.haml @@ -1,3 +1,4 @@ +- ref = local_assigns.fetch(:ref) - status = commit.status(ref) - if status = link_to builds_namespace_project_commit_path(commit.project.namespace, commit.project, commit), class: "ci-status ci-#{status}" do diff --git a/app/views/projects/commits/_commit.html.haml b/app/views/projects/commits/_commit.html.haml index fd70de9c13d..9f80a974d64 100644 --- a/app/views/projects/commits/_commit.html.haml +++ b/app/views/projects/commits/_commit.html.haml @@ -1,3 +1,4 @@ +- ref = local_assigns.fetch(:ref) - if @note_counts - note_count = @note_counts.fetch(commit.id, 0) - else diff --git a/app/views/projects/commits/_commits.html.haml b/app/views/projects/commits/_commits.html.haml index 943ec24cfb5..48756c68941 100644 --- a/app/views/projects/commits/_commits.html.haml +++ b/app/views/projects/commits/_commits.html.haml @@ -1,3 +1,4 @@ +- ref = local_assigns.fetch(:ref) - commits, hidden = limited_commits(@commits) - commits.chunk { |c| c.committed_date.in_time_zone.to_date }.each do |day, commits| From ac7efb29164e0f30e88be713c07672df3f54e3e6 Mon Sep 17 00:00:00 2001 From: Luke Bennett Date: Thu, 8 Sep 2016 16:50:36 +0100 Subject: [PATCH 101/175] Removed inline JS and added new affix declaration Tidied up UX Corrected naming convention issues with removing inline JS @deckar01 saves the day! Simplified `toggleSidebar` and `hideSidebar` Review changes Merge conflicts and update autoscroll button --- app/assets/javascripts/build.js | 83 ++++++++++++------------ app/assets/javascripts/dispatcher.js.es6 | 3 + app/assets/stylesheets/pages/builds.scss | 22 ++----- app/helpers/builds_helper.rb | 10 +++ app/views/projects/builds/show.html.haml | 28 ++++---- 5 files changed, 74 insertions(+), 72 deletions(-) diff --git a/app/assets/javascripts/build.js b/app/assets/javascripts/build.js index 12e653f4122..54fed3dd573 100644 --- a/app/assets/javascripts/build.js +++ b/app/assets/javascripts/build.js @@ -8,41 +8,44 @@ Build.state = null; function Build(options) { - this.page_url = options.page_url; - this.build_url = options.build_url; - this.build_status = options.build_status; + options = options || $('.js-build-options').data(); + this.pageUrl = options.pageUrl; + this.buildUrl = options.buildUrl; + this.buildStatus = options.buildStatus; this.state = options.state1; - this.build_stage = options.build_stage; - this.hideSidebar = bind(this.hideSidebar, this); - this.toggleSidebar = bind(this.toggleSidebar, this); + this.buildStage = options.buildStage; this.updateDropdown = bind(this.updateDropdown, this); this.$document = $(document); clearInterval(Build.interval); // Init breakpoint checker this.bp = Breakpoints.get(); + this.initSidebar(); + this.$buildScroll = $('#js-build-scroll'); - this.populateJobs(this.build_stage); - this.updateStageDropdownText(this.build_stage); + this.populateJobs(this.buildStage); + this.updateStageDropdownText(this.buildStage); + this.sidebarOnResize(); - $(window).off('resize.build').on('resize.build', this.hideSidebar); + this.$document.off('click', '.js-sidebar-build-toggle').on('click', '.js-sidebar-build-toggle', this.sidebarOnClick.bind(this)); this.$document.off('click', '.stage-item').on('click', '.stage-item', this.updateDropdown); - $('#js-build-scroll > a').off('click').on('click', this.stepTrace); + $(window).off('resize.build').on('resize.build', this.sidebarOnResize.bind(this)); + $('a', this.$buildScroll).off('click.stepTrace').on('click.stepTrace', this.stepTrace); this.updateArtifactRemoveDate(); if ($('#build-trace').length) { this.getInitialBuildTrace(); - this.initScrollButtons(); + this.initScrollButtonAffix(); } - if (this.build_status === "running" || this.build_status === "pending") { + if (this.buildStatus === "running" || this.buildStatus === "pending") { $('#autoscroll-button').on('click', function() { var state; state = $(this).data("state"); if ("enabled" === state) { $(this).data("state", "disabled"); - return $(this).text("enable autoscroll"); + return $(this).text("Enable autoscroll"); } else { $(this).data("state", "enabled"); - return $(this).text("disable autoscroll"); + return $(this).text("Disable autoscroll"); } // // Bind autoscroll button to follow build output @@ -50,7 +53,7 @@ }); Build.interval = setInterval((function(_this) { return function() { - if (window.location.href.split("#").first() === _this.page_url) { + if (window.location.href.split("#").first() === _this.pageUrl) { return _this.getBuildTrace(); } }; @@ -72,7 +75,6 @@ top: this.sidebarTranslationLimits.max }); this.$sidebar.niceScroll(); - this.hideSidebar(); this.$document.off('click', '.js-sidebar-build-toggle').on('click', '.js-sidebar-build-toggle', this.toggleSidebar); this.$document.off('scroll.translateSidebar').on('scroll.translateSidebar', this.translateSidebar.bind(this)); }; @@ -81,11 +83,11 @@ var removeRefreshStatuses = ['success', 'failed', 'canceled', 'skipped'] return $.ajax({ - url: this.build_url, + url: this.buildUrl, dataType: 'json', - success: function(build_data) { - $('.js-build-output').html(build_data.trace_html); - if (removeRefreshStatuses.indexOf(build_data.status) >= 0) { + success: function(buildData) { + $('.js-build-output').html(buildData.trace_html); + if (removeRefreshStatuses.indexOf(buildData.status) >= 0) { return $('.js-build-refresh').remove(); } } @@ -94,7 +96,7 @@ Build.prototype.getBuildTrace = function() { return $.ajax({ - url: this.page_url + "/trace.json?state=" + (encodeURIComponent(this.state)), + url: this.pageUrl + "/trace.json?state=" + (encodeURIComponent(this.state)), dataType: "json", success: (function(_this) { return function(log) { @@ -108,8 +110,8 @@ $('.js-build-output').html(log.html); } return _this.checkAutoscroll(); - } else if (log.status !== _this.build_status) { - return Turbolinks.visit(_this.page_url); + } else if (log.status !== _this.buildStatus) { + return Turbolinks.visit(_this.pageUrl); } }; })(this) @@ -122,12 +124,11 @@ } }; - Build.prototype.initScrollButtons = function() { - var $body, $buildScroll, $buildTrace; - $buildScroll = $('#js-build-scroll'); + Build.prototype.initScrollButtonAffix = function() { + var $body, $buildTrace; $body = $('body'); $buildTrace = $('#build-trace'); - return $buildScroll.affix({ + return this.$buildScroll.affix({ offset: { bottom: function() { return $body.outerHeight() - ($buildTrace.outerHeight() + $buildTrace.offset().top); @@ -136,18 +137,12 @@ }); }; - Build.prototype.shouldHideSidebar = function() { + Build.prototype.shouldHideSidebarForViewport = function() { var bootstrapBreakpoint; bootstrapBreakpoint = this.bp.getBreakpointSize(); return bootstrapBreakpoint === 'xs' || bootstrapBreakpoint === 'sm'; }; - Build.prototype.toggleSidebar = function() { - if (this.shouldHideSidebar()) { - return this.$sidebar.toggleClass('right-sidebar-expanded right-sidebar-collapsed'); - } - }; - Build.prototype.translateSidebar = function(e) { var newPosition = this.sidebarTranslationLimits.max - (document.body.scrollTop || document.documentElement.scrollTop); if (newPosition < this.sidebarTranslationLimits.min) newPosition = this.sidebarTranslationLimits.min; @@ -156,12 +151,20 @@ }); }; - Build.prototype.hideSidebar = function() { - if (this.shouldHideSidebar()) { - return this.$sidebar.removeClass('right-sidebar-expanded').addClass('right-sidebar-collapsed'); - } else { - return this.$sidebar.removeClass('right-sidebar-collapsed').addClass('right-sidebar-expanded'); - } + Build.prototype.toggleSidebar = function(shouldHide) { + var shouldShow = typeof shouldHide === 'boolean' ? !shouldHide : undefined; + this.$buildScroll.toggleClass('sidebar-expanded', shouldShow) + .toggleClass('sidebar-collapsed', shouldHide); + this.$sidebar.toggleClass('right-sidebar-expanded', shouldShow) + .toggleClass('right-sidebar-collapsed', shouldHide); + }; + + Build.prototype.sidebarOnResize = function() { + this.toggleSidebar(this.shouldHideSidebarForViewport()); + }; + + Build.prototype.sidebarOnClick = function() { + if (this.shouldHideSidebarForViewport()) this.toggleSidebar(); }; Build.prototype.updateArtifactRemoveDate = function() { diff --git a/app/assets/javascripts/dispatcher.js.es6 b/app/assets/javascripts/dispatcher.js.es6 index 8e4fd1f19ba..756a24cc0fc 100644 --- a/app/assets/javascripts/dispatcher.js.es6 +++ b/app/assets/javascripts/dispatcher.js.es6 @@ -29,6 +29,9 @@ case 'projects:boards:index': shortcut_handler = new ShortcutsNavigation(); break; + case 'projects:builds:show': + new Build(); + break; case 'projects:merge_requests:index': case 'projects:issues:index': Issuable.init(); diff --git a/app/assets/stylesheets/pages/builds.scss b/app/assets/stylesheets/pages/builds.scss index 6300ac9662f..f1d311cabbe 100644 --- a/app/assets/stylesheets/pages/builds.scss +++ b/app/assets/stylesheets/pages/builds.scss @@ -14,18 +14,10 @@ } } - .autoscroll-container { - position: fixed; - bottom: 20px; - right: 20px; - z-index: 100; - } - .scroll-controls { - &.affix-top { - position: absolute; - top: 10px; - right: 25px; + .scroll-step { + width: 31px; + margin: 0 0 0 auto; } &.affix-bottom { @@ -34,13 +26,13 @@ } &.affix { - right: 30px; + right: 25px; bottom: 15px; z-index: 1; + } - @media (min-width: $screen-md-min) { - right: 26%; - } + &.sidebar-expanded { + right: #{$gutter_width + ($gl-padding * 2)}; } a { diff --git a/app/helpers/builds_helper.rb b/app/helpers/builds_helper.rb index f3aaff9140d..fde297c588e 100644 --- a/app/helpers/builds_helper.rb +++ b/app/helpers/builds_helper.rb @@ -5,4 +5,14 @@ module BuildsHelper build_class += ' retried' if build.retried? build_class end + + def javascript_build_options + { + page_url: namespace_project_build_url(@project.namespace, @project, @build), + build_url: namespace_project_build_url(@project.namespace, @project, @build, :json), + build_status: @build.status, + build_stage: @build.stage, + state1: @build.trace_with_state[:state] + } + end end diff --git a/app/views/projects/builds/show.html.haml b/app/views/projects/builds/show.html.haml index b5e8b0bf6eb..ae7a7ecb392 100644 --- a/app/views/projects/builds/show.html.haml +++ b/app/views/projects/builds/show.html.haml @@ -1,6 +1,5 @@ - @no_container = true - page_title "#{@build.name} (##{@build.id})", "Builds" -- trace_with_state = @build.trace_with_state - header_title project_title(@project, "Builds", project_builds_path(@project)) = render "projects/pipelines/head", build_subnav: true @@ -28,32 +27,27 @@ Runners page .prepend-top-default - - if @build.active? - .autoscroll-container - %button.btn.btn-success.btn-sm#autoscroll-button{:type => "button", :data => {:state => 'disabled'}} enable autoscroll - if @build.erased? .erased.alert.alert-warning - erased_by = "by #{link_to @build.erased_by.name, user_path(@build.erased_by)}" if @build.erased_by Build has been erased #{erased_by.html_safe} #{time_ago_with_tooltip(@build.erased_at)} - else #js-build-scroll.scroll-controls - = link_to '#build-trace', class: 'btn' do - %i.fa.fa-angle-up - = link_to '#down-build-trace', class: 'btn' do - %i.fa.fa-angle-down + .scroll-step + = link_to '#build-trace', class: 'btn' do + %i.fa.fa-angle-up + = link_to '#down-build-trace', class: 'btn' do + %i.fa.fa-angle-down + - if @build.active? + .autoscroll-container + %button.btn.btn-sm#autoscroll-button{:type => "button", :data => {:state => 'disabled'}} + Enable autoscroll %pre.build-trace#build-trace %code.bash.js-build-output = icon("refresh spin", class: "js-build-refresh") - #down-build-trace + #down-build-trace = render "sidebar" - :javascript - new Build({ - page_url: "#{namespace_project_build_url(@project.namespace, @project, @build)}", - build_url: "#{namespace_project_build_url(@project.namespace, @project, @build, :json)}", - build_status: "#{@build.status}", - build_stage: "#{@build.stage}", - state1: "#{trace_with_state[:state]}" - }) +.js-build-options{ data: javascript_build_options } From dd45c5e11eb2b315d89779abf6103e2531e1cc08 Mon Sep 17 00:00:00 2001 From: Jared Deckard Date: Tue, 20 Sep 2016 10:50:32 -0500 Subject: [PATCH 102/175] Add javascript unit tests for Build Move comments to the correct location Remove array extension usage Move build options to fixture to match view --- app/assets/javascripts/build.js | 16 +- spec/javascripts/build_spec.js.es6 | 174 ++++++++++++++++++++++ spec/javascripts/fixtures/build.html.haml | 57 +++++++ 3 files changed, 239 insertions(+), 8 deletions(-) create mode 100644 spec/javascripts/build_spec.js.es6 create mode 100644 spec/javascripts/fixtures/build.html.haml diff --git a/app/assets/javascripts/build.js b/app/assets/javascripts/build.js index 54fed3dd573..3d284e5846f 100644 --- a/app/assets/javascripts/build.js +++ b/app/assets/javascripts/build.js @@ -37,6 +37,7 @@ this.initScrollButtonAffix(); } if (this.buildStatus === "running" || this.buildStatus === "pending") { + // Bind autoscroll button to follow build output $('#autoscroll-button').on('click', function() { var state; state = $(this).data("state"); @@ -47,20 +48,15 @@ $(this).data("state", "enabled"); return $(this).text("Disable autoscroll"); } - // - // Bind autoscroll button to follow build output - // }); Build.interval = setInterval((function(_this) { + // Check for new build output if user still watching build page + // Only valid for runnig build when output changes during time return function() { - if (window.location.href.split("#").first() === _this.pageUrl) { + if (_this.location() === _this.pageUrl) { return _this.getBuildTrace(); } }; - // - // Check for new build output if user still watching build page - // Only valid for runnig build when output changes during time - // })(this), 4000); } } @@ -79,6 +75,10 @@ this.$document.off('scroll.translateSidebar').on('scroll.translateSidebar', this.translateSidebar.bind(this)); }; + Build.prototype.location = function() { + return window.location.href.split("#")[0]; + }; + Build.prototype.getInitialBuildTrace = function() { var removeRefreshStatuses = ['success', 'failed', 'canceled', 'skipped'] diff --git a/spec/javascripts/build_spec.js.es6 b/spec/javascripts/build_spec.js.es6 new file mode 100644 index 00000000000..44485c7745c --- /dev/null +++ b/spec/javascripts/build_spec.js.es6 @@ -0,0 +1,174 @@ +/* eslint-disable */ +//= require build +//= require breakpoints +//= require jquery.nicescroll +//= require turbolinks + +(() => { + describe('Build', () => { + fixture.preload('build.html'); + + beforeEach(function() { + fixture.load('build.html'); + spyOn($, 'ajax'); + }); + + describe('constructor', () => { + beforeEach(function() { + jasmine.clock().install(); + }); + + afterEach(() => { + jasmine.clock().uninstall(); + }); + + describe('setup', function() { + beforeEach(function() { + this.build = new Build(); + }); + + it('copies build options', function() { + expect(this.build.pageUrl).toBe('http://example.com/root/test-build/builds/2'); + expect(this.build.buildUrl).toBe('http://example.com/root/test-build/builds/2.json'); + expect(this.build.buildStatus).toBe('passed'); + expect(this.build.buildStage).toBe('test'); + expect(this.build.state).toBe('buildstate'); + }); + + it('only shows the jobs matching the current stage', function() { + expect($('.build-job[data-stage="build"]').is(':visible')).toBe(false); + expect($('.build-job[data-stage="test"]').is(':visible')).toBe(true); + expect($('.build-job[data-stage="deploy"]').is(':visible')).toBe(false); + }); + + it('selects the current stage in the build dropdown menu', function() { + expect($('.stage-selection').text()).toBe('test'); + }); + + it('updates the jobs when the build dropdown changes', function() { + $('.stage-item:contains("build")').click(); + + expect($('.stage-selection').text()).toBe('build'); + expect($('.build-job[data-stage="build"]').is(':visible')).toBe(true); + expect($('.build-job[data-stage="test"]').is(':visible')).toBe(false); + expect($('.build-job[data-stage="deploy"]').is(':visible')).toBe(false); + }); + }); + + describe('initial build trace', function() { + beforeEach(function() { + new Build(); + }); + + it('displays the initial build trace', function() { + expect($.ajax.calls.count()).toBe(1); + const [{url, dataType, success, context}] = $.ajax.calls.argsFor(0); + expect(url).toBe('http://example.com/root/test-build/builds/2.json'); + expect(dataType).toBe('json'); + expect(success).toEqual(jasmine.any(Function)); + + success.call(context, {trace_html: 'Example', status: 'running'}); + + expect($('#build-trace .js-build-output').text()).toMatch(/Example/); + }); + + it('removes the spinner', function() { + const [{success, context}] = $.ajax.calls.argsFor(0); + success.call(context, {trace_html: 'Example', status: 'success'}); + + expect($('.js-build-refresh').length).toBe(0); + }); + }); + + describe('running build', function() { + beforeEach(function() { + $('.js-build-options').data('buildStatus', 'running'); + this.build = new Build(); + spyOn(this.build, 'location') + .and.returnValue('http://example.com/root/test-build/builds/2'); + }); + + it('updates the build trace on an interval', function() { + jasmine.clock().tick(4001); + + expect($.ajax.calls.count()).toBe(2); + let [{url, dataType, success, context}] = $.ajax.calls.argsFor(1); + expect(url).toBe( + 'http://example.com/root/test-build/builds/2/trace.json?state=buildstate' + ); + expect(dataType).toBe('json'); + expect(success).toEqual(jasmine.any(Function)); + + success.call(context, { + html: 'Update', + status: 'running', + state: 'newstate', + append: true + }); + + expect($('#build-trace .js-build-output').text()).toMatch(/Update/); + expect(this.build.state).toBe('newstate'); + + jasmine.clock().tick(4001); + + expect($.ajax.calls.count()).toBe(3); + [{url, dataType, success, context}] = $.ajax.calls.argsFor(2); + expect(url).toBe( + 'http://example.com/root/test-build/builds/2/trace.json?state=newstate' + ); + expect(dataType).toBe('json'); + expect(success).toEqual(jasmine.any(Function)); + + success.call(context, { + html: 'More', + status: 'running', + state: 'finalstate', + append: true + }); + + expect($('#build-trace .js-build-output').text()).toMatch(/UpdateMore/); + expect(this.build.state).toBe('finalstate'); + }); + + it('replaces the entire build trace', function() { + jasmine.clock().tick(4001); + let [{success, context}] = $.ajax.calls.argsFor(1); + success.call(context, { + html: 'Update', + status: 'running', + append: true + }); + + expect($('#build-trace .js-build-output').text()).toMatch(/Update/); + + jasmine.clock().tick(4001); + [{success, context}] = $.ajax.calls.argsFor(2); + success.call(context, { + html: 'Different', + status: 'running', + append: false + }); + + expect($('#build-trace .js-build-output').text()).not.toMatch(/Update/); + expect($('#build-trace .js-build-output').text()).toMatch(/Different/); + }); + + it('reloads the page when the build is done', function() { + spyOn(Turbolinks, 'visit'); + + jasmine.clock().tick(4001); + let [{success, context}] = $.ajax.calls.argsFor(1); + success.call(context, { + html: 'Final', + status: 'passed', + append: true + }); + + expect(Turbolinks.visit).toHaveBeenCalledWith( + 'http://example.com/root/test-build/builds/2' + ); + }); + }); + }); + }); +})(); diff --git a/spec/javascripts/fixtures/build.html.haml b/spec/javascripts/fixtures/build.html.haml new file mode 100644 index 00000000000..a2bc81c6be7 --- /dev/null +++ b/spec/javascripts/fixtures/build.html.haml @@ -0,0 +1,57 @@ +.build-page + .prepend-top-default + .autoscroll-container + %button.btn.btn-success.btn-sm#autoscroll-button{:type => "button", :data => {:state => 'disabled'}} enable autoscroll + #js-build-scroll.scroll-controls + %a.btn{href: '#build-trace'} + %i.fa.fa-angle-up + %a.btn{href: '#down-build-trace'} + %i.fa.fa-angle-down + %pre.build-trace#build-trace + %code.bash.js-build-output + %i.fa.fa-refresh.fa-spin.js-build-refresh + +%aside.right-sidebar.right-sidebar-expanded.build-sidebar.js-build-sidebar + .block.build-sidebar-header.visible-xs-block.visible-sm-block.append-bottom-default + Build + %strong #1 + %a.gutter-toggle.pull-right.js-sidebar-build-toggle{ href: "#" } + %i.fa.fa-angle-double-right + .blocks-container + .dropdown.build-dropdown + .title Stage + %button.dropdown-menu-toggle{type: 'button', 'data-toggle' => 'dropdown'} + %span.stage-selection More + %i.fa.fa-caret-down + %ul.dropdown-menu + %li + %a.stage-item build + %li + %a.stage-item test + %li + %a.stage-item deploy + .builds-container + .build-job{data: {stage: 'build'}} + %a{href: 'http://example.com/root/test-build/builds/1'} + %i.fa.fa-check + %i.fa.fa-check-circle-o + %span + Setup + .build-job{data: {stage: 'test'}} + %a{href: 'http://example.com/root/test-build/builds/2'} + %i.fa.fa-check + %i.fa.fa-check-circle-o + %span + Tests + .build-job{data: {stage: 'deploy'}} + %a{href: 'http://example.com/root/test-build/builds/3'} + %i.fa.fa-check + %i.fa.fa-check-circle-o + %span + Deploy + +.js-build-options{ data: { page_url: 'http://example.com/root/test-build/builds/2', + build_url: 'http://example.com/root/test-build/builds/2.json', + build_status: 'passed', + build_stage: 'test', + state1: 'buildstate' }} From e517da3ff07b09d680d11c98b8298d02a4b105eb Mon Sep 17 00:00:00 2001 From: "Luke \"Jared\" Bennett" Date: Fri, 28 Oct 2016 14:38:10 +0100 Subject: [PATCH 103/175] Created wait_for_turbolinks and added test for refs dropdown selection with special chars --- spec/features/projects/ref_switcher_spec.rb | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/spec/features/projects/ref_switcher_spec.rb b/spec/features/projects/ref_switcher_spec.rb index b3ba40b35af..472491188c9 100644 --- a/spec/features/projects/ref_switcher_spec.rb +++ b/spec/features/projects/ref_switcher_spec.rb @@ -22,8 +22,20 @@ feature 'Ref switcher', feature: true, js: true do input.native.send_keys :down input.native.send_keys :down input.native.send_keys :enter - - expect(page).to have_content 'expand-collapse-files' end + + expect(page).to have_title 'expand-collapse-files' + end + + it "user selects ref with special characters" do + click_button 'master' + wait_for_ajax + + page.within '.project-refs-form' do + page.fill_in 'Search branches and tags', with: "'test'" + click_link "'test'" + end + + expect(page).to have_title "'test'" end end From 4f377364ad2b073e59e8edde86f270c80cdb317a Mon Sep 17 00:00:00 2001 From: "Luke \"Jared\" Bennett" Date: Mon, 31 Oct 2016 14:56:55 +0000 Subject: [PATCH 104/175] Added new .eslintrc for jasmine tests and corrected build_spec --- package.json | 1 + spec/javascripts/.eslintrc | 11 +++++ spec/javascripts/build_spec.js.es6 | 65 +++++++++++++++--------------- 3 files changed, 45 insertions(+), 32 deletions(-) create mode 100644 spec/javascripts/.eslintrc diff --git a/package.json b/package.json index a303c9c1eac..e75e070451b 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "eslint-config-airbnb": "^12.0.0", "eslint-plugin-filenames": "^1.1.0", "eslint-plugin-import": "^2.0.1", + "eslint-plugin-jasmine": "^1.8.1", "eslint-plugin-jsx-a11y": "^2.2.3", "eslint-plugin-react": "^6.4.1" } diff --git a/spec/javascripts/.eslintrc b/spec/javascripts/.eslintrc new file mode 100644 index 00000000000..90388929612 --- /dev/null +++ b/spec/javascripts/.eslintrc @@ -0,0 +1,11 @@ +{ + "plugins": ["jasmine"], + "env": { + "jasmine": true + }, + "extends": "plugin:jasmine/recommended", + "rules": { + "prefer-arrow-callback": 0, + "func-names": 0 + } +} diff --git a/spec/javascripts/build_spec.js.es6 b/spec/javascripts/build_spec.js.es6 index 44485c7745c..370944b6a8c 100644 --- a/spec/javascripts/build_spec.js.es6 +++ b/spec/javascripts/build_spec.js.es6 @@ -1,4 +1,5 @@ -/* eslint-disable */ +/* global Build */ +/* eslint-disable no-new */ //= require build //= require breakpoints //= require jquery.nicescroll @@ -8,13 +9,13 @@ describe('Build', () => { fixture.preload('build.html'); - beforeEach(function() { + beforeEach(function () { fixture.load('build.html'); spyOn($, 'ajax'); }); describe('constructor', () => { - beforeEach(function() { + beforeEach(function () { jasmine.clock().install(); }); @@ -22,12 +23,12 @@ jasmine.clock().uninstall(); }); - describe('setup', function() { - beforeEach(function() { + describe('setup', function () { + beforeEach(function () { this.build = new Build(); }); - it('copies build options', function() { + it('copies build options', function () { expect(this.build.pageUrl).toBe('http://example.com/root/test-build/builds/2'); expect(this.build.buildUrl).toBe('http://example.com/root/test-build/builds/2.json'); expect(this.build.buildStatus).toBe('passed'); @@ -35,17 +36,17 @@ expect(this.build.state).toBe('buildstate'); }); - it('only shows the jobs matching the current stage', function() { + it('only shows the jobs matching the current stage', function () { expect($('.build-job[data-stage="build"]').is(':visible')).toBe(false); expect($('.build-job[data-stage="test"]').is(':visible')).toBe(true); expect($('.build-job[data-stage="deploy"]').is(':visible')).toBe(false); }); - it('selects the current stage in the build dropdown menu', function() { + it('selects the current stage in the build dropdown menu', function () { expect($('.stage-selection').text()).toBe('test'); }); - it('updates the jobs when the build dropdown changes', function() { + it('updates the jobs when the build dropdown changes', function () { $('.stage-item:contains("build")').click(); expect($('.stage-selection').text()).toBe('build'); @@ -55,44 +56,44 @@ }); }); - describe('initial build trace', function() { - beforeEach(function() { + describe('initial build trace', function () { + beforeEach(function () { new Build(); }); - it('displays the initial build trace', function() { + it('displays the initial build trace', function () { expect($.ajax.calls.count()).toBe(1); - const [{url, dataType, success, context}] = $.ajax.calls.argsFor(0); + const [{ url, dataType, success, context }] = $.ajax.calls.argsFor(0); expect(url).toBe('http://example.com/root/test-build/builds/2.json'); expect(dataType).toBe('json'); expect(success).toEqual(jasmine.any(Function)); - success.call(context, {trace_html: 'Example', status: 'running'}); + success.call(context, { trace_html: 'Example', status: 'running' }); expect($('#build-trace .js-build-output').text()).toMatch(/Example/); }); - it('removes the spinner', function() { - const [{success, context}] = $.ajax.calls.argsFor(0); - success.call(context, {trace_html: 'Example', status: 'success'}); + it('removes the spinner', function () { + const [{ success, context }] = $.ajax.calls.argsFor(0); + success.call(context, { trace_html: 'Example', status: 'success' }); expect($('.js-build-refresh').length).toBe(0); }); }); - describe('running build', function() { - beforeEach(function() { + describe('running build', function () { + beforeEach(function () { $('.js-build-options').data('buildStatus', 'running'); this.build = new Build(); spyOn(this.build, 'location') .and.returnValue('http://example.com/root/test-build/builds/2'); }); - it('updates the build trace on an interval', function() { + it('updates the build trace on an interval', function () { jasmine.clock().tick(4001); expect($.ajax.calls.count()).toBe(2); - let [{url, dataType, success, context}] = $.ajax.calls.argsFor(1); + let [{ url, dataType, success, context }] = $.ajax.calls.argsFor(1); expect(url).toBe( 'http://example.com/root/test-build/builds/2/trace.json?state=buildstate' ); @@ -103,7 +104,7 @@ html: 'Update', status: 'running', state: 'newstate', - append: true + append: true, }); expect($('#build-trace .js-build-output').text()).toMatch(/Update/); @@ -112,7 +113,7 @@ jasmine.clock().tick(4001); expect($.ajax.calls.count()).toBe(3); - [{url, dataType, success, context}] = $.ajax.calls.argsFor(2); + [{ url, dataType, success, context }] = $.ajax.calls.argsFor(2); expect(url).toBe( 'http://example.com/root/test-build/builds/2/trace.json?state=newstate' ); @@ -123,45 +124,45 @@ html: 'More', status: 'running', state: 'finalstate', - append: true + append: true, }); expect($('#build-trace .js-build-output').text()).toMatch(/UpdateMore/); expect(this.build.state).toBe('finalstate'); }); - it('replaces the entire build trace', function() { + it('replaces the entire build trace', function () { jasmine.clock().tick(4001); - let [{success, context}] = $.ajax.calls.argsFor(1); + let [{ success, context }] = $.ajax.calls.argsFor(1); success.call(context, { html: 'Update', status: 'running', - append: true + append: true, }); expect($('#build-trace .js-build-output').text()).toMatch(/Update/); jasmine.clock().tick(4001); - [{success, context}] = $.ajax.calls.argsFor(2); + [{ success, context }] = $.ajax.calls.argsFor(2); success.call(context, { html: 'Different', status: 'running', - append: false + append: false, }); expect($('#build-trace .js-build-output').text()).not.toMatch(/Update/); expect($('#build-trace .js-build-output').text()).toMatch(/Different/); }); - it('reloads the page when the build is done', function() { + it('reloads the page when the build is done', function () { spyOn(Turbolinks, 'visit'); jasmine.clock().tick(4001); - let [{success, context}] = $.ajax.calls.argsFor(1); + const [{ success, context }] = $.ajax.calls.argsFor(1); success.call(context, { html: 'Final', status: 'passed', - append: true + append: true, }); expect(Turbolinks.visit).toHaveBeenCalledWith( From db8fed26af82f1fb6f143a9b15b6af27138953f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Wed, 2 Nov 2016 18:52:04 +0100 Subject: [PATCH 105/175] Refactor template selector in issuable form MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- app/helpers/blob_helper.rb | 27 ---------- app/helpers/issuables_helper.rb | 51 +++++++++++++++++++ app/views/shared/issuable/_form.html.haml | 19 ++----- .../form/_template_selector.html.haml | 13 +++++ 4 files changed, 67 insertions(+), 43 deletions(-) create mode 100644 app/views/shared/issuable/form/_template_selector.html.haml diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb index e13b7cdd707..07ff6fb9488 100644 --- a/app/helpers/blob_helper.rb +++ b/app/helpers/blob_helper.rb @@ -179,33 +179,6 @@ module BlobHelper } end - def selected_template(issuable) - templates = issuable_templates(issuable) - params[:issuable_template] if templates.include?(params[:issuable_template]) - end - - def can_add_template?(issuable) - names = issuable_templates(issuable) - names.empty? && can?(current_user, :push_code, @project) && !@project.private? - end - - def merge_request_template_names - @merge_request_templates ||= Gitlab::Template::MergeRequestTemplate.dropdown_names(ref_project) - end - - def issue_template_names - @issue_templates ||= Gitlab::Template::IssueTemplate.dropdown_names(ref_project) - end - - def issuable_templates(issuable) - @issuable_templates ||= - if issuable.is_a?(Issue) - issue_template_names - elsif issuable.is_a?(MergeRequest) - merge_request_template_names - end - end - def ref_project @ref_project ||= @target_project || @project end diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb index ef6cfb235a9..8127c3f3ee3 100644 --- a/app/helpers/issuables_helper.rb +++ b/app/helpers/issuables_helper.rb @@ -30,6 +30,33 @@ module IssuablesHelper end end + def can_add_template?(issuable) + names = issuable_templates(issuable) + names.empty? && can?(current_user, :push_code, @project) && !@project.private? + end + + def template_dropdown_tag(issuable, &block) + title = selected_template(issuable) || "Choose a template" + options = { + toggle_class: 'js-issuable-selector', + title: title, + filter: true, + placeholder: 'Filter', + footer_content: true, + data: { + data: issuable_templates(issuable), + field_name: 'issuable_template', + selected: selected_template(issuable), + project_path: ref_project.path, + namespace_path: ref_project.namespace.path + } + } + + dropdown_tag(title, options: options) do + capture(&block) + end + end + def user_dropdown_label(user_id, default_label) return default_label if user_id.nil? return "Unassigned" if user_id == "0" @@ -153,4 +180,28 @@ module IssuablesHelper hexdigest(['issuables_count', issuable_type, opts.sort].flatten.join('-')) end + + def issuable_templates(issuable) + @issuable_templates ||= + case issuable + when Issue + issue_template_names + when MergeRequest + merge_request_template_names + else + raise 'Unknown issuable type!' + end + end + + def merge_request_template_names + @merge_request_templates ||= Gitlab::Template::MergeRequestTemplate.dropdown_names(ref_project) + end + + def issue_template_names + @issue_templates ||= Gitlab::Template::IssueTemplate.dropdown_names(ref_project) + end + + def selected_template(issuable) + params[:issuable_template] if issuable_templates(issuable).include?(params[:issuable_template]) + end end diff --git a/app/views/shared/issuable/_form.html.haml b/app/views/shared/issuable/_form.html.haml index 0ace6be8f4e..8d976952781 100644 --- a/app/views/shared/issuable/_form.html.haml +++ b/app/views/shared/issuable/_form.html.haml @@ -1,4 +1,5 @@ - project = @target_project || @project + = form_errors(issuable) - if @conflict @@ -11,23 +12,9 @@ .form-group = f.label :title, class: 'control-label' - - issuable_template_names = issuable_templates(issuable) + = render 'shared/issuable/form/template_selector', issuable: issuable - - if issuable_template_names.any? - .col-sm-3.col-lg-2 - .js-issuable-selector-wrap{ data: { issuable_type: issuable.class.to_s.underscore.downcase } } - - title = selected_template(issuable) || "Choose a template" - - = dropdown_tag(title, options: { toggle_class: 'js-issuable-selector', - title: title, filter: true, placeholder: 'Filter', footer_content: true, - data: { data: issuable_template_names, field_name: 'issuable_template', selected: selected_template(issuable), project_path: ref_project.path, namespace_path: ref_project.namespace.path } } ) do - %ul.dropdown-footer-list - %li - %a.no-template - No template - %a.reset-template - Reset template - %div{ class: issuable_template_names.any? ? 'col-sm-7 col-lg-8' : 'col-sm-10' } + %div{ class: issuable_templates(issuable).any? ? 'col-sm-7 col-lg-8' : 'col-sm-10' } = f.text_field :title, maxlength: 255, autofocus: true, autocomplete: 'off', class: 'form-control pad', required: true diff --git a/app/views/shared/issuable/form/_template_selector.html.haml b/app/views/shared/issuable/form/_template_selector.html.haml new file mode 100644 index 00000000000..d613bd31d81 --- /dev/null +++ b/app/views/shared/issuable/form/_template_selector.html.haml @@ -0,0 +1,13 @@ +- issuable = local_assigns.fetch(:issuable, nil) + +- return unless issuable && issuable_templates(issuable).any? + +.col-sm-3.col-lg-2 + .js-issuable-selector-wrap{ data: { issuable_type: issuable.to_ability_name } } + = template_dropdown_tag(issuable) do + %ul.dropdown-footer-list + %li + %a.no-template + No template + %a.reset-template + Reset template From 5d0f68f26b0b6597c99d1e21d6f6978d963ea0d3 Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Gray Date: Fri, 4 Nov 2016 11:23:58 -0500 Subject: [PATCH 106/175] Fix diff_comments failure --- features/steps/shared/diff_note.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/steps/shared/diff_note.rb b/features/steps/shared/diff_note.rb index 4df4e89f5b9..35b71599708 100644 --- a/features/steps/shared/diff_note.rb +++ b/features/steps/shared/diff_note.rb @@ -210,7 +210,7 @@ module SharedDiffNote end step 'I click side-by-side diff button' do - find('#parallel-diff-btn').click + find('#parallel-diff-btn').trigger('click') end step 'I see side-by-side diff button' do From d03615736f29cb791db6e98ad658a532d6c8d271 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Sat, 5 Nov 2016 02:18:04 +0800 Subject: [PATCH 107/175] No need to set author for GitLab members --- changelogs/unreleased/pipeline-notifications.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelogs/unreleased/pipeline-notifications.yml b/changelogs/unreleased/pipeline-notifications.yml index e415444020f..b43060674b2 100644 --- a/changelogs/unreleased/pipeline-notifications.yml +++ b/changelogs/unreleased/pipeline-notifications.yml @@ -3,4 +3,4 @@ title: Add CI notifications. Who triggered a pipeline would receive an email aft the pipeline is succeeded or failed. Users could also update notification settings accordingly merge_request: 6342 -author: Lin Jen-Shin +author: From 18a26c3367a56d3ebaed28c6e060eefefca19677 Mon Sep 17 00:00:00 2001 From: Connor Shea Date: Fri, 4 Nov 2016 12:48:05 -0600 Subject: [PATCH 108/175] Upgrade redis-rails from 4.0.0 to 5.0.1. This update adds support for Rails 5. Also update redis-rails dependencies. --- Gemfile | 2 +- Gemfile.lock | 32 ++++++++++++++++---------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Gemfile b/Gemfile index de624256c16..5286d2f6d6b 100644 --- a/Gemfile +++ b/Gemfile @@ -152,7 +152,7 @@ gem 'settingslogic', '~> 2.0.9' gem 'version_sorter', '~> 2.1.0' # Cache -gem 'redis-rails', '~> 4.0.0' +gem 'redis-rails', '~> 5.0.1' # Redis gem 'redis', '~> 3.2' diff --git a/Gemfile.lock b/Gemfile.lock index 6ea0578d9d2..165b25c170e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -573,23 +573,23 @@ GEM json redcarpet (3.3.3) redis (3.2.2) - redis-actionpack (4.0.1) - actionpack (~> 4) - redis-rack (~> 1.5.0) - redis-store (~> 1.1.0) - redis-activesupport (4.1.5) - activesupport (>= 3, < 5) - redis-store (~> 1.1.0) + redis-actionpack (5.0.1) + actionpack (>= 4.0, < 6) + redis-rack (>= 1, < 3) + redis-store (>= 1.1.0, < 1.4.0) + redis-activesupport (5.0.1) + activesupport (>= 3, < 6) + redis-store (~> 1.2.0) redis-namespace (1.5.2) redis (~> 3.0, >= 3.0.4) - redis-rack (1.5.0) + redis-rack (1.6.0) rack (~> 1.5) - redis-store (~> 1.1.0) - redis-rails (4.0.0) - redis-actionpack (~> 4) - redis-activesupport (~> 4) - redis-store (~> 1.1.0) - redis-store (1.1.7) + redis-store (~> 1.2.0) + redis-rails (5.0.1) + redis-actionpack (~> 5.0.0) + redis-activesupport (~> 5.0.0) + redis-store (~> 1.2.0) + redis-store (1.2.0) redis (>= 2.2) request_store (1.3.1) rerun (0.11.0) @@ -938,7 +938,7 @@ DEPENDENCIES redcarpet (~> 3.3.3) redis (~> 3.2) redis-namespace (~> 1.5.2) - redis-rails (~> 4.0.0) + redis-rails (~> 5.0.1) request_store (~> 1.3) rerun (~> 0.11.0) responders (~> 2.0) @@ -994,4 +994,4 @@ DEPENDENCIES wikicloth (= 0.8.1) BUNDLED WITH - 1.13.5 + 1.13.6 From 7cb3fbbbce40de77ff6ecdb936e062227efe9672 Mon Sep 17 00:00:00 2001 From: Victor Wu Date: Fri, 4 Nov 2016 19:11:08 +0000 Subject: [PATCH 109/175] Correct spelling of Andreesen's name --- doc/university/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/university/README.md b/doc/university/README.md index 510b753f70d..49714e4fb59 100644 --- a/doc/university/README.md +++ b/doc/university/README.md @@ -200,7 +200,7 @@ The curriculum is composed of GitLab videos, screencasts, presentations, project ## 4. External Articles -1. [2011 WSJ article by Mark Andreeson - Software is Eating the World](http://www.wsj.com/articles/SB10001424053111903480904576512250915629460) +1. [2011 WSJ article by Marc Andreessen - Software is Eating the World](http://www.wsj.com/articles/SB10001424053111903480904576512250915629460) 1. [2014 Blog post by Chris Dixon - Software eats software development](http://cdixon.org/2014/04/13/software-eats-software-development/) 1. [2015 Venture Beat article - Actually, Open Source is Eating the World](http://venturebeat.com/2015/12/06/its-actually-open-source-software-thats-eating-the-world/) From d498ec98e0286efecd70040180c69c2002f9ed78 Mon Sep 17 00:00:00 2001 From: Drew Blessing Date: Fri, 4 Nov 2016 14:48:05 -0500 Subject: [PATCH 110/175] Set default Sidekiq retries to 3 By default, Sidekiq will retry 25 times with an exponential backoff. This may result in jobs retrying for up to 21 days. Most Sidekiq failures occur when attempting to connect to external services - Project service hooks, web hooks, mailers, mirror updates, etc. We should set a default retry of 3, and if that's not sufficient individual workers can override this in the worker class. --- changelogs/unreleased/sidekiq_default_retries.yml | 4 ++++ config/initializers/sidekiq.rb | 3 +++ 2 files changed, 7 insertions(+) create mode 100644 changelogs/unreleased/sidekiq_default_retries.yml diff --git a/changelogs/unreleased/sidekiq_default_retries.yml b/changelogs/unreleased/sidekiq_default_retries.yml new file mode 100644 index 00000000000..3df2a415dbc --- /dev/null +++ b/changelogs/unreleased/sidekiq_default_retries.yml @@ -0,0 +1,4 @@ +--- +title: Set default Sidekiq retries to 3 +merge_request: 7294 +author: diff --git a/config/initializers/sidekiq.rb b/config/initializers/sidekiq.rb index 0455a98dbfe..023af2af23c 100644 --- a/config/initializers/sidekiq.rb +++ b/config/initializers/sidekiq.rb @@ -2,6 +2,9 @@ redis_config_hash = Gitlab::Redis.params redis_config_hash[:namespace] = Gitlab::Redis::SIDEKIQ_NAMESPACE +# Default is to retry 25 times with exponential backoff. That's too much. +Sidekiq.default_worker_options = { retry: 3 } + Sidekiq.configure_server do |config| config.redis = redis_config_hash From 80a2e3a9c89a34df06eb2996fd5bdbaa6223f98c Mon Sep 17 00:00:00 2001 From: the-undefined Date: Wed, 2 Nov 2016 06:47:12 +0000 Subject: [PATCH 111/175] Add missing security specs for raw snippet access Each project visibility type (Public, Internal, Private) has an access feature spec to catch security regressions. This commit adds relevent tests for the raw snippet path in each of these project access specs. Refacotrings: - Use an empty project factory for access specs --- .../project/snippet/internal_access_spec.rb | 78 ++++++++---- .../project/snippet/private_access_spec.rb | 16 ++- .../project/snippet/public_access_spec.rb | 116 ++++++++++++------ 3 files changed, 151 insertions(+), 59 deletions(-) diff --git a/spec/features/security/project/snippet/internal_access_spec.rb b/spec/features/security/project/snippet/internal_access_spec.rb index db53a9cec97..49deacc5c74 100644 --- a/spec/features/security/project/snippet/internal_access_spec.rb +++ b/spec/features/security/project/snippet/internal_access_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe "Internal Project Snippets Access", feature: true do include AccessMatchers - let(:project) { create(:project, :internal) } + let(:project) { create(:empty_project, :internal) } let(:owner) { project.owner } let(:master) { create(:user) } @@ -48,31 +48,63 @@ describe "Internal Project Snippets Access", feature: true do it { is_expected.to be_denied_for :visitor } end - describe "GET /:project_path/snippets/:id for an internal snippet" do - subject { namespace_project_snippet_path(project.namespace, project, internal_snippet) } + describe "GET /:project_path/snippets/:id" do + context "for an internal snippet" do + subject { namespace_project_snippet_path(project.namespace, project, internal_snippet) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for owner } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for developer } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_denied_for :external } + it { is_expected.to be_denied_for :visitor } + end + + context "for a private snippet" do + subject { namespace_project_snippet_path(project.namespace, project, private_snippet) } + + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for owner } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for developer } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :external } + it { is_expected.to be_denied_for :visitor } + end end - describe "GET /:project_path/snippets/:id for a private snippet" do - subject { namespace_project_snippet_path(project.namespace, project, private_snippet) } + describe "GET /:project_path/snippets/:id/raw" do + context "for an internal snippet" do + subject { raw_namespace_project_snippet_path(project.namespace, project, internal_snippet) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for owner } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for developer } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_denied_for :external } + it { is_expected.to be_denied_for :visitor } + end + + context "for a private snippet" do + subject { raw_namespace_project_snippet_path(project.namespace, project, private_snippet) } + + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for owner } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for developer } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :external } + it { is_expected.to be_denied_for :visitor } + end end end diff --git a/spec/features/security/project/snippet/private_access_spec.rb b/spec/features/security/project/snippet/private_access_spec.rb index d23d645c8e5..a1bfc076d99 100644 --- a/spec/features/security/project/snippet/private_access_spec.rb +++ b/spec/features/security/project/snippet/private_access_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe "Private Project Snippets Access", feature: true do include AccessMatchers - let(:project) { create(:project, :private) } + let(:project) { create(:empty_project, :private) } let(:owner) { project.owner } let(:master) { create(:user) } @@ -60,4 +60,18 @@ describe "Private Project Snippets Access", feature: true do it { is_expected.to be_denied_for :external } it { is_expected.to be_denied_for :visitor } end + + describe "GET /:project_path/snippets/:id/raw for a private snippet" do + subject { raw_namespace_project_snippet_path(project.namespace, project, private_snippet) } + + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for owner } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for developer } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :external } + it { is_expected.to be_denied_for :visitor } + end end diff --git a/spec/features/security/project/snippet/public_access_spec.rb b/spec/features/security/project/snippet/public_access_spec.rb index e3665b6116a..30bcd87ef04 100644 --- a/spec/features/security/project/snippet/public_access_spec.rb +++ b/spec/features/security/project/snippet/public_access_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe "Public Project Snippets Access", feature: true do include AccessMatchers - let(:project) { create(:project, :public) } + let(:project) { create(:empty_project, :public) } let(:owner) { project.owner } let(:master) { create(:user) } @@ -49,45 +49,91 @@ describe "Public Project Snippets Access", feature: true do it { is_expected.to be_denied_for :visitor } end - describe "GET /:project_path/snippets/:id for a public snippet" do - subject { namespace_project_snippet_path(project.namespace, project, public_snippet) } + describe "GET /:project_path/snippets/:id" do + context "for a public snippet" do + subject { namespace_project_snippet_path(project.namespace, project, public_snippet) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_allowed_for :external } - it { is_expected.to be_allowed_for :visitor } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for owner } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for developer } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_allowed_for :external } + it { is_expected.to be_allowed_for :visitor } + end + + context "for an internal snippet" do + subject { namespace_project_snippet_path(project.namespace, project, internal_snippet) } + + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for owner } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for developer } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_denied_for :external } + it { is_expected.to be_denied_for :visitor } + end + + context "for a private snippet" do + subject { namespace_project_snippet_path(project.namespace, project, private_snippet) } + + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for owner } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for developer } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :external } + it { is_expected.to be_denied_for :visitor } + end end - describe "GET /:project_path/snippets/:id for an internal snippet" do - subject { namespace_project_snippet_path(project.namespace, project, internal_snippet) } + describe "GET /:project_path/snippets/:id/raw" do + context "for a public snippet" do + subject { raw_namespace_project_snippet_path(project.namespace, project, public_snippet) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } - end + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for owner } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for developer } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_allowed_for :external } + it { is_expected.to be_allowed_for :visitor } + end - describe "GET /:project_path/snippets/:id for a private snippet" do - subject { namespace_project_snippet_path(project.namespace, project, private_snippet) } + context "for an internal snippet" do + subject { raw_namespace_project_snippet_path(project.namespace, project, internal_snippet) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for owner } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for developer } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_denied_for :external } + it { is_expected.to be_denied_for :visitor } + end + + context "for a private snippet" do + subject { raw_namespace_project_snippet_path(project.namespace, project, private_snippet) } + + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for owner } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for developer } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :external } + it { is_expected.to be_denied_for :visitor } + end end end From c16d5bcd48bb03f0eb145da4be9460cca87d1f91 Mon Sep 17 00:00:00 2001 From: winniehell Date: Sat, 5 Nov 2016 11:53:23 +0100 Subject: [PATCH 112/175] Move Ajax interceptor into describe block (!7304) --- .../boards/boards_store_spec.js.es6 | 261 +++++++++--------- spec/javascripts/boards/list_spec.js.es6 | 5 + spec/javascripts/boards/mock_data.js.es6 | 4 +- 3 files changed, 139 insertions(+), 131 deletions(-) diff --git a/spec/javascripts/boards/boards_store_spec.js.es6 b/spec/javascripts/boards/boards_store_spec.js.es6 index 6208c2386b0..b84dfc8197b 100644 --- a/spec/javascripts/boards/boards_store_spec.js.es6 +++ b/spec/javascripts/boards/boards_store_spec.js.es6 @@ -13,8 +13,9 @@ //= require boards/stores/boards_store //= require ./mock_data -(() => { +describe('Store', () => { beforeEach(() => { + Vue.http.interceptors.push(boardsMockInterceptor); gl.boardService = new BoardService('/test/issue-boards/board', '1'); gl.issueBoards.BoardsStore.create(); @@ -24,145 +25,147 @@ }); }); - describe('Store', () => { - it('starts with a blank state', () => { + afterEach(() => { + Vue.http.interceptors = _.without(Vue.http.interceptors, boardsMockInterceptor); + }); + + it('starts with a blank state', () => { + expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(0); + }); + + describe('lists', () => { + it('creates new list without persisting to DB', () => { + gl.issueBoards.BoardsStore.addList(listObj); + + expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(1); + }); + + it('finds list by ID', () => { + gl.issueBoards.BoardsStore.addList(listObj); + const list = gl.issueBoards.BoardsStore.findList('id', 1); + + expect(list.id).toBe(1); + }); + + it('finds list by type', () => { + gl.issueBoards.BoardsStore.addList(listObj); + const list = gl.issueBoards.BoardsStore.findList('type', 'label'); + + expect(list).toBeDefined(); + }); + + it('finds list limited by type', () => { + gl.issueBoards.BoardsStore.addList({ + id: 1, + position: 0, + title: 'Test', + list_type: 'backlog' + }); + const list = gl.issueBoards.BoardsStore.findList('id', 1, 'backlog'); + + expect(list).toBeDefined(); + }); + + it('gets issue when new list added', (done) => { + gl.issueBoards.BoardsStore.addList(listObj); + const list = gl.issueBoards.BoardsStore.findList('id', 1); + + expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(1); + + setTimeout(() => { + expect(list.issues.length).toBe(1); + expect(list.issues[0].id).toBe(1); + done(); + }, 0); + }); + + it('persists new list', (done) => { + gl.issueBoards.BoardsStore.new({ + title: 'Test', + type: 'label', + label: { + id: 1, + title: 'Testing', + color: 'red', + description: 'testing;' + } + }); + expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(1); + + setTimeout(() => { + const list = gl.issueBoards.BoardsStore.findList('id', 1); + expect(list).toBeDefined(); + expect(list.id).toBe(1); + expect(list.position).toBe(0); + done(); + }, 0); + }); + + it('check for blank state adding', () => { + expect(gl.issueBoards.BoardsStore.shouldAddBlankState()).toBe(true); + }); + + it('check for blank state not adding', () => { + gl.issueBoards.BoardsStore.addList(listObj); + expect(gl.issueBoards.BoardsStore.shouldAddBlankState()).toBe(false); + }); + + it('check for blank state adding when backlog & done list exist', () => { + gl.issueBoards.BoardsStore.addList({ + list_type: 'backlog' + }); + gl.issueBoards.BoardsStore.addList({ + list_type: 'done' + }); + + expect(gl.issueBoards.BoardsStore.shouldAddBlankState()).toBe(true); + }); + + it('adds the blank state', () => { + gl.issueBoards.BoardsStore.addBlankState(); + + const list = gl.issueBoards.BoardsStore.findList('type', 'blank', 'blank'); + expect(list).toBeDefined(); + }); + + it('removes list from state', () => { + gl.issueBoards.BoardsStore.addList(listObj); + + expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(1); + + gl.issueBoards.BoardsStore.removeList(1, 'label'); + expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(0); }); - describe('lists', () => { - it('creates new list without persisting to DB', () => { - gl.issueBoards.BoardsStore.addList(listObj); + it('moves the position of lists', () => { + const listOne = gl.issueBoards.BoardsStore.addList(listObj), + listTwo = gl.issueBoards.BoardsStore.addList(listObjDuplicate); - expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(1); - }); + expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(2); - it('finds list by ID', () => { - gl.issueBoards.BoardsStore.addList(listObj); - const list = gl.issueBoards.BoardsStore.findList('id', 1); + gl.issueBoards.BoardsStore.moveList(listOne, ['2', '1']); - expect(list.id).toBe(1); - }); + expect(listOne.position).toBe(1); + }); - it('finds list by type', () => { - gl.issueBoards.BoardsStore.addList(listObj); - const list = gl.issueBoards.BoardsStore.findList('type', 'label'); + it('moves an issue from one list to another', (done) => { + const listOne = gl.issueBoards.BoardsStore.addList(listObj), + listTwo = gl.issueBoards.BoardsStore.addList(listObjDuplicate); - expect(list).toBeDefined(); - }); + expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(2); - it('finds list limited by type', () => { - gl.issueBoards.BoardsStore.addList({ - id: 1, - position: 0, - title: 'Test', - list_type: 'backlog' - }); - const list = gl.issueBoards.BoardsStore.findList('id', 1, 'backlog'); + setTimeout(() => { + expect(listOne.issues.length).toBe(1); + expect(listTwo.issues.length).toBe(1); - expect(list).toBeDefined(); - }); + gl.issueBoards.BoardsStore.moveIssueToList(listOne, listTwo, listOne.findIssue(1)); - it('gets issue when new list added', (done) => { - gl.issueBoards.BoardsStore.addList(listObj); - const list = gl.issueBoards.BoardsStore.findList('id', 1); + expect(listOne.issues.length).toBe(0); + expect(listTwo.issues.length).toBe(1); - expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(1); - - setTimeout(() => { - expect(list.issues.length).toBe(1); - expect(list.issues[0].id).toBe(1); - done(); - }, 0); - }); - - it('persists new list', (done) => { - gl.issueBoards.BoardsStore.new({ - title: 'Test', - type: 'label', - label: { - id: 1, - title: 'Testing', - color: 'red', - description: 'testing;' - } - }); - expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(1); - - setTimeout(() => { - const list = gl.issueBoards.BoardsStore.findList('id', 1); - expect(list).toBeDefined(); - expect(list.id).toBe(1); - expect(list.position).toBe(0); - done(); - }, 0); - }); - - it('check for blank state adding', () => { - expect(gl.issueBoards.BoardsStore.shouldAddBlankState()).toBe(true); - }); - - it('check for blank state not adding', () => { - gl.issueBoards.BoardsStore.addList(listObj); - expect(gl.issueBoards.BoardsStore.shouldAddBlankState()).toBe(false); - }); - - it('check for blank state adding when backlog & done list exist', () => { - gl.issueBoards.BoardsStore.addList({ - list_type: 'backlog' - }); - gl.issueBoards.BoardsStore.addList({ - list_type: 'done' - }); - - expect(gl.issueBoards.BoardsStore.shouldAddBlankState()).toBe(true); - }); - - it('adds the blank state', () => { - gl.issueBoards.BoardsStore.addBlankState(); - - const list = gl.issueBoards.BoardsStore.findList('type', 'blank', 'blank'); - expect(list).toBeDefined(); - }); - - it('removes list from state', () => { - gl.issueBoards.BoardsStore.addList(listObj); - - expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(1); - - gl.issueBoards.BoardsStore.removeList(1, 'label'); - - expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(0); - }); - - it('moves the position of lists', () => { - const listOne = gl.issueBoards.BoardsStore.addList(listObj), - listTwo = gl.issueBoards.BoardsStore.addList(listObjDuplicate); - - expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(2); - - gl.issueBoards.BoardsStore.moveList(listOne, ['2', '1']); - - expect(listOne.position).toBe(1); - }); - - it('moves an issue from one list to another', (done) => { - const listOne = gl.issueBoards.BoardsStore.addList(listObj), - listTwo = gl.issueBoards.BoardsStore.addList(listObjDuplicate); - - expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(2); - - setTimeout(() => { - expect(listOne.issues.length).toBe(1); - expect(listTwo.issues.length).toBe(1); - - gl.issueBoards.BoardsStore.moveIssueToList(listOne, listTwo, listOne.findIssue(1)); - - expect(listOne.issues.length).toBe(0); - expect(listTwo.issues.length).toBe(1); - - done(); - }, 0); - }); + done(); + }, 0); }); }); -})(); +}); diff --git a/spec/javascripts/boards/list_spec.js.es6 b/spec/javascripts/boards/list_spec.js.es6 index 1a0427fdd90..dfbcbe3a7c1 100644 --- a/spec/javascripts/boards/list_spec.js.es6 +++ b/spec/javascripts/boards/list_spec.js.es6 @@ -17,12 +17,17 @@ describe('List model', () => { let list; beforeEach(() => { + Vue.http.interceptors.push(boardsMockInterceptor); gl.boardService = new BoardService('/test/issue-boards/board', '1'); gl.issueBoards.BoardsStore.create(); list = new List(listObj); }); + afterEach(() => { + Vue.http.interceptors = _.without(Vue.http.interceptors, boardsMockInterceptor); + }); + it('gets issues when created', (done) => { setTimeout(() => { expect(list.issues.length).toBe(1); diff --git a/spec/javascripts/boards/mock_data.js.es6 b/spec/javascripts/boards/mock_data.js.es6 index 80d05e8a1a3..fcb3d8f17d8 100644 --- a/spec/javascripts/boards/mock_data.js.es6 +++ b/spec/javascripts/boards/mock_data.js.es6 @@ -48,10 +48,10 @@ const BoardsMockData = { } }; -Vue.http.interceptors.push((request, next) => { +const boardsMockInterceptor = (request, next) => { const body = BoardsMockData[request.method][request.url]; next(request.respondWith(JSON.stringify(body), { status: 200 })); -}); +}; From a09079219fcb2cd7dc7e343446ea499792344df6 Mon Sep 17 00:00:00 2001 From: winniehell Date: Sat, 5 Nov 2016 12:41:36 +0100 Subject: [PATCH 113/175] Remove logging to console in diff_comments_store_spec --- spec/javascripts/diff_comments_store_spec.js.es6 | 1 - 1 file changed, 1 deletion(-) diff --git a/spec/javascripts/diff_comments_store_spec.js.es6 b/spec/javascripts/diff_comments_store_spec.js.es6 index 5d817802602..9b2845af608 100644 --- a/spec/javascripts/diff_comments_store_spec.js.es6 +++ b/spec/javascripts/diff_comments_store_spec.js.es6 @@ -92,7 +92,6 @@ it('is unresolved with 2 notes', () => { const discussion = CommentsStore.state['a']; createDiscussion(2, false); - console.log(discussion.isResolved()); expect(discussion.isResolved()).toBe(false); }); From 56264f35d40e3ebcebf2b88b9ff6f3a8f4f545e9 Mon Sep 17 00:00:00 2001 From: Hiroyuki Sato Date: Fri, 28 Oct 2016 20:38:14 +0900 Subject: [PATCH 114/175] Network page appear with an error message when entering nonexistent git revision --- app/assets/javascripts/network/network_bundle.js | 2 ++ app/controllers/projects/network_controller.rb | 4 +++- app/views/projects/network/show.html.haml | 5 +++-- lib/extracts_path.rb | 4 ++-- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/app/assets/javascripts/network/network_bundle.js b/app/assets/javascripts/network/network_bundle.js index 42d6799c82f..a192273a180 100644 --- a/app/assets/javascripts/network/network_bundle.js +++ b/app/assets/javascripts/network/network_bundle.js @@ -9,6 +9,8 @@ (function() { $(function() { + if (!$(".network-graph").length) return; + var network_graph; network_graph = new Network({ url: $(".network-graph").attr('data-url'), diff --git a/app/controllers/projects/network_controller.rb b/app/controllers/projects/network_controller.rb index 34318391dd9..54783bbc5bb 100644 --- a/app/controllers/projects/network_controller.rb +++ b/app/controllers/projects/network_controller.rb @@ -11,7 +11,9 @@ class Projects::NetworkController < Projects::ApplicationController @commit_url = namespace_project_commit_path(@project.namespace, @project, 'ae45ca32').gsub("ae45ca32", "%s") respond_to do |format| - format.html + format.html do + flash.now[:alert] = "Git revision '#{params[:extended_sha1]}' does not exist." if params[:extended_sha1].present? && !@commit + end format.json do @graph = Network::Graph.new(project, @ref, @commit, @options[:filter_ref]) diff --git a/app/views/projects/network/show.html.haml b/app/views/projects/network/show.html.haml index 29df1bab04e..d8951e69242 100644 --- a/app/views/projects/network/show.html.haml +++ b/app/views/projects/network/show.html.haml @@ -17,5 +17,6 @@ = check_box_tag :filter_ref, 1, @options[:filter_ref] %span Begin with the selected commit - .network-graph{ data: { url: @url, commit_url: @commit_url, ref: @ref, commit_id: @commit.id } } - = spinner nil, true + - if @commit + .network-graph{ data: { url: @url, commit_url: @commit_url, ref: @ref, commit_id: @commit.id } } + = spinner nil, true diff --git a/lib/extracts_path.rb b/lib/extracts_path.rb index 9b74364849e..a8cc189a8c2 100644 --- a/lib/extracts_path.rb +++ b/lib/extracts_path.rb @@ -125,9 +125,9 @@ module ExtractsPath request.format = :atom if @commit end - end - raise InvalidPathError unless @commit + raise InvalidPathError unless @commit + end @hex_path = Digest::SHA1.hexdigest(@path) @logs_path = logs_file_namespace_project_ref_path(@project.namespace, From ee7374a9fb16ca65603ef095de2856694612d68f Mon Sep 17 00:00:00 2001 From: Hiroyuki Sato Date: Fri, 28 Oct 2016 21:48:40 +0900 Subject: [PATCH 115/175] Separete a very long line --- app/controllers/projects/network_controller.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/controllers/projects/network_controller.rb b/app/controllers/projects/network_controller.rb index 54783bbc5bb..3dbc7a492b5 100644 --- a/app/controllers/projects/network_controller.rb +++ b/app/controllers/projects/network_controller.rb @@ -12,7 +12,9 @@ class Projects::NetworkController < Projects::ApplicationController respond_to do |format| format.html do - flash.now[:alert] = "Git revision '#{params[:extended_sha1]}' does not exist." if params[:extended_sha1].present? && !@commit + if params[:extended_sha1].present? && !@commit + flash.now[:alert] = "Git revision '#{params[:extended_sha1]}' does not exist." + end end format.json do From b5bb98100a58a39a4982c28d868c195ead19a69e Mon Sep 17 00:00:00 2001 From: Hiroyuki Sato Date: Fri, 28 Oct 2016 21:54:55 +0900 Subject: [PATCH 116/175] Add a CHANGELOG entry --- CHANGELOG.md | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ed09fb1db8..f1826e23c89 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -97,6 +97,40 @@ entry. - Fix and improve `Sortable.highest_label_priority`. !7165 - Fixed sticky merge request tabs when sidebar is pinned. !7167 - Only remove right connector of first build of last stage. !7179 + - Backups do not fail anymore when using tar on annex and custom_hooks only. !5814 + - Adds user project membership expired event to clarify why user was removed (Callum Dryden) + - Trim leading and trailing whitespace on project_path (Linus Thiel) + - Prevent award emoji via notes for issues/MRs authored by user (barthc) + - Adds an optional path parameter to the Commits API to filter commits by path (Luis HGO) + - Fix extra space on Build sidebar on Firefox !7060 + - Fix mobile layout issues in admin user overview page !7087 + - Fix HipChat notifications rendering (airatshigapov, eisnerd) + - Add hover to trash icon in notes !7008 (blackst0ne) + - Fix sidekiq stats in admin area (blackst0ne) + - Removed delete branch tooltip !6954 + - Escape ref and path for relative links !6050 (winniehell) + - Fixed link typo on /help/ui to Alerts section. !6915 (Sam Rose) + - Fix filtering of milestones with quotes in title (airatshigapov) + - Refactor less readable existance checking code from CoffeeScript !6289 (jlogandavison) + - Update mail_room and enable sentinel support to Reply By Email (!7101) + - Simpler arguments passed to named_route on toggle_award_url helper method + - Fix typo in framework css class. !7086 (Daniel Voogsgerd) + - New issue board list dropdown stays open after adding a new list + - Fix: Backup restore doesn't clear cache + - API: Fix project deploy keys 400 and 500 errors when adding an existing key. !6784 (Joshua Welsh) + - Replace jquery.cookie plugin with js.cookie !7085 + - Use MergeRequestsClosingIssues cache data on Issue#closed_by_merge_requests method + - Fix Sign in page 'Forgot your password?' link overlaps on medium-large screens + - Show full status link on MR & commit pipelines + - Fix documents and comments on Build API `scope` + - Fix applying labels for GitHub-imported MRs + - Fix importing MR comments from GitHub + - Refactor email, use setter method instead AR callbacks for email attribute (Semyon Pupkov) + - Fix 404 on network page when entering non-existent git revision !7172 (Hiroyuki Sato) + - Shortened merge request modal to let clipboard button not overlap + +## 8.13.2 + - Fix builds dropdown overlapping bug !7124 ## 8.13.1 (2016-10-25) From 8d0e84bcf49ccb136557302313bac0833b7d91e5 Mon Sep 17 00:00:00 2001 From: Hiroyuki Sato Date: Sat, 29 Oct 2016 00:47:15 +0900 Subject: [PATCH 117/175] Fix spinach test --- features/project/network_graph.feature | 2 +- features/steps/project/network_graph.rb | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/features/project/network_graph.feature b/features/project/network_graph.feature index 89a02706bd2..93c884e23c5 100644 --- a/features/project/network_graph.feature +++ b/features/project/network_graph.feature @@ -43,4 +43,4 @@ Feature: Project Network Graph Scenario: I should fail to look for a commit When I look for a commit by ";" - Then page status code should be 404 + Then I should see non-existent git revision error message diff --git a/features/steps/project/network_graph.rb b/features/steps/project/network_graph.rb index 019b3124a86..ff9251615c9 100644 --- a/features/steps/project/network_graph.rb +++ b/features/steps/project/network_graph.rb @@ -109,4 +109,8 @@ class Spinach::Features::ProjectNetworkGraph < Spinach::FeatureSteps find('button').click end end + + step 'I should see non-existent git revision error message' do + expect(page).to have_selector '.flash-alert', text: "Git revision ';' does not exist." + end end From d02f7d29c07632f219e103ba256636f49329067c Mon Sep 17 00:00:00 2001 From: Hiroyuki Sato Date: Sun, 6 Nov 2016 12:07:04 +0900 Subject: [PATCH 118/175] Update changelog --- CHANGELOG.md | 34 ------------------- ...en-entering-a-nonexistent-git-revision.yml | 4 +++ 2 files changed, 4 insertions(+), 34 deletions(-) create mode 100644 changelogs/unreleased/fix-404-on-network-when-entering-a-nonexistent-git-revision.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index f1826e23c89..7ed09fb1db8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -97,40 +97,6 @@ entry. - Fix and improve `Sortable.highest_label_priority`. !7165 - Fixed sticky merge request tabs when sidebar is pinned. !7167 - Only remove right connector of first build of last stage. !7179 - - Backups do not fail anymore when using tar on annex and custom_hooks only. !5814 - - Adds user project membership expired event to clarify why user was removed (Callum Dryden) - - Trim leading and trailing whitespace on project_path (Linus Thiel) - - Prevent award emoji via notes for issues/MRs authored by user (barthc) - - Adds an optional path parameter to the Commits API to filter commits by path (Luis HGO) - - Fix extra space on Build sidebar on Firefox !7060 - - Fix mobile layout issues in admin user overview page !7087 - - Fix HipChat notifications rendering (airatshigapov, eisnerd) - - Add hover to trash icon in notes !7008 (blackst0ne) - - Fix sidekiq stats in admin area (blackst0ne) - - Removed delete branch tooltip !6954 - - Escape ref and path for relative links !6050 (winniehell) - - Fixed link typo on /help/ui to Alerts section. !6915 (Sam Rose) - - Fix filtering of milestones with quotes in title (airatshigapov) - - Refactor less readable existance checking code from CoffeeScript !6289 (jlogandavison) - - Update mail_room and enable sentinel support to Reply By Email (!7101) - - Simpler arguments passed to named_route on toggle_award_url helper method - - Fix typo in framework css class. !7086 (Daniel Voogsgerd) - - New issue board list dropdown stays open after adding a new list - - Fix: Backup restore doesn't clear cache - - API: Fix project deploy keys 400 and 500 errors when adding an existing key. !6784 (Joshua Welsh) - - Replace jquery.cookie plugin with js.cookie !7085 - - Use MergeRequestsClosingIssues cache data on Issue#closed_by_merge_requests method - - Fix Sign in page 'Forgot your password?' link overlaps on medium-large screens - - Show full status link on MR & commit pipelines - - Fix documents and comments on Build API `scope` - - Fix applying labels for GitHub-imported MRs - - Fix importing MR comments from GitHub - - Refactor email, use setter method instead AR callbacks for email attribute (Semyon Pupkov) - - Fix 404 on network page when entering non-existent git revision !7172 (Hiroyuki Sato) - - Shortened merge request modal to let clipboard button not overlap - -## 8.13.2 - - Fix builds dropdown overlapping bug !7124 ## 8.13.1 (2016-10-25) diff --git a/changelogs/unreleased/fix-404-on-network-when-entering-a-nonexistent-git-revision.yml b/changelogs/unreleased/fix-404-on-network-when-entering-a-nonexistent-git-revision.yml new file mode 100644 index 00000000000..d1bc8ea2eb1 --- /dev/null +++ b/changelogs/unreleased/fix-404-on-network-when-entering-a-nonexistent-git-revision.yml @@ -0,0 +1,4 @@ +--- +title: Fix 404 on network page when entering non-existent git revision +merge_request: 7172 +author: Hiroyuki Sato From d8cc8d7adc4c50843ecacc77a30b2e6db4e3fd84 Mon Sep 17 00:00:00 2001 From: Hiroyuki Sato Date: Sun, 6 Nov 2016 12:33:39 +0900 Subject: [PATCH 119/175] Remove 'extended_sha1' option from ExtractsPath module --- .../projects/network_controller.rb | 1 + app/views/projects/network/show.html.haml | 2 +- lib/extracts_path.rb | 20 ++++++++----------- 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/app/controllers/projects/network_controller.rb b/app/controllers/projects/network_controller.rb index 3dbc7a492b5..e29e5994c4b 100644 --- a/app/controllers/projects/network_controller.rb +++ b/app/controllers/projects/network_controller.rb @@ -9,6 +9,7 @@ class Projects::NetworkController < Projects::ApplicationController def show @url = namespace_project_network_path(@project.namespace, @project, @ref, @options.merge(format: :json)) @commit_url = namespace_project_commit_path(@project.namespace, @project, 'ae45ca32').gsub("ae45ca32", "%s") + @commit = @repo.commit(params[:extended_sha1]) if params[:extended_sha1].present? respond_to do |format| format.html do diff --git a/app/views/projects/network/show.html.haml b/app/views/projects/network/show.html.haml index d8951e69242..af565873444 100644 --- a/app/views/projects/network/show.html.haml +++ b/app/views/projects/network/show.html.haml @@ -8,7 +8,7 @@ .project-network .controls = form_tag namespace_project_network_path(@project.namespace, @project, @id), method: :get, class: 'form-inline network-form' do |f| - = text_field_tag :extended_sha1, @options[:extended_sha1], placeholder: "Git revision", class: 'search-input form-control input-mx-250 search-sha' + = text_field_tag :extended_sha1, params[:extended_sha1], placeholder: "Git revision", class: 'search-input form-control input-mx-250 search-sha' = button_tag class: 'btn btn-success' do = icon('search') .inline.prepend-left-20 diff --git a/lib/extracts_path.rb b/lib/extracts_path.rb index a8cc189a8c2..82551f1f222 100644 --- a/lib/extracts_path.rb +++ b/lib/extracts_path.rb @@ -106,7 +106,7 @@ module ExtractsPath # resolved (e.g., when a user inserts an invalid path or ref). def assign_ref_vars # assign allowed options - allowed_options = ["filter_ref", "extended_sha1"] + allowed_options = ["filter_ref"] @options = params.select {|key, value| allowed_options.include?(key) && !value.blank? } @options = HashWithIndifferentAccess.new(@options) @@ -114,21 +114,17 @@ module ExtractsPath @ref, @path = extract_ref(@id) @repo = @project.repository - if @options[:extended_sha1].present? - @commit = @repo.commit(@options[:extended_sha1]) - else + @commit = @repo.commit(@ref) + + if @path.empty? && !@commit && @id.ends_with?('.atom') + @id = @ref = extract_ref_without_atom(@id) @commit = @repo.commit(@ref) - if @path.empty? && !@commit && @id.ends_with?('.atom') - @id = @ref = extract_ref_without_atom(@id) - @commit = @repo.commit(@ref) - - request.format = :atom if @commit - end - - raise InvalidPathError unless @commit + request.format = :atom if @commit end + raise InvalidPathError unless @commit + @hex_path = Digest::SHA1.hexdigest(@path) @logs_path = logs_file_namespace_project_ref_path(@project.namespace, @project, @ref, @path) From 4896ffe5f9f4ce1f5b32f9dd0c27189aefad2a42 Mon Sep 17 00:00:00 2001 From: Yann Gravrand Date: Wed, 26 Oct 2016 23:02:36 +0200 Subject: [PATCH 120/175] Fixes #22058 and #23578 --- CHANGELOG.md | 1 + app/assets/javascripts/gfm_auto_complete.js.es6 | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ed09fb1db8..ca35572b0c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ entry. - Trim leading and trailing whitespace on project_path (Linus Thiel) - Prevent award emoji via notes for issues/MRs authored by user (barthc) - Adds support for the `token` attribute in project hooks API (Gauvain Pocentek) +- Change auto selection behaviour of emoji and slash commands to be more UX/Type friendly (Yann Gravrand) - Adds an optional path parameter to the Commits API to filter commits by path (Luis HGO) - Fix Markdown styling inside reference links (Jan Zdráhal) - Create new issue board list after creating a new label diff --git a/app/assets/javascripts/gfm_auto_complete.js.es6 b/app/assets/javascripts/gfm_auto_complete.js.es6 index 824413bf20f..e72e2194be8 100644 --- a/app/assets/javascripts/gfm_auto_complete.js.es6 +++ b/app/assets/javascripts/gfm_auto_complete.js.es6 @@ -34,6 +34,8 @@ }, DefaultOptions: { sorter: function(query, items, searchKey) { + // Highlight first item only if at least one char was typed + this.setting.highlightFirst = query.length > 0; if ((items[0].name != null) && items[0].name === 'loading') { return items; } @@ -182,6 +184,7 @@ insertTpl: '${atwho-at}"${title}"', data: ['loading'], callbacks: { + sorter: this.DefaultOptions.sorter, beforeSave: function(milestones) { return $.map(milestones, function(m) { if (m.title == null) { @@ -236,6 +239,7 @@ displayTpl: this.Labels.template, insertTpl: '${atwho-at}${title}', callbacks: { + sorter: this.DefaultOptions.sorter, beforeSave: function(merges) { var sanitizeLabelTitle; sanitizeLabelTitle = function(title) { From 2b4700b2bee77ef03db53aa06579fd73b242bbe7 Mon Sep 17 00:00:00 2001 From: bogdanvlviv Date: Sun, 6 Nov 2016 21:27:51 +0200 Subject: [PATCH 121/175] Use method helper instead of add_template_helper --- app/mailers/base_mailer.rb | 4 ++-- app/mailers/notify.rb | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/app/mailers/base_mailer.rb b/app/mailers/base_mailer.rb index 61a574d3dc0..79c3c2e62c5 100644 --- a/app/mailers/base_mailer.rb +++ b/app/mailers/base_mailer.rb @@ -1,6 +1,6 @@ class BaseMailer < ActionMailer::Base - add_template_helper ApplicationHelper - add_template_helper GitlabMarkdownHelper + helper ApplicationHelper + helper GitlabMarkdownHelper attr_accessor :current_user helper_method :current_user, :can? diff --git a/app/mailers/notify.rb b/app/mailers/notify.rb index eca6ec29767..0bc1c19e9cd 100644 --- a/app/mailers/notify.rb +++ b/app/mailers/notify.rb @@ -10,12 +10,12 @@ class Notify < BaseMailer include Emails::Pipelines include Emails::Members - add_template_helper MergeRequestsHelper - add_template_helper DiffHelper - add_template_helper BlobHelper - add_template_helper EmailsHelper - add_template_helper MembersHelper - add_template_helper GitlabRoutingHelper + helper MergeRequestsHelper + helper DiffHelper + helper BlobHelper + helper EmailsHelper + helper MembersHelper + helper GitlabRoutingHelper def test_email(recipient_email, subject, body) mail(to: recipient_email, From a8f2fceadd60db759522c5669b99e68029df912e Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sun, 6 Nov 2016 13:54:54 -0800 Subject: [PATCH 122/175] Add an index for project_id in project_import_data to improve performance We see that many slow queries on GitLab.com are dominated by finding the project import data for a specific project. Adding an index is the most straightforward way of fixing this. Closes #23748 --- .../unreleased/add-project-import-data-index.yml | 4 ++++ ...06185620_add_project_import_data_project_index.rb | 12 ++++++++++++ db/schema.rb | 4 +++- 3 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 changelogs/unreleased/add-project-import-data-index.yml create mode 100644 db/migrate/20161106185620_add_project_import_data_project_index.rb diff --git a/changelogs/unreleased/add-project-import-data-index.yml b/changelogs/unreleased/add-project-import-data-index.yml new file mode 100644 index 00000000000..f5e4005f544 --- /dev/null +++ b/changelogs/unreleased/add-project-import-data-index.yml @@ -0,0 +1,4 @@ +--- +title: Add an index for project_id in project_import_data to improve performance +merge_request: +author: diff --git a/db/migrate/20161106185620_add_project_import_data_project_index.rb b/db/migrate/20161106185620_add_project_import_data_project_index.rb new file mode 100644 index 00000000000..750a6a8c51e --- /dev/null +++ b/db/migrate/20161106185620_add_project_import_data_project_index.rb @@ -0,0 +1,12 @@ +class AddProjectImportDataProjectIndex < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + # Set this constant to true if this migration requires downtime. + DOWNTIME = false + + disable_ddl_transaction! + + def change + add_concurrent_index :project_import_data, :project_id + end +end diff --git a/db/schema.rb b/db/schema.rb index 5476b0c93e5..212b0ed1c58 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20161103171205) do +ActiveRecord::Schema.define(version: 20161106185620) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -867,6 +867,8 @@ ActiveRecord::Schema.define(version: 20161103171205) do t.string "encrypted_credentials_salt" end + add_index "project_import_data", ["project_id"], name: "index_project_import_data_on_project_id", using: :btree + create_table "projects", force: :cascade do |t| t.string "name" t.string "path" From 0c36b810abede73b3cf59f951e7467dbac54ec98 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Sun, 6 Nov 2016 13:26:44 -0500 Subject: [PATCH 123/175] Fix broken link to observatory cli on Frontend Dev Guide --- changelogs/unreleased/broken-link-frontend-dev-guide.yml | 4 ++++ doc/development/frontend.md | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 changelogs/unreleased/broken-link-frontend-dev-guide.yml diff --git a/changelogs/unreleased/broken-link-frontend-dev-guide.yml b/changelogs/unreleased/broken-link-frontend-dev-guide.yml new file mode 100644 index 00000000000..d7b6f4a7701 --- /dev/null +++ b/changelogs/unreleased/broken-link-frontend-dev-guide.yml @@ -0,0 +1,4 @@ +--- +title: Fix broken link to observatory cli on Frontend Dev Guide +merge_request: +author: Sam Rose diff --git a/doc/development/frontend.md b/doc/development/frontend.md index 1d7d9127a64..ec8f2d6531c 100644 --- a/doc/development/frontend.md +++ b/doc/development/frontend.md @@ -228,7 +228,7 @@ For our currently-supported browsers, see our [requirements][requirements]. [page-specific-js-example]: https://gitlab.com/gitlab-org/gitlab-ce/blob/13bb9ed77f405c5f6ee4fdbc964ecf635c9a223f/app/views/projects/graphs/_head.html.haml#L6-8 [chrome-accessibility-developer-tools]: https://github.com/GoogleChrome/accessibility-developer-tools [audit-rules]: https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules -[observatory-cli]: https://github.com/mozilla/http-observatory-cli) +[observatory-cli]: https://github.com/mozilla/http-observatory-cli [qualys-ssl]: https://www.ssllabs.com/ssltest/analyze.html [secure_headers]: https://github.com/twitter/secureheaders [mdn-csp]: https://developer.mozilla.org/en-US/docs/Web/Security/CSP From 76c237460a801050e68def5ff54c15e4e74b38a8 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Thu, 29 Sep 2016 16:33:38 +0200 Subject: [PATCH 124/175] Ability to update labels priority via API --- .../unreleased/api-label-priorities.yml | 4 + lib/api/entities.rb | 3 + lib/api/labels.rb | 41 ++++++--- spec/requests/api/labels_spec.rb | 88 +++++++++++++++++-- 4 files changed, 117 insertions(+), 19 deletions(-) create mode 100644 changelogs/unreleased/api-label-priorities.yml diff --git a/changelogs/unreleased/api-label-priorities.yml b/changelogs/unreleased/api-label-priorities.yml new file mode 100644 index 00000000000..85b6c2761bb --- /dev/null +++ b/changelogs/unreleased/api-label-priorities.yml @@ -0,0 +1,4 @@ +--- +title: API: Ability to retrieve version information +merge_request: 7286 +author: Robert Schilling diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 01e31f6f7d1..9dd36ec969e 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -438,6 +438,9 @@ module API class Label < LabelBasic expose :open_issues_count, :closed_issues_count, :open_merge_requests_count + expose :priority do |label, options| + label.priority(options[:project]) + end expose :subscribed do |label, options| label.subscribed?(options[:current_user]) diff --git a/lib/api/labels.rb b/lib/api/labels.rb index 238cea00fba..97218054f37 100644 --- a/lib/api/labels.rb +++ b/lib/api/labels.rb @@ -11,7 +11,7 @@ module API success Entities::Label end get ':id/labels' do - present available_labels, with: Entities::Label, current_user: current_user + present available_labels, with: Entities::Label, current_user: current_user, project: user_project end desc 'Create a new label' do @@ -21,6 +21,7 @@ module API requires :name, type: String, desc: 'The name of the label to be created' requires :color, type: String, desc: "The color of the label given in 6-digit hex notation with leading '#' sign (e.g. #FFAABB)" optional :description, type: String, desc: 'The description of label to be created' + optional :priority, type: Integer, desc: 'The priority of the label', allow_blank: true end post ':id/labels' do authorize! :admin_label, user_project @@ -28,10 +29,15 @@ module API label = available_labels.find_by(title: params[:name]) conflict!('Label already exists') if label - label = user_project.labels.create(declared(params, include_parent_namespaces: false).to_h) + priority = params.delete(:priority) + label_params = declared(params, + include_parent_namespaces: false, + include_missing: false).to_h + label = user_project.labels.create(label_params) if label.valid? - present label, with: Entities::Label, current_user: current_user + label.prioritize!(user_project, priority) if priority + present label, with: Entities::Label, current_user: current_user, project: user_project else render_validation_error!(label) end @@ -49,7 +55,7 @@ module API label = user_project.labels.find_by(title: params[:name]) not_found!('Label') unless label - present label.destroy, with: Entities::Label, current_user: current_user + present label.destroy, with: Entities::Label, current_user: current_user, project: user_project end desc 'Update an existing label. At least one optional parameter is required.' do @@ -60,7 +66,8 @@ module API optional :new_name, type: String, desc: 'The new name of the label' optional :color, type: String, desc: "The new color of the label given in 6-digit hex notation with leading '#' sign (e.g. #FFAABB)" optional :description, type: String, desc: 'The new description of label' - at_least_one_of :new_name, :color, :description + optional :priority, type: Integer, desc: 'The priority of the label', allow_blank: true + at_least_one_of :new_name, :color, :description, :priority end put ':id/labels' do authorize! :admin_label, user_project @@ -68,17 +75,25 @@ module API label = user_project.labels.find_by(title: params[:name]) not_found!('Label not found') unless label - update_params = declared(params, - include_parent_namespaces: false, - include_missing: false).to_h + update_priority = params.key?(:priority) + priority = params.delete(:priority) + label_params = declared(params, + include_parent_namespaces: false, + include_missing: false).to_h # Rename new name to the actual label attribute name - update_params['name'] = update_params.delete('new_name') if update_params.key?('new_name') + label_params[:name] = label_params.delete('new_name') if label_params.key?('new_name') - if label.update(update_params) - present label, with: Entities::Label, current_user: current_user - else - render_validation_error!(label) + render_validation_error!(label) unless label.update(label_params) + + if update_priority + if priority.nil? + label.unprioritize!(user_project) + else + label.prioritize!(user_project, priority) + end end + + present label, with: Entities::Label, current_user: current_user, project: user_project end end end diff --git a/spec/requests/api/labels_spec.rb b/spec/requests/api/labels_spec.rb index f702dfaaf53..7e532912d08 100644 --- a/spec/requests/api/labels_spec.rb +++ b/spec/requests/api/labels_spec.rb @@ -6,6 +6,7 @@ describe API::API, api: true do let(:user) { create(:user) } let(:project) { create(:project, creator_id: user.id, namespace: user.namespace) } let!(:label1) { create(:label, title: 'label1', project: project) } + let!(:priority_label) { create(:label, title: 'bug', project: project, priority: 3) } before do project.team << [user, :master] @@ -21,8 +22,16 @@ describe API::API, api: true do expect(response).to have_http_status(200) expect(json_response).to be_an Array - expect(json_response.size).to eq(2) - expect(json_response.map { |l| l['name'] }).to match_array([group_label.name, label1.name]) + expect(json_response.size).to eq(3) + expect(json_response.map { |l| l['name'] }).to match_array([group_label.name, priority_label.name, label1.name]) + expect(json_response.last['name']).to eq(label1.name) + expect(json_response.last['color']).to be_present + expect(json_response.last['description']).to be_nil + expect(json_response.last['open_issues_count']).to eq(0) + expect(json_response.last['closed_issues_count']).to eq(0) + expect(json_response.last['open_merge_requests_count']).to eq(0) + expect(json_response.last['priority']).to be_nil + expect(json_response.last['subscribed']).to be_falsey end end @@ -31,21 +40,39 @@ describe API::API, api: true do post api("/projects/#{project.id}/labels", user), name: 'Foo', color: '#FFAABB', - description: 'test' + description: 'test', + priority: 2 + expect(response).to have_http_status(201) expect(json_response['name']).to eq('Foo') expect(json_response['color']).to eq('#FFAABB') expect(json_response['description']).to eq('test') + expect(json_response['priority']).to eq(2) end it 'returns created label when only required params' do post api("/projects/#{project.id}/labels", user), name: 'Foo & Bar', color: '#FFAABB' + expect(response.status).to eq(201) expect(json_response['name']).to eq('Foo & Bar') expect(json_response['color']).to eq('#FFAABB') expect(json_response['description']).to be_nil + expect(json_response['priority']).to be_nil + end + + it 'creates a prioritized label' do + post api("/projects/#{project.id}/labels", user), + name: 'Foo & Bar', + color: '#FFAABB', + priority: 3 + + expect(response.status).to eq(201) + expect(json_response['name']).to eq('Foo & Bar') + expect(json_response['color']).to eq('#FFAABB') + expect(json_response['description']).to be_nil + expect(json_response['priority']).to eq(3) end it 'returns a 400 bad request if name not given' do @@ -95,6 +122,15 @@ describe API::API, api: true do expect(json_response['message']).to eq('Label already exists') end + it 'returns 400 for invalid priority' do + post api("/projects/#{project.id}/labels", user), + name: 'Foo', + color: '#FFAAFFFF', + priority: 'foo' + + expect(response).to have_http_status(400) + end + it 'returns 409 if label already exists in project' do post api("/projects/#{project.id}/labels", user), name: 'label1', @@ -155,11 +191,43 @@ describe API::API, api: true do it 'returns 200 if description is changed' do put api("/projects/#{project.id}/labels", user), - name: 'label1', + name: 'bug', description: 'test' + expect(response).to have_http_status(200) - expect(json_response['name']).to eq(label1.name) + expect(json_response['name']).to eq(priority_label.name) expect(json_response['description']).to eq('test') + expect(json_response['priority']).to eq(3) + end + + it 'returns 200 if priority is changed' do + put api("/projects/#{project.id}/labels", user), + name: 'bug', + priority: 10 + + expect(response.status).to eq(200) + expect(json_response['name']).to eq(priority_label.name) + expect(json_response['priority']).to eq(10) + end + + it 'returns 200 if a priority is added' do + put api("/projects/#{project.id}/labels", user), + name: 'label1', + priority: 3 + + expect(response.status).to eq(200) + expect(json_response['name']).to eq(label1.name) + expect(json_response['priority']).to eq(3) + end + + it 'returns 200 if the priority is removed' do + put api("/projects/#{project.id}/labels", user), + name: priority_label.name, + priority: nil + + expect(response.status).to eq(200) + expect(json_response['name']).to eq(priority_label.name) + expect(json_response['priority']).to be_nil end it 'returns 404 if label does not exist' do @@ -178,7 +246,7 @@ describe API::API, api: true do it 'returns 400 if no new parameters given' do put api("/projects/#{project.id}/labels", user), name: 'label1' expect(response).to have_http_status(400) - expect(json_response['error']).to eq('new_name, color, description are missing, '\ + expect(json_response['error']).to eq('new_name, color, description, priority are missing, '\ 'at least one parameter must be provided') end @@ -206,6 +274,14 @@ describe API::API, api: true do expect(response).to have_http_status(400) expect(json_response['message']['color']).to eq(['must be a valid color code']) end + + it 'returns 400 for invalid priority' do + post api("/projects/#{project.id}/labels", user), + name: 'Foo', + priority: 'foo' + + expect(response).to have_http_status(400) + end end describe "POST /projects/:id/labels/:label_id/subscription" do From c7c3b771205e243edece746811095c71ae151fa1 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Fri, 4 Nov 2016 11:13:17 +0100 Subject: [PATCH 125/175] Update label's API documentation --- doc/api/labels.md | 44 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/doc/api/labels.md b/doc/api/labels.md index 656232cc940..b5242037949 100644 --- a/doc/api/labels.md +++ b/doc/api/labels.md @@ -26,7 +26,9 @@ Example response: "description": "Bug reported by user", "open_issues_count": 1, "closed_issues_count": 0, - "open_merge_requests_count": 1 + "open_merge_requests_count": 1, + "subscribed": false, + "priority": 10 }, { "color" : "#d9534f", @@ -34,7 +36,9 @@ Example response: "description": "Confirmed issue", "open_issues_count": 2, "closed_issues_count": 5, - "open_merge_requests_count": 0 + "open_merge_requests_count": 0, + "subscribed": false, + "priority": null }, { "name" : "critical", @@ -42,7 +46,9 @@ Example response: "description": "Critical issue. Need fix ASAP", "open_issues_count": 1, "closed_issues_count": 3, - "open_merge_requests_count": 1 + "open_merge_requests_count": 1, + "subscribed": false, + "priority": null }, { "name" : "documentation", @@ -50,7 +56,9 @@ Example response: "description": "Issue about documentation", "open_issues_count": 1, "closed_issues_count": 0, - "open_merge_requests_count": 2 + "open_merge_requests_count": 2, + "subscribed": false, + "priority": null }, { "color" : "#5cb85c", @@ -58,7 +66,9 @@ Example response: "description": "Enhancement proposal", "open_issues_count": 1, "closed_issues_count": 0, - "open_merge_requests_count": 1 + "open_merge_requests_count": 1, + "subscribed": false, + "priority": null } ] ``` @@ -80,6 +90,7 @@ POST /projects/:id/labels | `name` | string | yes | The name of the label | | `color` | string | yes | The color of the label in 6-digit hex notation with leading `#` sign | | `description` | string | no | The description of the label | +| `priority` | integer | no | The priority of the label. Must be greater or equal than zero or `null` to remove the priority. | ```bash curl --data "name=feature&color=#5843AD" --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/1/labels" @@ -91,7 +102,11 @@ Example response: { "name" : "feature", "color" : "#5843AD", - "description":null + "open_issues_count": 1, + "closed_issues_count": 0, + "open_merge_requests_count": 1, + "description": null, + "priority": null } ``` @@ -127,7 +142,8 @@ Example response: "template" : false, "project_id" : 1, "created_at" : "2015-11-03T21:22:30.737Z", - "id" : 9 + "id" : 9, + "priority": null } ``` @@ -151,6 +167,8 @@ PUT /projects/:id/labels | `new_name` | string | yes if `color` is not provided | The new name of the label | | `color` | string | yes if `new_name` is not provided | The new color of the label in 6-digit hex notation with leading `#` sign | | `description` | string | no | The new description of the label | +| `priority` | integer | no | The new priority of the label. Must be greater or equal than zero or `null` to remove the priority. | + ```bash curl --request PUT --data "name=documentation&new_name=docs&color=#8E44AD&description=Documentation" --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/1/labels" @@ -162,7 +180,11 @@ Example response: { "color" : "#8E44AD", "name" : "docs", - "description": "Documentation" + "description": "Documentation", + "open_issues_count": 1, + "closed_issues_count": 0, + "open_merge_requests_count": 1, + "priority": null } ``` @@ -197,7 +219,8 @@ Example response: "open_issues_count": 0, "closed_issues_count": 0, "open_merge_requests_count": 0, - "subscribed": true + "subscribed": true, + "priority": null } ``` @@ -232,6 +255,7 @@ Example response: "open_issues_count": 0, "closed_issues_count": 0, "open_merge_requests_count": 0, - "subscribed": false + "subscribed": false, + "priority": null } ``` From 630eb119cb99eb971a9e29d83293774b5b882490 Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Fri, 4 Nov 2016 12:55:15 +0000 Subject: [PATCH 126/175] Renaming columns requires downtime --- .../20161103171205_rename_repository_storage_column.rb | 4 ++-- doc/development/what_requires_downtime.md | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/db/migrate/20161103171205_rename_repository_storage_column.rb b/db/migrate/20161103171205_rename_repository_storage_column.rb index e9f992793b4..93280573939 100644 --- a/db/migrate/20161103171205_rename_repository_storage_column.rb +++ b/db/migrate/20161103171205_rename_repository_storage_column.rb @@ -5,12 +5,12 @@ class RenameRepositoryStorageColumn < ActiveRecord::Migration include Gitlab::Database::MigrationHelpers # Set this constant to true if this migration requires downtime. - DOWNTIME = false + DOWNTIME = true # When a migration requires downtime you **must** uncomment the following # constant and define a short and easy to understand explanation as to why the # migration requires downtime. - # DOWNTIME_REASON = '' + DOWNTIME_REASON = 'Renaming the application_settings.repository_storage column' # When using the methods "add_concurrent_index" or "add_column_with_default" # you must disable the use of transactions as these methods can not run in an diff --git a/doc/development/what_requires_downtime.md b/doc/development/what_requires_downtime.md index 2574c2c0472..bbcd26477f3 100644 --- a/doc/development/what_requires_downtime.md +++ b/doc/development/what_requires_downtime.md @@ -66,6 +66,12 @@ producing errors whenever it tries to use the `dummy` column. As a result of the above downtime _is_ required when removing a column, even when using PostgreSQL. +## Renaming Columns + +Renaming columns requires downtime as running GitLab instances will continue +using the old column name until a new version is deployed. This can result +in the instance producing errors, which in turn can impact the user experience. + ## Changing Column Constraints Generally changing column constraints requires checking all rows in the table to From 42b238a1148fe14e8c2485438fd97dd648e6b7e3 Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Fri, 4 Nov 2016 12:56:53 +0000 Subject: [PATCH 127/175] Simplify ApplicationSetting#repository_storages --- app/models/application_setting.rb | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb index 6e7a90e7d9c..9b02a68a202 100644 --- a/app/models/application_setting.rb +++ b/app/models/application_setting.rb @@ -202,11 +202,7 @@ class ApplicationSetting < ActiveRecord::Base end def repository_storages - value = read_attribute(:repository_storages) - value = [value] if value.is_a?(String) - value = [] if value.nil? - - value + Array(read_attribute(:repository_storages)) end # repository_storage is still required in the API. Remove in 9.0 From 29668aec46f0c7479bf974e6d27ace866c800940 Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Fri, 4 Nov 2016 04:47:39 +0000 Subject: [PATCH 128/175] Use `git update-ref --stdin -z` to speed up TestEnv.set_repo_refs Previously, we were calling `git update-ref ` about 30 times per test using `create(:project)` or similar. --- spec/support/test_env.rb | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/spec/support/test_env.rb b/spec/support/test_env.rb index c79975d8667..778e665500d 100644 --- a/spec/support/test_env.rb +++ b/spec/support/test_env.rb @@ -204,20 +204,18 @@ module TestEnv end def set_repo_refs(repo_path, branch_sha) + instructions = branch_sha.map {|branch, sha| "update refs/heads/#{branch}\x00#{sha}\x00" }.join("\x00") << "\x00" + update_refs = %W(#{Gitlab.config.git.bin_path} update-ref --stdin -z) + reset = proc do + IO.popen(update_refs, "w") {|io| io.write(instructions) } + $?.success? + end + Dir.chdir(repo_path) do - branch_sha.each do |branch, sha| - # Try to reset without fetching to avoid using the network. - reset = %W(#{Gitlab.config.git.bin_path} update-ref refs/heads/#{branch} #{sha}) - unless system(*reset) - if system(*%W(#{Gitlab.config.git.bin_path} fetch origin)) - unless system(*reset) - raise 'The fetched test seed '\ - 'does not contain the required revision.' - end - else - raise 'Could not fetch test seed repository.' - end - end + # Try to reset without fetching to avoid using the network. + unless reset.call + raise 'Could not fetch test seed repository.' unless system(*%W(#{Gitlab.config.git.bin_path} fetch origin)) + raise 'The fetched test seed does not contain the required revision.' unless reset.call end end end From 95a78fb53bbddfa10db7da3b12406332a7fafacc Mon Sep 17 00:00:00 2001 From: Hiroyuki Sato Date: Mon, 7 Nov 2016 20:44:15 +0900 Subject: [PATCH 129/175] Fix bug of json request url --- app/controllers/projects/network_controller.rb | 13 ++++++++++--- app/views/projects/network/show.html.haml | 2 +- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/app/controllers/projects/network_controller.rb b/app/controllers/projects/network_controller.rb index e29e5994c4b..e808c9c7343 100644 --- a/app/controllers/projects/network_controller.rb +++ b/app/controllers/projects/network_controller.rb @@ -5,16 +5,16 @@ class Projects::NetworkController < Projects::ApplicationController before_action :require_non_empty_project before_action :assign_ref_vars before_action :authorize_download_code! + before_action :assign_extended_sha1 def show @url = namespace_project_network_path(@project.namespace, @project, @ref, @options.merge(format: :json)) @commit_url = namespace_project_commit_path(@project.namespace, @project, 'ae45ca32').gsub("ae45ca32", "%s") - @commit = @repo.commit(params[:extended_sha1]) if params[:extended_sha1].present? respond_to do |format| format.html do - if params[:extended_sha1].present? && !@commit - flash.now[:alert] = "Git revision '#{params[:extended_sha1]}' does not exist." + if @options[:extended_sha1] && !@commit + flash.now[:alert] = "Git revision '#{@options[:extended_sha1]}' does not exist." end end @@ -23,4 +23,11 @@ class Projects::NetworkController < Projects::ApplicationController end end end + + def assign_extended_sha1 + return if params[:extended_sha1].blank? + + @options[:extended_sha1] = params[:extended_sha1] + @commit = @repo.commit(@options[:extended_sha1]) + end end diff --git a/app/views/projects/network/show.html.haml b/app/views/projects/network/show.html.haml index af565873444..d8951e69242 100644 --- a/app/views/projects/network/show.html.haml +++ b/app/views/projects/network/show.html.haml @@ -8,7 +8,7 @@ .project-network .controls = form_tag namespace_project_network_path(@project.namespace, @project, @id), method: :get, class: 'form-inline network-form' do |f| - = text_field_tag :extended_sha1, params[:extended_sha1], placeholder: "Git revision", class: 'search-input form-control input-mx-250 search-sha' + = text_field_tag :extended_sha1, @options[:extended_sha1], placeholder: "Git revision", class: 'search-input form-control input-mx-250 search-sha' = button_tag class: 'btn btn-success' do = icon('search') .inline.prepend-left-20 From 3c957c006633d2df44f0d23a3131294f9b657d2b Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Thu, 13 Oct 2016 17:53:01 +0200 Subject: [PATCH 130/175] Added tests for IssuePolicy --- spec/policies/issue_policy_spec.rb | 119 +++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 spec/policies/issue_policy_spec.rb diff --git a/spec/policies/issue_policy_spec.rb b/spec/policies/issue_policy_spec.rb new file mode 100644 index 00000000000..7591bfd1471 --- /dev/null +++ b/spec/policies/issue_policy_spec.rb @@ -0,0 +1,119 @@ +require 'spec_helper' + +describe IssuePolicy, models: true do + let(:user) { create(:user) } + + describe '#rules' do + context 'using a regular issue' do + let(:project) { create(:project, :public) } + let(:issue) { create(:issue, project: project) } + let(:policies) { described_class.abilities(user, issue).to_set } + + context 'with a regular user' do + it 'includes the read_issue permission' do + expect(policies).to include(:read_issue) + end + + it 'does not include the admin_issue permission' do + expect(policies).not_to include(:admin_issue) + end + + it 'does not include the update_issue permission' do + expect(policies).not_to include(:update_issue) + end + end + + context 'with a user that is a project reporter' do + before do + project.team << [user, :reporter] + end + + it 'includes the read_issue permission' do + expect(policies).to include(:read_issue) + end + + it 'includes the admin_issue permission' do + expect(policies).to include(:admin_issue) + end + + it 'includes the update_issue permission' do + expect(policies).to include(:update_issue) + end + end + + context 'with a user that is a project guest' do + before do + project.team << [user, :guest] + end + + it 'includes the read_issue permission' do + expect(policies).to include(:read_issue) + end + + it 'does not include the admin_issue permission' do + expect(policies).not_to include(:admin_issue) + end + + it 'does not include the update_issue permission' do + expect(policies).not_to include(:update_issue) + end + end + end + + context 'using a confidential issue' do + let(:issue) { create(:issue, :confidential) } + + context 'with a regular user' do + let(:policies) { described_class.abilities(user, issue).to_set } + + it 'does not include the read_issue permission' do + expect(policies).not_to include(:read_issue) + end + + it 'does not include the admin_issue permission' do + expect(policies).not_to include(:admin_issue) + end + + it 'does not include the update_issue permission' do + expect(policies).not_to include(:update_issue) + end + end + + context 'with a user that is a project member' do + let(:policies) { described_class.abilities(user, issue).to_set } + + before do + issue.project.team << [user, :reporter] + end + + it 'includes the read_issue permission' do + expect(policies).to include(:read_issue) + end + + it 'includes the admin_issue permission' do + expect(policies).to include(:admin_issue) + end + + it 'includes the update_issue permission' do + expect(policies).to include(:update_issue) + end + end + + context 'without a user' do + let(:policies) { described_class.abilities(nil, issue).to_set } + + it 'does not include the read_issue permission' do + expect(policies).not_to include(:read_issue) + end + + it 'does not include the admin_issue permission' do + expect(policies).not_to include(:admin_issue) + end + + it 'does not include the update_issue permission' do + expect(policies).not_to include(:update_issue) + end + end + end + end +end From 467b346f0684053081d7e762df1a2b5df5888543 Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Thu, 13 Oct 2016 17:53:47 +0200 Subject: [PATCH 131/175] Add User#projects_with_reporter_access_limited_to This method can be used to retrieve a list of projects for a user that said user has reporter access to. This list is then be reduced down to a specific set of projects. This allows you to reduce a list of projects to a list of projects you have reporter access to in an efficient manner. --- app/models/user.rb | 10 ++++++++++ spec/models/user_spec.rb | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/app/models/user.rb b/app/models/user.rb index 65e96ee6b2e..c0dffa7b6ea 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -444,6 +444,16 @@ class User < ActiveRecord::Base Project.where("projects.id IN (#{projects_union(min_access_level).to_sql})") end + # Returns the projects this user has reporter (or greater) access to, limited + # to at most the given projects. + # + # This method is useful when you have a list of projects and want to + # efficiently check to which of these projects the user has at least reporter + # access. + def projects_with_reporter_access_limited_to(projects) + authorized_projects(Gitlab::Access::REPORTER).where(id: projects) + end + def viewable_starred_projects starred_projects.where("projects.visibility_level IN (?) OR projects.id IN (#{projects_union.to_sql})", [Project::PUBLIC, Project::INTERNAL]) diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index ba47479a2e1..3b152e15b61 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -1205,4 +1205,40 @@ describe User, models: true do expect(user.viewable_starred_projects).not_to include(private_project) end end + + describe '#projects_with_reporter_access_limited_to' do + let(:project1) { create(:project) } + let(:project2) { create(:project) } + let(:user) { create(:user) } + + before do + project1.team << [user, :reporter] + project2.team << [user, :guest] + end + + it 'returns the projects when using a single project ID' do + projects = user.projects_with_reporter_access_limited_to(project1.id) + + expect(projects).to eq([project1]) + end + + it 'returns the projects when using an Array of project IDs' do + projects = user.projects_with_reporter_access_limited_to([project1.id]) + + expect(projects).to eq([project1]) + end + + it 'returns the projects when using an ActiveRecord relation' do + projects = user. + projects_with_reporter_access_limited_to(Project.select(:id)) + + expect(projects).to eq([project1]) + end + + it 'does not return projects you do not have reporter access to' do + projects = user.projects_with_reporter_access_limited_to(project2.id) + + expect(projects).to be_empty + end + end end From 24261f2dbd50583ac997c3f53f78104a96fa2cd3 Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Tue, 11 Oct 2016 17:37:19 +0200 Subject: [PATCH 132/175] Add the method ExternalIssue#project_id This method returns the project's ID, making ExternalIssue slightly more compatible with Issue (which also defines the "project_id" method). --- app/models/external_issue.rb | 9 +++++++++ spec/models/external_issue_spec.rb | 8 +++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/app/models/external_issue.rb b/app/models/external_issue.rb index fd9a8c1b8b7..91b508eb325 100644 --- a/app/models/external_issue.rb +++ b/app/models/external_issue.rb @@ -29,6 +29,15 @@ class ExternalIssue @project end + def project_id + @project.id + end + + # Pattern used to extract `JIRA-123` issue references from text + def self.reference_pattern + @reference_pattern ||= %r{(?\b([A-Z][A-Z0-9_]+-)\d+)} + end + def to_reference(_from_project = nil) id end diff --git a/spec/models/external_issue_spec.rb b/spec/models/external_issue_spec.rb index ebba6e14578..2debe1289a3 100644 --- a/spec/models/external_issue_spec.rb +++ b/spec/models/external_issue_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe ExternalIssue, models: true do - let(:project) { double('project', to_reference: 'namespace1/project1') } + let(:project) { double('project', id: 1, to_reference: 'namespace1/project1') } let(:issue) { described_class.new('EXT-1234', project) } describe 'modules' do @@ -36,4 +36,10 @@ describe ExternalIssue, models: true do end end end + + describe '#project_id' do + it 'returns the ID of the project' do + expect(issue.project_id).to eq(project.id) + end + end end From 89bb29b247b57e3b4ba053a5fd17f2087ac4414f Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Tue, 11 Oct 2016 17:31:19 +0200 Subject: [PATCH 133/175] Flush Housekeeping data from Redis specs These specs use raw Redis objects which can not use the memory based caching mechanism used for tests. As such we have to explicitly flush the data from Redis before/after each spec to ensure no data lingers on. --- spec/services/git_push_service_spec.rb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/spec/services/git_push_service_spec.rb b/spec/services/git_push_service_spec.rb index 45bc44ba172..1c7a3d04b09 100644 --- a/spec/services/git_push_service_spec.rb +++ b/spec/services/git_push_service_spec.rb @@ -538,9 +538,16 @@ describe GitPushService, services: true do let(:housekeeping) { Projects::HousekeepingService.new(project) } before do + # Flush any raw Redis data stored by the housekeeping code. + Gitlab::Redis.with { |conn| conn.flushall } + allow(Projects::HousekeepingService).to receive(:new).and_return(housekeeping) end + after do + Gitlab::Redis.with { |conn| conn.flushall } + end + it 'does not perform housekeeping when not needed' do expect(housekeeping).not_to receive(:execute) From f694f94c491452a50035c2ff43c8ba595c0e73aa Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Wed, 12 Oct 2016 14:01:34 +0200 Subject: [PATCH 134/175] Added IssueCollection This class can be used to reduce a list of issues down to a subset based on user permissions. This class operates in such a way that it can reduce issues using as few queries as possible, if any at all. --- app/models/concerns/issuable.rb | 5 +++ app/models/issue_collection.rb | 40 ++++++++++++++++++ app/policies/issuable_policy.rb | 2 +- app/policies/issue_policy.rb | 9 +---- spec/models/concerns/issuable_spec.rb | 21 ++++++++++ spec/models/issue_collection_spec.rb | 58 +++++++++++++++++++++++++++ 6 files changed, 127 insertions(+), 8 deletions(-) create mode 100644 app/models/issue_collection.rb create mode 100644 spec/models/issue_collection_spec.rb diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb index 613444e0d70..93a6b3122e0 100644 --- a/app/models/concerns/issuable.rb +++ b/app/models/concerns/issuable.rb @@ -286,6 +286,11 @@ module Issuable false end + def assignee_or_author?(user) + # We're comparing IDs here so we don't need to load any associations. + author_id == user.id || assignee_id == user.id + end + def record_metrics metrics = self.metrics || create_metrics metrics.record! diff --git a/app/models/issue_collection.rb b/app/models/issue_collection.rb new file mode 100644 index 00000000000..df36252a5b1 --- /dev/null +++ b/app/models/issue_collection.rb @@ -0,0 +1,40 @@ +# IssueCollection can be used to reduce a list of issues down to a subset. +# +# IssueCollection is not meant to be some sort of Enumerable, instead it's meant +# to take a list of issues and return a new list of issues based on some +# criteria. For example, given a list of issues you may want to return a list of +# issues that can be read or updated by a given user. +class IssueCollection + attr_reader :collection + + def initialize(collection) + @collection = collection + end + + # Returns all the issues that can be updated by the user. + def updatable_by_user(user) + return collection if user.admin? + + # Given all the issue projects we get a list of projects that the current + # user has at least reporter access to. + projects_with_reporter_access = user. + projects_with_reporter_access_limited_to(project_ids). + pluck(:id) + + collection.select do |issue| + if projects_with_reporter_access.include?(issue.project_id) + true + elsif issue.is_a?(Issue) + issue.assignee_or_author?(user) + else + false + end + end + end + + private + + def project_ids + @project_ids ||= collection.map(&:project_id).uniq + end +end diff --git a/app/policies/issuable_policy.rb b/app/policies/issuable_policy.rb index c253f9a9399..9501e499507 100644 --- a/app/policies/issuable_policy.rb +++ b/app/policies/issuable_policy.rb @@ -4,7 +4,7 @@ class IssuablePolicy < BasePolicy end def rules - if @user && (@subject.author == @user || @subject.assignee == @user) + if @user && @subject.assignee_or_author?(@user) can! :"read_#{action_name}" can! :"update_#{action_name}" end diff --git a/app/policies/issue_policy.rb b/app/policies/issue_policy.rb index bd1811a3c54..f3ede58a001 100644 --- a/app/policies/issue_policy.rb +++ b/app/policies/issue_policy.rb @@ -8,9 +8,8 @@ class IssuePolicy < IssuablePolicy if @subject.confidential? && !can_read_confidential? cannot! :read_issue - cannot! :admin_issue cannot! :update_issue - cannot! :read_issue + cannot! :admin_issue end end @@ -18,11 +17,7 @@ class IssuePolicy < IssuablePolicy def can_read_confidential? return false unless @user - return true if @user.admin? - return true if @subject.author == @user - return true if @subject.assignee == @user - return true if @subject.project.team.member?(@user, Gitlab::Access::REPORTER) - false + IssueCollection.new([@subject]).updatable_by_user(@user).any? end end diff --git a/spec/models/concerns/issuable_spec.rb b/spec/models/concerns/issuable_spec.rb index a59d30687f6..a9603074c32 100644 --- a/spec/models/concerns/issuable_spec.rb +++ b/spec/models/concerns/issuable_spec.rb @@ -341,4 +341,25 @@ describe Issue, "Issuable" do expect(Issue.with_label([bug.title, enhancement.title])).to match_array([issue2]) end end + + describe '#assignee_or_author?' do + let(:user) { build(:user, id: 1) } + let(:issue) { build(:issue) } + + it 'returns true for a user that is assigned to an issue' do + issue.assignee = user + + expect(issue.assignee_or_author?(user)).to eq(true) + end + + it 'returns true for a user that is the author of an issue' do + issue.author = user + + expect(issue.assignee_or_author?(user)).to eq(true) + end + + it 'returns false for a user that is not the assignee or author' do + expect(issue.assignee_or_author?(user)).to eq(false) + end + end end diff --git a/spec/models/issue_collection_spec.rb b/spec/models/issue_collection_spec.rb new file mode 100644 index 00000000000..d9ab397c302 --- /dev/null +++ b/spec/models/issue_collection_spec.rb @@ -0,0 +1,58 @@ +require 'spec_helper' + +describe IssueCollection do + let(:user) { create(:user) } + let(:project) { create(:project) } + let(:issue1) { create(:issue, project: project) } + let(:issue2) { create(:issue, project: project) } + let(:collection) { described_class.new([issue1, issue2]) } + + describe '#collection' do + it 'returns the issues in the same order as the input Array' do + expect(collection.collection).to eq([issue1, issue2]) + end + end + + describe '#updatable_by_user' do + context 'using an admin user' do + it 'returns all issues' do + user = create(:admin) + + expect(collection.updatable_by_user(user)).to eq([issue1, issue2]) + end + end + + context 'using a user that has no access to the project' do + it 'returns no issues when the user is not an assignee or author' do + expect(collection.updatable_by_user(user)).to be_empty + end + + it 'returns the issues the user is assigned to' do + issue1.assignee = user + + expect(collection.updatable_by_user(user)).to eq([issue1]) + end + + it 'returns the issues for which the user is the author' do + issue1.author = user + + expect(collection.updatable_by_user(user)).to eq([issue1]) + end + end + + context 'using a user that has reporter access to the project' do + it 'returns the issues of the project' do + project.team << [user, :reporter] + + expect(collection.updatable_by_user(user)).to eq([issue1, issue2]) + end + end + + context 'using a user that is the owner of a project' do + it 'returns the issues of the project' do + expect(collection.updatable_by_user(project.namespace.owner)). + to eq([issue1, issue2]) + end + end + end +end From 509910b89f636f95d2d5a9cd3f38ce8f7f4f47a6 Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Fri, 7 Oct 2016 15:20:57 +0200 Subject: [PATCH 135/175] Process commits in a separate worker This moves the code used for processing commits from GitPushService to its own Sidekiq worker: ProcessCommitWorker. Using a Sidekiq worker allows us to process multiple commits in parallel. This in turn will lead to issues being closed faster and cross references being created faster. Furthermore by isolating this code into a separate class it's easier to test and maintain the code. The new worker also ensures it can efficiently check which issues can be closed, without having to run numerous SQL queries for every issue. --- app/models/issue_collection.rb | 2 + app/policies/issue_policy.rb | 2 +- app/services/git_push_service.rb | 37 +----- app/services/issues/close_service.rb | 13 +++ app/workers/process_commit_worker.rb | 67 +++++++++++ .../process-commits-using-sidekiq.yml | 4 + config/sidekiq_queues.yml | 1 + spec/models/issue_collection_spec.rb | 9 ++ spec/services/git_push_service_spec.rb | 9 ++ spec/services/issues/close_service_spec.rb | 49 +++++--- spec/workers/process_commit_worker_spec.rb | 109 ++++++++++++++++++ 11 files changed, 251 insertions(+), 51 deletions(-) create mode 100644 app/workers/process_commit_worker.rb create mode 100644 changelogs/unreleased/process-commits-using-sidekiq.yml create mode 100644 spec/workers/process_commit_worker_spec.rb diff --git a/app/models/issue_collection.rb b/app/models/issue_collection.rb index df36252a5b1..f0b7d9914c8 100644 --- a/app/models/issue_collection.rb +++ b/app/models/issue_collection.rb @@ -32,6 +32,8 @@ class IssueCollection end end + alias_method :visible_to, :updatable_by_user + private def project_ids diff --git a/app/policies/issue_policy.rb b/app/policies/issue_policy.rb index f3ede58a001..52fa33bc4b0 100644 --- a/app/policies/issue_policy.rb +++ b/app/policies/issue_policy.rb @@ -18,6 +18,6 @@ class IssuePolicy < IssuablePolicy def can_read_confidential? return false unless @user - IssueCollection.new([@subject]).updatable_by_user(@user).any? + IssueCollection.new([@subject]).visible_to(@user).any? end end diff --git a/app/services/git_push_service.rb b/app/services/git_push_service.rb index e8415862de5..de313095bed 100644 --- a/app/services/git_push_service.rb +++ b/app/services/git_push_service.rb @@ -105,35 +105,11 @@ class GitPushService < BaseService # Extract any GFM references from the pushed commit messages. If the configured issue-closing regex is matched, # close the referenced Issue. Create cross-reference Notes corresponding to any other referenced Mentionables. def process_commit_messages - is_default_branch = is_default_branch? - - authors = Hash.new do |hash, commit| - email = commit.author_email - next hash[email] if hash.has_key?(email) - - hash[email] = commit_user(commit) - end + default = is_default_branch? @push_commits.each do |commit| - # Keep track of the issues that will be actually closed because they are on a default branch. - # Hence, when creating cross-reference notes, the not-closed issues (on non-default branches) - # will also have cross-reference. - closed_issues = [] - - if is_default_branch - # Close issues if these commits were pushed to the project's default branch and the commit message matches the - # closing regex. Exclude any mentioned Issues from cross-referencing even if the commits are being pushed to - # a different branch. - closed_issues = commit.closes_issues(current_user) - closed_issues.each do |issue| - if can?(current_user, :update_issue, issue) - Issues::CloseService.new(project, authors[commit], {}).execute(issue, commit: commit) - end - end - end - - commit.create_cross_references!(authors[commit], closed_issues) - update_issue_metrics(commit, authors) + ProcessCommitWorker. + perform_async(project.id, current_user.id, commit.id, default) end end @@ -176,11 +152,4 @@ class GitPushService < BaseService def branch_name @branch_name ||= Gitlab::Git.ref_name(params[:ref]) end - - def update_issue_metrics(commit, authors) - mentioned_issues = commit.all_references(authors[commit]).issues - - Issue::Metrics.where(issue_id: mentioned_issues.map(&:id), first_mentioned_in_commit_at: nil). - update_all(first_mentioned_in_commit_at: commit.committed_date) - end end diff --git a/app/services/issues/close_service.rb b/app/services/issues/close_service.rb index 45cca216ccc..ab4c51386a4 100644 --- a/app/services/issues/close_service.rb +++ b/app/services/issues/close_service.rb @@ -1,8 +1,21 @@ module Issues class CloseService < Issues::BaseService + # Closes the supplied issue if the current user is able to do so. def execute(issue, commit: nil, notifications: true, system_note: true) return issue unless can?(current_user, :update_issue, issue) + close_issue(issue, + commit: commit, + notifications: notifications, + system_note: system_note) + end + + # Closes the supplied issue without checking if the user is authorized to + # do so. + # + # The code calling this method is responsible for ensuring that a user is + # allowed to close the given issue. + def close_issue(issue, commit: nil, notifications: true, system_note: true) if project.jira_tracker? && project.jira_service.active project.jira_service.execute(commit, issue) todo_service.close_issue(issue, current_user) diff --git a/app/workers/process_commit_worker.rb b/app/workers/process_commit_worker.rb new file mode 100644 index 00000000000..071741fbacd --- /dev/null +++ b/app/workers/process_commit_worker.rb @@ -0,0 +1,67 @@ +# Worker for processing individiual commit messages pushed to a repository. +# +# Jobs for this worker are scheduled for every commit that is being pushed. As a +# result of this the workload of this worker should be kept to a bare minimum. +# Consider using an extra worker if you need to add any extra (and potentially +# slow) processing of commits. +class ProcessCommitWorker + include Sidekiq::Worker + include DedicatedSidekiqQueue + + # project_id - The ID of the project this commit belongs to. + # user_id - The ID of the user that pushed the commit. + # commit_sha - The SHA1 of the commit to process. + # default - The data was pushed to the default branch. + def perform(project_id, user_id, commit_sha, default = false) + project = Project.find_by(id: project_id) + + return unless project + + user = User.find_by(id: user_id) + + return unless user + + commit = find_commit(project, commit_sha) + + return unless commit + + author = commit.author || user + + process_commit_message(project, commit, user, author, default) + + update_issue_metrics(commit, author) + end + + def process_commit_message(project, commit, user, author, default = false) + closed_issues = default ? commit.closes_issues(user) : [] + + unless closed_issues.empty? + close_issues(project, user, author, commit, closed_issues) + end + + commit.create_cross_references!(author, closed_issues) + end + + def close_issues(project, user, author, commit, issues) + # We don't want to run permission related queries for every single issue, + # therefor we use IssueCollection here and skip the authorization check in + # Issues::CloseService#execute. + IssueCollection.new(issues).updatable_by_user(user).each do |issue| + Issues::CloseService.new(project, author). + close_issue(issue, commit: commit) + end + end + + def update_issue_metrics(commit, author) + mentioned_issues = commit.all_references(author).issues + + Issue::Metrics.where(issue_id: mentioned_issues.map(&:id), first_mentioned_in_commit_at: nil). + update_all(first_mentioned_in_commit_at: commit.committed_date) + end + + private + + def find_commit(project, sha) + project.commit(sha) + end +end diff --git a/changelogs/unreleased/process-commits-using-sidekiq.yml b/changelogs/unreleased/process-commits-using-sidekiq.yml new file mode 100644 index 00000000000..9f596e6a584 --- /dev/null +++ b/changelogs/unreleased/process-commits-using-sidekiq.yml @@ -0,0 +1,4 @@ +--- +title: Process commits using a dedicated Sidekiq worker +merge_request: 6802 +author: diff --git a/config/sidekiq_queues.yml b/config/sidekiq_queues.yml index f36fe893fd0..0aec8aedf72 100644 --- a/config/sidekiq_queues.yml +++ b/config/sidekiq_queues.yml @@ -21,6 +21,7 @@ - [post_receive, 5] - [merge, 5] - [update_merge_requests, 3] + - [process_commit, 2] - [new_note, 2] - [build, 2] - [pipeline, 2] diff --git a/spec/models/issue_collection_spec.rb b/spec/models/issue_collection_spec.rb index d9ab397c302..d742c814680 100644 --- a/spec/models/issue_collection_spec.rb +++ b/spec/models/issue_collection_spec.rb @@ -55,4 +55,13 @@ describe IssueCollection do end end end + + describe '#visible_to' do + it 'is an alias for updatable_by_user' do + updatable_by_user = described_class.instance_method(:updatable_by_user) + visible_to = described_class.instance_method(:visible_to) + + expect(visible_to).to eq(updatable_by_user) + end + end end diff --git a/spec/services/git_push_service_spec.rb b/spec/services/git_push_service_spec.rb index 1c7a3d04b09..cea7e6429f9 100644 --- a/spec/services/git_push_service_spec.rb +++ b/spec/services/git_push_service_spec.rb @@ -302,6 +302,9 @@ describe GitPushService, services: true do author_email: commit_author.email ) + allow_any_instance_of(ProcessCommitWorker).to receive(:find_commit). + and_return(commit) + allow(project.repository).to receive(:commits_between).and_return([commit]) end @@ -357,6 +360,9 @@ describe GitPushService, services: true do committed_date: commit_time ) + allow_any_instance_of(ProcessCommitWorker).to receive(:find_commit). + and_return(commit) + allow(project.repository).to receive(:commits_between).and_return([commit]) end @@ -393,6 +399,9 @@ describe GitPushService, services: true do allow(project.repository).to receive(:commits_between). and_return([closing_commit]) + allow_any_instance_of(ProcessCommitWorker).to receive(:find_commit). + and_return(closing_commit) + project.team << [commit_author, :master] end diff --git a/spec/services/issues/close_service_spec.rb b/spec/services/issues/close_service_spec.rb index 5dfb33f4b28..4465f22a001 100644 --- a/spec/services/issues/close_service_spec.rb +++ b/spec/services/issues/close_service_spec.rb @@ -15,10 +15,39 @@ describe Issues::CloseService, services: true do end describe '#execute' do + let(:service) { described_class.new(project, user) } + + it 'checks if the user is authorized to update the issue' do + expect(service).to receive(:can?).with(user, :update_issue, issue). + and_call_original + + service.execute(issue) + end + + it 'does not close the issue when the user is not authorized to do so' do + allow(service).to receive(:can?).with(user, :update_issue, issue). + and_return(false) + + expect(service).not_to receive(:close_issue) + expect(service.execute(issue)).to eq(issue) + end + + it 'closes the issue when the user is authorized to do so' do + allow(service).to receive(:can?).with(user, :update_issue, issue). + and_return(true) + + expect(service).to receive(:close_issue). + with(issue, commit: nil, notifications: true, system_note: true) + + service.execute(issue) + end + end + + describe '#close_issue' do context "valid params" do before do perform_enqueued_jobs do - described_class.new(project, user).execute(issue) + described_class.new(project, user).close_issue(issue) end end @@ -41,24 +70,12 @@ describe Issues::CloseService, services: true do end end - context 'current user is not authorized to close issue' do - before do - perform_enqueued_jobs do - described_class.new(project, guest).execute(issue) - end - end - - it 'does not close the issue' do - expect(issue).to be_open - end - end - context 'when issue is not confidential' do it 'executes issue hooks' do expect(project).to receive(:execute_hooks).with(an_instance_of(Hash), :issue_hooks) expect(project).to receive(:execute_services).with(an_instance_of(Hash), :issue_hooks) - described_class.new(project, user).execute(issue) + described_class.new(project, user).close_issue(issue) end end @@ -69,14 +86,14 @@ describe Issues::CloseService, services: true do expect(project).to receive(:execute_hooks).with(an_instance_of(Hash), :confidential_issue_hooks) expect(project).to receive(:execute_services).with(an_instance_of(Hash), :confidential_issue_hooks) - described_class.new(project, user).execute(issue) + described_class.new(project, user).close_issue(issue) end end context 'external issue tracker' do before do allow(project).to receive(:default_issues_tracker?).and_return(false) - described_class.new(project, user).execute(issue) + described_class.new(project, user).close_issue(issue) end it { expect(issue).to be_valid } diff --git a/spec/workers/process_commit_worker_spec.rb b/spec/workers/process_commit_worker_spec.rb new file mode 100644 index 00000000000..3e4fee42240 --- /dev/null +++ b/spec/workers/process_commit_worker_spec.rb @@ -0,0 +1,109 @@ +require 'spec_helper' + +describe ProcessCommitWorker do + let(:worker) { described_class.new } + let(:user) { create(:user) } + let(:project) { create(:project, :public) } + let(:issue) { create(:issue, project: project, author: user) } + let(:commit) { project.commit } + + describe '#perform' do + it 'does not process the commit when the project does not exist' do + expect(worker).not_to receive(:close_issues) + + worker.perform(-1, user.id, commit.id) + end + + it 'does not process the commit when the user does not exist' do + expect(worker).not_to receive(:close_issues) + + worker.perform(project.id, -1, commit.id) + end + + it 'does not process the commit when the commit no longer exists' do + expect(worker).not_to receive(:close_issues) + + worker.perform(project.id, user.id, 'this-should-does-not-exist') + end + + it 'processes the commit message' do + expect(worker).to receive(:process_commit_message).and_call_original + + worker.perform(project.id, user.id, commit.id) + end + + it 'updates the issue metrics' do + expect(worker).to receive(:update_issue_metrics).and_call_original + + worker.perform(project.id, user.id, commit.id) + end + end + + describe '#process_commit_message' do + context 'when pushing to the default branch' do + it 'closes issues that should be closed per the commit message' do + allow(commit).to receive(:safe_message). + and_return("Closes #{issue.to_reference}") + + expect(worker).to receive(:close_issues). + with(project, user, user, commit, [issue]) + + worker.process_commit_message(project, commit, user, user, true) + end + end + + context 'when pushing to a non-default branch' do + it 'does not close any issues' do + allow(commit).to receive(:safe_message). + and_return("Closes #{issue.to_reference}") + + expect(worker).not_to receive(:close_issues) + + worker.process_commit_message(project, commit, user, user, false) + end + end + + it 'creates cross references' do + expect(commit).to receive(:create_cross_references!) + + worker.process_commit_message(project, commit, user, user) + end + end + + describe '#close_issues' do + context 'when the user can update the issues' do + it 'closes the issues' do + worker.close_issues(project, user, user, commit, [issue]) + + issue.reload + + expect(issue.closed?).to eq(true) + end + end + + context 'when the user can not update the issues' do + it 'does not close the issues' do + other_user = create(:user) + + worker.close_issues(project, other_user, other_user, commit, [issue]) + + issue.reload + + expect(issue.closed?).to eq(false) + end + end + end + + describe '#update_issue_metrics' do + it 'updates any existing issue metrics' do + allow(commit).to receive(:safe_message). + and_return("Closes #{issue.to_reference}") + + worker.update_issue_metrics(commit, user) + + metric = Issue::Metrics.first + + expect(metric.first_mentioned_in_commit_at).to eq(commit.committed_date) + end + end +end From 82e551bdac7f2792e1d6aceb1b0b674dbd3dda81 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 7 Nov 2016 15:16:04 +0200 Subject: [PATCH 136/175] Refactor routing constraints Signed-off-by: Dmitriy Zaporozhets --- lib/constraints/constrainer_helper.rb | 15 ++++++++ lib/constraints/group_url_constrainer.rb | 16 ++++++--- lib/constraints/namespace_url_constrainer.rb | 24 ------------- lib/constraints/user_url_constrainer.rb | 16 ++++++--- .../constraints/constrainer_helper_spec.rb | 20 +++++++++++ .../constraints/group_url_constrainer_spec.rb | 17 ++++++--- .../namespace_url_constrainer_spec.rb | 35 ------------------- .../constraints/user_url_constrainer_spec.rb | 12 +++++-- 8 files changed, 81 insertions(+), 74 deletions(-) create mode 100644 lib/constraints/constrainer_helper.rb delete mode 100644 lib/constraints/namespace_url_constrainer.rb create mode 100644 spec/lib/constraints/constrainer_helper_spec.rb delete mode 100644 spec/lib/constraints/namespace_url_constrainer_spec.rb diff --git a/lib/constraints/constrainer_helper.rb b/lib/constraints/constrainer_helper.rb new file mode 100644 index 00000000000..ab07a6793d9 --- /dev/null +++ b/lib/constraints/constrainer_helper.rb @@ -0,0 +1,15 @@ +module ConstrainerHelper + def extract_resource_path(path) + id = path.dup + id.sub!(/\A#{relative_url_root}/, '') if relative_url_root + id.sub(/\A\/+/, '').sub(/\/+\z/, '').sub(/.atom\z/, '') + end + + private + + def relative_url_root + if defined?(Gitlab::Application.config.relative_url_root) + Gitlab::Application.config.relative_url_root + end + end +end diff --git a/lib/constraints/group_url_constrainer.rb b/lib/constraints/group_url_constrainer.rb index ca39b1961ae..2bf973a73da 100644 --- a/lib/constraints/group_url_constrainer.rb +++ b/lib/constraints/group_url_constrainer.rb @@ -1,7 +1,15 @@ -require 'constraints/namespace_url_constrainer' +require_relative 'constrainer_helper' -class GroupUrlConstrainer < NamespaceUrlConstrainer - def find_resource(id) - Group.find_by_path(id) +class GroupUrlConstrainer + include ConstrainerHelper + + def matches?(request) + id = extract_resource_path(request.path) + + if id =~ Gitlab::Regex.namespace_regex + !!Group.find_by_path(id) + else + false + end end end diff --git a/lib/constraints/namespace_url_constrainer.rb b/lib/constraints/namespace_url_constrainer.rb deleted file mode 100644 index 91b70143f11..00000000000 --- a/lib/constraints/namespace_url_constrainer.rb +++ /dev/null @@ -1,24 +0,0 @@ -class NamespaceUrlConstrainer - def matches?(request) - id = request.path - id = id.sub(/\A#{relative_url_root}/, '') if relative_url_root - id = id.sub(/\A\/+/, '').split('/').first - id = id.sub(/.atom\z/, '') if id - - if id =~ Gitlab::Regex.namespace_regex - find_resource(id) - end - end - - def find_resource(id) - Namespace.find_by_path(id) - end - - private - - def relative_url_root - if defined?(Gitlab::Application.config.relative_url_root) - Gitlab::Application.config.relative_url_root - end - end -end diff --git a/lib/constraints/user_url_constrainer.rb b/lib/constraints/user_url_constrainer.rb index 504a0f5d93e..9583cace022 100644 --- a/lib/constraints/user_url_constrainer.rb +++ b/lib/constraints/user_url_constrainer.rb @@ -1,7 +1,15 @@ -require 'constraints/namespace_url_constrainer' +require_relative 'constrainer_helper' -class UserUrlConstrainer < NamespaceUrlConstrainer - def find_resource(id) - User.find_by('lower(username) = ?', id.downcase) +class UserUrlConstrainer + include ConstrainerHelper + + def matches?(request) + id = extract_resource_path(request.path) + + if id =~ Gitlab::Regex.namespace_regex + !!User.find_by('lower(username) = ?', id.downcase) + else + false + end end end diff --git a/spec/lib/constraints/constrainer_helper_spec.rb b/spec/lib/constraints/constrainer_helper_spec.rb new file mode 100644 index 00000000000..27c8d72aefc --- /dev/null +++ b/spec/lib/constraints/constrainer_helper_spec.rb @@ -0,0 +1,20 @@ +require 'spec_helper' + +describe ConstrainerHelper, lib: true do + include ConstrainerHelper + + describe '#extract_resource_path' do + it { expect(extract_resource_path('/gitlab/')).to eq('gitlab') } + it { expect(extract_resource_path('///gitlab//')).to eq('gitlab') } + it { expect(extract_resource_path('/gitlab.atom')).to eq('gitlab') } + + context 'relative url' do + before do + allow(Gitlab::Application.config).to receive(:relative_url_root) { '/gitlab' } + end + + it { expect(extract_resource_path('/gitlab/foo')).to eq('foo') } + it { expect(extract_resource_path('/foo/bar')).to eq('foo/bar') } + end + end +end diff --git a/spec/lib/constraints/group_url_constrainer_spec.rb b/spec/lib/constraints/group_url_constrainer_spec.rb index f0b75a664f2..be69a36c2b6 100644 --- a/spec/lib/constraints/group_url_constrainer_spec.rb +++ b/spec/lib/constraints/group_url_constrainer_spec.rb @@ -1,10 +1,19 @@ require 'spec_helper' describe GroupUrlConstrainer, lib: true do - let!(:username) { create(:group, path: 'gitlab-org') } + let!(:group) { create(:group, path: 'gitlab') } - describe '#find_resource' do - it { expect(!!subject.find_resource('gitlab-org')).to be_truthy } - it { expect(!!subject.find_resource('gitlab-com')).to be_falsey } + describe '#matches?' do + context 'root group' do + it { expect(subject.matches?(request '/gitlab')).to be_truthy } + it { expect(subject.matches?(request '/gitlab.atom')).to be_truthy } + it { expect(subject.matches?(request '/gitlab/edit')).to be_falsey } + it { expect(subject.matches?(request '/gitlab-ce')).to be_falsey } + it { expect(subject.matches?(request '/.gitlab')).to be_falsey } + end + end + + def request(path) + OpenStruct.new(path: path) end end diff --git a/spec/lib/constraints/namespace_url_constrainer_spec.rb b/spec/lib/constraints/namespace_url_constrainer_spec.rb deleted file mode 100644 index 7814711fe27..00000000000 --- a/spec/lib/constraints/namespace_url_constrainer_spec.rb +++ /dev/null @@ -1,35 +0,0 @@ -require 'spec_helper' - -describe NamespaceUrlConstrainer, lib: true do - let!(:group) { create(:group, path: 'gitlab') } - - describe '#matches?' do - context 'existing namespace' do - it { expect(subject.matches?(request '/gitlab')).to be_truthy } - it { expect(subject.matches?(request '/gitlab.atom')).to be_truthy } - it { expect(subject.matches?(request '/gitlab/')).to be_truthy } - it { expect(subject.matches?(request '//gitlab/')).to be_truthy } - end - - context 'non-existing namespace' do - it { expect(subject.matches?(request '/gitlab-ce')).to be_falsey } - it { expect(subject.matches?(request '/gitlab.ce')).to be_falsey } - it { expect(subject.matches?(request '/g/gitlab')).to be_falsey } - it { expect(subject.matches?(request '/.gitlab')).to be_falsey } - end - - context 'relative url' do - before do - allow(Gitlab::Application.config).to receive(:relative_url_root) { '/gitlab' } - end - - it { expect(subject.matches?(request '/gitlab/gitlab')).to be_truthy } - it { expect(subject.matches?(request '/gitlab/gitlab-ce')).to be_falsey } - it { expect(subject.matches?(request '/gitlab/')).to be_falsey } - end - end - - def request(path) - OpenStruct.new(path: path) - end -end diff --git a/spec/lib/constraints/user_url_constrainer_spec.rb b/spec/lib/constraints/user_url_constrainer_spec.rb index 4b26692672f..d7b7d5664ff 100644 --- a/spec/lib/constraints/user_url_constrainer_spec.rb +++ b/spec/lib/constraints/user_url_constrainer_spec.rb @@ -3,8 +3,14 @@ require 'spec_helper' describe UserUrlConstrainer, lib: true do let!(:username) { create(:user, username: 'dz') } - describe '#find_resource' do - it { expect(!!subject.find_resource('dz')).to be_truthy } - it { expect(!!subject.find_resource('john')).to be_falsey } + describe '#matches?' do + it { expect(subject.matches?(request '/dz')).to be_truthy } + it { expect(subject.matches?(request '/dz.atom')).to be_truthy } + it { expect(subject.matches?(request '/dz/projects')).to be_falsey } + it { expect(subject.matches?(request '/gitlab')).to be_falsey } + end + + def request(path) + OpenStruct.new(path: path) end end From 4ca3db3f9d3bc288fe6b535aca6fb33b00f5e040 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 7 Nov 2016 15:34:25 +0200 Subject: [PATCH 137/175] Refactor group routing * separate controller actions from nested resources * prepare group routing for nested namespaces support Signed-off-by: Dmitriy Zaporozhets --- config/routes/group.rb | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/config/routes/group.rb b/config/routes/group.rb index 826048ba196..faec3f0ad56 100644 --- a/config/routes/group.rb +++ b/config/routes/group.rb @@ -12,26 +12,26 @@ constraints(GroupUrlConstrainer.new) do end end -scope constraints: { id: /[a-zA-Z.0-9_\-]+(? 'groups#show', as: :group_canonical +scope(path: 'groups/:id', controller: :groups) do + get :edit, as: :edit_group + get :issues, as: :issues_group + get :merge_requests, as: :merge_requests_group + get :projects, as: :projects_group + get :activity, as: :activity_group end + +scope(path: 'groups/:group_id', module: :groups, as: :group) do + resources :group_members, only: [:index, :create, :update, :destroy], concerns: :access_requestable do + post :resend_invite, on: :member + delete :leave, on: :collection + end + + resource :avatar, only: [:destroy] + resources :milestones, constraints: { id: /[^\/]+/ }, only: [:index, :show, :update, :new, :create] + resources :labels, except: [:show], constraints: { id: /\d+/ } +end + +# Must be last route in this file +get 'groups/:id' => 'groups#show', as: :group_canonical From 63f0b099744834424e6fef78c694beda9d8b16fe Mon Sep 17 00:00:00 2001 From: Rares Sfirlogea Date: Fri, 4 Nov 2016 12:52:38 +0100 Subject: [PATCH 138/175] Expose Label id to API [e44da1c] Add Label API expected keys to tests [ac929c8] Update Label API documentation --- changelogs/unreleased/add-api-label-id.yml | 4 + doc/api/labels.md | 189 +++++++++++---------- lib/api/entities.rb | 2 +- spec/requests/api/labels_spec.rb | 6 + 4 files changed, 111 insertions(+), 90 deletions(-) create mode 100644 changelogs/unreleased/add-api-label-id.yml diff --git a/changelogs/unreleased/add-api-label-id.yml b/changelogs/unreleased/add-api-label-id.yml new file mode 100644 index 00000000000..3af4f5e677d --- /dev/null +++ b/changelogs/unreleased/add-api-label-id.yml @@ -0,0 +1,4 @@ +--- +title: Expose label IDs in API +merge_request: 7275 +author: Rares Sfirlogea diff --git a/doc/api/labels.md b/doc/api/labels.md index b5242037949..78686fdcad4 100644 --- a/doc/api/labels.md +++ b/doc/api/labels.md @@ -20,56 +20,61 @@ Example response: ```json [ - { - "name" : "bug", - "color" : "#d9534f", - "description": "Bug reported by user", - "open_issues_count": 1, - "closed_issues_count": 0, - "open_merge_requests_count": 1, - "subscribed": false, - "priority": 10 - }, - { - "color" : "#d9534f", - "name" : "confirmed", - "description": "Confirmed issue", - "open_issues_count": 2, - "closed_issues_count": 5, - "open_merge_requests_count": 0, - "subscribed": false, - "priority": null - }, - { - "name" : "critical", - "color" : "#d9534f", - "description": "Critical issue. Need fix ASAP", - "open_issues_count": 1, - "closed_issues_count": 3, - "open_merge_requests_count": 1, - "subscribed": false, - "priority": null - }, - { - "name" : "documentation", - "color" : "#f0ad4e", - "description": "Issue about documentation", - "open_issues_count": 1, - "closed_issues_count": 0, - "open_merge_requests_count": 2, - "subscribed": false, - "priority": null - }, - { - "color" : "#5cb85c", - "name" : "enhancement", - "description": "Enhancement proposal", - "open_issues_count": 1, - "closed_issues_count": 0, - "open_merge_requests_count": 1, - "subscribed": false, - "priority": null - } + { + "id" : 1, + "name" : "bug", + "color" : "#d9534f", + "description": "Bug reported by user", + "open_issues_count": 1, + "closed_issues_count": 0, + "open_merge_requests_count": 1, + "subscribed": false, + "priority": 10 + }, + { + "id" : 4, + "color" : "#d9534f", + "name" : "confirmed", + "description": "Confirmed issue", + "open_issues_count": 2, + "closed_issues_count": 5, + "open_merge_requests_count": 0, + "subscribed": false, + "priority": null + }, + { + "id" : 7, + "name" : "critical", + "color" : "#d9534f", + "description": "Critical issue. Need fix ASAP", + "open_issues_count": 1, + "closed_issues_count": 3, + "open_merge_requests_count": 1, + "subscribed": false, + "priority": null + }, + { + "id" : 8, + "name" : "documentation", + "color" : "#f0ad4e", + "description": "Issue about documentation", + "open_issues_count": 1, + "closed_issues_count": 0, + "open_merge_requests_count": 2, + "subscribed": false, + "priority": null + }, + { + "id" : 9, + "color" : "#5cb85c", + "name" : "enhancement", + "description": "Enhancement proposal", + "open_issues_count": 1, + "closed_issues_count": 0, + "open_merge_requests_count": 1, + "subscribed": true, + "priority": null + } ] ``` @@ -100,13 +105,15 @@ Example response: ```json { - "name" : "feature", - "color" : "#5843AD", - "open_issues_count": 1, - "closed_issues_count": 0, - "open_merge_requests_count": 1, - "description": null, - "priority": null + "id" : 10, + "name" : "feature", + "color" : "#5843AD", + "description":null, + "open_issues_count": 0, + "closed_issues_count": 0, + "open_merge_requests_count": 0, + "subscribed": false, + "priority": null } ``` @@ -135,15 +142,15 @@ Example response: ```json { - "title" : "feature", - "color" : "#5843AD", - "description": "New feature proposal", - "updated_at" : "2015-11-03T21:22:30.737Z", - "template" : false, - "project_id" : 1, - "created_at" : "2015-11-03T21:22:30.737Z", - "id" : 9, - "priority": null + "id" : 1, + "name" : "bug", + "color" : "#d9534f", + "description": "Bug reported by user", + "open_issues_count": 1, + "closed_issues_count": 0, + "open_merge_requests_count": 1, + "subscribed": false, + "priority": null } ``` @@ -178,13 +185,15 @@ Example response: ```json { - "color" : "#8E44AD", - "name" : "docs", - "description": "Documentation", - "open_issues_count": 1, - "closed_issues_count": 0, - "open_merge_requests_count": 1, - "priority": null + "id" : 8, + "name" : "docs", + "color" : "#8E44AD", + "description": "Documentation", + "open_issues_count": 1, + "closed_issues_count": 0, + "open_merge_requests_count": 2, + "subscribed": false, + "priority": null } ``` @@ -213,14 +222,15 @@ Example response: ```json { - "name": "Docs", - "color": "#cc0033", - "description": "", - "open_issues_count": 0, - "closed_issues_count": 0, - "open_merge_requests_count": 0, - "subscribed": true, - "priority": null + "id" : 1, + "name" : "bug", + "color" : "#d9534f", + "description": "Bug reported by user", + "open_issues_count": 1, + "closed_issues_count": 0, + "open_merge_requests_count": 1, + "subscribed": true, + "priority": null } ``` @@ -249,13 +259,14 @@ Example response: ```json { - "name": "Docs", - "color": "#cc0033", - "description": "", - "open_issues_count": 0, - "closed_issues_count": 0, - "open_merge_requests_count": 0, - "subscribed": false, - "priority": null + "id" : 1, + "name" : "bug", + "color" : "#d9534f", + "description": "Bug reported by user", + "open_issues_count": 1, + "closed_issues_count": 0, + "open_merge_requests_count": 1, + "subscribed": false, + "priority": null } ``` diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 9dd36ec969e..1942aeea656 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -433,7 +433,7 @@ module API end class LabelBasic < Grape::Entity - expose :name, :color, :description + expose :id, :name, :color, :description end class Label < LabelBasic diff --git a/spec/requests/api/labels_spec.rb b/spec/requests/api/labels_spec.rb index 7e532912d08..2ff90b6deac 100644 --- a/spec/requests/api/labels_spec.rb +++ b/spec/requests/api/labels_spec.rb @@ -17,12 +17,18 @@ describe API::API, api: true do group = create(:group) group_label = create(:group_label, group: group) project.update(group: group) + expected_keys = [ + 'id', 'name', 'color', 'description', + 'open_issues_count', 'closed_issues_count', 'open_merge_requests_count', + 'subscribed', 'priority' + ] get api("/projects/#{project.id}/labels", user) expect(response).to have_http_status(200) expect(json_response).to be_an Array expect(json_response.size).to eq(3) + expect(json_response.first.keys).to match_array expected_keys expect(json_response.map { |l| l['name'] }).to match_array([group_label.name, priority_label.name, label1.name]) expect(json_response.last['name']).to eq(label1.name) expect(json_response.last['color']).to be_present From 314ef630148d55742ac6835c8a903190e88573d9 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 7 Nov 2016 16:13:31 +0200 Subject: [PATCH 139/175] Fix project index Signed-off-by: Dmitriy Zaporozhets --- app/controllers/projects_controller.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 6988527a3be..8cd50480ec1 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -2,9 +2,9 @@ class ProjectsController < Projects::ApplicationController include IssuableCollections include ExtractsPath - before_action :authenticate_user!, except: [:show, :activity, :refs] - before_action :project, except: [:new, :create] - before_action :repository, except: [:new, :create] + before_action :authenticate_user!, except: [:index, :show, :activity, :refs] + before_action :project, except: [:index, :new, :create] + before_action :repository, except: [:index, :new, :create] before_action :assign_ref_vars, only: [:show], if: :repo_exists? before_action :tree, only: [:show], if: [:repo_exists?, :project_view_files?] From 591e18364a82fc8a9a906310e37566c05ad4f4ab Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 3 Nov 2016 13:01:23 +0200 Subject: [PATCH 140/175] Add tests for project#index routing Signed-off-by: Dmitriy Zaporozhets --- spec/controllers/projects_controller_spec.rb | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb index 8eefa284ba0..a302d1c57f4 100644 --- a/spec/controllers/projects_controller_spec.rb +++ b/spec/controllers/projects_controller_spec.rb @@ -7,6 +7,26 @@ describe ProjectsController do let(:jpg) { fixture_file_upload(Rails.root + 'spec/fixtures/rails_sample.jpg', 'image/jpg') } let(:txt) { fixture_file_upload(Rails.root + 'spec/fixtures/doc_sample.txt', 'text/plain') } + describe 'GET index' do + context 'as a user' do + it 'redirects to root page' do + sign_in(user) + + get :index + + expect(response).to redirect_to(root_path) + end + end + + context 'as a guest' do + it 'redirects to Explore page' do + get :index + + expect(response).to redirect_to(explore_root_path) + end + end + end + describe "GET show" do context "user not project member" do before { sign_in(user) } From e6e4147880e831cdc6cc9ef31774297222f654c3 Mon Sep 17 00:00:00 2001 From: Lisanne Fellinger Date: Thu, 27 Oct 2016 22:08:20 +0200 Subject: [PATCH 141/175] Rewritten spinach git_blame tests to rspec feature tests Fixing rubocop violations Relocated git_blame spec and fixed styling issue Rewritten spinach git_blame tests to rspec feature tests Fixing rubocop violations Relocated git_blame spec and fixed styling issue Rewritten spinach git_blame tests to rspec feature tests Fixing rubocop violations Rewritten spinach git_blame tests to rspec feature tests Fixing rubocop violations Rewritten spinach git_blame tests to rspec feature tests Fixing rubocop violations Relocated git_blame spec and fixed styling issue --- ...spinach-tests-with-rspec-feature-tests.yml | 4 ++++ features/project/source/git_blame.feature | 10 --------- features/steps/project/source/git_blame.rb | 19 ----------------- .../projects/files/browse_files_spec.rb | 21 +++++++++++++++++++ 4 files changed, 25 insertions(+), 29 deletions(-) create mode 100644 changelogs/unreleased/23036-replace-git-blame-spinach-tests-with-rspec-feature-tests.yml delete mode 100644 features/project/source/git_blame.feature delete mode 100644 features/steps/project/source/git_blame.rb create mode 100644 spec/features/projects/files/browse_files_spec.rb diff --git a/changelogs/unreleased/23036-replace-git-blame-spinach-tests-with-rspec-feature-tests.yml b/changelogs/unreleased/23036-replace-git-blame-spinach-tests-with-rspec-feature-tests.yml new file mode 100644 index 00000000000..7b54d3df56d --- /dev/null +++ b/changelogs/unreleased/23036-replace-git-blame-spinach-tests-with-rspec-feature-tests.yml @@ -0,0 +1,4 @@ +--- +title: Rewrite git blame spinach feature tests to rspec feature tests +merge_request: 7197 +author: Lisanne Fellinger diff --git a/features/project/source/git_blame.feature b/features/project/source/git_blame.feature deleted file mode 100644 index 48b1077dc6b..00000000000 --- a/features/project/source/git_blame.feature +++ /dev/null @@ -1,10 +0,0 @@ -Feature: Project Source Git Blame - Background: - Given I sign in as a user - And I own project "Shop" - Given I visit project source page - - Scenario: I blame file - Given I click on ".gitignore" file in repo - And I click Blame button - Then I should see git file blame diff --git a/features/steps/project/source/git_blame.rb b/features/steps/project/source/git_blame.rb deleted file mode 100644 index d0a27f47e2a..00000000000 --- a/features/steps/project/source/git_blame.rb +++ /dev/null @@ -1,19 +0,0 @@ -class Spinach::Features::ProjectSourceGitBlame < Spinach::FeatureSteps - include SharedAuthentication - include SharedProject - include SharedPaths - - step 'I click on ".gitignore" file in repo' do - click_link ".gitignore" - end - - step 'I click Blame button' do - click_link 'Blame' - end - - step 'I should see git file blame' do - expect(page).to have_content "*.rb" - expect(page).to have_content "Dmitriy Zaporozhets" - expect(page).to have_content "Initial commit" - end -end diff --git a/spec/features/projects/files/browse_files_spec.rb b/spec/features/projects/files/browse_files_spec.rb new file mode 100644 index 00000000000..69295e450d0 --- /dev/null +++ b/spec/features/projects/files/browse_files_spec.rb @@ -0,0 +1,21 @@ +require 'spec_helper' + +feature 'user checks git blame', feature: true do + let(:project) { create(:project) } + let(:user) { create(:user) } + + before do + project.team << [user, :master] + login_with(user) + visit namespace_project_tree_path(project.namespace, project, project.default_branch) + end + + scenario "can see blame of '.gitignore'" do + click_link ".gitignore" + click_link 'Blame' + + expect(page).to have_content "*.rb" + expect(page).to have_content "Dmitriy Zaporozhets" + expect(page).to have_content "Initial commit" + end +end From 8357ae980a396cb0aa57ecd182a36c43821b548e Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 7 Nov 2016 16:20:06 +0200 Subject: [PATCH 142/175] Fix 404 when visit /projects page Signed-off-by: Dmitriy Zaporozhets --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ed09fb1db8..5b072ce9f60 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -71,6 +71,7 @@ entry. - Fix applying GitHub-imported labels when importing job is interrupted - Allow to search for user by secondary email address in the admin interface(/admin/users) !7115 (YarNayar) - Updated commit SHA styling on the branches page. +- Fix 404 when visit /projects page ## 8.13.3 (2016-11-02) From 41990128a33c268f3af2db80f4ac224802ac8b76 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 7 Nov 2016 17:14:34 +0200 Subject: [PATCH 143/175] Refactor project routing * split on multiple files * improve routing order Signed-off-by: Dmitriy Zaporozhets --- config/initializers/routing_draw.rb | 7 ++ config/routes.rb | 6 - config/routes/git_http.rb | 37 ++++++ config/routes/project.rb | 183 +--------------------------- config/routes/repository.rb | 110 +++++++++++++++++ config/routes/wiki.rb | 16 +++ 6 files changed, 176 insertions(+), 183 deletions(-) create mode 100644 config/initializers/routing_draw.rb create mode 100644 config/routes/git_http.rb create mode 100644 config/routes/repository.rb create mode 100644 config/routes/wiki.rb diff --git a/config/initializers/routing_draw.rb b/config/initializers/routing_draw.rb new file mode 100644 index 00000000000..25003cf0239 --- /dev/null +++ b/config/initializers/routing_draw.rb @@ -0,0 +1,7 @@ +# Adds draw method into Rails routing +# It allows us to keep routing splitted into files +class ActionDispatch::Routing::Mapper + def draw(routes_name) + instance_eval(File.read(Rails.root.join("config/routes/#{routes_name}.rb"))) + end +end diff --git a/config/routes.rb b/config/routes.rb index 659ea51bc75..7bf6c03e69b 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -2,12 +2,6 @@ require 'sidekiq/web' require 'sidekiq/cron/web' require 'api/api' -class ActionDispatch::Routing::Mapper - def draw(routes_name) - instance_eval(File.read(Rails.root.join("config/routes/#{routes_name}.rb"))) - end -end - Rails.application.routes.draw do concern :access_requestable do post :request_access, on: :collection diff --git a/config/routes/git_http.rb b/config/routes/git_http.rb new file mode 100644 index 00000000000..03adc4815f3 --- /dev/null +++ b/config/routes/git_http.rb @@ -0,0 +1,37 @@ +scope constraints: { id: /.+\.git/, format: nil } do + # Git HTTP clients ('git clone' etc.) + get '/info/refs', to: 'git_http#info_refs' + post '/git-upload-pack', to: 'git_http#git_upload_pack' + post '/git-receive-pack', to: 'git_http#git_receive_pack' + + # Git LFS API (metadata) + post '/info/lfs/objects/batch', to: 'lfs_api#batch' + post '/info/lfs/objects', to: 'lfs_api#deprecated' + get '/info/lfs/objects/*oid', to: 'lfs_api#deprecated' + + # GitLab LFS object storage + scope constraints: { oid: /[a-f0-9]{64}/ } do + get '/gitlab-lfs/objects/*oid', to: 'lfs_storage#download' + + scope constraints: { size: /[0-9]+/ } do + put '/gitlab-lfs/objects/*oid/*size/authorize', to: 'lfs_storage#upload_authorize' + put '/gitlab-lfs/objects/*oid/*size', to: 'lfs_storage#upload_finalize' + end + end +end + +# Allow /info/refs, /info/refs?service=git-upload-pack, and +# /info/refs?service=git-receive-pack, but nothing else. +# +git_http_handshake = lambda do |request| + request.query_string.blank? || + request.query_string.match(/\Aservice=git-(upload|receive)-pack\z/) +end + +ref_redirect = redirect do |params, request| + path = "#{params[:namespace_id]}/#{params[:project_id]}.git/info/refs" + path << "?#{request.query_string}" unless request.query_string.blank? + path +end + +get '/info/refs', constraints: git_http_handshake, to: ref_redirect diff --git a/config/routes/project.rb b/config/routes/project.rb index 8142e231621..2f4a56ae5c9 100644 --- a/config/routes/project.rb +++ b/config/routes/project.rb @@ -21,149 +21,13 @@ resources :namespaces, path: '/', constraints: { id: /[a-zA-Z.0-9_\-]+/ }, only: end scope module: :projects do - scope constraints: { id: /.+\.git/, format: nil } do - # Git HTTP clients ('git clone' etc.) - get '/info/refs', to: 'git_http#info_refs' - post '/git-upload-pack', to: 'git_http#git_upload_pack' - post '/git-receive-pack', to: 'git_http#git_receive_pack' - - # Git LFS API (metadata) - post '/info/lfs/objects/batch', to: 'lfs_api#batch' - post '/info/lfs/objects', to: 'lfs_api#deprecated' - get '/info/lfs/objects/*oid', to: 'lfs_api#deprecated' - - # GitLab LFS object storage - scope constraints: { oid: /[a-f0-9]{64}/ } do - get '/gitlab-lfs/objects/*oid', to: 'lfs_storage#download' - - scope constraints: { size: /[0-9]+/ } do - put '/gitlab-lfs/objects/*oid/*size/authorize', to: 'lfs_storage#upload_authorize' - put '/gitlab-lfs/objects/*oid/*size', to: 'lfs_storage#upload_finalize' - end - end - end - - # Allow /info/refs, /info/refs?service=git-upload-pack, and - # /info/refs?service=git-receive-pack, but nothing else. - # - git_http_handshake = lambda do |request| - request.query_string.blank? || - request.query_string.match(/\Aservice=git-(upload|receive)-pack\z/) - end - - ref_redirect = redirect do |params, request| - path = "#{params[:namespace_id]}/#{params[:project_id]}.git/info/refs" - path << "?#{request.query_string}" unless request.query_string.blank? - path - end - - get '/info/refs', constraints: git_http_handshake, to: ref_redirect - - # Blob routes: - get '/new/*id', to: 'blob#new', constraints: { id: /.+/ }, as: 'new_blob' - post '/create/*id', to: 'blob#create', constraints: { id: /.+/ }, as: 'create_blob' - get '/edit/*id', to: 'blob#edit', constraints: { id: /.+/ }, as: 'edit_blob' - put '/update/*id', to: 'blob#update', constraints: { id: /.+/ }, as: 'update_blob' - post '/preview/*id', to: 'blob#preview', constraints: { id: /.+/ }, as: 'preview_blob' + draw :git_http # # Templates # get '/templates/:template_type/:key' => 'templates#show', as: :template - scope do - get( - '/blob/*id/diff', - to: 'blob#diff', - constraints: { id: /.+/, format: false }, - as: :blob_diff - ) - get( - '/blob/*id', - to: 'blob#show', - constraints: { id: /.+/, format: false }, - as: :blob - ) - delete( - '/blob/*id', - to: 'blob#destroy', - constraints: { id: /.+/, format: false } - ) - put( - '/blob/*id', - to: 'blob#update', - constraints: { id: /.+/, format: false } - ) - post( - '/blob/*id', - to: 'blob#create', - constraints: { id: /.+/, format: false } - ) - end - - scope do - get( - '/raw/*id', - to: 'raw#show', - constraints: { id: /.+/, format: /(html|js)/ }, - as: :raw - ) - end - - scope do - get( - '/tree/*id', - to: 'tree#show', - constraints: { id: /.+/, format: /(html|js)/ }, - as: :tree - ) - end - - scope do - get( - '/find_file/*id', - to: 'find_file#show', - constraints: { id: /.+/, format: /html/ }, - as: :find_file - ) - end - - scope do - get( - '/files/*id', - to: 'find_file#list', - constraints: { id: /(?:[^.]|\.(?!json$))+/, format: /json/ }, - as: :files - ) - end - - scope do - post( - '/create_dir/*id', - to: 'tree#create_dir', - constraints: { id: /.+/ }, - as: 'create_dir' - ) - end - - scope do - get( - '/blame/*id', - to: 'blame#show', - constraints: { id: /.+/, format: /(html|js)/ }, - as: :blame - ) - end - - scope do - get( - '/commits/*id', - to: 'commits#show', - constraints: { id: /.+/, format: false }, - as: :commits - ) - end - resource :avatar, only: [:show, :destroy] resources :commit, only: [:show], constraints: { id: /\h{7,40}/ } do member do @@ -206,29 +70,6 @@ resources :namespaces, path: '/', constraints: { id: /[a-zA-Z.0-9_\-]+/ }, only: end end - WIKI_SLUG_ID = { id: /\S+/ } unless defined? WIKI_SLUG_ID - - scope do - # Order matters to give priority to these matches - get '/wikis/git_access', to: 'wikis#git_access' - get '/wikis/pages', to: 'wikis#pages', as: 'wiki_pages' - post '/wikis', to: 'wikis#create' - - get '/wikis/*id/history', to: 'wikis#history', as: 'wiki_history', constraints: WIKI_SLUG_ID - get '/wikis/*id/edit', to: 'wikis#edit', as: 'wiki_edit', constraints: WIKI_SLUG_ID - - get '/wikis/*id', to: 'wikis#show', as: 'wiki', constraints: WIKI_SLUG_ID - delete '/wikis/*id', to: 'wikis#destroy', constraints: WIKI_SLUG_ID - put '/wikis/*id', to: 'wikis#update', constraints: WIKI_SLUG_ID - post '/wikis/*id/preview_markdown', to: 'wikis#preview_markdown', constraints: WIKI_SLUG_ID, as: 'wiki_preview_markdown' - end - - resource :repository, only: [:create] do - member do - get 'archive', constraints: { format: Gitlab::Regex.archive_formats_regex } - end - end - resources :services, constraints: { id: /[^\/]+/ }, only: [:index, :edit, :update] do member do get :test @@ -245,23 +86,6 @@ resources :namespaces, path: '/', constraints: { id: /[a-zA-Z.0-9_\-]+/ }, only: resources :forks, only: [:index, :new, :create] resource :import, only: [:new, :create, :show] - resources :refs, only: [] do - collection do - get 'switch' - end - - member do - # tree viewer logs - get 'logs_tree', constraints: { id: Gitlab::Regex.git_reference_regex } - # Directories with leading dots erroneously get rejected if git - # ref regex used in constraints. Regex verification now done in controller. - get 'logs_tree/*path' => 'refs#logs_tree', as: :logs_file, constraints: { - id: /.*/, - path: /.*/ - } - end - end - resources :merge_requests, concerns: :awardable, constraints: { id: /\d+/ } do member do get :commits @@ -467,6 +291,11 @@ resources :namespaces, path: '/', constraints: { id: /[a-zA-Z.0-9_\-]+/ }, only: end end end + + # Since both wiki and repository routing contains wildcard characters + # its preferable to keep it below all other project routes + draw :wiki + draw :repository end end end diff --git a/config/routes/repository.rb b/config/routes/repository.rb new file mode 100644 index 00000000000..76dcf113aea --- /dev/null +++ b/config/routes/repository.rb @@ -0,0 +1,110 @@ +# All routing related to repositoty browsing + +resource :repository, only: [:create] do + member do + get 'archive', constraints: { format: Gitlab::Regex.archive_formats_regex } + end +end + +resources :refs, only: [] do + collection do + get 'switch' + end + + member do + # tree viewer logs + get 'logs_tree', constraints: { id: Gitlab::Regex.git_reference_regex } + # Directories with leading dots erroneously get rejected if git + # ref regex used in constraints. Regex verification now done in controller. + get 'logs_tree/*path' => 'refs#logs_tree', as: :logs_file, constraints: { + id: /.*/, + path: /.*/ + } + end +end + +get '/new/*id', to: 'blob#new', constraints: { id: /.+/ }, as: 'new_blob' +post '/create/*id', to: 'blob#create', constraints: { id: /.+/ }, as: 'create_blob' +get '/edit/*id', to: 'blob#edit', constraints: { id: /.+/ }, as: 'edit_blob' +put '/update/*id', to: 'blob#update', constraints: { id: /.+/ }, as: 'update_blob' +post '/preview/*id', to: 'blob#preview', constraints: { id: /.+/ }, as: 'preview_blob' + +scope do + get( + '/blob/*id/diff', + to: 'blob#diff', + constraints: { id: /.+/, format: false }, + as: :blob_diff + ) + get( + '/blob/*id', + to: 'blob#show', + constraints: { id: /.+/, format: false }, + as: :blob + ) + delete( + '/blob/*id', + to: 'blob#destroy', + constraints: { id: /.+/, format: false } + ) + put( + '/blob/*id', + to: 'blob#update', + constraints: { id: /.+/, format: false } + ) + post( + '/blob/*id', + to: 'blob#create', + constraints: { id: /.+/, format: false } + ) + + get( + '/raw/*id', + to: 'raw#show', + constraints: { id: /.+/, format: /(html|js)/ }, + as: :raw + ) + + get( + '/tree/*id', + to: 'tree#show', + constraints: { id: /.+/, format: /(html|js)/ }, + as: :tree + ) + + get( + '/find_file/*id', + to: 'find_file#show', + constraints: { id: /.+/, format: /html/ }, + as: :find_file + ) + + get( + '/files/*id', + to: 'find_file#list', + constraints: { id: /(?:[^.]|\.(?!json$))+/, format: /json/ }, + as: :files + ) + + post( + '/create_dir/*id', + to: 'tree#create_dir', + constraints: { id: /.+/ }, + as: 'create_dir' + ) + + get( + '/blame/*id', + to: 'blame#show', + constraints: { id: /.+/, format: /(html|js)/ }, + as: :blame + ) + + # File/dir history + get( + '/commits/*id', + to: 'commits#show', + constraints: { id: /.+/, format: false }, + as: :commits + ) +end diff --git a/config/routes/wiki.rb b/config/routes/wiki.rb new file mode 100644 index 00000000000..ecd4d395d66 --- /dev/null +++ b/config/routes/wiki.rb @@ -0,0 +1,16 @@ +WIKI_SLUG_ID = { id: /\S+/ } unless defined? WIKI_SLUG_ID + +scope do + # Order matters to give priority to these matches + get '/wikis/git_access', to: 'wikis#git_access' + get '/wikis/pages', to: 'wikis#pages', as: 'wiki_pages' + post '/wikis', to: 'wikis#create' + + get '/wikis/*id/history', to: 'wikis#history', as: 'wiki_history', constraints: WIKI_SLUG_ID + get '/wikis/*id/edit', to: 'wikis#edit', as: 'wiki_edit', constraints: WIKI_SLUG_ID + + get '/wikis/*id', to: 'wikis#show', as: 'wiki', constraints: WIKI_SLUG_ID + delete '/wikis/*id', to: 'wikis#destroy', constraints: WIKI_SLUG_ID + put '/wikis/*id', to: 'wikis#update', constraints: WIKI_SLUG_ID + post '/wikis/*id/preview_markdown', to: 'wikis#preview_markdown', constraints: WIKI_SLUG_ID, as: 'wiki_preview_markdown' +end From 16b0723a7ce709437084c12647e59b3a73479ddf Mon Sep 17 00:00:00 2001 From: Chris Wright Date: Tue, 30 Aug 2016 21:44:30 +0100 Subject: [PATCH 144/175] Use the Gitlab Workhorse HTTP header in the admin dashboard MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- app/helpers/components_helper.rb | 9 ++++++++ app/views/admin/dashboard/index.html.haml | 2 +- ...ect-workhorse-version-number-displayed.yml | 4 ++++ spec/helpers/components_helper_spec.rb | 21 +++++++++++++++++++ 4 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 app/helpers/components_helper.rb create mode 100644 changelogs/unreleased/21664-incorrect-workhorse-version-number-displayed.yml create mode 100644 spec/helpers/components_helper_spec.rb diff --git a/app/helpers/components_helper.rb b/app/helpers/components_helper.rb new file mode 100644 index 00000000000..8893209b314 --- /dev/null +++ b/app/helpers/components_helper.rb @@ -0,0 +1,9 @@ +module ComponentsHelper + def gitlab_workhorse_version + if request.headers['Gitlab-Workhorse'].present? + request.headers['Gitlab-Workhorse'].split('-').first + else + Gitlab::Workhorse.version + end + end +end diff --git a/app/views/admin/dashboard/index.html.haml b/app/views/admin/dashboard/index.html.haml index 90798c47d97..1db2150f336 100644 --- a/app/views/admin/dashboard/index.html.haml +++ b/app/views/admin/dashboard/index.html.haml @@ -87,7 +87,7 @@ %p GitLab Workhorse %span.pull-right - = Gitlab::Workhorse.version + = gitlab_workhorse_version %p GitLab API %span.pull-right diff --git a/changelogs/unreleased/21664-incorrect-workhorse-version-number-displayed.yml b/changelogs/unreleased/21664-incorrect-workhorse-version-number-displayed.yml new file mode 100644 index 00000000000..95d8fef1099 --- /dev/null +++ b/changelogs/unreleased/21664-incorrect-workhorse-version-number-displayed.yml @@ -0,0 +1,4 @@ +--- +title: Use the Gitlab Workhorse HTTP header in the admin dashboard +merge_request: +author: Chris Wright diff --git a/spec/helpers/components_helper_spec.rb b/spec/helpers/components_helper_spec.rb new file mode 100644 index 00000000000..94a59193be8 --- /dev/null +++ b/spec/helpers/components_helper_spec.rb @@ -0,0 +1,21 @@ +require 'spec_helper' + +describe ComponentsHelper do + describe '#gitlab_workhorse_version' do + context 'without a Gitlab-Workhorse header' do + it 'shows the version from Gitlab::Workhorse.version' do + expect(helper.gitlab_workhorse_version).to eq Gitlab::Workhorse.version + end + end + + context 'with a Gitlab-Workhorse header' do + before do + helper.request.headers['Gitlab-Workhorse'] = '42.42.0-rc3' + end + + it 'shows the actual GitLab Workhorse version currently in use' do + expect(helper.gitlab_workhorse_version).to eq '42.42.0' + end + end + end +end From 9d51421346178c9189ffb47189f51d573ab42822 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Fri, 19 Aug 2016 18:33:46 -0500 Subject: [PATCH 145/175] Use separate email-friendly token for incoming email and let incoming email token be reset --- app/controllers/profiles_controller.rb | 10 +++++- app/models/concerns/token_authenticatable.rb | 10 ++++-- app/models/project.rb | 11 +++--- app/models/user.rb | 12 ++++++- app/views/profiles/accounts/show.html.haml | 35 +++++++++++-------- config/routes/profile.rb | 1 + ...32256_add_incoming_email_token_to_users.rb | 16 +++++++++ db/schema.rb | 4 ++- .../email/handler/create_issue_handler.rb | 8 ++--- spec/features/projects/issues/issues_spec.rb | 0 ...ken.eml => wrong_incoming_email_token.eml} | 0 .../handler/create_issue_handler_spec.rb | 6 ++-- 12 files changed, 79 insertions(+), 34 deletions(-) create mode 100644 db/migrate/20160819232256_add_incoming_email_token_to_users.rb create mode 100644 spec/features/projects/issues/issues_spec.rb rename spec/fixtures/emails/{wrong_authentication_token.eml => wrong_incoming_email_token.eml} (100%) diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb index f71e0a1302b..e4865642cd3 100644 --- a/app/controllers/profiles_controller.rb +++ b/app/controllers/profiles_controller.rb @@ -26,7 +26,15 @@ class ProfilesController < Profiles::ApplicationController def reset_private_token if current_user.reset_authentication_token! - flash[:notice] = "Token was successfully updated" + flash[:notice] = "Private token was successfully updated" + end + + redirect_to profile_account_path + end + + def reset_incoming_email_token + if current_user.reset_incoming_email_token! + flash[:notice] = "Incoming email token was successfully updated" end redirect_to profile_account_path diff --git a/app/models/concerns/token_authenticatable.rb b/app/models/concerns/token_authenticatable.rb index 24c7b26d223..04d30f46210 100644 --- a/app/models/concerns/token_authenticatable.rb +++ b/app/models/concerns/token_authenticatable.rb @@ -4,17 +4,21 @@ module TokenAuthenticatable private def write_new_token(token_field) - new_token = generate_token(token_field) + new_token = generate_available_token(token_field) write_attribute(token_field, new_token) end - def generate_token(token_field) + def generate_available_token(token_field) loop do - token = Devise.friendly_token + token = generate_token(token_field) break token unless self.class.unscoped.find_by(token_field => token) end end + def generate_token(token_field) + Devise.friendly_token + end + class_methods do def authentication_token_fields @token_fields || [] diff --git a/app/models/project.rb b/app/models/project.rb index 686d285410b..56b84b0aebb 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -624,13 +624,12 @@ class Project < ActiveRecord::Base end def new_issue_address(author) - # This feature is disabled for the time being. - return nil + return unless Gitlab::IncomingEmail.enabled? && author - if Gitlab::IncomingEmail.enabled? && author # rubocop:disable Lint/UnreachableCode - Gitlab::IncomingEmail.reply_address( - "#{path_with_namespace}+#{author.authentication_token}") - end + author.ensure_incoming_email_token! + + Gitlab::IncomingEmail.reply_address( + "#{path_with_namespace}+#{author.incoming_email_token}") end def build_commit_note(commit) diff --git a/app/models/user.rb b/app/models/user.rb index 65e96ee6b2e..9a3619b0bc3 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -13,6 +13,7 @@ class User < ActiveRecord::Base DEFAULT_NOTIFICATION_LEVEL = :participating add_authentication_token_field :authentication_token + add_authentication_token_field :incoming_email_token default_value_for :admin, false default_value_for(:external) { current_application_settings.user_default_external } @@ -119,7 +120,7 @@ class User < ActiveRecord::Base before_validation :set_public_email, if: ->(user) { user.public_email_changed? } after_update :update_emails_with_primary_email, if: ->(user) { user.email_changed? } - before_save :ensure_authentication_token + before_save :ensure_authentication_token, :ensure_incoming_email_token before_save :ensure_external_user_rights after_save :ensure_namespace_correct after_initialize :set_projects_limit @@ -946,4 +947,13 @@ class User < ActiveRecord::Base signup_domain =~ regexp end end + + def generate_token(token_field) + if token_field == :incoming_email_token + # Needs to be all lowercase and alphanumeric because it's gonna be used in an email address. + SecureRandom.hex + else + super + end + end end diff --git a/app/views/profiles/accounts/show.html.haml b/app/views/profiles/accounts/show.html.haml index e2e974ba072..2c256b1b233 100644 --- a/app/views/profiles/accounts/show.html.haml +++ b/app/views/profiles/accounts/show.html.haml @@ -8,24 +8,29 @@ .row.prepend-top-default .col-lg-3.profile-settings-sidebar %h4.prepend-top-0 - Private Token + Private Tokens %p - Your private token is used to access application resources without authentication. + Your private token is used to access the API and Atom feeds without + username/password authentication. + %p + Your incoming email token is used to create new issues by email, and is + included in your project-specific email addresses. .col-lg-9 - = form_for @user, url: reset_private_token_profile_path, method: :put, html: { class: "private-token" } do |f| - %p.cgray - - if current_user.private_token - = label_tag "token", "Private token", class: "label-light" - = text_field_tag "token", current_user.private_token, class: "form-control" - - else - %span You don`t have one yet. Click generate to fix it. + %p.cgray + - if current_user.private_token + = label_tag "token", "Private token", class: "label-light" + = text_field_tag "token", current_user.private_token, class: "form-control" + - else + %span You don`t have one yet. Click generate to fix it. %p.help-block - It can be used for atom feeds or the API. Keep it secret! - .prepend-top-default - - if current_user.private_token - = f.submit 'Reset private token', data: { confirm: "Are you sure?" }, class: "btn btn-default" - - else - = f.submit 'Generate', class: "btn btn-default" + Keep this token secret, anyone with access to it can interact with the GitLab API as if they were you. + .prepend-top-default + - if current_user.private_token + = link_to 'Reset private token', reset_private_token_profile_path, method: :put, data: { confirm: "Are you sure?" }, class: "btn btn-default" + - else + = f.submit 'Generate', class: "btn btn-default" + = link_to 'Reset incoming email token', reset_incoming_email_token_profile_path, method: :put, data: { confirm: "Are you sure?" }, class: "btn btn-default" + %hr .row.prepend-top-default .col-lg-3.profile-settings-sidebar diff --git a/config/routes/profile.rb b/config/routes/profile.rb index 4cb68c9b34a..52b9a565db8 100644 --- a/config/routes/profile.rb +++ b/config/routes/profile.rb @@ -4,6 +4,7 @@ resource :profile, only: [:show, :update] do get :applications, to: 'oauth/applications#index' put :reset_private_token + put :reset_incoming_email_token put :update_username end diff --git a/db/migrate/20160819232256_add_incoming_email_token_to_users.rb b/db/migrate/20160819232256_add_incoming_email_token_to_users.rb new file mode 100644 index 00000000000..f2cf956adc9 --- /dev/null +++ b/db/migrate/20160819232256_add_incoming_email_token_to_users.rb @@ -0,0 +1,16 @@ +# See http://doc.gitlab.com/ce/development/migration_style_guide.html +# for more information on how to write migrations for GitLab. + +class AddIncomingEmailTokenToUsers < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + # Set this constant to true if this migration requires downtime. + DOWNTIME = false + + disable_ddl_transaction! + + def change + add_column :users, :incoming_email_token, :string + add_concurrent_index :users, :incoming_email_token + end +end diff --git a/db/schema.rb b/db/schema.rb index 5476b0c93e5..fd82fb326a6 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20161103171205) do +ActiveRecord::Schema.define(version: 20160819232256) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -1176,6 +1176,7 @@ ActiveRecord::Schema.define(version: 20161103171205) do t.boolean "ldap_email", default: false, null: false t.boolean "external", default: false t.string "organization" + t.string "incoming_email_token" end add_index "users", ["admin"], name: "index_users_on_admin", using: :btree @@ -1185,6 +1186,7 @@ ActiveRecord::Schema.define(version: 20161103171205) do add_index "users", ["current_sign_in_at"], name: "index_users_on_current_sign_in_at", using: :btree add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree add_index "users", ["email"], name: "index_users_on_email_trigram", using: :gin, opclasses: {"email"=>"gin_trgm_ops"} + add_index "users", ["incoming_email_token"], name: "index_users_on_incoming_email_token", using: :btree add_index "users", ["name"], name: "index_users_on_name", using: :btree add_index "users", ["name"], name: "index_users_on_name_trigram", using: :gin, opclasses: {"name"=>"gin_trgm_ops"} add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree diff --git a/lib/gitlab/email/handler/create_issue_handler.rb b/lib/gitlab/email/handler/create_issue_handler.rb index 4e6566af8ab..9f90a3ec2b2 100644 --- a/lib/gitlab/email/handler/create_issue_handler.rb +++ b/lib/gitlab/email/handler/create_issue_handler.rb @@ -5,16 +5,16 @@ module Gitlab module Email module Handler class CreateIssueHandler < BaseHandler - attr_reader :project_path, :authentication_token + attr_reader :project_path, :incoming_email_token def initialize(mail, mail_key) super(mail, mail_key) - @project_path, @authentication_token = + @project_path, @incoming_email_token = mail_key && mail_key.split('+', 2) end def can_handle? - !authentication_token.nil? + !incoming_email_token.nil? end def execute @@ -29,7 +29,7 @@ module Gitlab end def author - @author ||= User.find_by(authentication_token: authentication_token) + @author ||= User.find_by(incoming_email_token: incoming_email_token) end def project diff --git a/spec/features/projects/issues/issues_spec.rb b/spec/features/projects/issues/issues_spec.rb new file mode 100644 index 00000000000..e69de29bb2d diff --git a/spec/fixtures/emails/wrong_authentication_token.eml b/spec/fixtures/emails/wrong_incoming_email_token.eml similarity index 100% rename from spec/fixtures/emails/wrong_authentication_token.eml rename to spec/fixtures/emails/wrong_incoming_email_token.eml diff --git a/spec/lib/gitlab/email/handler/create_issue_handler_spec.rb b/spec/lib/gitlab/email/handler/create_issue_handler_spec.rb index a5cc7b02936..939189a3bc0 100644 --- a/spec/lib/gitlab/email/handler/create_issue_handler_spec.rb +++ b/spec/lib/gitlab/email/handler/create_issue_handler_spec.rb @@ -18,7 +18,7 @@ xdescribe Gitlab::Email::Handler::CreateIssueHandler, lib: true do create( :user, email: 'jake@adventuretime.ooo', - authentication_token: 'auth_token' + incoming_email_token: 'auth_token' ) end @@ -60,8 +60,8 @@ xdescribe Gitlab::Email::Handler::CreateIssueHandler, lib: true do end end - context "when we can't find the authentication_token" do - let(:email_raw) { fixture_file("emails/wrong_authentication_token.eml") } + context "when we can't find the incoming_email_token" do + let(:email_raw) { fixture_file("emails/wrong_incoming_email_token.eml") } it "raises an UserNotFoundError" do expect { receiver.execute }.to raise_error(Gitlab::Email::UserNotFoundError) From 011e561bfa227f3ecbafe5b1ffd51700c680a15f Mon Sep 17 00:00:00 2001 From: tiagonbotelho Date: Tue, 18 Oct 2016 19:03:31 +0100 Subject: [PATCH 146/175] implements reset incoming email token on issues modal and account page, reactivates all tests and writes more tests for it --- app/assets/javascripts/issuable.js.es6 | 22 +++++++++ app/assets/stylesheets/pages/profile.scss | 4 ++ app/controllers/profiles_controller.rb | 4 +- app/controllers/projects_controller.rb | 7 +++ app/helpers/accounts_helper.rb | 5 ++ app/models/project.rb | 2 +- app/models/user.rb | 2 +- app/views/profiles/accounts/show.html.haml | 49 +++++++++++-------- .../projects/issues/_issue_by_email.html.haml | 21 +++++--- .../use-separate-token-for-incoming-email.yml | 4 ++ config/routes/project.rb | 1 + db/schema.rb | 4 +- features/profile/profile.feature | 5 -- features/steps/profile/profile.rb | 12 ----- lib/gitlab/email/handler.rb | 3 +- lib/gitlab/incoming_email.rb | 12 ++++- spec/controllers/projects_controller_spec.rb | 27 ++++++++++ spec/features/issues_spec.rb | 23 ++++++++- spec/features/profile_spec.rb | 29 +++++++++++ spec/features/projects/issues/issues_spec.rb | 0 .../handler/create_issue_handler_spec.rb | 2 +- spec/models/project_spec.rb | 5 +- 22 files changed, 184 insertions(+), 59 deletions(-) create mode 100644 app/helpers/accounts_helper.rb create mode 100644 changelogs/unreleased/use-separate-token-for-incoming-email.yml delete mode 100644 spec/features/projects/issues/issues_spec.rb diff --git a/app/assets/javascripts/issuable.js.es6 b/app/assets/javascripts/issuable.js.es6 index 8fc498be27d..46503c290ae 100644 --- a/app/assets/javascripts/issuable.js.es6 +++ b/app/assets/javascripts/issuable.js.es6 @@ -10,6 +10,7 @@ Issuable.initSearch(); Issuable.initChecks(); Issuable.initResetFilters(); + Issuable.resetIncomingEmailToken(); return Issuable.initLabelFilterRemove(); }, initTemplates: function() { @@ -154,6 +155,27 @@ this.issuableBulkActions.willUpdateLabels = false; } return true; + }, + + resetIncomingEmailToken: function() { + $('.incoming-email-token-reset').on('click', function(e) { + e.preventDefault(); + + $.ajax({ + type: 'PUT', + url: $('.incoming-email-token-reset').attr('href'), + dataType: 'json', + success: function(response) { + $('#issue_email').val(response.new_issue_address).focus(); + }, + beforeSend: function() { + $('.incoming-email-token-reset').text('resetting...'); + }, + complete: function() { + $('.incoming-email-token-reset').text('reset it'); + } + }); + }); } }; diff --git a/app/assets/stylesheets/pages/profile.scss b/app/assets/stylesheets/pages/profile.scss index ede29db1979..6fab97a71aa 100644 --- a/app/assets/stylesheets/pages/profile.scss +++ b/app/assets/stylesheets/pages/profile.scss @@ -23,6 +23,10 @@ color: $md-link-color; } +.private-tokens-reset div.reset-action:not(:first-child) { + padding-top: 15px; +} + .oauth-buttons { .btn-group { margin-right: 10px; diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb index e4865642cd3..f0c71725ea8 100644 --- a/app/controllers/profiles_controller.rb +++ b/app/controllers/profiles_controller.rb @@ -26,7 +26,7 @@ class ProfilesController < Profiles::ApplicationController def reset_private_token if current_user.reset_authentication_token! - flash[:notice] = "Private token was successfully updated" + flash[:notice] = "Private token was successfully reset" end redirect_to profile_account_path @@ -34,7 +34,7 @@ class ProfilesController < Profiles::ApplicationController def reset_incoming_email_token if current_user.reset_incoming_email_token! - flash[:notice] = "Incoming email token was successfully updated" + flash[:notice] = "Incoming email token was successfully reset" end redirect_to profile_account_path diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 6988527a3be..4d5725448cd 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -160,6 +160,13 @@ class ProjectsController < Projects::ApplicationController end end + def new_issue_address + return render_404 unless Gitlab::IncomingEmail.supports_issue_creation? + + current_user.reset_incoming_email_token! + render json: { new_issue_address: @project.new_issue_address(current_user) } + end + def archive return access_denied! unless can?(current_user, :archive_project, @project) diff --git a/app/helpers/accounts_helper.rb b/app/helpers/accounts_helper.rb new file mode 100644 index 00000000000..5d27d30eaa3 --- /dev/null +++ b/app/helpers/accounts_helper.rb @@ -0,0 +1,5 @@ +module AccountsHelper + def incoming_email_token_enabled? + current_user.incoming_email_token && Gitlab::IncomingEmail.supports_issue_creation? + end +end diff --git a/app/models/project.rb b/app/models/project.rb index 56b84b0aebb..4c9c7c001dd 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -624,7 +624,7 @@ class Project < ActiveRecord::Base end def new_issue_address(author) - return unless Gitlab::IncomingEmail.enabled? && author + return unless Gitlab::IncomingEmail.supports_issue_creation? && author author.ensure_incoming_email_token! diff --git a/app/models/user.rb b/app/models/user.rb index 9a3619b0bc3..d6aeda809da 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -951,7 +951,7 @@ class User < ActiveRecord::Base def generate_token(token_field) if token_field == :incoming_email_token # Needs to be all lowercase and alphanumeric because it's gonna be used in an email address. - SecureRandom.hex + SecureRandom.hex.to_i(16).to_s(36) else super end diff --git a/app/views/profiles/accounts/show.html.haml b/app/views/profiles/accounts/show.html.haml index 2c256b1b233..72f658d1b68 100644 --- a/app/views/profiles/accounts/show.html.haml +++ b/app/views/profiles/accounts/show.html.haml @@ -8,28 +8,35 @@ .row.prepend-top-default .col-lg-3.profile-settings-sidebar %h4.prepend-top-0 - Private Tokens + = incoming_email_token_enabled? ? "Private Tokens" : "Private Token" %p - Your private token is used to access the API and Atom feeds without - username/password authentication. - %p - Your incoming email token is used to create new issues by email, and is - included in your project-specific email addresses. - .col-lg-9 - %p.cgray - - if current_user.private_token - = label_tag "token", "Private token", class: "label-light" - = text_field_tag "token", current_user.private_token, class: "form-control" - - else - %span You don`t have one yet. Click generate to fix it. - %p.help-block - Keep this token secret, anyone with access to it can interact with the GitLab API as if they were you. - .prepend-top-default - - if current_user.private_token - = link_to 'Reset private token', reset_private_token_profile_path, method: :put, data: { confirm: "Are you sure?" }, class: "btn btn-default" - - else - = f.submit 'Generate', class: "btn btn-default" - = link_to 'Reset incoming email token', reset_incoming_email_token_profile_path, method: :put, data: { confirm: "Are you sure?" }, class: "btn btn-default" + Keep + = incoming_email_token_enabled? ? "these tokens" : "this token" + secret, anyone with access to them can interact with GitLab as if they were you. + .col-lg-9.private-tokens-reset + .reset-action + %p.cgray + - if current_user.private_token + = label_tag "private-token", "Private token", class: "label-light" + = text_field_tag "private-token", current_user.private_token, class: "form-control", readonly: true, onclick: "this.select()" + - else + %span You don't have one yet. Click generate to fix it. + %p.help-block + Your private token is used to access the API and Atom feeds without username/password authentication. + .prepend-top-default + - if current_user.private_token + = link_to 'Reset private token', reset_private_token_profile_path, method: :put, data: { confirm: "Are you sure?" }, class: "btn btn-default private-token" + - else + = f.submit 'Generate', class: "btn btn-default" + - if incoming_email_token_enabled? + .reset-action + %p.cgray + = label_tag "incoming-email-token", "Incoming Email Token", class: 'label-light' + = text_field_tag "incoming-email-token", current_user.incoming_email_token, class: "form-control", readonly: true, onclick: "this.select()" + %p.help-block + Your incoming email token is used to create new issues by email, and is included in your project-specific email addresses. + .prepend-top-default + = link_to 'Reset incoming email token', reset_incoming_email_token_profile_path, method: :put, data: { confirm: "Are you sure?" }, class: "btn btn-default incoming-email-token" %hr .row.prepend-top-default diff --git a/app/views/projects/issues/_issue_by_email.html.haml b/app/views/projects/issues/_issue_by_email.html.haml index 72669372497..d2038a2be68 100644 --- a/app/views/projects/issues/_issue_by_email.html.haml +++ b/app/views/projects/issues/_issue_by_email.html.haml @@ -12,16 +12,23 @@ Create new issue by email .modal-body %p - Write an email to the below email address. (This is a private email address, so keep it secret.) + You can create a new issue inside this project by sending an email to the following email address: .email-modal-input-group.input-group = text_field_tag :issue_email, email, class: "monospace js-select-on-focus form-control", readonly: true .input-group-btn = clipboard_button(clipboard_target: '#issue_email') %p - Send an email to this address to create an issue. + The subject will be used as the title of the new issue, and the message will be the description. + + = link_to 'Slash commands', help_page_path('user/project/slash_commands'), target: '_blank', tabindex: -1 + and styling with + = link_to 'Markdown', help_page_path('user/markdown'), target: '_blank', tabindex: -1 + are supported. + %p - Use the subject line as the title of your issue. - %p - Use the message as the body of your issue (feel free to include some nice - = succeed ")." do - = link_to "Markdown", help_page_path('markdown', 'markdown') + This is a private email address, generated just for you. + + Anyone who gets ahold of it can create issues as if they were you. + You should + = link_to 'reset it', new_issue_address_namespace_project_path(@project.namespace, @project), class: 'incoming-email-token-reset' + if that ever happens. diff --git a/changelogs/unreleased/use-separate-token-for-incoming-email.yml b/changelogs/unreleased/use-separate-token-for-incoming-email.yml new file mode 100644 index 00000000000..e498f8dd0a6 --- /dev/null +++ b/changelogs/unreleased/use-separate-token-for-incoming-email.yml @@ -0,0 +1,4 @@ +--- +title: Use separate email-token for incoming email and revert back the inactive feature +merge_request: 5914 +author: diff --git a/config/routes/project.rb b/config/routes/project.rb index 8142e231621..7a1bfa6a9f0 100644 --- a/config/routes/project.rb +++ b/config/routes/project.rb @@ -18,6 +18,7 @@ resources :namespaces, path: '/', constraints: { id: /[a-zA-Z.0-9_\-]+/ }, only: get :autocomplete_sources get :activity get :refs + put :new_issue_address end scope module: :projects do diff --git a/db/schema.rb b/db/schema.rb index fd82fb326a6..a82a26c6623 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20160819232256) do +ActiveRecord::Schema.define(version: 20161103171205) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -1176,7 +1176,7 @@ ActiveRecord::Schema.define(version: 20160819232256) do t.boolean "ldap_email", default: false, null: false t.boolean "external", default: false t.string "organization" - t.string "incoming_email_token" + t.string "incoming_email_token" end add_index "users", ["admin"], name: "index_users_on_admin", using: :btree diff --git a/features/profile/profile.feature b/features/profile/profile.feature index 447dd92a458..dc1339deb4c 100644 --- a/features/profile/profile.feature +++ b/features/profile/profile.feature @@ -59,11 +59,6 @@ Feature: Profile When I unsuccessfully change my password Then I should see a password error message - Scenario: I reset my token - Given I visit profile account page - Then I reset my token - And I should see new token - Scenario: I visit history tab Given I have activity When I visit Audit Log page diff --git a/features/steps/profile/profile.rb b/features/steps/profile/profile.rb index 05ab2a7dc73..ea480d2ad68 100644 --- a/features/steps/profile/profile.rb +++ b/features/steps/profile/profile.rb @@ -104,18 +104,6 @@ class Spinach::Features::Profile < Spinach::FeatureSteps end end - step 'I reset my token' do - page.within '.private-token' do - @old_token = @user.private_token - click_button "Reset private token" - end - end - - step 'I should see new token' do - expect(find("#token").value).not_to eq @old_token - expect(find("#token").value).to eq @user.reload.private_token - end - step 'I have activity' do create(:closed_issue_event, author: current_user) end diff --git a/lib/gitlab/email/handler.rb b/lib/gitlab/email/handler.rb index 5cf9d5ebe28..bd3267e2a80 100644 --- a/lib/gitlab/email/handler.rb +++ b/lib/gitlab/email/handler.rb @@ -4,8 +4,7 @@ require 'gitlab/email/handler/create_issue_handler' module Gitlab module Email module Handler - # The `CreateIssueHandler` feature is disabled for the time being. - HANDLERS = [CreateNoteHandler] + HANDLERS = [CreateNoteHandler, CreateIssueHandler] def self.for(mail, mail_key) HANDLERS.find do |klass| diff --git a/lib/gitlab/incoming_email.rb b/lib/gitlab/incoming_email.rb index d7be50bd437..801dfde9a36 100644 --- a/lib/gitlab/incoming_email.rb +++ b/lib/gitlab/incoming_email.rb @@ -1,5 +1,7 @@ module Gitlab module IncomingEmail + WILDCARD_PLACEHOLDER = '%{key}'.freeze + class << self FALLBACK_MESSAGE_ID_REGEX = /\Areply\-(.+)@#{Gitlab.config.gitlab.host}\Z/.freeze @@ -7,8 +9,16 @@ module Gitlab config.enabled && config.address end + def supports_wildcard? + config.address && config.address.include?(WILDCARD_PLACEHOLDER) + end + + def supports_issue_creation? + enabled? && supports_wildcard? + end + def reply_address(key) - config.address.gsub('%{key}', key) + config.address.gsub(WILDCARD_PLACEHOLDER, key) end def key_from_address(address) diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb index 8eefa284ba0..ca6bf17005c 100644 --- a/spec/controllers/projects_controller_spec.rb +++ b/spec/controllers/projects_controller_spec.rb @@ -264,6 +264,33 @@ describe ProjectsController do end end + describe 'PUT #new_issue_address' do + subject do + put :new_issue_address, + namespace_id: project.namespace.to_param, + id: project.to_param + user.reload + end + + before do + sign_in(user) + project.team << [user, :developer] + allow(Gitlab.config.incoming_email).to receive(:enabled).and_return(true) + end + + it 'has http status 200' do + expect(response).to have_http_status(200) + end + + it 'changes the user incoming email token' do + expect { subject }.to change { user.incoming_email_token } + end + + it 'changes projects new issue address' do + expect { subject }.to change { project.new_issue_address(user) } + end + end + describe "POST #toggle_star" do it "toggles star if user is signed in" do sign_in(user) diff --git a/spec/features/issues_spec.rb b/spec/features/issues_spec.rb index b504329656f..cdd02a8c8e3 100644 --- a/spec/features/issues_spec.rb +++ b/spec/features/issues_spec.rb @@ -3,6 +3,7 @@ require 'spec_helper' describe 'Issues', feature: true do include IssueHelpers include SortingHelper + include WaitForAjax let(:project) { create(:project) } @@ -368,6 +369,26 @@ describe 'Issues', feature: true do end end + describe 'when I want to reset my incoming email token' do + let(:project1) { create(:project, namespace: @user.namespace) } + + before do + allow(Gitlab.config.incoming_email).to receive(:enabled).and_return(true) + project1.team << [@user, :master] + visit namespace_project_issues_path(@user.namespace, project1) + end + + it 'changes incoming email address token', js: true do + find('.issue-email-modal-btn').click + previous_token = find('input#issue_email').value + + find('.incoming-email-token-reset').click + wait_for_ajax + + expect(find('input#issue_email').value).not_to eq(previous_token) + end + end + describe 'update labels from issue#show', js: true do let(:issue) { create(:issue, project: project, author: @user, assignee: @user) } let!(:label) { create(:label, project: project) } @@ -553,7 +574,7 @@ describe 'Issues', feature: true do end end - xdescribe 'new issue by email' do + describe 'new issue by email' do shared_examples 'show the email in the modal' do before do stub_incoming_email_setting(enabled: true, address: "p+%{key}@gl.ab") diff --git a/spec/features/profile_spec.rb b/spec/features/profile_spec.rb index c3d8c349ca4..7a562b5e03d 100644 --- a/spec/features/profile_spec.rb +++ b/spec/features/profile_spec.rb @@ -32,4 +32,33 @@ describe 'Profile account page', feature: true do expect(current_path).to eq(profile_account_path) end end + + describe 'when I reset private token' do + before do + visit profile_account_path + end + + it 'resets private token' do + previous_token = find("#private-token").value + + click_link('Reset private token') + + expect(find('#private-token').value).not_to eq(previous_token) + end + end + + describe 'when I reset incoming email token' do + before do + allow(Gitlab.config.incoming_email).to receive(:enabled).and_return(true) + visit profile_account_path + end + + it 'resets incoming email token' do + previous_token = find('#incoming-email-token').value + + click_link('Reset incoming email token') + + expect(find('#incoming-email-token').value).not_to eq(previous_token) + end + end end diff --git a/spec/features/projects/issues/issues_spec.rb b/spec/features/projects/issues/issues_spec.rb deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/spec/lib/gitlab/email/handler/create_issue_handler_spec.rb b/spec/lib/gitlab/email/handler/create_issue_handler_spec.rb index 939189a3bc0..cb3651e3845 100644 --- a/spec/lib/gitlab/email/handler/create_issue_handler_spec.rb +++ b/spec/lib/gitlab/email/handler/create_issue_handler_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' require_relative '../email_shared_blocks' -xdescribe Gitlab::Email::Handler::CreateIssueHandler, lib: true do +describe Gitlab::Email::Handler::CreateIssueHandler, lib: true do include_context :email_shared_context it_behaves_like :email_shared_examples diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 0245897938c..0810d06b50f 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -295,7 +295,7 @@ describe Project, models: true do end end - xdescribe "#new_issue_address" do + describe "#new_issue_address" do let(:project) { create(:empty_project, path: "somewhere") } let(:user) { create(:user) } @@ -305,8 +305,7 @@ describe Project, models: true do end it 'returns the address to create a new issue' do - token = user.authentication_token - address = "p+#{project.namespace.path}/#{project.path}+#{token}@gl.ab" + address = "p+#{project.path_with_namespace}+#{user.incoming_email_token}@gl.ab" expect(project.new_issue_address(user)).to eq(address) end From 706113167682d0b47970834ba218657624c0196e Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 7 Nov 2016 18:35:14 +0200 Subject: [PATCH 147/175] Refactor namespace regex Signed-off-by: Dmitriy Zaporozhets --- config/routes/group.rb | 2 +- config/routes/user.rb | 45 +++++++++++++++++++++--------------------- lib/gitlab/regex.rb | 4 ++++ 3 files changed, 28 insertions(+), 23 deletions(-) diff --git a/config/routes/group.rb b/config/routes/group.rb index 826048ba196..4518cd4015a 100644 --- a/config/routes/group.rb +++ b/config/routes/group.rb @@ -3,7 +3,7 @@ require 'constraints/group_url_constrainer' constraints(GroupUrlConstrainer.new) do scope(path: ':id', as: :group, - constraints: { id: /[a-zA-Z.0-9_\-]+(? Date: Mon, 7 Nov 2016 16:12:05 +0000 Subject: [PATCH 148/175] Fixed todos empty state when filtering Closes #24127 --- app/helpers/todos_helper.rb | 4 ++++ app/views/dashboard/todos/index.html.haml | 20 ++++++++++++-------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/app/helpers/todos_helper.rb b/app/helpers/todos_helper.rb index a9db8bb2b82..a75a03b16d2 100644 --- a/app/helpers/todos_helper.rb +++ b/app/helpers/todos_helper.rb @@ -61,6 +61,10 @@ module TodosHelper } end + def todos_filter_empty? + todos_filter_params.all? {|key, value| value.nil?} + end + def todos_filter_path(options = {}) without = options.delete(:without) diff --git a/app/views/dashboard/todos/index.html.haml b/app/views/dashboard/todos/index.html.haml index e247eebc3fc..16bdf284f83 100644 --- a/app/views/dashboard/todos/index.html.haml +++ b/app/views/dashboard/todos/index.html.haml @@ -83,14 +83,18 @@ .todos-all-done = render "shared/empty_states/todos_all_done.svg" %h4.text-center - Good job! Looks like you don't have any todos left. - %p.text-center - Are you looking for things to do? Take a look at - = succeed "," do - = link_to "the opened issues", issues_dashboard_path - contribute to - = link_to "merge requests", merge_requests_dashboard_path - or mention someone in a comment to assign a new todo automatically. + - if todos_filter_empty? + Good job! Looks like you don't have any todos left. + - else + There are no Todos to show. + - if todos_filter_empty? + %p.text-center + Are you looking for things to do? Take a look at + = succeed "," do + = link_to "the opened issues", issues_dashboard_path + contribute to + = link_to "merge requests", merge_requests_dashboard_path + or mention someone in a comment to assign a new todo automatically. - else .todos-empty .todos-empty-hero From d59956afc02e66b46045d733b6d48014a7818d24 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Mon, 7 Nov 2016 17:55:20 +0000 Subject: [PATCH 149/175] Apply `*_params_ce` pattern to ProjectsController --- app/controllers/projects_controller.rb | 52 +++++++++++++++++--------- 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 6988527a3be..0620b3df637 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -318,26 +318,44 @@ class ProjectsController < Projects::ApplicationController end def project_params - project_feature_attributes = - { - project_feature_attributes: - [ - :issues_access_level, :builds_access_level, - :wiki_access_level, :merge_requests_access_level, - :snippets_access_level, :repository_access_level - ] - } + params.require(:project) + .permit(project_params_ce) + end - params.require(:project).permit( - :name, :path, :description, :issues_tracker, :tag_list, :runners_token, + def project_params_ce + [ + :avatar, + :build_allow_git_fetch, + :build_coverage_regex, + :build_timeout_in_minutes, :container_registry_enabled, - :issues_tracker_id, :default_branch, - :visibility_level, :import_url, :last_activity_at, :namespace_id, :avatar, - :build_allow_git_fetch, :build_timeout_in_minutes, :build_coverage_regex, - :public_builds, :only_allow_merge_if_build_succeeds, :request_access_enabled, + :default_branch, + :description, + :import_url, + :issues_tracker, + :issues_tracker_id, + :last_activity_at, + :lfs_enabled, + :name, + :namespace_id, :only_allow_merge_if_all_discussions_are_resolved, - :lfs_enabled, project_feature_attributes - ) + :only_allow_merge_if_build_succeeds, + :path, + :public_builds, + :request_access_enabled, + :runners_token, + :tag_list, + :visibility_level, + + project_feature_attributes: %i[ + builds_access_level + issues_access_level + merge_requests_access_level + repository_access_level + snippets_access_level + wiki_access_level + ] + ] end def repo_exists? From bab98d29799deaa6b778a50bfdc44bdf7dc753f2 Mon Sep 17 00:00:00 2001 From: tauriedavis Date: Mon, 7 Nov 2016 11:06:48 -0800 Subject: [PATCH 150/175] 17492 Update link color for more accessible contrast --- app/assets/stylesheets/framework/selects.scss | 2 +- app/assets/stylesheets/framework/variables.scss | 4 ++-- app/views/notify/pipeline_failed_email.html.haml | 14 +++++++------- app/views/notify/pipeline_success_email.html.haml | 12 ++++++------ 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/app/assets/stylesheets/framework/selects.scss b/app/assets/stylesheets/framework/selects.scss index 13749f1b7bd..920ce249b9a 100644 --- a/app/assets/stylesheets/framework/selects.scss +++ b/app/assets/stylesheets/framework/selects.scss @@ -63,7 +63,7 @@ } .select2-highlighted { - background: #3084bb !important; + background: $gl-link-color !important; } .select2-results li.select2-result-with-children > .select2-result-label { diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss index be2a7ceefff..e0d00759c9c 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -103,7 +103,7 @@ $gl-text-color-light: #8c8c8c; $gl-text-green: #4a2; $gl-text-red: #d12f19; $gl-text-orange: #d90; -$gl-link-color: #3084bb; +$gl-link-color: #3777b0; $gl-dark-link-color: #333; $gl-placeholder-color: #8f8f8f; $gl-icon-color: $gl-placeholder-color; @@ -197,7 +197,7 @@ $line-number-new: #ddfbe6; $line-number-select: #fbf2da; $match-line: $gray-light; $table-border-gray: #f0f0f0; -$line-target-blue: #eaf3fc; +$line-target-blue: #f6faff; $line-select-yellow: #fcf8e7; $line-select-yellow-dark: #f0e2bd; diff --git a/app/views/notify/pipeline_failed_email.html.haml b/app/views/notify/pipeline_failed_email.html.haml index 0995826775a..38c852f0a3a 100644 --- a/app/views/notify/pipeline_failed_email.html.haml +++ b/app/views/notify/pipeline_failed_email.html.haml @@ -103,11 +103,11 @@ %td{style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;padding-right:5px;"} %img{height: "13", src: image_url('mailers/ci_pipeline_notif_v1/icon-commit-gray.gif'), style: "display:block;", width: "13"}/ %td{style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;"} - %a{href: commit_url(@pipeline), style: "color:#3084bb;text-decoration:none;"} + %a{href: commit_url(@pipeline), style: "color:#3777b0;text-decoration:none;"} = @pipeline.short_sha - if @merge_request in - %a{href: merge_request_url(@merge_request), style: "color:#3084bb;text-decoration:none;"} + %a{href: merge_request_url(@merge_request), style: "color:#3777b0;text-decoration:none;"} = @merge_request.to_reference .commit{style: "color:#5c5c5c;font-weight:300;"} = @pipeline.git_commit_message.truncate(50) @@ -134,7 +134,7 @@ %tr.pre-section %td{style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;color:#333333;font-size:15px;font-weight:400;line-height:1.4;padding:15px 0;"} Pipeline - %a{href: pipeline_url(@pipeline), style: "color:#3084bb;text-decoration:none;"} + %a{href: pipeline_url(@pipeline), style: "color:#3777b0;text-decoration:none;"} = "\##{@pipeline.id}" had = failed.size @@ -158,7 +158,7 @@ %td{style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;color:#8c8c8c;font-weight:500;font-size:15px;vertical-align:middle;"} = build.stage %td{align: "right", style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;padding:20px 0;color:#8c8c8c;font-weight:500;font-size:15px;"} - %a{href: pipeline_build_url(@pipeline, build), style: "color:#3084bb;text-decoration:none;"} + %a{href: pipeline_build_url(@pipeline, build), style: "color:#3777b0;text-decoration:none;"} = build.name %tr.build-log %td{colspan: "2", style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;padding:0 0 15px;"} @@ -168,10 +168,10 @@ %td{style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;padding:25px 0;font-size:13px;line-height:1.6;color:#5c5c5c;"} %img{alt: "GitLab", height: "33", src: image_url('mailers/ci_pipeline_notif_v1/gitlab-logo-full-horizontal.gif'), style: "display:block;margin:0 auto 1em;", width: "90"}/ %div - %a{href: profile_notifications_url, style: "color:#3084bb;text-decoration:none;"} Manage all notifications + %a{href: profile_notifications_url, style: "color:#3777b0;text-decoration:none;"} Manage all notifications · - %a{href: help_url, style: "color:#3084bb;text-decoration:none;"} Help + %a{href: help_url, style: "color:#3777b0;text-decoration:none;"} Help %div You're receiving this email because of your account on = succeed "." do - %a{href: root_url, style: "color:#3084bb;text-decoration:none;"}= Gitlab.config.gitlab.host + %a{href: root_url, style: "color:#3777b0;text-decoration:none;"}= Gitlab.config.gitlab.host diff --git a/app/views/notify/pipeline_success_email.html.haml b/app/views/notify/pipeline_success_email.html.haml index cf9c1d4d72c..697c8d19257 100644 --- a/app/views/notify/pipeline_success_email.html.haml +++ b/app/views/notify/pipeline_success_email.html.haml @@ -103,11 +103,11 @@ %td{style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;padding-right:5px;"} %img{height: "13", src: image_url('mailers/ci_pipeline_notif_v1/icon-commit-gray.gif'), style: "display:block;", width: "13"}/ %td{style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;"} - %a{href: commit_url(@pipeline), style: "color:#3084bb;text-decoration:none;"} + %a{href: commit_url(@pipeline), style: "color:#3777b0;text-decoration:none;"} = @pipeline.short_sha - if @merge_request in - %a{href: merge_request_url(@merge_request), style: "color:#3084bb;text-decoration:none;"} + %a{href: merge_request_url(@merge_request), style: "color:#3777b0;text-decoration:none;"} = @merge_request.to_reference .commit{style: "color:#5c5c5c;font-weight:300;"} = @pipeline.git_commit_message.truncate(50) @@ -135,7 +135,7 @@ - build_count = @pipeline.statuses.latest.size - stage_count = @pipeline.stages.size Pipeline - %a{href: pipeline_url(@pipeline), style: "color:#3084bb;text-decoration:none;"} + %a{href: pipeline_url(@pipeline), style: "color:#3777b0;text-decoration:none;"} = "\##{@pipeline.id}" successfully completed = "#{build_count} #{'build'.pluralize(build_count)}" @@ -145,10 +145,10 @@ %td{style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;padding:25px 0;font-size:13px;line-height:1.6;color:#5c5c5c;"} %img{alt: "GitLab", height: "33", src: image_url('mailers/ci_pipeline_notif_v1/gitlab-logo-full-horizontal.gif'), style: "display:block;margin:0 auto 1em;", width: "90"}/ %div - %a{href: profile_notifications_url, style: "color:#3084bb;text-decoration:none;"} Manage all notifications + %a{href: profile_notifications_url, style: "color:#3777b0;text-decoration:none;"} Manage all notifications · - %a{href: help_url, style: "color:#3084bb;text-decoration:none;"} Help + %a{href: help_url, style: "color:#3777b0;text-decoration:none;"} Help %div You're receiving this email because of your account on = succeed "." do - %a{href: root_url, style: "color:#3084bb;text-decoration:none;"}= Gitlab.config.gitlab.host + %a{href: root_url, style: "color:#3777b0;text-decoration:none;"}= Gitlab.config.gitlab.host From 5569573a24efca76abede20370988a81d623e6a5 Mon Sep 17 00:00:00 2001 From: Hiroyuki Sato Date: Tue, 8 Nov 2016 05:12:17 +0900 Subject: [PATCH 151/175] Refactor method name --- app/controllers/projects/network_controller.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/projects/network_controller.rb b/app/controllers/projects/network_controller.rb index e808c9c7343..33a152ad34f 100644 --- a/app/controllers/projects/network_controller.rb +++ b/app/controllers/projects/network_controller.rb @@ -5,7 +5,7 @@ class Projects::NetworkController < Projects::ApplicationController before_action :require_non_empty_project before_action :assign_ref_vars before_action :authorize_download_code! - before_action :assign_extended_sha1 + before_action :assign_commit def show @url = namespace_project_network_path(@project.namespace, @project, @ref, @options.merge(format: :json)) @@ -24,7 +24,7 @@ class Projects::NetworkController < Projects::ApplicationController end end - def assign_extended_sha1 + def assign_commit return if params[:extended_sha1].blank? @options[:extended_sha1] = params[:extended_sha1] From d92c0037e1ad9f538d2f42f78349abdae7c01d75 Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Mon, 7 Nov 2016 21:45:28 +0100 Subject: [PATCH 152/175] Replace trigger with the new ID of the docs project [ci skip] --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d04069df885..195783454f9 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -331,7 +331,7 @@ trigger_docs: cache: {} artifacts: {} script: - - "curl -X POST -F token=${DOCS_TRIGGER_TOKEN} -F ref=master -F variables[PROJECT]=ce https://gitlab.com/api/v3/projects/38069/trigger/builds" + - "curl -X POST -F token=${DOCS_TRIGGER_TOKEN} -F ref=master -F variables[PROJECT]=ce https://gitlab.com/api/v3/projects/1794617/trigger/builds" only: - master@gitlab-org/gitlab-ce From fa1ac47ef167e55d79a69d69596012fe5ac99d20 Mon Sep 17 00:00:00 2001 From: Clement Ho Date: Thu, 8 Sep 2016 13:57:24 -0500 Subject: [PATCH 153/175] Replace jQuery.timeago with timeago.js --- app/assets/javascripts/activities.js | 4 +- app/assets/javascripts/application.js | 4 - app/assets/javascripts/build.js | 2 +- app/assets/javascripts/compare.js | 3 +- .../javascripts/lib/utils/common_utils.js | 19 -- .../javascripts/lib/utils/datetime_utility.js | 95 ++++--- app/assets/javascripts/lib/utils/timeago.js | 237 ++++++++++++++++++ .../javascripts/merge_request_widget.js.es6 | 2 +- app/assets/javascripts/milestone_select.js | 2 +- app/helpers/application_helper.rb | 18 +- app/views/events/_event.html.haml | 2 +- app/views/projects/_last_commit.html.haml | 2 +- app/views/projects/blame/show.html.haml | 2 +- .../projects/ci/pipelines/_pipeline.html.haml | 2 +- app/views/projects/refs/logs_tree.js.haml | 3 + changelogs/unreleased/upgrade-timeago.yml | 4 + spec/helpers/application_helper_spec.rb | 24 +- spec/javascripts/merge_request_widget_spec.js | 2 +- vendor/assets/javascripts/jquery.timeago.js | 182 -------------- 19 files changed, 320 insertions(+), 289 deletions(-) create mode 100644 app/assets/javascripts/lib/utils/timeago.js create mode 100644 changelogs/unreleased/upgrade-timeago.yml delete mode 100644 vendor/assets/javascripts/jquery.timeago.js diff --git a/app/assets/javascripts/activities.js b/app/assets/javascripts/activities.js index 59ac9b9cef5..919107b8cb9 100644 --- a/app/assets/javascripts/activities.js +++ b/app/assets/javascripts/activities.js @@ -13,12 +13,12 @@ } Activities.prototype.updateTooltips = function() { - return gl.utils.localTimeAgo($('.js-timeago', '.content_list')); + gl.utils.localTimeAgo($('.js-timeago', '.content_list')); }; Activities.prototype.reloadActivities = function() { $(".content_list").html(''); - return Pager.init(20, true); + Pager.init(20, true, false, this.updateTooltips); }; Activities.prototype.toggleFilter = function(sender) { diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 7d942de0184..e6b55c9b6ae 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -13,7 +13,6 @@ /*= require jquery-ui/sortable */ /*= require jquery_ujs */ /*= require jquery.endless-scroll */ -/*= require jquery.timeago */ /*= require jquery.highlight */ /*= require jquery.waitforimages */ /*= require jquery.atwho */ @@ -238,8 +237,5 @@ // bind sidebar events new gl.Sidebar(); - - // Custom time ago - gl.utils.shortTimeAgo($('.js-short-timeago')); }); }).call(this); diff --git a/app/assets/javascripts/build.js b/app/assets/javascripts/build.js index 12e653f4122..d63125ce44b 100644 --- a/app/assets/javascripts/build.js +++ b/app/assets/javascripts/build.js @@ -169,7 +169,7 @@ $date = $('.js-artifacts-remove'); if ($date.length) { date = $date.text(); - return $date.text($.timefor(new Date(date.replace(/([0-9]+)-([0-9]+)-([0-9]+)/g, '$1/$2/$3')), ' ')); + return $date.text(gl.utils.timefor(new Date(date.replace(/([0-9]+)-([0-9]+)-([0-9]+)/g, '$1/$2/$3')), ' ')); } }; diff --git a/app/assets/javascripts/compare.js b/app/assets/javascripts/compare.js index b3f769d4129..61cc91c524b 100644 --- a/app/assets/javascripts/compare.js +++ b/app/assets/javascripts/compare.js @@ -80,7 +80,8 @@ success: function(html) { loading.hide(); $target.html(html); - return $('.js-timeago', $target).timeago(); + var className = '.' + $target[0].className.replace(' ', '.'); + gl.utils.localTimeAgo($('.js-timeago', className)); } }); }; diff --git a/app/assets/javascripts/lib/utils/common_utils.js b/app/assets/javascripts/lib/utils/common_utils.js index 8447421195d..6cb3d95f984 100644 --- a/app/assets/javascripts/lib/utils/common_utils.js +++ b/app/assets/javascripts/lib/utils/common_utils.js @@ -119,31 +119,12 @@ parser.href = url; return parser; }; - gl.utils.cleanupBeforeFetch = function() { // Unbind scroll events $(document).off('scroll'); // Close any open tooltips $('.has-tooltip, [data-toggle="tooltip"]').tooltip('destroy'); }; - - return jQuery.timefor = function(time, suffix, expiredLabel) { - var suffixFromNow, timefor; - if (!time) { - return ''; - } - suffix || (suffix = 'remaining'); - expiredLabel || (expiredLabel = 'Past due'); - jQuery.timeago.settings.allowFuture = true; - suffixFromNow = jQuery.timeago.settings.strings.suffixFromNow; - jQuery.timeago.settings.strings.suffixFromNow = suffix; - timefor = $.timeago(time); - if (timefor.indexOf('ago') > -1) { - timefor = expiredLabel; - } - jQuery.timeago.settings.strings.suffixFromNow = suffixFromNow; - return timefor; - }; })(window); }).call(this); diff --git a/app/assets/javascripts/lib/utils/datetime_utility.js b/app/assets/javascripts/lib/utils/datetime_utility.js index 59e526ed623..3965109dd65 100644 --- a/app/assets/javascripts/lib/utils/datetime_utility.js +++ b/app/assets/javascripts/lib/utils/datetime_utility.js @@ -22,51 +22,64 @@ if (setTimeago == null) { setTimeago = true; } + $timeagoEls.each(function() { - var $el; - $el = $(this); - return $el.attr('title', gl.utils.formatDate($el.attr('datetime'))); + var $el = $(this); + $el.attr('title', gl.utils.formatDate($el.attr('datetime'))); + + if (setTimeago) { + // Recreate with custom template + $el.tooltip({ + template: '' + }); + } + gl.utils.renderTimeago($el); }); - if (setTimeago) { - $timeagoEls.timeago(); - $timeagoEls.tooltip('destroy'); - // Recreate with custom template - return $timeagoEls.tooltip({ - template: '' - }); - } }; - w.gl.utils.shortTimeAgo = function($el) { - var shortLocale, tmpLocale; - shortLocale = { - prefixAgo: null, - prefixFromNow: null, - suffixAgo: 'ago', - suffixFromNow: 'from now', - seconds: '1 min', - minute: '1 min', - minutes: '%d mins', - hour: '1 hr', - hours: '%d hrs', - day: '1 day', - days: '%d days', - month: '1 month', - months: '%d months', - year: '1 year', - years: '%d years', - wordSeparator: ' ', - numbers: [] + w.gl.utils.getTimeago = function() { + var locale = function(number, index) { + return [ + ['less than a minute ago', 'a while'], + ['less than a minute ago', 'in %s seconds'], + ['about a minute ago', 'in 1 minute'], + ['%s minutes ago', 'in %s minutes'], + ['about an hour ago', 'in 1 hour'], + ['about %s hours ago', 'in %s hours'], + ['a day ago', 'in 1 day'], + ['%s days ago', 'in %s days'], + ['a week ago', 'in 1 week'], + ['%s weeks ago', 'in %s weeks'], + ['a month ago', 'in 1 month'], + ['%s months ago', 'in %s months'], + ['a year ago', 'in 1 year'], + ['%s years ago', 'in %s years'] + ][index]; }; - tmpLocale = $.timeago.settings.strings; - $el.each(function(el) { - var $el1; - $el1 = $(this); - return $el1.attr('title', gl.utils.formatDate($el.attr('datetime'))); - }); - $.timeago.settings.strings = shortLocale; - $el.timeago(); - $.timeago.settings.strings = tmpLocale; + + timeago.register('gl_en', locale); + return timeago(); + }; + + w.gl.utils.timeFor = function(time, suffix, expiredLabel) { + var timefor; + if (!time) { + return ''; + } + suffix || (suffix = 'remaining'); + expiredLabel || (expiredLabel = 'Past due'); + timefor = gl.utils.getTimeago().format(time).replace('in', ''); + if (timefor.indexOf('ago') > -1) { + timefor = expiredLabel; + } else { + timefor = timefor.trim() + ' ' + suffix; + } + return timefor; + }; + + w.gl.utils.renderTimeago = function($element) { + var timeagoInstance = gl.utils.getTimeago(); + timeagoInstance.render($element, 'gl_en'); }; w.gl.utils.getDayDifference = function(a, b) { @@ -75,7 +88,7 @@ var date2 = Date.UTC(b.getFullYear(), b.getMonth(), b.getDate()); return Math.floor((date2 - date1) / millisecondsPerDay); - } + }; })(window); diff --git a/app/assets/javascripts/lib/utils/timeago.js b/app/assets/javascripts/lib/utils/timeago.js new file mode 100644 index 00000000000..42606dd2d46 --- /dev/null +++ b/app/assets/javascripts/lib/utils/timeago.js @@ -0,0 +1,237 @@ +/** + * Copyright (c) 2016 hustcc + * License: MIT + * Version: v2.0.2 + * https://github.com/hustcc/timeago.js + * This is a forked from (https://gitlab.com/ClemMakesApps/timeago.js) +**/ +/* eslint-disable */ +/* jshint expr: true */ +!function (root, factory) { + if (typeof module === 'object' && module.exports) + module.exports = factory(root); + else + root.timeago = factory(root); +}(typeof window !== 'undefined' ? window : this, +function () { + var cnt = 0, // the timer counter, for timer key + indexMapEn = 'second_minute_hour_day_week_month_year'.split('_'), + + // build-in locales: en & zh_CN + locales = { + 'en': function(number, index) { + if (index === 0) return ['just now', 'right now']; + var unit = indexMapEn[parseInt(index / 2)]; + if (number > 1) unit += 's'; + return [number + ' ' + unit + ' ago', 'in ' + number + ' ' + unit]; + }, + }, + // second, minute, hour, day, week, month, year(365 days) + SEC_ARRAY = [60, 60, 24, 7, 365/7/12, 12], + SEC_ARRAY_LEN = 6, + ATTR_DATETIME = 'datetime'; + + // format Date / string / timestamp to Date instance. + function toDate(input) { + if (input instanceof Date) return input; + if (!isNaN(input)) return new Date(toInt(input)); + if (/^\d+$/.test(input)) return new Date(toInt(input, 10)); + input = (input || '').trim().replace(/\.\d+/, '') // remove milliseconds + .replace(/-/, '/').replace(/-/, '/') + .replace(/T/, ' ').replace(/Z/, ' UTC') + .replace(/([\+\-]\d\d)\:?(\d\d)/, ' $1$2'); // -04:00 -> -0400 + return new Date(input); + } + // change f into int, remove Decimal. just for code compression + function toInt(f) { + return parseInt(f); + } + // format the diff second to *** time ago, with setting locale + function formatDiff(diff, locale, defaultLocale) { + // if locale is not exist, use defaultLocale. + // if defaultLocale is not exist, use build-in `en`. + // be sure of no error when locale is not exist. + locale = locales[locale] ? locale : (locales[defaultLocale] ? defaultLocale : 'en'); + // if (! locales[locale]) locale = defaultLocale; + var i = 0; + agoin = diff < 0 ? 1 : 0; // timein or timeago + diff = Math.abs(diff); + + for (; diff >= SEC_ARRAY[i] && i < SEC_ARRAY_LEN; i++) { + diff /= SEC_ARRAY[i]; + } + diff = toInt(diff); + i *= 2; + + if (diff > (i === 0 ? 9 : 1)) i += 1; + return locales[locale](diff, i)[agoin].replace('%s', diff); + } + // calculate the diff second between date to be formated an now date. + function diffSec(date, nowDate) { + nowDate = nowDate ? toDate(nowDate) : new Date(); + return (nowDate - toDate(date)) / 1000; + } + /** + * nextInterval: calculate the next interval time. + * - diff: the diff sec between now and date to be formated. + * + * What's the meaning? + * diff = 61 then return 59 + * diff = 3601 (an hour + 1 second), then return 3599 + * make the interval with high performace. + **/ + function nextInterval(diff) { + var rst = 1, i = 0, d = Math.abs(diff); + for (; diff >= SEC_ARRAY[i] && i < SEC_ARRAY_LEN; i++) { + diff /= SEC_ARRAY[i]; + rst *= SEC_ARRAY[i]; + } + // return leftSec(d, rst); + d = d % rst; + d = d ? rst - d : rst; + return Math.ceil(d); + } + // get the datetime attribute, jQuery and DOM + function getDateAttr(node) { + if (node.getAttribute) return node.getAttribute(ATTR_DATETIME); + if(node.attr) return node.attr(ATTR_DATETIME); + } + /** + * timeago: the function to get `timeago` instance. + * - nowDate: the relative date, default is new Date(). + * - defaultLocale: the default locale, default is en. if your set it, then the `locale` parameter of format is not needed of you. + * + * How to use it? + * var timeagoLib = require('timeago.js'); + * var timeago = timeagoLib(); // all use default. + * var timeago = timeagoLib('2016-09-10'); // the relative date is 2016-09-10, so the 2016-09-11 will be 1 day ago. + * var timeago = timeagoLib(null, 'zh_CN'); // set default locale is `zh_CN`. + * var timeago = timeagoLib('2016-09-10', 'zh_CN'); // the relative date is 2016-09-10, and locale is zh_CN, so the 2016-09-11 will be 1天前. + **/ + function Timeago(nowDate, defaultLocale) { + var timers = {}; // real-time render timers + // if do not set the defaultLocale, set it with `en` + if (! defaultLocale) defaultLocale = 'en'; // use default build-in locale + // what the timer will do + function doRender(node, date, locale, cnt) { + var diff = diffSec(date, nowDate); + node.innerHTML = formatDiff(diff, locale, defaultLocale); + // waiting %s seconds, do the next render + timers['k' + cnt] = setTimeout(function() { + doRender(node, date, locale, cnt); + }, nextInterval(diff) * 1000); + } + /** + * nextInterval: calculate the next interval time. + * - diff: the diff sec between now and date to be formated. + * + * What's the meaning? + * diff = 61 then return 59 + * diff = 3601 (an hour + 1 second), then return 3599 + * make the interval with high performace. + **/ + // this.nextInterval = function(diff) { // for dev test + // var rst = 1, i = 0, d = Math.abs(diff); + // for (; diff >= SEC_ARRAY[i] && i < SEC_ARRAY_LEN; i++) { + // diff /= SEC_ARRAY[i]; + // rst *= SEC_ARRAY[i]; + // } + // // return leftSec(d, rst); + // d = d % rst; + // d = d ? rst - d : rst; + // return Math.ceil(d); + // }; // for dev test + /** + * format: format the date to *** time ago, with setting or default locale + * - date: the date / string / timestamp to be formated + * - locale: the formated string's locale name, e.g. en / zh_CN + * + * How to use it? + * var timeago = require('timeago.js')(); + * timeago.format(new Date(), 'pl'); // Date instance + * timeago.format('2016-09-10', 'fr'); // formated date string + * timeago.format(1473473400269); // timestamp with ms + **/ + this.format = function(date, locale) { + return formatDiff(diffSec(date, nowDate), locale, defaultLocale); + }; + /** + * render: render the DOM real-time. + * - nodes: which nodes will be rendered. + * - locale: the locale name used to format date. + * + * How to use it? + * var timeago = new require('timeago.js')(); + * // 1. javascript selector + * timeago.render(document.querySelectorAll('.need_to_be_rendered')); + * // 2. use jQuery selector + * timeago.render($('.need_to_be_rendered'), 'pl'); + * + * Notice: please be sure the dom has attribute `datetime`. + **/ + this.render = function(nodes, locale) { + if (nodes.length === undefined) nodes = [nodes]; + for (var i = 0; i < nodes.length; i++) { + doRender(nodes[i], getDateAttr(nodes[i]), locale, ++ cnt); // render item + } + }; + /** + * cancel: cancel all the timers which are doing real-time render. + * + * How to use it? + * var timeago = new require('timeago.js')(); + * timeago.render(document.querySelectorAll('.need_to_be_rendered')); + * timeago.cancel(); // will stop all the timer, stop render in real time. + **/ + this.cancel = function() { + for (var key in timers) { + clearTimeout(timers[key]); + } + timers = {}; + }; + /** + * setLocale: set the default locale name. + * + * How to use it? + * var timeago = require('timeago.js'); + * timeago = new timeago(); + * timeago.setLocale('fr'); + **/ + this.setLocale = function(locale) { + defaultLocale = locale; + }; + return this; + } + /** + * timeago: the function to get `timeago` instance. + * - nowDate: the relative date, default is new Date(). + * - defaultLocale: the default locale, default is en. if your set it, then the `locale` parameter of format is not needed of you. + * + * How to use it? + * var timeagoLib = require('timeago.js'); + * var timeago = timeagoLib(); // all use default. + * var timeago = timeagoLib('2016-09-10'); // the relative date is 2016-09-10, so the 2016-09-11 will be 1 day ago. + * var timeago = timeagoLib(null, 'zh_CN'); // set default locale is `zh_CN`. + * var timeago = timeagoLib('2016-09-10', 'zh_CN'); // the relative date is 2016-09-10, and locale is zh_CN, so the 2016-09-11 will be 1天前. + **/ + function timeagoFactory(nowDate, defaultLocale) { + return new Timeago(nowDate, defaultLocale); + } + /** + * register: register a new language locale + * - locale: locale name, e.g. en / zh_CN, notice the standard. + * - localeFunc: the locale process function + * + * How to use it? + * var timeagoLib = require('timeago.js'); + * + * timeagoLib.register('the locale name', the_locale_func); + * // or + * timeagoLib.register('pl', require('timeago.js/locales/pl')); + **/ + timeagoFactory.register = function(locale, localeFunc) { + locales[locale] = localeFunc; + }; + + return timeagoFactory; +}); \ No newline at end of file diff --git a/app/assets/javascripts/merge_request_widget.js.es6 b/app/assets/javascripts/merge_request_widget.js.es6 index 3a2fe454b68..56c87af3226 100644 --- a/app/assets/javascripts/merge_request_widget.js.es6 +++ b/app/assets/javascripts/merge_request_widget.js.es6 @@ -218,7 +218,7 @@ } if (environment.deployed_at && environment.deployed_at_formatted) { - environment.deployed_at = $.timeago(environment.deployed_at) + '.'; + environment.deployed_at = gl.utils.getTimeago(environment.deployed_at) + '.'; } else { $('.js-environment-timeago', $template).remove(); environment.name += '.'; diff --git a/app/assets/javascripts/milestone_select.js b/app/assets/javascripts/milestone_select.js index c909b53dc21..d1cd38ad110 100644 --- a/app/assets/javascripts/milestone_select.js +++ b/app/assets/javascripts/milestone_select.js @@ -162,7 +162,7 @@ if (data.milestone != null) { data.milestone.namespace = _this.currentProject.namespace; data.milestone.path = _this.currentProject.path; - data.milestone.remaining = $.timefor(data.milestone.due_date); + data.milestone.remaining = gl.utils.timeFor(data.milestone.due_date); $value.html(milestoneLinkTemplate(data.milestone)); return $sidebarCollapsedValue.find('span').html(collapsedSidebarLabelTemplate(data.milestone)); } else { diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index ebd78bf9888..c816b616631 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -151,7 +151,6 @@ module ApplicationHelper # time - Time object # placement - Tooltip placement String (default: "top") # html_class - Custom class for `time` element (default: "time_ago") - # skip_js - When true, exclude the `script` tag (default: false) # # By default also includes a `script` element with Javascript necessary to # initialize the `timeago` jQuery extension. If this method is called many @@ -163,22 +162,19 @@ module ApplicationHelper # `html_class` argument is provided. # # Returns an HTML-safe String - def time_ago_with_tooltip(time, placement: 'top', html_class: '', skip_js: false, short_format: false) + def time_ago_with_tooltip(time, placement: 'top', html_class: '', short_format: false) css_classes = short_format ? 'js-short-timeago' : 'js-timeago' css_classes << " #{html_class}" unless html_class.blank? - css_classes << ' js-timeago-pending' unless skip_js element = content_tag :time, time.to_s, class: css_classes, - datetime: time.to_time.getutc.iso8601, title: time.to_time.in_time_zone.to_s(:medium), - data: { toggle: 'tooltip', placement: placement, container: 'body' } - - unless skip_js - element << javascript_tag( - "$('.js-timeago-pending').removeClass('js-timeago-pending').timeago()" - ) - end + datetime: time.to_time.getutc.iso8601, + data: { + toggle: 'tooltip', + placement: placement, + container: 'body' + } element end diff --git a/app/views/events/_event.html.haml b/app/views/events/_event.html.haml index 31fdcc5e21b..5c318cd3b8b 100644 --- a/app/views/events/_event.html.haml +++ b/app/views/events/_event.html.haml @@ -1,7 +1,7 @@ - if event.visible_to_user?(current_user) .event-item{ class: event_row_class(event) } .event-item-timestamp - #{time_ago_with_tooltip(event.created_at, skip_js: true)} + #{time_ago_with_tooltip(event.created_at)} = cache [event, current_application_settings, "v2.2"] do = author_avatar(event, size: 40) diff --git a/app/views/projects/_last_commit.html.haml b/app/views/projects/_last_commit.html.haml index 8e23d51b224..7f530708947 100644 --- a/app/views/projects/_last_commit.html.haml +++ b/app/views/projects/_last_commit.html.haml @@ -8,5 +8,5 @@ = link_to commit.short_id, namespace_project_commit_path(project.namespace, project, commit), class: "commit_short_id" = link_to_gfm commit.title, namespace_project_commit_path(project.namespace, project, commit), class: "commit-row-message" · -#{time_ago_with_tooltip(commit.committed_date, skip_js: true)} by +#{time_ago_with_tooltip(commit.committed_date)} by = commit_author_link(commit, avatar: true, size: 24) diff --git a/app/views/projects/blame/show.html.haml b/app/views/projects/blame/show.html.haml index dfb96305f48..cadfe5a3e30 100644 --- a/app/views/projects/blame/show.html.haml +++ b/app/views/projects/blame/show.html.haml @@ -32,7 +32,7 @@ .light = commit_author_link(commit, avatar: false) authored - #{time_ago_with_tooltip(commit.committed_date, skip_js: true)} + #{time_ago_with_tooltip(commit.committed_date)} %td.line-numbers - line_count = blame_group[:lines].count - (current_line...(current_line + line_count)).each do |i| diff --git a/app/views/projects/ci/pipelines/_pipeline.html.haml b/app/views/projects/ci/pipelines/_pipeline.html.haml index 1f748d73d06..2a2d24be736 100644 --- a/app/views/projects/ci/pipelines/_pipeline.html.haml +++ b/app/views/projects/ci/pipelines/_pipeline.html.haml @@ -59,7 +59,7 @@ - if pipeline.finished_at %p.finished-at = icon("calendar") - #{time_ago_with_tooltip(pipeline.finished_at, short_format: false, skip_js: true)} + #{time_ago_with_tooltip(pipeline.finished_at, short_format: false)} %td.pipeline-actions.hidden-xs .controls.pull-right diff --git a/app/views/projects/refs/logs_tree.js.haml b/app/views/projects/refs/logs_tree.js.haml index 1141168f037..44fa4b60343 100644 --- a/app/views/projects/refs/logs_tree.js.haml +++ b/app/views/projects/refs/logs_tree.js.haml @@ -16,3 +16,6 @@ var url = "#{escape_javascript(@more_log_url)}"; ajaxGet(url); } + +:plain + gl.utils.localTimeAgo($('.js-timeago', 'table.table_#{@hex_path} tbody')); \ No newline at end of file diff --git a/changelogs/unreleased/upgrade-timeago.yml b/changelogs/unreleased/upgrade-timeago.yml new file mode 100644 index 00000000000..ddb266ba558 --- /dev/null +++ b/changelogs/unreleased/upgrade-timeago.yml @@ -0,0 +1,4 @@ +--- +title: Replace jQuery.timeago with timeago.js +merge_request: 6274 +author: ClemMakesApps diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb index 73f5470cf35..c706e418d26 100644 --- a/spec/helpers/application_helper_spec.rb +++ b/spec/helpers/application_helper_spec.rb @@ -218,42 +218,24 @@ describe ApplicationHelper do end it 'includes a default js-timeago class' do - expect(element.attr('class')).to eq 'js-timeago js-timeago-pending' + expect(element.attr('class')).to eq 'js-timeago' end it 'accepts a custom html_class' do expect(element(html_class: 'custom_class').attr('class')). - to eq 'js-timeago custom_class js-timeago-pending' + to eq 'js-timeago custom_class' end it 'accepts a custom tooltip placement' do expect(element(placement: 'bottom').attr('data-placement')).to eq 'bottom' end - it 're-initializes timeago Javascript' do - el = element.next_element - - expect(el.name).to eq 'script' - expect(el.text).to include "$('.js-timeago-pending').removeClass('js-timeago-pending').timeago()" - end - - it 'allows the script tag to be excluded' do - expect(element(skip_js: true)).not_to include 'script' - end - it 'converts to Time' do expect { helper.time_ago_with_tooltip(Date.today) }.not_to raise_error end - it 'add class for the short format and includes inline script' do + it 'add class for the short format' do timeago_element = element(short_format: 'short') - expect(timeago_element.attr('class')).to eq 'js-short-timeago js-timeago-pending' - script_element = timeago_element.next_element - expect(script_element.name).to eq 'script' - end - - it 'add class for the short format and does not include inline script' do - timeago_element = element(short_format: 'short', skip_js: true) expect(timeago_element.attr('class')).to eq 'js-short-timeago' expect(timeago_element.next_element).to eq nil end diff --git a/spec/javascripts/merge_request_widget_spec.js b/spec/javascripts/merge_request_widget_spec.js index 49dfeab61d8..91f19aca719 100644 --- a/spec/javascripts/merge_request_widget_spec.js +++ b/spec/javascripts/merge_request_widget_spec.js @@ -1,6 +1,6 @@ /* eslint-disable */ /*= require merge_request_widget */ -/*= require jquery.timeago.js */ +/*= require lib/utils/timeago.js */ (function() { describe('MergeRequestWidget', function() { diff --git a/vendor/assets/javascripts/jquery.timeago.js b/vendor/assets/javascripts/jquery.timeago.js deleted file mode 100644 index de76cdd2ea7..00000000000 --- a/vendor/assets/javascripts/jquery.timeago.js +++ /dev/null @@ -1,182 +0,0 @@ -/* eslint-disable */ -/** - * Timeago is a jQuery plugin that makes it easy to support automatically - * updating fuzzy timestamps (e.g. "4 minutes ago" or "about 1 day ago"). - * - * @name timeago - * @version 1.1.0 - * @requires jQuery v1.2.3+ - * @author Ryan McGeary - * @license MIT License - http://www.opensource.org/licenses/mit-license.php - * - * For usage and examples, visit: - * http://timeago.yarp.com/ - * - * Copyright (c) 2008-2013, Ryan McGeary (ryan -[at]- mcgeary [*dot*] org) - */ - -(function (factory) { - if (typeof define === 'function' && define.amd) { - // AMD. Register as an anonymous module. - define(['jquery'], factory); - } else { - // Browser globals - factory(jQuery); - } -}(function ($) { - $.timeago = function(timestamp) { - if (timestamp instanceof Date) { - return inWords(timestamp); - } else if (typeof timestamp === "string") { - return inWords($.timeago.parse(timestamp)); - } else if (typeof timestamp === "number") { - return inWords(new Date(timestamp)); - } else { - return inWords($.timeago.datetime(timestamp)); - } - }; - var $t = $.timeago; - - $.extend($.timeago, { - settings: { - refreshMillis: 60000, - allowFuture: false, - strings: { - prefixAgo: null, - prefixFromNow: null, - suffixAgo: "ago", - suffixFromNow: "from now", - seconds: "less than a minute", - minute: "about a minute", - minutes: "%d minutes", - hour: "about an hour", - hours: "about %d hours", - day: "a day", - days: "%d days", - month: "about a month", - months: "%d months", - year: "about a year", - years: "%d years", - wordSeparator: " ", - numbers: [] - } - }, - inWords: function(distanceMillis) { - var $l = this.settings.strings; - var prefix = $l.prefixAgo; - var suffix = $l.suffixAgo; - if (this.settings.allowFuture) { - if (distanceMillis < 0) { - prefix = $l.prefixFromNow; - suffix = $l.suffixFromNow; - } - } - - var seconds = Math.abs(distanceMillis) / 1000; - var minutes = seconds / 60; - var hours = minutes / 60; - var days = hours / 24; - var years = days / 365; - - function substitute(stringOrFunction, number) { - var string = $.isFunction(stringOrFunction) ? stringOrFunction(number, distanceMillis) : stringOrFunction; - var value = ($l.numbers && $l.numbers[number]) || number; - return string.replace(/%d/i, value); - } - - var words = seconds < 45 && substitute($l.seconds, Math.round(seconds)) || - seconds < 90 && substitute($l.minute, 1) || - minutes < 45 && substitute($l.minutes, Math.round(minutes)) || - minutes < 90 && substitute($l.hour, 1) || - hours < 24 && substitute($l.hours, Math.round(hours)) || - hours < 42 && substitute($l.day, 1) || - days < 30 && substitute($l.days, Math.round(days)) || - days < 45 && substitute($l.month, 1) || - days < 365 && substitute($l.months, Math.round(days / 30)) || - years < 1.5 && substitute($l.year, 1) || - substitute($l.years, Math.round(years)); - - var separator = $l.wordSeparator || ""; - if ($l.wordSeparator === undefined) { separator = " "; } - return $.trim([prefix, words, suffix].join(separator)); - }, - parse: function(iso8601) { - var s = $.trim(iso8601); - s = s.replace(/\.\d+/,""); // remove milliseconds - s = s.replace(/-/,"/").replace(/-/,"/"); - s = s.replace(/T/," ").replace(/Z/," UTC"); - s = s.replace(/([\+\-]\d\d)\:?(\d\d)/," $1$2"); // -04:00 -> -0400 - return new Date(s); - }, - datetime: function(elem) { - var iso8601 = $t.isTime(elem) ? $(elem).attr("datetime") : $(elem).attr("title"); - return $t.parse(iso8601); - }, - isTime: function(elem) { - // jQuery's `is()` doesn't play well with HTML5 in IE - return $(elem).get(0).tagName.toLowerCase() === "time"; // $(elem).is("time"); - } - }); - - // functions that can be called via $(el).timeago('action') - // init is default when no action is given - // functions are called with context of a single element - var functions = { - init: function(){ - var refresh_el = $.proxy(refresh, this); - refresh_el(); - var $s = $t.settings; - if ($s.refreshMillis > 0) { - setInterval(refresh_el, $s.refreshMillis); - } - }, - update: function(time){ - $(this).data('timeago', { datetime: $t.parse(time) }); - refresh.apply(this); - } - }; - - $.fn.timeago = function(action, options) { - var fn = action ? functions[action] : functions.init; - if(!fn){ - throw new Error("Unknown function name '"+ action +"' for timeago"); - } - // each over objects here and call the requested function - this.each(function(){ - fn.call(this, options); - }); - return this; - }; - - function refresh() { - var data = prepareData(this); - if (!isNaN(data.datetime)) { - $(this).text(inWords(data.datetime)); - } - return this; - } - - function prepareData(element) { - element = $(element); - if (!element.data("timeago")) { - element.data("timeago", { datetime: $t.datetime(element) }); - var text = $.trim(element.text()); - if (text.length > 0 && !($t.isTime(element) && element.attr("title"))) { - element.attr("title", text); - } - } - return element.data("timeago"); - } - - function inWords(date) { - return $t.inWords(distance(date)); - } - - function distance(date) { - return (new Date().getTime() - date.getTime()); - } - - // fix for IE6 suckage - document.createElement("abbr"); - document.createElement("time"); -})); From 38909dac1d8b5ded2dd94f5eddc21206934d2231 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Mon, 7 Nov 2016 21:39:38 -0800 Subject: [PATCH 154/175] Bump omniauth-gitlab to 1.0.2 to fix incompatibility with omniauth-oauth2 Closes gitlab-com/support-forum#1270 --- Gemfile | 2 +- Gemfile.lock | 4 ++-- changelogs/unreleased/sh-bump-omniauth-gitlab.yml | 4 ++++ 3 files changed, 7 insertions(+), 3 deletions(-) create mode 100644 changelogs/unreleased/sh-bump-omniauth-gitlab.yml diff --git a/Gemfile b/Gemfile index 5286d2f6d6b..cb2a8470126 100644 --- a/Gemfile +++ b/Gemfile @@ -26,7 +26,7 @@ gem 'omniauth-bitbucket', '~> 0.0.2' gem 'omniauth-cas3', '~> 1.1.2' gem 'omniauth-facebook', '~> 4.0.0' gem 'omniauth-github', '~> 1.1.1' -gem 'omniauth-gitlab', '~> 1.0.0' +gem 'omniauth-gitlab', '~> 1.0.2' gem 'omniauth-google-oauth2', '~> 0.4.1' gem 'omniauth-kerberos', '~> 0.3.0', group: :kerberos gem 'omniauth-saml', '~> 1.7.0' diff --git a/Gemfile.lock b/Gemfile.lock index 165b25c170e..290e4c3e1b3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -456,7 +456,7 @@ GEM omniauth-github (1.1.2) omniauth (~> 1.0) omniauth-oauth2 (~> 1.1) - omniauth-gitlab (1.0.1) + omniauth-gitlab (1.0.2) omniauth (~> 1.0) omniauth-oauth2 (~> 1.0) omniauth-google-oauth2 (0.4.1) @@ -913,7 +913,7 @@ DEPENDENCIES omniauth-cas3 (~> 1.1.2) omniauth-facebook (~> 4.0.0) omniauth-github (~> 1.1.1) - omniauth-gitlab (~> 1.0.0) + omniauth-gitlab (~> 1.0.2) omniauth-google-oauth2 (~> 0.4.1) omniauth-kerberos (~> 0.3.0) omniauth-saml (~> 1.7.0) diff --git a/changelogs/unreleased/sh-bump-omniauth-gitlab.yml b/changelogs/unreleased/sh-bump-omniauth-gitlab.yml new file mode 100644 index 00000000000..17cd5a993dd --- /dev/null +++ b/changelogs/unreleased/sh-bump-omniauth-gitlab.yml @@ -0,0 +1,4 @@ +--- +title: Bump omniauth-gitlab to 1.0.2 to fix incompatibility with omniauth-oauth2 +merge_request: +author: From 34962c7d0833f222aaaea9d6b042542801177699 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 8 Nov 2016 10:13:13 +0200 Subject: [PATCH 155/175] Update non-exist group spinach test to match routing Signed-off-by: Dmitriy Zaporozhets --- features/steps/groups.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/steps/groups.rb b/features/steps/groups.rb index 0e81e99120b..0c88838767c 100644 --- a/features/steps/groups.rb +++ b/features/steps/groups.rb @@ -117,7 +117,7 @@ class Spinach::Features::Groups < Spinach::FeatureSteps end step 'I visit group "NonExistentGroup" page' do - visit group_path(-1) + visit group_path("NonExistentGroup") end step 'the archived project have some issues' do From 659ef54605e37ba750486f25957ec367264dffd4 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Tue, 8 Nov 2016 10:05:19 +0100 Subject: [PATCH 156/175] API: Return 400 when creating a systemhook fails --- .../unreleased/api-return-400-if-post-systemhook-fails.yml | 4 ++++ lib/api/system_hooks.rb | 2 +- spec/requests/api/system_hooks_spec.rb | 6 ++++++ 3 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 changelogs/unreleased/api-return-400-if-post-systemhook-fails.yml diff --git a/changelogs/unreleased/api-return-400-if-post-systemhook-fails.yml b/changelogs/unreleased/api-return-400-if-post-systemhook-fails.yml new file mode 100644 index 00000000000..d132d7e79c3 --- /dev/null +++ b/changelogs/unreleased/api-return-400-if-post-systemhook-fails.yml @@ -0,0 +1,4 @@ +--- +title: Return 400 when creating a system hook fails +merge_request: 7350 +author: Robert Schilling diff --git a/lib/api/system_hooks.rb b/lib/api/system_hooks.rb index 32f731c5652..b6bfff9f20f 100644 --- a/lib/api/system_hooks.rb +++ b/lib/api/system_hooks.rb @@ -32,7 +32,7 @@ module API if hook.save present hook, with: Entities::Hook else - not_found! + render_validation_error!(hook) end end diff --git a/spec/requests/api/system_hooks_spec.rb b/spec/requests/api/system_hooks_spec.rb index f685a3685e6..6c9df21f598 100644 --- a/spec/requests/api/system_hooks_spec.rb +++ b/spec/requests/api/system_hooks_spec.rb @@ -52,6 +52,12 @@ describe API::API, api: true do expect(response).to have_http_status(400) end + it "responds with 400 if url is invalid" do + post api("/hooks", admin), url: 'hp://mep.mep' + + expect(response).to have_http_status(400) + end + it "does not create new hook without url" do expect do post api("/hooks", admin) From dd93079a05d49922fdbe4c221781f39ce69684e8 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Tue, 8 Nov 2016 09:31:08 +0000 Subject: [PATCH 157/175] Changed helper method to check for none on params Moved if statements around in view --- app/helpers/todos_helper.rb | 2 +- app/views/dashboard/todos/index.html.haml | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/helpers/todos_helper.rb b/app/helpers/todos_helper.rb index a75a03b16d2..09c69786791 100644 --- a/app/helpers/todos_helper.rb +++ b/app/helpers/todos_helper.rb @@ -62,7 +62,7 @@ module TodosHelper end def todos_filter_empty? - todos_filter_params.all? {|key, value| value.nil?} + todos_filter_params.values.none? end def todos_filter_path(options = {}) diff --git a/app/views/dashboard/todos/index.html.haml b/app/views/dashboard/todos/index.html.haml index 16bdf284f83..5b2465e25ee 100644 --- a/app/views/dashboard/todos/index.html.haml +++ b/app/views/dashboard/todos/index.html.haml @@ -82,12 +82,9 @@ - elsif current_user.todos.any? .todos-all-done = render "shared/empty_states/todos_all_done.svg" - %h4.text-center - - if todos_filter_empty? - Good job! Looks like you don't have any todos left. - - else - There are no Todos to show. - if todos_filter_empty? + %h4.text-center + Good job! Looks like you don't have any todos left. %p.text-center Are you looking for things to do? Take a look at = succeed "," do @@ -95,6 +92,9 @@ contribute to = link_to "merge requests", merge_requests_dashboard_path or mention someone in a comment to assign a new todo automatically. + - else + %h4.text-center + There are no todos to show. - else .todos-empty .todos-empty-hero From ebc44befdc773b39a171d38dc13c38cd6630828a Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Mon, 7 Nov 2016 20:36:58 +0200 Subject: [PATCH 158/175] Fix broken commits search --- app/controllers/search_controller.rb | 2 +- app/views/search/results/_commit.html.haml | 2 +- changelogs/unreleased/24255-search-fix.yml | 4 ++++ spec/features/global_search_spec.rb | 28 ++++++++++++++++++++++ spec/features/search_spec.rb | 26 ++++++++++++++++++++ spec/spec_helper.rb | 1 + spec/support/search_helpers.rb | 5 ++++ 7 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 changelogs/unreleased/24255-search-fix.yml create mode 100644 spec/features/global_search_spec.rb create mode 100644 spec/support/search_helpers.rb diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb index d01e0dedf52..b666aa01d6b 100644 --- a/app/controllers/search_controller.rb +++ b/app/controllers/search_controller.rb @@ -16,7 +16,7 @@ class SearchController < ApplicationController @group = nil unless can?(current_user, :read_group, @group) end - return if params[:search].nil? || params[:search].blank? + return if params[:search].blank? @search_term = params[:search] diff --git a/app/views/search/results/_commit.html.haml b/app/views/search/results/_commit.html.haml index 5b2d83d6b92..f34eaf89027 100644 --- a/app/views/search/results/_commit.html.haml +++ b/app/views/search/results/_commit.html.haml @@ -1 +1 @@ -= render 'projects/commits/commit', project: @project, commit: commit += render 'projects/commits/commit', project: @project, commit: commit, ref: nil diff --git a/changelogs/unreleased/24255-search-fix.yml b/changelogs/unreleased/24255-search-fix.yml new file mode 100644 index 00000000000..c0afade9bc8 --- /dev/null +++ b/changelogs/unreleased/24255-search-fix.yml @@ -0,0 +1,4 @@ +--- +title: Fix broken commits search +merge_request: +author: diff --git a/spec/features/global_search_spec.rb b/spec/features/global_search_spec.rb new file mode 100644 index 00000000000..f6409e00f22 --- /dev/null +++ b/spec/features/global_search_spec.rb @@ -0,0 +1,28 @@ +require 'spec_helper' + +feature 'Global search', feature: true do + let(:user) { create(:user) } + let(:project) { create(:project, namespace: user.namespace) } + + before do + project.team << [user, :master] + login_with(user) + end + + describe 'I search through the issues and I see pagination' do + before do + allow_any_instance_of(Gitlab::SearchResults).to receive(:per_page).and_return(1) + create_list(:issue, 2, project: project, title: 'initial') + end + + it "has a pagination" do + visit dashboard_projects_path + + fill_in "search", with: "initial" + click_button "Go" + + select_filter("Issues") + expect(page).to have_selector('.gl-pagination .page', count: 2) + end + end +end diff --git a/spec/features/search_spec.rb b/spec/features/search_spec.rb index 1806200c82c..caecd027aaa 100644 --- a/spec/features/search_spec.rb +++ b/spec/features/search_spec.rb @@ -100,6 +100,32 @@ describe "Search", feature: true do expect(page).to have_link(snippet.title) end + + it 'finds a commit' do + visit namespace_project_path(project.namespace, project) + + page.within '.search' do + fill_in 'search', with: 'add' + click_button 'Go' + end + + click_link "Commits" + + expect(page).to have_selector('.commit-row-description') + end + + it 'finds a code' do + visit namespace_project_path(project.namespace, project) + + page.within '.search' do + fill_in 'search', with: 'def' + click_button 'Go' + end + + click_link "Code" + + expect(page).to have_selector('.file-content .code') + end end describe 'Right header search field', feature: true do diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index b2ca856f89f..73cf4c9a24c 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -29,6 +29,7 @@ RSpec.configure do |config| config.include Devise::Test::ControllerHelpers, type: :controller config.include Warden::Test::Helpers, type: :request config.include LoginHelpers, type: :feature + config.include SearchHelpers, type: :feature config.include StubConfiguration config.include EmailHelpers config.include TestEnv diff --git a/spec/support/search_helpers.rb b/spec/support/search_helpers.rb new file mode 100644 index 00000000000..abbbb636d66 --- /dev/null +++ b/spec/support/search_helpers.rb @@ -0,0 +1,5 @@ +module SearchHelpers + def select_filter(name) + find(:xpath, "//ul[contains(@class, 'search-filter')]//a[contains(.,'#{name}')]").click + end +end From 869696bca3d8ff72e2dbaa96744eb7a7d560f0cf Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Tue, 8 Nov 2016 14:21:19 +0200 Subject: [PATCH 159/175] Faster search --- app/models/repository.rb | 4 +++ .../unreleased/faster_project_search.yml | 4 +++ lib/gitlab/project_search_results.rb | 30 ++++++++----------- spec/models/repository_spec.rb | 13 ++++++++ 4 files changed, 33 insertions(+), 18 deletions(-) create mode 100644 changelogs/unreleased/faster_project_search.yml diff --git a/app/models/repository.rb b/app/models/repository.rb index 30be7262438..7d06ce1e85b 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -1064,6 +1064,10 @@ class Repository end def search_files(query, ref) + unless exists? && has_visible_content? && query.present? + return [] + end + offset = 2 args = %W(#{Gitlab.config.git.bin_path} grep -i -I -n --before-context #{offset} --after-context #{offset} -E -e #{Regexp.escape(query)} #{ref || root_ref}) Gitlab::Popen.popen(args, path_to_repo).first.scrub.split(/^--$/) diff --git a/changelogs/unreleased/faster_project_search.yml b/changelogs/unreleased/faster_project_search.yml new file mode 100644 index 00000000000..e29a9f34ed4 --- /dev/null +++ b/changelogs/unreleased/faster_project_search.yml @@ -0,0 +1,4 @@ +--- +title: Faster search inside Project +merge_request: +author: diff --git a/lib/gitlab/project_search_results.rb b/lib/gitlab/project_search_results.rb index 24733435a5a..b8326a64b22 100644 --- a/lib/gitlab/project_search_results.rb +++ b/lib/gitlab/project_search_results.rb @@ -5,11 +5,7 @@ module Gitlab def initialize(current_user, project, query, repository_ref = nil) @current_user = current_user @project = project - @repository_ref = if repository_ref.present? - repository_ref - else - nil - end + @repository_ref = repository_ref.presence @query = query end @@ -47,33 +43,31 @@ module Gitlab private def blobs - if project.empty_repo? || query.blank? - [] - else - project.repository.search_files(query, repository_ref) - end + @blobs ||= project.repository.search_files(query, repository_ref) end def wiki_blobs - if project.wiki_enabled? && query.present? - project_wiki = ProjectWiki.new(project) + @wiki_blobs ||= begin + if project.wiki_enabled? && query.present? + project_wiki = ProjectWiki.new(project) - unless project_wiki.empty? - project_wiki.search_files(query) + unless project_wiki.empty? + project_wiki.search_files(query) + else + [] + end else [] end - else - [] end end def notes - project.notes.user.search(query, as_user: @current_user).order('updated_at DESC') + @notes ||= project.notes.user.search(query, as_user: @current_user).order('updated_at DESC') end def commits - project.repository.find_commits_by_message(query) + @commits ||= project.repository.find_commits_by_message(query) end def project_ids_relation diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index 04b7d19d414..12989d4db53 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -362,6 +362,19 @@ describe Repository, models: true do expect(results.first).not_to start_with('fatal:') end + it 'properly handles when query is not present' do + results = repository.search_files('', 'master') + + expect(results).to match_array([]) + end + + it 'properly handles query when repo is empty' do + repository = create(:empty_project).repository + results = repository.search_files('test', 'master') + + expect(results).to match_array([]) + end + describe 'result' do subject { results.first } From 08d21fe89927fa9ebd3695fde047a17d27893dbf Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 8 Nov 2016 14:32:42 +0200 Subject: [PATCH 160/175] Add small improvements to constrainers and specs Signed-off-by: Dmitriy Zaporozhets --- lib/constraints/group_url_constrainer.rb | 2 +- lib/constraints/user_url_constrainer.rb | 2 +- spec/lib/constraints/group_url_constrainer_spec.rb | 2 +- spec/lib/constraints/user_url_constrainer_spec.rb | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/constraints/group_url_constrainer.rb b/lib/constraints/group_url_constrainer.rb index 2bf973a73da..2af6e1a11c8 100644 --- a/lib/constraints/group_url_constrainer.rb +++ b/lib/constraints/group_url_constrainer.rb @@ -7,7 +7,7 @@ class GroupUrlConstrainer id = extract_resource_path(request.path) if id =~ Gitlab::Regex.namespace_regex - !!Group.find_by_path(id) + Group.find_by(path: id).present? else false end diff --git a/lib/constraints/user_url_constrainer.rb b/lib/constraints/user_url_constrainer.rb index 9583cace022..4d722ad5af2 100644 --- a/lib/constraints/user_url_constrainer.rb +++ b/lib/constraints/user_url_constrainer.rb @@ -7,7 +7,7 @@ class UserUrlConstrainer id = extract_resource_path(request.path) if id =~ Gitlab::Regex.namespace_regex - !!User.find_by('lower(username) = ?', id.downcase) + User.find_by('lower(username) = ?', id.downcase).present? else false end diff --git a/spec/lib/constraints/group_url_constrainer_spec.rb b/spec/lib/constraints/group_url_constrainer_spec.rb index be69a36c2b6..42299b17c2b 100644 --- a/spec/lib/constraints/group_url_constrainer_spec.rb +++ b/spec/lib/constraints/group_url_constrainer_spec.rb @@ -14,6 +14,6 @@ describe GroupUrlConstrainer, lib: true do end def request(path) - OpenStruct.new(path: path) + double(:request, path: path) end end diff --git a/spec/lib/constraints/user_url_constrainer_spec.rb b/spec/lib/constraints/user_url_constrainer_spec.rb index d7b7d5664ff..b3f8530c609 100644 --- a/spec/lib/constraints/user_url_constrainer_spec.rb +++ b/spec/lib/constraints/user_url_constrainer_spec.rb @@ -11,6 +11,6 @@ describe UserUrlConstrainer, lib: true do end def request(path) - OpenStruct.new(path: path) + double(:request, path: path) end end From 5395f92e7ca93a907cdb2507b2ba2073863bc83a Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 8 Nov 2016 15:54:17 +0200 Subject: [PATCH 161/175] Fix routing spec for group controller Signed-off-by: Dmitriy Zaporozhets --- spec/routing/routing_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/routing/routing_spec.rb b/spec/routing/routing_spec.rb index c18a2d55e43..61dca5d5a62 100644 --- a/spec/routing/routing_spec.rb +++ b/spec/routing/routing_spec.rb @@ -266,13 +266,13 @@ describe "Groups", "routing" do end it "also display group#show on the short path" do - allow(Group).to receive(:find_by_path).and_return(true) + allow(Group).to receive(:find_by).and_return(true) expect(get('/1')).to route_to('groups#show', id: '1') end it "also display group#show with dot in the path" do - allow(Group).to receive(:find_by_path).and_return(true) + allow(Group).to receive(:find_by).and_return(true) expect(get('/group.with.dot')).to route_to('groups#show', id: 'group.with.dot') end From 8fec16ac4eda4bc0e908e39d4299c369e15127fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Tue, 8 Nov 2016 15:06:19 +0100 Subject: [PATCH 162/175] Clicking "force remove source branch" label now toggles the checkbox again MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- app/views/shared/issuable/_form.html.haml | 2 +- .../fix-uncheckable-label-for-force_remove_source_branch.yml | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 changelogs/unreleased/fix-uncheckable-label-for-force_remove_source_branch.yml diff --git a/app/views/shared/issuable/_form.html.haml b/app/views/shared/issuable/_form.html.haml index 8d976952781..3176af9c19b 100644 --- a/app/views/shared/issuable/_form.html.haml +++ b/app/views/shared/issuable/_form.html.haml @@ -129,7 +129,7 @@ .col-sm-10.col-sm-offset-2 .checkbox = label_tag 'merge_request[force_remove_source_branch]' do - = hidden_field_tag 'merge_request[force_remove_source_branch]', '0' + = hidden_field_tag 'merge_request[force_remove_source_branch]', '0', id: nil = check_box_tag 'merge_request[force_remove_source_branch]', '1', @merge_request.force_remove_source_branch? Remove source branch when merge request is accepted. diff --git a/changelogs/unreleased/fix-uncheckable-label-for-force_remove_source_branch.yml b/changelogs/unreleased/fix-uncheckable-label-for-force_remove_source_branch.yml new file mode 100644 index 00000000000..8b41063151b --- /dev/null +++ b/changelogs/unreleased/fix-uncheckable-label-for-force_remove_source_branch.yml @@ -0,0 +1,4 @@ +--- +title: Clicking "force remove source branch" label now toggles the checkbox again +merge_request: +author: From 62735ef8fafd941ffe34432c0685078a4b4c4744 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Tue, 8 Nov 2016 23:52:45 +0800 Subject: [PATCH 163/175] Add failed_pipeline and success_pipeline to API doc Feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6342#note_17981448 --- doc/api/notification_settings.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/doc/api/notification_settings.md b/doc/api/notification_settings.md index b3ceaf296a2..aea1c12a392 100644 --- a/doc/api/notification_settings.md +++ b/doc/api/notification_settings.md @@ -79,6 +79,8 @@ curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab | `close_merge_request` | boolean | no | Enable/disable this notification | | `reassign_merge_request` | boolean | no | Enable/disable this notification | | `merge_merge_request` | boolean | no | Enable/disable this notification | +| `failed_pipeline` | boolean | no | Enable/disable this notification | +| `success_pipeline` | boolean | no | Enable/disable this notification | Example response: @@ -143,6 +145,8 @@ curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab | `close_merge_request` | boolean | no | Enable/disable this notification | | `reassign_merge_request` | boolean | no | Enable/disable this notification | | `merge_merge_request` | boolean | no | Enable/disable this notification | +| `failed_pipeline` | boolean | no | Enable/disable this notification | +| `success_pipeline` | boolean | no | Enable/disable this notification | Example responses: @@ -163,7 +167,9 @@ Example responses: "reopen_merge_request": false, "close_merge_request": false, "reassign_merge_request": false, - "merge_merge_request": false + "merge_merge_request": false, + "failed_pipeline": false, + "success_pipeline": false } } ``` From 3e75e453fb258b3e60f3e9606b5f589006a4654b Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Wed, 9 Nov 2016 00:29:07 +0800 Subject: [PATCH 164/175] Try to cover more cases about receivers of pipeline notifications Feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6342#note_17981421 --- doc/workflow/notifications.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/workflow/notifications.md b/doc/workflow/notifications.md index 4824b4e34b9..c936e8833c6 100644 --- a/doc/workflow/notifications.md +++ b/doc/workflow/notifications.md @@ -89,8 +89,8 @@ In all of the below cases, the notification will be sent to: | Reopen merge request | | | Merge merge request | | | New comment | The above, plus anyone mentioned by `@username` in the comment, with notification level "Mention" or higher | -| Failed pipeline | The author of the pipeline and watchers | -| Successful pipeline | The author of the pipeline and watchers | +| Failed pipeline | The above, plus the author of the pipeline | +| Successful pipeline | The above, plus the author of the pipeline | In addition, if the title or description of an Issue or Merge Request is From cd7339a99697b0d539870442652f41f96ed9cfdf Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Tue, 8 Nov 2016 18:05:10 +0100 Subject: [PATCH 165/175] Document the usage of the Docker OverlayFS driver [ci skip] --- doc/ci/docker/using_docker_build.md | 69 ++++++++++++++++++++++++----- 1 file changed, 58 insertions(+), 11 deletions(-) diff --git a/doc/ci/docker/using_docker_build.md b/doc/ci/docker/using_docker_build.md index 959741f7338..89088cf9b83 100644 --- a/doc/ci/docker/using_docker_build.md +++ b/doc/ci/docker/using_docker_build.md @@ -44,7 +44,8 @@ GitLab Runner then executes build scripts as the `gitlab-runner` user. 2. Install Docker Engine on server. - For more information how to install Docker Engine on different systems checkout the [Supported installations](https://docs.docker.com/engine/installation/). + For more information how to install Docker Engine on different systems + checkout the [Supported installations](https://docs.docker.com/engine/installation/). 3. Add `gitlab-runner` user to `docker` group: @@ -122,11 +123,17 @@ In order to do that, follow the steps: Insecure = false ``` -1. You can now use `docker` in the build script (note the inclusion of the `docker:dind` service): +1. You can now use `docker` in the build script (note the inclusion of the + `docker:dind` service): ```yaml image: docker:latest + # When using dind, it's wise to use the overlayfs driver for + # improved performance. + variables: + DOCKER_DRIVER: overlay + services: - docker:dind @@ -140,15 +147,21 @@ In order to do that, follow the steps: - docker run my-docker-image /script/to/run/tests ``` -Docker-in-Docker works well, and is the recommended configuration, but it is not without its own challenges: -* By enabling `--docker-privileged`, you are effectively disabling all of -the security mechanisms of containers and exposing your host to privilege -escalation which can lead to container breakout. For more information, check out the official Docker documentation on -[Runtime privilege and Linux capabilities][docker-cap]. -* Using docker-in-docker, each build is in a clean environment without the past -history. Concurrent builds work fine because every build gets it's own instance of docker engine so they won't conflict with each other. But this also means builds can be slower because there's no caching of layers. -* By default, `docker:dind` uses `--storage-driver vfs` which is the slowest form -offered. +Docker-in-Docker works well, and is the recommended configuration, but it is +not without its own challenges: + +- By enabling `--docker-privileged`, you are effectively disabling all of + the security mechanisms of containers and exposing your host to privilege + escalation which can lead to container breakout. For more information, check + out the official Docker documentation on + [Runtime privilege and Linux capabilities][docker-cap]. +- Using docker-in-docker, each build is in a clean environment without the past + history. Concurrent builds work fine because every build gets it's own + instance of Docker engine so they won't conflict with each other. But this + also means builds can be slower because there's no caching of layers. +- By default, `docker:dind` uses `--storage-driver vfs` which is the slowest + form offered. To use a different driver, see + [Using the overlayfs driver](#using-the-overlayfs-driver). An example project using this approach can be found here: https://gitlab.com/gitlab-examples/docker. @@ -221,6 +234,40 @@ work as expected since volume mounting is done in the context of the host machine, not the build container. e.g. `docker run --rm -t -i -v $(pwd)/src:/home/app/src test-image:latest run_app_tests` +## Using the OverlayFS driver + +By default, when using `docker:dind`, Docker uses the `vfs` storage driver which +copies the filesystem on every run. This is a very disk-intensive operation +which can be avoided if a different driver is used, for example `overlay`. + +1. Make sure a recent kernel is used, preferably `>= 4.2`. +1. Check whether the `overlay` module is loaded: + + ``` + sudo lsmod | grep overlay + ``` + + If you see no result, then it isn't loaded. To load it use: + + ``` + sudo modprobe overlay + ``` + + If everything went fine, you need to make sure module is loaded on reboot. + On Ubuntu systems, this is done by editing `/etc/modules`. Just add the + following line into it: + + ``` + overlay + ``` + +1. Use the driver by defining a variable at the top of your `.gitlab-ci.yml`: + + ``` + variables: + DOCKER_DRIVER: overlay + ``` + ## Using the GitLab Container Registry > **Note:** From 5f2d9ba9ea9d86c409d74004ccf5811bc52a0828 Mon Sep 17 00:00:00 2001 From: tauriedavis Date: Mon, 7 Nov 2016 16:18:42 -0800 Subject: [PATCH 166/175] 24146 Add focus state to buttons and dropdowns --- app/assets/javascripts/application.js | 3 --- app/assets/stylesheets/framework/buttons.scss | 5 ----- app/assets/stylesheets/framework/dropdowns.scss | 5 ++++- app/assets/stylesheets/framework/header.scss | 4 ---- app/assets/stylesheets/framework/nav.scss | 1 - app/assets/stylesheets/framework/sidebar.scss | 1 - app/assets/stylesheets/pages/merge_conflicts.scss | 1 - app/assets/stylesheets/pages/search.scss | 2 -- app/views/layouts/_search.html.haml | 2 +- 9 files changed, 5 insertions(+), 19 deletions(-) diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 7d942de0184..3e277c45094 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -194,9 +194,6 @@ e.preventDefault(); return new ConfirmDangerModal(form, text); }); - $document.on('click', 'button', function () { - return $(this).blur(); - }); $('input[type="search"]').each(function () { var $this = $(this); $this.attr('value', $this.val()); diff --git a/app/assets/stylesheets/framework/buttons.scss b/app/assets/stylesheets/framework/buttons.scss index ed21ad83a1c..e7aff2d0cec 100644 --- a/app/assets/stylesheets/framework/buttons.scss +++ b/app/assets/stylesheets/framework/buttons.scss @@ -6,7 +6,6 @@ &:focus, &:active { - outline: none; background-color: $btn-active-gray; box-shadow: $gl-btn-active-background; } @@ -267,10 +266,6 @@ outline: none; } - &:focus { - outline: none; - } - &:active { outline: none; } diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss index 3e34ec98427..583c17e4a83 100644 --- a/app/assets/stylesheets/framework/dropdowns.scss +++ b/app/assets/stylesheets/framework/dropdowns.scss @@ -38,7 +38,6 @@ text-align: left; border: 1px solid $border-color; border-radius: $border-radius-base; - outline: 0; text-overflow: ellipsis; white-space: nowrap; overflow: hidden; @@ -55,6 +54,10 @@ } } + &.no-outline { + outline: 0; + } + &:hover, { border-color: $dropdown-toggle-hover-border-color; diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss index 4993ca7572a..5a34132112a 100644 --- a/app/assets/stylesheets/framework/header.scss +++ b/app/assets/stylesheets/framework/header.scss @@ -100,10 +100,6 @@ header { &:hover { background-color: $btn-gray-hover; } - - &:focus { - outline: none; - } } } diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss index fcaf5e18633..ce864c2de5e 100644 --- a/app/assets/stylesheets/framework/nav.scss +++ b/app/assets/stylesheets/framework/nav.scss @@ -58,7 +58,6 @@ &:active, &:focus { text-decoration: none; - outline: none; } } diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss index d74c14ee2a4..44c445c0543 100644 --- a/app/assets/stylesheets/framework/sidebar.scss +++ b/app/assets/stylesheets/framework/sidebar.scss @@ -83,7 +83,6 @@ display: block; text-decoration: none; font-weight: normal; - outline: none; &:hover, &:active, diff --git a/app/assets/stylesheets/pages/merge_conflicts.scss b/app/assets/stylesheets/pages/merge_conflicts.scss index 032feae8854..19ab198c2e7 100644 --- a/app/assets/stylesheets/pages/merge_conflicts.scss +++ b/app/assets/stylesheets/pages/merge_conflicts.scss @@ -228,7 +228,6 @@ $colors: ( position: absolute; right: 10px; padding: 0; - outline: none; color: #fff; width: 75px; // static width to make 2 buttons have same width height: 19px; diff --git a/app/assets/stylesheets/pages/search.scss b/app/assets/stylesheets/pages/search.scss index bf688af50e2..b4761df3f23 100644 --- a/app/assets/stylesheets/pages/search.scss +++ b/app/assets/stylesheets/pages/search.scss @@ -31,7 +31,6 @@ padding-right: 20px; border: none; font-size: 14px; - outline: none; padding: 0; margin-left: 5px; line-height: 25px; @@ -229,6 +228,5 @@ &:hover, &:focus { color: $gl-link-color; - outline: none; } } diff --git a/app/views/layouts/_search.html.haml b/app/views/layouts/_search.html.haml index d7386105b7d..8e65bd12c56 100644 --- a/app/views/layouts/_search.html.haml +++ b/app/views/layouts/_search.html.haml @@ -13,7 +13,7 @@ .location-badge= label .search-input-wrap .dropdown{ data: { url: search_autocomplete_path } } - = search_field_tag 'search', nil, placeholder: 'Search', class: 'search-input dropdown-menu-toggle js-search-dashboard-options', spellcheck: false, tabindex: '1', autocomplete: 'off', data: { toggle: 'dropdown', issues_path: issues_dashboard_url, mr_path: merge_requests_dashboard_url } + = search_field_tag 'search', nil, placeholder: 'Search', class: 'search-input dropdown-menu-toggle no-outline js-search-dashboard-options', spellcheck: false, tabindex: '1', autocomplete: 'off', data: { toggle: 'dropdown', issues_path: issues_dashboard_url, mr_path: merge_requests_dashboard_url } .dropdown-menu.dropdown-select = dropdown_content do %ul From b105e3dcbd5ba4ab5da28dfc68916f543e55da2f Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Tue, 8 Nov 2016 22:09:38 +0100 Subject: [PATCH 167/175] Bring back the old JIRA docs https://gitlab.zendesk.com/agent/tickets/48003 [ci skip] --- doc/integration/README.md | 2 +- doc/integration/jira.md | 196 +------------- .../img/builds_emails_service.png | Bin 30956 -> 33943 bytes .../img/jira_add_gitlab_commit_message.png | Bin 0 -> 46590 bytes .../img/jira_add_user_to_group.png | Bin 0 -> 41994 bytes .../img/jira_create_new_group.png | Bin 0 -> 32934 bytes .../img/jira_create_new_group_name.png | Bin 0 -> 9054 bytes .../img/jira_create_new_user.png | Bin 0 -> 21081 bytes .../img/jira_group_access.png | Bin 0 -> 32210 bytes .../img/jira_issue_closed.png | Bin 0 -> 77028 bytes .../img/jira_issue_reference.png | Bin 0 -> 36188 bytes .../img/jira_issues_workflow.png | Bin 0 -> 87067 bytes .../img/jira_merge_request_close.png | Bin 0 -> 102835 bytes .../img/jira_project_name.png | Bin 0 -> 41572 bytes ...reference_commit_message_in_jira_issue.png | Bin 0 -> 33706 bytes doc/project_services/img/jira_service.png | Bin 0 -> 56834 bytes .../img/jira_service_close_issue.png | Bin 0 -> 79569 bytes .../img/jira_service_page.png | Bin 0 -> 36280 bytes .../img/jira_submit_gitlab_merge_request.png | Bin 0 -> 51913 bytes .../img/jira_user_management_link.png | Bin 0 -> 43095 bytes .../img/jira_workflow_screenshot.png | Bin 0 -> 111093 bytes doc/project_services/jira.md | 247 +++++++++++++++++- doc/project_services/project_services.md | 2 +- 23 files changed, 249 insertions(+), 198 deletions(-) create mode 100644 doc/project_services/img/jira_add_gitlab_commit_message.png create mode 100644 doc/project_services/img/jira_add_user_to_group.png create mode 100644 doc/project_services/img/jira_create_new_group.png create mode 100644 doc/project_services/img/jira_create_new_group_name.png create mode 100644 doc/project_services/img/jira_create_new_user.png create mode 100644 doc/project_services/img/jira_group_access.png create mode 100644 doc/project_services/img/jira_issue_closed.png create mode 100644 doc/project_services/img/jira_issue_reference.png create mode 100644 doc/project_services/img/jira_issues_workflow.png create mode 100644 doc/project_services/img/jira_merge_request_close.png create mode 100644 doc/project_services/img/jira_project_name.png create mode 100644 doc/project_services/img/jira_reference_commit_message_in_jira_issue.png create mode 100644 doc/project_services/img/jira_service.png create mode 100644 doc/project_services/img/jira_service_close_issue.png create mode 100644 doc/project_services/img/jira_service_page.png create mode 100644 doc/project_services/img/jira_submit_gitlab_merge_request.png create mode 100644 doc/project_services/img/jira_user_management_link.png create mode 100644 doc/project_services/img/jira_workflow_screenshot.png diff --git a/doc/integration/README.md b/doc/integration/README.md index a928b74f9b8..c2fd299db07 100644 --- a/doc/integration/README.md +++ b/doc/integration/README.md @@ -5,7 +5,7 @@ trackers and external authentication. See the documentation below for details on how to configure these services. -- [JIRA](jira.md) Integrate with the JIRA issue tracker +- [Jira](../project_services/jira.md) Integrate with the JIRA issue tracker - [External issue tracker](external-issue-tracker.md) Redmine, JIRA, etc. - [LDAP](ldap.md) Set up sign in via LDAP - [OmniAuth](omniauth.md) Sign in via Twitter, GitHub, GitLab.com, Google, Bitbucket, Facebook, Shibboleth, SAML, Crowd and Azure diff --git a/doc/integration/jira.md b/doc/integration/jira.md index 2e31fd994de..78aa6634116 100644 --- a/doc/integration/jira.md +++ b/doc/integration/jira.md @@ -1,197 +1,3 @@ # GitLab JIRA integration -GitLab can be configured to interact with JIRA. Configuration happens via -user name and password. Connecting to a JIRA server via CAS is not possible. - -Each project can be configured to connect to a different JIRA instance, see the -[configuration](#configuration) section. If you have one JIRA instance you can -pre-fill the settings page with a default template. To configure the template -see the [Services Templates][services-templates] document. - -Once the project is connected to JIRA, you can reference and close the issues -in JIRA directly from GitLab. - -## Table of Contents -* [Referencing JIRA Issues from GitLab](#referencing-JIRA-issues) -* [Closing JIRA Issues from GitLab](#closing-JIRA-issues) -* [Configuration](#configuration) - -### Referencing JIRA Issues - -When GitLab project has JIRA issue tracker configured and enabled, mentioning -JIRA issue in GitLab will automatically add a comment in JIRA issue with the -link back to GitLab. This means that in comments in merge requests and commits -referencing an issue, eg. `PROJECT-7`, will add a comment in JIRA issue in the -format: - -``` - USER mentioned this issue in RESOURCE_NAME of [PROJECT_NAME|LINK_TO_COMMENT]: - ENTITY_TITLE -``` - -* `USER` A user that mentioned the issue. This is the link to the user profile in GitLab. -* `LINK_TO_THE_COMMENT` Link to the origin of mention with a name of the entity where JIRA issue was mentioned. -* `RESOURCE_NAME` Kind of resource which referenced the issue. Can be a commit or merge request. -* `PROJECT_NAME` GitLab project name. -* `ENTITY_TITLE` Merge request title or commit message first line. - -![example of mentioning or closing the JIRA issue](img/jira_issue_reference.png) - ---- - -### Closing JIRA Issues - -JIRA issues can be closed directly from GitLab by using trigger words, eg. -`Resolves PROJECT-1`, `Closes PROJECT-1` or `Fixes PROJECT-1`, in commits and -merge requests. When a commit which contains the trigger word in the commit -message is pushed, GitLab will add a comment in the mentioned JIRA issue. - -For example, for project named `PROJECT` in JIRA, we implemented a new feature -and created a merge request in GitLab. - -This feature was requested in JIRA issue `PROJECT-7`. Merge request in GitLab -contains the improvement and in merge request description we say that this -merge request `Closes PROJECT-7` issue. - -Once this merge request is merged, the JIRA issue will be automatically closed -with a link to the commit that resolved the issue. - -![A Git commit that causes the JIRA issue to be closed](img/jira_merge_request_close.png) - ---- - -![The GitLab integration user leaves a comment on JIRA](img/jira_service_close_issue.png) - ---- - -## Configuration - -### Configuring JIRA - -We need to create a user in JIRA which will have access to all projects that -need to integrate with GitLab. Login to your JIRA instance as admin and under -Administration go to User Management and create a new user. - -As an example, we'll create a user named `gitlab` and add it to `JIRA-developers` -group. - -**It is important that the user `GitLab` has write-access to projects in JIRA** - -We have split this stage in steps so it is easier to follow. - ---- - -1. Login to your JIRA instance as an administrator and under **Administration** - go to **User Management** to create a new user. - - ![JIRA user management link](img/jira_user_management_link.png) - - --- - -1. The next step is to create a new user (e.g., `gitlab`) who has write access - to projects in JIRA. Enter the user's name and a _valid_ e-mail address - since JIRA sends a verification e-mail to set-up the password. - _**Note:** JIRA creates the username automatically by using the e-mail - prefix. You can change it later if you want._ - - ![JIRA create new user](img/jira_create_new_user.png) - - --- - -1. Now, let's create a `gitlab-developers` group which will have write access - to projects in JIRA. Go to the **Groups** tab and select **Create group**. - - ![JIRA create new user](img/jira_create_new_group.png) - - --- - - Give it an optional description and hit **Create group**. - - ![jira create new group](img/jira_create_new_group_name.png) - - --- - -1. Give the newly-created group write access by going to - **Application access > View configuration** and adding the `gitlab-developers` - group to JIRA Core. - - ![JIRA group access](img/jira_group_access.png) - - --- - -1. Add the `gitlab` user to the `gitlab-developers` group by going to - **Users > GitLab user > Add group** and selecting the `gitlab-developers` - group from the dropdown menu. Notice that the group says _Access_ which is - what we aim for. - - ![JIRA add user to group](img/jira_add_user_to_group.png) - ---- - -The JIRA configuration is over. Write down the new JIRA username and its -password as they will be needed when configuring GitLab in the next section. - -### Configuring GitLab - -JIRA configuration in GitLab is done via a project's **Services**. - -#### GitLab 8.13.0 with JIRA v1000.x - -To enable JIRA integration in a project, navigate to the project's -and open the context menu clicking on the top right gear icon, then go to -**Services > JIRA**. - -Fill in the required details on the page as described in the table below. - -| Field | Description | -| ----- | ----------- | -| `URL` | The base URL to the JIRA project which is being linked to this GitLab project. Ex. https://JIRA.example.com | -| `Project key` | The short, all capital letter identifier for your JIRA project. | -| `Username` | The user name created in [configuring JIRA step](#configuring-JIRA). | -| `Password` |The password of the user created in [configuring JIRA step](#configuring-JIRA). | -| `JIRA issue transition` | This is the ID of a transition that moves issues to a closed state. You can find this number under JIRA workflow administration ([see screenshot](img/jira_workflow_screenshot.png)). | - -After saving the configuration, your GitLab project will be able to interact -with the linked JIRA project. - -![JIRA service page](img/jira_service_page.png) - ---- - -#### GitLab 6.x-7.7 with JIRA v6.x - -_**Note:** GitLab versions 8.13.0 and up contain various integration improvements. -We strongly recommend upgrading._ - -In `gitlab.yml` enable the JIRA issue tracker section by -[uncommenting these lines][JIRA-gitlab-yml]. This will make sure that all -issues within GitLab are pointing to the JIRA issue tracker. - -After you set this, you will be able to close issues in JIRA by a commit in -GitLab. - -Go to your project's **Settings** page and fill in the project name for the -JIRA project: - -![Set the JIRA project name in GitLab to 'NEW'](img/jira_project_name.png) - ---- - -You can also enable the JIRA service that will allow you to interact with JIRA -issues. Go to the **Settings > Services > JIRA** and: - -1. Tick the active check box to enable the service -1. Supply the URL to JIRA server, for example http://JIRA.example.com -1. Supply the username of a user we created under `Configuring JIRA` section, - for example `gitlab` -1. Supply the password of the user -1. Optional: supply the JIRA API version, default is version `2` -1. Optional: supply the JIRA issue transition ID (issue transition to closed). - This is dependent on JIRA settings, default is `2` -1. Hit save - - -![JIRA services page](img/jira_service.png) - -[services-templates]: ../project_services/services_templates.md -[JIRA-gitlab-yml]: https://gitlab.com/subscribers/gitlab-ee/blob/6-8-stable-ee/config/gitlab.yml.example#L111-115 +This document was moved under [project_services/jira](../project_services/jira.md). diff --git a/doc/project_services/img/builds_emails_service.png b/doc/project_services/img/builds_emails_service.png index 440728795beac492656846ccbe709cfef179e021..88943dc410e8ad8a7edee5ff3dcc7d162ab00390 100644 GIT binary patch literal 33943 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 U`iU|F@E1rzR7NCUSoh=q0PkGbCjbBd diff --git a/doc/project_services/img/jira_add_gitlab_commit_message.png b/doc/project_services/img/jira_add_gitlab_commit_message.png new file mode 100644 index 0000000000000000000000000000000000000000..aec472b911896de0354ca560a148ccca7f8b82fb GIT binary patch literal 46590 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 VyK8cW1^i`)&Q<*@d4E|x{Xf3ERG0t& literal 0 HcmV?d00001 diff --git a/doc/project_services/img/jira_add_user_to_group.png b/doc/project_services/img/jira_add_user_to_group.png new file mode 100644 index 0000000000000000000000000000000000000000..0ba737bda9a713c4ac57fe795c10b1af133a8dde GIT binary patch literal 41994 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

d*?Vn$ST$J0n^=G1Aj;3WcO78` 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˅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 literal 0 HcmV?d00001 diff --git a/doc/project_services/img/jira_reference_commit_message_in_jira_issue.png b/doc/project_services/img/jira_reference_commit_message_in_jira_issue.png new file mode 100644 index 0000000000000000000000000000000000000000..fb270d85e3c9c4dc05f7ddb2d9b0fbb44ad3593b GIT binary patch literal 33706 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%0DXcAk+aYdtg1CjNkN0n}J^9zsutn<)6$spF7 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 literal 0 HcmV?d00001 diff --git a/doc/project_services/img/jira_service.png b/doc/project_services/img/jira_service.png new file mode 100644 index 0000000000000000000000000000000000000000..13aefce6f84628fa4e0bb05c674a96a6e12e4948 GIT binary patch literal 56834 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 literal 0 HcmV?d00001 diff --git a/doc/project_services/img/jira_user_management_link.png b/doc/project_services/img/jira_user_management_link.png new file mode 100644 index 0000000000000000000000000000000000000000..5f002b59bac3ad76482355ac4534a1c297e3c636 GIT binary patch literal 43095 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:** +Full JIRA integration was previously exclusive to GitLab Enterprise Edition. +With [GitLab 8.3 forward][8_3_post], this feature in now [backported][jira-ce] +to GitLab Community Edition as well. + +--- + +GitLab can be configured to interact with [JIRA Core] either using an +on-premises instance or the SaaS solution that Atlassian offers. Configuration +happens via username and password on a per-project basis. Connecting to a JIRA +server via CAS is not possible. + +Each project can be configured to connect to a different JIRA instance or, in +case you have a single JIRA instance, you can pre-fill the JIRA service +settings page in GitLab with a default template. To configure the JIRA template, +see the [Services Templates documentation][services-templates]. + +Once the GitLab project is connected to JIRA, you can reference and close the +issues in JIRA directly from GitLab's merge requests. + +## Configuration + +The configuration consists of two parts: + +- [JIRA configuration](#configuring-jira) +- [GitLab configuration](#configuring-gitlab) + +### Configuring JIRA + +First things first, we need to create a user in JIRA which will have access to +all projects that need to integrate with GitLab. + +We have split this stage in steps so it is easier to follow. + +--- + +1. Login to your JIRA instance as an administrator and under **Administration** + go to **User Management** to create a new user. + + ![JIRA user management link](img/jira_user_management_link.png) + + --- + +1. The next step is to create a new user (e.g., `gitlab`) who has write access + to projects in JIRA. Enter the user's name and a _valid_ e-mail address + since JIRA sends a verification e-mail to set-up the password. + _**Note:** JIRA creates the username automatically by using the e-mail + prefix. You can change it later if you want._ + + ![JIRA create new user](img/jira_create_new_user.png) + + --- + +1. Now, let's create a `gitlab-developers` group which will have write access + to projects in JIRA. Go to the **Groups** tab and select **Create group**. + + ![JIRA create new user](img/jira_create_new_group.png) + + --- + + Give it an optional description and hit **Create group**. + + ![JIRA create new group](img/jira_create_new_group_name.png) + + --- + +1. Give the newly-created group write access by going to + **Application access > View configuration** and adding the `gitlab-developers` + group to JIRA Core. + + ![JIRA group access](img/jira_group_access.png) + + --- + +1. Add the `gitlab` user to the `gitlab-developers` group by going to + **Users > GitLab user > Add group** and selecting the `gitlab-developers` + group from the dropdown menu. Notice that the group says _Access_ which is + what we aim for. + + ![JIRA add user to group](img/jira_add_user_to_group.png) + +--- + +The JIRA configuration is over. Write down the new JIRA username and its +password as they will be needed when configuring GitLab in the next section. + +### Configuring GitLab + +>**Note:** +The currently supported JIRA versions are v6.x and v7.x. and GitLab +7.8 or higher is required. + +--- + +Assuming you [have already configured JIRA](#configuring-jira), now it's time +to configure GitLab. + +JIRA configuration in GitLab is done via a project's +[**Services**](../project_services/project_services.md). + +To enable JIRA integration in a project, navigate to the project's +**Settings > Services > JIRA**. + +Fill in the required details on the page, as described in the table below. + +| Setting | Description | +| ------- | ----------- | +| `Description` | A name for the issue tracker (to differentiate between instances, for example). | +| `Project url` | The URL to the JIRA project which is being linked to this GitLab project. It is of the form: `https:///issues/?jql=project=`. | +| `Issues url` | The URL to the JIRA project issues overview for the project that is linked to this GitLab project. It is of the form: `https:///browse/:id`. Leave `:id` as-is, it gets replaced by GitLab at runtime. | +| `New issue url` | This is the URL to create a new issue in JIRA for the project linked to this GitLab project, and it is of the form: `https:///secure/CreateIssue.jspa` | +| `Api url` | The base URL of the JIRA API. It may be omitted, in which case GitLab will automatically use API version `2` based on the `project url`. It is of the form: `https:///rest/api/2`. | +| `Username` | The username of the user created in [configuring JIRA step](#configuring-jira). | +| `Password` |The password of the user created in [configuring JIRA step](#configuring-jira). | +| `JIRA issue transition` | This setting is very important to set up correctly. It is the ID of a transition that moves issues to a closed state. You can find this number under the JIRA workflow administration (**Administration > Issues > Workflows**) by selecting **View** under **Operations** of the desired workflow of your project. The ID of each state can be found inside the parenthesis of each transition name under the **Transitions (id)** column ([see screenshot][trans]). By default, this ID is set to `2`. | + +After saving the configuration, your GitLab project will be able to interact +with the linked JIRA project. + +For example, given the settings below: + +- the JIRA URL is `https://jira.example.com` +- the project is named `GITLAB` +- the user is named `gitlab` +- the JIRA issue transition is 151 (based on the [JIRA issue transition][trans]) + +the following screenshot shows how the JIRA service settings should look like. + +![JIRA service page](img/jira_service_page.png) + +[trans]: img/jira_issues_workflow.png + +--- + +## JIRA issues + +By now you should have [configured JIRA](#configuring-jira) and enabled the +[JIRA service in GitLab](#configuring-gitlab). If everything is set up correctly +you should be able to reference and close JIRA issues by just mentioning their +ID in GitLab commits and merge requests. + +### Referencing JIRA Issues + +If you reference a JIRA issue, e.g., `GITLAB-1`, in a commit comment, a link +which points back to JIRA is created. + +The same works for comments in merge requests as well. + +![JIRA add GitLab commit message](img/jira_add_gitlab_commit_message.png) + +--- + +The mentioning action is two-fold, so a comment with a JIRA issue in GitLab +will automatically add a comment in that particular JIRA issue with the link +back to GitLab. + + +![JIRA reference commit message](img/jira_reference_commit_message_in_jira_issue.png) + +--- + +The comment on the JIRA issue is of the form: + +> USER mentioned this issue in LINK_TO_THE_MENTION + +Where: + +| Format | Description | +| ------ | ----------- | +| `USER` | A user that mentioned the issue. This is the link to the user profile in GitLab. | +| `LINK_TO_THE_MENTION` | Link to the origin of mention with a name of the entity where JIRA issue was mentioned. Can be commit or merge request. | + +### Closing JIRA issues + +JIRA issues can be closed directly from GitLab by using trigger words in +commits and merge requests. When a commit which contains the trigger word +followed by the JIRA issue ID in the commit message is pushed, GitLab will +add a comment in the mentioned JIRA issue and immediately close it (provided +the transition ID was set up correctly). + +There are currently three trigger words, and you can use either one to achieve +the same goal: + +- `Resolves GITLAB-1` +- `Closes GITLAB-1` +- `Fixes GITLAB-1` + +where `GITLAB-1` the issue ID of the JIRA project. + +### JIRA issue closing example + +Let's say for example that we submitted a bug fix and created a merge request +in GitLab. The workflow would be something like this: + +1. Create a new branch +1. Fix the bug +1. Commit the changes and push branch to GitLab +1. Open a new merge request and reference the JIRA issue including one of the + trigger words, e.g.: `Fixes GITLAB-1`, in the description +1. Submit the merge request +1. Ask someone to review +1. Merge the merge request +1. The JIRA issue is automatically closed + +--- + +In the following screenshot you can see what the link references to the JIRA +issue look like. + +![JIRA - submit a GitLab merge request](img/jira_submit_gitlab_merge_request.png) + +--- + +Once this merge request is merged, the JIRA issue will be automatically closed +with a link to the commit that resolved the issue. + +![The GitLab integration user leaves a comment on JIRA](img/jira_issue_closed.png) + +--- + +You can see from the above image that there are four references to GitLab: + +- The first is from a comment in a specific commit +- The second is from the JIRA issue reference in the merge request description +- The third is from the actual commit that solved the issue +- And the fourth is from the commit that the merge request created + +[services-templates]: ../project_services/services_templates.md "Services templates documentation" +[JIRA Core]: https://www.atlassian.com/software/jira/core "The JIRA Core website" +[jira-ce]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/2146 "MR - Backport JIRA service" +[8_3_post]: https://about.gitlab.com/2015/12/22/gitlab-8-3-released/ "GitLab 8.3 release post" + +## Troubleshooting + +### GitLab is unable to comment on a ticket + +Make sure that the user you set up for GitLab to communicate with JIRA has the +correct access permission to post comments on a ticket and to also transition the +ticket, if you'd like GitLab to also take care of closing them. + +### GitLab is unable to close a ticket + +Make sure the the `Transition ID` you set within the JIRA settings matches the +one your project needs to close a ticket. diff --git a/doc/project_services/project_services.md b/doc/project_services/project_services.md index 8116a1ce976..4442b7c1742 100644 --- a/doc/project_services/project_services.md +++ b/doc/project_services/project_services.md @@ -40,7 +40,7 @@ further configuration instructions and details. Contributions are welcome. | Gemnasium | Gemnasium monitors your project dependencies and alerts you about updates and security vulnerabilities | | [HipChat](hipchat.md) | Private group chat and IM | | [Irker (IRC gateway)](irker.md) | Send IRC messages, on update, to a list of recipients through an Irker gateway | -| [JIRA](../integration/jira.md) | JIRA issue tracker | +| [JIRA](jira.md) | JIRA issue tracker | | JetBrains TeamCity CI | A continuous integration and build server | | PivotalTracker | Project Management Software (Source Commits Endpoint) | | Pushover | Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop | From dc307830571aaca1ff20b409d7075eee83f21fb9 Mon Sep 17 00:00:00 2001 From: Drew Blessing Date: Thu, 29 Sep 2016 14:08:27 -0500 Subject: [PATCH 168/175] Introduce better credential and error checking to `rake gitlab:ldap:check` It was previously possible for invalid credential errors to go unnoticed in this task. Users would believe everything was configured correctly and then sign in would fail with 'invalid credentials'. This adds a specific bind check, plus catches errors connecting to the server. Also, specs :) --- changelogs/unreleased/ldap_check_bind.yml | 4 + doc/administration/auth/ldap.md | 4 + .../img}/raketasks/check_repos_output.png | Bin doc/administration/raketasks/check.md | 97 ++++++++++++++++++ doc/raketasks/check.md | 62 +---------- lib/gitlab/ldap/config.rb | 8 +- lib/tasks/gitlab/check.rake | 39 +++++-- spec/lib/gitlab/ldap/config_spec.rb | 39 ++++++- spec/tasks/gitlab/check_rake_spec.rb | 51 +++++++++ 9 files changed, 226 insertions(+), 78 deletions(-) create mode 100644 changelogs/unreleased/ldap_check_bind.yml rename doc/{ => administration/img}/raketasks/check_repos_output.png (100%) create mode 100644 doc/administration/raketasks/check.md create mode 100644 spec/tasks/gitlab/check_rake_spec.rb diff --git a/changelogs/unreleased/ldap_check_bind.yml b/changelogs/unreleased/ldap_check_bind.yml new file mode 100644 index 00000000000..daff8103a07 --- /dev/null +++ b/changelogs/unreleased/ldap_check_bind.yml @@ -0,0 +1,4 @@ +--- +title: Introduce better credential and error checking to `rake gitlab:ldap:check` +merge_request: 6601 +author: diff --git a/doc/administration/auth/ldap.md b/doc/administration/auth/ldap.md index bf7814875bf..fd23047f027 100644 --- a/doc/administration/auth/ldap.md +++ b/doc/administration/auth/ldap.md @@ -35,6 +35,10 @@ of one hour. To enable LDAP integration you need to add your LDAP server settings in `/etc/gitlab/gitlab.rb` or `/home/git/gitlab/config/gitlab.yml`. +There is a Rake task to check LDAP configuration. After configuring LDAP +using the documentation below, see [LDAP check Rake task](../raketasks/check.md#ldap-check) +for information on the LDAP check Rake task. + >**Note**: In GitLab EE, you can configure multiple LDAP servers to connect to one GitLab server. diff --git a/doc/raketasks/check_repos_output.png b/doc/administration/img/raketasks/check_repos_output.png similarity index 100% rename from doc/raketasks/check_repos_output.png rename to doc/administration/img/raketasks/check_repos_output.png diff --git a/doc/administration/raketasks/check.md b/doc/administration/raketasks/check.md new file mode 100644 index 00000000000..d1d2fed4861 --- /dev/null +++ b/doc/administration/raketasks/check.md @@ -0,0 +1,97 @@ +# Check Rake Tasks + +## Repository Integrity + +Even though Git is very resilient and tries to prevent data integrity issues, +there are times when things go wrong. The following Rake tasks intend to +help GitLab administrators diagnose problem repositories so they can be fixed. + +There are 3 things that are checked to determine integrity. + +1. Git repository file system check ([git fsck](https://git-scm.com/docs/git-fsck)). + This step verifies the connectivity and validity of objects in the repository. +1. Check for `config.lock` in the repository directory. +1. Check for any branch/references lock files in `refs/heads`. + +It's important to note that the existence of `config.lock` or reference locks +alone do not necessarily indicate a problem. Lock files are routinely created +and removed as Git and GitLab perform operations on the repository. They serve +to prevent data integrity issues. However, if a Git operation is interrupted these +locks may not be cleaned up properly. + +The following symptoms may indicate a problem with repository integrity. If users +experience these symptoms you may use the rake tasks described below to determine +exactly which repositories are causing the trouble. + +- Receiving an error when trying to push code - `remote: error: cannot lock ref` +- A 500 error when viewing the GitLab dashboard or when accessing a specific project. + +### Check all GitLab repositories + +This task loops through all repositories on the GitLab server and runs the +3 integrity checks described previously. + +**Omnibus Installation** + +``` +sudo gitlab-rake gitlab:repo:check +``` + +**Source Installation** + +```bash +sudo -u git -H bundle exec rake gitlab:repo:check RAILS_ENV=production +``` + +### Check repositories for a specific user + +This task checks all repositories that a specific user has access to. This is important +because sometimes you know which user is experiencing trouble but you don't know +which project might be the cause. + +If the rake task is executed without brackets at the end, you will be prompted +to enter a username. + +**Omnibus Installation** + +```bash +sudo gitlab-rake gitlab:user:check_repos +sudo gitlab-rake gitlab:user:check_repos[] +``` + +**Source Installation** + +```bash +sudo -u git -H bundle exec rake gitlab:user:check_repos RAILS_ENV=production +sudo -u git -H bundle exec rake gitlab:user:check_repos[] RAILS_ENV=production +``` + +Example output: + +![gitlab:user:check_repos output](../img/raketasks/check_repos_output.png) + +## LDAP Check + +The LDAP check Rake task will test the bind_dn and password credentials +(if configured) and will list a sample of LDAP users. This task is also +executed as part of the `gitlab:check` task, but can run independently +using the command below. + +**Omnibus Installation** + +``` +sudo gitlab-rake gitlab:ldap:check +``` + +**Source Installation** + +```bash +sudo -u git -H bundle exec rake gitlab:ldap:check RAILS_ENV=production +``` + +By default, the task will return a sample of 100 LDAP users. Change this +limit by passing a number to the check task: + +```bash +rake gitlab:ldap:check[50] +``` diff --git a/doc/raketasks/check.md b/doc/raketasks/check.md index 3ff3fee6a40..f7f6a40cd04 100644 --- a/doc/raketasks/check.md +++ b/doc/raketasks/check.md @@ -1,63 +1,3 @@ # Check Rake Tasks -## Repository Integrity - -Even though Git is very resilient and tries to prevent data integrity issues, -there are times when things go wrong. The following Rake tasks intend to -help GitLab administrators diagnose problem repositories so they can be fixed. - -There are 3 things that are checked to determine integrity. - -1. Git repository file system check ([git fsck](https://git-scm.com/docs/git-fsck)). - This step verifies the connectivity and validity of objects in the repository. -1. Check for `config.lock` in the repository directory. -1. Check for any branch/references lock files in `refs/heads`. - -It's important to note that the existence of `config.lock` or reference locks -alone do not necessarily indicate a problem. Lock files are routinely created -and removed as Git and GitLab perform operations on the repository. They serve -to prevent data integrity issues. However, if a Git operation is interrupted these -locks may not be cleaned up properly. - -The following symptoms may indicate a problem with repository integrity. If users -experience these symptoms you may use the rake tasks described below to determine -exactly which repositories are causing the trouble. - -- Receiving an error when trying to push code - `remote: error: cannot lock ref` -- A 500 error when viewing the GitLab dashboard or when accessing a specific project. - -### Check all GitLab repositories - -This task loops through all repositories on the GitLab server and runs the -3 integrity checks described previously. - -``` -# omnibus-gitlab -sudo gitlab-rake gitlab:repo:check - -# installation from source -bundle exec rake gitlab:repo:check RAILS_ENV=production -``` - -### Check repositories for a specific user - -This task checks all repositories that a specific user has access to. This is important -because sometimes you know which user is experiencing trouble but you don't know -which project might be the cause. - -If the rake task is executed without brackets at the end, you will be prompted -to enter a username. - -```bash -# omnibus-gitlab -sudo gitlab-rake gitlab:user:check_repos -sudo gitlab-rake gitlab:user:check_repos[] - -# installation from source -bundle exec rake gitlab:user:check_repos RAILS_ENV=production -bundle exec rake gitlab:user:check_repos[] RAILS_ENV=production -``` - -Example output: - -![gitlab:user:check_repos output](check_repos_output.png) +This document was moved to [administration/raketasks/check](../administration/raketasks/check.md). diff --git a/lib/gitlab/ldap/config.rb b/lib/gitlab/ldap/config.rb index f9bb5775323..6ea069d26df 100644 --- a/lib/gitlab/ldap/config.rb +++ b/lib/gitlab/ldap/config.rb @@ -92,6 +92,10 @@ module Gitlab options['timeout'].to_i end + def has_auth? + options['password'] || options['bind_dn'] + end + protected def base_config @@ -122,10 +126,6 @@ module Gitlab } } end - - def has_auth? - options['password'] || options['bind_dn'] - end end end end diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake index 2ae48a970ce..35c4194e87c 100644 --- a/lib/tasks/gitlab/check.rake +++ b/lib/tasks/gitlab/check.rake @@ -760,7 +760,7 @@ namespace :gitlab do end namespace :ldap do - task :check, [:limit] => :environment do |t, args| + task :check, [:limit] => :environment do |_, args| # Only show up to 100 results because LDAP directories can be very big. # This setting only affects the `rake gitlab:check` script. args.with_defaults(limit: 100) @@ -768,7 +768,7 @@ namespace :gitlab do start_checking "LDAP" if Gitlab::LDAP::Config.enabled? - print_users(args.limit) + check_ldap(args.limit) else puts 'LDAP is disabled in config/gitlab.yml' end @@ -776,21 +776,42 @@ namespace :gitlab do finished_checking "LDAP" end - def print_users(limit) - puts "LDAP users with access to your GitLab server (only showing the first #{limit} results)" - + def check_ldap(limit) servers = Gitlab::LDAP::Config.providers servers.each do |server| puts "Server: #{server}" - Gitlab::LDAP::Adapter.open(server) do |adapter| - users = adapter.users(adapter.config.uid, '*', limit) - users.each do |user| - puts "\tDN: #{user.dn}\t #{adapter.config.uid}: #{user.uid}" + + begin + Gitlab::LDAP::Adapter.open(server) do |adapter| + check_ldap_auth(adapter) + + puts "LDAP users with access to your GitLab server (only showing the first #{limit} results)" + + users = adapter.users(adapter.config.uid, '*', limit) + users.each do |user| + puts "\tDN: #{user.dn}\t #{adapter.config.uid}: #{user.uid}" + end end + rescue Net::LDAP::ConnectionRefusedError, Errno::ECONNREFUSED => e + puts "Could not connect to the LDAP server: #{e.message}".color(:red) end end end + + def check_ldap_auth(adapter) + auth = adapter.config.has_auth? + + if auth && adapter.ldap.bind + message = 'Success'.color(:green) + elsif auth + message = 'Failed. Check `bind_dn` and `password` configuration values'.color(:red) + else + message = 'Anonymous. No `bind_dn` or `password` configured'.color(:yellow) + end + + puts "LDAP authentication... #{message}" + end end namespace :repo do diff --git a/spec/lib/gitlab/ldap/config_spec.rb b/spec/lib/gitlab/ldap/config_spec.rb index 835853a83a4..f5ebe703083 100644 --- a/spec/lib/gitlab/ldap/config_spec.rb +++ b/spec/lib/gitlab/ldap/config_spec.rb @@ -1,20 +1,51 @@ require 'spec_helper' describe Gitlab::LDAP::Config, lib: true do - let(:config) { Gitlab::LDAP::Config.new provider } - let(:provider) { 'ldapmain' } + include LdapHelpers + + let(:config) { Gitlab::LDAP::Config.new('ldapmain') } describe '#initalize' do it 'requires a provider' do expect{ Gitlab::LDAP::Config.new }.to raise_error ArgumentError end - it "works" do + it 'works' do expect(config).to be_a described_class end - it "raises an error if a unknow provider is used" do + it 'raises an error if a unknown provider is used' do expect{ Gitlab::LDAP::Config.new 'unknown' }.to raise_error(RuntimeError) end end + + describe '#has_auth?' do + it 'is true when password is set' do + stub_ldap_config( + options: { + 'bind_dn' => 'uid=admin,dc=example,dc=com', + 'password' => 'super_secret' + } + ) + + expect(config.has_auth?).to be_truthy + end + + it 'is true when bind_dn is set and password is empty' do + stub_ldap_config( + options: { + 'bind_dn' => 'uid=admin,dc=example,dc=com', + 'password' => '' + } + ) + + expect(config.has_auth?).to be_truthy + end + + it 'is false when password and bind_dn are not set' do + stub_ldap_config(options: { 'bind_dn' => nil, 'password' => nil }) + + expect(config.has_auth?).to be_falsey + end + end end diff --git a/spec/tasks/gitlab/check_rake_spec.rb b/spec/tasks/gitlab/check_rake_spec.rb new file mode 100644 index 00000000000..538ff952bf4 --- /dev/null +++ b/spec/tasks/gitlab/check_rake_spec.rb @@ -0,0 +1,51 @@ +require 'rake_helper' + +describe 'gitlab:ldap:check rake task' do + include LdapHelpers + + before do + Rake.application.rake_require 'tasks/gitlab/check' + + stub_warn_user_is_not_gitlab + end + + context 'when LDAP is not enabled' do + it 'does not attempt to bind or search for users' do + expect(Gitlab::LDAP::Config).not_to receive(:providers) + expect(Gitlab::LDAP::Adapter).not_to receive(:open) + + run_rake_task('gitlab:ldap:check') + end + end + + context 'when LDAP is enabled' do + let(:ldap) { double(:ldap) } + let(:adapter) { ldap_adapter('ldapmain', ldap) } + + before do + allow(Gitlab::LDAP::Config) + .to receive_messages( + enabled?: true, + providers: ['ldapmain'] + ) + allow(Gitlab::LDAP::Adapter).to receive(:open).and_yield(adapter) + allow(adapter).to receive(:users).and_return([]) + end + + it 'attempts to bind using credentials' do + stub_ldap_config(has_auth?: true) + + expect(ldap).to receive(:bind) + + run_rake_task('gitlab:ldap:check') + end + + it 'searches for 100 LDAP users' do + stub_ldap_config(uid: 'uid') + + expect(adapter).to receive(:users).with('uid', '*', 100) + + run_rake_task('gitlab:ldap:check') + end + end +end From 79d94b167999544086db235602a9213a2d37831e Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Wed, 26 Oct 2016 17:34:06 +0000 Subject: [PATCH 169/175] Merge branch '22481-honour-issue-visibility-for-groups' into 'security' Honour issue and merge request visibility in their respective finders This MR fixes a security issue with the IssuesFinder and MergeRequestFinder where they would return items the user did not have permission to see. This was most visible on the issue and merge requests page for a group containing projects that had set their issues or merge requests to "private". Closes https://gitlab.com/gitlab-org/gitlab-ce/issues/22481 See merge request !2000 --- app/finders/issuable_finder.rb | 33 +++++------ app/models/concerns/issuable.rb | 6 +- app/models/project.rb | 34 ++++++++++- app/models/project_feature.rb | 14 ++++- spec/features/groups/issues_spec.rb | 8 +++ spec/features/groups/merge_requests_spec.rb | 8 +++ spec/models/concerns/issuable_spec.rb | 5 ++ ...ures_apply_to_issuables_shared_examples.rb | 56 +++++++++++++++++++ 8 files changed, 139 insertions(+), 25 deletions(-) create mode 100644 spec/features/groups/issues_spec.rb create mode 100644 spec/features/groups/merge_requests_spec.rb create mode 100644 spec/support/project_features_apply_to_issuables_shared_examples.rb diff --git a/app/finders/issuable_finder.rb b/app/finders/issuable_finder.rb index cc2073081b5..6297b2db369 100644 --- a/app/finders/issuable_finder.rb +++ b/app/finders/issuable_finder.rb @@ -61,31 +61,26 @@ class IssuableFinder def project return @project if defined?(@project) - if project? - @project = Project.find(params[:project_id]) + project = Project.find(params[:project_id]) + project = nil unless Ability.allowed?(current_user, :"read_#{klass.to_ability_name}", project) - unless Ability.allowed?(current_user, :read_project, @project) - @project = nil - end - else - @project = nil - end - - @project + @project = project end def projects return @projects if defined?(@projects) + return @projects = project if project? - if project? - @projects = project - elsif current_user && params[:authorized_only].presence && !current_user_related? - @projects = current_user.authorized_projects.reorder(nil) - elsif group - @projects = GroupProjectsFinder.new(group).execute(current_user).reorder(nil) - else - @projects = ProjectsFinder.new.execute(current_user).reorder(nil) - end + projects = + if current_user && params[:authorized_only].presence && !current_user_related? + current_user.authorized_projects + elsif group + GroupProjectsFinder.new(group).execute(current_user) + else + ProjectsFinder.new.execute(current_user) + end + + @projects = projects.with_feature_available_for_user(klass, current_user).reorder(nil) end def search diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb index 93a6b3122e0..664bb594aa9 100644 --- a/app/models/concerns/issuable.rb +++ b/app/models/concerns/issuable.rb @@ -183,6 +183,10 @@ module Issuable grouping_columns end + + def to_ability_name + model_name.singular + end end def today? @@ -244,7 +248,7 @@ module Issuable # issuable.class # => MergeRequest # issuable.to_ability_name # => "merge_request" def to_ability_name - self.class.to_s.underscore + self.class.to_ability_name end # Returns a Hash of attributes to be used for Twitter card metadata diff --git a/app/models/project.rb b/app/models/project.rb index 4c9c7c001dd..bbe590b5a8a 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -207,8 +207,38 @@ class Project < ActiveRecord::Base scope :for_milestones, ->(ids) { joins(:milestones).where('milestones.id' => ids).distinct } scope :with_push, -> { joins(:events).where('events.action = ?', Event::PUSHED) } - scope :with_builds_enabled, -> { joins('LEFT JOIN project_features ON projects.id = project_features.project_id').where('project_features.builds_access_level IS NULL or project_features.builds_access_level > 0') } - scope :with_issues_enabled, -> { joins('LEFT JOIN project_features ON projects.id = project_features.project_id').where('project_features.issues_access_level IS NULL or project_features.issues_access_level > 0') } + scope :with_project_feature, -> { joins('LEFT JOIN project_features ON projects.id = project_features.project_id') } + + # "enabled" here means "not disabled". It includes private features! + scope :with_feature_enabled, ->(feature) { + access_level_attribute = ProjectFeature.access_level_attribute(feature) + with_project_feature.where(project_features: { access_level_attribute => [nil, ProjectFeature::PRIVATE, ProjectFeature::ENABLED] }) + } + + # Picks a feature where the level is exactly that given. + scope :with_feature_access_level, ->(feature, level) { + access_level_attribute = ProjectFeature.access_level_attribute(feature) + with_project_feature.where(project_features: { access_level_attribute => level }) + } + + scope :with_builds_enabled, -> { with_feature_enabled(:builds) } + scope :with_issues_enabled, -> { with_feature_enabled(:issues) } + + # project features may be "disabled", "internal" or "enabled". If "internal", + # they are only available to team members. This scope returns projects where + # the feature is either enabled, or internal with permission for the user. + def self.with_feature_available_for_user(feature, user) + return with_feature_enabled(feature) if user.try(:admin?) + + unconditional = with_feature_access_level(feature, [nil, ProjectFeature::ENABLED]) + return unconditional if user.nil? + + conditional = with_feature_access_level(feature, ProjectFeature::PRIVATE) + authorized = user.authorized_projects.merge(conditional.reorder(nil)) + + union = Gitlab::SQL::Union.new([unconditional.select(:id), authorized.select(:id)]) + where(arel_table[:id].in(Arel::Nodes::SqlLiteral.new(union.to_sql))) + end scope :active, -> { joins(:issues, :notes, :merge_requests).order('issues.created_at, notes.created_at, merge_requests.created_at DESC') } scope :abandoned, -> { where('projects.last_activity_at < ?', 6.months.ago) } diff --git a/app/models/project_feature.rb b/app/models/project_feature.rb index b37ce1d3cf6..34fd5a57b5e 100644 --- a/app/models/project_feature.rb +++ b/app/models/project_feature.rb @@ -20,6 +20,15 @@ class ProjectFeature < ActiveRecord::Base FEATURES = %i(issues merge_requests wiki snippets builds repository) + class << self + def access_level_attribute(feature) + feature = feature.model_name.plural.to_sym if feature.respond_to?(:model_name) + raise ArgumentError, "invalid project feature: #{feature}" unless FEATURES.include?(feature) + + "#{feature}_access_level".to_sym + end + end + # Default scopes force us to unscope here since a service may need to check # permissions for a project in pending_delete # http://stackoverflow.com/questions/1540645/how-to-disable-default-scope-for-a-belongs-to @@ -35,9 +44,8 @@ class ProjectFeature < ActiveRecord::Base default_value_for :repository_access_level, value: ENABLED, allows_nil: false def feature_available?(feature, user) - raise ArgumentError, 'invalid project feature' unless FEATURES.include?(feature) - - get_permission(user, public_send("#{feature}_access_level")) + access_level = public_send(ProjectFeature.access_level_attribute(feature)) + get_permission(user, access_level) end def builds_enabled? diff --git a/spec/features/groups/issues_spec.rb b/spec/features/groups/issues_spec.rb new file mode 100644 index 00000000000..476eca17a9d --- /dev/null +++ b/spec/features/groups/issues_spec.rb @@ -0,0 +1,8 @@ +require 'spec_helper' + +feature 'Group issues page', feature: true do + let(:path) { issues_group_path(group) } + let(:issuable) { create(:issue, project: project, title: "this is my created issuable")} + + include_examples 'project features apply to issuables', Issue +end diff --git a/spec/features/groups/merge_requests_spec.rb b/spec/features/groups/merge_requests_spec.rb new file mode 100644 index 00000000000..a2791b57544 --- /dev/null +++ b/spec/features/groups/merge_requests_spec.rb @@ -0,0 +1,8 @@ +require 'spec_helper' + +feature 'Group merge requests page', feature: true do + let(:path) { merge_requests_group_path(group) } + let(:issuable) { create(:merge_request, source_project: project, target_project: project, title: "this is my created issuable")} + + include_examples 'project features apply to issuables', MergeRequest +end diff --git a/spec/models/concerns/issuable_spec.rb b/spec/models/concerns/issuable_spec.rb index a9603074c32..6e987967ca5 100644 --- a/spec/models/concerns/issuable_spec.rb +++ b/spec/models/concerns/issuable_spec.rb @@ -97,6 +97,11 @@ describe Issue, "Issuable" do end end + describe '.to_ability_name' do + it { expect(Issue.to_ability_name).to eq("issue") } + it { expect(MergeRequest.to_ability_name).to eq("merge_request") } + end + describe "#today?" do it "returns true when created today" do # Avoid timezone differences and just return exactly what we want diff --git a/spec/support/project_features_apply_to_issuables_shared_examples.rb b/spec/support/project_features_apply_to_issuables_shared_examples.rb new file mode 100644 index 00000000000..4621d17549b --- /dev/null +++ b/spec/support/project_features_apply_to_issuables_shared_examples.rb @@ -0,0 +1,56 @@ +shared_examples 'project features apply to issuables' do |klass| + let(:described_class) { klass } + + let(:group) { create(:group) } + let(:user_in_group) { create(:group_member, :developer, user: create(:user), group: group ).user } + let(:user_outside_group) { create(:user) } + + let(:project) { create(:empty_project, :public, project_args) } + + def project_args + feature = "#{described_class.model_name.plural}_access_level".to_sym + + args = { group: group } + args[feature] = access_level + + args + end + + before do + _ = issuable + login_as(user) + visit path + end + + context 'public access level' do + let(:access_level) { ProjectFeature::ENABLED } + + context 'group member' do + let(:user) { user_in_group } + + it { expect(page).to have_content(issuable.title) } + end + + context 'non-member' do + let(:user) { user_outside_group } + + it { expect(page).to have_content(issuable.title) } + end + end + + context 'private access level' do + let(:access_level) { ProjectFeature::PRIVATE } + + context 'group member' do + let(:user) { user_in_group } + + it { expect(page).to have_content(issuable.title) } + end + + context 'non-member' do + let(:user) { user_outside_group } + + it { expect(page).not_to have_content(issuable.title) } + end + end +end From bf061d0aff091a73611037b811cea2d3380962f4 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Tue, 1 Nov 2016 20:18:51 +0000 Subject: [PATCH 170/175] Merge branch 'issue_23548_dev' into 'master' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit disable markdown in comments when referencing disabled features fixes https://gitlab.com/gitlab-org/gitlab-ce/issues/23548 This MR prevents the following references when tool is disabled: - issues - snippets - commits - when repo is disabled - commit range - when repo is disabled - milestones This MR does not prevent references to repository files, since they are just markdown links and don't leak information. See merge request !2011 Signed-off-by: Rémy Coutable --- app/models/issue.rb | 52 ++++---- app/policies/issue_policy.rb | 4 + lib/banzai/reference_parser/base_parser.rb | 16 ++- lib/banzai/reference_parser/commit_parser.rb | 6 + .../reference_parser/commit_range_parser.rb | 6 + .../reference_parser/external_issue_parser.rb | 6 + lib/banzai/reference_parser/label_parser.rb | 6 + .../reference_parser/merge_request_parser.rb | 6 + .../reference_parser/milestone_parser.rb | 6 + lib/banzai/reference_parser/snippet_parser.rb | 6 + lib/banzai/reference_parser/user_parser.rb | 34 ++++-- .../features/issues/new_branch_button_spec.rb | 1 + .../lib/banzai/filter/redactor_filter_spec.rb | 42 ++++--- .../reference_parser/base_parser_spec.rb | 35 +----- .../reference_parser/commit_parser_spec.rb | 8 ++ .../commit_range_parser_spec.rb | 8 ++ .../external_issue_parser_spec.rb | 8 ++ .../reference_parser/issue_parser_spec.rb | 10 +- .../reference_parser/label_parser_spec.rb | 8 ++ .../merge_request_parser_spec.rb | 13 ++ .../reference_parser/milestone_parser_spec.rb | 8 ++ .../reference_parser/snippet_parser_spec.rb | 8 ++ .../reference_parser/user_parser_spec.rb | 2 + .../gitlab/closing_issue_extractor_spec.rb | 3 +- .../lib/gitlab/gfm/reference_rewriter_spec.rb | 2 +- spec/lib/gitlab/reference_extractor_spec.rb | 3 +- spec/models/issue_spec.rb | 112 ++++++++++-------- spec/support/cycle_analytics_helpers.rb | 3 +- .../reference_parser_shared_examples.rb | 43 +++++++ 29 files changed, 324 insertions(+), 141 deletions(-) create mode 100644 spec/support/reference_parser_shared_examples.rb diff --git a/app/models/issue.rb b/app/models/issue.rb index 4f02b02c488..adbca510ef7 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -250,31 +250,11 @@ class Issue < ActiveRecord::Base # Returns `true` if the current issue can be viewed by either a logged in User # or an anonymous user. def visible_to_user?(user = nil) + return false unless project.feature_available?(:issues, user) + user ? readable_by?(user) : publicly_visible? end - # Returns `true` if the given User can read the current Issue. - def readable_by?(user) - if user.admin? - true - elsif project.owner == user - true - elsif confidential? - author == user || - assignee == user || - project.team.member?(user, Gitlab::Access::REPORTER) - else - project.public? || - project.internal? && !user.external? || - project.team.member?(user) - end - end - - # Returns `true` if this Issue is visible to everybody. - def publicly_visible? - project.public? && !confidential? - end - def overdue? due_date.try(:past?) || false end @@ -297,4 +277,32 @@ class Issue < ActiveRecord::Base end end end + + private + + # Returns `true` if the given User can read the current Issue. + # + # This method duplicates the same check of issue_policy.rb + # for performance reasons, check commit: 002ad215818450d2cbbc5fa065850a953dc7ada8 + # Make sure to sync this method with issue_policy.rb + def readable_by?(user) + if user.admin? + true + elsif project.owner == user + true + elsif confidential? + author == user || + assignee == user || + project.team.member?(user, Gitlab::Access::REPORTER) + else + project.public? || + project.internal? && !user.external? || + project.team.member?(user) + end + end + + # Returns `true` if this Issue is visible to everybody. + def publicly_visible? + project.public? && !confidential? + end end diff --git a/app/policies/issue_policy.rb b/app/policies/issue_policy.rb index 52fa33bc4b0..88f3179c6ff 100644 --- a/app/policies/issue_policy.rb +++ b/app/policies/issue_policy.rb @@ -1,4 +1,8 @@ class IssuePolicy < IssuablePolicy + # This class duplicates the same check of Issue#readable_by? for performance reasons + # Make sure to sync this class checks with issue.rb to avoid security problems. + # Check commit 002ad215818450d2cbbc5fa065850a953dc7ada8 for more information. + def issue @subject end diff --git a/lib/banzai/reference_parser/base_parser.rb b/lib/banzai/reference_parser/base_parser.rb index f5d110e987b..d8a855ec1fe 100644 --- a/lib/banzai/reference_parser/base_parser.rb +++ b/lib/banzai/reference_parser/base_parser.rb @@ -63,12 +63,7 @@ module Banzai nodes.select do |node| if node.has_attribute?(project_attr) node_id = node.attr(project_attr).to_i - - if project && project.id == node_id - true - else - can?(user, :read_project, projects[node_id]) - end + can_read_reference?(user, projects[node_id]) else true end @@ -226,6 +221,15 @@ module Banzai attr_reader :current_user, :project + # When a feature is disabled or visible only for + # team members we should not allow team members + # see reference comments. + # Override this method on subclasses + # to check if user can read resource + def can_read_reference?(user, ref_project) + raise NotImplementedError + end + def lazy(&block) Gitlab::Lazy.new(&block) end diff --git a/lib/banzai/reference_parser/commit_parser.rb b/lib/banzai/reference_parser/commit_parser.rb index 0fee9d267de..8c54a041cb8 100644 --- a/lib/banzai/reference_parser/commit_parser.rb +++ b/lib/banzai/reference_parser/commit_parser.rb @@ -29,6 +29,12 @@ module Banzai commits end + + private + + def can_read_reference?(user, ref_project) + can?(user, :download_code, ref_project) + end end end end diff --git a/lib/banzai/reference_parser/commit_range_parser.rb b/lib/banzai/reference_parser/commit_range_parser.rb index 69d01f8db15..0878b6afba3 100644 --- a/lib/banzai/reference_parser/commit_range_parser.rb +++ b/lib/banzai/reference_parser/commit_range_parser.rb @@ -33,6 +33,12 @@ module Banzai range.valid_commits? ? range : nil end + + private + + def can_read_reference?(user, ref_project) + can?(user, :download_code, ref_project) + end end end end diff --git a/lib/banzai/reference_parser/external_issue_parser.rb b/lib/banzai/reference_parser/external_issue_parser.rb index a1264db2111..6e7b7669578 100644 --- a/lib/banzai/reference_parser/external_issue_parser.rb +++ b/lib/banzai/reference_parser/external_issue_parser.rb @@ -20,6 +20,12 @@ module Banzai def issue_ids_per_project(nodes) gather_attributes_per_project(nodes, self.class.data_attribute) end + + private + + def can_read_reference?(user, ref_project) + can?(user, :read_issue, ref_project) + end end end end diff --git a/lib/banzai/reference_parser/label_parser.rb b/lib/banzai/reference_parser/label_parser.rb index e5d1eb11d7f..aa76c64ac5f 100644 --- a/lib/banzai/reference_parser/label_parser.rb +++ b/lib/banzai/reference_parser/label_parser.rb @@ -6,6 +6,12 @@ module Banzai def references_relation Label end + + private + + def can_read_reference?(user, ref_project) + can?(user, :read_label, ref_project) + end end end end diff --git a/lib/banzai/reference_parser/merge_request_parser.rb b/lib/banzai/reference_parser/merge_request_parser.rb index c9a9ca79c09..40451947e6c 100644 --- a/lib/banzai/reference_parser/merge_request_parser.rb +++ b/lib/banzai/reference_parser/merge_request_parser.rb @@ -6,6 +6,12 @@ module Banzai def references_relation MergeRequest.includes(:author, :assignee, :target_project) end + + private + + def can_read_reference?(user, ref_project) + can?(user, :read_merge_request, ref_project) + end end end end diff --git a/lib/banzai/reference_parser/milestone_parser.rb b/lib/banzai/reference_parser/milestone_parser.rb index a000ac61e5c..d3968d6b229 100644 --- a/lib/banzai/reference_parser/milestone_parser.rb +++ b/lib/banzai/reference_parser/milestone_parser.rb @@ -6,6 +6,12 @@ module Banzai def references_relation Milestone end + + private + + def can_read_reference?(user, ref_project) + can?(user, :read_milestone, ref_project) + end end end end diff --git a/lib/banzai/reference_parser/snippet_parser.rb b/lib/banzai/reference_parser/snippet_parser.rb index fa71b3c952a..63b592137bb 100644 --- a/lib/banzai/reference_parser/snippet_parser.rb +++ b/lib/banzai/reference_parser/snippet_parser.rb @@ -6,6 +6,12 @@ module Banzai def references_relation Snippet end + + private + + def can_read_reference?(user, ref_project) + can?(user, :read_project_snippet, ref_project) + end end end end diff --git a/lib/banzai/reference_parser/user_parser.rb b/lib/banzai/reference_parser/user_parser.rb index 863f5725d3b..7adaffa19c1 100644 --- a/lib/banzai/reference_parser/user_parser.rb +++ b/lib/banzai/reference_parser/user_parser.rb @@ -30,22 +30,36 @@ module Banzai nodes.each do |node| if node.has_attribute?(group_attr) - node_group = groups[node.attr(group_attr).to_i] - - if node_group && - can?(user, :read_group, node_group) - visible << node - end - # Remaining nodes will be processed by the parent class' - # implementation of this method. + next unless can_read_group_reference?(node, user, groups) + visible << node + elsif can_read_project_reference?(node) + visible << node else remaining << node end end + # If project does not belong to a group + # and does not have the same project id as the current project + # base class will check if user can read the project that contains + # the user reference. visible + super(current_user, remaining) end + # Check if project belongs to a group which + # user can read. + def can_read_group_reference?(node, user, groups) + node_group = groups[node.attr('data-group').to_i] + + node_group && can?(user, :read_group, node_group) + end + + def can_read_project_reference?(node) + node_id = node.attr('data-project').to_i + + project && project.id == node_id + end + def nodes_user_can_reference(current_user, nodes) project_attr = 'data-project' author_attr = 'data-author' @@ -88,6 +102,10 @@ module Banzai collection_objects_for_ids(Project, ids). flat_map { |p| p.team.members.to_a } end + + def can_read_reference?(user, ref_project) + can?(user, :read_project, ref_project) + end end end end diff --git a/spec/features/issues/new_branch_button_spec.rb b/spec/features/issues/new_branch_button_spec.rb index 755f4eb1b0b..ab901e74617 100644 --- a/spec/features/issues/new_branch_button_spec.rb +++ b/spec/features/issues/new_branch_button_spec.rb @@ -22,6 +22,7 @@ feature 'Start new branch from an issue', feature: true do create(:note, :on_issue, :system, project: project, noteable: issue, note: "Mentioned in !#{referenced_mr.iid}") end + let(:referenced_mr) do create(:merge_request, :simple, source_project: project, target_project: project, description: "Fixes ##{issue.iid}", author: user) diff --git a/spec/lib/banzai/filter/redactor_filter_spec.rb b/spec/lib/banzai/filter/redactor_filter_spec.rb index f181125156b..0140a91c7ba 100644 --- a/spec/lib/banzai/filter/redactor_filter_spec.rb +++ b/spec/lib/banzai/filter/redactor_filter_spec.rb @@ -28,31 +28,39 @@ describe Banzai::Filter::RedactorFilter, lib: true do and_return(parser_class) end - it 'removes unpermitted Project references' do - user = create(:user) - project = create(:empty_project) + context 'valid projects' do + before { allow_any_instance_of(Banzai::ReferenceParser::BaseParser).to receive(:can_read_reference?).and_return(true) } - link = reference_link(project: project.id, reference_type: 'test') - doc = filter(link, current_user: user) + it 'allows permitted Project references' do + user = create(:user) + project = create(:empty_project) + project.team << [user, :master] - expect(doc.css('a').length).to eq 0 + link = reference_link(project: project.id, reference_type: 'test') + doc = filter(link, current_user: user) + + expect(doc.css('a').length).to eq 1 + end end - it 'allows permitted Project references' do - user = create(:user) - project = create(:empty_project) - project.team << [user, :master] + context 'invalid projects' do + before { allow_any_instance_of(Banzai::ReferenceParser::BaseParser).to receive(:can_read_reference?).and_return(false) } - link = reference_link(project: project.id, reference_type: 'test') - doc = filter(link, current_user: user) + it 'removes unpermitted references' do + user = create(:user) + project = create(:empty_project) - expect(doc.css('a').length).to eq 1 - end + link = reference_link(project: project.id, reference_type: 'test') + doc = filter(link, current_user: user) - it 'handles invalid Project references' do - link = reference_link(project: 12345, reference_type: 'test') + expect(doc.css('a').length).to eq 0 + end - expect { filter(link) }.not_to raise_error + it 'handles invalid references' do + link = reference_link(project: 12345, reference_type: 'test') + + expect { filter(link) }.not_to raise_error + end end end diff --git a/spec/lib/banzai/reference_parser/base_parser_spec.rb b/spec/lib/banzai/reference_parser/base_parser_spec.rb index 9095d2b1345..aa127f0179d 100644 --- a/spec/lib/banzai/reference_parser/base_parser_spec.rb +++ b/spec/lib/banzai/reference_parser/base_parser_spec.rb @@ -27,41 +27,12 @@ describe Banzai::ReferenceParser::BaseParser, lib: true do let(:link) { empty_html_link } context 'when the link has a data-project attribute' do - it 'returns the nodes if the attribute value equals the current project ID' do + it 'checks if user can read the resource' do link['data-project'] = project.id.to_s - expect(Ability).not_to receive(:allowed?) - expect(subject.nodes_visible_to_user(user, [link])).to eq([link]) - end + expect(subject).to receive(:can_read_reference?).with(user, project) - it 'returns the nodes if the user can read the project' do - other_project = create(:empty_project, :public) - - link['data-project'] = other_project.id.to_s - - expect(Ability).to receive(:allowed?). - with(user, :read_project, other_project). - and_return(true) - - expect(subject.nodes_visible_to_user(user, [link])).to eq([link]) - end - - it 'returns an empty Array when the attribute value is empty' do - link['data-project'] = '' - - expect(subject.nodes_visible_to_user(user, [link])).to eq([]) - end - - it 'returns an empty Array when the user can not read the project' do - other_project = create(:empty_project, :public) - - link['data-project'] = other_project.id.to_s - - expect(Ability).to receive(:allowed?). - with(user, :read_project, other_project). - and_return(false) - - expect(subject.nodes_visible_to_user(user, [link])).to eq([]) + subject.nodes_visible_to_user(user, [link]) end end diff --git a/spec/lib/banzai/reference_parser/commit_parser_spec.rb b/spec/lib/banzai/reference_parser/commit_parser_spec.rb index 0b76d29fce0..412ffa77c36 100644 --- a/spec/lib/banzai/reference_parser/commit_parser_spec.rb +++ b/spec/lib/banzai/reference_parser/commit_parser_spec.rb @@ -8,6 +8,14 @@ describe Banzai::ReferenceParser::CommitParser, lib: true do subject { described_class.new(project, user) } let(:link) { empty_html_link } + describe '#nodes_visible_to_user' do + context 'when the link has a data-issue attribute' do + before { link['data-commit'] = 123 } + + it_behaves_like "referenced feature visibility", "repository" + end + end + describe '#referenced_by' do context 'when the link has a data-project attribute' do before do diff --git a/spec/lib/banzai/reference_parser/commit_range_parser_spec.rb b/spec/lib/banzai/reference_parser/commit_range_parser_spec.rb index ba982f38542..96e55b0997a 100644 --- a/spec/lib/banzai/reference_parser/commit_range_parser_spec.rb +++ b/spec/lib/banzai/reference_parser/commit_range_parser_spec.rb @@ -8,6 +8,14 @@ describe Banzai::ReferenceParser::CommitRangeParser, lib: true do subject { described_class.new(project, user) } let(:link) { empty_html_link } + describe '#nodes_visible_to_user' do + context 'when the link has a data-issue attribute' do + before { link['data-commit-range'] = '123..456' } + + it_behaves_like "referenced feature visibility", "repository" + end + end + describe '#referenced_by' do context 'when the link has a data-project attribute' do before do diff --git a/spec/lib/banzai/reference_parser/external_issue_parser_spec.rb b/spec/lib/banzai/reference_parser/external_issue_parser_spec.rb index a6ef8394fe7..50a5d1a19ba 100644 --- a/spec/lib/banzai/reference_parser/external_issue_parser_spec.rb +++ b/spec/lib/banzai/reference_parser/external_issue_parser_spec.rb @@ -8,6 +8,14 @@ describe Banzai::ReferenceParser::ExternalIssueParser, lib: true do subject { described_class.new(project, user) } let(:link) { empty_html_link } + describe '#nodes_visible_to_user' do + context 'when the link has a data-issue attribute' do + before { link['data-external-issue'] = 123 } + + it_behaves_like "referenced feature visibility", "issues" + end + end + describe '#referenced_by' do context 'when the link has a data-project attribute' do before do diff --git a/spec/lib/banzai/reference_parser/issue_parser_spec.rb b/spec/lib/banzai/reference_parser/issue_parser_spec.rb index 85cfe728b6a..6873b7b85f9 100644 --- a/spec/lib/banzai/reference_parser/issue_parser_spec.rb +++ b/spec/lib/banzai/reference_parser/issue_parser_spec.rb @@ -4,10 +4,10 @@ describe Banzai::ReferenceParser::IssueParser, lib: true do include ReferenceParserHelpers let(:project) { create(:empty_project, :public) } - let(:user) { create(:user) } - let(:issue) { create(:issue, project: project) } - subject { described_class.new(project, user) } - let(:link) { empty_html_link } + let(:user) { create(:user) } + let(:issue) { create(:issue, project: project) } + let(:link) { empty_html_link } + subject { described_class.new(project, user) } describe '#nodes_visible_to_user' do context 'when the link has a data-issue attribute' do @@ -15,6 +15,8 @@ describe Banzai::ReferenceParser::IssueParser, lib: true do link['data-issue'] = issue.id.to_s end + it_behaves_like "referenced feature visibility", "issues" + it 'returns the nodes when the user can read the issue' do expect(Ability).to receive(:issues_readable_by_user). with([issue], user). diff --git a/spec/lib/banzai/reference_parser/label_parser_spec.rb b/spec/lib/banzai/reference_parser/label_parser_spec.rb index 77fda47f0e7..8c540d35ddd 100644 --- a/spec/lib/banzai/reference_parser/label_parser_spec.rb +++ b/spec/lib/banzai/reference_parser/label_parser_spec.rb @@ -9,6 +9,14 @@ describe Banzai::ReferenceParser::LabelParser, lib: true do subject { described_class.new(project, user) } let(:link) { empty_html_link } + describe '#nodes_visible_to_user' do + context 'when the link has a data-issue attribute' do + before { link['data-label'] = label.id.to_s } + + it_behaves_like "referenced feature visibility", "issues", "merge_requests" + end + end + describe '#referenced_by' do describe 'when the link has a data-label attribute' do context 'using an existing label ID' do diff --git a/spec/lib/banzai/reference_parser/merge_request_parser_spec.rb b/spec/lib/banzai/reference_parser/merge_request_parser_spec.rb index cf89ad598ea..cb69ca16800 100644 --- a/spec/lib/banzai/reference_parser/merge_request_parser_spec.rb +++ b/spec/lib/banzai/reference_parser/merge_request_parser_spec.rb @@ -8,6 +8,19 @@ describe Banzai::ReferenceParser::MergeRequestParser, lib: true do subject { described_class.new(merge_request.target_project, user) } let(:link) { empty_html_link } + describe '#nodes_visible_to_user' do + context 'when the link has a data-issue attribute' do + let(:project) { merge_request.target_project } + + before do + project.update_attribute(:visibility_level, Gitlab::VisibilityLevel::PUBLIC) + link['data-merge-request'] = merge_request.id.to_s + end + + it_behaves_like "referenced feature visibility", "merge_requests" + end + end + describe '#referenced_by' do describe 'when the link has a data-merge-request attribute' do context 'using an existing merge request ID' do diff --git a/spec/lib/banzai/reference_parser/milestone_parser_spec.rb b/spec/lib/banzai/reference_parser/milestone_parser_spec.rb index 6aa45a22cc4..2d4d589ae34 100644 --- a/spec/lib/banzai/reference_parser/milestone_parser_spec.rb +++ b/spec/lib/banzai/reference_parser/milestone_parser_spec.rb @@ -9,6 +9,14 @@ describe Banzai::ReferenceParser::MilestoneParser, lib: true do subject { described_class.new(project, user) } let(:link) { empty_html_link } + describe '#nodes_visible_to_user' do + context 'when the link has a data-issue attribute' do + before { link['data-milestone'] = milestone.id.to_s } + + it_behaves_like "referenced feature visibility", "issues", "merge_requests" + end + end + describe '#referenced_by' do describe 'when the link has a data-milestone attribute' do context 'using an existing milestone ID' do diff --git a/spec/lib/banzai/reference_parser/snippet_parser_spec.rb b/spec/lib/banzai/reference_parser/snippet_parser_spec.rb index 59127b7c5d1..d217a775802 100644 --- a/spec/lib/banzai/reference_parser/snippet_parser_spec.rb +++ b/spec/lib/banzai/reference_parser/snippet_parser_spec.rb @@ -9,6 +9,14 @@ describe Banzai::ReferenceParser::SnippetParser, lib: true do subject { described_class.new(project, user) } let(:link) { empty_html_link } + describe '#nodes_visible_to_user' do + context 'when the link has a data-issue attribute' do + before { link['data-snippet'] = snippet.id.to_s } + + it_behaves_like "referenced feature visibility", "snippets" + end + end + describe '#referenced_by' do describe 'when the link has a data-snippet attribute' do context 'using an existing snippet ID' do diff --git a/spec/lib/banzai/reference_parser/user_parser_spec.rb b/spec/lib/banzai/reference_parser/user_parser_spec.rb index 4e7f82a6e09..fafc2cec546 100644 --- a/spec/lib/banzai/reference_parser/user_parser_spec.rb +++ b/spec/lib/banzai/reference_parser/user_parser_spec.rb @@ -103,6 +103,8 @@ describe Banzai::ReferenceParser::UserParser, lib: true do it 'returns the nodes if the attribute value equals the current project ID' do link['data-project'] = project.id.to_s + # Ensure that we dont call for Ability.allowed? + # When project_id in the node is equal to current project ID expect(Ability).not_to receive(:allowed?) expect(subject.nodes_visible_to_user(user, [link])).to eq([link]) diff --git a/spec/lib/gitlab/closing_issue_extractor_spec.rb b/spec/lib/gitlab/closing_issue_extractor_spec.rb index de3f64249a2..1bbaca0739a 100644 --- a/spec/lib/gitlab/closing_issue_extractor_spec.rb +++ b/spec/lib/gitlab/closing_issue_extractor_spec.rb @@ -257,8 +257,9 @@ describe Gitlab::ClosingIssueExtractor, lib: true do context 'with an external issue tracker reference' do it 'extracts the referenced issue' do jira_project = create(:jira_project, name: 'JIRA_EXT1') + jira_project.team << [jira_project.creator, :master] jira_issue = ExternalIssue.new("#{jira_project.name}-1", project: jira_project) - closing_issue_extractor = described_class.new jira_project + closing_issue_extractor = described_class.new(jira_project, jira_project.creator) message = "Resolve #{jira_issue.to_reference}" expect(closing_issue_extractor.closed_by_message(message)).to eq([jira_issue]) diff --git a/spec/lib/gitlab/gfm/reference_rewriter_spec.rb b/spec/lib/gitlab/gfm/reference_rewriter_spec.rb index f045463c1cb..6b3dfebd85d 100644 --- a/spec/lib/gitlab/gfm/reference_rewriter_spec.rb +++ b/spec/lib/gitlab/gfm/reference_rewriter_spec.rb @@ -6,7 +6,7 @@ describe Gitlab::Gfm::ReferenceRewriter do let(:new_project) { create(:project, name: 'new') } let(:user) { create(:user) } - before { old_project.team << [user, :guest] } + before { old_project.team << [user, :reporter] } describe '#rewrite' do subject do diff --git a/spec/lib/gitlab/reference_extractor_spec.rb b/spec/lib/gitlab/reference_extractor_spec.rb index 7b4ccc83915..bf0ab9635fd 100644 --- a/spec/lib/gitlab/reference_extractor_spec.rb +++ b/spec/lib/gitlab/reference_extractor_spec.rb @@ -3,6 +3,8 @@ require 'spec_helper' describe Gitlab::ReferenceExtractor, lib: true do let(:project) { create(:project) } + before { project.team << [project.creator, :developer] } + subject { Gitlab::ReferenceExtractor.new(project, project.creator) } it 'accesses valid user objects' do @@ -42,7 +44,6 @@ describe Gitlab::ReferenceExtractor, lib: true do end it 'accesses valid issue objects' do - project.team << [project.creator, :developer] @i0 = create(:issue, project: project) @i1 = create(:issue, project: project) diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb index 60d30eb7418..300425767ed 100644 --- a/spec/models/issue_spec.rb +++ b/spec/models/issue_spec.rb @@ -22,7 +22,7 @@ describe Issue, models: true do it { is_expected.to have_db_index(:deleted_at) } end - describe 'visible_to_user' do + describe '.visible_to_user' do let(:user) { create(:user) } let(:authorized_user) { create(:user) } let(:project) { create(:project, namespace: authorized_user.namespace) } @@ -102,17 +102,17 @@ describe Issue, models: true do it 'returns the merge request to close this issue' do mr - expect(issue.closed_by_merge_requests).to eq([mr]) + expect(issue.closed_by_merge_requests(mr.author)).to eq([mr]) end it "returns an empty array when the merge request is closed already" do closed_mr - expect(issue.closed_by_merge_requests).to eq([]) + expect(issue.closed_by_merge_requests(closed_mr.author)).to eq([]) end it "returns an empty array when the current issue is closed already" do - expect(closed_issue.closed_by_merge_requests).to eq([]) + expect(closed_issue.closed_by_merge_requests(closed_issue.author)).to eq([]) end end @@ -218,7 +218,7 @@ describe Issue, models: true do source_project: subject.project, source_branch: "#{subject.iid}-branch" }) merge_request.create_cross_references!(user) - expect(subject.referenced_merge_requests).not_to be_empty + expect(subject.referenced_merge_requests(user)).not_to be_empty expect(subject.related_branches(user)).to eq([subject.to_branch_name]) end @@ -314,23 +314,6 @@ describe Issue, models: true do end describe '#visible_to_user?' do - context 'with a user' do - let(:user) { build(:user) } - let(:issue) { build(:issue) } - - it 'returns true when the issue is readable' do - expect(issue).to receive(:readable_by?).with(user).and_return(true) - - expect(issue.visible_to_user?(user)).to eq(true) - end - - it 'returns false when the issue is not readable' do - expect(issue).to receive(:readable_by?).with(user).and_return(false) - - expect(issue.visible_to_user?(user)).to eq(false) - end - end - context 'without a user' do let(:issue) { build(:issue) } @@ -346,9 +329,40 @@ describe Issue, models: true do expect(issue.visible_to_user?).to eq(false) end end - end - describe '#readable_by?' do + context 'with a user' do + let(:user) { build(:user) } + let(:issue) { build(:issue) } + + it 'returns true when the issue is readable' do + expect(issue).to receive(:readable_by?).with(user).and_return(true) + + expect(issue.visible_to_user?(user)).to eq(true) + end + + it 'returns false when the issue is not readable' do + expect(issue).to receive(:readable_by?).with(user).and_return(false) + + expect(issue.visible_to_user?(user)).to eq(false) + end + + it 'returns false when feature is disabled' do + expect(issue).not_to receive(:readable_by?) + + issue.project.project_feature.update_attribute(:issues_access_level, ProjectFeature::DISABLED) + + expect(issue.visible_to_user?(user)).to eq(false) + end + + it 'returns false when restricted for members' do + expect(issue).not_to receive(:readable_by?) + + issue.project.project_feature.update_attribute(:issues_access_level, ProjectFeature::PRIVATE) + + expect(issue.visible_to_user?(user)).to eq(false) + end + end + describe 'with a regular user that is not a team member' do let(:user) { create(:user) } @@ -358,13 +372,13 @@ describe Issue, models: true do it 'returns true for a regular issue' do issue = build(:issue, project: project) - expect(issue).to be_readable_by(user) + expect(issue.visible_to_user?(user)).to eq(true) end it 'returns false for a confidential issue' do issue = build(:issue, project: project, confidential: true) - expect(issue).not_to be_readable_by(user) + expect(issue.visible_to_user?(user)).to eq(false) end end @@ -375,13 +389,13 @@ describe Issue, models: true do it 'returns true for a regular issue' do issue = build(:issue, project: project) - expect(issue).to be_readable_by(user) + expect(issue.visible_to_user?(user)).to eq(true) end it 'returns false for a confidential issue' do issue = build(:issue, :confidential, project: project) - expect(issue).not_to be_readable_by(user) + expect(issue.visible_to_user?(user)).to eq(false) end end @@ -393,13 +407,13 @@ describe Issue, models: true do it 'returns false for a regular issue' do issue = build(:issue, project: project) - expect(issue).not_to be_readable_by(user) + expect(issue.visible_to_user?(user)).to eq(false) end it 'returns false for a confidential issue' do issue = build(:issue, :confidential, project: project) - expect(issue).not_to be_readable_by(user) + expect(issue.visible_to_user?(user)).to eq(false) end end end @@ -410,26 +424,28 @@ describe Issue, models: true do it 'returns false for a regular issue' do issue = build(:issue, project: project) - expect(issue).not_to be_readable_by(user) + expect(issue.visible_to_user?(user)).to eq(false) end it 'returns false for a confidential issue' do issue = build(:issue, :confidential, project: project) - expect(issue).not_to be_readable_by(user) + expect(issue.visible_to_user?(user)).to eq(false) end context 'when the user is the project owner' do + before { project.team << [user, :master] } + it 'returns true for a regular issue' do issue = build(:issue, project: project) - expect(issue).not_to be_readable_by(user) + expect(issue.visible_to_user?(user)).to eq(true) end it 'returns true for a confidential issue' do issue = build(:issue, :confidential, project: project) - expect(issue).not_to be_readable_by(user) + expect(issue.visible_to_user?(user)).to eq(true) end end end @@ -447,13 +463,13 @@ describe Issue, models: true do it 'returns true for a regular issue' do issue = build(:issue, project: project) - expect(issue).to be_readable_by(user) + expect(issue.visible_to_user?(user)).to eq(true) end it 'returns true for a confidential issue' do issue = build(:issue, :confidential, project: project) - expect(issue).to be_readable_by(user) + expect(issue.visible_to_user?(user)).to eq(true) end end @@ -467,13 +483,13 @@ describe Issue, models: true do it 'returns true for a regular issue' do issue = build(:issue, project: project) - expect(issue).to be_readable_by(user) + expect(issue.visible_to_user?(user)).to eq(true) end it 'returns true for a confidential issue' do issue = build(:issue, :confidential, project: project) - expect(issue).to be_readable_by(user) + expect(issue.visible_to_user?(user)).to eq(true) end end @@ -487,13 +503,13 @@ describe Issue, models: true do it 'returns true for a regular issue' do issue = build(:issue, project: project) - expect(issue).to be_readable_by(user) + expect(issue.visible_to_user?(user)).to eq(true) end it 'returns true for a confidential issue' do issue = build(:issue, :confidential, project: project) - expect(issue).to be_readable_by(user) + expect(issue.visible_to_user?(user)).to eq(true) end end end @@ -505,13 +521,13 @@ describe Issue, models: true do it 'returns true for a regular issue' do issue = build(:issue, project: project) - expect(issue).to be_readable_by(user) + expect(issue.visible_to_user?(user)).to eq(true) end it 'returns true for a confidential issue' do issue = build(:issue, :confidential, project: project) - expect(issue).to be_readable_by(user) + expect(issue.visible_to_user?(user)).to eq(true) end end end @@ -523,13 +539,13 @@ describe Issue, models: true do it 'returns true for a regular issue' do issue = build(:issue, project: project) - expect(issue).to be_publicly_visible + expect(issue).to be_truthy end it 'returns false for a confidential issue' do issue = build(:issue, :confidential, project: project) - expect(issue).not_to be_publicly_visible + expect(issue).not_to be_falsy end end @@ -539,13 +555,13 @@ describe Issue, models: true do it 'returns false for a regular issue' do issue = build(:issue, project: project) - expect(issue).not_to be_publicly_visible + expect(issue).not_to be_falsy end it 'returns false for a confidential issue' do issue = build(:issue, :confidential, project: project) - expect(issue).not_to be_publicly_visible + expect(issue).not_to be_falsy end end @@ -555,13 +571,13 @@ describe Issue, models: true do it 'returns false for a regular issue' do issue = build(:issue, project: project) - expect(issue).not_to be_publicly_visible + expect(issue).not_to be_falsy end it 'returns false for a confidential issue' do issue = build(:issue, :confidential, project: project) - expect(issue).not_to be_publicly_visible + expect(issue).not_to be_falsy end end end diff --git a/spec/support/cycle_analytics_helpers.rb b/spec/support/cycle_analytics_helpers.rb index 62a5b46d47b..75c95d70951 100644 --- a/spec/support/cycle_analytics_helpers.rb +++ b/spec/support/cycle_analytics_helpers.rb @@ -49,7 +49,8 @@ module CycleAnalyticsHelpers end def merge_merge_requests_closing_issue(issue) - merge_requests = issue.closed_by_merge_requests + merge_requests = issue.closed_by_merge_requests(user) + merge_requests.each { |merge_request| MergeRequests::MergeService.new(project, user).execute(merge_request) } end diff --git a/spec/support/reference_parser_shared_examples.rb b/spec/support/reference_parser_shared_examples.rb new file mode 100644 index 00000000000..8eb74635a60 --- /dev/null +++ b/spec/support/reference_parser_shared_examples.rb @@ -0,0 +1,43 @@ +RSpec.shared_examples "referenced feature visibility" do |*related_features| + let(:feature_fields) do + related_features.map { |feature| (feature + "_access_level").to_sym } + end + + before { link['data-project'] = project.id.to_s } + + context "when feature is disabled" do + it "does not create reference" do + set_features_fields_to(ProjectFeature::DISABLED) + expect(subject.nodes_visible_to_user(user, [link])).to eq([]) + end + end + + context "when feature is enabled only for team members" do + before { set_features_fields_to(ProjectFeature::PRIVATE) } + + it "does not create reference for non member" do + non_member = create(:user) + + expect(subject.nodes_visible_to_user(non_member, [link])).to eq([]) + end + + it "creates reference for member" do + project.team << [user, :developer] + + expect(subject.nodes_visible_to_user(user, [link])).to eq([link]) + end + end + + context "when feature is enabled" do + # The project is public + it "creates reference" do + set_features_fields_to(ProjectFeature::ENABLED) + + expect(subject.nodes_visible_to_user(user, [link])).to eq([link]) + end + end + + def set_features_fields_to(visibility_level) + feature_fields.each { |field| project.project_feature.update_attribute(field, visibility_level) } + end +end From a14ee68fe4815d2906ece670bcc333303fd3c816 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Mon, 7 Nov 2016 16:27:35 +0000 Subject: [PATCH 171/175] Merge branch 'markdown-xss-fix-option-2.1' into 'security' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix for HackerOne XSS vulnerability in markdown This is an updated blacklist patch to fix https://dev.gitlab.org/gitlab/gitlabhq/merge_requests/2007. No text is removed. Dangerous schemes/protocols and invalid URIs are left intact but not linked. Fixes https://gitlab.com/gitlab-org/gitlab-ce/issues/23153 See merge request !2015 Signed-off-by: Rémy Coutable --- lib/banzai/filter/autolink_filter.rb | 38 ++++++++++++++----- .../lib/banzai/filter/autolink_filter_spec.rb | 22 +++++++++++ 2 files changed, 50 insertions(+), 10 deletions(-) diff --git a/lib/banzai/filter/autolink_filter.rb b/lib/banzai/filter/autolink_filter.rb index 799b83b1069..80c844baecd 100644 --- a/lib/banzai/filter/autolink_filter.rb +++ b/lib/banzai/filter/autolink_filter.rb @@ -71,6 +71,14 @@ module Banzai @doc = parse_html(rinku) end + # Return true if any of the UNSAFE_PROTOCOLS strings are included in the URI scheme + def contains_unsafe?(scheme) + return false unless scheme + + scheme = scheme.strip.downcase + Banzai::Filter::SanitizationFilter::UNSAFE_PROTOCOLS.any? { |protocol| scheme.include?(protocol) } + end + # Autolinks any text matching LINK_PATTERN that Rinku didn't already # replace def text_parse @@ -89,17 +97,27 @@ module Banzai doc end - def autolink_filter(text) - text.gsub(LINK_PATTERN) do |match| - # Remove any trailing HTML entities and store them for appending - # outside the link element. The entity must be marked HTML safe in - # order to be output literally rather than escaped. - match.gsub!(/((?:&[\w#]+;)+)\z/, '') - dropped = ($1 || '').html_safe - - options = link_options.merge(href: match) - content_tag(:a, match, options) + dropped + def autolink_match(match) + # start by stripping out dangerous links + begin + uri = Addressable::URI.parse(match) + return match if contains_unsafe?(uri.scheme) + rescue Addressable::URI::InvalidURIError + return match end + + # Remove any trailing HTML entities and store them for appending + # outside the link element. The entity must be marked HTML safe in + # order to be output literally rather than escaped. + match.gsub!(/((?:&[\w#]+;)+)\z/, '') + dropped = ($1 || '').html_safe + + options = link_options.merge(href: match) + content_tag(:a, match, options) + dropped + end + + def autolink_filter(text) + text.gsub(LINK_PATTERN) { |match| autolink_match(match) } end def link_options diff --git a/spec/lib/banzai/filter/autolink_filter_spec.rb b/spec/lib/banzai/filter/autolink_filter_spec.rb index dca7f997570..a6d2ea11fcc 100644 --- a/spec/lib/banzai/filter/autolink_filter_spec.rb +++ b/spec/lib/banzai/filter/autolink_filter_spec.rb @@ -99,6 +99,28 @@ describe Banzai::Filter::AutolinkFilter, lib: true do expect(doc.at_css('a')['href']).to eq link end + it 'autolinks rdar' do + link = 'rdar://localhost.com/blah' + doc = filter("See #{link}") + + expect(doc.at_css('a').text).to eq link + expect(doc.at_css('a')['href']).to eq link + end + + it 'does not autolink javascript' do + link = 'javascript://alert(document.cookie);' + doc = filter("See #{link}") + + expect(doc.at_css('a')).to be_nil + end + + it 'does not autolink bad URLs' do + link = 'foo://23423:::asdf' + doc = filter("See #{link}") + + expect(doc.to_s).to eq("See #{link}") + end + it 'does not include trailing punctuation' do doc = filter("See #{link}.") expect(doc.at_css('a').text).to eq link From b0bf92140f469db90ef378fd42a6f65eee1d4633 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Wed, 2 Nov 2016 21:50:44 +0000 Subject: [PATCH 172/175] Merge branch 'fix-unathorized-cloning' into 'security' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ensure external users are not able to clone disabled repositories. Closes https://gitlab.com/gitlab-org/gitlab-ce/issues/23788 See merge request !2017 Signed-off-by: Rémy Coutable --- .../projects/git_http_client_controller.rb | 8 +- .../projects/git_http_controller.rb | 6 +- app/helpers/lfs_helper.rb | 4 +- app/models/guest.rb | 7 ++ ...ntainer_registry_authentication_service.rb | 2 +- lib/gitlab/git_access.rb | 91 ++++++++++++------- spec/factories/projects.rb | 10 +- spec/lib/gitlab/git_access_spec.rb | 25 +++++ spec/lib/gitlab/git_access_wiki_spec.rb | 2 +- spec/models/guest_spec.rb | 47 ++++++++++ spec/requests/git_http_spec.rb | 32 +++++++ 11 files changed, 187 insertions(+), 47 deletions(-) create mode 100644 app/models/guest.rb create mode 100644 spec/models/guest_spec.rb diff --git a/app/controllers/projects/git_http_client_controller.rb b/app/controllers/projects/git_http_client_controller.rb index 383e184d796..3f41916e6d3 100644 --- a/app/controllers/projects/git_http_client_controller.rb +++ b/app/controllers/projects/git_http_client_controller.rb @@ -21,10 +21,6 @@ class Projects::GitHttpClientController < Projects::ApplicationController def authenticate_user @authentication_result = Gitlab::Auth::Result.new - if project && project.public? && download_request? - return # Allow access - end - if allow_basic_auth? && basic_auth_provided? login, password = user_name_and_password(request) @@ -41,6 +37,10 @@ class Projects::GitHttpClientController < Projects::ApplicationController send_final_spnego_response return # Allow access end + elsif project && download_request? && Guest.can?(:download_code, project) + @authentication_result = Gitlab::Auth::Result.new(nil, project, :none, [:download_code]) + + return # Allow access end send_challenges diff --git a/app/controllers/projects/git_http_controller.rb b/app/controllers/projects/git_http_controller.rb index 662d38b10a5..13caeb42d40 100644 --- a/app/controllers/projects/git_http_controller.rb +++ b/app/controllers/projects/git_http_controller.rb @@ -78,11 +78,7 @@ class Projects::GitHttpController < Projects::GitHttpClientController def upload_pack_allowed? return false unless Gitlab.config.gitlab_shell.upload_pack - if user - access_check.allowed? - else - ci? || project.public? - end + access_check.allowed? || ci? end def access diff --git a/app/helpers/lfs_helper.rb b/app/helpers/lfs_helper.rb index 95b60aeab5f..d3966ba1f10 100644 --- a/app/helpers/lfs_helper.rb +++ b/app/helpers/lfs_helper.rb @@ -1,6 +1,6 @@ module LfsHelper include Gitlab::Routing.url_helpers - + def require_lfs_enabled! return if Gitlab.config.lfs.enabled @@ -27,7 +27,7 @@ module LfsHelper def lfs_download_access? return false unless project.lfs_enabled? - project.public? || ci? || lfs_deploy_token? || user_can_download_code? || build_can_download_code? + ci? || lfs_deploy_token? || user_can_download_code? || build_can_download_code? end def user_can_download_code? diff --git a/app/models/guest.rb b/app/models/guest.rb new file mode 100644 index 00000000000..01285ca1264 --- /dev/null +++ b/app/models/guest.rb @@ -0,0 +1,7 @@ +class Guest + class << self + def can?(action, subject) + Ability.allowed?(nil, action, subject) + end + end +end diff --git a/app/services/auth/container_registry_authentication_service.rb b/app/services/auth/container_registry_authentication_service.rb index 8ea88da8a53..3fc1c70be75 100644 --- a/app/services/auth/container_registry_authentication_service.rb +++ b/app/services/auth/container_registry_authentication_service.rb @@ -76,7 +76,7 @@ module Auth case requested_action when 'pull' - requested_project.public? || build_can_pull?(requested_project) || user_can_pull?(requested_project) + build_can_pull?(requested_project) || user_can_pull?(requested_project) when 'push' build_can_push?(requested_project) || user_can_push?(requested_project) else diff --git a/lib/gitlab/git_access.rb b/lib/gitlab/git_access.rb index 799794c0171..bcbf6455998 100644 --- a/lib/gitlab/git_access.rb +++ b/lib/gitlab/git_access.rb @@ -2,8 +2,18 @@ # class return an instance of `GitlabAccessStatus` module Gitlab class GitAccess + UnauthorizedError = Class.new(StandardError) + + ERROR_MESSAGES = { + upload: 'You are not allowed to upload code for this project.', + download: 'You are not allowed to download code from this project.', + deploy_key: 'Deploy keys are not allowed to push code.', + no_repo: 'A repository for this project does not exist yet.' + } + DOWNLOAD_COMMANDS = %w{ git-upload-pack git-upload-archive } PUSH_COMMANDS = %w{ git-receive-pack } + ALL_COMMANDS = DOWNLOAD_COMMANDS + PUSH_COMMANDS attr_reader :actor, :project, :protocol, :user_access, :authentication_abilities @@ -16,56 +26,43 @@ module Gitlab end def check(cmd, changes) - return build_status_object(false, "Git access over #{protocol.upcase} is not allowed") unless protocol_allowed? - - unless actor - return build_status_object(false, "No user or key was provided.") - end - - if user && !user_access.allowed? - return build_status_object(false, "Your account has been blocked.") - end - - unless project && (user_access.can_read_project? || deploy_key_can_read_project?) - return build_status_object(false, 'The project you were looking for could not be found.') - end + check_protocol! + check_active_user! + check_project_accessibility! + check_command_existence!(cmd) case cmd when *DOWNLOAD_COMMANDS download_access_check when *PUSH_COMMANDS push_access_check(changes) - else - build_status_object(false, "The command you're trying to execute is not allowed.") end + + build_status_object(true) + rescue UnauthorizedError => ex + build_status_object(false, ex.message) end def download_access_check if user user_download_access_check - elsif deploy_key - build_status_object(true) - else - raise 'Wrong actor' + elsif deploy_key.nil? && !Guest.can?(:download_code, project) + raise UnauthorizedError, ERROR_MESSAGES[:download] end end def push_access_check(changes) if user user_push_access_check(changes) - elsif deploy_key - build_status_object(false, "Deploy keys are not allowed to push code.") else - raise 'Wrong actor' + raise UnauthorizedError, ERROR_MESSAGES[deploy_key ? :deploy_key : :upload] end end def user_download_access_check unless user_can_download_code? || build_can_download_code? - return build_status_object(false, "You are not allowed to download code from this project.") + raise UnauthorizedError, ERROR_MESSAGES[:download] end - - build_status_object(true) end def user_can_download_code? @@ -78,15 +75,15 @@ module Gitlab def user_push_access_check(changes) unless authentication_abilities.include?(:push_code) - return build_status_object(false, "You are not allowed to upload code for this project.") + raise UnauthorizedError, ERROR_MESSAGES[:upload] end if changes.blank? - return build_status_object(true) + return # Allow access. end unless project.repository.exists? - return build_status_object(false, "A repository for this project does not exist yet.") + raise UnauthorizedError, ERROR_MESSAGES[:no_repo] end changes_list = Gitlab::ChangesList.new(changes) @@ -96,11 +93,9 @@ module Gitlab status = change_access_check(change) unless status.allowed? # If user does not have access to make at least one change - cancel all push - return status + raise UnauthorizedError, status.message end end - - build_status_object(true) end def change_access_check(change) @@ -113,6 +108,30 @@ module Gitlab private + def check_protocol! + unless protocol_allowed? + raise UnauthorizedError, "Git access over #{protocol.upcase} is not allowed" + end + end + + def check_active_user! + if user && !user_access.allowed? + raise UnauthorizedError, "Your account has been blocked." + end + end + + def check_project_accessibility! + if project.blank? || !can_read_project? + raise UnauthorizedError, 'The project you were looking for could not be found.' + end + end + + def check_command_existence!(cmd) + unless ALL_COMMANDS.include?(cmd) + raise UnauthorizedError, "The command you're trying to execute is not allowed." + end + end + def matching_merge_request?(newrev, branch_name) Checks::MatchingMergeRequest.new(newrev, branch_name, project).match? end @@ -130,6 +149,16 @@ module Gitlab end end + def can_read_project? + if user + user_access.can_read_project? + elsif deploy_key + deploy_key_can_read_project? + else + Guest.can?(:read_project, project) + end + end + protected def user diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb index dd4a86b1e31..bfd88a254f1 100644 --- a/spec/factories/projects.rb +++ b/spec/factories/projects.rb @@ -49,13 +49,17 @@ FactoryGirl.define do end after(:create) do |project, evaluator| + # Builds and MRs can't have higher visibility level than repository access level. + builds_access_level = [evaluator.builds_access_level, evaluator.repository_access_level].min + merge_requests_access_level = [evaluator.merge_requests_access_level, evaluator.repository_access_level].min + project.project_feature. - update_attributes( + update_attributes!( wiki_access_level: evaluator.wiki_access_level, - builds_access_level: evaluator.builds_access_level, + builds_access_level: builds_access_level, snippets_access_level: evaluator.snippets_access_level, issues_access_level: evaluator.issues_access_level, - merge_requests_access_level: evaluator.merge_requests_access_level, + merge_requests_access_level: merge_requests_access_level, repository_access_level: evaluator.repository_access_level ) end diff --git a/spec/lib/gitlab/git_access_spec.rb b/spec/lib/gitlab/git_access_spec.rb index 62aa212f1f6..f1d0a190002 100644 --- a/spec/lib/gitlab/git_access_spec.rb +++ b/spec/lib/gitlab/git_access_spec.rb @@ -66,6 +66,7 @@ describe Gitlab::GitAccess, lib: true do context 'pull code' do it { expect(subject.allowed?).to be_falsey } + it { expect(subject.message).to match(/You are not allowed to download code/) } end end @@ -77,6 +78,7 @@ describe Gitlab::GitAccess, lib: true do context 'pull code' do it { expect(subject.allowed?).to be_falsey } + it { expect(subject.message).to match(/Your account has been blocked/) } end end @@ -84,6 +86,29 @@ describe Gitlab::GitAccess, lib: true do context 'pull code' do it { expect(subject.allowed?).to be_falsey } end + + context 'when project is public' do + let(:public_project) { create(:project, :public) } + let(:guest_access) { Gitlab::GitAccess.new(nil, public_project, 'web', authentication_abilities: []) } + subject { guest_access.check('git-upload-pack', '_any') } + + context 'when repository is enabled' do + it 'give access to download code' do + public_project.project_feature.update_attribute(:repository_access_level, ProjectFeature::ENABLED) + + expect(subject.allowed?).to be_truthy + end + end + + context 'when repository is disabled' do + it 'does not give access to download code' do + public_project.project_feature.update_attribute(:repository_access_level, ProjectFeature::DISABLED) + + expect(subject.allowed?).to be_falsey + expect(subject.message).to match(/You are not allowed to download code/) + end + end + end end describe 'deploy key permissions' do diff --git a/spec/lib/gitlab/git_access_wiki_spec.rb b/spec/lib/gitlab/git_access_wiki_spec.rb index 576cda595bb..576aa5c366f 100644 --- a/spec/lib/gitlab/git_access_wiki_spec.rb +++ b/spec/lib/gitlab/git_access_wiki_spec.rb @@ -18,7 +18,7 @@ describe Gitlab::GitAccessWiki, lib: true do project.team << [user, :developer] end - subject { access.push_access_check(changes) } + subject { access.check('git-receive-pack', changes) } it { expect(subject.allowed?).to be_truthy } end diff --git a/spec/models/guest_spec.rb b/spec/models/guest_spec.rb new file mode 100644 index 00000000000..d79f929f7a1 --- /dev/null +++ b/spec/models/guest_spec.rb @@ -0,0 +1,47 @@ +require 'spec_helper' + +describe Guest, lib: true do + let(:public_project) { create(:project, :public) } + let(:private_project) { create(:project, :private) } + let(:internal_project) { create(:project, :internal) } + + describe '.can_pull?' do + context 'when project is private' do + it 'does not allow to pull the repo' do + expect(Guest.can?(:download_code, private_project)).to eq(false) + end + end + + context 'when project is internal' do + it 'does not allow to pull the repo' do + expect(Guest.can?(:download_code, internal_project)).to eq(false) + end + end + + context 'when project is public' do + context 'when repository is disabled' do + it 'does not allow to pull the repo' do + public_project.project_feature.update_attribute(:repository_access_level, ProjectFeature::DISABLED) + + expect(Guest.can?(:download_code, public_project)).to eq(false) + end + end + + context 'when repository is accessible only by team members' do + it 'does not allow to pull the repo' do + public_project.project_feature.update_attribute(:repository_access_level, ProjectFeature::PRIVATE) + + expect(Guest.can?(:download_code, public_project)).to eq(false) + end + end + + context 'when repository is enabled' do + it 'allows to pull the repo' do + public_project.project_feature.update_attribute(:repository_access_level, ProjectFeature::ENABLED) + + expect(Guest.can?(:download_code, public_project)).to eq(true) + end + end + end + end +end diff --git a/spec/requests/git_http_spec.rb b/spec/requests/git_http_spec.rb index 27f0fd22ae6..f1728d61def 100644 --- a/spec/requests/git_http_spec.rb +++ b/spec/requests/git_http_spec.rb @@ -115,6 +115,38 @@ describe 'Git HTTP requests', lib: true do end.to raise_error(JWT::DecodeError) end end + + context 'when the repo is public' do + context 'but the repo is disabled' do + it 'does not allow to clone the repo' do + project = create(:project, :public, repository_access_level: ProjectFeature::DISABLED) + + download("#{project.path_with_namespace}.git", {}) do |response| + expect(response).to have_http_status(:unauthorized) + end + end + end + + context 'but the repo is enabled' do + it 'allows to clone the repo' do + project = create(:project, :public, repository_access_level: ProjectFeature::ENABLED) + + download("#{project.path_with_namespace}.git", {}) do |response| + expect(response).to have_http_status(:ok) + end + end + end + + context 'but only project members are allowed' do + it 'does not allow to clone the repo' do + project = create(:project, :public, repository_access_level: ProjectFeature::PRIVATE) + + download("#{project.path_with_namespace}.git", {}) do |response| + expect(response).to have_http_status(:unauthorized) + end + end + end + end end context "when the project is private" do From b0088b527eacd16773a85ad8f88e49de7c646cf1 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Fri, 4 Nov 2016 14:15:43 +0000 Subject: [PATCH 173/175] Merge branch '23403-fix-events-for-private-project-features' into 'security' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Respect project visibility settings in the contributions calendar This MR fixes a number of bugs relating to access controls and date selection of events for the contributions calendar Closes https://gitlab.com/gitlab-org/gitlab-ce/issues/23403 See merge request !2019 Signed-off-by: Rémy Coutable --- app/controllers/users_controller.rb | 3 +- app/models/event.rb | 3 +- lib/gitlab/contributions_calendar.rb | 74 ++++++++----- .../lib/gitlab/contributions_calendar_spec.rb | 104 ++++++++++++++++++ spec/models/event_spec.rb | 5 +- 5 files changed, 159 insertions(+), 30 deletions(-) create mode 100644 spec/lib/gitlab/contributions_calendar_spec.rb diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 6a881b271d7..c4508ccc3b9 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -104,8 +104,7 @@ class UsersController < ApplicationController end def contributions_calendar - @contributions_calendar ||= Gitlab::ContributionsCalendar. - new(contributed_projects, user) + @contributions_calendar ||= Gitlab::ContributionsCalendar.new(user, current_user) end def load_events diff --git a/app/models/event.rb b/app/models/event.rb index 43e67069b70..c76d88b1c7b 100644 --- a/app/models/event.rb +++ b/app/models/event.rb @@ -49,6 +49,7 @@ class Event < ActiveRecord::Base update_all(updated_at: Time.now) end + # Update Gitlab::ContributionsCalendar#activity_dates if this changes def contributions where("action = ? OR (target_type in (?) AND action in (?))", Event::PUSHED, ["MergeRequest", "Issue"], @@ -62,7 +63,7 @@ class Event < ActiveRecord::Base def visible_to_user?(user = nil) if push? - true + Ability.allowed?(user, :download_code, project) elsif membership_changed? true elsif created_project? diff --git a/lib/gitlab/contributions_calendar.rb b/lib/gitlab/contributions_calendar.rb index b164f5a2eea..7e3d5647b39 100644 --- a/lib/gitlab/contributions_calendar.rb +++ b/lib/gitlab/contributions_calendar.rb @@ -1,45 +1,44 @@ module Gitlab class ContributionsCalendar - attr_reader :activity_dates, :projects, :user + attr_reader :contributor + attr_reader :current_user + attr_reader :projects - def initialize(projects, user) - @projects = projects - @user = user + def initialize(contributor, current_user = nil) + @contributor = contributor + @current_user = current_user + @projects = ContributedProjectsFinder.new(contributor).execute(current_user) end def activity_dates return @activity_dates if @activity_dates.present? - @activity_dates = {} + # Can't use Event.contributions here because we need to check 3 different + # project_features for the (currently) 3 different contribution types date_from = 1.year.ago + repo_events = event_counts(date_from, :repository). + having(action: Event::PUSHED) + issue_events = event_counts(date_from, :issues). + having(action: [Event::CREATED, Event::CLOSED], target_type: "Issue") + mr_events = event_counts(date_from, :merge_requests). + having(action: [Event::MERGED, Event::CREATED, Event::CLOSED], target_type: "MergeRequest") - events = Event.reorder(nil).contributions.where(author_id: user.id). - where("created_at > ?", date_from).where(project_id: projects). - group('date(created_at)'). - select('date(created_at) as date, count(id) as total_amount'). - map(&:attributes) + union = Gitlab::SQL::Union.new([repo_events, issue_events, mr_events]) + events = Event.find_by_sql(union.to_sql).map(&:attributes) - activity_dates = (1.year.ago.to_date..Date.today).to_a - - activity_dates.each do |date| - day_events = events.find { |day_events| day_events["date"] == date } - - if day_events - @activity_dates[date] = day_events["total_amount"] - end + @activity_events = events.each_with_object(Hash.new {|h, k| h[k] = 0 }) do |event, activities| + activities[event["date"]] += event["total_amount"] end - - @activity_dates end def events_by_date(date) - events = Event.contributions.where(author_id: user.id). - where("created_at > ? AND created_at < ?", date.beginning_of_day, date.end_of_day). + events = Event.contributions.where(author_id: contributor.id). + where(created_at: date.beginning_of_day..date.end_of_day). where(project_id: projects) - events.select do |event| - event.push? || event.issue? || event.merge_request? - end + # Use visible_to_user? instead of the complicated logic in activity_dates + # because we're only viewing the events for a single day. + events.select {|event| event.visible_to_user?(current_user) } end def starting_year @@ -49,5 +48,30 @@ module Gitlab def starting_month Date.today.month end + + private + + def event_counts(date_from, feature) + t = Event.arel_table + + # re-running the contributed projects query in each union is expensive, so + # use IN(project_ids...) instead. It's the intersection of two users so + # the list will be (relatively) short + @contributed_project_ids ||= projects.uniq.pluck(:id) + authed_projects = Project.where(id: @contributed_project_ids). + with_feature_available_for_user(feature, current_user). + reorder(nil). + select(:id) + + conditions = t[:created_at].gteq(date_from.beginning_of_day). + and(t[:created_at].lteq(Date.today.end_of_day)). + and(t[:author_id].eq(contributor.id)) + + Event.reorder(nil). + select(t[:project_id], t[:target_type], t[:action], 'date(created_at) AS date', 'count(id) as total_amount'). + group(t[:project_id], t[:target_type], t[:action], 'date(created_at)'). + where(conditions). + having(t[:project_id].in(Arel::Nodes::SqlLiteral.new(authed_projects.to_sql))) + end end end diff --git a/spec/lib/gitlab/contributions_calendar_spec.rb b/spec/lib/gitlab/contributions_calendar_spec.rb new file mode 100644 index 00000000000..01b2a55b63c --- /dev/null +++ b/spec/lib/gitlab/contributions_calendar_spec.rb @@ -0,0 +1,104 @@ +require 'spec_helper' + +describe Gitlab::ContributionsCalendar do + let(:contributor) { create(:user) } + let(:user) { create(:user) } + + let(:private_project) do + create(:empty_project, :private) do |project| + create(:project_member, user: contributor, project: project) + end + end + + let(:public_project) do + create(:empty_project, :public) do |project| + create(:project_member, user: contributor, project: project) + end + end + + let(:feature_project) do + create(:empty_project, :public, issues_access_level: ProjectFeature::PRIVATE) do |project| + create(:project_member, user: contributor, project: project).project + end + end + + let(:today) { Time.now.to_date } + let(:last_week) { today - 7.days } + let(:last_year) { today - 1.year } + + before do + travel_to today + end + + after do + travel_back + end + + def calendar(current_user = nil) + described_class.new(contributor, current_user) + end + + def create_event(project, day) + @targets ||= {} + @targets[project] ||= create(:issue, project: project, author: contributor) + + Event.create!( + project: project, + action: Event::CREATED, + target: @targets[project], + author: contributor, + created_at: day, + ) + end + + describe '#activity_dates' do + it "returns a hash of date => count" do + create_event(public_project, last_week) + create_event(public_project, last_week) + create_event(public_project, today) + + expect(calendar.activity_dates).to eq(last_week => 2, today => 1) + end + + it "only shows private events to authorized users" do + create_event(private_project, today) + create_event(feature_project, today) + + expect(calendar.activity_dates[today]).to eq(0) + expect(calendar(user).activity_dates[today]).to eq(0) + expect(calendar(contributor).activity_dates[today]).to eq(2) + end + end + + describe '#events_by_date' do + it "returns all events for a given date" do + e1 = create_event(public_project, today) + e2 = create_event(public_project, today) + create_event(public_project, last_week) + + expect(calendar.events_by_date(today)).to contain_exactly(e1, e2) + end + + it "only shows private events to authorized users" do + e1 = create_event(public_project, today) + e2 = create_event(private_project, today) + e3 = create_event(feature_project, today) + create_event(public_project, last_week) + + expect(calendar.events_by_date(today)).to contain_exactly(e1) + expect(calendar(contributor).events_by_date(today)).to contain_exactly(e1, e2, e3) + end + end + + describe '#starting_year' do + it "should be the start of last year" do + expect(calendar.starting_year).to eq(last_year.year) + end + end + + describe '#starting_month' do + it "should be the start of this month" do + expect(calendar.starting_month).to eq(today.month) + end + end +end diff --git a/spec/models/event_spec.rb b/spec/models/event_spec.rb index aca49be2942..29a3af68a9b 100644 --- a/spec/models/event_spec.rb +++ b/spec/models/event_spec.rb @@ -27,13 +27,14 @@ describe Event, models: true do end describe "Push event" do - let(:project) { create(:project) } + let(:project) { create(:project, :private) } let(:user) { project.owner } let(:event) { create_event(project, user) } it do expect(event.push?).to be_truthy - expect(event.visible_to_user?).to be_truthy + expect(event.visible_to_user?(user)).to be_truthy + expect(event.visible_to_user?(nil)).to be_falsey expect(event.tag?).to be_falsey expect(event.branch_name).to eq("master") expect(event.author).to eq(user) From 32042ef56adfa24ce5952c6f3b7dc97dea5fd2d4 Mon Sep 17 00:00:00 2001 From: Alejandro Rodriguez Date: Tue, 8 Nov 2016 18:37:15 +0000 Subject: [PATCH 174/175] Merge branch 'unauthenticated-container-registry-access' into 'security' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restore unauthenticated access to public container registries Fixes https://gitlab.com/gitlab-org/gitlab-ce/issues/24284 See merge request !2025 Signed-off-by: Rémy Coutable --- app/controllers/jwt_controller.rb | 4 ++-- ...ontainer_registry_authentication_service.rb | 16 ++++++++++------ spec/requests/jwt_controller_spec.rb | 18 ++++++++++++++++-- 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/app/controllers/jwt_controller.rb b/app/controllers/jwt_controller.rb index 7e4da73bc11..c736200a104 100644 --- a/app/controllers/jwt_controller.rb +++ b/app/controllers/jwt_controller.rb @@ -12,7 +12,7 @@ class JwtController < ApplicationController return head :not_found unless service result = service.new(@authentication_result.project, @authentication_result.actor, auth_params). - execute(authentication_abilities: @authentication_result.authentication_abilities || []) + execute(authentication_abilities: @authentication_result.authentication_abilities) render json: result, status: result[:http_status] end @@ -20,7 +20,7 @@ class JwtController < ApplicationController private def authenticate_project_or_user - @authentication_result = Gitlab::Auth::Result.new + @authentication_result = Gitlab::Auth::Result.new(nil, nil, :none, Gitlab::Auth.read_authentication_abilities) authenticate_with_http_basic do |login, password| @authentication_result = Gitlab::Auth.find_for_git_client(login, password, project: nil, ip: request.ip) diff --git a/app/services/auth/container_registry_authentication_service.rb b/app/services/auth/container_registry_authentication_service.rb index 3fc1c70be75..c00c5aebf57 100644 --- a/app/services/auth/container_registry_authentication_service.rb +++ b/app/services/auth/container_registry_authentication_service.rb @@ -9,8 +9,8 @@ module Auth return error('UNAVAILABLE', status: 404, message: 'registry not enabled') unless registry.enabled - unless current_user || project - return error('DENIED', status: 403, message: 'access forbidden') unless scope + unless scope || current_user || project + return error('DENIED', status: 403, message: 'access forbidden') end { token: authorized_token(scope).encoded } @@ -92,23 +92,23 @@ module Auth # Build can: # 1. pull from its own project (for ex. a build) # 2. read images from dependent projects if creator of build is a team member - @authentication_abilities.include?(:build_read_container_image) && + has_authentication_ability?(:build_read_container_image) && (requested_project == project || can?(current_user, :build_read_container_image, requested_project)) end def user_can_pull?(requested_project) - @authentication_abilities.include?(:read_container_image) && + has_authentication_ability?(:read_container_image) && can?(current_user, :read_container_image, requested_project) end def build_can_push?(requested_project) # Build can push only to the project from which it originates - @authentication_abilities.include?(:build_create_container_image) && + has_authentication_ability?(:build_create_container_image) && requested_project == project end def user_can_push?(requested_project) - @authentication_abilities.include?(:create_container_image) && + has_authentication_ability?(:create_container_image) && can?(current_user, :create_container_image, requested_project) end @@ -118,5 +118,9 @@ module Auth http_status: status } end + + def has_authentication_ability?(capability) + (@authentication_abilities || []).include?(capability) + end end end diff --git a/spec/requests/jwt_controller_spec.rb b/spec/requests/jwt_controller_spec.rb index f0ef155bd7b..a3e7844b2f3 100644 --- a/spec/requests/jwt_controller_spec.rb +++ b/spec/requests/jwt_controller_spec.rb @@ -20,7 +20,7 @@ describe JwtController do end end - context 'when using authorized request' do + context 'when using authenticated request' do context 'using CI token' do let(:build) { create(:ci_build, :running) } let(:project) { build.project } @@ -65,7 +65,7 @@ describe JwtController do let(:access_token) { create(:personal_access_token, user: user) } let(:headers) { { authorization: credentials(user.username, access_token.token) } } - it 'rejects the authorization attempt' do + it 'accepts the authorization attempt' do expect(response).to have_http_status(200) end end @@ -81,6 +81,20 @@ describe JwtController do end end + context 'when using unauthenticated request' do + it 'accepts the authorization attempt' do + get '/jwt/auth', parameters + + expect(response).to have_http_status(200) + end + + it 'allows read access' do + expect(service).to receive(:execute).with(authentication_abilities: Gitlab::Auth.read_authentication_abilities) + + get '/jwt/auth', parameters + end + end + context 'unknown service' do subject! { get '/jwt/auth', service: 'unknown' } From 940cb3db5b936aec90a08c94aa9952f9b52c1fd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Wed, 9 Nov 2016 12:32:14 +0100 Subject: [PATCH 175/175] Add 8.13.5, 8.12.9, and 8.11.11 CHANGELOG MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ci skip] Signed-off-by: Rémy Coutable --- CHANGELOG.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b072ce9f60..8250b9b5cdb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -73,6 +73,28 @@ entry. - Updated commit SHA styling on the branches page. - Fix 404 when visit /projects page +## 8.13.5 (2016-11-08) + +- Restore unauthenticated access to public container registries + +## 8.13.4 (2016-11-07) + +- Fix showing pipeline status for a given commit from correct branch. !7034 +- Only skip group when it's actually a group in the "Share with group" select. !7262 +- Introduce round-robin project creation to spread load over multiple shards. !7266 +- Ensure merge request's "remove branch" accessors return booleans. !7267 +- Ensure external users are not able to clone disabled repositories. +- Fix XSS issue in Markdown autolinker. +- Respect event visibility in Gitlab::ContributionsCalendar. +- Honour issue and merge request visibility in their respective finders. +- Disable reference Markdown for unavailable features. +- Fix lightweight tags not processed correctly by GitTagPushService. !6532 +- Allow owners to fetch source code in CI builds. !6943 +- Return conflict error in label API when title is taken by group label. !7014 +- Reduce the overhead to calculate number of open/closed issues and merge requests within the group or project. !7123 +- Fix builds tab visibility. !7178 +- Fix project features default values. !7181 + ## 8.13.3 (2016-11-02) - Removes any symlinks before importing a project export file. CVE-2016-9086 @@ -270,6 +292,10 @@ entry. - Fix broken Project API docs (Takuya Noguchi) - Migrate invalid project members (owner -> master) +## 8.12.9 (2016-11-07) + +- Fix XSS issue in Markdown autolinker + ## 8.12.8 (2016-11-02) - Removes any symlinks before importing a project export file. CVE-2016-9086 @@ -534,6 +560,10 @@ entry. - Fix non-master branch readme display in tree view - Add UX improvements for merge request version diffs +## 8.11.11 (2016-11-07) + +- Fix XSS issue in Markdown autolinker + ## 8.11.10 (2016-11-02) - Removes any symlinks before importing a project export file. CVE-2016-9086

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 literal 0 HcmV?d00001 diff --git a/doc/project_services/img/jira_create_new_group.png b/doc/project_services/img/jira_create_new_group.png new file mode 100644 index 0000000000000000000000000000000000000000..0609060cb05c4d5827efdc9d685186ade64bbbf6 GIT binary patch literal 32934 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 P8HkL8f_Q=0>-YZ;typU$ literal 0 HcmV?d00001 diff --git a/doc/project_services/img/jira_create_new_user.png b/doc/project_services/img/jira_create_new_user.png new file mode 100644 index 0000000000000000000000000000000000000000..9eaa444ed25b9b17e12a311a77a36bba023368aa GIT binary patch literal 21081 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 literal 0 HcmV?d00001 diff --git a/doc/project_services/img/jira_group_access.png b/doc/project_services/img/jira_group_access.png new file mode 100644 index 0000000000000000000000000000000000000000..8d4657427ae206efea0da2ee8a4b0a50196f576f GIT binary patch literal 32210 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