diff options
author | Steve Azzopardi <steveazz@outlook.com> | 2018-10-18 09:36:24 +0200 |
---|---|---|
committer | Filipa Lacerda <filipa@gitlab.com> | 2018-11-02 10:03:41 +0000 |
commit | 6d49e882d9f5ab5d397e15221f299c979e030b09 (patch) | |
tree | 10d57c37623e0037fedee55f1a6043693f782c9a | |
parent | 6ebbd70fbb3bfbda9745ad16ec1cd26ad41366c5 (diff) | |
download | gitlab-ce-52202-consider-moving-isjobstuck-verification-to-backend-11-4.tar.gz |
Add stuck field in BuildDetailEntity52202-consider-moving-isjobstuck-verification-to-backend-11-4
Frontend currently defines when a job is stuck, which we already have in
the backend, expose `stuck` field in the
`Project::JobsController#show.json` so the duplication of the logic is
removed.
Use `stuck` flag from API
Removes isJobStuck check from frontend and uses
the flag being provided by the API
Renders missing tags message
Moves available runners check into a computed prop
Fix changelog for stuck job
-rw-r--r-- | app/assets/javascripts/jobs/components/job_app.vue | 6 | ||||
-rw-r--r-- | app/assets/javascripts/jobs/components/stuck_block.vue | 16 | ||||
-rw-r--r-- | app/assets/javascripts/jobs/store/getters.js | 11 | ||||
-rw-r--r-- | app/serializers/build_details_entity.rb | 1 | ||||
-rw-r--r-- | changelogs/unreleased/52202-consider-moving-isjobstuck-verification-to-backend-11-4.yml | 5 | ||||
-rw-r--r-- | spec/controllers/projects/jobs_controller_spec.rb | 2 | ||||
-rw-r--r-- | spec/features/projects/jobs_spec.rb | 56 | ||||
-rw-r--r-- | spec/fixtures/api/schemas/job/job_details.json | 3 | ||||
-rw-r--r-- | spec/javascripts/jobs/components/job_app_spec.js | 100 | ||||
-rw-r--r-- | spec/javascripts/jobs/store/getters_spec.js | 30 |
10 files changed, 148 insertions, 82 deletions
diff --git a/app/assets/javascripts/jobs/components/job_app.vue b/app/assets/javascripts/jobs/components/job_app.vue index 4e8d3ad24cc..a32e2d2ac95 100644 --- a/app/assets/javascripts/jobs/components/job_app.vue +++ b/app/assets/javascripts/jobs/components/job_app.vue @@ -32,9 +32,9 @@ 'shouldRenderCalloutMessage', 'shouldRenderTriggeredLabel', 'hasEnvironment', - 'isJobStuck', 'hasTrace', 'emptyStateIllustration', + 'hasRunnersForProject', ]), }, }; @@ -72,9 +72,9 @@ <!-- Body Section --> <stuck-block - v-if="isJobStuck" + v-if="job.stuck" class="js-job-stuck" - :has-no-runners-for-project="job.runners.available" + :has-no-runners-for-project="hasRunnersForProject" :tags="job.tags" :runners-path="runnerSettingsUrl" /> diff --git a/app/assets/javascripts/jobs/components/stuck_block.vue b/app/assets/javascripts/jobs/components/stuck_block.vue index a60643b2c65..1d5789b175a 100644 --- a/app/assets/javascripts/jobs/components/stuck_block.vue +++ b/app/assets/javascripts/jobs/components/stuck_block.vue @@ -23,14 +23,7 @@ export default { <template> <div class="bs-callout bs-callout-warning"> <p - v-if="hasNoRunnersForProject" - class="js-stuck-no-runners append-bottom-0" - > - {{ s__(`Job|This job is stuck, because the project - doesn't have any runners online assigned to it.`) }} - </p> - <p - v-else-if="tags.length" + v-if="tags.length" class="js-stuck-with-tags append-bottom-0" > {{ s__(`This job is stuck, because you don't have @@ -44,6 +37,13 @@ export default { </span> </p> <p + v-else-if="hasNoRunnersForProject" + class="js-stuck-no-runners append-bottom-0" + > + {{ s__(`Job|This job is stuck, because the project + doesn't have any runners online assigned to it.`) }} + </p> + <p v-else class="js-stuck-no-active-runner append-bottom-0" > diff --git a/app/assets/javascripts/jobs/store/getters.js b/app/assets/javascripts/jobs/store/getters.js index 9f4f372e3d2..e1d163d8eee 100644 --- a/app/assets/javascripts/jobs/store/getters.js +++ b/app/assets/javascripts/jobs/store/getters.js @@ -39,15 +39,8 @@ export const hasTrace = state => state.job.has_trace || state.job.status.group = export const emptyStateIllustration = state => (state.job && state.job.status && state.job.status.illustration) || {}; -/** - * When the job is pending and there are no available runners - * we need to render the stuck block; - * - * @returns {Boolean} - */ -export const isJobStuck = state => - state.job.status.group === 'pending' && - (!_.isEmpty(state.job.runners) && state.job.runners.available === false); +export const hasRunnersForProject = state => state.job.runners.available + && !state.job.runners.online; // prevent babel-plugin-rewire from generating an invalid default during karma tests export default () => {}; diff --git a/app/serializers/build_details_entity.rb b/app/serializers/build_details_entity.rb index 066a5b1885c..9ddce0d2c80 100644 --- a/app/serializers/build_details_entity.rb +++ b/app/serializers/build_details_entity.rb @@ -5,6 +5,7 @@ class BuildDetailsEntity < JobEntity expose :tag_list, as: :tags expose :has_trace?, as: :has_trace expose :stage + expose :stuck?, as: :stuck expose :user, using: UserEntity expose :runner, using: RunnerEntity expose :pipeline, using: PipelineEntity diff --git a/changelogs/unreleased/52202-consider-moving-isjobstuck-verification-to-backend-11-4.yml b/changelogs/unreleased/52202-consider-moving-isjobstuck-verification-to-backend-11-4.yml new file mode 100644 index 00000000000..e32ad09bf94 --- /dev/null +++ b/changelogs/unreleased/52202-consider-moving-isjobstuck-verification-to-backend-11-4.yml @@ -0,0 +1,5 @@ +--- +title: Fix stuck job warning message +merge_request: 8060 +author: +type: fixed diff --git a/spec/controllers/projects/jobs_controller_spec.rb b/spec/controllers/projects/jobs_controller_spec.rb index 2a32b555863..26272785b25 100644 --- a/spec/controllers/projects/jobs_controller_spec.rb +++ b/spec/controllers/projects/jobs_controller_spec.rb @@ -297,6 +297,7 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do expect(response).to match_response_schema('job/job_details') expect(json_response['runners']['online']).to be false expect(json_response['runners']['available']).to be false + expect(json_response['stuck']).to be true end end @@ -309,6 +310,7 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do expect(response).to match_response_schema('job/job_details') expect(json_response['runners']['online']).to be false expect(json_response['runners']['available']).to be true + expect(json_response['stuck']).to be true end end diff --git a/spec/features/projects/jobs_spec.rb b/spec/features/projects/jobs_spec.rb index a3a301504ff..24520d0aecb 100644 --- a/spec/features/projects/jobs_spec.rb +++ b/spec/features/projects/jobs_spec.rb @@ -738,6 +738,62 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do expect(page).not_to have_css('.js-build-sidebar.right-sidebar-collpased') end end + + context 'stuck', :js do + before do + visit project_job_path(project, job) + wait_for_requests + end + + context 'without active runners available' do + let(:runner) { create(:ci_runner, :instance, active: false) } + let(:job) { create(:ci_build, :pending, pipeline: pipeline, runner: runner) } + + it 'renders message about job being stuck because no runners are active' do + expect(page).to have_css('.js-stuck-no-active-runner') + expect(page).to have_content("This job is stuck, because you don't have any active runners that can run this job.") + end + end + + context 'when available runners can not run specified tag' do + let(:runner) { create(:ci_runner, :instance, active: false) } + let(:job) { create(:ci_build, :pending, pipeline: pipeline, runner: runner, tag_list: %w(docker linux)) } + + it 'renders message about job being stuck because of no runners with the specified tags' do + expect(page).to have_css('.js-stuck-with-tags') + expect(page).to have_content("This job is stuck, because you don't have any active runners online with any of these tags assigned to them:") + end + end + + context 'when runners are offline and build has tags' do + let(:runner) { create(:ci_runner, :instance, active: true) } + let(:job) { create(:ci_build, :pending, pipeline: pipeline, runner: runner, tag_list: %w(docker linux)) } + + it 'renders message about job being stuck because of no runners with the specified tags' do + expect(page).to have_css('.js-stuck-with-tags') + expect(page).to have_content("This job is stuck, because you don't have any active runners online with any of these tags assigned to them:") + end + end + + context 'without any runners available' do + let(:job) { create(:ci_build, :pending, pipeline: pipeline) } + + it 'renders message about job being stuck because not runners are available' do + expect(page).to have_css('.js-stuck-no-active-runner') + expect(page).to have_content("This job is stuck, because you don't have any active runners that can run this job.") + end + end + + context 'without available runners online' do + let(:runner) { create(:ci_runner, :instance, active: true) } + let(:job) { create(:ci_build, :pending, pipeline: pipeline, runner: runner) } + + it 'renders message about job being stuck because runners are offline' do + expect(page).to have_css('.js-stuck-no-runners') + expect(page).to have_content("This job is stuck, because the project doesn't have any runners online assigned to it.") + end + end + end end describe "POST /:project/jobs/:id/cancel", :js do diff --git a/spec/fixtures/api/schemas/job/job_details.json b/spec/fixtures/api/schemas/job/job_details.json index 8218474705c..cdf7b049ab6 100644 --- a/spec/fixtures/api/schemas/job/job_details.json +++ b/spec/fixtures/api/schemas/job/job_details.json @@ -18,6 +18,7 @@ "runner": { "$ref": "runner.json" }, "runners": { "$ref": "runners.json" }, "has_trace": { "type": "boolean" }, - "stage": { "type": "string" } + "stage": { "type": "string" }, + "stuck": { "type": "boolean" } } } diff --git a/spec/javascripts/jobs/components/job_app_spec.js b/spec/javascripts/jobs/components/job_app_spec.js index 6e0bcf801cd..223c1a3cb1b 100644 --- a/spec/javascripts/jobs/components/job_app_spec.js +++ b/spec/javascripts/jobs/components/job_app_spec.js @@ -128,59 +128,73 @@ describe('Job App ', () => { }); describe('stuck block', () => { - it('renders stuck block when there are no runners', () => { - store.dispatch( - 'receiveJobSuccess', - Object.assign({}, job, { - status: { - group: 'pending', - icon: 'status_pending', - label: 'pending', - text: 'pending', - details_path: 'path', - }, - }), - ); + describe('without active runners availabl', () => { + it('renders stuck block when there are no runners', () => { + store.dispatch('receiveJobSuccess', + Object.assign({}, job, { + stuck: true, + runners: { + available: false, + online: false, + }, + tags: [], + }), + ); + vm = mountComponentWithStore(Component, { props, store }); - vm = mountComponentWithStore(Component, { - props, - store, + expect(vm.$el.querySelector('.js-job-stuck')).not.toBeNull(); + expect(vm.$el.querySelector('.js-job-stuck').textContent).toContain( + "This job is stuck, because you don't have any active runners that can run this job.", + ); }); - - expect(vm.$el.querySelector('.js-job-stuck')).not.toBeNull(); }); - it('renders tags in stuck block when there are no runners', () => { - store.dispatch( - 'receiveJobSuccess', - Object.assign({}, job, { - status: { - group: 'pending', - icon: 'status_pending', - label: 'pending', - text: 'pending', - details_path: 'path', - }, - }), - ); + describe('when available runners can not run specified tag', () => { + it('renders tags in stuck block when there are no runners', () => { + store.dispatch('receiveJobSuccess', + Object.assign({}, job, { + stuck: true, + runners: { + available: false, + online: false, + }, + }), + ); - vm = mountComponentWithStore(Component, { - props, - store, - }); + vm = mountComponentWithStore(Component, { + props, + store, + }); - expect(vm.$el.querySelector('.js-job-stuck').textContent).toContain(job.tags[0]); + expect(vm.$el.querySelector('.js-job-stuck').textContent).toContain(job.tags[0]); + expect(vm.$el.querySelector('.js-job-stuck').textContent).toContain( + "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:", + ); + }); }); - it(' does not renders stuck block when there are no runners', () => { - store.dispatch('receiveJobSuccess', Object.assign({}, job, { runners: { available: true } })); + describe('when runners are offline and build has tags', () => { + it('renders message about job being stuck because of no runners with the specified tags', () => { + store.dispatch('receiveJobSuccess', + Object.assign({}, job, { + stuck: true, + runners: { + available: true, + online: true, + }, + }), + ); - vm = mountComponentWithStore(Component, { - props, - store, - }); + vm = mountComponentWithStore(Component, { + props, + store, + }); - expect(vm.$el.querySelector('.js-job-stuck')).toBeNull(); + expect(vm.$el.querySelector('.js-job-stuck').textContent).toContain(job.tags[0]); + expect(vm.$el.querySelector('.js-job-stuck').textContent).toContain( + "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:", + ); + }); }); }); diff --git a/spec/javascripts/jobs/store/getters_spec.js b/spec/javascripts/jobs/store/getters_spec.js index e262a47b837..78d3fc9e908 100644 --- a/spec/javascripts/jobs/store/getters_spec.js +++ b/spec/javascripts/jobs/store/getters_spec.js @@ -170,43 +170,37 @@ describe('Job Store Getters', () => { }); }); - describe('isJobStuck', () => { - describe('when job is pending and runners are not available', () => { + describe('hasRunnersForProject', () => { + describe('with available and offline runners', () => { it('returns true', () => { - localState.job.status = { - group: 'pending', - }; localState.job.runners = { - available: false, + available: true, + online: false, }; - expect(getters.isJobStuck(localState)).toEqual(true); + expect(getters.hasRunnersForProject(localState)).toEqual(true); }); }); - describe('when job is not pending', () => { + describe('with non available runners', () => { it('returns false', () => { - localState.job.status = { - group: 'running', - }; localState.job.runners = { available: false, + online: false, }; - expect(getters.isJobStuck(localState)).toEqual(false); + expect(getters.hasRunnersForProject(localState)).toEqual(false); }); }); - describe('when runners are available', () => { + describe('with online runners', () => { it('returns false', () => { - localState.job.status = { - group: 'pending', - }; localState.job.runners = { - available: true, + available: false, + online: true, }; - expect(getters.isJobStuck(localState)).toEqual(false); + expect(getters.hasRunnersForProject(localState)).toEqual(false); }); }); }); |