Move job stuck status to backend
This commit is contained in:
parent
5726e51aaa
commit
50f703f95a
|
@ -77,11 +77,11 @@
|
|||
'shouldRenderCalloutMessage',
|
||||
'shouldRenderTriggeredLabel',
|
||||
'hasEnvironment',
|
||||
'isJobStuck',
|
||||
'hasTrace',
|
||||
'emptyStateIllustration',
|
||||
'isScrollingDown',
|
||||
'emptyStateAction',
|
||||
'hasRunnersForProject',
|
||||
]),
|
||||
|
||||
shouldRenderContent() {
|
||||
|
@ -195,9 +195,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"
|
||||
/>
|
||||
|
|
|
@ -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
|
||||
|
@ -43,6 +36,13 @@ export default {
|
|||
{{ tag }}
|
||||
</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"
|
||||
|
|
|
@ -41,17 +41,10 @@ export const emptyStateIllustration = state =>
|
|||
(state.job && state.job.status && state.job.status.illustration) || {};
|
||||
|
||||
export const emptyStateAction = state => (state.job && state.job.status && state.job.status.action) || {};
|
||||
/**
|
||||
* When the job is pending and there are no available runners
|
||||
* we need to render the stuck block;
|
||||
*
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
export const isJobStuck = state =>
|
||||
(!_.isEmpty(state.job.status) && state.job.status.group === 'pending') &&
|
||||
(!_.isEmpty(state.job.runners) && state.job.runners.available === false);
|
||||
|
||||
export const isScrollingDown = state => isScrolledToBottom() && !state.isTraceComplete;
|
||||
|
||||
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 () => {};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Renders stuck block when runners are stuck
|
||||
merge_request:
|
||||
author:
|
||||
type: fixed
|
|
@ -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
|
||||
|
||||
|
|
|
@ -721,6 +721,62 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
|
|||
expect(page).not_to have_css('.js-job-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
|
||||
|
|
|
@ -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" }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -88,7 +88,9 @@ describe('Job App ', () => {
|
|||
|
||||
describe('triggered job', () => {
|
||||
beforeEach(() => {
|
||||
mock.onGet(props.endpoint).replyOnce(200, Object.assign({}, job, { started: '2017-05-24T10:59:52.000+01:00' }));
|
||||
mock
|
||||
.onGet(props.endpoint)
|
||||
.replyOnce(200, Object.assign({}, job, { started: '2017-05-24T10:59:52.000+01:00' }));
|
||||
vm = mountComponentWithStore(Component, { props, store });
|
||||
});
|
||||
|
||||
|
@ -133,57 +135,106 @@ describe('Job App ', () => {
|
|||
});
|
||||
|
||||
describe('stuck block', () => {
|
||||
it('renders stuck block when there are no runners', done => {
|
||||
mock.onGet(props.endpoint).replyOnce(
|
||||
200,
|
||||
Object.assign({}, job, {
|
||||
status: {
|
||||
group: 'pending',
|
||||
icon: 'status_pending',
|
||||
label: 'pending',
|
||||
text: 'pending',
|
||||
details_path: 'path',
|
||||
},
|
||||
runners: {
|
||||
available: false,
|
||||
},
|
||||
}),
|
||||
);
|
||||
vm = mountComponentWithStore(Component, { props, store });
|
||||
describe('without active runners availabl', () => {
|
||||
it('renders stuck block when there are no runners', done => {
|
||||
mock.onGet(props.endpoint).replyOnce(
|
||||
200,
|
||||
Object.assign({}, job, {
|
||||
status: {
|
||||
group: 'pending',
|
||||
icon: 'status_pending',
|
||||
label: 'pending',
|
||||
text: 'pending',
|
||||
details_path: 'path',
|
||||
},
|
||||
stuck: true,
|
||||
runners: {
|
||||
available: false,
|
||||
online: false,
|
||||
},
|
||||
tags: [],
|
||||
}),
|
||||
);
|
||||
vm = mountComponentWithStore(Component, { props, store });
|
||||
|
||||
setTimeout(() => {
|
||||
expect(vm.$el.querySelector('.js-job-stuck')).not.toBeNull();
|
||||
|
||||
done();
|
||||
}, 0);
|
||||
setTimeout(() => {
|
||||
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.",
|
||||
);
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
});
|
||||
|
||||
it('renders tags in stuck block when there are no runners', done => {
|
||||
mock.onGet(props.endpoint).replyOnce(
|
||||
200,
|
||||
Object.assign({}, job, {
|
||||
status: {
|
||||
group: 'pending',
|
||||
icon: 'status_pending',
|
||||
label: 'pending',
|
||||
text: 'pending',
|
||||
details_path: 'path',
|
||||
},
|
||||
runners: {
|
||||
available: false,
|
||||
},
|
||||
}),
|
||||
);
|
||||
describe('when available runners can not run specified tag', () => {
|
||||
it('renders tags in stuck block when there are no runners', done => {
|
||||
mock.onGet(props.endpoint).replyOnce(
|
||||
200,
|
||||
Object.assign({}, job, {
|
||||
status: {
|
||||
group: 'pending',
|
||||
icon: 'status_pending',
|
||||
label: 'pending',
|
||||
text: 'pending',
|
||||
details_path: 'path',
|
||||
},
|
||||
stuck: true,
|
||||
runners: {
|
||||
available: false,
|
||||
online: false,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
vm = mountComponentWithStore(Component, {
|
||||
props,
|
||||
store,
|
||||
vm = mountComponentWithStore(Component, {
|
||||
props,
|
||||
store,
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
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:",
|
||||
);
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
expect(vm.$el.querySelector('.js-job-stuck').textContent).toContain(job.tags[0]);
|
||||
done();
|
||||
}, 0);
|
||||
describe('when runners are offline and build has tags', () => {
|
||||
it('renders message about job being stuck because of no runners with the specified tags', done => {
|
||||
mock.onGet(props.endpoint).replyOnce(
|
||||
200,
|
||||
Object.assign({}, job, {
|
||||
status: {
|
||||
group: 'pending',
|
||||
icon: 'status_pending',
|
||||
label: 'pending',
|
||||
text: 'pending',
|
||||
details_path: 'path',
|
||||
},
|
||||
stuck: true,
|
||||
runners: {
|
||||
available: true,
|
||||
online: true,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
vm = mountComponentWithStore(Component, {
|
||||
props,
|
||||
store,
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
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:",
|
||||
);
|
||||
done();
|
||||
}, 0);
|
||||
})
|
||||
});
|
||||
|
||||
it('does not renders stuck block when there are no runners', done => {
|
||||
|
@ -418,10 +469,11 @@ describe('Job App ', () => {
|
|||
vm.$store.state.trace = 'Update';
|
||||
|
||||
setTimeout(() => {
|
||||
expect(vm.$el.querySelector('.js-build-trace').textContent.trim()).not.toContain('Update');
|
||||
expect(vm.$el.querySelector('.js-build-trace').textContent.trim()).toContain(
|
||||
'Different',
|
||||
expect(vm.$el.querySelector('.js-build-trace').textContent.trim()).not.toContain(
|
||||
'Update',
|
||||
);
|
||||
|
||||
expect(vm.$el.querySelector('.js-build-trace').textContent.trim()).toContain('Different');
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
|
|
|
@ -175,43 +175,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,
|
||||
};
|
||||
|
||||
expect(getters.isJobStuck(localState)).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when job is not pending', () => {
|
||||
it('returns false', () => {
|
||||
localState.job.status = {
|
||||
group: 'running',
|
||||
};
|
||||
localState.job.runners = {
|
||||
available: false,
|
||||
};
|
||||
|
||||
expect(getters.isJobStuck(localState)).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when runners are available', () => {
|
||||
it('returns false', () => {
|
||||
localState.job.status = {
|
||||
group: 'pending',
|
||||
};
|
||||
localState.job.runners = {
|
||||
available: true,
|
||||
online: false
|
||||
};
|
||||
|
||||
expect(getters.isJobStuck(localState)).toEqual(false);
|
||||
expect(getters.hasRunnersForProject(localState)).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('with non available runners', () => {
|
||||
it('returns false', () => {
|
||||
localState.job.runners = {
|
||||
available: false,
|
||||
online: false
|
||||
};
|
||||
|
||||
expect(getters.hasRunnersForProject(localState)).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('with online runners', () => {
|
||||
it('returns false', () => {
|
||||
localState.job.runners = {
|
||||
available: false,
|
||||
online: true
|
||||
};
|
||||
|
||||
expect(getters.hasRunnersForProject(localState)).toEqual(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue