Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-03-25 15:08:19 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-03-25 15:08:19 +0300
commite6baeabaa9651d90b03bb64ffce75a2c3cb89aab (patch)
tree85f3cbd6e437b17be59505cf3ac4794c1838609e /spec
parent5064bf8c5647d4c4430cbb4d097cf1592416de29 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/controllers/dashboard_controller_spec.rb4
-rw-r--r--spec/factories/ci/builds.rb4
-rw-r--r--spec/factories/snippets.rb2
-rw-r--r--spec/frontend/registry/explorer/pages/details_spec.js63
-rw-r--r--spec/frontend/registry/explorer/pages/index_spec.js62
-rw-r--r--spec/frontend/registry/explorer/pages/list_spec.js41
-rw-r--r--spec/frontend/registry/explorer/stores/actions_spec.js67
-rw-r--r--spec/frontend/registry/explorer/stores/getters_spec.js18
-rw-r--r--spec/frontend/registry/explorer/stores/mutations_spec.js16
-rw-r--r--spec/frontend/registry/shared/mocks.js4
-rw-r--r--spec/helpers/events_helper_spec.rb79
-rw-r--r--spec/lib/gitlab/ci/build/image_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/config/entry/image_spec.rb16
-rw-r--r--spec/lib/gitlab/ci/config/entry/root_spec.rb14
-rw-r--r--spec/lib/gitlab/ci/config/external/file/project_spec.rb4
-rw-r--r--spec/lib/gitlab/ci/config/external/mapper_spec.rb26
-rw-r--r--spec/lib/gitlab/ci/config/external/processor_spec.rb20
-rw-r--r--spec/lib/gitlab/ci/config_spec.rb26
-rw-r--r--spec/lib/gitlab/ci/yaml_processor_spec.rb20
-rw-r--r--spec/lib/gitlab/config/loader/yaml_spec.rb4
-rw-r--r--spec/lib/gitlab/import_export/snippet_repo_restorer_spec.rb13
-rw-r--r--spec/models/ci/build_spec.rb6
-rw-r--r--spec/models/project_services/buildkite_service_spec.rb18
-rw-r--r--spec/models/project_services/drone_ci_service_spec.rb4
-rw-r--r--spec/models/snippet_repository_spec.rb2
-rw-r--r--spec/models/snippet_spec.rb34
-rw-r--r--spec/requests/api/lint_spec.rb2
-rw-r--r--spec/requests/api/runner_spec.rb2
-rw-r--r--spec/services/ci/create_pipeline_service_spec.rb10
-rw-r--r--spec/services/projects/container_repository/cleanup_tags_service_spec.rb93
30 files changed, 494 insertions, 182 deletions
diff --git a/spec/controllers/dashboard_controller_spec.rb b/spec/controllers/dashboard_controller_spec.rb
index 305419efe96..a280d829d83 100644
--- a/spec/controllers/dashboard_controller_spec.rb
+++ b/spec/controllers/dashboard_controller_spec.rb
@@ -31,6 +31,8 @@ describe DashboardController do
before do
create(:event, :created, project: project, target: create(:issue))
+ create(:wiki_page_event, :created, project: project)
+ create(:wiki_page_event, :updated, project: project)
sign_in(user)
@@ -45,7 +47,7 @@ describe DashboardController do
it 'returns count' do
get :activity, params: { format: :json }
- expect(json_response['count']).to eq(1)
+ expect(json_response['count']).to eq(3)
end
end
diff --git a/spec/factories/ci/builds.rb b/spec/factories/ci/builds.rb
index 446c1c59030..5bb7853a154 100644
--- a/spec/factories/ci/builds.rb
+++ b/spec/factories/ci/builds.rb
@@ -16,7 +16,7 @@ FactoryBot.define do
options do
{
- image: 'ruby:2.1',
+ image: 'ruby:2.7',
services: ['postgres'],
script: ['ls -a']
}
@@ -336,7 +336,7 @@ FactoryBot.define do
trait :extended_options do
options do
{
- image: { name: 'ruby:2.1', entrypoint: '/bin/sh' },
+ image: { name: 'ruby:2.7', entrypoint: '/bin/sh' },
services: ['postgres', { name: 'docker:stable-dind', entrypoint: '/bin/sh', command: 'sleep 30', alias: 'docker' }],
script: %w(echo),
after_script: %w(ls date),
diff --git a/spec/factories/snippets.rb b/spec/factories/snippets.rb
index 3d99a04ea1a..21e1d911f96 100644
--- a/spec/factories/snippets.rb
+++ b/spec/factories/snippets.rb
@@ -28,7 +28,7 @@ FactoryBot.define do
bare_repo: TestEnv.factory_repo_path_bare,
refs: TestEnv::BRANCH_SHA)
- snippet.track_snippet_repository
+ snippet.track_snippet_repository(snippet.repository.storage)
end
end
diff --git a/spec/frontend/registry/explorer/pages/details_spec.js b/spec/frontend/registry/explorer/pages/details_spec.js
index 660004e5eea..60e509e4a88 100644
--- a/spec/frontend/registry/explorer/pages/details_spec.js
+++ b/spec/frontend/registry/explorer/pages/details_spec.js
@@ -5,8 +5,15 @@ import stubChildren from 'helpers/stub_children';
import component from '~/registry/explorer/pages/details.vue';
import store from '~/registry/explorer/stores/';
import { SET_MAIN_LOADING } from '~/registry/explorer/stores/mutation_types/';
+import {
+ DELETE_TAG_SUCCESS_MESSAGE,
+ DELETE_TAG_ERROR_MESSAGE,
+ DELETE_TAGS_SUCCESS_MESSAGE,
+ DELETE_TAGS_ERROR_MESSAGE,
+} from '~/registry/explorer/constants';
import { tagsListResponse } from '../mock_data';
import { GlModal } from '../stubs';
+import { $toast } from '../../shared/mocks';
describe('Details Page', () => {
let wrapper;
@@ -40,6 +47,7 @@ describe('Details Page', () => {
id: routeId,
},
},
+ $toast,
},
});
dispatchSpy = jest.spyOn(store, 'dispatch');
@@ -249,13 +257,11 @@ describe('Details Page', () => {
});
});
- it('when only one element is selected', () => {
- const deleteModal = findDeleteModal();
-
- wrapper.setData({ itemsToBeDeleted: [0] });
- deleteModal.vm.$emit('ok');
+ describe('when only one element is selected', () => {
+ it('execute the delete and remove selection', () => {
+ wrapper.setData({ itemsToBeDeleted: [0] });
+ findDeleteModal().vm.$emit('ok');
- return wrapper.vm.$nextTick().then(() => {
expect(store.dispatch).toHaveBeenCalledWith('requestDeleteTag', {
tag: store.state.tags[0],
params: wrapper.vm.$route.params.id,
@@ -264,15 +270,33 @@ describe('Details Page', () => {
expect(wrapper.vm.itemsToBeDeleted).toEqual([]);
expect(findCheckedCheckboxes()).toHaveLength(0);
});
+
+ it('show success toast on successful delete', () => {
+ return wrapper.vm.handleSingleDelete(0).then(() => {
+ expect(wrapper.vm.$toast.show).toHaveBeenCalledWith(DELETE_TAG_SUCCESS_MESSAGE, {
+ type: 'success',
+ });
+ });
+ });
+
+ it('show error toast on erred delete', () => {
+ dispatchSpy.mockRejectedValue();
+ return wrapper.vm.handleSingleDelete(0).then(() => {
+ expect(wrapper.vm.$toast.show).toHaveBeenCalledWith(DELETE_TAG_ERROR_MESSAGE, {
+ type: 'error',
+ });
+ });
+ });
});
- it('when multiple elements are selected', () => {
- const deleteModal = findDeleteModal();
+ describe('when multiple elements are selected', () => {
+ beforeEach(() => {
+ wrapper.setData({ itemsToBeDeleted: [0, 1] });
+ });
- wrapper.setData({ itemsToBeDeleted: [0, 1] });
- deleteModal.vm.$emit('ok');
+ it('execute the delete and remove selection', () => {
+ findDeleteModal().vm.$emit('ok');
- return wrapper.vm.$nextTick().then(() => {
expect(store.dispatch).toHaveBeenCalledWith('requestDeleteTags', {
ids: store.state.tags.map(t => t.name),
params: wrapper.vm.$route.params.id,
@@ -281,6 +305,23 @@ describe('Details Page', () => {
expect(wrapper.vm.itemsToBeDeleted).toEqual([]);
expect(findCheckedCheckboxes()).toHaveLength(0);
});
+
+ it('show success toast on successful delete', () => {
+ return wrapper.vm.handleMultipleDelete(0).then(() => {
+ expect(wrapper.vm.$toast.show).toHaveBeenCalledWith(DELETE_TAGS_SUCCESS_MESSAGE, {
+ type: 'success',
+ });
+ });
+ });
+
+ it('show error toast on erred delete', () => {
+ dispatchSpy.mockRejectedValue();
+ return wrapper.vm.handleMultipleDelete(0).then(() => {
+ expect(wrapper.vm.$toast.show).toHaveBeenCalledWith(DELETE_TAGS_ERROR_MESSAGE, {
+ type: 'error',
+ });
+ });
+ });
});
});
diff --git a/spec/frontend/registry/explorer/pages/index_spec.js b/spec/frontend/registry/explorer/pages/index_spec.js
new file mode 100644
index 00000000000..f52e7d67866
--- /dev/null
+++ b/spec/frontend/registry/explorer/pages/index_spec.js
@@ -0,0 +1,62 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlAlert, GlSprintf, GlLink } from '@gitlab/ui';
+import component from '~/registry/explorer/pages/index.vue';
+import store from '~/registry/explorer/stores/';
+
+describe('List Page', () => {
+ let wrapper;
+ let dispatchSpy;
+
+ const findRouterView = () => wrapper.find({ ref: 'router-view' });
+ const findAlert = () => wrapper.find(GlAlert);
+ const findLink = () => wrapper.find(GlLink);
+
+ const mountComponent = () => {
+ wrapper = shallowMount(component, {
+ store,
+ stubs: {
+ RouterView: true,
+ GlSprintf,
+ },
+ });
+ };
+
+ beforeEach(() => {
+ dispatchSpy = jest.spyOn(store, 'dispatch');
+ mountComponent();
+ });
+
+ it('has a router view', () => {
+ expect(findRouterView().exists()).toBe(true);
+ });
+
+ describe('garbageCollectionTip alert', () => {
+ beforeEach(() => {
+ store.dispatch('setInitialState', { isAdmin: true, garbageCollectionHelpPagePath: 'foo' });
+ store.dispatch('setShowGarbageCollectionTip', true);
+ });
+
+ afterEach(() => {
+ store.dispatch('setInitialState', {});
+ store.dispatch('setShowGarbageCollectionTip', false);
+ });
+
+ it('is visible when the user is an admin and the user performed a delete action', () => {
+ expect(findAlert().exists()).toBe(true);
+ });
+
+ it('on dismiss disappears ', () => {
+ findAlert().vm.$emit('dismiss');
+ expect(dispatchSpy).toHaveBeenCalledWith('setShowGarbageCollectionTip', false);
+ return wrapper.vm.$nextTick().then(() => {
+ expect(findAlert().exists()).toBe(false);
+ });
+ });
+
+ it('contains a link to the docs', () => {
+ const link = findLink();
+ expect(link.exists()).toBe(true);
+ expect(link.attributes('href')).toBe(store.state.config.garbageCollectionHelpPagePath);
+ });
+ });
+});
diff --git a/spec/frontend/registry/explorer/pages/list_spec.js b/spec/frontend/registry/explorer/pages/list_spec.js
index 5b713778495..3e46a29f776 100644
--- a/spec/frontend/registry/explorer/pages/list_spec.js
+++ b/spec/frontend/registry/explorer/pages/list_spec.js
@@ -8,8 +8,13 @@ import GroupEmptyState from '~/registry/explorer/components/group_empty_state.vu
import ProjectEmptyState from '~/registry/explorer/components/project_empty_state.vue';
import store from '~/registry/explorer/stores/';
import { SET_MAIN_LOADING } from '~/registry/explorer/stores/mutation_types/';
+import {
+ DELETE_IMAGE_SUCCESS_MESSAGE,
+ DELETE_IMAGE_ERROR_MESSAGE,
+} from '~/registry/explorer/constants';
import { imagesListResponse } from '../mock_data';
import { GlModal, GlEmptyState } from '../stubs';
+import { $toast } from '../../shared/mocks';
const localVue = createLocalVue();
localVue.use(VueRouter);
@@ -40,6 +45,9 @@ describe('List Page', () => {
GlEmptyState,
GlSprintf,
},
+ mocks: {
+ $toast,
+ },
});
dispatchSpy = jest.spyOn(store, 'dispatch');
store.dispatch('receiveImagesListSuccess', imagesListResponse);
@@ -174,11 +182,29 @@ describe('List Page', () => {
const itemToDelete = wrapper.vm.images[0];
wrapper.setData({ itemToDelete });
findDeleteModal().vm.$emit('ok');
- return wrapper.vm.$nextTick().then(() => {
- expect(store.dispatch).toHaveBeenCalledWith(
- 'requestDeleteImage',
- itemToDelete.destroy_path,
- );
+ expect(store.dispatch).toHaveBeenCalledWith(
+ 'requestDeleteImage',
+ itemToDelete.destroy_path,
+ );
+ });
+
+ it('should show a success toast when delete request is successful', () => {
+ dispatchSpy.mockResolvedValue();
+ return wrapper.vm.handleDeleteImage().then(() => {
+ expect(wrapper.vm.$toast.show).toHaveBeenCalledWith(DELETE_IMAGE_SUCCESS_MESSAGE, {
+ type: 'success',
+ });
+ expect(wrapper.vm.itemToDelete).toEqual({});
+ });
+ });
+
+ it('should show a error toast when delete request fails', () => {
+ dispatchSpy.mockRejectedValue();
+ return wrapper.vm.handleDeleteImage().then(() => {
+ expect(wrapper.vm.$toast.show).toHaveBeenCalledWith(DELETE_IMAGE_ERROR_MESSAGE, {
+ type: 'error',
+ });
+ expect(wrapper.vm.itemToDelete).toEqual({});
});
});
});
@@ -227,7 +253,7 @@ describe('List Page', () => {
beforeEach(() => {
jest.spyOn(Tracking, 'event');
- dispatchSpy.mockReturnValue();
+ dispatchSpy.mockResolvedValue();
});
it('send an event when delete button is clicked', () => {
@@ -235,13 +261,14 @@ describe('List Page', () => {
deleteBtn.vm.$emit('click');
testTrackingCall('click_button');
});
+
it('send an event when cancel is pressed on modal', () => {
const deleteModal = findDeleteModal();
deleteModal.vm.$emit('cancel');
testTrackingCall('cancel_delete');
});
+
it('send an event when confirm is clicked on modal', () => {
- dispatchSpy.mockReturnValue();
const deleteModal = findDeleteModal();
deleteModal.vm.$emit('ok');
testTrackingCall('confirm_delete');
diff --git a/spec/frontend/registry/explorer/stores/actions_spec.js b/spec/frontend/registry/explorer/stores/actions_spec.js
index 3e22621058e..b39c79dd1ab 100644
--- a/spec/frontend/registry/explorer/stores/actions_spec.js
+++ b/spec/frontend/registry/explorer/stores/actions_spec.js
@@ -38,6 +38,17 @@ describe('Actions RegistryExplorer Store', () => {
);
});
+ it('setShowGarbageCollectionTip', done => {
+ testAction(
+ actions.setShowGarbageCollectionTip,
+ true,
+ null,
+ [{ type: types.SET_SHOW_GARBAGE_COLLECTION_TIP, payload: true }],
+ [],
+ done,
+ );
+ });
+
describe('receives api responses', () => {
const response = {
data: [1, 2, 3],
@@ -183,18 +194,19 @@ describe('Actions RegistryExplorer Store', () => {
[{ type: types.SET_MAIN_LOADING, payload: true }],
[
{
+ type: 'setShowGarbageCollectionTip',
+ payload: true,
+ },
+ {
type: 'requestTagsList',
payload: { pagination: {}, params },
},
],
- () => {
- expect(createFlash).toHaveBeenCalled();
- done();
- },
+ done,
);
});
- it('should show flash message on error', done => {
+ it('should turn off loading on error', done => {
testAction(
actions.requestDeleteTag,
{
@@ -208,10 +220,7 @@ describe('Actions RegistryExplorer Store', () => {
{ type: types.SET_MAIN_LOADING, payload: false },
],
[],
- () => {
- expect(createFlash).toHaveBeenCalled();
- done();
- },
+ done,
);
});
});
@@ -235,18 +244,19 @@ describe('Actions RegistryExplorer Store', () => {
[{ type: types.SET_MAIN_LOADING, payload: true }],
[
{
+ type: 'setShowGarbageCollectionTip',
+ payload: true,
+ },
+ {
type: 'requestTagsList',
payload: { pagination: {}, params },
},
],
- () => {
- expect(createFlash).toHaveBeenCalled();
- done();
- },
+ done,
);
});
- it('should show flash message on error', done => {
+ it('should turn off loading on error', done => {
mock.onDelete(url).replyOnce(500);
testAction(
@@ -263,17 +273,14 @@ describe('Actions RegistryExplorer Store', () => {
{ type: types.SET_MAIN_LOADING, payload: false },
],
[],
- () => {
- expect(createFlash).toHaveBeenCalled();
- done();
- },
+ done,
);
});
});
describe('request delete single image', () => {
+ const deletePath = 'delete/path';
it('successfully performs the delete request', done => {
- const deletePath = 'delete/path';
mock.onDelete(deletePath).replyOnce(200);
testAction(
@@ -288,32 +295,32 @@ describe('Actions RegistryExplorer Store', () => {
],
[
{
+ type: 'setShowGarbageCollectionTip',
+ payload: true,
+ },
+ {
type: 'requestImagesList',
payload: { pagination: {} },
},
],
- () => {
- expect(createFlash).toHaveBeenCalled();
- done();
- },
+ done,
);
});
- it('should show flash message on error', done => {
+ it('should turn off loading on error', done => {
+ mock.onDelete(deletePath).replyOnce(400);
testAction(
actions.requestDeleteImage,
- null,
+ deletePath,
{},
[
{ type: types.SET_MAIN_LOADING, payload: true },
{ type: types.SET_MAIN_LOADING, payload: false },
],
[],
- () => {
- expect(createFlash).toHaveBeenCalled();
- done();
- },
- );
+ ).catch(() => {
+ done();
+ });
});
});
});
diff --git a/spec/frontend/registry/explorer/stores/getters_spec.js b/spec/frontend/registry/explorer/stores/getters_spec.js
index 211b8169d82..cd053ea8edc 100644
--- a/spec/frontend/registry/explorer/stores/getters_spec.js
+++ b/spec/frontend/registry/explorer/stores/getters_spec.js
@@ -49,4 +49,22 @@ describe('Getters RegistryExplorer store', () => {
expect(getters[getter](state)).toBe(expectedPieces.join(' '));
});
});
+
+ describe('showGarbageCollection', () => {
+ it.each`
+ result | showGarbageCollectionTip | isAdmin
+ ${true} | ${true} | ${true}
+ ${false} | ${true} | ${false}
+ ${false} | ${false} | ${true}
+ `(
+ 'return $result when showGarbageCollectionTip $showGarbageCollectionTip and isAdmin is $isAdmin',
+ ({ result, showGarbageCollectionTip, isAdmin }) => {
+ state = {
+ config: { isAdmin },
+ showGarbageCollectionTip,
+ };
+ expect(getters.showGarbageCollection(state)).toBe(result);
+ },
+ );
+ });
});
diff --git a/spec/frontend/registry/explorer/stores/mutations_spec.js b/spec/frontend/registry/explorer/stores/mutations_spec.js
index 1d5055c02d2..029fd23f7ce 100644
--- a/spec/frontend/registry/explorer/stores/mutations_spec.js
+++ b/spec/frontend/registry/explorer/stores/mutations_spec.js
@@ -10,7 +10,12 @@ describe('Mutations Registry Explorer Store', () => {
describe('SET_INITIAL_STATE', () => {
it('should set the initial state', () => {
- const payload = { endpoint: 'foo', isGroupPage: true, expirationPolicy: { foo: 'bar' } };
+ const payload = {
+ endpoint: 'foo',
+ isGroupPage: true,
+ expirationPolicy: { foo: 'bar' },
+ isAdmin: true,
+ };
const expectedState = { ...mockState, config: payload };
mutations[types.SET_INITIAL_STATE](mockState, {
...payload,
@@ -50,6 +55,15 @@ describe('Mutations Registry Explorer Store', () => {
});
});
+ describe('SET_SHOW_GARBAGE_COLLECTION_TIP', () => {
+ it('should set the showGarbageCollectionTip', () => {
+ const expectedState = { ...mockState, showGarbageCollectionTip: true };
+ mutations[types.SET_SHOW_GARBAGE_COLLECTION_TIP](mockState, true);
+
+ expect(mockState).toEqual(expectedState);
+ });
+ });
+
describe('SET_PAGINATION', () => {
const generatePagination = () => [
{
diff --git a/spec/frontend/registry/shared/mocks.js b/spec/frontend/registry/shared/mocks.js
new file mode 100644
index 00000000000..e33d06e7499
--- /dev/null
+++ b/spec/frontend/registry/shared/mocks.js
@@ -0,0 +1,4 @@
+// eslint-disable-next-line import/prefer-default-export
+export const $toast = {
+ show: jest.fn(),
+};
diff --git a/spec/helpers/events_helper_spec.rb b/spec/helpers/events_helper_spec.rb
index 61229127770..0109525bcac 100644
--- a/spec/helpers/events_helper_spec.rb
+++ b/spec/helpers/events_helper_spec.rb
@@ -88,6 +88,85 @@ describe EventsHelper do
end
end
+ describe '#event_preposition' do
+ context 'for wiki page events' do
+ let(:event) { create(:wiki_page_event) }
+
+ it 'returns a suitable phrase' do
+ expect(helper.event_preposition(event)).to eq('in the wiki for')
+ end
+ end
+
+ context 'for push action events' do
+ let(:event) { create(:push_event) }
+
+ it 'returns a suitable phrase' do
+ expect(helper.event_preposition(event)).to eq('at')
+ end
+ end
+
+ context 'for commented actions' do
+ let(:event) { create(:event, :commented) }
+
+ it 'returns a suitable phrase' do
+ expect(helper.event_preposition(event)).to eq('at')
+ end
+ end
+
+ context 'for any event with a target' do
+ let(:event) { create(:event, target: create(:issue)) }
+
+ it 'returns a suitable phrase' do
+ expect(helper.event_preposition(event)).to eq('at')
+ end
+ end
+
+ context 'for milestone events' do
+ let(:event) { create(:event, target: create(:milestone)) }
+
+ it 'returns a suitable phrase' do
+ expect(helper.event_preposition(event)).to eq('in')
+ end
+ end
+
+ context 'for non-matching events' do
+ let(:event) { create(:event, :created) }
+
+ it 'returns no preposition' do
+ expect(helper.event_preposition(event)).to be_nil
+ end
+ end
+ end
+
+ describe 'event_wiki_page_target_url' do
+ let(:project) { create(:project) }
+ let(:wiki_page) { create(:wiki_page, wiki: create(:project_wiki, project: project)) }
+ let(:event) { create(:wiki_page_event, project: project, wiki_page: wiki_page) }
+
+ it 'links to the wiki page' do
+ url = helper.project_wiki_url(project, wiki_page.slug)
+
+ expect(helper.event_wiki_page_target_url(event)).to eq(url)
+ end
+ end
+
+ describe '#event_wiki_title_html' do
+ let(:event) { create(:wiki_page_event) }
+
+ it 'produces a suitable title chunk' do
+ url = helper.event_wiki_page_target_url(event)
+ title = event.target_title
+ html = [
+ "<span class=\"event-target-type append-right-4\">wiki page</span>",
+ "<a title=\"#{title}\" class=\"has-tooltip event-target-link append-right-4\" href=\"#{url}\">",
+ title,
+ "</a>"
+ ].join
+
+ expect(helper.event_wiki_title_html(event)).to eq(html)
+ end
+ end
+
describe '#event_note_target_url' do
let(:project) { create(:project, :public, :repository) }
let(:event) { create(:event, project: project) }
diff --git a/spec/lib/gitlab/ci/build/image_spec.rb b/spec/lib/gitlab/ci/build/image_spec.rb
index 04bab9c58b8..4f7cfc9783a 100644
--- a/spec/lib/gitlab/ci/build/image_spec.rb
+++ b/spec/lib/gitlab/ci/build/image_spec.rb
@@ -9,7 +9,7 @@ describe Gitlab::Ci::Build::Image do
subject { described_class.from_image(job) }
context 'when image is defined in job' do
- let(:image_name) { 'ruby:2.1' }
+ let(:image_name) { 'ruby:2.7' }
let(:job) { create(:ci_build, options: { image: image_name } ) }
context 'when image is defined as string' do
diff --git a/spec/lib/gitlab/ci/config/entry/image_spec.rb b/spec/lib/gitlab/ci/config/entry/image_spec.rb
index 8de2e5de724..de3e887a6ed 100644
--- a/spec/lib/gitlab/ci/config/entry/image_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/image_spec.rb
@@ -6,11 +6,11 @@ describe Gitlab::Ci::Config::Entry::Image do
let(:entry) { described_class.new(config) }
context 'when configuration is a string' do
- let(:config) { 'ruby:2.2' }
+ let(:config) { 'ruby:2.7' }
describe '#value' do
it 'returns image hash' do
- expect(entry.value).to eq({ name: 'ruby:2.2' })
+ expect(entry.value).to eq({ name: 'ruby:2.7' })
end
end
@@ -28,7 +28,7 @@ describe Gitlab::Ci::Config::Entry::Image do
describe '#image' do
it "returns image's name" do
- expect(entry.name).to eq 'ruby:2.2'
+ expect(entry.name).to eq 'ruby:2.7'
end
end
@@ -46,7 +46,7 @@ describe Gitlab::Ci::Config::Entry::Image do
end
context 'when configuration is a hash' do
- let(:config) { { name: 'ruby:2.2', entrypoint: %w(/bin/sh run) } }
+ let(:config) { { name: 'ruby:2.7', entrypoint: %w(/bin/sh run) } }
describe '#value' do
it 'returns image hash' do
@@ -68,7 +68,7 @@ describe Gitlab::Ci::Config::Entry::Image do
describe '#image' do
it "returns image's name" do
- expect(entry.name).to eq 'ruby:2.2'
+ expect(entry.name).to eq 'ruby:2.7'
end
end
@@ -80,7 +80,7 @@ describe Gitlab::Ci::Config::Entry::Image do
context 'when configuration has ports' do
let(:ports) { [{ number: 80, protocol: 'http', name: 'foobar' }] }
- let(:config) { { name: 'ruby:2.2', entrypoint: %w(/bin/sh run), ports: ports } }
+ let(:config) { { name: 'ruby:2.7', entrypoint: %w(/bin/sh run), ports: ports } }
let(:entry) { described_class.new(config, { with_image_ports: image_ports }) }
let(:image_ports) { false }
@@ -112,7 +112,7 @@ describe Gitlab::Ci::Config::Entry::Image do
end
context 'when entry value is not correct' do
- let(:config) { ['ruby:2.2'] }
+ let(:config) { ['ruby:2.7'] }
describe '#errors' do
it 'saves errors' do
@@ -129,7 +129,7 @@ describe Gitlab::Ci::Config::Entry::Image do
end
context 'when unexpected key is specified' do
- let(:config) { { name: 'ruby:2.2', non_existing: 'test' } }
+ let(:config) { { name: 'ruby:2.7', non_existing: 'test' } }
describe '#errors' do
it 'saves errors' do
diff --git a/spec/lib/gitlab/ci/config/entry/root_spec.rb b/spec/lib/gitlab/ci/config/entry/root_spec.rb
index c3871b6b3cf..ba2dbf72fba 100644
--- a/spec/lib/gitlab/ci/config/entry/root_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/root_spec.rb
@@ -29,7 +29,7 @@ describe Gitlab::Ci::Config::Entry::Root do
let(:hash) do
{
before_script: %w(ls pwd),
- image: 'ruby:2.2',
+ image: 'ruby:2.7',
default: {},
services: ['postgres:9.1', 'mysql:5.5'],
variables: { VAR: 'root' },
@@ -124,7 +124,7 @@ describe Gitlab::Ci::Config::Entry::Root do
{ name: :rspec,
script: %w[rspec ls],
before_script: %w(ls pwd),
- image: { name: 'ruby:2.2' },
+ image: { name: 'ruby:2.7' },
services: [{ name: 'postgres:9.1' }, { name: 'mysql:5.5' }],
stage: 'test',
cache: { key: 'k', untracked: true, paths: ['public/'], policy: 'pull-push' },
@@ -138,7 +138,7 @@ describe Gitlab::Ci::Config::Entry::Root do
{ name: :spinach,
before_script: [],
script: %w[spinach],
- image: { name: 'ruby:2.2' },
+ image: { name: 'ruby:2.7' },
services: [{ name: 'postgres:9.1' }, { name: 'mysql:5.5' }],
stage: 'test',
cache: { key: 'k', untracked: true, paths: ['public/'], policy: 'pull-push' },
@@ -154,7 +154,7 @@ describe Gitlab::Ci::Config::Entry::Root do
before_script: [],
script: ["make changelog | tee release_changelog.txt"],
release: { name: "Release $CI_TAG_NAME", tag_name: 'v0.06', description: "./release_changelog.txt" },
- image: { name: "ruby:2.2" },
+ image: { name: "ruby:2.7" },
services: [{ name: "postgres:9.1" }, { name: "mysql:5.5" }],
cache: { key: "k", untracked: true, paths: ["public/"], policy: "pull-push" },
only: { refs: %w(branches tags) },
@@ -173,7 +173,7 @@ describe Gitlab::Ci::Config::Entry::Root do
{ before_script: %w(ls pwd),
after_script: ['make clean'],
default: {
- image: 'ruby:2.1',
+ image: 'ruby:2.7',
services: ['postgres:9.1', 'mysql:5.5']
},
variables: { VAR: 'root' },
@@ -200,7 +200,7 @@ describe Gitlab::Ci::Config::Entry::Root do
rspec: { name: :rspec,
script: %w[rspec ls],
before_script: %w(ls pwd),
- image: { name: 'ruby:2.1' },
+ image: { name: 'ruby:2.7' },
services: [{ name: 'postgres:9.1' }, { name: 'mysql:5.5' }],
stage: 'test',
cache: { key: 'k', untracked: true, paths: ['public/'], policy: "pull-push" },
@@ -212,7 +212,7 @@ describe Gitlab::Ci::Config::Entry::Root do
spinach: { name: :spinach,
before_script: [],
script: %w[spinach],
- image: { name: 'ruby:2.1' },
+ image: { name: 'ruby:2.7' },
services: [{ name: 'postgres:9.1' }, { name: 'mysql:5.5' }],
stage: 'test',
cache: { key: 'k', untracked: true, paths: ['public/'], policy: "pull-push" },
diff --git a/spec/lib/gitlab/ci/config/external/file/project_spec.rb b/spec/lib/gitlab/ci/config/external/file/project_spec.rb
index b2924ae9d91..4d8f0dbc861 100644
--- a/spec/lib/gitlab/ci/config/external/file/project_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/file/project_spec.rb
@@ -71,7 +71,7 @@ describe Gitlab::Ci::Config::External::File::Project do
let(:root_ref_sha) { project.repository.root_ref_sha }
before do
- stub_project_blob(root_ref_sha, '/file.yml') { 'image: ruby:2.1' }
+ stub_project_blob(root_ref_sha, '/file.yml') { 'image: ruby:2.7' }
end
it 'returns true' do
@@ -96,7 +96,7 @@ describe Gitlab::Ci::Config::External::File::Project do
let(:ref_sha) { project.commit('master').sha }
before do
- stub_project_blob(ref_sha, '/file.yml') { 'image: ruby:2.1' }
+ stub_project_blob(ref_sha, '/file.yml') { 'image: ruby:2.7' }
end
it 'returns true' do
diff --git a/spec/lib/gitlab/ci/config/external/mapper_spec.rb b/spec/lib/gitlab/ci/config/external/mapper_spec.rb
index 6839002c3ab..fa358f36527 100644
--- a/spec/lib/gitlab/ci/config/external/mapper_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/mapper_spec.rb
@@ -15,7 +15,7 @@ describe Gitlab::Ci::Config::External::Mapper do
let(:file_content) do
<<~HEREDOC
- image: 'ruby:2.2'
+ image: 'ruby:2.7'
HEREDOC
end
@@ -34,7 +34,7 @@ describe Gitlab::Ci::Config::External::Mapper do
context 'when the string is a local file' do
let(:values) do
{ include: local_file,
- image: 'ruby:2.2' }
+ image: 'ruby:2.7' }
end
it 'returns File instances' do
@@ -46,7 +46,7 @@ describe Gitlab::Ci::Config::External::Mapper do
context 'when the key is a local file hash' do
let(:values) do
{ include: { 'local' => local_file },
- image: 'ruby:2.2' }
+ image: 'ruby:2.7' }
end
it 'returns File instances' do
@@ -57,7 +57,7 @@ describe Gitlab::Ci::Config::External::Mapper do
context 'when the string is a remote file' do
let(:values) do
- { include: remote_url, image: 'ruby:2.2' }
+ { include: remote_url, image: 'ruby:2.7' }
end
it 'returns File instances' do
@@ -69,7 +69,7 @@ describe Gitlab::Ci::Config::External::Mapper do
context 'when the key is a remote file hash' do
let(:values) do
{ include: { 'remote' => remote_url },
- image: 'ruby:2.2' }
+ image: 'ruby:2.7' }
end
it 'returns File instances' do
@@ -81,7 +81,7 @@ describe Gitlab::Ci::Config::External::Mapper do
context 'when the key is a template file hash' do
let(:values) do
{ include: { 'template' => template_file },
- image: 'ruby:2.2' }
+ image: 'ruby:2.7' }
end
it 'returns File instances' do
@@ -93,7 +93,7 @@ describe Gitlab::Ci::Config::External::Mapper do
context 'when the key is a hash of file and remote' do
let(:values) do
{ include: { 'local' => local_file, 'remote' => remote_url },
- image: 'ruby:2.2' }
+ image: 'ruby:2.7' }
end
it 'returns ambigious specification error' do
@@ -105,7 +105,7 @@ describe Gitlab::Ci::Config::External::Mapper do
context "when 'include' is defined as an array" do
let(:values) do
{ include: [remote_url, local_file],
- image: 'ruby:2.2' }
+ image: 'ruby:2.7' }
end
it 'returns Files instances' do
@@ -117,7 +117,7 @@ describe Gitlab::Ci::Config::External::Mapper do
context "when 'include' is defined as an array of hashes" do
let(:values) do
{ include: [{ remote: remote_url }, { local: local_file }],
- image: 'ruby:2.2' }
+ image: 'ruby:2.7' }
end
it 'returns Files instances' do
@@ -128,7 +128,7 @@ describe Gitlab::Ci::Config::External::Mapper do
context 'when it has ambigious match' do
let(:values) do
{ include: [{ remote: remote_url, local: local_file }],
- image: 'ruby:2.2' }
+ image: 'ruby:2.7' }
end
it 'returns ambigious specification error' do
@@ -140,7 +140,7 @@ describe Gitlab::Ci::Config::External::Mapper do
context "when 'include' is not defined" do
let(:values) do
{
- image: 'ruby:2.2'
+ image: 'ruby:2.7'
}
end
@@ -155,7 +155,7 @@ describe Gitlab::Ci::Config::External::Mapper do
{ 'local' => local_file },
{ 'local' => local_file }
],
- image: 'ruby:2.2' }
+ image: 'ruby:2.7' }
end
it 'raises an exception' do
@@ -169,7 +169,7 @@ describe Gitlab::Ci::Config::External::Mapper do
{ 'local' => local_file },
{ 'remote' => remote_url }
],
- image: 'ruby:2.2' }
+ image: 'ruby:2.7' }
end
before do
diff --git a/spec/lib/gitlab/ci/config/external/processor_spec.rb b/spec/lib/gitlab/ci/config/external/processor_spec.rb
index ff08d4703fe..45f646660a7 100644
--- a/spec/lib/gitlab/ci/config/external/processor_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/processor_spec.rb
@@ -24,7 +24,7 @@ describe Gitlab::Ci::Config::External::Processor do
subject { processor.perform }
context 'when no external files defined' do
- let(:values) { { image: 'ruby:2.2' } }
+ let(:values) { { image: 'ruby:2.7' } }
it 'returns the same values' do
expect(processor.perform).to eq(values)
@@ -32,7 +32,7 @@ describe Gitlab::Ci::Config::External::Processor do
end
context 'when an invalid local file is defined' do
- let(:values) { { include: '/lib/gitlab/ci/templates/non-existent-file.yml', image: 'ruby:2.2' } }
+ let(:values) { { include: '/lib/gitlab/ci/templates/non-existent-file.yml', image: 'ruby:2.7' } }
it 'raises an error' do
expect { processor.perform }.to raise_error(
@@ -44,7 +44,7 @@ describe Gitlab::Ci::Config::External::Processor do
context 'when an invalid remote file is defined' do
let(:remote_file) { 'http://doesntexist.com/.gitlab-ci-1.yml' }
- let(:values) { { include: remote_file, image: 'ruby:2.2' } }
+ let(:values) { { include: remote_file, image: 'ruby:2.7' } }
before do
stub_full_request(remote_file).and_raise(SocketError.new('Some HTTP error'))
@@ -60,7 +60,7 @@ describe Gitlab::Ci::Config::External::Processor do
context 'with a valid remote external file is defined' do
let(:remote_file) { 'https://gitlab.com/gitlab-org/gitlab-foss/blob/1234/.gitlab-ci-1.yml' }
- let(:values) { { include: remote_file, image: 'ruby:2.2' } }
+ let(:values) { { include: remote_file, image: 'ruby:2.7' } }
let(:external_file_content) do
<<-HEREDOC
before_script:
@@ -94,7 +94,7 @@ describe Gitlab::Ci::Config::External::Processor do
end
context 'with a valid local external file is defined' do
- let(:values) { { include: '/lib/gitlab/ci/templates/template.yml', image: 'ruby:2.2' } }
+ let(:values) { { include: '/lib/gitlab/ci/templates/template.yml', image: 'ruby:2.7' } }
let(:local_file_content) do
<<-HEREDOC
before_script:
@@ -131,7 +131,7 @@ describe Gitlab::Ci::Config::External::Processor do
let(:values) do
{
include: external_files,
- image: 'ruby:2.2'
+ image: 'ruby:2.7'
}
end
@@ -163,7 +163,7 @@ describe Gitlab::Ci::Config::External::Processor do
end
context 'when external files are defined but not valid' do
- let(:values) { { include: '/lib/gitlab/ci/templates/template.yml', image: 'ruby:2.2' } }
+ let(:values) { { include: '/lib/gitlab/ci/templates/template.yml', image: 'ruby:2.7' } }
let(:local_file_content) { 'invalid content file ////' }
@@ -185,7 +185,7 @@ describe Gitlab::Ci::Config::External::Processor do
let(:values) do
{
include: remote_file,
- image: 'ruby:2.2'
+ image: 'ruby:2.7'
}
end
@@ -198,7 +198,7 @@ describe Gitlab::Ci::Config::External::Processor do
it 'takes precedence' do
stub_full_request(remote_file).to_return(body: remote_file_content)
- expect(processor.perform[:image]).to eq('ruby:2.2')
+ expect(processor.perform[:image]).to eq('ruby:2.7')
end
end
@@ -208,7 +208,7 @@ describe Gitlab::Ci::Config::External::Processor do
include: [
{ local: '/local/file.yml' }
],
- image: 'ruby:2.2'
+ image: 'ruby:2.7'
}
end
diff --git a/spec/lib/gitlab/ci/config_spec.rb b/spec/lib/gitlab/ci/config_spec.rb
index d8101e8a621..3b65dbe11ec 100644
--- a/spec/lib/gitlab/ci/config_spec.rb
+++ b/spec/lib/gitlab/ci/config_spec.rb
@@ -20,7 +20,7 @@ describe Gitlab::Ci::Config do
context 'when config is valid' do
let(:yml) do
<<-EOS
- image: ruby:2.2
+ image: ruby:2.7
rspec:
script:
@@ -32,7 +32,7 @@ describe Gitlab::Ci::Config do
describe '#to_hash' do
it 'returns hash created from string' do
hash = {
- image: 'ruby:2.2',
+ image: 'ruby:2.7',
rspec: {
script: ['gem install rspec',
'rspec']
@@ -85,7 +85,7 @@ describe Gitlab::Ci::Config do
context 'when using extendable hash' do
let(:yml) do
<<-EOS
- image: ruby:2.2
+ image: ruby:2.7
rspec:
script: rspec
@@ -98,7 +98,7 @@ describe Gitlab::Ci::Config do
it 'correctly extends the hash' do
hash = {
- image: 'ruby:2.2',
+ image: 'ruby:2.7',
rspec: { script: 'rspec' },
test: {
extends: 'rspec',
@@ -188,7 +188,7 @@ describe Gitlab::Ci::Config do
let(:yml) do
<<-EOS
image:
- name: ruby:2.2
+ name: ruby:2.7
ports:
- 80
EOS
@@ -202,12 +202,12 @@ describe Gitlab::Ci::Config do
context 'in the job image' do
let(:yml) do
<<-EOS
- image: ruby:2.2
+ image: ruby:2.7
test:
script: rspec
image:
- name: ruby:2.2
+ name: ruby:2.7
ports:
- 80
EOS
@@ -221,11 +221,11 @@ describe Gitlab::Ci::Config do
context 'in the services' do
let(:yml) do
<<-EOS
- image: ruby:2.2
+ image: ruby:2.7
test:
script: rspec
- image: ruby:2.2
+ image: ruby:2.7
services:
- name: test
alias: test
@@ -266,7 +266,7 @@ describe Gitlab::Ci::Config do
- #{local_location}
- #{remote_location}
- image: ruby:2.2
+ image: ruby:2.7
HEREDOC
end
@@ -296,7 +296,7 @@ describe Gitlab::Ci::Config do
}
composed_hash = {
before_script: before_script_values,
- image: "ruby:2.2",
+ image: "ruby:2.7",
rspec: { script: ["bundle exec rspec"] },
variables: variables
}
@@ -381,7 +381,7 @@ describe Gitlab::Ci::Config do
include:
- #{remote_location}
- image: ruby:2.2
+ image: ruby:2.7
HEREDOC
end
@@ -392,7 +392,7 @@ describe Gitlab::Ci::Config do
end
it 'takes precedence' do
- expect(config.to_hash).to eq({ image: 'ruby:2.2' })
+ expect(config.to_hash).to eq({ image: 'ruby:2.7' })
end
end
diff --git a/spec/lib/gitlab/ci/yaml_processor_spec.rb b/spec/lib/gitlab/ci/yaml_processor_spec.rb
index af0a85f6c4e..62adba4319e 100644
--- a/spec/lib/gitlab/ci/yaml_processor_spec.rb
+++ b/spec/lib/gitlab/ci/yaml_processor_spec.rb
@@ -665,7 +665,7 @@ module Gitlab
describe "Image and service handling" do
context "when extended docker configuration is used" do
it "returns image and service when defined" do
- config = YAML.dump({ image: { name: "ruby:2.1", entrypoint: ["/usr/local/bin/init", "run"] },
+ config = YAML.dump({ image: { name: "ruby:2.7", entrypoint: ["/usr/local/bin/init", "run"] },
services: ["mysql", { name: "docker:dind", alias: "docker",
entrypoint: ["/usr/local/bin/init", "run"],
command: ["/usr/local/bin/init", "run"] }],
@@ -683,7 +683,7 @@ module Gitlab
options: {
before_script: ["pwd"],
script: ["rspec"],
- image: { name: "ruby:2.1", entrypoint: ["/usr/local/bin/init", "run"] },
+ image: { name: "ruby:2.7", entrypoint: ["/usr/local/bin/init", "run"] },
services: [{ name: "mysql" },
{ name: "docker:dind", alias: "docker", entrypoint: ["/usr/local/bin/init", "run"],
command: ["/usr/local/bin/init", "run"] }]
@@ -696,7 +696,7 @@ module Gitlab
end
it "returns image and service when overridden for job" do
- config = YAML.dump({ image: "ruby:2.1",
+ config = YAML.dump({ image: "ruby:2.7",
services: ["mysql"],
before_script: ["pwd"],
rspec: { image: { name: "ruby:2.5", entrypoint: ["/usr/local/bin/init", "run"] },
@@ -731,7 +731,7 @@ module Gitlab
context "when etended docker configuration is not used" do
it "returns image and service when defined" do
- config = YAML.dump({ image: "ruby:2.1",
+ config = YAML.dump({ image: "ruby:2.7",
services: ["mysql", "docker:dind"],
before_script: ["pwd"],
rspec: { script: "rspec" } })
@@ -747,7 +747,7 @@ module Gitlab
options: {
before_script: ["pwd"],
script: ["rspec"],
- image: { name: "ruby:2.1" },
+ image: { name: "ruby:2.7" },
services: [{ name: "mysql" }, { name: "docker:dind" }]
},
allow_failure: false,
@@ -758,7 +758,7 @@ module Gitlab
end
it "returns image and service when overridden for job" do
- config = YAML.dump({ image: "ruby:2.1",
+ config = YAML.dump({ image: "ruby:2.7",
services: ["mysql"],
before_script: ["pwd"],
rspec: { image: "ruby:2.5", services: ["postgresql", "docker:dind"], script: "rspec" } })
@@ -1292,7 +1292,7 @@ module Gitlab
describe "Artifacts" do
it "returns artifacts when defined" do
config = YAML.dump({
- image: "ruby:2.1",
+ image: "ruby:2.7",
services: ["mysql"],
before_script: ["pwd"],
rspec: {
@@ -1318,7 +1318,7 @@ module Gitlab
options: {
before_script: ["pwd"],
script: ["rspec"],
- image: { name: "ruby:2.1" },
+ image: { name: "ruby:2.7" },
services: [{ name: "mysql" }],
artifacts: {
name: "custom_name",
@@ -1945,7 +1945,7 @@ module Gitlab
context 'when hidden job have a script definition' do
let(:config) do
YAML.dump({
- '.hidden_job' => { image: 'ruby:2.1', script: 'test' },
+ '.hidden_job' => { image: 'ruby:2.7', script: 'test' },
'normal_job' => { script: 'test' }
})
end
@@ -1956,7 +1956,7 @@ module Gitlab
context "when hidden job doesn't have a script definition" do
let(:config) do
YAML.dump({
- '.hidden_job' => { image: 'ruby:2.1' },
+ '.hidden_job' => { image: 'ruby:2.7' },
'normal_job' => { script: 'test' }
})
end
diff --git a/spec/lib/gitlab/config/loader/yaml_spec.rb b/spec/lib/gitlab/config/loader/yaml_spec.rb
index 28039e99916..a52c1c362e1 100644
--- a/spec/lib/gitlab/config/loader/yaml_spec.rb
+++ b/spec/lib/gitlab/config/loader/yaml_spec.rb
@@ -6,7 +6,7 @@ describe Gitlab::Config::Loader::Yaml do
let(:loader) { described_class.new(yml) }
context 'when yaml syntax is correct' do
- let(:yml) { 'image: ruby:2.2' }
+ let(:yml) { 'image: ruby:2.7' }
describe '#valid?' do
it 'returns true' do
@@ -16,7 +16,7 @@ describe Gitlab::Config::Loader::Yaml do
describe '#load!' do
it 'returns a valid hash' do
- expect(loader.load!).to eq(image: 'ruby:2.2')
+ expect(loader.load!).to eq(image: 'ruby:2.7')
end
end
end
diff --git a/spec/lib/gitlab/import_export/snippet_repo_restorer_spec.rb b/spec/lib/gitlab/import_export/snippet_repo_restorer_spec.rb
index d72d41ddf38..3ce950d6a64 100644
--- a/spec/lib/gitlab/import_export/snippet_repo_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/snippet_repo_restorer_spec.rb
@@ -55,9 +55,11 @@ describe Gitlab::ImportExport::SnippetRepoRestorer do
let(:snippet_bundle_path) { File.join(bundle_path, "#{snippet_with_repo.hexdigest}.bundle") }
let(:result) { exporter.save }
- it 'creates the repository from the bundle' do
+ before do
expect(exporter.save).to be_truthy
+ end
+ it 'creates the repository from the bundle' do
expect(snippet.repository_exists?).to be_falsey
expect(snippet.snippet_repository).to be_nil
expect(snippet.repository).to receive(:create_from_bundle).and_call_original
@@ -66,5 +68,14 @@ describe Gitlab::ImportExport::SnippetRepoRestorer do
expect(snippet.repository_exists?).to be_truthy
expect(snippet.snippet_repository).not_to be_nil
end
+
+ it 'sets same shard in snippet repository as in the repository storage' do
+ expect(snippet).to receive(:repository_storage).and_return('picked')
+ expect(snippet.repository).to receive(:create_from_bundle)
+
+ restorer.restore
+
+ expect(snippet.snippet_repository.shard_name).to eq 'picked'
+ end
end
end
diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb
index 8c7969af177..88c26c92417 100644
--- a/spec/models/ci/build_spec.rb
+++ b/spec/models/ci/build_spec.rb
@@ -1882,7 +1882,7 @@ describe Ci::Build do
describe '#options' do
let(:options) do
{
- image: "ruby:2.1",
+ image: "ruby:2.7",
services: ["postgres"],
script: ["ls -a"]
}
@@ -1893,11 +1893,11 @@ describe Ci::Build do
end
it 'allows to access with keys' do
- expect(build.options[:image]).to eq('ruby:2.1')
+ expect(build.options[:image]).to eq('ruby:2.7')
end
it 'allows to access with strings' do
- expect(build.options['image']).to eq('ruby:2.1')
+ expect(build.options['image']).to eq('ruby:2.7')
end
context 'when ci_build_metadata_config is set' do
diff --git a/spec/models/project_services/buildkite_service_spec.rb b/spec/models/project_services/buildkite_service_spec.rb
index c622b7706c6..8b6fa36eaa5 100644
--- a/spec/models/project_services/buildkite_service_spec.rb
+++ b/spec/models/project_services/buildkite_service_spec.rb
@@ -84,6 +84,10 @@ describe BuildkiteService, :use_clean_rails_memory_store_caching do
describe '#calculate_reactive_cache' do
describe '#commit_status' do
+ let(:buildkite_full_url) do
+ 'https://gitlab.buildkite.com/status/secret-sauce-status-token.json?commit=123'
+ end
+
subject { service.calculate_reactive_cache('123', 'unused')[:commit_status] }
it 'sets commit status to :error when status is 500' do
@@ -103,13 +107,25 @@ describe BuildkiteService, :use_clean_rails_memory_store_caching do
is_expected.to eq('Great Success')
end
+
+ Gitlab::HTTP::HTTP_ERRORS.each do |http_error|
+ it "sets commit status to :error with a #{http_error.name} error" do
+ WebMock.stub_request(:get, buildkite_full_url)
+ .to_raise(http_error)
+
+ expect(Gitlab::ErrorTracking)
+ .to receive(:log_exception)
+ .with(instance_of(http_error), project_id: project.id)
+
+ is_expected.to eq(:error)
+ end
+ end
end
end
end
def stub_request(status: 200, body: nil)
body ||= %q({"status":"success"})
- buildkite_full_url = 'https://gitlab.buildkite.com/status/secret-sauce-status-token.json?commit=123'
stub_full_request(buildkite_full_url)
.to_return(status: status,
diff --git a/spec/models/project_services/drone_ci_service_spec.rb b/spec/models/project_services/drone_ci_service_spec.rb
index 0639a4c1f23..1ee9c5f90c6 100644
--- a/spec/models/project_services/drone_ci_service_spec.rb
+++ b/spec/models/project_services/drone_ci_service_spec.rb
@@ -106,6 +106,10 @@ describe DroneCiService, :use_clean_rails_memory_store_caching do
WebMock.stub_request(:get, commit_status_path)
.to_raise(http_error)
+ expect(Gitlab::ErrorTracking)
+ .to receive(:log_exception)
+ .with(instance_of(http_error), project_id: project.id)
+
is_expected.to eq(:error)
end
end
diff --git a/spec/models/snippet_repository_spec.rb b/spec/models/snippet_repository_spec.rb
index c31fe192367..dc9f9a95d24 100644
--- a/spec/models/snippet_repository_spec.rb
+++ b/spec/models/snippet_repository_spec.rb
@@ -16,7 +16,7 @@ describe SnippetRepository do
describe '.find_snippet' do
it 'finds snippet by disk path' do
snippet = create(:snippet, author: user)
- snippet.track_snippet_repository
+ snippet.track_snippet_repository(snippet.repository.storage)
expect(described_class.find_snippet(snippet.disk_path)).to eq(snippet)
end
diff --git a/spec/models/snippet_spec.rb b/spec/models/snippet_spec.rb
index 0e19dfc147b..8ce3718e3c1 100644
--- a/spec/models/snippet_spec.rb
+++ b/spec/models/snippet_spec.rb
@@ -567,18 +567,21 @@ describe Snippet do
describe '#track_snippet_repository' do
let(:snippet) { create(:snippet) }
+ let(:shard_name) { 'foo' }
+
+ subject { snippet.track_snippet_repository(shard_name) }
context 'when a snippet repository entry does not exist' do
it 'creates a new entry' do
- expect { snippet.track_snippet_repository }.to change(snippet, :snippet_repository)
+ expect { subject }.to change(snippet, :snippet_repository)
end
it 'tracks the snippet storage location' do
- snippet.track_snippet_repository
+ subject
expect(snippet.snippet_repository).to have_attributes(
disk_path: snippet.disk_path,
- shard_name: snippet.repository_storage
+ shard_name: shard_name
)
end
end
@@ -586,21 +589,20 @@ describe Snippet do
context 'when a tracking entry exists' do
let!(:snippet) { create(:snippet, :repository) }
let(:snippet_repository) { snippet.snippet_repository }
- let!(:shard) { create(:shard, name: 'foo') }
+ let(:shard_name) { 'bar' }
it 'does not create a new entry in the database' do
- expect { snippet.track_snippet_repository }.not_to change(snippet, :snippet_repository)
+ expect { subject }.not_to change(snippet, :snippet_repository)
end
it 'updates the snippet storage location' do
allow(snippet).to receive(:disk_path).and_return('fancy/new/path')
- allow(snippet).to receive(:repository_storage).and_return('foo')
- snippet.track_snippet_repository
+ subject
expect(snippet.snippet_repository).to have_attributes(
disk_path: 'fancy/new/path',
- shard_name: 'foo'
+ shard_name: shard_name
)
end
end
@@ -609,19 +611,31 @@ describe Snippet do
describe '#create_repository' do
let(:snippet) { create(:snippet) }
+ subject { snippet.create_repository }
+
it 'creates the repository' do
expect(snippet.repository).to receive(:after_create).and_call_original
- expect(snippet.create_repository).to be_truthy
+ expect(subject).to be_truthy
expect(snippet.repository.exists?).to be_truthy
end
it 'tracks snippet repository' do
expect do
- snippet.create_repository
+ subject
end.to change(SnippetRepository, :count).by(1)
end
+ it 'sets same shard in snippet repository as in the repository storage' do
+ expect(snippet).to receive(:repository_storage).and_return('picked')
+ expect(snippet).to receive(:repository_exists?).and_return(false)
+ expect(snippet.repository).to receive(:create_if_not_exists)
+
+ subject
+
+ expect(snippet.snippet_repository.shard_name).to eq 'picked'
+ end
+
context 'when repository exists' do
let!(:snippet) { create(:snippet, :repository) }
diff --git a/spec/requests/api/lint_spec.rb b/spec/requests/api/lint_spec.rb
index 5815ce07125..71c2619d898 100644
--- a/spec/requests/api/lint_spec.rb
+++ b/spec/requests/api/lint_spec.rb
@@ -29,7 +29,7 @@ describe API::Lint do
end
it "responds with errors about invalid configuration" do
- post api('/ci/lint'), params: { content: '{ image: "ruby:2.1", services: ["postgres"] }' }
+ post api('/ci/lint'), params: { content: '{ image: "ruby:2.7", services: ["postgres"] }' }
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['status']).to eq('invalid')
diff --git a/spec/requests/api/runner_spec.rb b/spec/requests/api/runner_spec.rb
index 5a8add1e9db..03560cae775 100644
--- a/spec/requests/api/runner_spec.rb
+++ b/spec/requests/api/runner_spec.rb
@@ -523,7 +523,7 @@ describe API::Runner, :clean_gitlab_redis_shared_state do
expect(json_response['token']).to eq(job.token)
expect(json_response['job_info']).to eq(expected_job_info)
expect(json_response['git_info']).to eq(expected_git_info)
- expect(json_response['image']).to eq({ 'name' => 'ruby:2.1', 'entrypoint' => '/bin/sh', 'ports' => [] })
+ expect(json_response['image']).to eq({ 'name' => 'ruby:2.7', 'entrypoint' => '/bin/sh', 'ports' => [] })
expect(json_response['services']).to eq([{ 'name' => 'postgres', 'entrypoint' => nil,
'alias' => nil, 'command' => nil, 'ports' => [] },
{ 'name' => 'docker:stable-dind', 'entrypoint' => '/bin/sh',
diff --git a/spec/services/ci/create_pipeline_service_spec.rb b/spec/services/ci/create_pipeline_service_spec.rb
index 3b819c795b2..681ce9669e2 100644
--- a/spec/services/ci/create_pipeline_service_spec.rb
+++ b/spec/services/ci/create_pipeline_service_spec.rb
@@ -555,7 +555,7 @@ describe Ci::CreatePipelineService do
let(:ci_yaml) do
<<-EOS
image:
- name: ruby:2.2
+ name: ruby:2.7
ports:
- 80
EOS
@@ -567,12 +567,12 @@ describe Ci::CreatePipelineService do
context 'in the job image' do
let(:ci_yaml) do
<<-EOS
- image: ruby:2.2
+ image: ruby:2.7
test:
script: rspec
image:
- name: ruby:2.2
+ name: ruby:2.7
ports:
- 80
EOS
@@ -584,11 +584,11 @@ describe Ci::CreatePipelineService do
context 'in the service' do
let(:ci_yaml) do
<<-EOS
- image: ruby:2.2
+ image: ruby:2.7
test:
script: rspec
- image: ruby:2.2
+ image: ruby:2.7
services:
- name: test
ports:
diff --git a/spec/services/projects/container_repository/cleanup_tags_service_spec.rb b/spec/services/projects/container_repository/cleanup_tags_service_spec.rb
index 96cddef4628..01f09f208fd 100644
--- a/spec/services/projects/container_repository/cleanup_tags_service_spec.rb
+++ b/spec/services/projects/container_repository/cleanup_tags_service_spec.rb
@@ -41,7 +41,8 @@ describe Projects::ContainerRepository::CleanupTagsService do
let(:params) { {} }
it 'does not remove anything' do
- expect_any_instance_of(ContainerRegistry::Client).not_to receive(:delete_repository_tag_by_digest)
+ expect_any_instance_of(Projects::ContainerRepository::DeleteTagsService)
+ .not_to receive(:execute)
is_expected.to include(status: :success, deleted: [])
end
@@ -49,15 +50,10 @@ describe Projects::ContainerRepository::CleanupTagsService do
context 'when regex matching everything is specified' do
shared_examples 'removes all matches' do
- it 'does remove B* and C' do
- # The :A cannot be removed as config is shared with :latest
- # The :E cannot be removed as it does not have valid manifest
+ it 'does remove all tags except latest' do
+ expect_delete(%w(A Ba Bb C D E))
- expect_delete('sha256:configB').twice
- expect_delete('sha256:configC')
- expect_delete('sha256:configD')
-
- is_expected.to include(status: :success, deleted: %w(D Bb Ba C))
+ is_expected.to include(status: :success, deleted: %w(A Ba Bb C D E))
end
end
@@ -82,10 +78,9 @@ describe Projects::ContainerRepository::CleanupTagsService do
end
it 'does remove C and D' do
- expect_delete('sha256:configC')
- expect_delete('sha256:configD')
+ expect_delete(%w(C D))
- is_expected.to include(status: :success, deleted: %w(D C))
+ is_expected.to include(status: :success, deleted: %w(C D))
end
context 'with overriding allow regex' do
@@ -95,7 +90,7 @@ describe Projects::ContainerRepository::CleanupTagsService do
end
it 'does not remove C' do
- expect_delete('sha256:configD')
+ expect_delete(%w(D))
is_expected.to include(status: :success, deleted: %w(D))
end
@@ -108,36 +103,52 @@ describe Projects::ContainerRepository::CleanupTagsService do
end
it 'does not remove C' do
- expect_delete('sha256:configD')
+ expect_delete(%w(D))
is_expected.to include(status: :success, deleted: %w(D))
end
end
end
- context 'when removing a tagged image that is used by another tag' do
+ context 'with allow regex value' do
let(:params) do
- { 'name_regex_delete' => 'Ba' }
+ { 'name_regex_delete' => '.*',
+ 'name_regex_keep' => 'B.*' }
end
- it 'does not remove the tag' do
- # Issue: https://gitlab.com/gitlab-org/gitlab-foss/issues/21405
+ it 'does not remove B*' do
+ expect_delete(%w(A C D E))
- is_expected.to include(status: :success, deleted: [])
+ is_expected.to include(status: :success, deleted: %w(A C D E))
end
end
- context 'with allow regex value' do
+ context 'when keeping only N tags' do
let(:params) do
- { 'name_regex_delete' => '.*',
- 'name_regex_keep' => 'B.*' }
+ { 'name_regex' => 'A|B.*|C',
+ 'keep_n' => 1 }
end
- it 'does not remove B*' do
- expect_delete('sha256:configC')
- expect_delete('sha256:configD')
+ it 'sorts tags by date' do
+ expect_delete(%w(Bb Ba C))
+
+ expect(service).to receive(:order_by_date).and_call_original
- is_expected.to include(status: :success, deleted: %w(D C))
+ is_expected.to include(status: :success, deleted: %w(Bb Ba C))
+ end
+ end
+
+ context 'when not keeping N tags' do
+ let(:params) do
+ { 'name_regex' => 'A|B.*|C' }
+ end
+
+ it 'does not sort tags by date' do
+ expect_delete(%w(A Ba Bb C))
+
+ expect(service).not_to receive(:order_by_date)
+
+ is_expected.to include(status: :success, deleted: %w(A Ba Bb C))
end
end
@@ -147,10 +158,10 @@ describe Projects::ContainerRepository::CleanupTagsService do
'keep_n' => 3 }
end
- it 'does remove C as it is oldest' do
- expect_delete('sha256:configC')
+ it 'does remove B* and C as they are the oldest' do
+ expect_delete(%w(Bb Ba C))
- is_expected.to include(status: :success, deleted: %w(C))
+ is_expected.to include(status: :success, deleted: %w(Bb Ba C))
end
end
@@ -161,10 +172,9 @@ describe Projects::ContainerRepository::CleanupTagsService do
end
it 'does remove B* and C as they are older than 1 day' do
- expect_delete('sha256:configB').twice
- expect_delete('sha256:configC')
+ expect_delete(%w(Ba Bb C))
- is_expected.to include(status: :success, deleted: %w(Bb Ba C))
+ is_expected.to include(status: :success, deleted: %w(Ba Bb C))
end
end
@@ -176,8 +186,7 @@ describe Projects::ContainerRepository::CleanupTagsService do
end
it 'does remove B* and C' do
- expect_delete('sha256:configB').twice
- expect_delete('sha256:configC')
+ expect_delete(%w(Bb Ba C))
is_expected.to include(status: :success, deleted: %w(Bb Ba C))
end
@@ -195,8 +204,7 @@ describe Projects::ContainerRepository::CleanupTagsService do
end
it 'succeeds without a user' do
- expect_delete('sha256:configB').twice
- expect_delete('sha256:configC')
+ expect_delete(%w(Bb Ba C))
is_expected.to include(status: :success, deleted: %w(Bb Ba C))
end
@@ -238,9 +246,14 @@ describe Projects::ContainerRepository::CleanupTagsService do
end
end
- def expect_delete(digest)
- expect_any_instance_of(ContainerRegistry::Client)
- .to receive(:delete_repository_tag_by_digest)
- .with(repository.path, digest) { true }
+ def expect_delete(tags)
+ expect(Projects::ContainerRepository::DeleteTagsService)
+ .to receive(:new)
+ .with(repository.project, user, tags: tags)
+ .and_call_original
+
+ expect_any_instance_of(Projects::ContainerRepository::DeleteTagsService)
+ .to receive(:execute)
+ .with(repository) { { status: :success, deleted: tags } }
end
end