From 8bbaf266cc8d1ff03c4f7a4173ce9a7ac60c0cbb Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Thu, 8 Mar 2018 17:33:06 +0000 Subject: Handle empty states for job page --- app/views/projects/jobs/_empty_state.html.haml | 5 ++-- app/views/projects/jobs/_empty_status.html.haml | 29 ++++++++++++++++++++++ app/views/projects/jobs/show.html.haml | 23 +++-------------- .../unreleased/42568-pipeline-empty-state.yml | 5 ++++ db/fixtures/development/14_pipelines.rb | 4 +++ spec/features/projects/jobs_spec.rb | 27 ++++++++++++++++++++ 6 files changed, 72 insertions(+), 21 deletions(-) create mode 100644 app/views/projects/jobs/_empty_status.html.haml create mode 100644 changelogs/unreleased/42568-pipeline-empty-state.yml diff --git a/app/views/projects/jobs/_empty_state.html.haml b/app/views/projects/jobs/_empty_state.html.haml index c66313bdbf3..311934d9c33 100644 --- a/app/views/projects/jobs/_empty_state.html.haml +++ b/app/views/projects/jobs/_empty_state.html.haml @@ -1,7 +1,7 @@ - illustration = local_assigns.fetch(:illustration) - illustration_size = local_assigns.fetch(:illustration_size) - title = local_assigns.fetch(:title) -- content = local_assigns.fetch(:content) +- content = local_assigns.fetch(:content, nil) - action = local_assigns.fetch(:action, nil) .row.empty-state @@ -11,7 +11,8 @@ .col-xs-12 .text-content %h4.text-center= title - %p= content + - if content + %p= content - if action .text-center = action diff --git a/app/views/projects/jobs/_empty_status.html.haml b/app/views/projects/jobs/_empty_status.html.haml new file mode 100644 index 00000000000..707085cddd5 --- /dev/null +++ b/app/views/projects/jobs/_empty_status.html.haml @@ -0,0 +1,29 @@ +- if @build.playable? + = render 'empty_state', + illustration: 'illustrations/manual_action.svg', + illustration_size: 'svg-394', + title: _('This job requires a manual action'), + content: _('This job depends on a user to trigger its process. Often they are used to deploy code to production environments'), + action: ( link_to _('Trigger this manual action'), play_project_job_path(@project, @build), method: :post, class: 'btn btn-primary', title: _('Trigger this manual action') ) +- elsif @build.created? + = render 'empty_state', + illustration: 'illustrations/job_not_triggered.svg', + illustration_size: 'svg-306', + title: _('This job has not been triggered yet'), + content: _('This job depends on upstream jobs that need to succeed in order for this job to be triggered') +- elsif @build.canceled? + = render 'empty_state', + illustration: 'illustrations/canceled-job_empty.svg', + illustration_size: 'svg-430', + title: _('This job has been canceled') +- elsif @build.skipped? + = render 'empty_state', + illustration: 'illustrations/canceled-job_empty.svg', + illustration_size: 'svg-430', + title: _('This job has been skipped') +- else + = render 'empty_state', + illustration: 'illustrations/pending_job_empty.svg', + illustration_size: 'svg-430', + title: _('This job has not started yet'), + content: _('This job is in pending state and is waiting to be picked by a runner') diff --git a/app/views/projects/jobs/show.html.haml b/app/views/projects/jobs/show.html.haml index 849c273db8c..04c28841511 100644 --- a/app/views/projects/jobs/show.html.haml +++ b/app/views/projects/jobs/show.html.haml @@ -54,7 +54,8 @@ Job has been erased by #{link_to(@build.erased_by_name, user_path(@build.erased_by))} #{time_ago_with_tooltip(@build.erased_at)} - else Job has been erased #{time_ago_with_tooltip(@build.erased_at)} - - if @build.started? + + - if @build.has_trace? .build-trace-container.prepend-top-default .top-bar.js-top-bar .js-truncated-info.truncated-info.hidden-xs.pull-left.hidden< @@ -88,25 +89,9 @@ %pre.build-trace#build-trace %code.bash.js-build-output .build-loader-animation.js-build-refresh - - elsif @build.playable? - = render 'empty_state', - illustration: 'illustrations/manual_action.svg', - illustration_size: 'svg-394', - title: _('This job requires a manual action'), - content: _('This job depends on a user to trigger its process. Often they are used to deploy code to production environments'), - action: ( link_to _('Trigger this manual action'), play_project_job_path(@project, @build), method: :post, class: 'btn btn-primary', title: _('Trigger this manual action') ) - - elsif @build.created? - = render 'empty_state', - illustration: 'illustrations/job_not_triggered.svg', - illustration_size: 'svg-306', - title: _('This job has not been triggered yet'), - content: _('This job depends on upstream jobs that need to succeed in order for this job to be triggered') - else - = render 'empty_state', - illustration: 'illustrations/pending_job_empty.svg', - illustration_size: 'svg-430', - title: _('This job has not started yet'), - content: _('This job is in pending state and is waiting to be picked by a runner') + = render "empty_status" + = render "sidebar" .js-build-options{ data: javascript_build_options } diff --git a/changelogs/unreleased/42568-pipeline-empty-state.yml b/changelogs/unreleased/42568-pipeline-empty-state.yml new file mode 100644 index 00000000000..d36edcf1b37 --- /dev/null +++ b/changelogs/unreleased/42568-pipeline-empty-state.yml @@ -0,0 +1,5 @@ +--- +title: Improve empty state for canceled job +merge_request: 17646 +author: +type: fixed diff --git a/db/fixtures/development/14_pipelines.rb b/db/fixtures/development/14_pipelines.rb index d3a63aa2a78..fe21b7aad0e 100644 --- a/db/fixtures/development/14_pipelines.rb +++ b/db/fixtures/development/14_pipelines.rb @@ -30,6 +30,10 @@ class Gitlab::Seeder::Pipelines queued_at: 8.hour.ago, started_at: 8.hour.ago, finished_at: 7.hour.ago }, { name: 'spinach:osx', stage: 'test', status: :failed, allow_failure: true, queued_at: 8.hour.ago, started_at: 8.hour.ago, finished_at: 7.hour.ago }, + { name: 'spinach:osx1', stage: 'test', status: :canceled, + queued_at: 8.hour.ago, started_at: 8.hour.ago, finished_at: 7.hour.ago }, + { name: 'spinach:osx1', stage: 'test', status: :running, + queued_at: 8.hour.ago, started_at: 8.hour.ago, finished_at: 7.hour.ago }, # deploy stage { name: 'staging', stage: 'deploy', environment: 'staging', status_event: :success, diff --git a/spec/features/projects/jobs_spec.rb b/spec/features/projects/jobs_spec.rb index 5d311f2dde3..aa4c2757a25 100644 --- a/spec/features/projects/jobs_spec.rb +++ b/spec/features/projects/jobs_spec.rb @@ -419,6 +419,33 @@ feature 'Jobs' do expect(page).to have_content('This job is in pending state and is waiting to be picked by a runner') end end + + context 'Canceled job' do + context 'with log' do + let(:job) { create(:ci_build, :canceled, :trace_artifact, pipeline: pipeline) } + + before do + visit project_job_path(project, job) + end + + it 'renders job log' do + expect(page).to have_selector('.js-build-output') + end + end + + context 'without log' do + let(:job) { create(:ci_build, :canceled, pipeline: pipeline) } + + before do + visit project_job_path(project, job) + end + + it 'renders empty state' do + expect(page).not_to have_selector('.js-build-output') + expect(page).to have_content('This job has been canceled') + end + end + end end describe "POST /:project/jobs/:id/cancel", :js do -- cgit v1.2.3 From cd6a58c8100356be95019be6a69724066469bd42 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Fri, 9 Mar 2018 17:59:59 +0000 Subject: Fix broken test --- features/steps/shared/builds.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/steps/shared/builds.rb b/features/steps/shared/builds.rb index a3e4459f169..f5950145348 100644 --- a/features/steps/shared/builds.rb +++ b/features/steps/shared/builds.rb @@ -11,7 +11,7 @@ module SharedBuilds step 'project has a recent build' do @pipeline = create(:ci_empty_pipeline, project: @project, sha: @project.commit.sha, ref: 'master') - @build = create(:ci_build, :running, :coverage, pipeline: @pipeline) + @build = create(:ci_build, :running, :coverage, :trace_artifact, pipeline: @pipeline) end step 'recent build is successful' do -- cgit v1.2.3 From c7776a1d32621740f1eea17ec0385889280df65e Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Mon, 12 Mar 2018 19:13:13 +0000 Subject: Render skipped illustration for skipped state --- app/views/projects/jobs/_empty_status.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/projects/jobs/_empty_status.html.haml b/app/views/projects/jobs/_empty_status.html.haml index 707085cddd5..9e144dbfe32 100644 --- a/app/views/projects/jobs/_empty_status.html.haml +++ b/app/views/projects/jobs/_empty_status.html.haml @@ -18,7 +18,7 @@ title: _('This job has been canceled') - elsif @build.skipped? = render 'empty_state', - illustration: 'illustrations/canceled-job_empty.svg', + illustration: 'illustrations/skipped-job_empty.svg', illustration_size: 'svg-430', title: _('This job has been skipped') - else -- cgit v1.2.3 From 18bce8fcfeaaeeda5aea37f21adedcdc49dd4147 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Mon, 19 Mar 2018 10:07:30 +0000 Subject: Update partial name and remove changes to database fixtures --- app/views/projects/jobs/_empty_states.html.haml | 29 +++++++++++++++++++++++++ app/views/projects/jobs/_empty_status.html.haml | 29 ------------------------- app/views/projects/jobs/show.html.haml | 2 +- db/fixtures/development/14_pipelines.rb | 4 ---- 4 files changed, 30 insertions(+), 34 deletions(-) create mode 100644 app/views/projects/jobs/_empty_states.html.haml delete mode 100644 app/views/projects/jobs/_empty_status.html.haml diff --git a/app/views/projects/jobs/_empty_states.html.haml b/app/views/projects/jobs/_empty_states.html.haml new file mode 100644 index 00000000000..9e144dbfe32 --- /dev/null +++ b/app/views/projects/jobs/_empty_states.html.haml @@ -0,0 +1,29 @@ +- if @build.playable? + = render 'empty_state', + illustration: 'illustrations/manual_action.svg', + illustration_size: 'svg-394', + title: _('This job requires a manual action'), + content: _('This job depends on a user to trigger its process. Often they are used to deploy code to production environments'), + action: ( link_to _('Trigger this manual action'), play_project_job_path(@project, @build), method: :post, class: 'btn btn-primary', title: _('Trigger this manual action') ) +- elsif @build.created? + = render 'empty_state', + illustration: 'illustrations/job_not_triggered.svg', + illustration_size: 'svg-306', + title: _('This job has not been triggered yet'), + content: _('This job depends on upstream jobs that need to succeed in order for this job to be triggered') +- elsif @build.canceled? + = render 'empty_state', + illustration: 'illustrations/canceled-job_empty.svg', + illustration_size: 'svg-430', + title: _('This job has been canceled') +- elsif @build.skipped? + = render 'empty_state', + illustration: 'illustrations/skipped-job_empty.svg', + illustration_size: 'svg-430', + title: _('This job has been skipped') +- else + = render 'empty_state', + illustration: 'illustrations/pending_job_empty.svg', + illustration_size: 'svg-430', + title: _('This job has not started yet'), + content: _('This job is in pending state and is waiting to be picked by a runner') diff --git a/app/views/projects/jobs/_empty_status.html.haml b/app/views/projects/jobs/_empty_status.html.haml deleted file mode 100644 index 9e144dbfe32..00000000000 --- a/app/views/projects/jobs/_empty_status.html.haml +++ /dev/null @@ -1,29 +0,0 @@ -- if @build.playable? - = render 'empty_state', - illustration: 'illustrations/manual_action.svg', - illustration_size: 'svg-394', - title: _('This job requires a manual action'), - content: _('This job depends on a user to trigger its process. Often they are used to deploy code to production environments'), - action: ( link_to _('Trigger this manual action'), play_project_job_path(@project, @build), method: :post, class: 'btn btn-primary', title: _('Trigger this manual action') ) -- elsif @build.created? - = render 'empty_state', - illustration: 'illustrations/job_not_triggered.svg', - illustration_size: 'svg-306', - title: _('This job has not been triggered yet'), - content: _('This job depends on upstream jobs that need to succeed in order for this job to be triggered') -- elsif @build.canceled? - = render 'empty_state', - illustration: 'illustrations/canceled-job_empty.svg', - illustration_size: 'svg-430', - title: _('This job has been canceled') -- elsif @build.skipped? - = render 'empty_state', - illustration: 'illustrations/skipped-job_empty.svg', - illustration_size: 'svg-430', - title: _('This job has been skipped') -- else - = render 'empty_state', - illustration: 'illustrations/pending_job_empty.svg', - illustration_size: 'svg-430', - title: _('This job has not started yet'), - content: _('This job is in pending state and is waiting to be picked by a runner') diff --git a/app/views/projects/jobs/show.html.haml b/app/views/projects/jobs/show.html.haml index 04c28841511..1db01133900 100644 --- a/app/views/projects/jobs/show.html.haml +++ b/app/views/projects/jobs/show.html.haml @@ -90,7 +90,7 @@ %code.bash.js-build-output .build-loader-animation.js-build-refresh - else - = render "empty_status" + = render "empty_states" = render "sidebar" diff --git a/db/fixtures/development/14_pipelines.rb b/db/fixtures/development/14_pipelines.rb index fe21b7aad0e..d3a63aa2a78 100644 --- a/db/fixtures/development/14_pipelines.rb +++ b/db/fixtures/development/14_pipelines.rb @@ -30,10 +30,6 @@ class Gitlab::Seeder::Pipelines queued_at: 8.hour.ago, started_at: 8.hour.ago, finished_at: 7.hour.ago }, { name: 'spinach:osx', stage: 'test', status: :failed, allow_failure: true, queued_at: 8.hour.ago, started_at: 8.hour.ago, finished_at: 7.hour.ago }, - { name: 'spinach:osx1', stage: 'test', status: :canceled, - queued_at: 8.hour.ago, started_at: 8.hour.ago, finished_at: 7.hour.ago }, - { name: 'spinach:osx1', stage: 'test', status: :running, - queued_at: 8.hour.ago, started_at: 8.hour.ago, finished_at: 7.hour.ago }, # deploy stage { name: 'staging', stage: 'deploy', environment: 'staging', status_event: :success, -- cgit v1.2.3 From d696194f8f80dd6fe4feb9ec7bb42a29ab9e98f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20=C4=8Cupi=C4=87?= Date: Sat, 24 Mar 2018 11:46:04 +0100 Subject: Add illustrations to build statuses --- lib/gitlab/ci/status/canceled.rb | 4 ++++ lib/gitlab/ci/status/core.rb | 4 ++++ lib/gitlab/ci/status/created.rb | 4 ++++ lib/gitlab/ci/status/manual.rb | 4 ++++ lib/gitlab/ci/status/pending.rb | 4 ++++ lib/gitlab/ci/status/skipped.rb | 4 ++++ spec/lib/gitlab/ci/status/build/factory_spec.rb | 4 ++++ spec/lib/gitlab/ci/status/canceled_spec.rb | 4 ++++ spec/lib/gitlab/ci/status/created_spec.rb | 4 ++++ spec/lib/gitlab/ci/status/manual_spec.rb | 4 ++++ spec/lib/gitlab/ci/status/pending_spec.rb | 4 ++++ spec/lib/gitlab/ci/status/skipped_spec.rb | 4 ++++ 12 files changed, 48 insertions(+) diff --git a/lib/gitlab/ci/status/canceled.rb b/lib/gitlab/ci/status/canceled.rb index e6195a60d4f..9a25375678d 100644 --- a/lib/gitlab/ci/status/canceled.rb +++ b/lib/gitlab/ci/status/canceled.rb @@ -17,6 +17,10 @@ module Gitlab def favicon 'favicon_status_canceled' end + + def illustration + 'canceled-job_empty' + end end end end diff --git a/lib/gitlab/ci/status/core.rb b/lib/gitlab/ci/status/core.rb index d4fd83b93f8..89fb9a0b7bc 100644 --- a/lib/gitlab/ci/status/core.rb +++ b/lib/gitlab/ci/status/core.rb @@ -22,6 +22,10 @@ module Gitlab raise NotImplementedError end + def illustration + raise NotImplementedError + end + def label raise NotImplementedError end diff --git a/lib/gitlab/ci/status/created.rb b/lib/gitlab/ci/status/created.rb index 846f00b83dd..033ecbe9380 100644 --- a/lib/gitlab/ci/status/created.rb +++ b/lib/gitlab/ci/status/created.rb @@ -17,6 +17,10 @@ module Gitlab def favicon 'favicon_status_created' end + + def illustration + 'job_not_triggered' + end end end end diff --git a/lib/gitlab/ci/status/manual.rb b/lib/gitlab/ci/status/manual.rb index fc387e2fd25..92c449e2c63 100644 --- a/lib/gitlab/ci/status/manual.rb +++ b/lib/gitlab/ci/status/manual.rb @@ -17,6 +17,10 @@ module Gitlab def favicon 'favicon_status_manual' end + + def illustration + 'manual_action' + end end end end diff --git a/lib/gitlab/ci/status/pending.rb b/lib/gitlab/ci/status/pending.rb index 6780780db32..63c0b5b501f 100644 --- a/lib/gitlab/ci/status/pending.rb +++ b/lib/gitlab/ci/status/pending.rb @@ -17,6 +17,10 @@ module Gitlab def favicon 'favicon_status_pending' end + + def illustration + 'pending_job_empty' + end end end end diff --git a/lib/gitlab/ci/status/skipped.rb b/lib/gitlab/ci/status/skipped.rb index 0dbdc4de426..5dbe2847344 100644 --- a/lib/gitlab/ci/status/skipped.rb +++ b/lib/gitlab/ci/status/skipped.rb @@ -17,6 +17,10 @@ module Gitlab def favicon 'favicon_status_skipped' end + + def illustration + 'skipped-job_empty' + end end end end diff --git a/spec/lib/gitlab/ci/status/build/factory_spec.rb b/spec/lib/gitlab/ci/status/build/factory_spec.rb index d196bc6a4c2..04b718c5897 100644 --- a/spec/lib/gitlab/ci/status/build/factory_spec.rb +++ b/spec/lib/gitlab/ci/status/build/factory_spec.rb @@ -115,6 +115,7 @@ describe Gitlab::Ci::Status::Build::Factory do expect(status.text).to eq 'canceled' expect(status.icon).to eq 'status_canceled' expect(status.favicon).to eq 'favicon_status_canceled' + expect(status.illustration).to eq 'canceled-job_empty' expect(status.label).to eq 'canceled' expect(status).to have_details expect(status).to have_action @@ -167,6 +168,7 @@ describe Gitlab::Ci::Status::Build::Factory do expect(status.text).to eq 'pending' expect(status.icon).to eq 'status_pending' expect(status.favicon).to eq 'favicon_status_pending' + expect(status.illustration).to eq 'pending_job_empty' expect(status.label).to eq 'pending' expect(status).to have_details expect(status).to have_action @@ -192,6 +194,7 @@ describe Gitlab::Ci::Status::Build::Factory do expect(status.text).to eq 'skipped' expect(status.icon).to eq 'status_skipped' expect(status.favicon).to eq 'favicon_status_skipped' + expect(status.illustration).to eq 'skipped-job_empty' expect(status.label).to eq 'skipped' expect(status).to have_details expect(status).not_to have_action @@ -221,6 +224,7 @@ describe Gitlab::Ci::Status::Build::Factory do expect(status.group).to eq 'manual' expect(status.icon).to eq 'status_manual' expect(status.favicon).to eq 'favicon_status_manual' + expect(status.illustration).to eq 'manual_action' expect(status.label).to include 'manual play action' expect(status).to have_details expect(status.action_path).to include 'play' diff --git a/spec/lib/gitlab/ci/status/canceled_spec.rb b/spec/lib/gitlab/ci/status/canceled_spec.rb index dc74d7e28c5..fc1d9e726ab 100644 --- a/spec/lib/gitlab/ci/status/canceled_spec.rb +++ b/spec/lib/gitlab/ci/status/canceled_spec.rb @@ -21,6 +21,10 @@ describe Gitlab::Ci::Status::Canceled do it { expect(subject.favicon).to eq 'favicon_status_canceled' } end + describe '#illustration' do + it { expect(subject.illustration).to eq 'canceled-job_empty' } + end + describe '#group' do it { expect(subject.group).to eq 'canceled' } end diff --git a/spec/lib/gitlab/ci/status/created_spec.rb b/spec/lib/gitlab/ci/status/created_spec.rb index ce4333f2aca..f7e3b0d8f1a 100644 --- a/spec/lib/gitlab/ci/status/created_spec.rb +++ b/spec/lib/gitlab/ci/status/created_spec.rb @@ -21,6 +21,10 @@ describe Gitlab::Ci::Status::Created do it { expect(subject.favicon).to eq 'favicon_status_created' } end + describe '#illustration' do + it { expect(subject.illustration).to eq 'job_not_triggered' } + end + describe '#group' do it { expect(subject.group).to eq 'created' } end diff --git a/spec/lib/gitlab/ci/status/manual_spec.rb b/spec/lib/gitlab/ci/status/manual_spec.rb index 0463f2e1aff..161c4774ff3 100644 --- a/spec/lib/gitlab/ci/status/manual_spec.rb +++ b/spec/lib/gitlab/ci/status/manual_spec.rb @@ -21,6 +21,10 @@ describe Gitlab::Ci::Status::Manual do it { expect(subject.favicon).to eq 'favicon_status_manual' } end + describe '#illustration' do + it { expect(subject.illustration).to eq 'manual_action' } + end + describe '#group' do it { expect(subject.group).to eq 'manual' } end diff --git a/spec/lib/gitlab/ci/status/pending_spec.rb b/spec/lib/gitlab/ci/status/pending_spec.rb index 0e25358dd8a..92349308842 100644 --- a/spec/lib/gitlab/ci/status/pending_spec.rb +++ b/spec/lib/gitlab/ci/status/pending_spec.rb @@ -21,6 +21,10 @@ describe Gitlab::Ci::Status::Pending do it { expect(subject.favicon).to eq 'favicon_status_pending' } end + describe '#illustration' do + it { expect(subject.illustration).to eq 'pending_job_empty' } + end + describe '#group' do it { expect(subject.group).to eq 'pending' } end diff --git a/spec/lib/gitlab/ci/status/skipped_spec.rb b/spec/lib/gitlab/ci/status/skipped_spec.rb index 63694ca0ea6..993490c6d4e 100644 --- a/spec/lib/gitlab/ci/status/skipped_spec.rb +++ b/spec/lib/gitlab/ci/status/skipped_spec.rb @@ -21,6 +21,10 @@ describe Gitlab::Ci::Status::Skipped do it { expect(subject.favicon).to eq 'favicon_status_skipped' } end + describe '#illustration' do + it { expect(subject.illustration).to eq 'skipped-job_empty' } + end + describe '#group' do it { expect(subject.group).to eq 'skipped' } end -- cgit v1.2.3 From d0349362a7681dc72636b0041a28d58a6e979707 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20=C4=8Cupi=C4=87?= Date: Mon, 26 Mar 2018 17:28:53 +0200 Subject: Extend Gitlab::Ci::Status#illustration to include metadata --- lib/gitlab/ci/status/canceled.rb | 6 +++++- lib/gitlab/ci/status/created.rb | 7 ++++++- lib/gitlab/ci/status/manual.rb | 7 ++++++- lib/gitlab/ci/status/pending.rb | 7 ++++++- lib/gitlab/ci/status/skipped.rb | 6 +++++- spec/lib/gitlab/ci/status/build/factory_spec.rb | 8 ++++---- spec/lib/gitlab/ci/status/canceled_spec.rb | 2 +- spec/lib/gitlab/ci/status/created_spec.rb | 2 +- spec/lib/gitlab/ci/status/manual_spec.rb | 2 +- spec/lib/gitlab/ci/status/pending_spec.rb | 2 +- spec/lib/gitlab/ci/status/skipped_spec.rb | 2 +- 11 files changed, 37 insertions(+), 14 deletions(-) diff --git a/lib/gitlab/ci/status/canceled.rb b/lib/gitlab/ci/status/canceled.rb index 9a25375678d..bea8dcd5587 100644 --- a/lib/gitlab/ci/status/canceled.rb +++ b/lib/gitlab/ci/status/canceled.rb @@ -19,7 +19,11 @@ module Gitlab end def illustration - 'canceled-job_empty' + { + image: 'illustrations/canceled-job_empty.svg', + size: 'svg-430', + title: _('This job has been canceled') + } end end end diff --git a/lib/gitlab/ci/status/created.rb b/lib/gitlab/ci/status/created.rb index 033ecbe9380..3b2a9e5d0ef 100644 --- a/lib/gitlab/ci/status/created.rb +++ b/lib/gitlab/ci/status/created.rb @@ -19,7 +19,12 @@ module Gitlab end def illustration - 'job_not_triggered' + { + image: 'illustrations/job_not_triggered.svg', + size: 'svg-306', + title: _('This job has not been triggered yet'), + content: _('This job depends on upstream jobs that need to succeed in order for this job to be triggered') + } end end end diff --git a/lib/gitlab/ci/status/manual.rb b/lib/gitlab/ci/status/manual.rb index 92c449e2c63..cb587a7815e 100644 --- a/lib/gitlab/ci/status/manual.rb +++ b/lib/gitlab/ci/status/manual.rb @@ -19,7 +19,12 @@ module Gitlab end def illustration - 'manual_action' + { + image: 'illustrations/manual_action.svg', + size: 'svg-394', + title: _('This job requires a manual action'), + content: _('This job depends on a user to trigger its process. Often they are used to deploy code to production environments') + } end end end diff --git a/lib/gitlab/ci/status/pending.rb b/lib/gitlab/ci/status/pending.rb index 63c0b5b501f..6a27a83696a 100644 --- a/lib/gitlab/ci/status/pending.rb +++ b/lib/gitlab/ci/status/pending.rb @@ -19,7 +19,12 @@ module Gitlab end def illustration - 'pending_job_empty' + { + image: 'illustrations/pending_job_empty.svg', + size: 'svg-430', + title: _('This job has not started yet'), + content: _('This job is in pending state and is waiting to be picked by a runner') + } end end end diff --git a/lib/gitlab/ci/status/skipped.rb b/lib/gitlab/ci/status/skipped.rb index 5dbe2847344..ff7529b5f03 100644 --- a/lib/gitlab/ci/status/skipped.rb +++ b/lib/gitlab/ci/status/skipped.rb @@ -19,7 +19,11 @@ module Gitlab end def illustration - 'skipped-job_empty' + { + image: 'illustrations/skipped-job_empty.svg', + size: 'svg-430', + title: _('This job has been skipped') + } end end end diff --git a/spec/lib/gitlab/ci/status/build/factory_spec.rb b/spec/lib/gitlab/ci/status/build/factory_spec.rb index 04b718c5897..0c9a751561f 100644 --- a/spec/lib/gitlab/ci/status/build/factory_spec.rb +++ b/spec/lib/gitlab/ci/status/build/factory_spec.rb @@ -115,7 +115,7 @@ describe Gitlab::Ci::Status::Build::Factory do expect(status.text).to eq 'canceled' expect(status.icon).to eq 'status_canceled' expect(status.favicon).to eq 'favicon_status_canceled' - expect(status.illustration).to eq 'canceled-job_empty' + expect(status.illustration).to include(:image, :size, :title) expect(status.label).to eq 'canceled' expect(status).to have_details expect(status).to have_action @@ -168,7 +168,7 @@ describe Gitlab::Ci::Status::Build::Factory do expect(status.text).to eq 'pending' expect(status.icon).to eq 'status_pending' expect(status.favicon).to eq 'favicon_status_pending' - expect(status.illustration).to eq 'pending_job_empty' + expect(status.illustration).to include(:image, :size, :title, :content) expect(status.label).to eq 'pending' expect(status).to have_details expect(status).to have_action @@ -194,7 +194,7 @@ describe Gitlab::Ci::Status::Build::Factory do expect(status.text).to eq 'skipped' expect(status.icon).to eq 'status_skipped' expect(status.favicon).to eq 'favicon_status_skipped' - expect(status.illustration).to eq 'skipped-job_empty' + expect(status.illustration).to include(:image, :size, :title) expect(status.label).to eq 'skipped' expect(status).to have_details expect(status).not_to have_action @@ -224,7 +224,7 @@ describe Gitlab::Ci::Status::Build::Factory do expect(status.group).to eq 'manual' expect(status.icon).to eq 'status_manual' expect(status.favicon).to eq 'favicon_status_manual' - expect(status.illustration).to eq 'manual_action' + expect(status.illustration).to include(:image, :size, :title, :content) expect(status.label).to include 'manual play action' expect(status).to have_details expect(status.action_path).to include 'play' diff --git a/spec/lib/gitlab/ci/status/canceled_spec.rb b/spec/lib/gitlab/ci/status/canceled_spec.rb index fc1d9e726ab..70cf2c1d300 100644 --- a/spec/lib/gitlab/ci/status/canceled_spec.rb +++ b/spec/lib/gitlab/ci/status/canceled_spec.rb @@ -22,7 +22,7 @@ describe Gitlab::Ci::Status::Canceled do end describe '#illustration' do - it { expect(subject.illustration).to eq 'canceled-job_empty' } + it { expect(subject.illustration).to include(:image, :size, :title) } end describe '#group' do diff --git a/spec/lib/gitlab/ci/status/created_spec.rb b/spec/lib/gitlab/ci/status/created_spec.rb index f7e3b0d8f1a..8a7771e0dc8 100644 --- a/spec/lib/gitlab/ci/status/created_spec.rb +++ b/spec/lib/gitlab/ci/status/created_spec.rb @@ -22,7 +22,7 @@ describe Gitlab::Ci::Status::Created do end describe '#illustration' do - it { expect(subject.illustration).to eq 'job_not_triggered' } + it { expect(subject.illustration).to include(:image, :size, :title, :content) } end describe '#group' do diff --git a/spec/lib/gitlab/ci/status/manual_spec.rb b/spec/lib/gitlab/ci/status/manual_spec.rb index 161c4774ff3..9b2dffe53d0 100644 --- a/spec/lib/gitlab/ci/status/manual_spec.rb +++ b/spec/lib/gitlab/ci/status/manual_spec.rb @@ -22,7 +22,7 @@ describe Gitlab::Ci::Status::Manual do end describe '#illustration' do - it { expect(subject.illustration).to eq 'manual_action' } + it { expect(subject.illustration).to include(:image, :size, :title, :content) } end describe '#group' do diff --git a/spec/lib/gitlab/ci/status/pending_spec.rb b/spec/lib/gitlab/ci/status/pending_spec.rb index 92349308842..d859371df9d 100644 --- a/spec/lib/gitlab/ci/status/pending_spec.rb +++ b/spec/lib/gitlab/ci/status/pending_spec.rb @@ -22,7 +22,7 @@ describe Gitlab::Ci::Status::Pending do end describe '#illustration' do - it { expect(subject.illustration).to eq 'pending_job_empty' } + it { expect(subject.illustration).to include(:image, :size, :title, :content) } end describe '#group' do diff --git a/spec/lib/gitlab/ci/status/skipped_spec.rb b/spec/lib/gitlab/ci/status/skipped_spec.rb index 993490c6d4e..f7fa8a035f2 100644 --- a/spec/lib/gitlab/ci/status/skipped_spec.rb +++ b/spec/lib/gitlab/ci/status/skipped_spec.rb @@ -22,7 +22,7 @@ describe Gitlab::Ci::Status::Skipped do end describe '#illustration' do - it { expect(subject.illustration).to eq 'skipped-job_empty' } + it { expect(subject.illustration).to include(:image, :size, :title) } end describe '#group' do -- cgit v1.2.3 From 4b0cbf630629cf1db5285baa0880513e4dd5ca16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20=C4=8Cupi=C4=87?= Date: Mon, 26 Mar 2018 20:23:11 +0200 Subject: Set up traces in jobs feature spec --- spec/features/projects/jobs_spec.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/spec/features/projects/jobs_spec.rb b/spec/features/projects/jobs_spec.rb index aa4c2757a25..d1cee58fce5 100644 --- a/spec/features/projects/jobs_spec.rb +++ b/spec/features/projects/jobs_spec.rb @@ -113,7 +113,7 @@ feature 'Jobs' do describe "GET /:project/jobs/:id" do context "Job from project" do - let(:job) { create(:ci_build, :success, pipeline: pipeline) } + let(:job) { create(:ci_build, :success, :trace_live, pipeline: pipeline) } before do visit project_job_path(project, job) @@ -136,7 +136,7 @@ feature 'Jobs' do end context 'when job is not running', :js do - let(:job) { create(:ci_build, :success, pipeline: pipeline) } + let(:job) { create(:ci_build, :success, :trace_artifact, pipeline: pipeline) } before do visit project_job_path(project, job) @@ -153,7 +153,7 @@ feature 'Jobs' do end context 'if job failed' do - let(:job) { create(:ci_build, :failed, pipeline: pipeline) } + let(:job) { create(:ci_build, :failed, :trace_artifact, pipeline: pipeline) } before do visit project_job_path(project, job) @@ -339,7 +339,7 @@ feature 'Jobs' do context 'job is successfull and has deployment' do let(:deployment) { create(:deployment) } - let(:job) { create(:ci_build, :success, environment: environment.name, deployments: [deployment], pipeline: pipeline) } + let(:job) { create(:ci_build, :success, :trace_artifact, environment: environment.name, deployments: [deployment], pipeline: pipeline) } it 'shows a link for the job' do visit project_job_path(project, job) @@ -349,7 +349,7 @@ feature 'Jobs' do end context 'job is complete and not successful' do - let(:job) { create(:ci_build, :failed, environment: environment.name, pipeline: pipeline) } + let(:job) { create(:ci_build, :failed, :trace_artifact, environment: environment.name, pipeline: pipeline) } it 'shows a link for the job' do visit project_job_path(project, job) @@ -360,7 +360,7 @@ feature 'Jobs' do context 'job creates a new deployment' do let!(:deployment) { create(:deployment, environment: environment, sha: project.commit.id) } - let(:job) { create(:ci_build, :success, environment: environment.name, pipeline: pipeline) } + let(:job) { create(:ci_build, :success, :trace_artifact, environment: environment.name, pipeline: pipeline) } it 'shows a link to latest deployment' do visit project_job_path(project, job) -- cgit v1.2.3 From 6df1eb14fa02268f16b961d15fc43b7b03586778 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20=C4=8Cupi=C4=87?= Date: Mon, 26 Mar 2018 20:47:06 +0200 Subject: Use Gitlab::Ci::Status#illustration in job empty_states partial --- app/views/projects/jobs/_empty_states.html.haml | 38 ++++++------------------- spec/features/projects/jobs_spec.rb | 18 ++++++++++++ 2 files changed, 27 insertions(+), 29 deletions(-) diff --git a/app/views/projects/jobs/_empty_states.html.haml b/app/views/projects/jobs/_empty_states.html.haml index 9e144dbfe32..6d4a9931923 100644 --- a/app/views/projects/jobs/_empty_states.html.haml +++ b/app/views/projects/jobs/_empty_states.html.haml @@ -1,29 +1,9 @@ -- if @build.playable? - = render 'empty_state', - illustration: 'illustrations/manual_action.svg', - illustration_size: 'svg-394', - title: _('This job requires a manual action'), - content: _('This job depends on a user to trigger its process. Often they are used to deploy code to production environments'), - action: ( link_to _('Trigger this manual action'), play_project_job_path(@project, @build), method: :post, class: 'btn btn-primary', title: _('Trigger this manual action') ) -- elsif @build.created? - = render 'empty_state', - illustration: 'illustrations/job_not_triggered.svg', - illustration_size: 'svg-306', - title: _('This job has not been triggered yet'), - content: _('This job depends on upstream jobs that need to succeed in order for this job to be triggered') -- elsif @build.canceled? - = render 'empty_state', - illustration: 'illustrations/canceled-job_empty.svg', - illustration_size: 'svg-430', - title: _('This job has been canceled') -- elsif @build.skipped? - = render 'empty_state', - illustration: 'illustrations/skipped-job_empty.svg', - illustration_size: 'svg-430', - title: _('This job has been skipped') -- else - = render 'empty_state', - illustration: 'illustrations/pending_job_empty.svg', - illustration_size: 'svg-430', - title: _('This job has not started yet'), - content: _('This job is in pending state and is waiting to be picked by a runner') +- detailed_status = @build.detailed_status(current_user) +- illustration = detailed_status.illustration + += render 'empty_state', + illustration: illustration[:image], + illustration_size: illustration[:size], + title: illustration[:title], + content: illustration[:content], + action: @build.playable? ? link_to(_("Trigger this manual action"), detailed_status.action_path, method: detailed_status.action_method, class: 'btn btn-primary', title: _("Trigger this manual action")) : nil diff --git a/spec/features/projects/jobs_spec.rb b/spec/features/projects/jobs_spec.rb index d1cee58fce5..749a1b81872 100644 --- a/spec/features/projects/jobs_spec.rb +++ b/spec/features/projects/jobs_spec.rb @@ -379,6 +379,7 @@ feature 'Jobs' do end it 'shows manual action empty state' do + expect(page).to have_content(job.detailed_status(user).illustration[:title]) expect(page).to have_content('This job requires a manual action') expect(page).to have_content('This job depends on a user to trigger its process. Often they are used to deploy code to production environments') expect(page).to have_link('Trigger this manual action') @@ -402,6 +403,7 @@ feature 'Jobs' do end it 'shows empty state' do + expect(page).to have_content(job.detailed_status(user).illustration[:title]) expect(page).to have_content('This job has not been triggered yet') expect(page).to have_content('This job depends on upstream jobs that need to succeed in order for this job to be triggered') end @@ -415,6 +417,7 @@ feature 'Jobs' do end it 'shows pending empty state' do + expect(page).to have_content(job.detailed_status(user).illustration[:title]) expect(page).to have_content('This job has not started yet') expect(page).to have_content('This job is in pending state and is waiting to be picked by a runner') end @@ -441,11 +444,26 @@ feature 'Jobs' do end it 'renders empty state' do + expect(page).to have_content(job.detailed_status(user).illustration[:title]) expect(page).not_to have_selector('.js-build-output') expect(page).to have_content('This job has been canceled') end end end + + context 'Skipped job' do + let(:job) { create(:ci_build, :skipped, pipeline: pipeline) } + + before do + visit project_job_path(project, job) + end + + it 'renders empty state' do + expect(page).to have_content(job.detailed_status(user).illustration[:title]) + expect(page).not_to have_selector('.js-build-output') + expect(page).to have_content('This job has been skipped') + end + end end describe "POST /:project/jobs/:id/cancel", :js do -- cgit v1.2.3 From 0969f198496c2ab0b4be6dcd0d9c6434f71e780d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20=C4=8Cupi=C4=87?= Date: Wed, 28 Mar 2018 13:31:53 +0200 Subject: Move illustration to build specific statuses --- lib/gitlab/ci/status/build/action.rb | 9 +++++++++ lib/gitlab/ci/status/build/canceled.rb | 21 +++++++++++++++++++++ lib/gitlab/ci/status/build/created.rb | 22 ++++++++++++++++++++++ lib/gitlab/ci/status/build/factory.rb | 7 ++++++- lib/gitlab/ci/status/build/pending.rb | 22 ++++++++++++++++++++++ lib/gitlab/ci/status/build/skipped.rb | 21 +++++++++++++++++++++ lib/gitlab/ci/status/canceled.rb | 8 -------- lib/gitlab/ci/status/created.rb | 9 --------- lib/gitlab/ci/status/manual.rb | 9 --------- lib/gitlab/ci/status/pending.rb | 9 --------- lib/gitlab/ci/status/skipped.rb | 8 -------- 11 files changed, 101 insertions(+), 44 deletions(-) create mode 100644 lib/gitlab/ci/status/build/canceled.rb create mode 100644 lib/gitlab/ci/status/build/created.rb create mode 100644 lib/gitlab/ci/status/build/pending.rb create mode 100644 lib/gitlab/ci/status/build/skipped.rb diff --git a/lib/gitlab/ci/status/build/action.rb b/lib/gitlab/ci/status/build/action.rb index 6c9125647ad..17eb37448cb 100644 --- a/lib/gitlab/ci/status/build/action.rb +++ b/lib/gitlab/ci/status/build/action.rb @@ -14,6 +14,15 @@ module Gitlab end end + def illustration + { + image: 'illustrations/manual_action.svg', + size: 'svg-394', + title: _('This job requires a manual action'), + content: _('This job depends on a user to trigger its process. Often they are used to deploy code to production environments'), + } + end + def self.matches?(build, user) build.playable? end diff --git a/lib/gitlab/ci/status/build/canceled.rb b/lib/gitlab/ci/status/build/canceled.rb new file mode 100644 index 00000000000..c83e2734a73 --- /dev/null +++ b/lib/gitlab/ci/status/build/canceled.rb @@ -0,0 +1,21 @@ +module Gitlab + module Ci + module Status + module Build + class Canceled < Status::Extended + def illustration + { + image: 'illustrations/canceled-job_empty.svg', + size: 'svg-430', + title: _('This job has been canceled') + } + end + + def self.matches?(build, user) + build.canceled? + end + end + end + end + end +end diff --git a/lib/gitlab/ci/status/build/created.rb b/lib/gitlab/ci/status/build/created.rb new file mode 100644 index 00000000000..5be8e9de425 --- /dev/null +++ b/lib/gitlab/ci/status/build/created.rb @@ -0,0 +1,22 @@ +module Gitlab + module Ci + module Status + module Build + class Created < Status::Extended + def illustration + { + image: 'illustrations/job_not_triggered.svg', + size: 'svg-306', + title: _('This job has not been triggered yet'), + content: _('This job depends on upstream jobs that need to succeed in order for this job to be triggered') + } + end + + def self.matches?(build, user) + build.created? + end + end + end + end + end +end diff --git a/lib/gitlab/ci/status/build/factory.rb b/lib/gitlab/ci/status/build/factory.rb index c852d607373..ae4b2bd79bc 100644 --- a/lib/gitlab/ci/status/build/factory.rb +++ b/lib/gitlab/ci/status/build/factory.rb @@ -9,7 +9,12 @@ module Gitlab [Status::Build::FailedAllowed, Status::Build::Play, Status::Build::Stop], - [Status::Build::Action]] + [Status::Build::Action], + [Status::Build::Action, + Status::Build::Canceled, + Status::Build::Created, + Status::Build::Pending, + Status::Build::Skipped]] end def self.common_helpers diff --git a/lib/gitlab/ci/status/build/pending.rb b/lib/gitlab/ci/status/build/pending.rb new file mode 100644 index 00000000000..9dd9a27ad57 --- /dev/null +++ b/lib/gitlab/ci/status/build/pending.rb @@ -0,0 +1,22 @@ +module Gitlab + module Ci + module Status + module Build + class Pending < Status::Extended + def illustration + { + image: 'illustrations/pending_job_empty.svg', + size: 'svg-430', + title: _('This job has not started yet'), + content: _('This job is in pending state and is waiting to be picked by a runner') + } + end + + def self.matches?(build, user) + build.pending? + end + end + end + end + end +end diff --git a/lib/gitlab/ci/status/build/skipped.rb b/lib/gitlab/ci/status/build/skipped.rb new file mode 100644 index 00000000000..3e678d0baee --- /dev/null +++ b/lib/gitlab/ci/status/build/skipped.rb @@ -0,0 +1,21 @@ +module Gitlab + module Ci + module Status + module Build + class Skipped < Status::Extended + def illustration + { + image: 'illustrations/skipped-job_empty.svg', + size: 'svg-430', + title: _('This job has been skipped') + } + end + + def self.matches?(build, user) + build.skipped? + end + end + end + end + end +end diff --git a/lib/gitlab/ci/status/canceled.rb b/lib/gitlab/ci/status/canceled.rb index bea8dcd5587..e6195a60d4f 100644 --- a/lib/gitlab/ci/status/canceled.rb +++ b/lib/gitlab/ci/status/canceled.rb @@ -17,14 +17,6 @@ module Gitlab def favicon 'favicon_status_canceled' end - - def illustration - { - image: 'illustrations/canceled-job_empty.svg', - size: 'svg-430', - title: _('This job has been canceled') - } - end end end end diff --git a/lib/gitlab/ci/status/created.rb b/lib/gitlab/ci/status/created.rb index 3b2a9e5d0ef..846f00b83dd 100644 --- a/lib/gitlab/ci/status/created.rb +++ b/lib/gitlab/ci/status/created.rb @@ -17,15 +17,6 @@ module Gitlab def favicon 'favicon_status_created' end - - def illustration - { - image: 'illustrations/job_not_triggered.svg', - size: 'svg-306', - title: _('This job has not been triggered yet'), - content: _('This job depends on upstream jobs that need to succeed in order for this job to be triggered') - } - end end end end diff --git a/lib/gitlab/ci/status/manual.rb b/lib/gitlab/ci/status/manual.rb index cb587a7815e..fc387e2fd25 100644 --- a/lib/gitlab/ci/status/manual.rb +++ b/lib/gitlab/ci/status/manual.rb @@ -17,15 +17,6 @@ module Gitlab def favicon 'favicon_status_manual' end - - def illustration - { - image: 'illustrations/manual_action.svg', - size: 'svg-394', - title: _('This job requires a manual action'), - content: _('This job depends on a user to trigger its process. Often they are used to deploy code to production environments') - } - end end end end diff --git a/lib/gitlab/ci/status/pending.rb b/lib/gitlab/ci/status/pending.rb index 6a27a83696a..6780780db32 100644 --- a/lib/gitlab/ci/status/pending.rb +++ b/lib/gitlab/ci/status/pending.rb @@ -17,15 +17,6 @@ module Gitlab def favicon 'favicon_status_pending' end - - def illustration - { - image: 'illustrations/pending_job_empty.svg', - size: 'svg-430', - title: _('This job has not started yet'), - content: _('This job is in pending state and is waiting to be picked by a runner') - } - end end end end diff --git a/lib/gitlab/ci/status/skipped.rb b/lib/gitlab/ci/status/skipped.rb index ff7529b5f03..0dbdc4de426 100644 --- a/lib/gitlab/ci/status/skipped.rb +++ b/lib/gitlab/ci/status/skipped.rb @@ -17,14 +17,6 @@ module Gitlab def favicon 'favicon_status_skipped' end - - def illustration - { - image: 'illustrations/skipped-job_empty.svg', - size: 'svg-430', - title: _('This job has been skipped') - } - end end end end -- cgit v1.2.3 From c48f33c5bec02e8fd49326514023f6b6af66d693 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20=C4=8Cupi=C4=87?= Date: Wed, 28 Mar 2018 13:51:30 +0200 Subject: Move action link to build extended status illustration --- app/views/projects/jobs/_empty_states.html.haml | 2 +- lib/gitlab/ci/status/build/action.rb | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/app/views/projects/jobs/_empty_states.html.haml b/app/views/projects/jobs/_empty_states.html.haml index 6d4a9931923..4d2c776e538 100644 --- a/app/views/projects/jobs/_empty_states.html.haml +++ b/app/views/projects/jobs/_empty_states.html.haml @@ -6,4 +6,4 @@ illustration_size: illustration[:size], title: illustration[:title], content: illustration[:content], - action: @build.playable? ? link_to(_("Trigger this manual action"), detailed_status.action_path, method: detailed_status.action_method, class: 'btn btn-primary', title: _("Trigger this manual action")) : nil + action: illustration[:action_path] ? link_to(_("Trigger this manual action"), illustration[:action_path], method: illustration[:action_method], class: 'btn btn-primary', title: _("Trigger this manual action")) : nil diff --git a/lib/gitlab/ci/status/build/action.rb b/lib/gitlab/ci/status/build/action.rb index 17eb37448cb..f7f3d47c098 100644 --- a/lib/gitlab/ci/status/build/action.rb +++ b/lib/gitlab/ci/status/build/action.rb @@ -20,6 +20,8 @@ module Gitlab size: 'svg-394', title: _('This job requires a manual action'), content: _('This job depends on a user to trigger its process. Often they are used to deploy code to production environments'), + action_path: action_path, + action_method: action_method } end -- cgit v1.2.3 From b57fcbe6162a17b02fc0516af2487ddd57c251bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20=C4=8Cupi=C4=87?= Date: Wed, 28 Mar 2018 14:57:09 +0200 Subject: Separate the manual empty state from the action empty state --- lib/gitlab/ci/status/build/action.rb | 11 ----------- lib/gitlab/ci/status/build/factory.rb | 2 +- lib/gitlab/ci/status/build/manual.rb | 24 ++++++++++++++++++++++++ 3 files changed, 25 insertions(+), 12 deletions(-) create mode 100644 lib/gitlab/ci/status/build/manual.rb diff --git a/lib/gitlab/ci/status/build/action.rb b/lib/gitlab/ci/status/build/action.rb index f7f3d47c098..6c9125647ad 100644 --- a/lib/gitlab/ci/status/build/action.rb +++ b/lib/gitlab/ci/status/build/action.rb @@ -14,17 +14,6 @@ module Gitlab end end - def illustration - { - image: 'illustrations/manual_action.svg', - size: 'svg-394', - title: _('This job requires a manual action'), - content: _('This job depends on a user to trigger its process. Often they are used to deploy code to production environments'), - action_path: action_path, - action_method: action_method - } - end - def self.matches?(build, user) build.playable? end diff --git a/lib/gitlab/ci/status/build/factory.rb b/lib/gitlab/ci/status/build/factory.rb index ae4b2bd79bc..004a9b305b7 100644 --- a/lib/gitlab/ci/status/build/factory.rb +++ b/lib/gitlab/ci/status/build/factory.rb @@ -10,7 +10,7 @@ module Gitlab Status::Build::Play, Status::Build::Stop], [Status::Build::Action], - [Status::Build::Action, + [Status::Build::Manual, Status::Build::Canceled, Status::Build::Created, Status::Build::Pending, diff --git a/lib/gitlab/ci/status/build/manual.rb b/lib/gitlab/ci/status/build/manual.rb new file mode 100644 index 00000000000..01e94e159a1 --- /dev/null +++ b/lib/gitlab/ci/status/build/manual.rb @@ -0,0 +1,24 @@ +module Gitlab + module Ci + module Status + module Build + class Manual < Status::Extended + def illustration + { + image: 'illustrations/manual_action.svg', + size: 'svg-394', + title: _('This job requires a manual action'), + content: _('This job depends on a user to trigger its process. Often they are used to deploy code to production environments'), + action_path: play_project_job_path(subject.project, subject), + action_method: :post + } + end + + def self.matches?(build, user) + build.playable? + end + end + end + end + end +end -- cgit v1.2.3 From d6509274f32fce8b879051d19e4c9d2bb8f9d09e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20=C4=8Cupi=C4=87?= Date: Wed, 28 Mar 2018 14:58:32 +0200 Subject: Fix tests for build empty state statuses --- spec/lib/gitlab/ci/status/build/canceled_spec.rb | 11 +++++++++++ spec/lib/gitlab/ci/status/build/created_spec.rb | 11 +++++++++++ spec/lib/gitlab/ci/status/build/manual_spec.rb | 13 +++++++++++++ spec/lib/gitlab/ci/status/build/pending_spec.rb | 11 +++++++++++ spec/lib/gitlab/ci/status/build/skipped_spec.rb | 11 +++++++++++ spec/lib/gitlab/ci/status/canceled_spec.rb | 4 ---- spec/lib/gitlab/ci/status/created_spec.rb | 4 ---- spec/lib/gitlab/ci/status/manual_spec.rb | 4 ---- spec/lib/gitlab/ci/status/pending_spec.rb | 4 ---- spec/lib/gitlab/ci/status/skipped_spec.rb | 4 ---- 10 files changed, 57 insertions(+), 20 deletions(-) create mode 100644 spec/lib/gitlab/ci/status/build/canceled_spec.rb create mode 100644 spec/lib/gitlab/ci/status/build/created_spec.rb create mode 100644 spec/lib/gitlab/ci/status/build/manual_spec.rb create mode 100644 spec/lib/gitlab/ci/status/build/pending_spec.rb create mode 100644 spec/lib/gitlab/ci/status/build/skipped_spec.rb diff --git a/spec/lib/gitlab/ci/status/build/canceled_spec.rb b/spec/lib/gitlab/ci/status/build/canceled_spec.rb new file mode 100644 index 00000000000..689b4237b6e --- /dev/null +++ b/spec/lib/gitlab/ci/status/build/canceled_spec.rb @@ -0,0 +1,11 @@ +require 'spec_helper' + +describe Gitlab::Ci::Status::Build::Canceled do + subject do + described_class.new(double('subject')) + end + + describe '#illustration' do + it { expect(subject.illustration).to include(:image, :size, :title) } + end +end diff --git a/spec/lib/gitlab/ci/status/build/created_spec.rb b/spec/lib/gitlab/ci/status/build/created_spec.rb new file mode 100644 index 00000000000..ace553c67a1 --- /dev/null +++ b/spec/lib/gitlab/ci/status/build/created_spec.rb @@ -0,0 +1,11 @@ +require 'spec_helper' + +describe Gitlab::Ci::Status::Build::Created do + subject do + described_class.new(double('subject')) + end + + describe '#illustration' do + it { expect(subject.illustration).to include(:image, :size, :title, :content) } + end +end diff --git a/spec/lib/gitlab/ci/status/build/manual_spec.rb b/spec/lib/gitlab/ci/status/build/manual_spec.rb new file mode 100644 index 00000000000..1cbbbfa7570 --- /dev/null +++ b/spec/lib/gitlab/ci/status/build/manual_spec.rb @@ -0,0 +1,13 @@ +require 'spec_helper' + +describe Gitlab::Ci::Status::Build::Manual do + subject do + user = create(:user) + build = create(:ci_build, :manual) + described_class.new(Gitlab::Ci::Status::Core.new(build, user)) + end + + describe '#illustration' do + it { expect(subject.illustration).to include(:image, :size, :title, :content, :action_path, :action_method) } + end +end diff --git a/spec/lib/gitlab/ci/status/build/pending_spec.rb b/spec/lib/gitlab/ci/status/build/pending_spec.rb new file mode 100644 index 00000000000..2c114313536 --- /dev/null +++ b/spec/lib/gitlab/ci/status/build/pending_spec.rb @@ -0,0 +1,11 @@ +require 'spec_helper' + +describe Gitlab::Ci::Status::Build::Pending do + subject do + described_class.new(double('subject')) + end + + describe '#illustration' do + it { expect(subject.illustration).to include(:image, :size, :title, :content) } + end +end diff --git a/spec/lib/gitlab/ci/status/build/skipped_spec.rb b/spec/lib/gitlab/ci/status/build/skipped_spec.rb new file mode 100644 index 00000000000..4667d10e6f6 --- /dev/null +++ b/spec/lib/gitlab/ci/status/build/skipped_spec.rb @@ -0,0 +1,11 @@ +require 'spec_helper' + +describe Gitlab::Ci::Status::Build::Skipped do + subject do + described_class.new(double('subject')) + end + + describe '#illustration' do + it { expect(subject.illustration).to include(:image, :size, :title) } + end +end diff --git a/spec/lib/gitlab/ci/status/canceled_spec.rb b/spec/lib/gitlab/ci/status/canceled_spec.rb index 70cf2c1d300..dc74d7e28c5 100644 --- a/spec/lib/gitlab/ci/status/canceled_spec.rb +++ b/spec/lib/gitlab/ci/status/canceled_spec.rb @@ -21,10 +21,6 @@ describe Gitlab::Ci::Status::Canceled do it { expect(subject.favicon).to eq 'favicon_status_canceled' } end - describe '#illustration' do - it { expect(subject.illustration).to include(:image, :size, :title) } - end - describe '#group' do it { expect(subject.group).to eq 'canceled' } end diff --git a/spec/lib/gitlab/ci/status/created_spec.rb b/spec/lib/gitlab/ci/status/created_spec.rb index 8a7771e0dc8..ce4333f2aca 100644 --- a/spec/lib/gitlab/ci/status/created_spec.rb +++ b/spec/lib/gitlab/ci/status/created_spec.rb @@ -21,10 +21,6 @@ describe Gitlab::Ci::Status::Created do it { expect(subject.favicon).to eq 'favicon_status_created' } end - describe '#illustration' do - it { expect(subject.illustration).to include(:image, :size, :title, :content) } - end - describe '#group' do it { expect(subject.group).to eq 'created' } end diff --git a/spec/lib/gitlab/ci/status/manual_spec.rb b/spec/lib/gitlab/ci/status/manual_spec.rb index 9b2dffe53d0..0463f2e1aff 100644 --- a/spec/lib/gitlab/ci/status/manual_spec.rb +++ b/spec/lib/gitlab/ci/status/manual_spec.rb @@ -21,10 +21,6 @@ describe Gitlab::Ci::Status::Manual do it { expect(subject.favicon).to eq 'favicon_status_manual' } end - describe '#illustration' do - it { expect(subject.illustration).to include(:image, :size, :title, :content) } - end - describe '#group' do it { expect(subject.group).to eq 'manual' } end diff --git a/spec/lib/gitlab/ci/status/pending_spec.rb b/spec/lib/gitlab/ci/status/pending_spec.rb index d859371df9d..0e25358dd8a 100644 --- a/spec/lib/gitlab/ci/status/pending_spec.rb +++ b/spec/lib/gitlab/ci/status/pending_spec.rb @@ -21,10 +21,6 @@ describe Gitlab::Ci::Status::Pending do it { expect(subject.favicon).to eq 'favicon_status_pending' } end - describe '#illustration' do - it { expect(subject.illustration).to include(:image, :size, :title, :content) } - end - describe '#group' do it { expect(subject.group).to eq 'pending' } end diff --git a/spec/lib/gitlab/ci/status/skipped_spec.rb b/spec/lib/gitlab/ci/status/skipped_spec.rb index f7fa8a035f2..63694ca0ea6 100644 --- a/spec/lib/gitlab/ci/status/skipped_spec.rb +++ b/spec/lib/gitlab/ci/status/skipped_spec.rb @@ -21,10 +21,6 @@ describe Gitlab::Ci::Status::Skipped do it { expect(subject.favicon).to eq 'favicon_status_skipped' } end - describe '#illustration' do - it { expect(subject.illustration).to include(:image, :size, :title) } - end - describe '#group' do it { expect(subject.group).to eq 'skipped' } end -- cgit v1.2.3 From bb0483dc2f9501461407766f74600e0f3d283686 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20=C4=8Cupi=C4=87?= Date: Wed, 28 Mar 2018 16:18:06 +0200 Subject: Move the empty state extended status to be the beginning --- lib/gitlab/ci/status/build/factory.rb | 14 +++++++------- spec/lib/gitlab/ci/status/build/factory_spec.rb | 18 ++++++++++-------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/lib/gitlab/ci/status/build/factory.rb b/lib/gitlab/ci/status/build/factory.rb index 004a9b305b7..b809a9cf766 100644 --- a/lib/gitlab/ci/status/build/factory.rb +++ b/lib/gitlab/ci/status/build/factory.rb @@ -4,17 +4,17 @@ module Gitlab module Build class Factory < Status::Factory def self.extended_statuses - [[Status::Build::Cancelable, + [[Status::Build::Manual, + Status::Build::Canceled, + Status::Build::Created, + Status::Build::Pending, + Status::Build::Skipped], + [Status::Build::Cancelable, Status::Build::Retryable], [Status::Build::FailedAllowed, Status::Build::Play, Status::Build::Stop], - [Status::Build::Action], - [Status::Build::Manual, - Status::Build::Canceled, - Status::Build::Created, - Status::Build::Pending, - Status::Build::Skipped]] + [Status::Build::Action]] end def self.common_helpers diff --git a/spec/lib/gitlab/ci/status/build/factory_spec.rb b/spec/lib/gitlab/ci/status/build/factory_spec.rb index 0c9a751561f..a68fed0a41c 100644 --- a/spec/lib/gitlab/ci/status/build/factory_spec.rb +++ b/spec/lib/gitlab/ci/status/build/factory_spec.rb @@ -104,7 +104,7 @@ describe Gitlab::Ci::Status::Build::Factory do it 'matches correct extended statuses' do expect(factory.extended_statuses) - .to eq [Gitlab::Ci::Status::Build::Retryable] + .to eq [Gitlab::Ci::Status::Build::Canceled, Gitlab::Ci::Status::Build::Retryable] end it 'fabricates a retryable build status' do @@ -157,7 +157,7 @@ describe Gitlab::Ci::Status::Build::Factory do it 'matches correct extended statuses' do expect(factory.extended_statuses) - .to eq [Gitlab::Ci::Status::Build::Cancelable] + .to eq [Gitlab::Ci::Status::Build::Pending, Gitlab::Ci::Status::Build::Cancelable] end it 'fabricates a cancelable build status' do @@ -182,12 +182,12 @@ describe Gitlab::Ci::Status::Build::Factory do expect(factory.core_status).to be_a Gitlab::Ci::Status::Skipped end - it 'does not match extended statuses' do - expect(factory.extended_statuses).to be_empty + it 'matches correct extended statuses' do + expect(factory.extended_statuses).to eq [Gitlab::Ci::Status::Build::Skipped] end - it 'fabricates a core skipped status' do - expect(status).to be_a Gitlab::Ci::Status::Skipped + it 'fabricates a skipped build status' do + expect(status).to be_a Gitlab::Ci::Status::Build::Skipped end it 'fabricates status with correct details' do @@ -211,7 +211,8 @@ describe Gitlab::Ci::Status::Build::Factory do it 'matches correct extended statuses' do expect(factory.extended_statuses) - .to eq [Gitlab::Ci::Status::Build::Play, + .to eq [Gitlab::Ci::Status::Build::Manual, + Gitlab::Ci::Status::Build::Play, Gitlab::Ci::Status::Build::Action] end @@ -259,7 +260,8 @@ describe Gitlab::Ci::Status::Build::Factory do it 'matches correct extended statuses' do expect(factory.extended_statuses) - .to eq [Gitlab::Ci::Status::Build::Stop, + .to eq [Gitlab::Ci::Status::Build::Manual, + Gitlab::Ci::Status::Build::Stop, Gitlab::Ci::Status::Build::Action] end -- cgit v1.2.3 From ddabac46b918611ecaa82ea5af554a7f0f9b7407 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20=C4=8Cupi=C4=87?= Date: Thu, 29 Mar 2018 19:24:19 +0200 Subject: Move action button titles to respective statuses --- app/views/projects/jobs/_empty_states.html.haml | 2 +- lib/gitlab/ci/status/build/cancelable.rb | 4 ++++ lib/gitlab/ci/status/build/manual.rb | 4 +--- lib/gitlab/ci/status/build/play.rb | 4 ++++ lib/gitlab/ci/status/build/retryable.rb | 4 ++++ lib/gitlab/ci/status/build/stop.rb | 4 ++++ spec/lib/gitlab/ci/status/build/cancelable_spec.rb | 4 ++++ spec/lib/gitlab/ci/status/build/manual_spec.rb | 2 +- spec/lib/gitlab/ci/status/build/play_spec.rb | 4 ++++ spec/lib/gitlab/ci/status/build/retryable_spec.rb | 4 ++++ spec/lib/gitlab/ci/status/build/stop_spec.rb | 4 ++++ 11 files changed, 35 insertions(+), 5 deletions(-) diff --git a/app/views/projects/jobs/_empty_states.html.haml b/app/views/projects/jobs/_empty_states.html.haml index 4d2c776e538..e5198d047df 100644 --- a/app/views/projects/jobs/_empty_states.html.haml +++ b/app/views/projects/jobs/_empty_states.html.haml @@ -6,4 +6,4 @@ illustration_size: illustration[:size], title: illustration[:title], content: illustration[:content], - action: illustration[:action_path] ? link_to(_("Trigger this manual action"), illustration[:action_path], method: illustration[:action_method], class: 'btn btn-primary', title: _("Trigger this manual action")) : nil + action: detailed_status.has_action? ? link_to(detailed_status.action_button_title, detailed_status.action_path, method: detailed_status.action_method, class: 'btn btn-primary', title: detailed_status.action_button_title) : nil diff --git a/lib/gitlab/ci/status/build/cancelable.rb b/lib/gitlab/ci/status/build/cancelable.rb index 2d9166d6bdd..024047d4983 100644 --- a/lib/gitlab/ci/status/build/cancelable.rb +++ b/lib/gitlab/ci/status/build/cancelable.rb @@ -23,6 +23,10 @@ module Gitlab 'Cancel' end + def action_button_title + _('Cancel this job') + end + def self.matches?(build, user) build.cancelable? end diff --git a/lib/gitlab/ci/status/build/manual.rb b/lib/gitlab/ci/status/build/manual.rb index 01e94e159a1..042da6392d3 100644 --- a/lib/gitlab/ci/status/build/manual.rb +++ b/lib/gitlab/ci/status/build/manual.rb @@ -8,9 +8,7 @@ module Gitlab image: 'illustrations/manual_action.svg', size: 'svg-394', title: _('This job requires a manual action'), - content: _('This job depends on a user to trigger its process. Often they are used to deploy code to production environments'), - action_path: play_project_job_path(subject.project, subject), - action_method: :post + content: _('This job depends on a user to trigger its process. Often they are used to deploy code to production environments') } end diff --git a/lib/gitlab/ci/status/build/play.rb b/lib/gitlab/ci/status/build/play.rb index b7b45466d3b..a8b9ebf0803 100644 --- a/lib/gitlab/ci/status/build/play.rb +++ b/lib/gitlab/ci/status/build/play.rb @@ -19,6 +19,10 @@ module Gitlab 'Play' end + def action_button_title + _('Trigger this manual action') + end + def action_path play_project_job_path(subject.project, subject) end diff --git a/lib/gitlab/ci/status/build/retryable.rb b/lib/gitlab/ci/status/build/retryable.rb index 44ffe783e50..5aeb8e51480 100644 --- a/lib/gitlab/ci/status/build/retryable.rb +++ b/lib/gitlab/ci/status/build/retryable.rb @@ -15,6 +15,10 @@ module Gitlab 'Retry' end + def action_button_title + _('Retry this job') + end + def action_path retry_project_job_path(subject.project, subject) end diff --git a/lib/gitlab/ci/status/build/stop.rb b/lib/gitlab/ci/status/build/stop.rb index 46e730797e4..dea838bfa39 100644 --- a/lib/gitlab/ci/status/build/stop.rb +++ b/lib/gitlab/ci/status/build/stop.rb @@ -19,6 +19,10 @@ module Gitlab 'Stop' end + def action_button_title + _('Stop this environment') + end + def action_path play_project_job_path(subject.project, subject) end diff --git a/spec/lib/gitlab/ci/status/build/cancelable_spec.rb b/spec/lib/gitlab/ci/status/build/cancelable_spec.rb index 9cdebaa5cf2..0b88e0c7c9c 100644 --- a/spec/lib/gitlab/ci/status/build/cancelable_spec.rb +++ b/spec/lib/gitlab/ci/status/build/cancelable_spec.rb @@ -72,6 +72,10 @@ describe Gitlab::Ci::Status::Build::Cancelable do describe '#action_title' do it { expect(subject.action_title).to eq 'Cancel' } end + + describe '#action_button_title' do + it { expect(subject.action_button_title).to eq 'Cancel this job' } + end end describe '.matches?' do diff --git a/spec/lib/gitlab/ci/status/build/manual_spec.rb b/spec/lib/gitlab/ci/status/build/manual_spec.rb index 1cbbbfa7570..c8c650d4e56 100644 --- a/spec/lib/gitlab/ci/status/build/manual_spec.rb +++ b/spec/lib/gitlab/ci/status/build/manual_spec.rb @@ -8,6 +8,6 @@ describe Gitlab::Ci::Status::Build::Manual do end describe '#illustration' do - it { expect(subject.illustration).to include(:image, :size, :title, :content, :action_path, :action_method) } + it { expect(subject.illustration).to include(:image, :size, :title, :content) } end end diff --git a/spec/lib/gitlab/ci/status/build/play_spec.rb b/spec/lib/gitlab/ci/status/build/play_spec.rb index 81d5f553fd1..b0c3a8bb398 100644 --- a/spec/lib/gitlab/ci/status/build/play_spec.rb +++ b/spec/lib/gitlab/ci/status/build/play_spec.rb @@ -53,6 +53,10 @@ describe Gitlab::Ci::Status::Build::Play do it { expect(subject.action_title).to eq 'Play' } end + describe '#action_button_title' do + it { expect(subject.action_button_title).to eq 'Trigger this manual action' } + end + describe '.matches?' do subject { described_class.matches?(build, user) } diff --git a/spec/lib/gitlab/ci/status/build/retryable_spec.rb b/spec/lib/gitlab/ci/status/build/retryable_spec.rb index 14d42e0d70f..d6e909f6268 100644 --- a/spec/lib/gitlab/ci/status/build/retryable_spec.rb +++ b/spec/lib/gitlab/ci/status/build/retryable_spec.rb @@ -72,6 +72,10 @@ describe Gitlab::Ci::Status::Build::Retryable do describe '#action_title' do it { expect(subject.action_title).to eq 'Retry' } end + + describe '#action_button_title' do + it { expect(subject.action_button_title).to eq 'Retry this job' } + end end describe '.matches?' do diff --git a/spec/lib/gitlab/ci/status/build/stop_spec.rb b/spec/lib/gitlab/ci/status/build/stop_spec.rb index 18e250772f0..7a72ca2c14d 100644 --- a/spec/lib/gitlab/ci/status/build/stop_spec.rb +++ b/spec/lib/gitlab/ci/status/build/stop_spec.rb @@ -44,6 +44,10 @@ describe Gitlab::Ci::Status::Build::Stop do describe '#action_title' do it { expect(subject.action_title).to eq 'Stop' } end + + describe '#action_button_title' do + it { expect(subject.action_button_title).to eq 'Stop this environment' } + end end describe '.matches?' do -- cgit v1.2.3 From 3447d71e73a538dbcb30fb478474bdd526ff38a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20=C4=8Cupi=C4=87?= Date: Thu, 29 Mar 2018 19:39:30 +0200 Subject: Add specs for empty states .matches? methods --- spec/lib/gitlab/ci/status/build/canceled_spec.rb | 22 ++++++++++++++++++++++ spec/lib/gitlab/ci/status/build/created_spec.rb | 22 ++++++++++++++++++++++ spec/lib/gitlab/ci/status/build/manual_spec.rb | 23 ++++++++++++++++++++++- spec/lib/gitlab/ci/status/build/pending_spec.rb | 22 ++++++++++++++++++++++ spec/lib/gitlab/ci/status/build/skipped_spec.rb | 22 ++++++++++++++++++++++ 5 files changed, 110 insertions(+), 1 deletion(-) diff --git a/spec/lib/gitlab/ci/status/build/canceled_spec.rb b/spec/lib/gitlab/ci/status/build/canceled_spec.rb index 689b4237b6e..c6b5cc68770 100644 --- a/spec/lib/gitlab/ci/status/build/canceled_spec.rb +++ b/spec/lib/gitlab/ci/status/build/canceled_spec.rb @@ -1,6 +1,8 @@ require 'spec_helper' describe Gitlab::Ci::Status::Build::Canceled do + let(:user) { create(:user) } + subject do described_class.new(double('subject')) end @@ -8,4 +10,24 @@ describe Gitlab::Ci::Status::Build::Canceled do describe '#illustration' do it { expect(subject.illustration).to include(:image, :size, :title) } end + + describe '.matches?' do + subject {described_class.matches?(build, user) } + + context 'when build is canceled' do + let(:build) { create(:ci_build, :canceled) } + + it 'is a correct match' do + expect(subject).to be true + end + end + + context 'when build is not canceled' do + let(:build) { create(:ci_build) } + + it 'does not match' do + expect(subject).to be false + end + end + end end diff --git a/spec/lib/gitlab/ci/status/build/created_spec.rb b/spec/lib/gitlab/ci/status/build/created_spec.rb index ace553c67a1..8bdfe6ef7a2 100644 --- a/spec/lib/gitlab/ci/status/build/created_spec.rb +++ b/spec/lib/gitlab/ci/status/build/created_spec.rb @@ -1,6 +1,8 @@ require 'spec_helper' describe Gitlab::Ci::Status::Build::Created do + let(:user) { create(:user) } + subject do described_class.new(double('subject')) end @@ -8,4 +10,24 @@ describe Gitlab::Ci::Status::Build::Created do describe '#illustration' do it { expect(subject.illustration).to include(:image, :size, :title, :content) } end + + describe '.matches?' do + subject {described_class.matches?(build, user) } + + context 'when build is created' do + let(:build) { create(:ci_build, :created) } + + it 'is a correct match' do + expect(subject).to be true + end + end + + context 'when build is not created' do + let(:build) { create(:ci_build) } + + it 'does not match' do + expect(subject).to be false + end + end + end end diff --git a/spec/lib/gitlab/ci/status/build/manual_spec.rb b/spec/lib/gitlab/ci/status/build/manual_spec.rb index c8c650d4e56..6386296f992 100644 --- a/spec/lib/gitlab/ci/status/build/manual_spec.rb +++ b/spec/lib/gitlab/ci/status/build/manual_spec.rb @@ -1,8 +1,9 @@ require 'spec_helper' describe Gitlab::Ci::Status::Build::Manual do + let(:user) { create(:user) } + subject do - user = create(:user) build = create(:ci_build, :manual) described_class.new(Gitlab::Ci::Status::Core.new(build, user)) end @@ -10,4 +11,24 @@ describe Gitlab::Ci::Status::Build::Manual do describe '#illustration' do it { expect(subject.illustration).to include(:image, :size, :title, :content) } end + + describe '.matches?' do + subject {described_class.matches?(build, user) } + + context 'when build is manual' do + let(:build) { create(:ci_build, :manual) } + + it 'is a correct match' do + expect(subject).to be true + end + end + + context 'when build is not manual' do + let(:build) { create(:ci_build) } + + it 'does not match' do + expect(subject).to be false + end + end + end end diff --git a/spec/lib/gitlab/ci/status/build/pending_spec.rb b/spec/lib/gitlab/ci/status/build/pending_spec.rb index 2c114313536..4cf70828e53 100644 --- a/spec/lib/gitlab/ci/status/build/pending_spec.rb +++ b/spec/lib/gitlab/ci/status/build/pending_spec.rb @@ -1,6 +1,8 @@ require 'spec_helper' describe Gitlab::Ci::Status::Build::Pending do + let(:user) { create(:user) } + subject do described_class.new(double('subject')) end @@ -8,4 +10,24 @@ describe Gitlab::Ci::Status::Build::Pending do describe '#illustration' do it { expect(subject.illustration).to include(:image, :size, :title, :content) } end + + describe '.matches?' do + subject {described_class.matches?(build, user) } + + context 'when build is pending' do + let(:build) { create(:ci_build, :pending) } + + it 'is a correct match' do + expect(subject).to be true + end + end + + context 'when build is not pending' do + let(:build) { create(:ci_build, :success) } + + it 'does not match' do + expect(subject).to be false + end + end + end end diff --git a/spec/lib/gitlab/ci/status/build/skipped_spec.rb b/spec/lib/gitlab/ci/status/build/skipped_spec.rb index 4667d10e6f6..46f6933025a 100644 --- a/spec/lib/gitlab/ci/status/build/skipped_spec.rb +++ b/spec/lib/gitlab/ci/status/build/skipped_spec.rb @@ -1,6 +1,8 @@ require 'spec_helper' describe Gitlab::Ci::Status::Build::Skipped do + let(:user) { create(:user) } + subject do described_class.new(double('subject')) end @@ -8,4 +10,24 @@ describe Gitlab::Ci::Status::Build::Skipped do describe '#illustration' do it { expect(subject.illustration).to include(:image, :size, :title) } end + + describe '.matches?' do + subject {described_class.matches?(build, user) } + + context 'when build is skipped' do + let(:build) { create(:ci_build, :skipped) } + + it 'is a correct match' do + expect(subject).to be true + end + end + + context 'when build is not skipped' do + let(:build) { create(:ci_build) } + + it 'does not match' do + expect(subject).to be false + end + end + end end -- cgit v1.2.3 From 8a4ec84965bb746c86e7e73aa2f9abb238d85ca6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20=C4=8Cupi=C4=87?= Date: Tue, 3 Apr 2018 16:54:03 +0200 Subject: Add action_button_title Core status method --- lib/gitlab/ci/status/core.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/gitlab/ci/status/core.rb b/lib/gitlab/ci/status/core.rb index 89fb9a0b7bc..031bd4cd29c 100644 --- a/lib/gitlab/ci/status/core.rb +++ b/lib/gitlab/ci/status/core.rb @@ -61,6 +61,10 @@ module Gitlab def action_title raise NotImplementedError end + + def action_button_title + raise NotImplementedError + end end end end -- cgit v1.2.3 From 6c55a9d8f29a4d934dab2c3294c319bb8592fe2b Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Thu, 29 Mar 2018 19:37:00 +0200 Subject: Remove support for legacy tar.gz pages artifacts --- app/services/projects/update_pages_service.rb | 14 +-- .../services/projects/update_pages_service_spec.rb | 104 ++++++++++----------- 2 files changed, 51 insertions(+), 67 deletions(-) diff --git a/app/services/projects/update_pages_service.rb b/app/services/projects/update_pages_service.rb index 7e228d1833d..de77f6bf585 100644 --- a/app/services/projects/update_pages_service.rb +++ b/app/services/projects/update_pages_service.rb @@ -74,25 +74,13 @@ module Projects end def extract_archive!(temp_path) - if artifacts.ends_with?('.tar.gz') || artifacts.ends_with?('.tgz') - extract_tar_archive!(temp_path) - elsif artifacts.ends_with?('.zip') + if artifacts.ends_with?('.zip') extract_zip_archive!(temp_path) else raise InvaildStateError, 'unsupported artifacts format' end end - def extract_tar_archive!(temp_path) - build.artifacts_file.use_file do |artifacts_path| - results = Open3.pipeline(%W(gunzip -c #{artifacts_path}), - %W(dd bs=#{BLOCK_SIZE} count=#{blocks}), - %W(tar -x -C #{temp_path} #{SITE_PATH}), - err: '/dev/null') - raise FailedToExtractError, 'pages failed to extract' unless results.compact.all?(&:success?) - end - end - def extract_zip_archive!(temp_path) raise InvaildStateError, 'missing artifacts metadata' unless build.artifacts_metadata? diff --git a/spec/services/projects/update_pages_service_spec.rb b/spec/services/projects/update_pages_service_spec.rb index dd31a677dfe..1b6caeab15d 100644 --- a/spec/services/projects/update_pages_service_spec.rb +++ b/spec/services/projects/update_pages_service_spec.rb @@ -21,76 +21,72 @@ describe Projects::UpdatePagesService do end context 'legacy artifacts' do - %w(tar.gz zip).each do |format| - let(:extension) { format } + let(:extension) { 'zip' } - context "for valid #{format}" do + before do + build.update_attributes(legacy_artifacts_file: file) + build.update_attributes(legacy_artifacts_metadata: metadata) + end + + describe 'pages artifacts' do + context 'with expiry date' do before do - build.update_attributes(legacy_artifacts_file: file) - build.update_attributes(legacy_artifacts_metadata: metadata) + build.artifacts_expire_in = "2 days" + build.save! end - describe 'pages artifacts' do - context 'with expiry date' do - before do - build.artifacts_expire_in = "2 days" - build.save! - end - - it "doesn't delete artifacts" do - expect(execute).to eq(:success) - - expect(build.reload.artifacts?).to eq(true) - end - end - - context 'without expiry date' do - it "does delete artifacts" do - expect(execute).to eq(:success) + it "doesn't delete artifacts" do + expect(execute).to eq(:success) - expect(build.reload.artifacts?).to eq(false) - end - end + expect(build.reload.artifacts?).to eq(true) end + end - it 'succeeds' do - expect(project.pages_deployed?).to be_falsey + context 'without expiry date' do + it "does delete artifacts" do expect(execute).to eq(:success) - expect(project.pages_deployed?).to be_truthy - # Check that all expected files are extracted - %w[index.html zero .hidden/file].each do |filename| - expect(File.exist?(File.join(project.public_pages_path, filename))).to be_truthy - end + expect(build.reload.artifacts?).to eq(false) end + end + end - it 'limits pages size' do - stub_application_setting(max_pages_size: 1) - expect(execute).not_to eq(:success) - end + it 'succeeds' do + expect(project.pages_deployed?).to be_falsey + expect(execute).to eq(:success) + expect(project.pages_deployed?).to be_truthy - it 'removes pages after destroy' do - expect(PagesWorker).to receive(:perform_in) - expect(project.pages_deployed?).to be_falsey - expect(execute).to eq(:success) - expect(project.pages_deployed?).to be_truthy - project.destroy - expect(project.pages_deployed?).to be_falsey - end + # Check that all expected files are extracted + %w[index.html zero .hidden/file].each do |filename| + expect(File.exist?(File.join(project.public_pages_path, filename))).to be_truthy + end + end - it 'fails if sha on branch is not latest' do - build.update_attributes(ref: 'feature') + it 'limits pages size' do + stub_application_setting(max_pages_size: 1) + expect(execute).not_to eq(:success) + end - expect(execute).not_to eq(:success) - end + it 'removes pages after destroy' do + expect(PagesWorker).to receive(:perform_in) + expect(project.pages_deployed?).to be_falsey + expect(execute).to eq(:success) + expect(project.pages_deployed?).to be_truthy + project.destroy + expect(project.pages_deployed?).to be_falsey + end - it 'fails for empty file fails' do - build.update_attributes(legacy_artifacts_file: empty_file) + it 'fails if sha on branch is not latest' do + build.update_attributes(ref: 'feature') - expect { execute } - .to raise_error(Projects::UpdatePagesService::FailedToExtractError) - end - end + expect(execute).not_to eq(:success) + end + + it 'fails for empty file fails' do + build.update_attributes(legacy_artifacts_file: empty_file) + + expect { execute } + .to raise_error(Projects::UpdatePagesService::FailedToExtractError) end end -- cgit v1.2.3 From 8ac7ea4301eb9c1c90a592e878ac32154f6eb354 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20=C4=8Cupi=C4=87?= Date: Tue, 3 Apr 2018 19:47:04 +0200 Subject: Set up traces in build show spec --- spec/views/projects/jobs/show.html.haml_spec.rb | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/spec/views/projects/jobs/show.html.haml_spec.rb b/spec/views/projects/jobs/show.html.haml_spec.rb index 6a67da79ec5..64d6ae6d2a3 100644 --- a/spec/views/projects/jobs/show.html.haml_spec.rb +++ b/spec/views/projects/jobs/show.html.haml_spec.rb @@ -18,7 +18,7 @@ describe 'projects/jobs/show' do describe 'environment info in job view' do context 'job with latest deployment' do let(:build) do - create(:ci_build, :success, environment: 'staging') + create(:ci_build, :success, :trace_artifact, environment: 'staging') end before do @@ -37,11 +37,11 @@ describe 'projects/jobs/show' do context 'job with outdated deployment' do let(:build) do - create(:ci_build, :success, environment: 'staging', pipeline: pipeline) + create(:ci_build, :success, :trace_artifact, environment: 'staging', pipeline: pipeline) end let(:second_build) do - create(:ci_build, :success, environment: 'staging', pipeline: pipeline) + create(:ci_build, :success, :trace_artifact, environment: 'staging', pipeline: pipeline) end let(:environment) do @@ -67,7 +67,7 @@ describe 'projects/jobs/show' do context 'job failed to deploy' do let(:build) do - create(:ci_build, :failed, environment: 'staging', pipeline: pipeline) + create(:ci_build, :failed, :trace_artifact, environment: 'staging', pipeline: pipeline) end let!(:environment) do @@ -85,7 +85,7 @@ describe 'projects/jobs/show' do context 'job will deploy' do let(:build) do - create(:ci_build, :running, environment: 'staging', pipeline: pipeline) + create(:ci_build, :running, :trace_live, environment: 'staging', pipeline: pipeline) end context 'when environment exists' do @@ -133,7 +133,7 @@ describe 'projects/jobs/show' do context 'job that failed to deploy and environment has not been created' do let(:build) do - create(:ci_build, :failed, environment: 'staging', pipeline: pipeline) + create(:ci_build, :failed, :trace_artifact, environment: 'staging', pipeline: pipeline) end let!(:environment) do @@ -151,7 +151,7 @@ describe 'projects/jobs/show' do context 'job that will deploy and environment has not been created' do let(:build) do - create(:ci_build, :running, environment: 'staging', pipeline: pipeline) + create(:ci_build, :running, :trace_live, environment: 'staging', pipeline: pipeline) end let!(:environment) do @@ -171,8 +171,9 @@ describe 'projects/jobs/show' do end context 'when job is running' do + let(:build) { create(:ci_build, :trace_live, :running, pipeline: pipeline) } + before do - build.run! render end -- cgit v1.2.3 From 5af00309d3a4d50e89b278981dcd6485ae4e77f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20=C4=8Cupi=C4=87?= Date: Tue, 3 Apr 2018 20:14:33 +0200 Subject: Properly set up jobs in mini pipeline graph spec --- .../features/merge_request/user_sees_mini_pipeline_graph_spec.rb | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/spec/features/merge_request/user_sees_mini_pipeline_graph_spec.rb b/spec/features/merge_request/user_sees_mini_pipeline_graph_spec.rb index a43ba05c64c..fd1629746ef 100644 --- a/spec/features/merge_request/user_sees_mini_pipeline_graph_spec.rb +++ b/spec/features/merge_request/user_sees_mini_pipeline_graph_spec.rb @@ -9,6 +9,7 @@ describe 'Merge request < User sees mini pipeline graph', :js do before do build.run + build.trace.set('hello') sign_in(user) visit_merge_request end @@ -26,15 +27,15 @@ describe 'Merge request < User sees mini pipeline graph', :js do let(:artifacts_file2) { fixture_file_upload(Rails.root.join('spec/fixtures/dk.png'), 'image/png') } before do - create(:ci_build, pipeline: pipeline, legacy_artifacts_file: artifacts_file1) - create(:ci_build, pipeline: pipeline, when: 'manual') + create(:ci_build, :success, :trace_artifact, pipeline: pipeline, legacy_artifacts_file: artifacts_file1) + create(:ci_build, :manual, pipeline: pipeline, when: 'manual') end it 'avoids repeated database queries' do before = ActiveRecord::QueryRecorder.new { visit_merge_request(format: :json, serializer: 'widget') } - create(:ci_build, pipeline: pipeline, legacy_artifacts_file: artifacts_file2) - create(:ci_build, pipeline: pipeline, when: 'manual') + create(:ci_build, :success, :trace_artifact, pipeline: pipeline, legacy_artifacts_file: artifacts_file2) + create(:ci_build, :manual, pipeline: pipeline, when: 'manual') after = ActiveRecord::QueryRecorder.new { visit_merge_request(format: :json, serializer: 'widget') } -- cgit v1.2.3 From ff1383fb11267996bf040260513e6d3d8f468def Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20=C4=8Cupi=C4=87?= Date: Tue, 3 Apr 2018 20:17:26 +0200 Subject: Properly set up job trace in user_browses_job_spec --- spec/features/projects/jobs/user_browses_job_spec.rb | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/spec/features/projects/jobs/user_browses_job_spec.rb b/spec/features/projects/jobs/user_browses_job_spec.rb index 4c49cff30d4..8fa902cc386 100644 --- a/spec/features/projects/jobs/user_browses_job_spec.rb +++ b/spec/features/projects/jobs/user_browses_job_spec.rb @@ -1,16 +1,14 @@ require 'spec_helper' describe 'User browses a job', :js do - let!(:build) { create(:ci_build, :running, :coverage, pipeline: pipeline) } - let(:pipeline) { create(:ci_empty_pipeline, project: project, sha: project.commit.sha, ref: 'master') } - let(:project) { create(:project, :repository, namespace: user.namespace) } let(:user) { create(:user) } + let(:project) { create(:project, :repository, namespace: user.namespace) } + let(:pipeline) { create(:ci_empty_pipeline, project: project, sha: project.commit.sha, ref: 'master') } + let!(:build) { create(:ci_build, :success, :trace_artifact, :coverage, pipeline: pipeline) } before do project.add_master(user) project.enable_ci - build.success - build.trace.set('job trace') sign_in(user) -- cgit v1.2.3 From c1b71e2fa1e49da82b15ee7f12148a372face09c Mon Sep 17 00:00:00 2001 From: Jan Provaznik Date: Fri, 23 Mar 2018 15:27:15 +0100 Subject: Check if at least one filter is set on dashboard When listing issues and merge requests on dasboard page, make sure that at least one filter is enabled. User's id is used in search autocomplete widget instead of username, which allows presetting user in filter dropdowns. Related to #43246 --- app/assets/javascripts/search_autocomplete.js | 8 ++++---- app/controllers/dashboard_controller.rb | 14 +++++++++++++ app/helpers/application_helper.rb | 2 -- app/helpers/issuables_helper.rb | 24 ++++++---------------- app/views/dashboard/issues.html.haml | 2 +- app/views/dashboard/merge_requests.html.haml | 2 +- app/views/shared/issuable/_filter.html.haml | 4 ---- app/views/shared/issuable/_nav.html.haml | 11 +++++----- spec/controllers/dashboard_controller_spec.rb | 2 ++ spec/features/dashboard/issues_spec.rb | 9 -------- .../issuables_list_metadata_shared_examples.rb | 8 ++++---- .../issuables_requiring_filter_shared_examples.rb | 15 ++++++++++++++ 12 files changed, 53 insertions(+), 48 deletions(-) create mode 100644 spec/support/issuables_requiring_filter_shared_examples.rb diff --git a/app/assets/javascripts/search_autocomplete.js b/app/assets/javascripts/search_autocomplete.js index 7dd3e9858c6..2da022fde63 100644 --- a/app/assets/javascripts/search_autocomplete.js +++ b/app/assets/javascripts/search_autocomplete.js @@ -233,21 +233,21 @@ export default class SearchAutocomplete { const issueItems = [ { text: 'Issues assigned to me', - url: `${issuesPath}/?assignee_username=${userName}`, + url: `${issuesPath}/?assignee_id=${userId}`, }, { text: "Issues I've created", - url: `${issuesPath}/?author_username=${userName}`, + url: `${issuesPath}/?author_id=${userId}`, }, ]; const mergeRequestItems = [ { text: 'Merge requests assigned to me', - url: `${mrPath}/?assignee_username=${userName}`, + url: `${mrPath}/?assignee_id=${userId}`, }, { text: "Merge requests I've created", - url: `${mrPath}/?author_username=${userName}`, + url: `${mrPath}/?author_id=${userId}`, }, ]; diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb index 280ed93faf8..d228956d8e3 100644 --- a/app/controllers/dashboard_controller.rb +++ b/app/controllers/dashboard_controller.rb @@ -2,9 +2,17 @@ class DashboardController < Dashboard::ApplicationController include IssuesAction include MergeRequestsAction + FILTER_PARAMS = [ + :author_id, + :assignee_id, + :milestone_title, + :label_name + ].freeze + before_action :event_filter, only: :activity before_action :projects, only: [:issues, :merge_requests] before_action :set_show_full_reference, only: [:issues, :merge_requests] + before_action :check_filters_presence, only: [:issues, :merge_requests] respond_to :html @@ -39,4 +47,10 @@ class DashboardController < Dashboard::ApplicationController def set_show_full_reference @show_full_reference = true end + + def check_filters_presence + @no_filters_set = FILTER_PARAMS.none? { |k| params.key?(k) } + + render action: action_name if @no_filters_set + end end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 86ec500ceb3..228c8d2e8f9 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -228,9 +228,7 @@ module ApplicationHelper scope: params[:scope], milestone_title: params[:milestone_title], assignee_id: params[:assignee_id], - assignee_username: params[:assignee_username], author_id: params[:author_id], - author_username: params[:author_username], search: params[:search], label_name: params[:label_name] } diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb index 6d6b840f485..06c3e569c84 100644 --- a/app/helpers/issuables_helper.rb +++ b/app/helpers/issuables_helper.rb @@ -159,16 +159,18 @@ module IssuablesHelper label_names.join(', ') end - def issuables_state_counter_text(issuable_type, state) + def issuables_state_counter_text(issuable_type, state, display_count) titles = { opened: "Open" } state_title = titles[state] || state.to_s.humanize - count = issuables_count_for_state(issuable_type, state) - html = content_tag(:span, state_title) - html << " " << content_tag(:span, number_with_delimiter(count), class: 'badge') + + if display_count + count = issuables_count_for_state(issuable_type, state) + html << " " << content_tag(:span, number_with_delimiter(count), class: 'badge') + end html.html_safe end @@ -191,24 +193,10 @@ module IssuablesHelper end end - def issuable_filter_params - [ - :search, - :author_id, - :assignee_id, - :milestone_title, - :label_name - ] - end - def issuable_reference(issuable) @show_full_reference ? issuable.to_reference(full: true) : issuable.to_reference(@group || @project) end - def issuable_filter_present? - issuable_filter_params.any? { |k| params.key?(k) } - end - def issuable_initial_data(issuable) data = { endpoint: issuable_path(issuable), diff --git a/app/views/dashboard/issues.html.haml b/app/views/dashboard/issues.html.haml index 3e85535dae0..24d69b56c20 100644 --- a/app/views/dashboard/issues.html.haml +++ b/app/views/dashboard/issues.html.haml @@ -5,7 +5,7 @@ = auto_discovery_link_tag(:atom, params.merge(rss_url_options), title: "#{current_user.name} issues") .top-area - = render 'shared/issuable/nav', type: :issues + = render 'shared/issuable/nav', type: :issues, display_count: !@no_filters_set .nav-controls = link_to params.merge(rss_url_options), class: 'btn has-tooltip', data: { container: 'body' }, title: 'Subscribe' do = icon('rss') diff --git a/app/views/dashboard/merge_requests.html.haml b/app/views/dashboard/merge_requests.html.haml index 53cd1130299..fb57ec7835c 100644 --- a/app/views/dashboard/merge_requests.html.haml +++ b/app/views/dashboard/merge_requests.html.haml @@ -3,7 +3,7 @@ - header_title "Merge Requests", merge_requests_dashboard_path(assignee_id: current_user.id) .top-area - = render 'shared/issuable/nav', type: :merge_requests + = render 'shared/issuable/nav', type: :merge_requests, display_count: !@no_filters_set .nav-controls = render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New merge request", with_feature_enabled: 'merge_requests', type: :merge_requests diff --git a/app/views/shared/issuable/_filter.html.haml b/app/views/shared/issuable/_filter.html.haml index 7704c88905b..58b37290cd5 100644 --- a/app/views/shared/issuable/_filter.html.haml +++ b/app/views/shared/issuable/_filter.html.haml @@ -24,10 +24,6 @@ .filter-item.inline.labels-filter = render "shared/issuable/label_dropdown", selected: selected_labels, use_id: false, selected_toggle: params[:label_name], data_options: { field_name: "label_name[]" } - - if issuable_filter_present? - .filter-item.inline.reset-filters - %a{ href: page_filter_path(without: issuable_filter_params) } Reset filters - .pull-right = render 'shared/sort_dropdown' diff --git a/app/views/shared/issuable/_nav.html.haml b/app/views/shared/issuable/_nav.html.haml index 4d8109eb90c..a5f40ea934b 100644 --- a/app/views/shared/issuable/_nav.html.haml +++ b/app/views/shared/issuable/_nav.html.haml @@ -1,22 +1,23 @@ - type = local_assigns.fetch(:type, :issues) - page_context_word = type.to_s.humanize(capitalize: false) +- display_count = local_assigns.fetch(:display_count, :true) %ul.nav-links.issues-state-filters.mobile-separator %li{ class: active_when(params[:state] == 'opened') }> = link_to page_filter_path(state: 'opened', label: true), id: 'state-opened', title: "Filter by #{page_context_word} that are currently opened.", data: { state: 'opened' } do - #{issuables_state_counter_text(type, :opened)} + #{issuables_state_counter_text(type, :opened, display_count)} - if type == :merge_requests %li{ class: active_when(params[:state] == 'merged') }> = link_to page_filter_path(state: 'merged', label: true), id: 'state-merged', title: 'Filter by merge requests that are currently merged.', data: { state: 'merged' } do - #{issuables_state_counter_text(type, :merged)} + #{issuables_state_counter_text(type, :merged, display_count)} %li{ class: active_when(params[:state] == 'closed') }> = link_to page_filter_path(state: 'closed', label: true), id: 'state-closed', title: 'Filter by merge requests that are currently closed and unmerged.', data: { state: 'closed' } do - #{issuables_state_counter_text(type, :closed)} + #{issuables_state_counter_text(type, :closed, display_count)} - else %li{ class: active_when(params[:state] == 'closed') }> = link_to page_filter_path(state: 'closed', label: true), id: 'state-closed', title: 'Filter by issues that are currently closed.', data: { state: 'closed' } do - #{issuables_state_counter_text(type, :closed)} + #{issuables_state_counter_text(type, :closed, display_count)} - = render 'shared/issuable/nav_links/all', page_context_word: page_context_word, counter: issuables_state_counter_text(type, :all) + = render 'shared/issuable/nav_links/all', page_context_word: page_context_word, counter: issuables_state_counter_text(type, :all, display_count) diff --git a/spec/controllers/dashboard_controller_spec.rb b/spec/controllers/dashboard_controller_spec.rb index 97c2c3fb940..3458d679107 100644 --- a/spec/controllers/dashboard_controller_spec.rb +++ b/spec/controllers/dashboard_controller_spec.rb @@ -11,9 +11,11 @@ describe DashboardController do describe 'GET issues' do it_behaves_like 'issuables list meta-data', :issue, :issues + it_behaves_like 'issuables requiring filter', :issues end describe 'GET merge requests' do it_behaves_like 'issuables list meta-data', :merge_request, :merge_requests + it_behaves_like 'issuables requiring filter', :merge_requests end end diff --git a/spec/features/dashboard/issues_spec.rb b/spec/features/dashboard/issues_spec.rb index 8d1d5a51750..e41a2e4ce09 100644 --- a/spec/features/dashboard/issues_spec.rb +++ b/spec/features/dashboard/issues_spec.rb @@ -51,15 +51,6 @@ RSpec.describe 'Dashboard Issues' do expect(page).not_to have_content(other_issue.title) end - it 'shows all issues' do - click_link('Reset filters') - - expect(page).to have_content(authored_issue.title) - expect(page).to have_content(authored_issue_on_public_project.title) - expect(page).to have_content(assigned_issue.title) - expect(page).to have_content(other_issue.title) - end - it 'state filter tabs work' do find('#state-closed').click expect(page).to have_current_path(issues_dashboard_url(assignee_id: current_user.id, state: 'closed'), url: true) diff --git a/spec/support/issuables_list_metadata_shared_examples.rb b/spec/support/issuables_list_metadata_shared_examples.rb index 75982432ab4..e61983c60b4 100644 --- a/spec/support/issuables_list_metadata_shared_examples.rb +++ b/spec/support/issuables_list_metadata_shared_examples.rb @@ -5,9 +5,9 @@ shared_examples 'issuables list meta-data' do |issuable_type, action = nil| %w[fix improve/awesome].each do |source_branch| issuable = if issuable_type == :issue - create(issuable_type, project: project) + create(issuable_type, project: project, author: project.creator) else - create(issuable_type, source_project: project, source_branch: source_branch) + create(issuable_type, source_project: project, source_branch: source_branch, author: project.creator) end @issuable_ids << issuable.id @@ -16,7 +16,7 @@ shared_examples 'issuables list meta-data' do |issuable_type, action = nil| it "creates indexed meta-data object for issuable notes and votes count" do if action - get action + get action, author_id: project.creator.id else get :index, namespace_id: project.namespace, project_id: project end @@ -35,7 +35,7 @@ shared_examples 'issuables list meta-data' do |issuable_type, action = nil| it "doesn't execute any queries with false conditions" do get_action = if action - proc { get action } + proc { get action, author_id: project.creator.id } else proc { get :index, namespace_id: project2.namespace, project_id: project2 } end diff --git a/spec/support/issuables_requiring_filter_shared_examples.rb b/spec/support/issuables_requiring_filter_shared_examples.rb new file mode 100644 index 00000000000..439ef5ed92e --- /dev/null +++ b/spec/support/issuables_requiring_filter_shared_examples.rb @@ -0,0 +1,15 @@ +shared_examples 'issuables requiring filter' do |action| + it "doesn't load any issuables if no filter is set" do + expect_any_instance_of(described_class).not_to receive(:issuables_collection) + + get action + + expect(response).to render_template(action) + end + + it "loads issuables if at least one filter is set" do + expect_any_instance_of(described_class).to receive(:issuables_collection).and_call_original + + get action, author_id: user.id + end +end -- cgit v1.2.3 From a32941aee32ddfd7b114011f951741e06a53be5d Mon Sep 17 00:00:00 2001 From: Winnie Hellmann Date: Thu, 29 Mar 2018 13:43:53 +0200 Subject: Display illustration and message if no filter is selected --- app/assets/stylesheets/framework/images.scss | 2 +- app/views/dashboard/issues.html.haml | 6 +++++- app/views/dashboard/merge_requests.html.haml | 6 +++++- app/views/shared/dashboard/_no_filter_selected.html.haml | 8 ++++++++ app/views/shared/issuable/_filter.html.haml | 5 +++-- 5 files changed, 22 insertions(+), 5 deletions(-) create mode 100644 app/views/shared/dashboard/_no_filter_selected.html.haml diff --git a/app/assets/stylesheets/framework/images.scss b/app/assets/stylesheets/framework/images.scss index df1cafc9f8e..62a0fba3da3 100644 --- a/app/assets/stylesheets/framework/images.scss +++ b/app/assets/stylesheets/framework/images.scss @@ -20,7 +20,7 @@ width: 100%; } - $image-widths: 80 250 306 394 430; + $image-widths: 80 130 250 306 394 430; @each $width in $image-widths { &.svg-#{$width} { img, diff --git a/app/views/dashboard/issues.html.haml b/app/views/dashboard/issues.html.haml index 24d69b56c20..35bf92a0d07 100644 --- a/app/views/dashboard/issues.html.haml +++ b/app/views/dashboard/issues.html.haml @@ -12,4 +12,8 @@ = render 'shared/new_project_item_select', path: 'issues/new', label: "New issue", with_feature_enabled: 'issues', type: :issues = render 'shared/issuable/filter', type: :issues -= render 'shared/issues' + +- if current_user && @no_filters_set + = render 'shared/dashboard/no_filter_selected' +- else + = render 'shared/issues' diff --git a/app/views/dashboard/merge_requests.html.haml b/app/views/dashboard/merge_requests.html.haml index fb57ec7835c..7b69a6f5d0f 100644 --- a/app/views/dashboard/merge_requests.html.haml +++ b/app/views/dashboard/merge_requests.html.haml @@ -8,4 +8,8 @@ = render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New merge request", with_feature_enabled: 'merge_requests', type: :merge_requests = render 'shared/issuable/filter', type: :merge_requests -= render 'shared/merge_requests' + +- if current_user && @no_filters_set + = render 'shared/dashboard/no_filter_selected' +- else + = render 'shared/merge_requests' diff --git a/app/views/shared/dashboard/_no_filter_selected.html.haml b/app/views/shared/dashboard/_no_filter_selected.html.haml new file mode 100644 index 00000000000..e5c2f5b2346 --- /dev/null +++ b/app/views/shared/dashboard/_no_filter_selected.html.haml @@ -0,0 +1,8 @@ +.row.empty-state.text-center + .col-xs-12 + .svg-130 + = image_tag 'illustrations/issue-dashboard_results-without-filter.svg' + .col-xs-12 + .text-content + %h4 + = _("Please select at least one filter to see results") diff --git a/app/views/shared/issuable/_filter.html.haml b/app/views/shared/issuable/_filter.html.haml index 58b37290cd5..994198e2f69 100644 --- a/app/views/shared/issuable/_filter.html.haml +++ b/app/views/shared/issuable/_filter.html.haml @@ -24,8 +24,9 @@ .filter-item.inline.labels-filter = render "shared/issuable/label_dropdown", selected: selected_labels, use_id: false, selected_toggle: params[:label_name], data_options: { field_name: "label_name[]" } - .pull-right - = render 'shared/sort_dropdown' + - if !@no_filters_set + .pull-right + = render 'shared/sort_dropdown' - has_labels = @labels && @labels.any? .row-content-block.second-block.filtered-labels{ class: ("hidden" unless has_labels) } -- cgit v1.2.3 From d10416e231a27c63c322ba7338f2ea8279436336 Mon Sep 17 00:00:00 2001 From: Jan Provaznik Date: Tue, 27 Mar 2018 17:29:13 +0200 Subject: Fixed dashboard filtering tests --- app/controllers/dashboard_controller.rb | 11 +- changelogs/unreleased/43246-checkfilter.yml | 6 + spec/features/atom/dashboard_issues_spec.rb | 17 ++- spec/features/dashboard/issues_filter_spec.rb | 32 +++--- spec/features/dashboard/merge_requests_spec.rb | 8 +- .../search/user_uses_header_search_field_spec.rb | 127 ++++++++++++++------- spec/helpers/issuables_helper_spec.rb | 29 +---- spec/javascripts/search_autocomplete_spec.js | 8 +- 8 files changed, 137 insertions(+), 101 deletions(-) create mode 100644 changelogs/unreleased/43246-checkfilter.yml diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb index d228956d8e3..68d328fa797 100644 --- a/app/controllers/dashboard_controller.rb +++ b/app/controllers/dashboard_controller.rb @@ -12,7 +12,7 @@ class DashboardController < Dashboard::ApplicationController before_action :event_filter, only: :activity before_action :projects, only: [:issues, :merge_requests] before_action :set_show_full_reference, only: [:issues, :merge_requests] - before_action :check_filters_presence, only: [:issues, :merge_requests] + before_action :check_filters_presence!, only: [:issues, :merge_requests] respond_to :html @@ -48,9 +48,14 @@ class DashboardController < Dashboard::ApplicationController @show_full_reference = true end - def check_filters_presence + def check_filters_presence! @no_filters_set = FILTER_PARAMS.none? { |k| params.key?(k) } - render action: action_name if @no_filters_set + return unless @no_filters_set + + respond_to do |format| + format.html + format.atom { head :bad_request } + end end end diff --git a/changelogs/unreleased/43246-checkfilter.yml b/changelogs/unreleased/43246-checkfilter.yml new file mode 100644 index 00000000000..e6c0e716213 --- /dev/null +++ b/changelogs/unreleased/43246-checkfilter.yml @@ -0,0 +1,6 @@ +--- +title: Require at least one filter when listing issues or merge requests on dashboard + page +merge_request: +author: +type: performance diff --git a/spec/features/atom/dashboard_issues_spec.rb b/spec/features/atom/dashboard_issues_spec.rb index d673bac4995..fb6c71ce997 100644 --- a/spec/features/atom/dashboard_issues_spec.rb +++ b/spec/features/atom/dashboard_issues_spec.rb @@ -13,17 +13,26 @@ describe "Dashboard Issues Feed" do end describe "atom feed" do - it "renders atom feed via personal access token" do + it "returns 400 if no filter is used" do personal_access_token = create(:personal_access_token, user: user) visit issues_dashboard_path(:atom, private_token: personal_access_token.token) + expect(response_headers['Content-Type']).to have_content('application/atom+xml') + expect(page.status_code).to eq(400) + end + + it "renders atom feed via personal access token" do + personal_access_token = create(:personal_access_token, user: user) + + visit issues_dashboard_path(:atom, private_token: personal_access_token.token, assignee_id: user.id) + expect(response_headers['Content-Type']).to have_content('application/atom+xml') expect(body).to have_selector('title', text: "#{user.name} issues") end it "renders atom feed via RSS token" do - visit issues_dashboard_path(:atom, rss_token: user.rss_token) + visit issues_dashboard_path(:atom, rss_token: user.rss_token, assignee_id: user.id) expect(response_headers['Content-Type']).to have_content('application/atom+xml') expect(body).to have_selector('title', text: "#{user.name} issues") @@ -44,7 +53,7 @@ describe "Dashboard Issues Feed" do let!(:issue2) { create(:issue, author: user, assignees: [assignee], project: project2, description: 'test desc') } it "renders issue fields" do - visit issues_dashboard_path(:atom, rss_token: user.rss_token) + visit issues_dashboard_path(:atom, rss_token: user.rss_token, assignee_id: assignee.id) entry = find(:xpath, "//feed/entry[contains(summary/text(),'#{issue2.title}')]") @@ -67,7 +76,7 @@ describe "Dashboard Issues Feed" do end it "renders issue label and milestone info" do - visit issues_dashboard_path(:atom, rss_token: user.rss_token) + visit issues_dashboard_path(:atom, rss_token: user.rss_token, assignee_id: assignee.id) entry = find(:xpath, "//feed/entry[contains(summary/text(),'#{issue1.title}')]") diff --git a/spec/features/dashboard/issues_filter_spec.rb b/spec/features/dashboard/issues_filter_spec.rb index 029fc45c791..b15f3afca4a 100644 --- a/spec/features/dashboard/issues_filter_spec.rb +++ b/spec/features/dashboard/issues_filter_spec.rb @@ -17,6 +17,12 @@ feature 'Dashboard Issues filtering', :js do visit_issues end + context 'without any filter' do + it 'shows error message' do + expect(page).to have_content 'Please select at least one filter to see results' + end + end + context 'filtering by milestone' do it 'shows all issues with no milestone' do show_milestone_dropdown @@ -27,15 +33,6 @@ feature 'Dashboard Issues filtering', :js do expect(page).to have_selector('.issue', count: 1) end - it 'shows all issues with any milestone' do - show_milestone_dropdown - - click_link 'Any Milestone' - - expect(page).to have_issuable_counts(open: 2, closed: 0, all: 2) - expect(page).to have_selector('.issue', count: 2) - end - it 'shows all issues with the selected milestone' do show_milestone_dropdown @@ -68,13 +65,6 @@ feature 'Dashboard Issues filtering', :js do let(:label) { create(:label, project: project) } let!(:label_link) { create(:label_link, label: label, target: issue) } - it 'shows all issues without filter' do - page.within 'ul.content-list' do - expect(page).to have_content issue.title - expect(page).to have_content issue2.title - end - end - it 'shows all issues with the selected label' do page.within '.labels-filter' do find('.dropdown').click @@ -89,9 +79,19 @@ feature 'Dashboard Issues filtering', :js do end context 'sorting' do +<<<<<<< HEAD it 'shows sorted issues' do sort_by('Created date') visit_issues +======= + before do + visit_issues(assignee_id: user.id) + end + + it 'remembers last sorting value' do + sorting_by('Created date') + visit_issues(assignee_id: user.id) +>>>>>>> Fixed dashboard filtering tests expect(find('.issues-filters')).to have_content('Created date') end diff --git a/spec/features/dashboard/merge_requests_spec.rb b/spec/features/dashboard/merge_requests_spec.rb index 4a9344115d2..0965b745c03 100644 --- a/spec/features/dashboard/merge_requests_spec.rb +++ b/spec/features/dashboard/merge_requests_spec.rb @@ -103,15 +103,11 @@ feature 'Dashboard Merge Requests' do expect(page).not_to have_content(other_merge_request.title) end - it 'shows all merge requests', :js do + it 'shows error message without filter', :js do filter_item_select('Any Assignee', '.js-assignee-search') filter_item_select('Any Author', '.js-author-search') - expect(page).to have_content(authored_merge_request.title) - expect(page).to have_content(authored_merge_request_from_fork.title) - expect(page).to have_content(assigned_merge_request.title) - expect(page).to have_content(assigned_merge_request_from_fork.title) - expect(page).to have_content(other_merge_request.title) + expect(page).to have_content('Please select at least one filter to see results') end it 'shows sorted merge requests' do diff --git a/spec/features/search/user_uses_header_search_field_spec.rb b/spec/features/search/user_uses_header_search_field_spec.rb index 5ddea36add5..a9128104b87 100644 --- a/spec/features/search/user_uses_header_search_field_spec.rb +++ b/spec/features/search/user_uses_header_search_field_spec.rb @@ -9,49 +9,25 @@ describe 'User uses header search field' do before do project.add_reporter(user) sign_in(user) - - visit(project_path(project)) - end - - it 'starts searching by pressing the enter key', :js do - fill_in('search', with: 'gitlab') - find('#search').native.send_keys(:enter) - - page.within('.breadcrumbs-sub-title') do - expect(page).to have_content('Search') - end end - it 'contains location badge' do - expect(page).to have_selector('.has-location-badge') - end - - context 'when clicking the search field', :js do + context 'when user is in a global scope', :js do before do + visit(root_path) page.find('#search').click end - it 'shows category search dropdown' do - expect(page).to have_selector('.dropdown-header', text: /#{project.name}/i) - end - context 'when clicking issues' do - let!(:issue) { create(:issue, project: project, author: user, assignees: [user]) } - it 'shows assigned issues' do - find('.dropdown-menu').click_link('Issues assigned to me') + find('.search-input-container .dropdown-menu').click_link('Issues assigned to me') - expect(page).to have_selector('.filtered-search') - expect_tokens([assignee_token(user.name)]) - expect_filtered_search_input_empty + expect(find('.js-assignee-search')).to have_content(user.name) end it 'shows created issues' do - find('.dropdown-menu').click_link("Issues I've created") + find('.search-input-container .dropdown-menu').click_link("Issues I've created") - expect(page).to have_selector('.filtered-search') - expect_tokens([author_token(user.name)]) - expect_filtered_search_input_empty + expect(find('.js-author-search')).to have_content(user.name) end end @@ -59,32 +35,97 @@ describe 'User uses header search field' do let!(:merge_request) { create(:merge_request, source_project: project, author: user, assignee: user) } it 'shows assigned merge requests' do - find('.dropdown-menu').click_link('Merge requests assigned to me') + find('.search-input-container .dropdown-menu').click_link('Merge requests assigned to me') - expect(page).to have_selector('.merge-requests-holder') - expect_tokens([assignee_token(user.name)]) - expect_filtered_search_input_empty + expect(find('.js-assignee-search')).to have_content(user.name) end it 'shows created merge requests' do - find('.dropdown-menu').click_link("Merge requests I've created") + find('.search-input-container .dropdown-menu').click_link("Merge requests I've created") - expect(page).to have_selector('.merge-requests-holder') - expect_tokens([author_token(user.name)]) - expect_filtered_search_input_empty + expect(find('.js-author-search')).to have_content(user.name) end end end - context 'when entering text into the search field', :js do + context 'when user is in a project scope' do before do - page.within('.search-input-wrap') do - fill_in('search', with: project.name[0..3]) + visit(project_path(project)) + end + + it 'starts searching by pressing the enter key', :js do + fill_in('search', with: 'gitlab') + find('#search').native.send_keys(:enter) + + page.within('.breadcrumbs-sub-title') do + expect(page).to have_content('Search') end end - it 'does not display the category search dropdown' do - expect(page).not_to have_selector('.dropdown-header', text: /#{project.name}/i) + it 'contains location badge' do + expect(page).to have_selector('.has-location-badge') + end + + context 'when clicking the search field', :js do + before do + page.find('#search').click + end + + it 'shows category search dropdown' do + expect(page).to have_selector('.dropdown-header', text: /#{project.name}/i) + end + + context 'when clicking issues' do + let!(:issue) { create(:issue, project: project, author: user, assignees: [user]) } + + it 'shows assigned issues' do + find('.dropdown-menu').click_link('Issues assigned to me') + + expect(page).to have_selector('.filtered-search') + expect_tokens([assignee_token(user.name)]) + expect_filtered_search_input_empty + end + + it 'shows created issues' do + find('.dropdown-menu').click_link("Issues I've created") + + expect(page).to have_selector('.filtered-search') + expect_tokens([author_token(user.name)]) + expect_filtered_search_input_empty + end + end + + context 'when clicking merge requests' do + let!(:merge_request) { create(:merge_request, source_project: project, author: user, assignee: user) } + + it 'shows assigned merge requests' do + find('.dropdown-menu').click_link('Merge requests assigned to me') + + expect(page).to have_selector('.merge-requests-holder') + expect_tokens([assignee_token(user.name)]) + expect_filtered_search_input_empty + end + + it 'shows created merge requests' do + find('.dropdown-menu').click_link("Merge requests I've created") + + expect(page).to have_selector('.merge-requests-holder') + expect_tokens([author_token(user.name)]) + expect_filtered_search_input_empty + end + end + end + + context 'when entering text into the search field', :js do + before do + page.within('.search-input-wrap') do + fill_in('search', with: project.name[0..3]) + end + end + + it 'does not display the category search dropdown' do + expect(page).not_to have_selector('.dropdown-header', text: /#{project.name}/i) + end end end end diff --git a/spec/helpers/issuables_helper_spec.rb b/spec/helpers/issuables_helper_spec.rb index 2fecd1a3d27..4224cea4652 100644 --- a/spec/helpers/issuables_helper_spec.rb +++ b/spec/helpers/issuables_helper_spec.rb @@ -40,22 +40,22 @@ describe IssuablesHelper do end it 'returns "Open" when state is :opened' do - expect(helper.issuables_state_counter_text(:issues, :opened)) + expect(helper.issuables_state_counter_text(:issues, :opened, true)) .to eq('Open 42') end it 'returns "Closed" when state is :closed' do - expect(helper.issuables_state_counter_text(:issues, :closed)) + expect(helper.issuables_state_counter_text(:issues, :closed, true)) .to eq('Closed 42') end it 'returns "Merged" when state is :merged' do - expect(helper.issuables_state_counter_text(:merge_requests, :merged)) + expect(helper.issuables_state_counter_text(:merge_requests, :merged, true)) .to eq('Merged 42') end it 'returns "All" when state is :all' do - expect(helper.issuables_state_counter_text(:merge_requests, :all)) + expect(helper.issuables_state_counter_text(:merge_requests, :all, true)) .to eq('All 42') end end @@ -101,27 +101,6 @@ describe IssuablesHelper do end end - describe '#issuable_filter_present?' do - it 'returns true when any key is present' do - allow(helper).to receive(:params).and_return( - ActionController::Parameters.new(milestone_title: 'Velit consectetur asperiores natus delectus.', - project_id: 'gitlabhq', - scope: 'all') - ) - - expect(helper.issuable_filter_present?).to be_truthy - end - - it 'returns false when no key is present' do - allow(helper).to receive(:params).and_return( - ActionController::Parameters.new(project_id: 'gitlabhq', - scope: 'all') - ) - - expect(helper.issuable_filter_present?).to be_falsey - end - end - describe '#updated_at_by' do let(:user) { create(:user) } let(:unedited_issuable) { create(:issue) } diff --git a/spec/javascripts/search_autocomplete_spec.js b/spec/javascripts/search_autocomplete_spec.js index 40115792652..ac47f14ab46 100644 --- a/spec/javascripts/search_autocomplete_spec.js +++ b/spec/javascripts/search_autocomplete_spec.js @@ -98,8 +98,8 @@ import * as urlUtils from '~/lib/utils/url_utility'; assertLinks = function(list, issuesPath, mrsPath) { var a1, a2, a3, a4, issuesAssignedToMeLink, issuesIHaveCreatedLink, mrsAssignedToMeLink, mrsIHaveCreatedLink; if (issuesPath) { - issuesAssignedToMeLink = issuesPath + "/?assignee_username=" + userName; - issuesIHaveCreatedLink = issuesPath + "/?author_username=" + userName; + issuesAssignedToMeLink = issuesPath + "/?assignee_id=" + userId; + issuesIHaveCreatedLink = issuesPath + "/?author_id=" + userId; a1 = "a[href='" + issuesAssignedToMeLink + "']"; a2 = "a[href='" + issuesIHaveCreatedLink + "']"; expect(list.find(a1).length).toBe(1); @@ -107,8 +107,8 @@ import * as urlUtils from '~/lib/utils/url_utility'; expect(list.find(a2).length).toBe(1); expect(list.find(a2).text()).toBe("Issues I've created"); } - mrsAssignedToMeLink = mrsPath + "/?assignee_username=" + userName; - mrsIHaveCreatedLink = mrsPath + "/?author_username=" + userName; + mrsAssignedToMeLink = mrsPath + "/?assignee_id=" + userId; + mrsIHaveCreatedLink = mrsPath + "/?author_id=" + userId; a3 = "a[href='" + mrsAssignedToMeLink + "']"; a4 = "a[href='" + mrsIHaveCreatedLink + "']"; expect(list.find(a3).length).toBe(1); -- cgit v1.2.3 From d343ef8bcee69b81190f52aded3f0ae217ffdc94 Mon Sep 17 00:00:00 2001 From: Winnie Hellmann Date: Tue, 3 Apr 2018 20:19:51 +0200 Subject: Resolve conflicts in issues_filter_spec.rb --- spec/features/dashboard/issues_filter_spec.rb | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/spec/features/dashboard/issues_filter_spec.rb b/spec/features/dashboard/issues_filter_spec.rb index b15f3afca4a..bab34ac9346 100644 --- a/spec/features/dashboard/issues_filter_spec.rb +++ b/spec/features/dashboard/issues_filter_spec.rb @@ -79,19 +79,13 @@ feature 'Dashboard Issues filtering', :js do end context 'sorting' do -<<<<<<< HEAD - it 'shows sorted issues' do - sort_by('Created date') - visit_issues -======= before do visit_issues(assignee_id: user.id) end it 'remembers last sorting value' do - sorting_by('Created date') + sort_by('Created date') visit_issues(assignee_id: user.id) ->>>>>>> Fixed dashboard filtering tests expect(find('.issues-filters')).to have_content('Created date') end -- cgit v1.2.3 From d7f81b7e5def5b241c9bf7ba35a8b6c0f55a686e Mon Sep 17 00:00:00 2001 From: Winnie Hellmann Date: Wed, 4 Apr 2018 15:39:17 +0200 Subject: Increase top margin of illustration --- app/views/shared/dashboard/_no_filter_selected.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/shared/dashboard/_no_filter_selected.html.haml b/app/views/shared/dashboard/_no_filter_selected.html.haml index e5c2f5b2346..b2e6967f6aa 100644 --- a/app/views/shared/dashboard/_no_filter_selected.html.haml +++ b/app/views/shared/dashboard/_no_filter_selected.html.haml @@ -1,6 +1,6 @@ .row.empty-state.text-center .col-xs-12 - .svg-130 + .svg-130.prepend-top-default = image_tag 'illustrations/issue-dashboard_results-without-filter.svg' .col-xs-12 .text-content -- cgit v1.2.3 From 75f8a45f6a202aa5bec00613dcd16573fc1cc46a Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Wed, 4 Apr 2018 19:28:53 +0100 Subject: Scrolls to the top of the page before erase click --- spec/features/projects/jobs/user_browses_job_spec.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/spec/features/projects/jobs/user_browses_job_spec.rb b/spec/features/projects/jobs/user_browses_job_spec.rb index 8fa902cc386..a728e6eb996 100644 --- a/spec/features/projects/jobs/user_browses_job_spec.rb +++ b/spec/features/projects/jobs/user_browses_job_spec.rb @@ -2,6 +2,7 @@ require 'spec_helper' describe 'User browses a job', :js do let(:user) { create(:user) } + let(:user_access_level) { :developer } let(:project) { create(:project, :repository, namespace: user.namespace) } let(:pipeline) { create(:ci_empty_pipeline, project: project, sha: project.commit.sha, ref: 'master') } let!(:build) { create(:ci_build, :success, :trace_artifact, :coverage, pipeline: pipeline) } @@ -19,7 +20,9 @@ describe 'User browses a job', :js do expect(page).to have_content("Job ##{build.id}") expect(page).to have_css('#build-trace') - accept_confirm { click_link('Erase') } + # scroll to the top of the page first + execute_script "window.scrollTo(0,0)" + accept_confirm { find('.js-erase-link').click } expect(page).to have_no_css('.artifacts') expect(build).not_to have_trace -- cgit v1.2.3 From d883fe1cce01f53a3acc442e8b94ca20540e0525 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20=C4=8Cupi=C4=87?= Date: Wed, 4 Apr 2018 21:00:32 +0200 Subject: Add success CI Build empty state status --- lib/gitlab/ci/status/build/factory.rb | 3 ++- lib/gitlab/ci/status/build/success.rb | 21 ++++++++++++++++ spec/lib/gitlab/ci/status/build/factory_spec.rb | 16 ++++++++++++ spec/lib/gitlab/ci/status/build/success_spec.rb | 33 +++++++++++++++++++++++++ 4 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 lib/gitlab/ci/status/build/success.rb create mode 100644 spec/lib/gitlab/ci/status/build/success_spec.rb diff --git a/lib/gitlab/ci/status/build/factory.rb b/lib/gitlab/ci/status/build/factory.rb index b809a9cf766..d3a34384f6f 100644 --- a/lib/gitlab/ci/status/build/factory.rb +++ b/lib/gitlab/ci/status/build/factory.rb @@ -8,7 +8,8 @@ module Gitlab Status::Build::Canceled, Status::Build::Created, Status::Build::Pending, - Status::Build::Skipped], + Status::Build::Skipped, + Status::Build::Success], [Status::Build::Cancelable, Status::Build::Retryable], [Status::Build::FailedAllowed, diff --git a/lib/gitlab/ci/status/build/success.rb b/lib/gitlab/ci/status/build/success.rb new file mode 100644 index 00000000000..bafc1b2f93a --- /dev/null +++ b/lib/gitlab/ci/status/build/success.rb @@ -0,0 +1,21 @@ +module Gitlab + module Ci + module Status + module Build + class Success < Status::Extended + def illustration + { + image: 'illustrations/skipped-job_empty.svg', + size: 'svg-430', + title: _('Job has been erased') + } + end + + def self.matches?(build, user) + build.success? + end + end + end + end + end +end diff --git a/spec/lib/gitlab/ci/status/build/factory_spec.rb b/spec/lib/gitlab/ci/status/build/factory_spec.rb index a68fed0a41c..28166d08c02 100644 --- a/spec/lib/gitlab/ci/status/build/factory_spec.rb +++ b/spec/lib/gitlab/ci/status/build/factory_spec.rb @@ -36,6 +36,22 @@ describe Gitlab::Ci::Status::Build::Factory do expect(status).to have_details expect(status).to have_action end + + context 'when job log gets erased' do + before do + build.trace.set(nil) + end + + it 'matches correct extended statuses' do + expect(factory.extended_statuses) + .to eq [Gitlab::Ci::Status::Build::Success, + Gitlab::Ci::Status::Build::Retryable] + end + + it 'fabricates a retryable build status' do + expect(status).to be_a Gitlab::Ci::Status::Build::Retryable + end + end end context 'when build is failed' do diff --git a/spec/lib/gitlab/ci/status/build/success_spec.rb b/spec/lib/gitlab/ci/status/build/success_spec.rb new file mode 100644 index 00000000000..730cd7aefbc --- /dev/null +++ b/spec/lib/gitlab/ci/status/build/success_spec.rb @@ -0,0 +1,33 @@ +require 'spec_helper' + +describe Gitlab::Ci::Status::Build::Success do + let(:user) { create(:user) } + + subject do + described_class.new(double('subject')) + end + + describe '#illustration' do + it { expect(subject.illustration).to include(:image, :size, :title) } + end + + describe '.matches?' do + subject {described_class.matches?(build, user) } + + context 'when build succeeded' do + let(:build) { create(:ci_build, :success) } + + it 'is a correct match' do + expect(subject).to be true + end + end + + context 'when build did not succeed' do + let(:build) { create(:ci_build, :skipped) } + + it 'does not match' do + expect(subject).to be false + end + end + end +end -- cgit v1.2.3 From 00b45348b9dca5c394fa64a7f4975232dc712b5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20=C4=8Cupi=C4=87?= Date: Wed, 4 Apr 2018 22:15:18 +0200 Subject: Fix job setup in success empty state specs --- lib/gitlab/ci/status/build/success.rb | 2 +- spec/lib/gitlab/ci/status/build/factory_spec.rb | 4 ++-- spec/lib/gitlab/ci/status/build/success_spec.rb | 10 ++++++---- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/lib/gitlab/ci/status/build/success.rb b/lib/gitlab/ci/status/build/success.rb index bafc1b2f93a..daf43315c90 100644 --- a/lib/gitlab/ci/status/build/success.rb +++ b/lib/gitlab/ci/status/build/success.rb @@ -12,7 +12,7 @@ module Gitlab end def self.matches?(build, user) - build.success? + !build.has_trace? && build.success? end end end diff --git a/spec/lib/gitlab/ci/status/build/factory_spec.rb b/spec/lib/gitlab/ci/status/build/factory_spec.rb index 28166d08c02..d68d8f6f105 100644 --- a/spec/lib/gitlab/ci/status/build/factory_spec.rb +++ b/spec/lib/gitlab/ci/status/build/factory_spec.rb @@ -13,7 +13,7 @@ describe Gitlab::Ci::Status::Build::Factory do end context 'when build is successful' do - let(:build) { create(:ci_build, :success) } + let(:build) { create(:ci_build, :success, :trace_artifact) } it 'matches correct core status' do expect(factory.core_status).to be_a Gitlab::Ci::Status::Success @@ -39,7 +39,7 @@ describe Gitlab::Ci::Status::Build::Factory do context 'when job log gets erased' do before do - build.trace.set(nil) + build.erase end it 'matches correct extended statuses' do diff --git a/spec/lib/gitlab/ci/status/build/success_spec.rb b/spec/lib/gitlab/ci/status/build/success_spec.rb index 730cd7aefbc..e67ab461463 100644 --- a/spec/lib/gitlab/ci/status/build/success_spec.rb +++ b/spec/lib/gitlab/ci/status/build/success_spec.rb @@ -12,18 +12,20 @@ describe Gitlab::Ci::Status::Build::Success do end describe '.matches?' do - subject {described_class.matches?(build, user) } + subject { described_class.matches?(build, user) } - context 'when build succeeded' do + context 'when build succeeded but does not have trace' do let(:build) { create(:ci_build, :success) } it 'is a correct match' do + build.erase + expect(subject).to be true end end - context 'when build did not succeed' do - let(:build) { create(:ci_build, :skipped) } + context 'when build succeed but has trace' do + let!(:build) { create(:ci_build, :success, :trace_artifact) } it 'does not match' do expect(subject).to be false -- cgit v1.2.3 From 0b1b9c409d3adbf4517351dbb9037ed053f73e67 Mon Sep 17 00:00:00 2001 From: James Ramsay Date: Mon, 19 Feb 2018 15:41:04 -0500 Subject: Add option to suppress archive commit sha Repository archives are always named `--` even if the ref is a commit. A consequence of always including the sha even for tags is that packaging a release is more difficult because both the ref and sha must be known by the packager. - add append_sha option (defaults true) to provide a method for toggling this feature. Support added to GitLab Workhorse by gitlab-org/gitlab-workhorse!232 --- app/helpers/workhorse_helper.rb | 4 ++-- lib/api/helpers.rb | 4 ++-- lib/api/repositories.rb | 2 +- lib/api/v3/repositories.rb | 2 +- lib/gitlab/git/repository.rb | 15 +++++++++++---- lib/gitlab/workhorse.rb | 4 ++-- spec/lib/gitlab/git/repository_spec.rb | 10 ++++++++-- 7 files changed, 27 insertions(+), 14 deletions(-) diff --git a/app/helpers/workhorse_helper.rb b/app/helpers/workhorse_helper.rb index 88f374be1e5..9f78b80c71d 100644 --- a/app/helpers/workhorse_helper.rb +++ b/app/helpers/workhorse_helper.rb @@ -24,8 +24,8 @@ module WorkhorseHelper end # Archive a Git repository and send it through Workhorse - def send_git_archive(repository, ref:, format:) - headers.store(*Gitlab::Workhorse.send_git_archive(repository, ref: ref, format: format)) + def send_git_archive(repository, **kwargs) + headers.store(*Gitlab::Workhorse.send_git_archive(repository, **kwargs)) head :ok end diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb index e59e8a45908..e22d32e4c1b 100644 --- a/lib/api/helpers.rb +++ b/lib/api/helpers.rb @@ -489,8 +489,8 @@ module API header(*Gitlab::Workhorse.send_git_blob(repository, blob)) end - def send_git_archive(repository, ref:, format:) - header(*Gitlab::Workhorse.send_git_archive(repository, ref: ref, format: format)) + def send_git_archive(repository, **kwargs) + header(*Gitlab::Workhorse.send_git_archive(repository, **kwargs)) end def send_artifacts_entry(build, entry) diff --git a/lib/api/repositories.rb b/lib/api/repositories.rb index 9638c53a1df..2396dc73f0e 100644 --- a/lib/api/repositories.rb +++ b/lib/api/repositories.rb @@ -88,7 +88,7 @@ module API end get ':id/repository/archive', requirements: { format: Gitlab::PathRegex.archive_formats_regex } do begin - send_git_archive user_project.repository, ref: params[:sha], format: params[:format] + send_git_archive user_project.repository, ref: params[:sha], format: params[:format], append_sha: true rescue not_found!('File') end diff --git a/lib/api/v3/repositories.rb b/lib/api/v3/repositories.rb index 5b54734bb45..f701d64e886 100644 --- a/lib/api/v3/repositories.rb +++ b/lib/api/v3/repositories.rb @@ -75,7 +75,7 @@ module API end get ':id/repository/archive', requirements: { format: Gitlab::PathRegex.archive_formats_regex } do begin - send_git_archive user_project.repository, ref: params[:sha], format: params[:format] + send_git_archive user_project.repository, ref: params[:sha], format: params[:format], append_sha: true rescue not_found!('File') end diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb index d16a096ffb9..a928a05f03f 100644 --- a/lib/gitlab/git/repository.rb +++ b/lib/gitlab/git/repository.rb @@ -394,17 +394,24 @@ module Gitlab nil end - def archive_prefix(ref, sha) + def archive_prefix(ref, sha, append_sha:) + append_sha = (ref != sha) if append_sha.nil? + project_name = self.name.chomp('.git') - "#{project_name}-#{ref.tr('/', '-')}-#{sha}" + formatted_ref = ref.tr('/', '-') + + prefix_segments = [project_name, formatted_ref] + prefix_segments << sha if append_sha + + prefix_segments.join('-') end - def archive_metadata(ref, storage_path, format = "tar.gz") + def archive_metadata(ref, storage_path, format = "tar.gz", append_sha: true) ref ||= root_ref commit = Gitlab::Git::Commit.find(self, ref) return {} if commit.nil? - prefix = archive_prefix(ref, commit.id) + prefix = archive_prefix(ref, commit.id, append_sha: append_sha) { 'RepoPath' => path, diff --git a/lib/gitlab/workhorse.rb b/lib/gitlab/workhorse.rb index b102812ec12..bdb20060cc0 100644 --- a/lib/gitlab/workhorse.rb +++ b/lib/gitlab/workhorse.rb @@ -63,10 +63,10 @@ module Gitlab ] end - def send_git_archive(repository, ref:, format:) + def send_git_archive(repository, ref:, format:, append_sha: true) format ||= 'tar.gz' format.downcase! - params = repository.archive_metadata(ref, Gitlab.config.gitlab.repository_downloads_path, format) + params = repository.archive_metadata(ref, Gitlab.config.gitlab.repository_downloads_path, format, append_sha) raise "Repository or ref not found" if params.empty? if Gitlab::GitalyClient.feature_enabled?(:workhorse_archive, status: Gitlab::GitalyClient::MigrationStatus::OPT_OUT) diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb index 5cbe2808d0b..2bb8aa69def 100644 --- a/spec/lib/gitlab/git/repository_spec.rb +++ b/spec/lib/gitlab/git/repository_spec.rb @@ -247,16 +247,22 @@ describe Gitlab::Git::Repository, seed_helper: true do end it 'returns parameterised string for a ref containing slashes' do - prefix = repository.archive_prefix('test/branch', 'SHA') + prefix = repository.archive_prefix('test/branch', 'SHA', append_sha: true) expect(prefix).to eq("#{project_name}-test-branch-SHA") end it 'returns correct string for a ref containing dots' do - prefix = repository.archive_prefix('test.branch', 'SHA') + prefix = repository.archive_prefix('test.branch', 'SHA', append_sha: true) expect(prefix).to eq("#{project_name}-test.branch-SHA") end + + it 'returns string with sha when append_sha is false' do + prefix = repository.archive_prefix('test.branch', 'SHA', append_sha: false) + + expect(prefix).to eq("#{project_name}-test.branch") + end end describe '#archive' do -- cgit v1.2.3 From 10143937c1fdfe2ef4628f32a1e87ca564233d17 Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Thu, 5 Apr 2018 13:54:41 +0530 Subject: Add page helper methods for notesApp --- app/assets/javascripts/lib/utils/dom_utils.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/assets/javascripts/lib/utils/dom_utils.js b/app/assets/javascripts/lib/utils/dom_utils.js index de65ea15a60..914de9de940 100644 --- a/app/assets/javascripts/lib/utils/dom_utils.js +++ b/app/assets/javascripts/lib/utils/dom_utils.js @@ -1,7 +1,12 @@ -/* eslint-disable import/prefer-default-export */ +import $ from 'jquery'; +import { isInIssuePage, isInMRPage, isInEpicPage, hasVueMRDiscussionsCookie } from './common_utils'; + +const isVueMRDiscussions = () => isInMRPage() && hasVueMRDiscussionsCookie() && !$('#diffs').is(':visible'); export const addClassIfElementExists = (element, className) => { if (element) { element.classList.add(className); } }; + +export const isInVueNoteablePage = () => isInIssuePage() || isInEpicPage() || isVueMRDiscussions(); -- cgit v1.2.3 From 1f27c6382510c91a129715642f146531b1074544 Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Thu, 5 Apr 2018 13:54:59 +0530 Subject: Use `isInVueNoteablePage` from dom_utils --- app/assets/javascripts/awards_handler.js | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/app/assets/javascripts/awards_handler.js b/app/assets/javascripts/awards_handler.js index 0e1ca7fe883..976d32abe9b 100644 --- a/app/assets/javascripts/awards_handler.js +++ b/app/assets/javascripts/awards_handler.js @@ -4,7 +4,8 @@ import $ from 'jquery'; import _ from 'underscore'; import Cookies from 'js-cookie'; import { __ } from './locale'; -import { isInIssuePage, isInMRPage, isInEpicPage, hasVueMRDiscussionsCookie, updateTooltipTitle } from './lib/utils/common_utils'; +import { updateTooltipTitle } from './lib/utils/common_utils'; +import { isInVueNoteablePage } from './lib/utils/dom_utils'; import flash from './flash'; import axios from './lib/utils/axios_utils'; @@ -243,7 +244,7 @@ class AwardsHandler { addAward(votesBlock, awardUrl, emoji, checkMutuality, callback) { const isMainAwardsBlock = votesBlock.closest('.js-noteable-awards').length; - if (this.isInVueNoteablePage() && !isMainAwardsBlock) { + if (isInVueNoteablePage() && !isMainAwardsBlock) { const id = votesBlock.attr('id').replace('note_', ''); this.hideMenuElement($('.emoji-menu')); @@ -295,16 +296,8 @@ class AwardsHandler { } } - isVueMRDiscussions() { - return isInMRPage() && hasVueMRDiscussionsCookie() && !$('#diffs').is(':visible'); - } - - isInVueNoteablePage() { - return isInIssuePage() || isInEpicPage() || this.isVueMRDiscussions(); - } - getVotesBlock() { - if (this.isInVueNoteablePage()) { + if (isInVueNoteablePage()) { const $el = $('.js-add-award.is-active').closest('.note.timeline-entry'); if ($el.length) { -- cgit v1.2.3 From 1db4ea20c6ce67559a5c28b6b423abe292354dd8 Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Thu, 5 Apr 2018 13:55:34 +0530 Subject: Set noteableType on noteableData as provided from DOM dataset --- app/assets/javascripts/mr_notes/index.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/assets/javascripts/mr_notes/index.js b/app/assets/javascripts/mr_notes/index.js index 096c4ef5f31..e3c5bf06b3d 100644 --- a/app/assets/javascripts/mr_notes/index.js +++ b/app/assets/javascripts/mr_notes/index.js @@ -13,8 +13,11 @@ export default function initMrNotes() { data() { const notesDataset = document.getElementById('js-vue-mr-discussions') .dataset; + const noteableData = JSON.parse(notesDataset.noteableData); + noteableData.noteableType = notesDataset.noteableType; + return { - noteableData: JSON.parse(notesDataset.noteableData), + noteableData, currentUserData: JSON.parse(notesDataset.currentUserData), notesData: JSON.parse(notesDataset.notesData), }; -- cgit v1.2.3 From 02968711128d4bd8939467181504cbe314274cc2 Mon Sep 17 00:00:00 2001 From: Winnie Hellmann Date: Thu, 5 Apr 2018 10:19:55 +0200 Subject: Use template strings in search_autocomplete_spec.js --- spec/javascripts/search_autocomplete_spec.js | 214 ++++++++++++++------------- 1 file changed, 110 insertions(+), 104 deletions(-) diff --git a/spec/javascripts/search_autocomplete_spec.js b/spec/javascripts/search_autocomplete_spec.js index ac47f14ab46..1a27955983d 100644 --- a/spec/javascripts/search_autocomplete_spec.js +++ b/spec/javascripts/search_autocomplete_spec.js @@ -6,8 +6,21 @@ import SearchAutocomplete from '~/search_autocomplete'; import '~/lib/utils/common_utils'; import * as urlUtils from '~/lib/utils/url_utility'; -(function() { - var assertLinks, dashboardIssuesPath, dashboardMRsPath, groupIssuesPath, groupMRsPath, groupName, mockDashboardOptions, mockGroupOptions, mockProjectOptions, projectIssuesPath, projectMRsPath, projectName, userId, widget; +describe('Search autocomplete dropdown', () => { + var assertLinks, + dashboardIssuesPath, + dashboardMRsPath, + groupIssuesPath, + groupMRsPath, + groupName, + mockDashboardOptions, + mockGroupOptions, + mockProjectOptions, + projectIssuesPath, + projectMRsPath, + projectName, + userId, + widget; var userName = 'root'; widget = null; @@ -66,133 +79,126 @@ import * as urlUtils from '~/lib/utils/url_utility'; // Mock `gl` object in window for dashboard specific page. App code will need it. mockDashboardOptions = function() { window.gl || (window.gl = {}); - return window.gl.dashboardOptions = { + return (window.gl.dashboardOptions = { issuesPath: dashboardIssuesPath, - mrPath: dashboardMRsPath - }; + mrPath: dashboardMRsPath, + }); }; // Mock `gl` object in window for project specific page. App code will need it. mockProjectOptions = function() { window.gl || (window.gl = {}); - return window.gl.projectOptions = { + return (window.gl.projectOptions = { 'gitlab-ce': { issuesPath: projectIssuesPath, mrPath: projectMRsPath, - projectName: projectName - } - }; + projectName: projectName, + }, + }); }; mockGroupOptions = function() { window.gl || (window.gl = {}); - return window.gl.groupOptions = { + return (window.gl.groupOptions = { 'gitlab-org': { issuesPath: groupIssuesPath, mrPath: groupMRsPath, - projectName: groupName - } - }; + projectName: groupName, + }, + }); }; assertLinks = function(list, issuesPath, mrsPath) { - var a1, a2, a3, a4, issuesAssignedToMeLink, issuesIHaveCreatedLink, mrsAssignedToMeLink, mrsIHaveCreatedLink; if (issuesPath) { - issuesAssignedToMeLink = issuesPath + "/?assignee_id=" + userId; - issuesIHaveCreatedLink = issuesPath + "/?author_id=" + userId; - a1 = "a[href='" + issuesAssignedToMeLink + "']"; - a2 = "a[href='" + issuesIHaveCreatedLink + "']"; - expect(list.find(a1).length).toBe(1); - expect(list.find(a1).text()).toBe('Issues assigned to me'); - expect(list.find(a2).length).toBe(1); - expect(list.find(a2).text()).toBe("Issues I've created"); + const issuesAssignedToMeLink = `a[href="${issuesPath}/?assignee_id=${userId}"]`; + const issuesIHaveCreatedLink = `a[href="${issuesPath}/?author_id=${userId}"]`; + expect(list.find(issuesAssignedToMeLink).length).toBe(1); + expect(list.find(issuesAssignedToMeLink).text()).toBe('Issues assigned to me'); + expect(list.find(issuesIHaveCreatedLink).length).toBe(1); + expect(list.find(issuesIHaveCreatedLink).text()).toBe("Issues I've created"); } - mrsAssignedToMeLink = mrsPath + "/?assignee_id=" + userId; - mrsIHaveCreatedLink = mrsPath + "/?author_id=" + userId; - a3 = "a[href='" + mrsAssignedToMeLink + "']"; - a4 = "a[href='" + mrsIHaveCreatedLink + "']"; - expect(list.find(a3).length).toBe(1); - expect(list.find(a3).text()).toBe('Merge requests assigned to me'); - expect(list.find(a4).length).toBe(1); - return expect(list.find(a4).text()).toBe("Merge requests I've created"); + const mrsAssignedToMeLink = `a[href="${mrsPath}/?assignee_id=${userId}"]`; + const mrsIHaveCreatedLink = `a[href="${mrsPath}/?author_id=${userId}"]`; + expect(list.find(mrsAssignedToMeLink).length).toBe(1); + expect(list.find(mrsAssignedToMeLink).text()).toBe('Merge requests assigned to me'); + expect(list.find(mrsIHaveCreatedLink).length).toBe(1); + expect(list.find(mrsIHaveCreatedLink).text()).toBe("Merge requests I've created"); }; - describe('Search autocomplete dropdown', function() { - preloadFixtures('static/search_autocomplete.html.raw'); - beforeEach(function() { - loadFixtures('static/search_autocomplete.html.raw'); + preloadFixtures('static/search_autocomplete.html.raw'); + beforeEach(function() { + loadFixtures('static/search_autocomplete.html.raw'); - // Prevent turbolinks from triggering within gl_dropdown - spyOn(urlUtils, 'visitUrl').and.returnValue(true); + // Prevent turbolinks from triggering within gl_dropdown + spyOn(urlUtils, 'visitUrl').and.returnValue(true); - window.gon = {}; - window.gon.current_user_id = userId; - window.gon.current_username = userName; + window.gon = {}; + window.gon.current_user_id = userId; + window.gon.current_username = userName; - return widget = new SearchAutocomplete(); - }); + return (widget = new SearchAutocomplete()); + }); - afterEach(function() { - // Undo what we did to the shared - removeBodyAttributes(); - window.gon = {}; - }); - it('should show Dashboard specific dropdown menu', function() { - var list; - addBodyAttributes(); - mockDashboardOptions(); - widget.searchInput.triggerHandler('focus'); - list = widget.wrap.find('.dropdown-menu').find('ul'); - return assertLinks(list, dashboardIssuesPath, dashboardMRsPath); - }); - it('should show Group specific dropdown menu', function() { - var list; - addBodyAttributes('group'); - mockGroupOptions(); - widget.searchInput.triggerHandler('focus'); - list = widget.wrap.find('.dropdown-menu').find('ul'); - return assertLinks(list, groupIssuesPath, groupMRsPath); - }); - it('should show Project specific dropdown menu', function() { - var list; - addBodyAttributes('project'); - mockProjectOptions(); - widget.searchInput.triggerHandler('focus'); - list = widget.wrap.find('.dropdown-menu').find('ul'); - return assertLinks(list, projectIssuesPath, projectMRsPath); - }); - it('should show only Project mergeRequest dropdown menu items when project issues are disabled', function() { - addBodyAttributes('project'); - disableProjectIssues(); - mockProjectOptions(); - widget.searchInput.triggerHandler('focus'); - const list = widget.wrap.find('.dropdown-menu').find('ul'); - assertLinks(list, null, projectMRsPath); - }); - it('should not show category related menu if there is text in the input', function() { - var link, list; - addBodyAttributes('project'); - mockProjectOptions(); - widget.searchInput.val('help'); - widget.searchInput.triggerHandler('focus'); - list = widget.wrap.find('.dropdown-menu').find('ul'); - link = "a[href='" + projectIssuesPath + "/?assignee_id=" + userId + "']"; - return expect(list.find(link).length).toBe(0); - }); - return it('should not submit the search form when selecting an autocomplete row with the keyboard', function() { - var ENTER = 13; - var DOWN = 40; - addBodyAttributes(); - mockDashboardOptions(true); - var submitSpy = spyOnEvent('form', 'submit'); - widget.searchInput.triggerHandler('focus'); - widget.wrap.trigger($.Event('keydown', { which: DOWN })); - var enterKeyEvent = $.Event('keydown', { which: ENTER }); - widget.searchInput.trigger(enterKeyEvent); - // This does not currently catch failing behavior. For security reasons, - // browsers will not trigger default behavior (form submit, in this - // example) on JavaScript-created keypresses. - expect(submitSpy).not.toHaveBeenTriggered(); - }); + afterEach(function() { + // Undo what we did to the shared + removeBodyAttributes(); + window.gon = {}; + }); + it('should show Dashboard specific dropdown menu', function() { + var list; + addBodyAttributes(); + mockDashboardOptions(); + widget.searchInput.triggerHandler('focus'); + list = widget.wrap.find('.dropdown-menu').find('ul'); + return assertLinks(list, dashboardIssuesPath, dashboardMRsPath); + }); + it('should show Group specific dropdown menu', function() { + var list; + addBodyAttributes('group'); + mockGroupOptions(); + widget.searchInput.triggerHandler('focus'); + list = widget.wrap.find('.dropdown-menu').find('ul'); + return assertLinks(list, groupIssuesPath, groupMRsPath); + }); + it('should show Project specific dropdown menu', function() { + var list; + addBodyAttributes('project'); + mockProjectOptions(); + widget.searchInput.triggerHandler('focus'); + list = widget.wrap.find('.dropdown-menu').find('ul'); + return assertLinks(list, projectIssuesPath, projectMRsPath); + }); + it('should show only Project mergeRequest dropdown menu items when project issues are disabled', function() { + addBodyAttributes('project'); + disableProjectIssues(); + mockProjectOptions(); + widget.searchInput.triggerHandler('focus'); + const list = widget.wrap.find('.dropdown-menu').find('ul'); + assertLinks(list, null, projectMRsPath); + }); + it('should not show category related menu if there is text in the input', function() { + var link, list; + addBodyAttributes('project'); + mockProjectOptions(); + widget.searchInput.val('help'); + widget.searchInput.triggerHandler('focus'); + list = widget.wrap.find('.dropdown-menu').find('ul'); + link = "a[href='" + projectIssuesPath + '/?assignee_id=' + userId + "']"; + return expect(list.find(link).length).toBe(0); + }); + it('should not submit the search form when selecting an autocomplete row with the keyboard', function() { + var ENTER = 13; + var DOWN = 40; + addBodyAttributes(); + mockDashboardOptions(true); + var submitSpy = spyOnEvent('form', 'submit'); + widget.searchInput.triggerHandler('focus'); + widget.wrap.trigger($.Event('keydown', { which: DOWN })); + var enterKeyEvent = $.Event('keydown', { which: ENTER }); + widget.searchInput.trigger(enterKeyEvent); + // This does not currently catch failing behavior. For security reasons, + // browsers will not trigger default behavior (form submit, in this + // example) on JavaScript-created keypresses. + expect(submitSpy).not.toHaveBeenTriggered(); }); -}).call(window); +}); -- cgit v1.2.3 From 323bac4a6e1de5d9ba9c1cb3a2868f514888c44a Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Thu, 5 Apr 2018 11:30:02 +0200 Subject: Improve docs about pipeline variables expressions --- doc/ci/variables/README.md | 55 ++++++++++++++++++++++++++++++++++++---------- doc/ci/yaml/README.md | 3 ++- 2 files changed, 46 insertions(+), 12 deletions(-) diff --git a/doc/ci/variables/README.md b/doc/ci/variables/README.md index 9f268f47e6f..381405a9db9 100644 --- a/doc/ci/variables/README.md +++ b/doc/ci/variables/README.md @@ -454,8 +454,8 @@ export CI_REGISTRY_PASSWORD="longalfanumstring" > Variables expressions were added in GitLab 10.7. It is possible to use variables expressions with only / except policies in -`.gitlab-ci.yml`. By using this approach you can limit what builds are going to -be created within a pipeline after pushing code to GitLab. +`.gitlab-ci.yml`. By using this approach you can limit what jobs are going to +be created within a pipeline after pushing a code to GitLab. This is particularly useful in combination with secret variables and triggered pipeline variables. @@ -470,22 +470,21 @@ deploy: - $STAGING ``` -Each provided variables expression is going to be evaluated before creating -a pipeline. +Each expression provided is going to be evaluated before creating a pipeline. If any of the conditions in `variables` evaluates to truth when using `only`, a new job is going to be created. If any of the expressions evaluates to truth when `except` is being used, a job is not going to be created. -This follows usual rules for `only` / `except` policies. +This follows usual rules for [`only` / `except` policies][builds-policies]. ### Supported syntax -Below you can find currently supported syntax reference: +Below you can find supported syntax reference: 1. Equality matching using a string - Example: `$VARIABLE == "some value"` + > Example: `$VARIABLE == "some value"` You can use equality operator `==` to compare a variable content to a string. We support both, double quotes and single quotes to define a string @@ -494,26 +493,59 @@ Below you can find currently supported syntax reference: 1. Checking for an undefined value - It sometimes happens that you want to check whether variable is defined or - not. To do that, you can compare variable to `null` value, like + > Example: `$VARIABLE == null` + + It sometimes happens that you want to check whether a variable is defined + or not. To do that, you can compare a variable to `null` keyword, like `$VARIABLE == null`. This expression is going to evaluate to truth if - variable is not set. + variable is not defined. 1. Checking for an empty variable + > Example: `$VARIABLE == ""` + If you want to check whether a variable is defined, but is empty, you can simply compare it against an empty string, like `$VAR == ''`. 1. Comparing two variables - It is possible to compare two variables. `$VARIABLE_1 == $VARIABLE_2`. + > Example: `$VARIABLE_1 == $VARIABLE_2` + + It is possible to compare two variables. This is going to compare values + of these variables. 1. Variable presence check + > Example: `$STAGING` + If you only want to create a job when there is some variable present, which means that it is defined and non-empty, you can simply use variable name as an expression, like `$STAGING`. If `$STAGING` variable is defined, and is non empty, expression will evaluate to truth. + `$STAGING` value needs to a string, with length higher than zero. + Variable that contains only whitespace characters is not an empty variable. + +### Unsupported predefined variables + +Because GitLab evaluates variables before creating jobs, we do not support a +few variables that depend on persistence layer, like `$CI_JOB_ID`. + +Environments (like `production` or `staging`) are also being created based on +what jobs pipeline consists of, thus some environment-specific variables are +not supported as well. + +We do not support variables containing tokens because of security reasons. + +You can find a full list of unsupported variables below: + +- `CI_JOB_ID` +- `CI_JOB_TOKEN` +- `CI_BUILD_ID` +- `CI_BUILD_TOKEN` +- `CI_REGISTRY_USER` +- `CI_REGISTRY_PASSWORD` +- `CI_REPOSITORY_URL` +- `CI_ENVIRONMENT_URL` [ce-13784]: https://gitlab.com/gitlab-org/gitlab-ce/issues/13784 "Simple protection of CI secret variables" [eep]: https://about.gitlab.com/products/ "Available only in GitLab Premium" @@ -525,3 +557,4 @@ Below you can find currently supported syntax reference: [triggered]: ../triggers/README.md [triggers]: ../triggers/README.md#pass-job-variables-to-a-trigger [subgroups]: ../../user/group/subgroups/index.md +[builds-policies]: ../yaml/README.md#only-and-except-complex diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md index be114e7008e..68aa64b3834 100644 --- a/doc/ci/yaml/README.md +++ b/doc/ci/yaml/README.md @@ -354,7 +354,7 @@ deploy: - $STAGING ``` -Learn more about variables expressions on a separate page. +Learn more about variables expressions on [a separate page][variables-expressions]. ## `tags` @@ -1574,3 +1574,4 @@ CI with various languages. [ce-7447]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7447 [ce-12909]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/12909 [schedules]: ../../user/project/pipelines/schedules.md +[variables-expressions]: ../variables/README.md#variables-expressions -- cgit v1.2.3 From f379e1b370d033097c1d0102401eb6156384890c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20=C4=8Cupi=C4=87?= Date: Thu, 5 Apr 2018 13:52:54 +0200 Subject: Rename success to erased empty state spec --- lib/gitlab/ci/status/build/erased.rb | 21 +++++++++++++++ lib/gitlab/ci/status/build/factory.rb | 2 +- lib/gitlab/ci/status/build/success.rb | 21 --------------- spec/lib/gitlab/ci/status/build/erased_spec.rb | 33 +++++++++++++++++++++++ spec/lib/gitlab/ci/status/build/factory_spec.rb | 35 ++++++++++++++++--------- spec/lib/gitlab/ci/status/build/success_spec.rb | 35 ------------------------- 6 files changed, 78 insertions(+), 69 deletions(-) create mode 100644 lib/gitlab/ci/status/build/erased.rb delete mode 100644 lib/gitlab/ci/status/build/success.rb create mode 100644 spec/lib/gitlab/ci/status/build/erased_spec.rb delete mode 100644 spec/lib/gitlab/ci/status/build/success_spec.rb diff --git a/lib/gitlab/ci/status/build/erased.rb b/lib/gitlab/ci/status/build/erased.rb new file mode 100644 index 00000000000..3a5113b16b6 --- /dev/null +++ b/lib/gitlab/ci/status/build/erased.rb @@ -0,0 +1,21 @@ +module Gitlab + module Ci + module Status + module Build + class Erased < Status::Extended + def illustration + { + image: 'illustrations/skipped-job_empty.svg', + size: 'svg-430', + title: _('Job has been erased') + } + end + + def self.matches?(build, user) + build.erased? + end + end + end + end + end +end diff --git a/lib/gitlab/ci/status/build/factory.rb b/lib/gitlab/ci/status/build/factory.rb index d3a34384f6f..466a0a989ad 100644 --- a/lib/gitlab/ci/status/build/factory.rb +++ b/lib/gitlab/ci/status/build/factory.rb @@ -9,7 +9,7 @@ module Gitlab Status::Build::Created, Status::Build::Pending, Status::Build::Skipped, - Status::Build::Success], + Status::Build::Erased], [Status::Build::Cancelable, Status::Build::Retryable], [Status::Build::FailedAllowed, diff --git a/lib/gitlab/ci/status/build/success.rb b/lib/gitlab/ci/status/build/success.rb deleted file mode 100644 index daf43315c90..00000000000 --- a/lib/gitlab/ci/status/build/success.rb +++ /dev/null @@ -1,21 +0,0 @@ -module Gitlab - module Ci - module Status - module Build - class Success < Status::Extended - def illustration - { - image: 'illustrations/skipped-job_empty.svg', - size: 'svg-430', - title: _('Job has been erased') - } - end - - def self.matches?(build, user) - !build.has_trace? && build.success? - end - end - end - end - end -end diff --git a/spec/lib/gitlab/ci/status/build/erased_spec.rb b/spec/lib/gitlab/ci/status/build/erased_spec.rb new file mode 100644 index 00000000000..0acd271e375 --- /dev/null +++ b/spec/lib/gitlab/ci/status/build/erased_spec.rb @@ -0,0 +1,33 @@ +require 'spec_helper' + +describe Gitlab::Ci::Status::Build::Erased do + let(:user) { create(:user) } + + subject do + described_class.new(double('subject')) + end + + describe '#illustration' do + it { expect(subject.illustration).to include(:image, :size, :title) } + end + + describe '.matches?' do + subject { described_class.matches?(build, user) } + + context 'when build is erased' do + let(:build) { create(:ci_build, :success, :erased) } + + it 'is a correct match' do + expect(subject).to be true + end + end + + context 'when build is not erased' do + let(:build) { create(:ci_build, :success, :trace_artifact) } + + it 'does not match' do + expect(subject).to be false + end + end + end +end diff --git a/spec/lib/gitlab/ci/status/build/factory_spec.rb b/spec/lib/gitlab/ci/status/build/factory_spec.rb index d68d8f6f105..94eedc50bb2 100644 --- a/spec/lib/gitlab/ci/status/build/factory_spec.rb +++ b/spec/lib/gitlab/ci/status/build/factory_spec.rb @@ -36,21 +36,32 @@ describe Gitlab::Ci::Status::Build::Factory do expect(status).to have_details expect(status).to have_action end + end - context 'when job log gets erased' do - before do - build.erase - end + context 'when build is erased' do + let(:build) { create(:ci_build, :success, :erased) } - it 'matches correct extended statuses' do - expect(factory.extended_statuses) - .to eq [Gitlab::Ci::Status::Build::Success, - Gitlab::Ci::Status::Build::Retryable] - end + it 'matches correct core status' do + expect(factory.core_status).to be_a Gitlab::Ci::Status::Success + end - it 'fabricates a retryable build status' do - expect(status).to be_a Gitlab::Ci::Status::Build::Retryable - end + it 'matches correct extended statuses' do + expect(factory.extended_statuses) + .to eq [Gitlab::Ci::Status::Build::Erased, + Gitlab::Ci::Status::Build::Retryable] + end + + it 'fabricates a retryable build status' do + expect(status).to be_a Gitlab::Ci::Status::Build::Retryable + end + + it 'fabricates status with correct details' do + expect(status.text).to eq 'passed' + expect(status.icon).to eq 'status_success' + expect(status.favicon).to eq 'favicon_status_success' + expect(status.label).to eq 'passed' + expect(status).to have_details + expect(status).to have_action end end diff --git a/spec/lib/gitlab/ci/status/build/success_spec.rb b/spec/lib/gitlab/ci/status/build/success_spec.rb deleted file mode 100644 index e67ab461463..00000000000 --- a/spec/lib/gitlab/ci/status/build/success_spec.rb +++ /dev/null @@ -1,35 +0,0 @@ -require 'spec_helper' - -describe Gitlab::Ci::Status::Build::Success do - let(:user) { create(:user) } - - subject do - described_class.new(double('subject')) - end - - describe '#illustration' do - it { expect(subject.illustration).to include(:image, :size, :title) } - end - - describe '.matches?' do - subject { described_class.matches?(build, user) } - - context 'when build succeeded but does not have trace' do - let(:build) { create(:ci_build, :success) } - - it 'is a correct match' do - build.erase - - expect(subject).to be true - end - end - - context 'when build succeed but has trace' do - let!(:build) { create(:ci_build, :success, :trace_artifact) } - - it 'does not match' do - expect(subject).to be false - end - end - end -end -- cgit v1.2.3 From 99edc15127d9d23475c94079d53e2893f58c042a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20=C4=8Cupi=C4=87?= Date: Thu, 5 Apr 2018 17:32:03 +0200 Subject: Put Erased empty state at the beginning --- lib/gitlab/ci/status/build/factory.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/gitlab/ci/status/build/factory.rb b/lib/gitlab/ci/status/build/factory.rb index 466a0a989ad..9d2d4170266 100644 --- a/lib/gitlab/ci/status/build/factory.rb +++ b/lib/gitlab/ci/status/build/factory.rb @@ -4,12 +4,12 @@ module Gitlab module Build class Factory < Status::Factory def self.extended_statuses - [[Status::Build::Manual, + [[Status::Build::Erased, + Status::Build::Manual, Status::Build::Canceled, Status::Build::Created, Status::Build::Pending, - Status::Build::Skipped, - Status::Build::Erased], + Status::Build::Skipped], [Status::Build::Cancelable, Status::Build::Retryable], [Status::Build::FailedAllowed, -- cgit v1.2.3 From 33c163b347ca37ae91240be40a05c881c89c7135 Mon Sep 17 00:00:00 2001 From: Nathan Jones Date: Mon, 10 Jul 2017 23:33:08 +0000 Subject: Update index.md to describe leaving out the host in prometheus['listen_address'] to allow public access. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- doc/administration/monitoring/prometheus/index.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/doc/administration/monitoring/prometheus/index.md b/doc/administration/monitoring/prometheus/index.md index f43c89dad87..3d24812c66a 100644 --- a/doc/administration/monitoring/prometheus/index.md +++ b/doc/administration/monitoring/prometheus/index.md @@ -62,7 +62,14 @@ To change the address/port that Prometheus listens on: ``` Replace `localhost:9090` with the address/port you want Prometheus to - listen on. + listen on. If you would like to allow access to Prometheus to hosts other + than `localhost`, leave out the host, or use `0.0.0.0` to allow public access: + + ```ruby + prometheus['listen_address'] = ':9090' + # or + prometheus['listen_address'] = '0.0.0.0:9090' + ``` 1. Save the file and [reconfigure GitLab][reconfigure] for the changes to take effect -- cgit v1.2.3 From 22423d284704c3ec2f7715736a75155d14ff413d Mon Sep 17 00:00:00 2001 From: Felipe Artur Date: Wed, 4 Apr 2018 18:43:33 -0300 Subject: Show issues of subgroups in group-level issue board --- .../javascripts/boards/components/board_sidebar.js | 6 +----- .../boards/components/issue_card_inner.js | 13 ++--------- .../boards/components/sidebar/remove_issue.js | 6 +----- .../javascripts/boards/filtered_search_boards.js | 1 + app/assets/javascripts/boards/models/issue.js | 6 ++++-- app/controllers/boards/issues_controller.rb | 3 ++- app/controllers/groups/milestones_controller.rb | 2 +- app/models/issue.rb | 12 ++++++++--- app/services/boards/issues/list_service.rb | 5 +++++ app/services/issuable_base_service.rb | 3 ++- .../shared/boards/components/_sidebar.html.haml | 2 +- .../boards/components/sidebar/_assignee.html.haml | 3 +-- .../boards/components/sidebar/_due_date.html.haml | 3 +-- .../boards/components/sidebar/_labels.html.haml | 3 +-- .../boards/components/sidebar/_milestone.html.haml | 3 +-- changelogs/unreleased/issue_44270.yml | 5 +++++ spec/features/labels_hierarchy_spec.rb | 6 ++++-- spec/services/boards/issues/list_service_spec.rb | 25 +++++++++++++++++----- 18 files changed, 62 insertions(+), 45 deletions(-) create mode 100644 changelogs/unreleased/issue_44270.yml diff --git a/app/assets/javascripts/boards/components/board_sidebar.js b/app/assets/javascripts/boards/components/board_sidebar.js index a44969272a1..c4ee4f6c855 100644 --- a/app/assets/javascripts/boards/components/board_sidebar.js +++ b/app/assets/javascripts/boards/components/board_sidebar.js @@ -60,10 +60,6 @@ gl.issueBoards.BoardSidebar = Vue.extend({ this.issue = this.detail.issue; this.list = this.detail.list; - - this.$nextTick(() => { - this.endpoint = this.$refs.assigneeDropdown.dataset.issueUpdate; - }); }, deep: true }, @@ -91,7 +87,7 @@ gl.issueBoards.BoardSidebar = Vue.extend({ saveAssignees () { this.loadingAssignees = true; - gl.issueBoards.BoardsStore.detail.issue.update(this.endpoint) + gl.issueBoards.BoardsStore.detail.issue.update() .then(() => { this.loadingAssignees = false; }) diff --git a/app/assets/javascripts/boards/components/issue_card_inner.js b/app/assets/javascripts/boards/components/issue_card_inner.js index 8aee5b23c76..84fe9b1288a 100644 --- a/app/assets/javascripts/boards/components/issue_card_inner.js +++ b/app/assets/javascripts/boards/components/issue_card_inner.js @@ -68,15 +68,6 @@ gl.issueBoards.IssueCardInner = Vue.extend({ return this.issue.assignees.length > this.numberOverLimit; }, - cardUrl() { - let baseUrl = this.issueLinkBase; - - if (this.groupId && this.issue.project) { - baseUrl = this.issueLinkBase.replace(':project_path', this.issue.project.path); - } - - return `${baseUrl}/${this.issue.iid}`; - }, issueId() { if (this.issue.iid) { return `#${this.issue.iid}`; @@ -153,13 +144,13 @@ gl.issueBoards.IssueCardInner = Vue.extend({ /> {{ issue.title }} - {{ issueId }} + {{ issue.referencePath }}
diff --git a/app/assets/javascripts/boards/components/sidebar/remove_issue.js b/app/assets/javascripts/boards/components/sidebar/remove_issue.js index 09c683ff621..0a0820ec5fd 100644 --- a/app/assets/javascripts/boards/components/sidebar/remove_issue.js +++ b/app/assets/javascripts/boards/components/sidebar/remove_issue.js @@ -17,14 +17,10 @@ gl.issueBoards.RemoveIssueBtn = Vue.extend({ type: Object, required: true, }, - issueUpdate: { - type: String, - required: true, - }, }, computed: { updateUrl() { - return this.issueUpdate.replace(':project_path', this.issue.project.path); + return this.issue.path; }, }, methods: { diff --git a/app/assets/javascripts/boards/filtered_search_boards.js b/app/assets/javascripts/boards/filtered_search_boards.js index fb40b9f5565..70367c4f711 100644 --- a/app/assets/javascripts/boards/filtered_search_boards.js +++ b/app/assets/javascripts/boards/filtered_search_boards.js @@ -6,6 +6,7 @@ export default class FilteredSearchBoards extends FilteredSearchManager { constructor(store, updateUrl = false, cantEdit = []) { super({ page: 'boards', + isGroupDecendent: true, stateFiltersSelector: '.issues-state-filters', }); diff --git a/app/assets/javascripts/boards/models/issue.js b/app/assets/javascripts/boards/models/issue.js index 4c5079efc8b..85f98615cf4 100644 --- a/app/assets/javascripts/boards/models/issue.js +++ b/app/assets/javascripts/boards/models/issue.js @@ -23,6 +23,8 @@ class ListIssue { }; this.isLoading = {}; this.sidebarInfoEndpoint = obj.issue_sidebar_endpoint; + this.referencePath = obj.reference_path; + this.path = obj.real_path; this.toggleSubscriptionEndpoint = obj.toggle_subscription_endpoint; this.milestone_id = obj.milestone_id; this.project_id = obj.project_id; @@ -98,7 +100,7 @@ class ListIssue { this.isLoading[key] = value; } - update (url) { + update () { const data = { issue: { milestone_id: this.milestone ? this.milestone.id : null, @@ -113,7 +115,7 @@ class ListIssue { } const projectPath = this.project ? this.project.path : ''; - return Vue.http.patch(url.replace(':project_path', projectPath), data); + return Vue.http.patch(this.path + '.json', data); } } diff --git a/app/controllers/boards/issues_controller.rb b/app/controllers/boards/issues_controller.rb index 19dbee84c11..7d7ff217e5d 100644 --- a/app/controllers/boards/issues_controller.rb +++ b/app/controllers/boards/issues_controller.rb @@ -96,7 +96,8 @@ module Boards resource.as_json( only: [:id, :iid, :project_id, :title, :confidential, :due_date, :relative_position], labels: true, - sidebar_endpoints: true, + issue_endpoints: true, + include_full_project_path: board.group_board?, include: { project: { only: [:id, :path] }, assignees: { only: [:id, :name, :username], methods: [:avatar_url] }, diff --git a/app/controllers/groups/milestones_controller.rb b/app/controllers/groups/milestones_controller.rb index acf6aaf57f4..5903689dc62 100644 --- a/app/controllers/groups/milestones_controller.rb +++ b/app/controllers/groups/milestones_controller.rb @@ -12,7 +12,7 @@ class Groups::MilestonesController < Groups::ApplicationController @milestones = Kaminari.paginate_array(milestones).page(params[:page]) end format.json do - render json: milestones.map { |m| m.for_display.slice(:title, :name) } + render json: milestones.map { |m| m.for_display.slice(:id, :title, :name) } end end end diff --git a/app/models/issue.rb b/app/models/issue.rb index 13abc6c1a0d..13d9e42bcc8 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -272,11 +272,17 @@ class Issue < ActiveRecord::Base def as_json(options = {}) super(options).tap do |json| - if options.key?(:sidebar_endpoints) && project + if options.key?(:issue_endpoints) && project url_helper = Gitlab::Routing.url_helpers - json.merge!(issue_sidebar_endpoint: url_helper.project_issue_path(project, self, format: :json, serializer: 'sidebar'), - toggle_subscription_endpoint: url_helper.toggle_subscription_project_issue_path(project, self)) + issue_reference = options[:include_full_project_path] ? to_reference(full: true) : to_reference + + json.merge!( + reference_path: issue_reference, + real_path: url_helper.project_issue_path(project, self), + issue_sidebar_endpoint: url_helper.project_issue_path(project, self, format: :json, serializer: 'sidebar'), + toggle_subscription_endpoint: url_helper.toggle_subscription_project_issue_path(project, self) + ) end if options.key?(:labels) diff --git a/app/services/boards/issues/list_service.rb b/app/services/boards/issues/list_service.rb index ecd74b74f8a..8a1796a1096 100644 --- a/app/services/boards/issues/list_service.rb +++ b/app/services/boards/issues/list_service.rb @@ -35,6 +35,7 @@ module Boards def filter_params set_parent set_state + set_scope params end @@ -51,6 +52,10 @@ module Boards params[:state] = list && list.closed? ? 'closed' : 'opened' end + def set_scope + params[:include_subgroups] = true if board.group_board? + end + def board_label_ids @board_label_ids ||= board.lists.movable.pluck(:label_id) end diff --git a/app/services/issuable_base_service.rb b/app/services/issuable_base_service.rb index 91ec702fbc6..1f67e3ecf9d 100644 --- a/app/services/issuable_base_service.rb +++ b/app/services/issuable_base_service.rb @@ -51,9 +51,10 @@ class IssuableBaseService < BaseService return unless milestone_id params[:milestone_id] = '' if milestone_id == IssuableFinder::NONE + group_ids = project.group&.self_and_ancestors&.pluck(:id) milestone = - Milestone.for_projects_and_groups([project.id], [project.group&.id]).find_by_id(milestone_id) + Milestone.for_projects_and_groups([project.id], group_ids).find_by_id(milestone_id) params[:milestone_id] = '' unless milestone end diff --git a/app/views/shared/boards/components/_sidebar.html.haml b/app/views/shared/boards/components/_sidebar.html.haml index 8e5e32e9f16..b385cc3f962 100644 --- a/app/views/shared/boards/components/_sidebar.html.haml +++ b/app/views/shared/boards/components/_sidebar.html.haml @@ -22,6 +22,6 @@ = render "shared/boards/components/sidebar/labels" = render "shared/boards/components/sidebar/notifications" %remove-btn{ ":issue" => "issue", - ":issue-update" => "'#{build_issue_link_base}/' + issue.iid + '.json'", + ":issue-update" => "issue.sidebarInfoEndpoint", ":list" => "list", "v-if" => "canRemove" } diff --git a/app/views/shared/boards/components/sidebar/_assignee.html.haml b/app/views/shared/boards/components/sidebar/_assignee.html.haml index 3d2e8471a60..1374da9d82c 100644 --- a/app/views/shared/boards/components/sidebar/_assignee.html.haml +++ b/app/views/shared/boards/components/sidebar/_assignee.html.haml @@ -21,8 +21,7 @@ .dropdown - dropdown_options = issue_assignees_dropdown_options %button.dropdown-menu-toggle.js-user-search.js-author-search.js-multiselect.js-save-user-data.js-issue-board-sidebar{ type: 'button', ref: 'assigneeDropdown', data: board_sidebar_user_data, - ":data-issuable-id" => "issue.iid", - ":data-issue-update" => "'#{build_issue_link_base}/' + issue.iid + '.json'" } + ":data-issuable-id" => "issue.iid" } = dropdown_options[:title] = icon("chevron-down") .dropdown-menu.dropdown-select.dropdown-menu-user.dropdown-menu-selectable.dropdown-menu-author diff --git a/app/views/shared/boards/components/sidebar/_due_date.html.haml b/app/views/shared/boards/components/sidebar/_due_date.html.haml index db794d6f855..c1a97269954 100644 --- a/app/views/shared/boards/components/sidebar/_due_date.html.haml +++ b/app/views/shared/boards/components/sidebar/_due_date.html.haml @@ -22,8 +22,7 @@ ":value" => "issue.dueDate" } .dropdown %button.dropdown-menu-toggle.js-due-date-select.js-issue-boards-due-date{ type: 'button', - data: { toggle: 'dropdown', field_name: "issue[due_date]", ability_name: "issue" }, - ":data-issue-update" => "'#{build_issue_link_base}/' + issue.iid + '.json'" } + data: { toggle: 'dropdown', field_name: "issue[due_date]", ability_name: "issue" }} %span.dropdown-toggle-text Due date = icon('chevron-down') .dropdown-menu.dropdown-menu-due-date diff --git a/app/views/shared/boards/components/sidebar/_labels.html.haml b/app/views/shared/boards/components/sidebar/_labels.html.haml index dfc0f9be321..3c514ededc5 100644 --- a/app/views/shared/boards/components/sidebar/_labels.html.haml +++ b/app/views/shared/boards/components/sidebar/_labels.html.haml @@ -26,8 +26,7 @@ project_id: @project&.try(:id), labels: labels_filter_path(false), namespace_path: @namespace_path, - project_path: @project.try(:path) }, - ":data-issue-update" => "'#{build_issue_link_base}/' + issue.iid + '.json'" } + project_path: @project.try(:path) }} %span.dropdown-toggle-text Label = icon('chevron-down') diff --git a/app/views/shared/boards/components/sidebar/_milestone.html.haml b/app/views/shared/boards/components/sidebar/_milestone.html.haml index d09c7c218e0..f51c4a97f2b 100644 --- a/app/views/shared/boards/components/sidebar/_milestone.html.haml +++ b/app/views/shared/boards/components/sidebar/_milestone.html.haml @@ -18,8 +18,7 @@ .dropdown %button.dropdown-menu-toggle.js-milestone-select.js-issue-board-sidebar{ type: "button", data: { toggle: "dropdown", show_no: "true", field_name: "issue[milestone_id]", milestones: milestones_filter_path(format: :json), ability_name: "issue", use_id: "true", default_no: "true" }, ":data-selected" => "milestoneTitle", - ":data-issuable-id" => "issue.iid", - ":data-issue-update" => "'#{build_issue_link_base}/' + issue.iid + '.json'" } + ":data-issuable-id" => "issue.iid" } Milestone = icon("chevron-down") .dropdown-menu.dropdown-select.dropdown-menu-selectable diff --git a/changelogs/unreleased/issue_44270.yml b/changelogs/unreleased/issue_44270.yml new file mode 100644 index 00000000000..6234162be30 --- /dev/null +++ b/changelogs/unreleased/issue_44270.yml @@ -0,0 +1,5 @@ +--- +title: Show issues of subgroups in group-level issue board +merge_request: +author: +type: changed diff --git a/spec/features/labels_hierarchy_spec.rb b/spec/features/labels_hierarchy_spec.rb index 99e1fb30d5b..d4a49a1cbf4 100644 --- a/spec/features/labels_hierarchy_spec.rb +++ b/spec/features/labels_hierarchy_spec.rb @@ -116,10 +116,12 @@ feature 'Labels Hierarchy', :js, :nested_groups do wait_for_requests if board - pending("Waiting for https://gitlab.com/gitlab-org/gitlab-ce/issues/44270") - select_label_on_dropdown(group_label_3.title) + expect(page).to have_selector('.card-title') do |card| + expect(card).not_to have_selector('a', text: labeled_issue_2.title) + end + expect(page).to have_selector('.card-title') do |card| expect(card).to have_selector('a', text: labeled_issue_3.title) end diff --git a/spec/services/boards/issues/list_service_spec.rb b/spec/services/boards/issues/list_service_spec.rb index b4efa3e44b6..8d67bf67747 100644 --- a/spec/services/boards/issues/list_service_spec.rb +++ b/spec/services/boards/issues/list_service_spec.rb @@ -48,10 +48,8 @@ describe Boards::Issues::ListService do context 'when parent is a group' do let(:user) { create(:user) } - let(:group) { create(:group) } let(:project) { create(:project, :empty_repo, namespace: group) } let(:project1) { create(:project, :empty_repo, namespace: group) } - let(:board) { create(:board, group: group) } let(:m1) { create(:milestone, group: group) } let(:m2) { create(:milestone, group: group) } @@ -92,13 +90,30 @@ describe Boards::Issues::ListService do let!(:closed_issue4) { create(:labeled_issue, :closed, project: project1, labels: [p1, p1_project1]) } let!(:closed_issue5) { create(:labeled_issue, :closed, project: project1, labels: [development]) } - let(:parent) { group } - before do group.add_developer(user) end - it_behaves_like 'issues list service' + context 'and group has no parent' do + let(:parent) { group } + let(:group) { create(:group) } + let(:board) { create(:board, group: group) } + + it_behaves_like 'issues list service' + end + + context 'and group is an ancestor' do + let(:parent) { create(:group) } + let(:group) { create(:group, parent: parent) } + let!(:backlog) { create(:backlog_list, board: board) } + let(:board) { create(:board, group: parent) } + + before do + parent.add_developer(user) + end + + it_behaves_like 'issues list service' + end end end end -- cgit v1.2.3 From 62574be35d5a92c6c825912e1ab9969c5acdb7d9 Mon Sep 17 00:00:00 2001 From: Felipe Artur Date: Thu, 5 Apr 2018 12:28:49 -0300 Subject: Fix specs --- app/models/milestone.rb | 4 ++-- spec/features/labels_hierarchy_spec.rb | 6 ++---- spec/javascripts/boards/issue_card_spec.js | 2 ++ 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/models/milestone.rb b/app/models/milestone.rb index dafae58d121..a66a0015827 100644 --- a/app/models/milestone.rb +++ b/app/models/milestone.rb @@ -34,8 +34,8 @@ class Milestone < ActiveRecord::Base scope :for_projects_and_groups, -> (project_ids, group_ids) do conditions = [] - conditions << arel_table[:project_id].in(project_ids) if project_ids.compact.any? - conditions << arel_table[:group_id].in(group_ids) if group_ids.compact.any? + conditions << arel_table[:project_id].in(project_ids) if project_ids&.compact&.any? + conditions << arel_table[:group_id].in(group_ids) if group_ids&.compact&.any? where(conditions.reduce(:or)) end diff --git a/spec/features/labels_hierarchy_spec.rb b/spec/features/labels_hierarchy_spec.rb index d4a49a1cbf4..3e05e7b7f38 100644 --- a/spec/features/labels_hierarchy_spec.rb +++ b/spec/features/labels_hierarchy_spec.rb @@ -115,9 +115,9 @@ feature 'Labels Hierarchy', :js, :nested_groups do it 'filters by descendant group labels' do wait_for_requests - if board - select_label_on_dropdown(group_label_3.title) + select_label_on_dropdown(group_label_3.title) + if board expect(page).to have_selector('.card-title') do |card| expect(card).not_to have_selector('a', text: labeled_issue_2.title) end @@ -126,8 +126,6 @@ feature 'Labels Hierarchy', :js, :nested_groups do expect(card).to have_selector('a', text: labeled_issue_3.title) end else - select_label_on_dropdown(group_label_3.title) - expect_issues_list_count(1) expect(page).to have_selector('span.issue-title-text', text: labeled_issue_3.title) end diff --git a/spec/javascripts/boards/issue_card_spec.js b/spec/javascripts/boards/issue_card_spec.js index 37088a6421c..aa01f7d6d09 100644 --- a/spec/javascripts/boards/issue_card_spec.js +++ b/spec/javascripts/boards/issue_card_spec.js @@ -41,6 +41,8 @@ describe('Issue card component', () => { confidential: false, labels: [list.label], assignees: [], + reference_path: '#1', + real_path: '/test/1' }); component = new Vue({ -- cgit v1.2.3 From 7c6f4adac9bc2f0bba46a4267f1081c7542e4dc4 Mon Sep 17 00:00:00 2001 From: Felipe Artur Date: Thu, 5 Apr 2018 14:57:48 -0300 Subject: Fix more specs --- app/assets/javascripts/boards/models/issue.js | 2 +- app/services/boards/issues/list_service.rb | 2 +- spec/fixtures/api/schemas/issue.json | 2 ++ spec/javascripts/boards/issue_card_spec.js | 2 +- spec/services/boards/issues/list_service_spec.rb | 2 +- 5 files changed, 6 insertions(+), 4 deletions(-) diff --git a/app/assets/javascripts/boards/models/issue.js b/app/assets/javascripts/boards/models/issue.js index 85f98615cf4..b381d48d625 100644 --- a/app/assets/javascripts/boards/models/issue.js +++ b/app/assets/javascripts/boards/models/issue.js @@ -115,7 +115,7 @@ class ListIssue { } const projectPath = this.project ? this.project.path : ''; - return Vue.http.patch(this.path + '.json', data); + return Vue.http.patch(`${this.path}.json`, data); } } diff --git a/app/services/boards/issues/list_service.rb b/app/services/boards/issues/list_service.rb index 8a1796a1096..ac70a99c2c5 100644 --- a/app/services/boards/issues/list_service.rb +++ b/app/services/boards/issues/list_service.rb @@ -53,7 +53,7 @@ module Boards end def set_scope - params[:include_subgroups] = true if board.group_board? + params[:include_subgroups] = board.group_board? end def board_label_ids diff --git a/spec/fixtures/api/schemas/issue.json b/spec/fixtures/api/schemas/issue.json index b579e32c9aa..8833825e3fb 100644 --- a/spec/fixtures/api/schemas/issue.json +++ b/spec/fixtures/api/schemas/issue.json @@ -15,6 +15,8 @@ "relative_position": { "type": "integer" }, "issue_sidebar_endpoint": { "type": "string" }, "toggle_subscription_endpoint": { "type": "string" }, + "reference_path": { "type": "string" }, + "real_path": { "type": "string" }, "project": { "id": { "type": "integer" }, "path": { "type": "string" } diff --git a/spec/javascripts/boards/issue_card_spec.js b/spec/javascripts/boards/issue_card_spec.js index aa01f7d6d09..be1ea0b57b4 100644 --- a/spec/javascripts/boards/issue_card_spec.js +++ b/spec/javascripts/boards/issue_card_spec.js @@ -42,7 +42,7 @@ describe('Issue card component', () => { labels: [list.label], assignees: [], reference_path: '#1', - real_path: '/test/1' + real_path: '/test/1', }); component = new Vue({ diff --git a/spec/services/boards/issues/list_service_spec.rb b/spec/services/boards/issues/list_service_spec.rb index 8d67bf67747..27a7bf0e605 100644 --- a/spec/services/boards/issues/list_service_spec.rb +++ b/spec/services/boards/issues/list_service_spec.rb @@ -102,7 +102,7 @@ describe Boards::Issues::ListService do it_behaves_like 'issues list service' end - context 'and group is an ancestor' do + context 'and group is an ancestor', :nested_groups do let(:parent) { create(:group) } let(:group) { create(:group, parent: parent) } let!(:backlog) { create(:backlog_list, board: board) } -- cgit v1.2.3 From b9c0cf1318d663edc3af593f88521e86e0614824 Mon Sep 17 00:00:00 2001 From: Felipe Artur Date: Thu, 5 Apr 2018 15:14:04 -0300 Subject: Improve specs and docs --- app/services/issues/update_service.rb | 2 +- doc/user/project/issue_board.md | 3 +-- spec/services/issues/update_service_spec.rb | 6 ++++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/app/services/issues/update_service.rb b/app/services/issues/update_service.rb index 4161932ad2a..1374f10c586 100644 --- a/app/services/issues/update_service.rb +++ b/app/services/issues/update_service.rb @@ -90,7 +90,7 @@ module Issues issue = if board_group_id - IssuesFinder.new(current_user, group_id: board_group_id).find_by(id: id) + IssuesFinder.new(current_user, group_id: board_group_id, include_subgroups: true).find_by(id: id) else project.issues.find(id) end diff --git a/doc/user/project/issue_board.md b/doc/user/project/issue_board.md index b4a842f33d6..7eab825fa32 100644 --- a/doc/user/project/issue_board.md +++ b/doc/user/project/issue_board.md @@ -240,8 +240,7 @@ Issue Board, that is create/delete lists and drag issues around. >Introduced in GitLab 10.6 Group issue board is analogous to project-level issue board and it is accessible at the group -navigation level. A group-level issue board allows you to view all issues from all projects in that group -(currently, it does not see issues from projects in subgroups). Similarly, you can only filter by group labels for these +navigation level. A group-level issue board allows you to view all issues from all projects in that group or descendant subgroups. Similarly, you can only filter by group labels for these boards. When updating milestones and labels for an issue through the sidebar update mechanism, again only group-level objects are available. diff --git a/spec/services/issues/update_service_spec.rb b/spec/services/issues/update_service_spec.rb index f95474208f3..23b1134b5a3 100644 --- a/spec/services/issues/update_service_spec.rb +++ b/spec/services/issues/update_service_spec.rb @@ -97,11 +97,13 @@ describe Issues::UpdateService, :mailer do expect(issue.relative_position).to be_between(issue1.relative_position, issue2.relative_position) end - context 'when moving issue between issues from different projects' do + context 'when moving issue between issues from different projects', :nested_groups do let(:group) { create(:group) } + let(:subgroup) { create(:group, parent: group) } + let(:project_1) { create(:project, namespace: group) } let(:project_2) { create(:project, namespace: group) } - let(:project_3) { create(:project, namespace: group) } + let(:project_3) { create(:project, namespace: subgroup) } let(:issue_1) { create(:issue, project: project_1) } let(:issue_2) { create(:issue, project: project_2) } -- cgit v1.2.3 From b099c6ff9fcbd81beb75fd12bff8d1d5b9c16083 Mon Sep 17 00:00:00 2001 From: m b Date: Fri, 23 Mar 2018 00:09:26 -0500 Subject: Deleting a MR you are assigned to should decrements counter The merge request counter in the UI was not decreasing when a merge request was deleting. This was just due to the cache not being refreshed on a delete action. fixes: https://gitlab.com/gitlab-org/gitlab-ce/issues/44458 --- app/models/user.rb | 5 ----- app/services/issuable/destroy_service.rb | 1 + changelogs/unreleased/ui-mr-counter-cache.yml | 5 +++++ spec/services/issuable/destroy_service_spec.rb | 14 ++++++++++++-- 4 files changed, 18 insertions(+), 7 deletions(-) create mode 100644 changelogs/unreleased/ui-mr-counter-cache.yml diff --git a/app/models/user.rb b/app/models/user.rb index 7b6857a0d34..ce56b39b1c8 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1046,11 +1046,6 @@ class User < ActiveRecord::Base end end - def update_cache_counts - assigned_open_merge_requests_count(force: true) - assigned_open_issues_count(force: true) - end - def update_todos_count_cache todos_done_count(force: true) todos_pending_count(force: true) diff --git a/app/services/issuable/destroy_service.rb b/app/services/issuable/destroy_service.rb index 7197a426a72..0b1a33518c6 100644 --- a/app/services/issuable/destroy_service.rb +++ b/app/services/issuable/destroy_service.rb @@ -4,6 +4,7 @@ module Issuable TodoService.new.destroy_target(issuable) do |issuable| if issuable.destroy issuable.update_project_counter_caches + issuable.assignees.each(&:invalidate_cache_counts) end end end diff --git a/changelogs/unreleased/ui-mr-counter-cache.yml b/changelogs/unreleased/ui-mr-counter-cache.yml new file mode 100644 index 00000000000..5e241bfe93f --- /dev/null +++ b/changelogs/unreleased/ui-mr-counter-cache.yml @@ -0,0 +1,5 @@ +--- +title: Deleting a MR you are assigned to should decrements counter +merge_request: 17951 +author: m b +type: fixed diff --git a/spec/services/issuable/destroy_service_spec.rb b/spec/services/issuable/destroy_service_spec.rb index 0a3647a814f..8ccbba7fa58 100644 --- a/spec/services/issuable/destroy_service_spec.rb +++ b/spec/services/issuable/destroy_service_spec.rb @@ -8,7 +8,7 @@ describe Issuable::DestroyService do describe '#execute' do context 'when issuable is an issue' do - let!(:issue) { create(:issue, project: project, author: user) } + let!(:issue) { create(:issue, project: project, author: user, assignees: [user]) } it 'destroys the issue' do expect { service.execute(issue) }.to change { project.issues.count }.by(-1) @@ -26,10 +26,15 @@ describe Issuable::DestroyService do expect { service.execute(issue) } .to change { user.todos_pending_count }.from(1).to(0) end + + it 'invalidates the issues count cache for the assignees' do + expect_any_instance_of(User).to receive(:invalidate_cache_counts).once + service.execute(issue) + end end context 'when issuable is a merge request' do - let!(:merge_request) { create(:merge_request, target_project: project, source_project: project, author: user) } + let!(:merge_request) { create(:merge_request, target_project: project, source_project: project, author: user, assignee: user) } it 'destroys the merge request' do expect { service.execute(merge_request) }.to change { project.merge_requests.count }.by(-1) @@ -41,6 +46,11 @@ describe Issuable::DestroyService do service.execute(merge_request) end + it 'invalidates the merge request caches for the MR assignee' do + expect_any_instance_of(User).to receive(:invalidate_cache_counts).once + service.execute(merge_request) + end + it 'updates the todo caches for users with todos on the merge request' do create(:todo, target: merge_request, user: user, author: user, project: project) -- cgit v1.2.3 From 0a111c91d22f7bfe52cb47f6ffa4ecbe622c6a5d Mon Sep 17 00:00:00 2001 From: Felipe Artur Date: Thu, 5 Apr 2018 15:31:46 -0300 Subject: Fix rubocop --- app/views/shared/boards/components/sidebar/_labels.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/shared/boards/components/sidebar/_labels.html.haml b/app/views/shared/boards/components/sidebar/_labels.html.haml index 3c514ededc5..87e6b52f46e 100644 --- a/app/views/shared/boards/components/sidebar/_labels.html.haml +++ b/app/views/shared/boards/components/sidebar/_labels.html.haml @@ -26,7 +26,7 @@ project_id: @project&.try(:id), labels: labels_filter_path(false), namespace_path: @namespace_path, - project_path: @project.try(:path) }} + project_path: @project.try(:path) } } %span.dropdown-toggle-text Label = icon('chevron-down') -- cgit v1.2.3 From b72da4e3d71a8b6ae022221453d7b4fa353ff6d9 Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Thu, 5 Apr 2018 20:20:39 +0200 Subject: Update GitLab.com settings with current state --- doc/user/gitlab_com/index.md | 106 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 89 insertions(+), 17 deletions(-) diff --git a/doc/user/gitlab_com/index.md b/doc/user/gitlab_com/index.md index d5f77191938..7baccb796c6 100644 --- a/doc/user/gitlab_com/index.md +++ b/doc/user/gitlab_com/index.md @@ -72,15 +72,23 @@ The maximum size your Git repository is allowed to be including LFS. ## Shared Runners Shared Runners on GitLab.com run in [autoscale mode] and powered by -DigitalOcean. Autoscaling means reduced waiting times to spin up builds, -and isolated VMs for each project, thus maximizing security. +Google Cloud Platform and DigitalOcean. Autoscaling means reduced +waiting times to spin up CI/CD jobs, and isolated VMs for each project, +thus maximizing security. They're free to use for public open source projects and limited to 2000 CI minutes per month per group for private projects. Read about all [GitLab.com plans](https://about.gitlab.com/pricing/). -All your builds run on 2GB (RAM) ephemeral instances, with CoreOS and the latest -Docker Engine installed. The default region of the VMs is NYC. +In case of DigitalOcean based Runners, all your CI/CD jobs run on ephemeral +instances with 2GB of RAM, CoreOS and the latest Docker Engine installed. +Instances provide 2 vCPUs and 60GB of SSD disk space. The default region of the +VMs is NYC1. + +In case of Google Cloud Platform based Runners, all your CI/CD jobs run on +ephemeral instances with 3.75GB of RAM, CoreOS and the latest Docker Engine +installed. Instances provide 1 vCPU and 25GB of HDD disk space. The default +region of the VMs is US East1. Below are the shared Runners settings. @@ -88,52 +96,116 @@ Below are the shared Runners settings. | ----------- | ----------------- | ---------- | | [GitLab Runner] | [Runner versions dashboard][ci_version_dashboard] | - | | Executor | `docker+machine` | - | -| Default Docker image | `ruby:2.1` | - | +| Default Docker image | `ruby:2.5` | - | | `privileged` (run [Docker in Docker]) | `true` | `false` | -[ci_version_dashboard]: https://monitor.gitlab.net/dashboard/db/ci?refresh=5m&orgId=1&panelId=12&fullscreen&from=now-1h&to=now&var-runner_type=All&var-cache_server=All&var-gl_monitor_fqdn=postgres-01.db.prd.gitlab.com&var-has_minutes=yes&var-hanging_droplets_cleaner=All&var-droplet_zero_machines_cleaner=All&var-runner_job_failure_reason=All&theme=light +[ci_version_dashboard]: https://monitor.gitlab.net/dashboard/db/ci?from=now-1h&to=now&refresh=5m&orgId=1&panelId=12&fullscreen&theme=light ### `config.toml` The full contents of our `config.toml` are: +**DigitalOcean** + ```toml +concurrent = X +check_interval = 1 +metrics_server = "X" +sentry_dsn = "X" + [[runners]] name = "docker-auto-scale" - limit = X request_concurrency = X - url = "https://gitlab.com/ci" + url = "https://gitlab.com/" token = "SHARED_RUNNER_TOKEN" executor = "docker+machine" environment = [ "DOCKER_DRIVER=overlay2" ] + limit = X [runners.docker] - image = "ruby:2.1" + image = "ruby:2.5" privileged = true [runners.machine] - IdleCount = 40 + IdleCount = 20 IdleTime = 1800 + OffPeakPeriods = ["* * * * * sat,sun *"] + OffPeakTimezone = "UTC" + OffPeakIdleCount = 5 + OffPeakIdleTime = 1800 MaxBuilds = 1 + MachineName = "srm-%s" MachineDriver = "digitalocean" - MachineName = "machine-%s-digital-ocean-2gb" MachineOptions = [ - "digitalocean-image=coreos-stable", + "digitalocean-image=X", "digitalocean-ssh-user=core", - "digitalocean-access-token=DIGITAL_OCEAN_ACCESS_TOKEN", "digitalocean-region=nyc1", - "digitalocean-size=2gb", + "digitalocean-size=s-2vcpu-2gb", "digitalocean-private-networking", - "digitalocean-userdata=/etc/gitlab-runner/cloudinit.sh", - "engine-registry-mirror=http://IP_TO_OUR_REGISTRY_MIRROR" + "digitalocean-tags=shared_runners,gitlab_com", + "engine-registry-mirror=http://INTERNAL_IP_OF_OUR_REGISTRY_MIRROR", + "digitalocean-access-token=DIGITAL_OCEAN_ACCESS_TOKEN", ] [runners.cache] Type = "s3" - ServerAddress = "IP_TO_OUR_CACHE_SERVER" + BucketName = "runner" + Insecure = true + Shared = true + ServerAddress = "INTERNAL_IP_OF_OUR_CACHE_SERVER" AccessKey = "ACCESS_KEY" SecretKey = "ACCESS_SECRET_KEY" +``` + +**Google Cloud Platform** + +```toml +concurrent = X +check_interval = 1 +metrics_server = "X" +sentry_dsn = "X" + +[[runners]] + name = "docker-auto-scale" + request_concurrency = X + url = "https://gitlab.com/" + token = "SHARED_RUNNER_TOKEN" + executor = "docker+machine" + environment = [ + "DOCKER_DRIVER=overlay2" + ] + limit = X + [runners.docker] + image = "ruby:2.5" + privileged = true + [runners.machine] + IdleCount = 20 + IdleTime = 1800 + OffPeakPeriods = ["* * * * * sat,sun *"] + OffPeakTimezone = "UTC" + OffPeakIdleCount = 5 + OffPeakIdleTime = 1800 + MaxBuilds = 1 + MachineName = "srm-%s" + MachineDriver = "google" + MachineOptions = [ + "google-project=PROJECT", + "google-disk-size=25", + "google-machine-type=n1-standard-1", + "google-username=core", + "google-tags=gitlab-com,srm", + "google-use-internal-ip", + "google-zone=us-east1-d", + "google-machine-image=PROJECT/global/images/IMAGE", + "engine-registry-mirror=http://INTERNAL_IP_OF_OUR_REGISTRY_MIRROR" + ] + [runners.cache] + Type = "s3" BucketName = "runner" + Insecure = true Shared = true + ServerAddress = "INTERNAL_IP_OF_OUR_CACHE_SERVER" + AccessKey = "ACCESS_KEY" + SecretKey = "ACCESS_SECRET_KEY" ``` ## Sidekiq -- cgit v1.2.3 From 696daa7ef1d784dfd1521bd5b5cc2cc18d89e96e Mon Sep 17 00:00:00 2001 From: Felipe Artur Date: Thu, 5 Apr 2018 16:50:00 -0300 Subject: Fix rubocop --- app/views/shared/boards/components/sidebar/_due_date.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/shared/boards/components/sidebar/_due_date.html.haml b/app/views/shared/boards/components/sidebar/_due_date.html.haml index c1a97269954..d13b998e6f4 100644 --- a/app/views/shared/boards/components/sidebar/_due_date.html.haml +++ b/app/views/shared/boards/components/sidebar/_due_date.html.haml @@ -22,7 +22,7 @@ ":value" => "issue.dueDate" } .dropdown %button.dropdown-menu-toggle.js-due-date-select.js-issue-boards-due-date{ type: 'button', - data: { toggle: 'dropdown', field_name: "issue[due_date]", ability_name: "issue" }} + data: { toggle: 'dropdown', field_name: "issue[due_date]", ability_name: "issue" } } %span.dropdown-toggle-text Due date = icon('chevron-down') .dropdown-menu.dropdown-menu-due-date -- cgit v1.2.3 From b9dfd071ed7260e9a3f470317011bcdcfedd61ed Mon Sep 17 00:00:00 2001 From: Felipe Artur Date: Wed, 28 Mar 2018 17:39:12 -0300 Subject: Include subgroup issues when searching for group issues using the API --- changelogs/unreleased/issue_42443.yml | 5 +++++ lib/api/issues.rb | 2 +- spec/requests/api/issues_spec.rb | 24 ++++++++++++++++++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 changelogs/unreleased/issue_42443.yml diff --git a/changelogs/unreleased/issue_42443.yml b/changelogs/unreleased/issue_42443.yml new file mode 100644 index 00000000000..954fbd98a4b --- /dev/null +++ b/changelogs/unreleased/issue_42443.yml @@ -0,0 +1,5 @@ +--- +title: Include subgroup issues when searching for group issues using the API +merge_request: +author: +type: added diff --git a/lib/api/issues.rb b/lib/api/issues.rb index f74b3b26802..88e7f46c92c 100644 --- a/lib/api/issues.rb +++ b/lib/api/issues.rb @@ -97,7 +97,7 @@ module API get ":id/issues" do group = find_group!(params[:id]) - issues = paginate(find_issues(group_id: group.id)) + issues = paginate(find_issues(group_id: group.id, include_subgroups: true)) options = { with: Entities::IssueBasic, diff --git a/spec/requests/api/issues_spec.rb b/spec/requests/api/issues_spec.rb index 6614e8cea43..90f9c4ad214 100644 --- a/spec/requests/api/issues_spec.rb +++ b/spec/requests/api/issues_spec.rb @@ -384,6 +384,30 @@ describe API::Issues do end let(:base_url) { "/groups/#{group.id}/issues" } + context 'when group has subgroups', :nested_groups do + let(:subgroup_1) { create(:group, parent: group) } + let(:subgroup_2) { create(:group, parent: subgroup_1) } + + let(:subgroup_1_project) { create(:project, namespace: subgroup_1) } + let(:subgroup_2_project) { create(:project, namespace: subgroup_2) } + + let!(:issue_1) { create(:issue, project: subgroup_1_project) } + let!(:issue_2) { create(:issue, project: subgroup_2_project) } + + before do + group.add_developer(user) + end + + it 'also returns subgroups projects issues' do + get api(base_url, user) + + issue_ids = json_response.map { |issue| issue['id'] } + + expect_paginated_array_response(size: 5) + expect(issue_ids).to include(issue_1.id, issue_2.id) + end + end + it 'returns all group issues (including opened and closed)' do get api(base_url, admin) -- cgit v1.2.3 From 847f1667c89831213859d62ca66fbd55181fb129 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Fri, 6 Apr 2018 10:41:58 +0200 Subject: Document unsupported variables for dynamic environments --- doc/ci/environments.md | 15 ++++++++++++--- doc/ci/variables/README.md | 4 ++++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/doc/ci/environments.md b/doc/ci/environments.md index 58c4a71cef9..b3d9f0bc96c 100644 --- a/doc/ci/environments.md +++ b/doc/ci/environments.md @@ -247,10 +247,19 @@ declaring their names dynamically in `.gitlab-ci.yml`. Dynamic environments is the basis of [Review apps](review_apps/index.md). >**Note:** -The `name` and `url` parameters can use any of the defined CI variables, +The `name` and `url` parameters can use most of the defined CI variables, including predefined, secure variables and `.gitlab-ci.yml` -[`variables`](yaml/README.md#variables). -You however cannot use variables defined under `script` or on the Runner's side. +[`variables`](yaml/README.md#variables). You however cannot use variables +defined under `script` or on the Runner's side. There are other variables that +are unsupported in environment name context: +- `CI_JOB_ID` +- `CI_JOB_TOKEN` +- `CI_BUILD_ID` +- `CI_BUILD_TOKEN` +- `CI_REGISTRY_USER` +- `CI_REGISTRY_PASSWORD` +- `CI_REPOSITORY_URL` +- `CI_ENVIRONMENT_URL` GitLab Runner exposes various [environment variables][variables] when a job runs, and as such, you can use them as environment names. Let's add another job in diff --git a/doc/ci/variables/README.md b/doc/ci/variables/README.md index 381405a9db9..4a504a98902 100644 --- a/doc/ci/variables/README.md +++ b/doc/ci/variables/README.md @@ -547,6 +547,9 @@ You can find a full list of unsupported variables below: - `CI_REPOSITORY_URL` - `CI_ENVIRONMENT_URL` +These variables are also not supported in a contex of a +[dynamic environment name][dynamic-environments]. + [ce-13784]: https://gitlab.com/gitlab-org/gitlab-ce/issues/13784 "Simple protection of CI secret variables" [eep]: https://about.gitlab.com/products/ "Available only in GitLab Premium" [envs]: ../environments.md @@ -558,3 +561,4 @@ You can find a full list of unsupported variables below: [triggers]: ../triggers/README.md#pass-job-variables-to-a-trigger [subgroups]: ../../user/group/subgroups/index.md [builds-policies]: ../yaml/README.md#only-and-except-complex +[dynamic-environments]: ../environments.md#dynamic-environments -- cgit v1.2.3 From 388f43b6111bf35561988d327c462ab75afc34f6 Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Thu, 5 Apr 2018 13:55:55 +0530 Subject: Add map for supported noteable types --- app/assets/javascripts/notes/constants.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/assets/javascripts/notes/constants.js b/app/assets/javascripts/notes/constants.js index 68f8cb1cf1e..c4de4826eda 100644 --- a/app/assets/javascripts/notes/constants.js +++ b/app/assets/javascripts/notes/constants.js @@ -14,3 +14,9 @@ export const EPIC_NOTEABLE_TYPE = 'epic'; export const MERGE_REQUEST_NOTEABLE_TYPE = 'merge_request'; export const UNRESOLVE_NOTE_METHOD_NAME = 'delete'; export const RESOLVE_NOTE_METHOD_NAME = 'post'; + +export const NOTEABLE_TYPE_MAPPING = { + Issue: ISSUE_NOTEABLE_TYPE, + MergeRequest: MERGE_REQUEST_NOTEABLE_TYPE, + Epic: EPIC_NOTEABLE_TYPE, +}; -- cgit v1.2.3 From 15195f67840cd5369d776938b62b02aa939a4270 Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Thu, 5 Apr 2018 13:56:15 +0530 Subject: Use noteable type map from constants --- app/assets/javascripts/notes/mixins/noteable.js | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/app/assets/javascripts/notes/mixins/noteable.js b/app/assets/javascripts/notes/mixins/noteable.js index 5bf8216a1f3..b68543d71c8 100644 --- a/app/assets/javascripts/notes/mixins/noteable.js +++ b/app/assets/javascripts/notes/mixins/noteable.js @@ -9,16 +9,7 @@ export default { }, computed: { noteableType() { - switch (this.note.noteable_type) { - case 'MergeRequest': - return constants.MERGE_REQUEST_NOTEABLE_TYPE; - case 'Issue': - return constants.ISSUE_NOTEABLE_TYPE; - case 'Epic': - return constants.EPIC_NOTEABLE_TYPE; - default: - return ''; - } + return constants.NOTEABLE_TYPE_MAPPING[this.note.noteable_type]; }, }, }; -- cgit v1.2.3 From 223eeae1a774df4f8d7f132040ba10547184ec68 Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Thu, 5 Apr 2018 13:56:54 +0530 Subject: Return noteableType from app initial config --- app/assets/javascripts/notes/components/notes_app.vue | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/app/assets/javascripts/notes/components/notes_app.vue b/app/assets/javascripts/notes/components/notes_app.vue index 5bd81c7cad6..ebfc827ac57 100644 --- a/app/assets/javascripts/notes/components/notes_app.vue +++ b/app/assets/javascripts/notes/components/notes_app.vue @@ -49,16 +49,7 @@ export default { computed: { ...mapGetters(['notes', 'getNotesDataByProp', 'discussionCount']), noteableType() { - // FIXME -- @fatihacet Get this from JSON data. - const { ISSUE_NOTEABLE_TYPE, MERGE_REQUEST_NOTEABLE_TYPE, EPIC_NOTEABLE_TYPE } = constants; - - if (this.noteableData.noteableType === EPIC_NOTEABLE_TYPE) { - return EPIC_NOTEABLE_TYPE; - } - - return this.noteableData.merge_params - ? MERGE_REQUEST_NOTEABLE_TYPE - : ISSUE_NOTEABLE_TYPE; + return this.noteableData.noteableType; }, allNotes() { if (this.isLoading) { -- cgit v1.2.3 From a983583ae8f3dd3e8cafb13d3934636cb095cfcc Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Thu, 5 Apr 2018 13:57:26 +0530 Subject: Set `noteable_type` to use in notesApp --- app/views/projects/issues/_discussion.html.haml | 1 + app/views/projects/merge_requests/show.html.haml | 1 + 2 files changed, 2 insertions(+) diff --git a/app/views/projects/issues/_discussion.html.haml b/app/views/projects/issues/_discussion.html.haml index cdfc3e232c5..816f2fa816d 100644 --- a/app/views/projects/issues/_discussion.html.haml +++ b/app/views/projects/issues/_discussion.html.haml @@ -8,4 +8,5 @@ %section.js-vue-notes-event #js-vue-notes{ data: { notes_data: notes_data(@issue), noteable_data: serialize_issuable(@issue), + noteable_type: 'issue', current_user_data: UserSerializer.new.represent(current_user, only_path: true).to_json } } diff --git a/app/views/projects/merge_requests/show.html.haml b/app/views/projects/merge_requests/show.html.haml index 9866cc716ee..15a0e4d7ef5 100644 --- a/app/views/projects/merge_requests/show.html.haml +++ b/app/views/projects/merge_requests/show.html.haml @@ -80,6 +80,7 @@ - if has_vue_discussions_cookie? #js-vue-mr-discussions{ data: { notes_data: notes_data(@merge_request), noteable_data: serialize_issuable(@merge_request), + noteable_type: 'merge_request', current_user_data: UserSerializer.new.represent(current_user).to_json} } #commits.commits.tab-pane -- cgit v1.2.3 From 7544a555aafc4bd021e5ae73bef6a650e6144b38 Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Thu, 5 Apr 2018 14:57:22 +0530 Subject: Add noteableType to mock data object --- spec/javascripts/notes/mock_data.js | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/javascripts/notes/mock_data.js b/spec/javascripts/notes/mock_data.js index 2d88cee61f1..24388fba219 100644 --- a/spec/javascripts/notes/mock_data.js +++ b/spec/javascripts/notes/mock_data.js @@ -52,6 +52,7 @@ export const noteableDataMock = { updated_at: '2017-08-04T09:53:01.226Z', updated_by_id: 1, web_url: '/gitlab-org/gitlab-ce/issues/26', + noteableType: 'issue', }; export const lastFetchedAt = '1501862675'; -- cgit v1.2.3 From bf54baa73bb648be3e13a74c14641e3916b54269 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 6 Apr 2018 09:17:35 +0000 Subject: Add note about contributing back to GitLab to plugins.md --- doc/administration/plugins.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/administration/plugins.md b/doc/administration/plugins.md index c91ac3012b9..dedb1f913d7 100644 --- a/doc/administration/plugins.md +++ b/doc/administration/plugins.md @@ -1,5 +1,9 @@ # Plugins +**Note:** Instead of writing and supporting your own plugin you can make changes +directly to the GitLab source code and contribute it back to the upstream. This way we can +ensure functionality is preserved across versions and covered by tests. + **Note:** Plugins must be configured on the filesystem of the GitLab server. Only GitLab server administrators will be able to complete these tasks. Please explore [system hooks] or [webhooks] as an option if you do not -- cgit v1.2.3 From 43ef375e084884ed4260ac9c9de8f601d5594c90 Mon Sep 17 00:00:00 2001 From: Shah El-Rahman Date: Fri, 6 Apr 2018 09:36:22 +0000 Subject: Add confirmation modal to "Change username" --- .../profile/account/components/update_username.vue | 121 +++++++++++++++ app/assets/javascripts/profile/account/index.js | 15 ++ .../javascripts/vue_shared/components/gl_modal.vue | 77 +++++---- app/controllers/profiles_controller.rb | 18 ++- app/views/profiles/accounts/show.html.haml | 16 +- ...g-username-url-still-redirects-to-old-route.yml | 5 + spec/controllers/profiles_controller_spec.rb | 22 +++ spec/features/profile_spec.rb | 8 +- spec/features/profiles/account_spec.rb | 12 +- .../account/components/update_username_spec.js | 172 +++++++++++++++++++++ 10 files changed, 400 insertions(+), 66 deletions(-) create mode 100644 app/assets/javascripts/profile/account/components/update_username.vue create mode 100644 changelogs/unreleased/41758-after-changing-username-url-still-redirects-to-old-route.yml create mode 100644 spec/javascripts/profile/account/components/update_username_spec.js diff --git a/app/assets/javascripts/profile/account/components/update_username.vue b/app/assets/javascripts/profile/account/components/update_username.vue new file mode 100644 index 00000000000..e5de3f69b01 --- /dev/null +++ b/app/assets/javascripts/profile/account/components/update_username.vue @@ -0,0 +1,121 @@ + + diff --git a/app/assets/javascripts/profile/account/index.js b/app/assets/javascripts/profile/account/index.js index 84049a1f0b7..59c13e1a042 100644 --- a/app/assets/javascripts/profile/account/index.js +++ b/app/assets/javascripts/profile/account/index.js @@ -1,10 +1,25 @@ import Vue from 'vue'; import Translate from '~/vue_shared/translate'; +import UpdateUsername from './components/update_username.vue'; import deleteAccountModal from './components/delete_account_modal.vue'; export default () => { Vue.use(Translate); + const updateUsernameElement = document.getElementById('update-username'); + // eslint-disable-next-line no-new + new Vue({ + el: updateUsernameElement, + components: { + UpdateUsername, + }, + render(createElement) { + return createElement('update-username', { + props: { ...updateUsernameElement.dataset }, + }); + }, + }); + const deleteAccountButton = document.getElementById('delete-account-button'); const deleteAccountModalEl = document.getElementById('delete-account-modal'); // eslint-disable-next-line no-new diff --git a/app/assets/javascripts/vue_shared/components/gl_modal.vue b/app/assets/javascripts/vue_shared/components/gl_modal.vue index 67c9181c7b1..f28e5e2715d 100644 --- a/app/assets/javascripts/vue_shared/components/gl_modal.vue +++ b/app/assets/javascripts/vue_shared/components/gl_modal.vue @@ -1,47 +1,42 @@