From ede2fbdc8734f095d371614d362b5ae373d6a243 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Mon, 12 Apr 2021 09:09:09 +0000 Subject: [PATCH] Add latest changes from gitlab-org/gitlab@master --- .rubocop_manual_todo.yml | 7 - GITALY_SERVER_VERSION | 2 +- Gemfile | 2 +- Gemfile.lock | 4 +- .../jobs/components/manual_variables_form.vue | 12 +- .../clusters/concerns/application_version.rb | 6 + .../unreleased/btn-confirm-push-rules.yml | 5 + ...after-let-it-be-services-merge-request.yml | 5 + changelogs/unreleased/pks-lfs-quarantine.yml | 5 + ...-style-hashtransformation-ee-directory.yml | 5 + ...tyle-hashtransformation-spec-directory.yml | 5 + ..._integrity_inspect_quarantined_objects.yml | 8 ++ .../gitlab_rails_cheat_sheet.md | 15 +++ lib/gitlab/gitaly_client/blob_service.rb | 47 +++++-- .../components/manual_variables_form_spec.js | 121 ++++++++---------- spec/knapsack_env.rb | 46 +++++++ .../serializers/pull_request_entity_spec.rb | 2 +- spec/lib/gitlab/ci/status/composite_spec.rb | 8 +- spec/lib/gitlab/conflict/file_spec.rb | 6 +- .../gitlab/gitaly_client/blob_service_spec.rb | 27 ++++ .../project/tree_restorer_spec.rb | 2 +- spec/models/concerns/featurable_spec.rb | 2 +- spec/models/event_spec.rb | 8 +- spec/models/packages/dependency_spec.rb | 2 +- .../alert_management/alert/assignees_spec.rb | 2 +- .../alert_management/alert/notes_spec.rb | 2 +- .../alert_management/alert/todos_spec.rb | 2 +- spec/requests/api/projects_spec.rb | 2 +- .../merge_requests/base_service_spec.rb | 1 + .../create_pipeline_service_spec.rb | 2 + .../merge_requests/export_csv_service_spec.rb | 2 + .../merge_orchestration_service_spec.rb | 1 + .../merge_requests/merge_service_spec.rb | 1 + .../merge_to_ref_service_spec.rb | 2 + spec/spec_helper.rb | 10 +- spec/support/helpers/graphql_helpers.rb | 4 +- .../project_tree_expectations.rb | 4 +- .../delete_tags_service_shared_context.rb | 2 +- ...ter_application_version_shared_examples.rb | 11 ++ 39 files changed, 279 insertions(+), 121 deletions(-) create mode 100644 changelogs/unreleased/btn-confirm-push-rules.yml create mode 100644 changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-services-merge-request.yml create mode 100644 changelogs/unreleased/pks-lfs-quarantine.yml create mode 100644 changelogs/unreleased/pl-rubocop-style-hashtransformation-ee-directory.yml create mode 100644 changelogs/unreleased/pl-rubocop-style-hashtransformation-spec-directory.yml create mode 100644 config/feature_flags/development/lfs_integrity_inspect_quarantined_objects.yml create mode 100644 spec/knapsack_env.rb diff --git a/.rubocop_manual_todo.yml b/.rubocop_manual_todo.yml index 855b68bc1ab..0bda1b60623 100644 --- a/.rubocop_manual_todo.yml +++ b/.rubocop_manual_todo.yml @@ -442,7 +442,6 @@ RSpec/EmptyLineAfterFinalLetItBe: - ee/spec/controllers/registrations/groups_controller_spec.rb - ee/spec/controllers/registrations/projects_controller_spec.rb - ee/spec/controllers/subscriptions_controller_spec.rb - - ee/spec/features/admin/admin_show_new_user_signups_cap_alert_spec.rb - ee/spec/features/boards/group_boards/multiple_boards_spec.rb - ee/spec/features/ci_shared_runner_warnings_spec.rb - ee/spec/features/dashboards/todos_spec.rb @@ -1036,12 +1035,6 @@ RSpec/EmptyLineAfterFinalLetItBe: - spec/services/markdown_content_rewriter_service_spec.rb - spec/services/members/create_service_spec.rb - spec/services/members/invite_service_spec.rb - - spec/services/merge_requests/base_service_spec.rb - - spec/services/merge_requests/create_pipeline_service_spec.rb - - spec/services/merge_requests/export_csv_service_spec.rb - - spec/services/merge_requests/merge_orchestration_service_spec.rb - - spec/services/merge_requests/merge_service_spec.rb - - spec/services/merge_requests/merge_to_ref_service_spec.rb - spec/services/metrics/dashboard/annotations/create_service_spec.rb - spec/services/metrics/dashboard/gitlab_alert_embed_service_spec.rb - spec/services/metrics/users_starred_dashboards/create_service_spec.rb diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION index 6481c6362c3..97af8533d21 100644 --- a/GITALY_SERVER_VERSION +++ b/GITALY_SERVER_VERSION @@ -1 +1 @@ -2b9f2f35e178b8b56b5f657420aa72c6a77c62eb +ca2b1ea56e839a9bc4878abb1e9ecac8002b4b07 diff --git a/Gemfile b/Gemfile index 759d0cb3047..7cb30fd26fc 100644 --- a/Gemfile +++ b/Gemfile @@ -475,7 +475,7 @@ group :ed25519 do end # Gitaly GRPC protocol definitions -gem 'gitaly', '~> 13.9.0.pre.rc1' +gem 'gitaly', '~> 13.11.0.pre.rc1' gem 'grpc', '~> 1.30.2' diff --git a/Gemfile.lock b/Gemfile.lock index b587b0f77c6..fe836915448 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -440,7 +440,7 @@ GEM rails (>= 3.2.0) git (1.7.0) rchardet (~> 1.8) - gitaly (13.9.0.pre.rc1) + gitaly (13.11.0.pre.rc1) grpc (~> 1.0) github-markup (1.7.0) gitlab (4.16.1) @@ -1427,7 +1427,7 @@ DEPENDENCIES gettext (~> 3.3) gettext_i18n_rails (~> 1.8.0) gettext_i18n_rails_js (~> 1.3) - gitaly (~> 13.9.0.pre.rc1) + gitaly (~> 13.11.0.pre.rc1) github-markup (~> 1.7.0) gitlab-chronic (~> 0.10.5) gitlab-dangerfiles (~> 1.1.1) diff --git a/app/assets/javascripts/jobs/components/manual_variables_form.vue b/app/assets/javascripts/jobs/components/manual_variables_form.vue index 793f790931c..d45012d2023 100644 --- a/app/assets/javascripts/jobs/components/manual_variables_form.vue +++ b/app/assets/javascripts/jobs/components/manual_variables_form.vue @@ -117,7 +117,12 @@ export default {
{{ s__('CiVariables|Value') }}
-
+
{{ s__('Pipeline|Key') }}
@@ -126,6 +131,7 @@ export default { v-model="variable.key" :placeholder="$options.i18n.keyPlaceholder" class="ci-variable-body-item form-control" + data-testid="ci-variable-key" />
@@ -138,6 +144,7 @@ export default { v-model="variable.secret_value" :placeholder="$options.i18n.valuePlaceholder" class="ci-variable-body-item form-control" + data-testid="ci-variable-value" />
@@ -149,6 +156,7 @@ export default { category="tertiary" icon="clear" :aria-label="__('Delete variable')" + data-testid="delete-variable-btn" @click="deleteVariable(variable.id)" /> @@ -181,7 +189,7 @@ export default {
-

+

[:installed, :updated] do |application| application.version = application.class.const_get(:VERSION, false) end + + before_transition any => [:externally_installed] do |application| + application.version = EXTERNAL_VERSION + end end end diff --git a/changelogs/unreleased/btn-confirm-push-rules.yml b/changelogs/unreleased/btn-confirm-push-rules.yml new file mode 100644 index 00000000000..41ede801659 --- /dev/null +++ b/changelogs/unreleased/btn-confirm-push-rules.yml @@ -0,0 +1,5 @@ +--- +title: Move to btn-confirm from btn-success in push_rules directory +merge_request: 58033 +author: Yogi (@yo) +type: changed diff --git a/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-services-merge-request.yml b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-services-merge-request.yml new file mode 100644 index 00000000000..dd7b6e30576 --- /dev/null +++ b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-services-merge-request.yml @@ -0,0 +1,5 @@ +--- +title: Fix EmptyLineAfterFinalLetItBe offenses in spec/services/merge_requests +merge_request: 58429 +author: Huzaifa Iftikhar @huzaifaiftikhar +type: fixed diff --git a/changelogs/unreleased/pks-lfs-quarantine.yml b/changelogs/unreleased/pks-lfs-quarantine.yml new file mode 100644 index 00000000000..19821eda678 --- /dev/null +++ b/changelogs/unreleased/pks-lfs-quarantine.yml @@ -0,0 +1,5 @@ +--- +title: Use object quarantine directory to enumerate new LFS pointers +merge_request: 58634 +author: +type: performance diff --git a/changelogs/unreleased/pl-rubocop-style-hashtransformation-ee-directory.yml b/changelogs/unreleased/pl-rubocop-style-hashtransformation-ee-directory.yml new file mode 100644 index 00000000000..bb10b5d9703 --- /dev/null +++ b/changelogs/unreleased/pl-rubocop-style-hashtransformation-ee-directory.yml @@ -0,0 +1,5 @@ +--- +title: Fix cop offenses for Style/HashTransformation in ee directory +merge_request: 56581 +author: Karthik Sivadas @karthik.sivadas +type: other diff --git a/changelogs/unreleased/pl-rubocop-style-hashtransformation-spec-directory.yml b/changelogs/unreleased/pl-rubocop-style-hashtransformation-spec-directory.yml new file mode 100644 index 00000000000..fa96b475216 --- /dev/null +++ b/changelogs/unreleased/pl-rubocop-style-hashtransformation-spec-directory.yml @@ -0,0 +1,5 @@ +--- +title: Fix cop offenses for Style/HashTransformation in spec directory +merge_request: 56586 +author: Karthik Sivadas @karthik.sivadas +type: other diff --git a/config/feature_flags/development/lfs_integrity_inspect_quarantined_objects.yml b/config/feature_flags/development/lfs_integrity_inspect_quarantined_objects.yml new file mode 100644 index 00000000000..f8b589c0a4f --- /dev/null +++ b/config/feature_flags/development/lfs_integrity_inspect_quarantined_objects.yml @@ -0,0 +1,8 @@ +--- +name: lfs_integrity_inspect_quarantined_objects +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58634 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/327440 +milestone: '13.11' +type: development +group: group::gitaly +default_enabled: false diff --git a/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md b/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md index 2506d4cbf0e..6b1cf2d1194 100644 --- a/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md +++ b/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md @@ -762,6 +762,21 @@ end Gitlab::CurrentSettings.current_application_settings.runners_registration_token ``` +### Run pipeline schedules manually + +You can run pipeline schedules manually through the Rails console to reveal any errors that are usually not visible. + +```ruby +# schedule_id can be obtained from Edit Pipeline Schedule page +schedule = Ci::PipelineSchedule.find_by(id: ) + +# Select the user that you want to run the schedule for +user = User.find_by_username('') + +# Run the schedule +ps = Ci::CreatePipelineService.new(schedule.project, user, ref: schedule.ref).execute!(:schedule, ignore_skip_ci: true, save_on_errors: false, schedule: schedule) +``` + ## License ### See current license information diff --git a/lib/gitlab/gitaly_client/blob_service.rb b/lib/gitlab/gitaly_client/blob_service.rb index c66b3335d89..669fb1c0a31 100644 --- a/lib/gitlab/gitaly_client/blob_service.rb +++ b/lib/gitlab/gitaly_client/blob_service.rb @@ -78,17 +78,7 @@ module Gitlab end def get_new_lfs_pointers(revision, limit, not_in, dynamic_timeout = nil) - request = Gitaly::GetNewLFSPointersRequest.new( - repository: @gitaly_repo, - revision: encode_binary(revision), - limit: limit || 0 - ) - - if not_in.nil? || not_in == :all - request.not_in_all = true - else - request.not_in_refs += not_in - end + request, rpc = create_new_lfs_pointers_request(revision, limit, not_in) timeout = if dynamic_timeout @@ -100,7 +90,7 @@ module Gitlab response = GitalyClient.call( @gitaly_repo.storage_name, :blob_service, - :get_new_lfs_pointers, + rpc, request, timeout: timeout ) @@ -118,6 +108,39 @@ module Gitlab private + def create_new_lfs_pointers_request(revision, limit, not_in) + # If the check happens for a change which is using a quarantine + # environment for incoming objects, then we can avoid doing the + # necessary graph walk to detect only new LFS pointers and instead scan + # through all quarantined objects. + git_env = ::Gitlab::Git::HookEnv.all(@gitaly_repo.gl_repository) + if Feature.enabled?(:lfs_integrity_inspect_quarantined_objects, @project, default_enabled: :yaml) && git_env['GIT_OBJECT_DIRECTORY_RELATIVE'].present? + repository = @gitaly_repo.dup + repository.git_alternate_object_directories = Google::Protobuf::RepeatedField.new(:string) + + request = Gitaly::ListAllLFSPointersRequest.new( + repository: repository, + limit: limit || 0 + ) + + [request, :list_all_lfs_pointers] + else + request = Gitaly::GetNewLFSPointersRequest.new( + repository: @gitaly_repo, + revision: encode_binary(revision), + limit: limit || 0 + ) + + if not_in.nil? || not_in == :all + request.not_in_all = true + else + request.not_in_refs += not_in + end + + [request, :get_new_lfs_pointers] + end + end + def consume_blob_response(response) data = [] blob = nil diff --git a/spec/frontend/jobs/components/manual_variables_form_spec.js b/spec/frontend/jobs/components/manual_variables_form_spec.js index aecbf1f5330..376a822dde5 100644 --- a/spec/frontend/jobs/components/manual_variables_form_spec.js +++ b/spec/frontend/jobs/components/manual_variables_form_spec.js @@ -1,7 +1,7 @@ -import { GlButton } from '@gitlab/ui'; import { createLocalVue, mount, shallowMount } from '@vue/test-utils'; import Vue from 'vue'; import Vuex from 'vuex'; +import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import Form from '~/jobs/components/manual_variables_form.vue'; const localVue = createLocalVue(); @@ -21,49 +21,48 @@ describe('Manual Variables Form', () => { variablesSettingsUrl: '/settings', }; - const createComponent = (props = {}, mountFn = shallowMount) => { + const createComponent = ({ props = {}, mountFn = shallowMount } = {}) => { store = new Vuex.Store({ actions: { triggerManualJob: jest.fn(), }, }); - wrapper = mountFn(localVue.extend(Form), { - propsData: props, - localVue, - store, - }); + wrapper = extendedWrapper( + mountFn(localVue.extend(Form), { + propsData: { ...requiredProps, ...props }, + localVue, + store, + }), + ); }; - const findTriggerBtn = () => wrapper.find('[data-testid="trigger-manual-job-btn"]'); + const findInputKey = () => wrapper.findComponent({ ref: 'inputKey' }); + const findInputValue = () => wrapper.findComponent({ ref: 'inputSecretValue' }); - afterEach((done) => { - // The component has a `nextTick` callback after some events so we need - // to wait for those to finish before destroying. - setImmediate(() => { - wrapper.destroy(); - wrapper = null; + const findTriggerBtn = () => wrapper.findByTestId('trigger-manual-job-btn'); + const findHelpText = () => wrapper.findByTestId('form-help-text'); + const findDeleteVarBtn = () => wrapper.findByTestId('delete-variable-btn'); + const findCiVariableKey = () => wrapper.findByTestId('ci-variable-key'); + const findCiVariableValue = () => wrapper.findByTestId('ci-variable-value'); + const findAllVariables = () => wrapper.findAllByTestId('ci-variable-row'); - done(); - }); + afterEach(() => { + wrapper.destroy(); }); describe('shallowMount', () => { beforeEach(() => { - createComponent(requiredProps); + createComponent(); }); it('renders empty form with correct placeholders', () => { - expect(wrapper.find({ ref: 'inputKey' }).attributes('placeholder')).toBe( - 'Input variable key', - ); - expect(wrapper.find({ ref: 'inputSecretValue' }).attributes('placeholder')).toBe( - 'Input variable value', - ); + expect(findInputKey().attributes('placeholder')).toBe('Input variable key'); + expect(findInputValue().attributes('placeholder')).toBe('Input variable value'); }); it('renders help text with provided link', () => { - expect(wrapper.find('p').text()).toBe( + expect(findHelpText().text()).toBe( 'Specify variable values to be used in this run. The values specified in CI/CD settings will be used as default', ); @@ -71,57 +70,47 @@ describe('Manual Variables Form', () => { }); describe('when adding a new variable', () => { - it('creates a new variable when user types a new key and resets the form', (done) => { - wrapper.vm - .$nextTick() - .then(() => wrapper.find({ ref: 'inputKey' }).setValue('new key')) - .then(() => { - expect(wrapper.vm.variables.length).toBe(1); - expect(wrapper.vm.variables[0].key).toBe('new key'); - expect(wrapper.find({ ref: 'inputKey' }).attributes('value')).toBe(undefined); - }) - .then(done) - .catch(done.fail); + it('creates a new variable when user types a new key and resets the form', async () => { + await findInputKey().setValue('new key'); + + expect(findAllVariables()).toHaveLength(1); + expect(findCiVariableKey().element.value).toBe('new key'); + expect(findInputKey().attributes('value')).toBe(undefined); }); - it('creates a new variable when user types a new value and resets the form', (done) => { - wrapper.vm - .$nextTick() - .then(() => wrapper.find({ ref: 'inputSecretValue' }).setValue('new value')) - .then(() => { - expect(wrapper.vm.variables.length).toBe(1); - expect(wrapper.vm.variables[0].secret_value).toBe('new value'); - expect(wrapper.find({ ref: 'inputSecretValue' }).attributes('value')).toBe(undefined); - }) - .then(done) - .catch(done.fail); - }); - }); + it('creates a new variable when user types a new value and resets the form', async () => { + await findInputValue().setValue('new value'); - describe('when deleting a variable', () => { - beforeEach((done) => { - wrapper.vm.variables = [ - { - key: 'new key', - secret_value: 'value', - id: '1', - }, - ]; - - wrapper.vm.$nextTick(done); - }); - - it('removes the variable row', () => { - wrapper.find(GlButton).vm.$emit('click'); - - expect(wrapper.vm.variables.length).toBe(0); + expect(findAllVariables()).toHaveLength(1); + expect(findCiVariableValue().element.value).toBe('new value'); + expect(findInputValue().attributes('value')).toBe(undefined); }); }); }); describe('mount', () => { beforeEach(() => { - createComponent(requiredProps, mount); + createComponent({ mountFn: mount }); + }); + + describe('when deleting a variable', () => { + it('removes the variable row', async () => { + await wrapper.setData({ + variables: [ + { + key: 'new key', + secret_value: 'value', + id: '1', + }, + ], + }); + + findDeleteVarBtn().trigger('click'); + + await wrapper.vm.$nextTick(); + + expect(findAllVariables()).toHaveLength(0); + }); }); it('trigger button is disabled after trigger action', async () => { diff --git a/spec/knapsack_env.rb b/spec/knapsack_env.rb new file mode 100644 index 00000000000..7dc1a43d644 --- /dev/null +++ b/spec/knapsack_env.rb @@ -0,0 +1,46 @@ +# frozen_string_literal: true + +require 'knapsack' + +module KnapsackEnv + class RSpecContextAdapter < Knapsack::Adapters::RSpecAdapter + def bind_time_tracker + ::RSpec.configure do |config| + # Original version starts timer in `config.prepend_before(:each) do` + # https://github.com/KnapsackPro/knapsack/blob/v1.17.0/lib/knapsack/adapters/rspec_adapter.rb#L9 + config.prepend_before(:context) do + Knapsack.tracker.start_timer + end + + # Original version is `config.prepend_before(:each) do` + # https://github.com/KnapsackPro/knapsack/blob/v1.17.0/lib/knapsack/adapters/rspec_adapter.rb#L9 + config.prepend_before(:each) do # rubocop:disable RSpec/HookArgument + current_example_group = + if ::RSpec.respond_to?(:current_example) + ::RSpec.current_example.metadata[:example_group] + else + example.metadata + end + + Knapsack.tracker.test_path = Knapsack::Adapters::RSpecAdapter.test_path(current_example_group) + end + + # Original version stops timer in `config.append_after(:each) do` + # https://github.com/KnapsackPro/knapsack/blob/v1.17.0/lib/knapsack/adapters/rspec_adapter.rb#L20 + config.append_after(:context) do + Knapsack.tracker.stop_timer + end + + config.after(:suite) do + Knapsack.logger.info(Knapsack::Presenter.global_time) + end + end + end + end + + def self.configure! + return unless ENV['CI'] && ENV['KNAPSACK_GENERATE_REPORT'] && !ENV['NO_KNAPSACK'] + + RSpecContextAdapter.bind + end +end diff --git a/spec/lib/atlassian/jira_connect/serializers/pull_request_entity_spec.rb b/spec/lib/atlassian/jira_connect/serializers/pull_request_entity_spec.rb index 872ba1ab43d..6399fc9053b 100644 --- a/spec/lib/atlassian/jira_connect/serializers/pull_request_entity_spec.rb +++ b/spec/lib/atlassian/jira_connect/serializers/pull_request_entity_spec.rb @@ -14,7 +14,7 @@ RSpec.describe Atlassian::JiraConnect::Serializers::PullRequestEntity do end context 'with user_notes_count option' do - let(:user_notes_count) { merge_requests.map { |merge_request| [merge_request.id, 1] }.to_h } + let(:user_notes_count) { merge_requests.to_h { |merge_request| [merge_request.id, 1] } } subject { described_class.represent(merge_requests, user_notes_count: user_notes_count).as_json } diff --git a/spec/lib/gitlab/ci/status/composite_spec.rb b/spec/lib/gitlab/ci/status/composite_spec.rb index 543cfe874ca..2b9523bd83d 100644 --- a/spec/lib/gitlab/ci/status/composite_spec.rb +++ b/spec/lib/gitlab/ci/status/composite_spec.rb @@ -6,13 +6,13 @@ RSpec.describe Gitlab::Ci::Status::Composite do let_it_be(:pipeline) { create(:ci_pipeline) } before_all do - @statuses = Ci::HasStatus::STATUSES_ENUM.map do |status, idx| + @statuses = Ci::HasStatus::STATUSES_ENUM.to_h do |status, idx| [status, create(:ci_build, pipeline: pipeline, status: status, importing: true)] - end.to_h + end - @statuses_with_allow_failure = Ci::HasStatus::STATUSES_ENUM.map do |status, idx| + @statuses_with_allow_failure = Ci::HasStatus::STATUSES_ENUM.to_h do |status, idx| [status, create(:ci_build, pipeline: pipeline, status: status, allow_failure: true, importing: true)] - end.to_h + end end describe '#status' do diff --git a/spec/lib/gitlab/conflict/file_spec.rb b/spec/lib/gitlab/conflict/file_spec.rb index bb9bee763d8..46e5334cd81 100644 --- a/spec/lib/gitlab/conflict/file_spec.rb +++ b/spec/lib/gitlab/conflict/file_spec.rb @@ -21,7 +21,7 @@ RSpec.describe Gitlab::Conflict::File do let(:section_keys) { conflict_file.sections.map { |section| section[:id] }.compact } context 'when resolving everything to the same side' do - let(:resolution_hash) { section_keys.map { |key| [key, 'head'] }.to_h } + let(:resolution_hash) { section_keys.to_h { |key| [key, 'head'] } } let(:resolved_lines) { conflict_file.resolve_lines(resolution_hash) } let(:expected_lines) { conflict_file.lines.reject { |line| line.type == 'old' } } @@ -54,8 +54,8 @@ RSpec.describe Gitlab::Conflict::File do end it 'raises ResolutionError when passed a hash without resolutions for all sections' do - empty_hash = section_keys.map { |key| [key, nil] }.to_h - invalid_hash = section_keys.map { |key| [key, 'invalid'] }.to_h + empty_hash = section_keys.to_h { |key| [key, nil] } + invalid_hash = section_keys.to_h { |key| [key, 'invalid'] } expect { conflict_file.resolve_lines({}) } .to raise_error(Gitlab::Git::Conflict::Resolver::ResolutionError) diff --git a/spec/lib/gitlab/gitaly_client/blob_service_spec.rb b/spec/lib/gitlab/gitaly_client/blob_service_spec.rb index 037734f1b13..e35f541f5c8 100644 --- a/spec/lib/gitlab/gitaly_client/blob_service_spec.rb +++ b/spec/lib/gitlab/gitaly_client/blob_service_spec.rb @@ -43,6 +43,33 @@ RSpec.describe Gitlab::GitalyClient::BlobService do subject end end + + context 'with hook environment' do + let(:git_env) do + { + 'GIT_OBJECT_DIRECTORY_RELATIVE' => '.git/objects', + 'GIT_ALTERNATE_OBJECT_DIRECTORIES_RELATIVE' => ['/dir/one', '/dir/two'] + } + end + + let(:expected_params) do + expected_repository = repository.gitaly_repository + expected_repository.git_alternate_object_directories = Google::Protobuf::RepeatedField.new(:string) + + { limit: limit, repository: expected_repository } + end + + it 'sends a list_all_lfs_pointers message' do + allow(Gitlab::Git::HookEnv).to receive(:all).with(repository.gl_repository).and_return(git_env) + + expect_any_instance_of(Gitaly::BlobService::Stub) + .to receive(:list_all_lfs_pointers) + .with(gitaly_request_with_params(expected_params), kind_of(Hash)) + .and_return([]) + + subject + end + end end describe '#get_all_lfs_pointers' do diff --git a/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb b/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb index e2bf87bf29f..bc5e6ea7bb3 100644 --- a/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb +++ b/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb @@ -684,7 +684,7 @@ RSpec.describe Gitlab::ImportExport::Project::TreeRestorer do it 'overrides project feature access levels' do access_level_keys = ProjectFeature.available_features.map { |feature| ProjectFeature.access_level_attribute(feature) } - disabled_access_levels = Hash[access_level_keys.collect { |item| [item, 'disabled'] }] + disabled_access_levels = access_level_keys.to_h { |item| [item, 'disabled'] } project.create_import_data(data: { override_params: disabled_access_levels }) diff --git a/spec/models/concerns/featurable_spec.rb b/spec/models/concerns/featurable_spec.rb index bcff5ce383e..295f3523dd5 100644 --- a/spec/models/concerns/featurable_spec.rb +++ b/spec/models/concerns/featurable_spec.rb @@ -164,7 +164,7 @@ RSpec.describe Featurable do end def update_all_project_features(project, features, value) - project_feature_attributes = features.map { |f| ["#{f}_access_level", value] }.to_h + project_feature_attributes = features.to_h { |f| ["#{f}_access_level", value] } project.project_feature.update!(project_feature_attributes) end end diff --git a/spec/models/event_spec.rb b/spec/models/event_spec.rb index 47148c4febc..949e8ec0a72 100644 --- a/spec/models/event_spec.rb +++ b/spec/models/event_spec.rb @@ -299,11 +299,11 @@ RSpec.describe Event do end def visible_to_none_except(*roles) - visible_to_none.merge(roles.map { |role| [role, true] }.to_h) + visible_to_none.merge(roles.to_h { |role| [role, true] }) end def visible_to_all_except(*roles) - visible_to_all.merge(roles.map { |role| [role, false] }.to_h) + visible_to_all.merge(roles.to_h { |role| [role, false] }) end shared_examples 'visibility examples' do @@ -723,7 +723,7 @@ RSpec.describe Event do note_on_design: true, note_on_commit: true } - valid_target_factories.map do |kind, needs_project| + valid_target_factories.to_h do |kind, needs_project| extra_data = if kind == :merge_request { source_project: project } elsif needs_project @@ -735,7 +735,7 @@ RSpec.describe Event do target = kind == :project ? nil : build(kind, **extra_data) [kind, build(:event, :created, author: project.owner, project: project, target: target)] - end.to_h + end end it 'passes a sanity check', :aggregate_failures do diff --git a/spec/models/packages/dependency_spec.rb b/spec/models/packages/dependency_spec.rb index fa6b0fd1848..4437cad46cd 100644 --- a/spec/models/packages/dependency_spec.rb +++ b/spec/models/packages/dependency_spec.rb @@ -54,7 +54,7 @@ RSpec.describe Packages::Dependency, type: :model do context 'with too big parameter' do let(:size) { (Packages::Dependency::MAX_CHUNKED_QUERIES_COUNT * chunk_size) + 1 } - let(:names_and_version_patterns) { Hash[(1..size).map { |v| [v, v] }] } + let(:names_and_version_patterns) { (1..size).to_h { |v| [v, v] } } it { expect { subject }.to raise_error(ArgumentError, 'Too many names_and_version_patterns') } end diff --git a/spec/requests/api/graphql/project/alert_management/alert/assignees_spec.rb b/spec/requests/api/graphql/project/alert_management/alert/assignees_spec.rb index 9ab94f1d749..a59402208ec 100644 --- a/spec/requests/api/graphql/project/alert_management/alert/assignees_spec.rb +++ b/spec/requests/api/graphql/project/alert_management/alert/assignees_spec.rb @@ -34,7 +34,7 @@ RSpec.describe 'getting Alert Management Alert Assignees' do end let(:alerts) { graphql_data.dig('project', 'alertManagementAlerts', 'nodes') } - let(:assignees) { alerts.map { |alert| [alert['iid'], alert['assignees']['nodes']] }.to_h } + let(:assignees) { alerts.to_h { |alert| [alert['iid'], alert['assignees']['nodes']] } } let(:first_assignees) { assignees[first_alert.iid.to_s] } let(:second_assignees) { assignees[second_alert.iid.to_s] } diff --git a/spec/requests/api/graphql/project/alert_management/alert/notes_spec.rb b/spec/requests/api/graphql/project/alert_management/alert/notes_spec.rb index 5d46f370756..72d185144ef 100644 --- a/spec/requests/api/graphql/project/alert_management/alert/notes_spec.rb +++ b/spec/requests/api/graphql/project/alert_management/alert/notes_spec.rb @@ -38,7 +38,7 @@ RSpec.describe 'getting Alert Management Alert Notes' do end let(:alerts_result) { graphql_data.dig('project', 'alertManagementAlerts', 'nodes') } - let(:notes_result) { alerts_result.map { |alert| [alert['iid'], alert['notes']['nodes']] }.to_h } + let(:notes_result) { alerts_result.to_h { |alert| [alert['iid'], alert['notes']['nodes']] } } let(:first_notes_result) { notes_result[first_alert.iid.to_s] } let(:second_notes_result) { notes_result[second_alert.iid.to_s] } diff --git a/spec/requests/api/graphql/project/alert_management/alert/todos_spec.rb b/spec/requests/api/graphql/project/alert_management/alert/todos_spec.rb index 3a9077061ad..ca58079fdfe 100644 --- a/spec/requests/api/graphql/project/alert_management/alert/todos_spec.rb +++ b/spec/requests/api/graphql/project/alert_management/alert/todos_spec.rb @@ -34,7 +34,7 @@ RSpec.describe 'getting Alert Management Alert Assignees' do end let(:gql_alerts) { graphql_data.dig('project', 'alertManagementAlerts', 'nodes') } - let(:gql_todos) { gql_alerts.map { |gql_alert| [gql_alert['iid'], gql_alert['todos']['nodes']] }.to_h } + let(:gql_todos) { gql_alerts.to_h { |gql_alert| [gql_alert['iid'], gql_alert['todos']['nodes']] } } let(:gql_alert_todo) { gql_todos[alert.iid.to_s].first } let(:gql_other_alert_todo) { gql_todos[other_alert.iid.to_s].first } diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index 0a63f1d7fa0..00b732b4a36 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' RSpec.shared_examples 'languages and percentages JSON response' do - let(:expected_languages) { project.repository.languages.map { |language| language.values_at(:label, :value)}.to_h } + let(:expected_languages) { project.repository.languages.to_h { |language| language.values_at(:label, :value) } } before do allow(project.repository).to receive(:languages).and_return( diff --git a/spec/services/merge_requests/base_service_spec.rb b/spec/services/merge_requests/base_service_spec.rb index 83431105545..d8ba2bc43fb 100644 --- a/spec/services/merge_requests/base_service_spec.rb +++ b/spec/services/merge_requests/base_service_spec.rb @@ -6,6 +6,7 @@ RSpec.describe MergeRequests::BaseService do include ProjectForksHelper let_it_be(:project) { create(:project, :repository) } + let(:title) { 'Awesome merge_request' } let(:params) do { diff --git a/spec/services/merge_requests/create_pipeline_service_spec.rb b/spec/services/merge_requests/create_pipeline_service_spec.rb index 4dd70627977..3e2e940dc24 100644 --- a/spec/services/merge_requests/create_pipeline_service_spec.rb +++ b/spec/services/merge_requests/create_pipeline_service_spec.rb @@ -7,6 +7,7 @@ RSpec.describe MergeRequests::CreatePipelineService do let_it_be(:project, reload: true) { create(:project, :repository) } let_it_be(:user) { create(:user) } + let(:service) { described_class.new(project, actor, params) } let(:actor) { user } let(:params) { {} } @@ -50,6 +51,7 @@ RSpec.describe MergeRequests::CreatePipelineService do context 'with fork merge request' do let_it_be(:forked_project) { fork_project(project, nil, repository: true, target_project: create(:project, :private, :repository)) } + let(:source_project) { forked_project } context 'when actor has permission to create pipelines in target project' do diff --git a/spec/services/merge_requests/export_csv_service_spec.rb b/spec/services/merge_requests/export_csv_service_spec.rb index 4ce032c396e..97217e979a5 100644 --- a/spec/services/merge_requests/export_csv_service_spec.rb +++ b/spec/services/merge_requests/export_csv_service_spec.rb @@ -4,6 +4,7 @@ require 'spec_helper' RSpec.describe MergeRequests::ExportCsvService do let_it_be(:merge_request) { create(:merge_request) } + let(:csv) { CSV.parse(subject.csv_data, headers: true).first } subject { described_class.new(MergeRequest.where(id: merge_request.id), merge_request.project) } @@ -46,6 +47,7 @@ RSpec.describe MergeRequests::ExportCsvService do describe 'approvers' do context 'when approved' do let_it_be(:merge_request) { create(:merge_request) } + let(:approvers) { create_list(:user, 2) } before do diff --git a/spec/services/merge_requests/merge_orchestration_service_spec.rb b/spec/services/merge_requests/merge_orchestration_service_spec.rb index 67dbb5a1a01..da37cc97857 100644 --- a/spec/services/merge_requests/merge_orchestration_service_spec.rb +++ b/spec/services/merge_requests/merge_orchestration_service_spec.rb @@ -4,6 +4,7 @@ require 'spec_helper' RSpec.describe MergeRequests::MergeOrchestrationService do let_it_be(:maintainer) { create(:user) } + let(:merge_params) { { sha: merge_request.diff_head_sha } } let(:user) { maintainer } let(:service) { described_class.new(project, user, merge_params) } diff --git a/spec/services/merge_requests/merge_service_spec.rb b/spec/services/merge_requests/merge_service_spec.rb index 561fb524897..c73cbad9d2f 100644 --- a/spec/services/merge_requests/merge_service_spec.rb +++ b/spec/services/merge_requests/merge_service_spec.rb @@ -5,6 +5,7 @@ require 'spec_helper' RSpec.describe MergeRequests::MergeService do let_it_be(:user) { create(:user) } let_it_be(:user2) { create(:user) } + let(:merge_request) { create(:merge_request, :simple, author: user2, assignees: [user2]) } let(:project) { merge_request.project } diff --git a/spec/services/merge_requests/merge_to_ref_service_spec.rb b/spec/services/merge_requests/merge_to_ref_service_spec.rb index 4806da7cbe7..938165a807c 100644 --- a/spec/services/merge_requests/merge_to_ref_service_spec.rb +++ b/spec/services/merge_requests/merge_to_ref_service_spec.rb @@ -68,6 +68,7 @@ RSpec.describe MergeRequests::MergeToRefService do end let_it_be(:user) { create(:user) } + let(:merge_request) { create(:merge_request, :simple) } let(:project) { merge_request.project } @@ -226,6 +227,7 @@ RSpec.describe MergeRequests::MergeToRefService do describe 'cascading merge refs' do let_it_be(:project) { create(:project, :repository) } + let(:params) { { commit_message: 'Cascading merge', first_parent_ref: first_parent_ref, target_ref: target_ref, sha: merge_request.diff_head_sha } } context 'when first merge happens' do diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 1550e2f9b3b..487c7bb10e2 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -15,6 +15,9 @@ Warning[:deprecated] = true unless ENV.key?('SILENCE_DEPRECATIONS') require './spec/deprecation_toolkit_env' DeprecationToolkitEnv.configure! +require './spec/knapsack_env' +KnapsackEnv.configure! + require './spec/simplecov_env' SimpleCovEnv.start! @@ -47,11 +50,6 @@ if rspec_profiling_is_configured && (!ENV.key?('CI') || branch_can_be_profiled) require 'rspec_profiling/rspec' end -if ENV['CI'] && ENV['KNAPSACK_GENERATE_REPORT'] && !ENV['NO_KNAPSACK'] - require 'knapsack' - Knapsack::Adapters::RSpecAdapter.bind -end - # require rainbow gem String monkeypatch, so we can test SystemChecks require 'rainbow/ext/string' Rainbow.enabled = false @@ -81,7 +79,7 @@ RSpec.configure do |config| config.run_all_when_everything_filtered = true config.use_transactional_fixtures = true - config.use_instantiated_fixtures = false + config.use_instantiated_fixtures = false config.fixture_path = Rails.root config.verbose_retry = true diff --git a/spec/support/helpers/graphql_helpers.rb b/spec/support/helpers/graphql_helpers.rb index a7f9e16c489..fc21efa6db4 100644 --- a/spec/support/helpers/graphql_helpers.rb +++ b/spec/support/helpers/graphql_helpers.rb @@ -277,11 +277,11 @@ module GraphqlHelpers # prepare_input_for_mutation({ 'my_key' => 1 }) # => { 'myKey' => 1} def prepare_input_for_mutation(input) - input.map do |name, value| + input.to_h do |name, value| value = prepare_input_for_mutation(value) if value.is_a?(Hash) [GraphqlHelpers.fieldnamerize(name), value] - end.to_h + end end def input_variable_name_for_mutation(mutation_name) diff --git a/spec/support/import_export/project_tree_expectations.rb b/spec/support/import_export/project_tree_expectations.rb index 966c977e8e9..2423a58a3e6 100644 --- a/spec/support/import_export/project_tree_expectations.rb +++ b/spec/support/import_export/project_tree_expectations.rb @@ -97,13 +97,13 @@ module ImportExport def normalize_elements(elem) case elem when Hash - elem.map do |key, value| + elem.to_h do |key, value| if ignore_key?(key, value) [key, :ignored] else [key, normalize_elements(value)] end - end.to_h + end when Array elem.map { |a| normalize_elements(a) } else diff --git a/spec/support/shared_contexts/services/projects/container_repository/delete_tags_service_shared_context.rb b/spec/support/shared_contexts/services/projects/container_repository/delete_tags_service_shared_context.rb index bcc98cf6416..80f011f622b 100644 --- a/spec/support/shared_contexts/services/projects/container_repository/delete_tags_service_shared_context.rb +++ b/spec/support/shared_contexts/services/projects/container_repository/delete_tags_service_shared_context.rb @@ -23,7 +23,7 @@ RSpec.shared_context 'container repository delete tags service shared context' d end def stub_delete_reference_requests(tags) - tags = Hash[Array.wrap(tags).map { |tag| [tag, 200] }] unless tags.is_a?(Hash) + tags = Array.wrap(tags).to_h { |tag| [tag, 200] } unless tags.is_a?(Hash) tags.each do |tag, status| stub_request(:delete, "http://registry.gitlab/v2/#{repository.path}/tags/reference/#{tag}") diff --git a/spec/support/shared_examples/models/cluster_application_version_shared_examples.rb b/spec/support/shared_examples/models/cluster_application_version_shared_examples.rb index ed2e4fee2de..3acc43eb0da 100644 --- a/spec/support/shared_examples/models/cluster_application_version_shared_examples.rb +++ b/spec/support/shared_examples/models/cluster_application_version_shared_examples.rb @@ -47,4 +47,15 @@ RSpec.shared_examples 'cluster application version specs' do |application_name| end end end + + describe '#make_externally_installed' do + subject { build(application_name) } + + it 'sets to a special version' do + subject.make_externally_installed! + + expect(subject).to be_persisted + expect(subject.version).to eq('EXTERNALLY_INSTALLED') + end + end end