diff options
Diffstat (limited to 'spec')
31 files changed, 353 insertions, 56 deletions
diff --git a/spec/controllers/registrations_controller_spec.rb b/spec/controllers/registrations_controller_spec.rb index 898f3863008..d334a2ff566 100644 --- a/spec/controllers/registrations_controller_spec.rb +++ b/spec/controllers/registrations_controller_spec.rb @@ -49,7 +49,7 @@ describe RegistrationsController do end it 'displays an error when the reCAPTCHA is not solved' do - # Without this, `verify_recaptcha` arbitraily returns true in test env + # Without this, `verify_recaptcha` arbitrarily returns true in test env Recaptcha.configuration.skip_verify_env.delete('test') post(:create, user_params) diff --git a/spec/controllers/sessions_controller_spec.rb b/spec/controllers/sessions_controller_spec.rb index 8e25b61e2f1..c691b3f478b 100644 --- a/spec/controllers/sessions_controller_spec.rb +++ b/spec/controllers/sessions_controller_spec.rb @@ -89,7 +89,7 @@ describe SessionsController do end it 'displays an error when the reCAPTCHA is not solved' do - # Without this, `verify_recaptcha` arbitraily returns true in test env + # Without this, `verify_recaptcha` arbitrarily returns true in test env Recaptcha.configuration.skip_verify_env.delete('test') counter = double(:counter) diff --git a/spec/db/schema_spec.rb b/spec/db/schema_spec.rb new file mode 100644 index 00000000000..e8584846b56 --- /dev/null +++ b/spec/db/schema_spec.rb @@ -0,0 +1,96 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'Database schema' do + let(:connection) { ActiveRecord::Base.connection } + let(:tables) { connection.tables } + + # Use if you are certain that this column should not have a foreign key + IGNORED_FK_COLUMNS = { + abuse_reports: %w[reporter_id user_id], + application_settings: %w[performance_bar_allowed_group_id], + audit_events: %w[author_id entity_id], + award_emoji: %w[awardable_id user_id], + chat_names: %w[chat_id service_id team_id user_id], + chat_teams: %w[team_id], + ci_builds: %w[erased_by_id runner_id trigger_request_id user_id], + ci_pipelines: %w[user_id], + ci_runner_projects: %w[runner_id], + ci_trigger_requests: %w[commit_id], + cluster_providers_gcp: %w[gcp_project_id operation_id], + deploy_keys_projects: %w[deploy_key_id], + deployments: %w[deployable_id environment_id user_id], + emails: %w[user_id], + events: %w[target_id], + forked_project_links: %w[forked_from_project_id], + identities: %w[user_id], + issues: %w[last_edited_by_id], + keys: %w[user_id], + label_links: %w[target_id], + lfs_objects_projects: %w[lfs_object_id project_id], + members: %w[source_id created_by_id], + merge_requests: %w[last_edited_by_id], + namespaces: %w[owner_id parent_id], + notes: %w[author_id commit_id noteable_id updated_by_id resolved_by_id discussion_id], + notification_settings: %w[source_id], + oauth_access_grants: %w[resource_owner_id application_id], + oauth_access_tokens: %w[resource_owner_id application_id], + oauth_applications: %w[owner_id], + project_group_links: %w[group_id], + project_statistics: %w[namespace_id], + projects: %w[creator_id namespace_id ci_id], + redirect_routes: %w[source_id], + repository_languages: %w[programming_language_id], + routes: %w[source_id], + sent_notifications: %w[project_id noteable_id recipient_id commit_id in_reply_to_discussion_id], + snippets: %w[author_id], + spam_logs: %w[user_id], + subscriptions: %w[user_id subscribable_id], + taggings: %w[tag_id taggable_id tagger_id], + timelogs: %w[user_id], + todos: %w[target_id commit_id], + uploads: %w[model_id], + user_agent_details: %w[subject_id], + users: %w[color_scheme_id created_by_id theme_id], + users_star_projects: %w[user_id], + web_hooks: %w[service_id] + }.with_indifferent_access.freeze + + context 'for table' do + ActiveRecord::Base.connection.tables.sort.each do |table| + describe table do + let(:indexes) { connection.indexes(table) } + let(:columns) { connection.columns(table) } + let(:foreign_keys) { connection.foreign_keys(table) } + + context 'all foreign keys' do + # for index to be effective, the FK constraint has to be at first place + it 'are indexed' do + first_indexed_column = indexes.map(&:columns).map(&:first) + foreign_keys_columns = foreign_keys.map(&:column) + + expect(first_indexed_column.uniq).to include(*foreign_keys_columns) + end + end + + context 'columns ending with _id' do + let(:column_names) { columns.map(&:name) } + let(:column_names_with_id) { column_names.select { |column_name| column_name.ends_with?('_id') } } + let(:foreign_keys_columns) { foreign_keys.map(&:column) } + let(:ignored_columns) { ignored_fk_columns(table) } + + it 'do have the foreign keys' do + expect(column_names_with_id - ignored_columns).to contain_exactly(*foreign_keys_columns) + end + end + end + end + end + + private + + def ignored_fk_columns(column) + IGNORED_FK_COLUMNS.fetch(column, []) + end +end diff --git a/spec/fast_spec_helper.rb b/spec/fast_spec_helper.rb index fe475e1f7a0..0b5ab16ad71 100644 --- a/spec/fast_spec_helper.rb +++ b/spec/fast_spec_helper.rb @@ -9,3 +9,4 @@ require 'active_support/all' ActiveSupport::Dependencies.autoload_paths << 'lib' ActiveSupport::Dependencies.autoload_paths << 'ee/lib' +ActiveSupport::XmlMini.backend = 'Nokogiri' diff --git a/spec/features/issues/form_spec.rb b/spec/features/issues/form_spec.rb index 1456a2f0375..f2e4c5779df 100644 --- a/spec/features/issues/form_spec.rb +++ b/spec/features/issues/form_spec.rb @@ -27,7 +27,7 @@ describe 'New/edit issue', :js do before do # Using `allow_any_instance_of`/`and_wrap_original`, `original` would # somehow refer to the very block we defined to _wrap_ that method, instead of - # the original method, resulting in infinite recurison when called. + # the original method, resulting in infinite recursion when called. # This is likely a bug with helper modules included into dynamically generated view classes. # To work around this, we have to hold on to and call to the original implementation manually. original_issue_dropdown_options = FormHelper.instance_method(:issue_assignees_dropdown_options) diff --git a/spec/features/issues/user_creates_branch_and_merge_request_spec.rb b/spec/features/issues/user_creates_branch_and_merge_request_spec.rb index 3dfcbc2fcb8..297cd808460 100644 --- a/spec/features/issues/user_creates_branch_and_merge_request_spec.rb +++ b/spec/features/issues/user_creates_branch_and_merge_request_spec.rb @@ -55,11 +55,11 @@ describe 'User creates branch and merge request on issue page', :js do test_branch_name_checking(input_branch_name) test_source_checking(input_source) - # The button inside dropdown should be disabled if any errors occured. + # The button inside dropdown should be disabled if any errors occurred. expect(page).to have_button('Create branch', disabled: true) end - # The top level button should be disabled if any errors occured. + # The top level button should be disabled if any errors occurred. expect(page).to have_button('Create branch', disabled: true) end diff --git a/spec/features/projects/jobs_spec.rb b/spec/features/projects/jobs_spec.rb index a1323699969..99a7fbb63bd 100644 --- a/spec/features/projects/jobs_spec.rb +++ b/spec/features/projects/jobs_spec.rb @@ -719,7 +719,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do context 'on mobile', :js do let(:job) { create(:ci_build, pipeline: pipeline) } - it 'renders collpased sidebar' do + it 'renders collapsed sidebar' do page.current_window.resize_to(600, 800) visit project_job_path(project, job) @@ -738,7 +738,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do wait_for_requests expect(page).to have_css('.js-job-sidebar.right-sidebar-expanded') - expect(page).not_to have_css('.js-job-sidebar.right-sidebar-collpased') + expect(page).not_to have_css('.js-job-sidebar.right-sidebar-collapsed') end end diff --git a/spec/finders/pipelines_finder_spec.rb b/spec/finders/pipelines_finder_spec.rb index c6e832ad69b..c2c304589c9 100644 --- a/spec/finders/pipelines_finder_spec.rb +++ b/spec/finders/pipelines_finder_spec.rb @@ -225,7 +225,7 @@ describe PipelinesFinder do end end - context 'when the project has limited access to piplines' do + context 'when the project has limited access to pipelines' do let(:project) { create(:project, :private, :repository) } let(:current_user) { create(:user) } let!(:pipelines) { create_list(:ci_pipeline, 2, project: project) } diff --git a/spec/fixtures/trace/sample_trace b/spec/fixtures/trace/sample_trace index 7bfe3f83b7b..3d8beb0dec2 100644 --- a/spec/fixtures/trace/sample_trace +++ b/spec/fixtures/trace/sample_trace @@ -2334,12 +2334,12 @@ Boards::Lists::MoveService keeps position of lists when list type is closed when list type is set to label keeps position of lists when new position is nil - keeps position of lists when new positon is equal to old position - keeps position of lists when new positon is negative - keeps position of lists when new positon is equal to number of labels lists - keeps position of lists when new positon is greater than number of labels lists - increments position of intermediate lists when new positon is equal to first position - decrements position of intermediate lists when new positon is equal to last position + keeps position of lists when new position is equal to old position + keeps position of lists when new position is negative + keeps position of lists when new position is equal to number of labels lists + keeps position of lists when new position is greater than number of labels lists + increments position of intermediate lists when new position is equal to first position + decrements position of intermediate lists when new position is equal to last position decrements position of intermediate lists when new position is greater than old position increments position of intermediate lists when new position is lower than old position when board parent is a group @@ -2347,12 +2347,12 @@ Boards::Lists::MoveService keeps position of lists when list type is closed when list type is set to label keeps position of lists when new position is nil - keeps position of lists when new positon is equal to old position - keeps position of lists when new positon is negative - keeps position of lists when new positon is equal to number of labels lists - keeps position of lists when new positon is greater than number of labels lists - increments position of intermediate lists when new positon is equal to first position - decrements position of intermediate lists when new positon is equal to last position + keeps position of lists when new position is equal to old position + keeps position of lists when new position is negative + keeps position of lists when new position is equal to number of labels lists + keeps position of lists when new position is greater than number of labels lists + increments position of intermediate lists when new position is equal to first position + decrements position of intermediate lists when new position is equal to last position decrements position of intermediate lists when new position is greater than old position increments position of intermediate lists when new position is lower than old position diff --git a/spec/javascripts/diffs/store/actions_spec.js b/spec/javascripts/diffs/store/actions_spec.js index d94a9cd1710..acd95a3dd8b 100644 --- a/spec/javascripts/diffs/store/actions_spec.js +++ b/spec/javascripts/diffs/store/actions_spec.js @@ -416,7 +416,7 @@ describe('DiffsStoreActions', () => { const getters = { getDiffFileDiscussions: jasmine.createSpy().and.returnValue([{ id: 1 }]), diffHasAllExpandedDiscussions: jasmine.createSpy().and.returnValue(true), - diffHasAllCollpasedDiscussions: jasmine.createSpy().and.returnValue(false), + diffHasAllCollapsedDiscussions: jasmine.createSpy().and.returnValue(false), }; const dispatch = jasmine.createSpy('dispatch'); @@ -434,7 +434,7 @@ describe('DiffsStoreActions', () => { const getters = { getDiffFileDiscussions: jasmine.createSpy().and.returnValue([{ id: 1 }]), diffHasAllExpandedDiscussions: jasmine.createSpy().and.returnValue(false), - diffHasAllCollpasedDiscussions: jasmine.createSpy().and.returnValue(true), + diffHasAllCollapsedDiscussions: jasmine.createSpy().and.returnValue(true), }; const dispatch = jasmine.createSpy(); @@ -452,7 +452,7 @@ describe('DiffsStoreActions', () => { const getters = { getDiffFileDiscussions: jasmine.createSpy().and.returnValue([{ expanded: false, id: 1 }]), diffHasAllExpandedDiscussions: jasmine.createSpy().and.returnValue(false), - diffHasAllCollpasedDiscussions: jasmine.createSpy().and.returnValue(false), + diffHasAllCollapsedDiscussions: jasmine.createSpy().and.returnValue(false), }; const dispatch = jasmine.createSpy(); diff --git a/spec/javascripts/diffs/store/getters_spec.js b/spec/javascripts/diffs/store/getters_spec.js index 2449bb65d07..eef95c823fb 100644 --- a/spec/javascripts/diffs/store/getters_spec.js +++ b/spec/javascripts/diffs/store/getters_spec.js @@ -106,13 +106,13 @@ describe('Diffs Module Getters', () => { }); }); - describe('diffHasAllCollpasedDiscussions', () => { + describe('diffHasAllCollapsedDiscussions', () => { it('returns true when all discussions are collapsed', () => { discussionMock.diff_file.file_hash = diffFileMock.fileHash; discussionMock.expanded = false; expect( - getters.diffHasAllCollpasedDiscussions(localState, { + getters.diffHasAllCollapsedDiscussions(localState, { getDiffFileDiscussions: () => [discussionMock], })(diffFileMock), ).toEqual(true); @@ -120,7 +120,7 @@ describe('Diffs Module Getters', () => { it('returns false when there are no discussions', () => { expect( - getters.diffHasAllCollpasedDiscussions(localState, { + getters.diffHasAllCollapsedDiscussions(localState, { getDiffFileDiscussions: () => [], })(diffFileMock), ).toEqual(false); @@ -130,7 +130,7 @@ describe('Diffs Module Getters', () => { discussionMock1.expanded = false; expect( - getters.diffHasAllCollpasedDiscussions(localState, { + getters.diffHasAllCollapsedDiscussions(localState, { getDiffFileDiscussions: () => [discussionMock, discussionMock1], })(diffFileMock), ).toEqual(false); diff --git a/spec/javascripts/ide/stores/modules/pipelines/actions_spec.js b/spec/javascripts/ide/stores/modules/pipelines/actions_spec.js index d85354c3681..c9c09ee9afe 100644 --- a/spec/javascripts/ide/stores/modules/pipelines/actions_spec.js +++ b/spec/javascripts/ide/stores/modules/pipelines/actions_spec.js @@ -77,7 +77,7 @@ describe('IDE pipelines actions', () => { { type: 'setErrorMessage', payload: { - text: 'An error occured whilst fetching the latest pipline.', + text: 'An error occured whilst fetching the latest pipeline.', action: jasmine.any(Function), actionText: 'Please try again', actionPayload: null, diff --git a/spec/lib/gitlab/ci/build/policy/changes_spec.rb b/spec/lib/gitlab/ci/build/policy/changes_spec.rb index ab401108c84..523d00c1272 100644 --- a/spec/lib/gitlab/ci/build/policy/changes_spec.rb +++ b/spec/lib/gitlab/ci/build/policy/changes_spec.rb @@ -49,6 +49,12 @@ describe Gitlab::Ci::Build::Policy::Changes do expect(policy).to be_satisfied_by(pipeline, seed) end + it 'is satisfied by matching a pattern with a glob' do + policy = described_class.new(%w[some/**/*.{rb,txt}]) + + expect(policy).to be_satisfied_by(pipeline, seed) + end + it 'is not satisfied when pattern does not match path' do policy = described_class.new(%w[some/*.rb]) @@ -61,6 +67,12 @@ describe Gitlab::Ci::Build::Policy::Changes do expect(policy).not_to be_satisfied_by(pipeline, seed) end + it 'is not satified when pattern with glob does not match' do + policy = described_class.new(%w[invalid/*.{md,rake}]) + + expect(policy).not_to be_satisfied_by(pipeline, seed) + end + context 'when pipelines does not run for a branch update' do before do pipeline.before_sha = Gitlab::Git::BLANK_SHA diff --git a/spec/lib/gitlab/ci/build/policy/refs_spec.rb b/spec/lib/gitlab/ci/build/policy/refs_spec.rb index 7211187e511..553fc0fb9bf 100644 --- a/spec/lib/gitlab/ci/build/policy/refs_spec.rb +++ b/spec/lib/gitlab/ci/build/policy/refs_spec.rb @@ -16,7 +16,7 @@ describe Gitlab::Ci::Build::Policy::Refs do end end - context 'when maching tags' do + context 'when matching tags' do context 'when pipeline runs for a tag' do let(:pipeline) do build_stubbed(:ci_pipeline, ref: 'feature', tag: true) @@ -56,10 +56,10 @@ describe Gitlab::Ci::Build::Policy::Refs do end end - context 'when maching a source' do + context 'when matching a source' do let(:pipeline) { build_stubbed(:ci_pipeline, source: :push) } - it 'is satisifed when provided source keyword matches' do + it 'is satisfied when provided source keyword matches' do expect(described_class.new(%w[pushes])) .to be_satisfied_by(pipeline) end diff --git a/spec/lib/gitlab/ci/config/entry/artifacts_spec.rb b/spec/lib/gitlab/ci/config/entry/artifacts_spec.rb index d48aac15f28..bd1f2c92844 100644 --- a/spec/lib/gitlab/ci/config/entry/artifacts_spec.rb +++ b/spec/lib/gitlab/ci/config/entry/artifacts_spec.rb @@ -8,7 +8,7 @@ describe Gitlab::Ci::Config::Entry::Artifacts do let(:config) { { paths: %w[public/] } } describe '#value' do - it 'returns artifacs configuration' do + it 'returns artifacts configuration' do expect(entry.value).to eq config end end diff --git a/spec/lib/gitlab/ci/config/entry/policy_spec.rb b/spec/lib/gitlab/ci/config/entry/policy_spec.rb index bef93fe7af7..83001b7fdd8 100644 --- a/spec/lib/gitlab/ci/config/entry/policy_spec.rb +++ b/spec/lib/gitlab/ci/config/entry/policy_spec.rb @@ -58,7 +58,7 @@ describe Gitlab::Ci::Config::Entry::Policy do end context 'when using complex policy' do - context 'when specifiying refs policy' do + context 'when specifying refs policy' do let(:config) { { refs: ['master'] } } it 'is a correct configuraton' do diff --git a/spec/lib/gitlab/ci/config/entry/reports_spec.rb b/spec/lib/gitlab/ci/config/entry/reports_spec.rb index 1140bfdf6c3..38943138cbf 100644 --- a/spec/lib/gitlab/ci/config/entry/reports_spec.rb +++ b/spec/lib/gitlab/ci/config/entry/reports_spec.rb @@ -19,7 +19,7 @@ describe Gitlab::Ci::Config::Entry::Reports do shared_examples 'a valid entry' do |keyword, file| describe '#value' do - it 'returns artifacs configuration' do + it 'returns artifacts configuration' do expect(entry.value).to eq({ "#{keyword}": [file] } ) end end diff --git a/spec/lib/gitlab/file_detector_spec.rb b/spec/lib/gitlab/file_detector_spec.rb index edab53247e9..4ba9094b24e 100644 --- a/spec/lib/gitlab/file_detector_spec.rb +++ b/spec/lib/gitlab/file_detector_spec.rb @@ -15,14 +15,22 @@ describe Gitlab::FileDetector do describe '.type_of' do it 'returns the type of a README file' do - %w[README readme INDEX index].each do |filename| + filenames = Gitlab::MarkupHelper::PLAIN_FILENAMES + Gitlab::MarkupHelper::PLAIN_FILENAMES.map(&:upcase) + extensions = Gitlab::MarkupHelper::EXTENSIONS + Gitlab::MarkupHelper::EXTENSIONS.map(&:upcase) + + filenames.each do |filename| expect(described_class.type_of(filename)).to eq(:readme) - %w[.md .adoc .rst].each do |extname| - expect(described_class.type_of(filename + extname)).to eq(:readme) + + extensions.each do |extname| + expect(described_class.type_of("#{filename}.#{extname}")).to eq(:readme) end end end + it 'returns nil for a README.rb file' do + expect(described_class.type_of('README.rb')).to be_nil + end + it 'returns nil for a README file in a directory' do expect(described_class.type_of('foo/README.md')).to be_nil end diff --git a/spec/lib/gitlab/git/commit_spec.rb b/spec/lib/gitlab/git/commit_spec.rb index 9ef27081f98..6be35eee0fd 100644 --- a/spec/lib/gitlab/git/commit_spec.rb +++ b/spec/lib/gitlab/git/commit_spec.rb @@ -94,7 +94,7 @@ describe Gitlab::Git::Commit, :seed_helper do context 'body_size less than threshold' do let(:body_size) { 123 } - it 'fetches commit message seperately' do + it 'fetches commit message separately' do expect(described_class).to receive(:get_message).with(repository, id) commit.safe_message diff --git a/spec/lib/gitlab/git/tag_spec.rb b/spec/lib/gitlab/git/tag_spec.rb index 2d9db576a6c..c5bad062c2a 100644 --- a/spec/lib/gitlab/git/tag_spec.rb +++ b/spec/lib/gitlab/git/tag_spec.rb @@ -68,7 +68,7 @@ describe Gitlab::Git::Tag, :seed_helper do context 'message_size less than threshold' do let(:message_size) { 123 } - it 'fetches tag message seperately' do + it 'fetches tag message separately' do expect(described_class).to receive(:get_message).with(repository, gitaly_tag.id) tag.message diff --git a/spec/lib/gitlab/kubernetes/helm/install_command_spec.rb b/spec/lib/gitlab/kubernetes/helm/install_command_spec.rb index 2b7e3ea6def..39852b7fe29 100644 --- a/spec/lib/gitlab/kubernetes/helm/install_command_spec.rb +++ b/spec/lib/gitlab/kubernetes/helm/install_command_spec.rb @@ -26,7 +26,8 @@ describe Gitlab::Kubernetes::Helm::InstallCommand do it_behaves_like 'helm commands' do let(:commands) do <<~EOS - helm init --client-only + helm init --upgrade + for i in $(seq 1 30); do helm version && break; sleep 1s; echo "Retrying ($i)..."; done helm repo add app-name https://repository.example.com helm repo update #{helm_install_comand} @@ -54,7 +55,8 @@ describe Gitlab::Kubernetes::Helm::InstallCommand do it_behaves_like 'helm commands' do let(:commands) do <<~EOS - helm init --client-only + helm init --upgrade + for i in $(seq 1 30); do helm version && break; sleep 1s; echo "Retrying ($i)..."; done helm repo add app-name https://repository.example.com helm repo update #{helm_install_command} @@ -84,7 +86,8 @@ describe Gitlab::Kubernetes::Helm::InstallCommand do it_behaves_like 'helm commands' do let(:commands) do <<~EOS - helm init --client-only + helm init --upgrade + for i in $(seq 1 30); do helm version && break; sleep 1s; echo "Retrying ($i)..."; done #{helm_install_command} EOS end @@ -111,7 +114,8 @@ describe Gitlab::Kubernetes::Helm::InstallCommand do it_behaves_like 'helm commands' do let(:commands) do <<~EOS - helm init --client-only + helm init --upgrade + for i in $(seq 1 30); do helm version && break; sleep 1s; echo "Retrying ($i)..."; done helm repo add app-name https://repository.example.com helm repo update #{helm_install_command} @@ -134,7 +138,8 @@ describe Gitlab::Kubernetes::Helm::InstallCommand do it_behaves_like 'helm commands' do let(:commands) do <<~EOS - helm init --client-only + helm init --upgrade + for i in $(seq 1 30); do helm version && break; sleep 1s; echo "Retrying ($i)..."; done helm repo add app-name https://repository.example.com helm repo update #{helm_install_command} @@ -157,7 +162,8 @@ describe Gitlab::Kubernetes::Helm::InstallCommand do it_behaves_like 'helm commands' do let(:commands) do <<~EOS - helm init --client-only + helm init --upgrade + for i in $(seq 1 30); do helm version && break; sleep 1s; echo "Retrying ($i)..."; done helm repo add app-name https://repository.example.com helm repo update #{helm_install_command} @@ -182,7 +188,8 @@ describe Gitlab::Kubernetes::Helm::InstallCommand do it_behaves_like 'helm commands' do let(:commands) do <<~EOS - helm init --client-only + helm init --upgrade + for i in $(seq 1 30); do helm version && break; sleep 1s; echo "Retrying ($i)..."; done helm repo add app-name https://repository.example.com helm repo update #{helm_install_command} diff --git a/spec/lib/gitlab/kubernetes/helm/pod_spec.rb b/spec/lib/gitlab/kubernetes/helm/pod_spec.rb index c92bc92c42d..2dd3a570a1d 100644 --- a/spec/lib/gitlab/kubernetes/helm/pod_spec.rb +++ b/spec/lib/gitlab/kubernetes/helm/pod_spec.rb @@ -30,7 +30,7 @@ describe Gitlab::Kubernetes::Helm::Pod do it 'should generate the appropriate specifications for the container' do container = subject.generate.spec.containers.first expect(container.name).to eq('helm') - expect(container.image).to eq('registry.gitlab.com/gitlab-org/cluster-integration/helm-install-image/releases/2.7.2-kube-1.11.0') + expect(container.image).to eq('registry.gitlab.com/gitlab-org/cluster-integration/helm-install-image/releases/2.11.0-kube-1.11.0') expect(container.env.count).to eq(3) expect(container.env.map(&:name)).to match_array([:HELM_VERSION, :TILLER_NAMESPACE, :COMMAND_SCRIPT]) expect(container.command).to match_array(["/bin/sh"]) diff --git a/spec/lib/gitlab/kubernetes/helm/upgrade_command_spec.rb b/spec/lib/gitlab/kubernetes/helm/upgrade_command_spec.rb index 9c9fc91ef3c..9b201dae417 100644 --- a/spec/lib/gitlab/kubernetes/helm/upgrade_command_spec.rb +++ b/spec/lib/gitlab/kubernetes/helm/upgrade_command_spec.rb @@ -21,7 +21,8 @@ describe Gitlab::Kubernetes::Helm::UpgradeCommand do it_behaves_like 'helm commands' do let(:commands) do <<~EOS - helm init --client-only + helm init --upgrade + for i in $(seq 1 30); do helm version && break; sleep 1s; echo "Retrying ($i)..."; done helm upgrade #{application.name} #{application.chart} --tls --tls-ca-cert /data/helm/#{application.name}/config/ca.pem --tls-cert /data/helm/#{application.name}/config/cert.pem --tls-key /data/helm/#{application.name}/config/key.pem --reset-values --install --namespace #{namespace} -f /data/helm/#{application.name}/config/values.yaml EOS end @@ -33,7 +34,8 @@ describe Gitlab::Kubernetes::Helm::UpgradeCommand do it_behaves_like 'helm commands' do let(:commands) do <<~EOS - helm init --client-only + helm init --upgrade + for i in $(seq 1 30); do helm version && break; sleep 1s; echo "Retrying ($i)..."; done helm upgrade #{application.name} #{application.chart} --tls --tls-ca-cert /data/helm/#{application.name}/config/ca.pem --tls-cert /data/helm/#{application.name}/config/cert.pem --tls-key /data/helm/#{application.name}/config/key.pem --reset-values --install --namespace #{namespace} -f /data/helm/#{application.name}/config/values.yaml EOS end @@ -56,7 +58,8 @@ describe Gitlab::Kubernetes::Helm::UpgradeCommand do it_behaves_like 'helm commands' do let(:commands) do <<~EOS - helm init --client-only + helm init --upgrade + for i in $(seq 1 30); do helm version && break; sleep 1s; echo "Retrying ($i)..."; done helm repo add #{application.name} #{application.repository} helm upgrade #{application.name} #{application.chart} --tls --tls-ca-cert /data/helm/#{application.name}/config/ca.pem --tls-cert /data/helm/#{application.name}/config/cert.pem --tls-key /data/helm/#{application.name}/config/key.pem --reset-values --install --namespace #{namespace} -f /data/helm/#{application.name}/config/values.yaml EOS @@ -70,7 +73,8 @@ describe Gitlab::Kubernetes::Helm::UpgradeCommand do it_behaves_like 'helm commands' do let(:commands) do <<~EOS - helm init --client-only + helm init --upgrade + for i in $(seq 1 30); do helm version && break; sleep 1s; echo "Retrying ($i)..."; done helm upgrade #{application.name} #{application.chart} --reset-values --install --namespace #{namespace} -f /data/helm/#{application.name}/config/values.yaml EOS end diff --git a/spec/models/clusters/applications/prometheus_spec.rb b/spec/models/clusters/applications/prometheus_spec.rb index 86de9dc60f2..b5aa1dcece5 100644 --- a/spec/models/clusters/applications/prometheus_spec.rb +++ b/spec/models/clusters/applications/prometheus_spec.rb @@ -35,7 +35,7 @@ describe Clusters::Applications::Prometheus do describe 'transition to installed' do let(:project) { create(:project) } - let(:cluster) { create(:cluster, projects: [project]) } + let(:cluster) { create(:cluster, :with_installed_helm, projects: [project]) } let(:prometheus_service) { double('prometheus_service') } subject { create(:clusters_applications_prometheus, :installing, cluster: cluster) } diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 131db6a5ff9..a58dc8e25e8 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -1782,7 +1782,7 @@ describe MergeRequest do allow(subject).to receive(:head_pipeline) { nil } end - it { expect(subject.mergeable_ci_state?).to be_truthy } + it { expect(subject.mergeable_ci_state?).to be_falsey } end end diff --git a/spec/policies/ci/pipeline_policy_spec.rb b/spec/policies/ci/pipeline_policy_spec.rb index bd32faf06ef..8022f61e67d 100644 --- a/spec/policies/ci/pipeline_policy_spec.rb +++ b/spec/policies/ci/pipeline_policy_spec.rb @@ -74,5 +74,23 @@ describe Ci::PipelinePolicy, :models do expect(policy).to be_allowed :update_pipeline end end + + describe 'destroy_pipeline' do + let(:project) { create(:project, :public) } + + context 'when user has owner access' do + let(:user) { project.owner } + + it 'is enabled' do + expect(policy).to be_allowed :destroy_pipeline + end + end + + context 'when user is not owner' do + it 'is disabled' do + expect(policy).not_to be_allowed :destroy_pipeline + end + end + end end end diff --git a/spec/requests/api/pipelines_spec.rb b/spec/requests/api/pipelines_spec.rb index f0e1992bccd..638cc9767d4 100644 --- a/spec/requests/api/pipelines_spec.rb +++ b/spec/requests/api/pipelines_spec.rb @@ -438,6 +438,67 @@ describe API::Pipelines do end end + describe 'DELETE /projects/:id/pipelines/:pipeline_id' do + context 'authorized user' do + let(:owner) { project.owner } + + it 'destroys the pipeline' do + delete api("/projects/#{project.id}/pipelines/#{pipeline.id}", owner) + + expect(response).to have_gitlab_http_status(204) + expect { pipeline.reload }.to raise_error(ActiveRecord::RecordNotFound) + end + + it 'returns 404 when it does not exist' do + delete api("/projects/#{project.id}/pipelines/123456", owner) + + expect(response).to have_gitlab_http_status(404) + expect(json_response['message']).to eq '404 Not found' + end + + it 'logs an audit event' do + expect { delete api("/projects/#{project.id}/pipelines/#{pipeline.id}", owner) }.to change { SecurityEvent.count }.by(1) + end + + context 'when the pipeline has jobs' do + let!(:build) { create(:ci_build, project: project, pipeline: pipeline) } + + it 'destroys associated jobs' do + delete api("/projects/#{project.id}/pipelines/#{pipeline.id}", owner) + + expect(response).to have_gitlab_http_status(204) + expect { build.reload }.to raise_error(ActiveRecord::RecordNotFound) + end + end + end + + context 'unauthorized user' do + context 'when user is not member' do + it 'should return a 404' do + delete api("/projects/#{project.id}/pipelines/#{pipeline.id}", non_member) + + expect(response).to have_gitlab_http_status(404) + expect(json_response['message']).to eq '404 Project Not Found' + end + end + + context 'when user is developer' do + let(:developer) { create(:user) } + + before do + project.add_developer(developer) + end + + it 'should return a 403' do + delete api("/projects/#{project.id}/pipelines/#{pipeline.id}", developer) + + expect(response).to have_gitlab_http_status(403) + expect(json_response['message']).to eq '403 Forbidden' + end + end + end + end + describe 'POST /projects/:id/pipelines/:pipeline_id/retry' do context 'authorized user' do let!(:pipeline) do diff --git a/spec/services/ci/destroy_pipeline_service_spec.rb b/spec/services/ci/destroy_pipeline_service_spec.rb new file mode 100644 index 00000000000..097daf67feb --- /dev/null +++ b/spec/services/ci/destroy_pipeline_service_spec.rb @@ -0,0 +1,60 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe ::Ci::DestroyPipelineService do + let(:project) { create(:project) } + let!(:pipeline) { create(:ci_pipeline, project: project) } + + subject { described_class.new(project, user).execute(pipeline) } + + context 'user is owner' do + let(:user) { project.owner } + + it 'destroys the pipeline' do + subject + + expect { pipeline.reload }.to raise_error(ActiveRecord::RecordNotFound) + end + + it 'logs an audit event' do + expect { subject }.to change { SecurityEvent.count }.by(1) + end + + context 'when the pipeline has jobs' do + let!(:build) { create(:ci_build, project: project, pipeline: pipeline) } + + it 'destroys associated jobs' do + subject + + expect { build.reload }.to raise_error(ActiveRecord::RecordNotFound) + end + + it 'destroys associated stages' do + stages = pipeline.stages + + subject + + expect(stages).to all(raise_error(ActiveRecord::RecordNotFound)) + end + + context 'when job has artifacts' do + let!(:artifact) { create(:ci_job_artifact, :archive, job: build) } + + it 'destroys associated artifacts' do + subject + + expect { artifact.reload }.to raise_error(ActiveRecord::RecordNotFound) + end + end + end + end + + context 'user is not owner' do + let(:user) { create(:user) } + + it 'raises an exception' do + expect { subject }.to raise_error(Gitlab::Access::AccessDeniedError) + end + end +end diff --git a/spec/services/system_hooks_service_spec.rb b/spec/services/system_hooks_service_spec.rb index e0335880e8e..81b2c17fdb5 100644 --- a/spec/services/system_hooks_service_spec.rb +++ b/spec/services/system_hooks_service_spec.rb @@ -32,7 +32,7 @@ describe SystemHooksService do end it do - project.old_path_with_namespace = 'transfered_from_path' + project.old_path_with_namespace = 'transferred_from_path' expect(event_data(project, :transfer)).to include( :event_name, :name, :created_at, :updated_at, :path, :project_id, :owner_name, :owner_email, :project_visibility, diff --git a/spec/support/shared_examples/models/cluster_application_status_shared_examples.rb b/spec/support/shared_examples/models/cluster_application_status_shared_examples.rb index 82f0dd5d00f..c391cc48f4e 100644 --- a/spec/support/shared_examples/models/cluster_application_status_shared_examples.rb +++ b/spec/support/shared_examples/models/cluster_application_status_shared_examples.rb @@ -44,10 +44,40 @@ shared_examples 'cluster application status specs' do |application_name| subject { create(application_name, :installing) } it 'is installed' do - subject.make_installed + subject.make_installed! expect(subject).to be_installed end + + it 'updates helm version' do + subject.cluster.application_helm.update!(version: '1.2.3') + + subject.make_installed! + + subject.cluster.application_helm.reload + + expect(subject.cluster.application_helm.version).to eq(Gitlab::Kubernetes::Helm::HELM_VERSION) + end + end + + describe '#make_updated' do + subject { create(application_name, :updating) } + + it 'is updated' do + subject.make_updated! + + expect(subject).to be_updated + end + + it 'updates helm version' do + subject.cluster.application_helm.update!(version: '1.2.3') + + subject.make_updated! + + subject.cluster.application_helm.reload + + expect(subject.cluster.application_helm.version).to eq(Gitlab::Kubernetes::Helm::HELM_VERSION) + end end describe '#make_errored' do diff --git a/spec/workers/emails_on_push_worker_spec.rb b/spec/workers/emails_on_push_worker_spec.rb index f17c5ac6aac..05b4fb49ea3 100644 --- a/spec/workers/emails_on_push_worker_spec.rb +++ b/spec/workers/emails_on_push_worker_spec.rb @@ -101,7 +101,7 @@ describe EmailsOnPushWorker, :mailer do context "when there are multiple recipients" do before do - # This is a hack because we modify the mail object before sending, for efficency, + # This is a hack because we modify the mail object before sending, for efficiency, # but the TestMailer adapter just appends the objects to an array. To clone a mail # object, create a new one! # https://github.com/mikel/mail/issues/314#issuecomment-12750108 |